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

Commit 6b41f941 authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville
Browse files

mwifiex: handle driver initialization error paths



mwifiex_fw_dpc() asynchronously takes care of firmware download
and initialization. Currently the error paths in mwifiex_fw_dpc()
are not handled. So if wrong firmware is downloaded, required
cleanup work is not performed. memory is leaked and workqueue
remains unterminated in this case.

mwifiex_terminate_workqueue() is moved to avoid forward
declaration.

Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9d55911e
Loading
Loading
Loading
Loading
+55 −28
Original line number Diff line number Diff line
@@ -389,6 +389,17 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
	pr_debug("info: %s: free adapter\n", __func__);
}

/*
 * This function cancels all works in the queue and destroys
 * the main workqueue.
 */
static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
{
	flush_workqueue(adapter->workqueue);
	destroy_workqueue(adapter->workqueue);
	adapter->workqueue = NULL;
}

/*
 * This function gets firmware and initializes it.
 *
@@ -398,7 +409,7 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
 */
static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
{
	int ret;
	int ret, i;
	char fmt[64];
	struct mwifiex_private *priv;
	struct mwifiex_adapter *adapter = context;
@@ -407,7 +418,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
	if (!firmware) {
		dev_err(adapter->dev,
			"Failed to get firmware %s\n", adapter->fw_name);
		goto done;
		goto err_dnld_fw;
	}

	memset(&fw, 0, sizeof(struct mwifiex_fw_image));
@@ -420,7 +431,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
	else
		ret = mwifiex_dnld_fw(adapter, &fw);
	if (ret == -1)
		goto done;
		goto err_dnld_fw;

	dev_notice(adapter->dev, "WLAN FW is active\n");

@@ -432,13 +443,15 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
	}

	/* enable host interrupt after fw dnld is successful */
	if (adapter->if_ops.enable_int)
		adapter->if_ops.enable_int(adapter);
	if (adapter->if_ops.enable_int) {
		if (adapter->if_ops.enable_int(adapter))
			goto err_dnld_fw;
	}

	adapter->init_wait_q_woken = false;
	ret = mwifiex_init_fw(adapter);
	if (ret == -1) {
		goto done;
		goto err_init_fw;
	} else if (!ret) {
		adapter->hw_status = MWIFIEX_HW_STATUS_READY;
		goto done;
@@ -447,12 +460,12 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
	wait_event_interruptible(adapter->init_wait_q,
				 adapter->init_wait_q_woken);
	if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
		goto done;
		goto err_init_fw;

	priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
	if (mwifiex_register_cfg80211(adapter)) {
		dev_err(adapter->dev, "cannot register with cfg80211\n");
		goto err_init_fw;
		goto err_register_cfg80211;
	}

	rtnl_lock();
@@ -483,13 +496,39 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
	goto done;

err_add_intf:
	for (i = 0; i < adapter->priv_num; i++) {
		priv = adapter->priv[i];

		if (!priv)
			continue;

		if (priv->wdev && priv->netdev)
			mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
	}
	rtnl_unlock();
err_register_cfg80211:
	wiphy_unregister(adapter->wiphy);
	wiphy_free(adapter->wiphy);
err_init_fw:
	if (adapter->if_ops.disable_int)
		adapter->if_ops.disable_int(adapter);
err_dnld_fw:
	pr_debug("info: %s: unregister device\n", __func__);
	if (adapter->if_ops.unregister_dev)
		adapter->if_ops.unregister_dev(adapter);

	if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
	    (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
		pr_debug("info: %s: shutdown mwifiex\n", __func__);
		adapter->init_wait_q_woken = false;

		if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
			wait_event_interruptible(adapter->init_wait_q,
						 adapter->init_wait_q_woken);
	}
	adapter->surprise_removed = true;
	mwifiex_terminate_workqueue(adapter);
	mwifiex_free_adapter(adapter);
done:
	if (adapter->cal_data) {
		release_firmware(adapter->cal_data);
@@ -497,6 +536,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
	}
	release_firmware(adapter->firmware);
	complete(&adapter->fw_load);
	up(adapter->card_sem);
	return;
}

@@ -806,18 +846,6 @@ static void mwifiex_main_work_queue(struct work_struct *work)
	mwifiex_main_process(adapter);
}

/*
 * This function cancels all works in the queue and destroys
 * the main workqueue.
 */
static void
mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
{
	flush_workqueue(adapter->workqueue);
	destroy_workqueue(adapter->workqueue);
	adapter->workqueue = NULL;
}

/*
 * This function adds the card.
 *
@@ -846,6 +874,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
	}

	adapter->iface_type = iface_type;
	adapter->card_sem = sem;

	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
	adapter->surprise_removed = false;
@@ -876,17 +905,12 @@ mwifiex_add_card(void *card, struct semaphore *sem,
		goto err_init_fw;
	}

	up(sem);
	return 0;

err_init_fw:
	pr_debug("info: %s: unregister device\n", __func__);
	if (adapter->if_ops.unregister_dev)
		adapter->if_ops.unregister_dev(adapter);
err_registerdev:
	adapter->surprise_removed = true;
	mwifiex_terminate_workqueue(adapter);
err_kmalloc:
	if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
	    (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
		pr_debug("info: %s: shutdown mwifiex\n", __func__);
@@ -896,7 +920,10 @@ mwifiex_add_card(void *card, struct semaphore *sem,
			wait_event_interruptible(adapter->init_wait_q,
						 adapter->init_wait_q_woken);
	}

err_registerdev:
	adapter->surprise_removed = true;
	mwifiex_terminate_workqueue(adapter);
err_kmalloc:
	mwifiex_free_adapter(adapter);

err_init_sw:
+1 −0
Original line number Diff line number Diff line
@@ -749,6 +749,7 @@ struct mwifiex_adapter {

	atomic_t is_tx_received;
	atomic_t pending_bridged_pkts;
	struct semaphore *card_sem;
};

int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);