Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7e057dc authored by Zhu Yi's avatar Zhu Yi Committed by John W. Linville
Browse files

iwmc3200wifi: add iwm_if_add and iwm_if_remove



We used to do alloc_netdev and register_netdev at the same time in
iwm_if_alloc. But some bus related structures will only be initialized
after iwm_priv is allocated. This caused a race condition that the
netdev might be registered earlier. The patch adds iwm_if_add and
iwm_if_remove so that the bus layer could register the device after
all initialization is done.

Signed-off-by: default avatarZhu Yi <yi.zhu@intel.com>
Signed-off-by: default avatarSamuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 8d96e796
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -315,6 +315,8 @@ extern const struct iw_handler_def iwm_iw_handler_def;
void *iwm_if_alloc(int sizeof_bus, struct device *dev,
		   struct iwm_if_ops *if_ops);
void iwm_if_free(struct iwm_priv *iwm);
int iwm_if_add(struct iwm_priv *iwm);
void iwm_if_remove(struct iwm_priv *iwm);
int iwm_mode_to_nl80211_iftype(int mode);
int iwm_priv_init(struct iwm_priv *iwm);
void iwm_priv_deinit(struct iwm_priv *iwm);
+20 −12
Original line number Diff line number Diff line
@@ -123,8 +123,7 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,

	wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode);

	ndev = alloc_netdev_mq(0, "wlan%d", ether_setup,
			       IWM_TX_QUEUES);
	ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
	if (!ndev) {
		dev_err(dev, "no memory for network device instance\n");
		goto out_priv;
@@ -134,19 +133,10 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,
	ndev->wireless_handlers = &iwm_iw_handler_def;
	ndev->ieee80211_ptr = wdev;
	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
	ret = register_netdev(ndev);
	if (ret < 0) {
		dev_err(dev, "Failed to register netdev: %d\n", ret);
		goto out_ndev;
	}

	wdev->netdev = ndev;

	return iwm;

 out_ndev:
	free_netdev(ndev);

 out_priv:
	iwm_priv_deinit(iwm);

@@ -160,8 +150,26 @@ void iwm_if_free(struct iwm_priv *iwm)
	if (!iwm_to_ndev(iwm))
		return;

	unregister_netdev(iwm_to_ndev(iwm));
	free_netdev(iwm_to_ndev(iwm));
	iwm_wdev_free(iwm);
	iwm_priv_deinit(iwm);
}

int iwm_if_add(struct iwm_priv *iwm)
{
	struct net_device *ndev = iwm_to_ndev(iwm);
	int ret;

	ret = register_netdev(ndev);
	if (ret < 0) {
		dev_err(&ndev->dev, "Failed to register netdev: %d\n", ret);
		return ret;
	}

	return 0;
}

void iwm_if_remove(struct iwm_priv *iwm)
{
	unregister_netdev(iwm_to_ndev(iwm));
}
+9 −0
Original line number Diff line number Diff line
@@ -454,10 +454,18 @@ static int iwm_sdio_probe(struct sdio_func *func,

	INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker);

	ret = iwm_if_add(iwm);
	if (ret) {
		dev_err(dev, "add SDIO interface failed\n");
		goto destroy_wq;
	}

	dev_info(dev, "IWM SDIO probe\n");

	return 0;

 destroy_wq:
	destroy_workqueue(hw->isr_wq);
 debugfs_exit:
	iwm_debugfs_exit(iwm);
 if_free:
@@ -472,6 +480,7 @@ static void iwm_sdio_remove(struct sdio_func *func)
	struct device *dev = &func->dev;

	iwm_debugfs_exit(iwm);
	iwm_if_remove(iwm);
	iwm_if_free(iwm);
	destroy_workqueue(hw->isr_wq);