Commit 59a4cc25 authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville

mwifiex: use asynchronous firmware loading

Make use of request_firmware_nowait instead of request_firmware
to load FW asynchronously. This fixes timeouts introduced with
recent udev changes.
Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarKiran Divekar <dkiran@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 13d7ba78
...@@ -292,29 +292,28 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) ...@@ -292,29 +292,28 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
} }
/* /*
* This function initializes the hardware and firmware. * This function gets firmware and initializes it.
* *
* The main initialization steps followed are - * The main initialization steps followed are -
* - Download the correct firmware to card * - Download the correct firmware to card
* - Allocate and initialize the adapter structure
* - Initialize the private structures
* - Issue the init commands to firmware * - Issue the init commands to firmware
*/ */
static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
{ {
int ret, err; int ret;
char fmt[64];
struct mwifiex_private *priv;
struct mwifiex_adapter *adapter = context;
struct mwifiex_fw_image fw; struct mwifiex_fw_image fw;
memset(&fw, 0, sizeof(struct mwifiex_fw_image)); if (!firmware) {
dev_err(adapter->dev,
err = request_firmware(&adapter->firmware, adapter->fw_name, "Failed to get firmware %s\n", adapter->fw_name);
adapter->dev);
if (err < 0) {
dev_err(adapter->dev, "request_firmware() returned"
" error code %#x\n", err);
ret = -1;
goto done; goto done;
} }
memset(&fw, 0, sizeof(struct mwifiex_fw_image));
adapter->firmware = firmware;
fw.fw_buf = (u8 *) adapter->firmware->data; fw.fw_buf = (u8 *) adapter->firmware->data;
fw.fw_len = adapter->firmware->size; fw.fw_len = adapter->firmware->size;
...@@ -335,16 +334,54 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) ...@@ -335,16 +334,54 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
/* Wait for mwifiex_init to complete */ /* Wait for mwifiex_init to complete */
wait_event_interruptible(adapter->init_wait_q, wait_event_interruptible(adapter->init_wait_q,
adapter->init_wait_q_woken); adapter->init_wait_q_woken);
if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) { if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
ret = -1;
goto done; goto done;
priv = adapter->priv[0];
if (mwifiex_register_cfg80211(priv) != 0) {
dev_err(adapter->dev, "cannot register with cfg80211\n");
goto err_init_fw;
}
rtnl_lock();
/* Create station interface by default */
if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
NL80211_IFTYPE_STATION, NULL, NULL)) {
dev_err(adapter->dev, "cannot create default STA interface\n");
goto err_add_intf;
} }
ret = 0; rtnl_unlock();
mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
dev_notice(adapter->dev, "driver_version = %s\n", fmt);
goto done;
err_add_intf:
mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
rtnl_unlock();
err_init_fw:
pr_debug("info: %s: unregister device\n", __func__);
adapter->if_ops.unregister_dev(adapter);
done: done:
release_firmware(adapter->firmware); release_firmware(adapter->firmware);
if (ret) complete(&adapter->fw_load);
ret = -1; return;
}
/*
* This function initializes the hardware and gets firmware.
*/
static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
{
int ret;
init_completion(&adapter->fw_load);
ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name,
adapter->dev, GFP_KERNEL, adapter,
mwifiex_fw_dpc);
if (ret < 0)
dev_err(adapter->dev,
"request_firmware_nowait() returned error %d\n", ret);
return ret; return ret;
} }
...@@ -649,8 +686,6 @@ mwifiex_add_card(void *card, struct semaphore *sem, ...@@ -649,8 +686,6 @@ mwifiex_add_card(void *card, struct semaphore *sem,
struct mwifiex_if_ops *if_ops, u8 iface_type) struct mwifiex_if_ops *if_ops, u8 iface_type)
{ {
struct mwifiex_adapter *adapter; struct mwifiex_adapter *adapter;
char fmt[64];
struct mwifiex_private *priv;
if (down_interruptible(sem)) if (down_interruptible(sem))
goto exit_sem_err; goto exit_sem_err;
...@@ -691,37 +726,9 @@ mwifiex_add_card(void *card, struct semaphore *sem, ...@@ -691,37 +726,9 @@ mwifiex_add_card(void *card, struct semaphore *sem,
goto err_init_fw; goto err_init_fw;
} }
priv = adapter->priv[0];
if (mwifiex_register_cfg80211(priv) != 0) {
dev_err(adapter->dev, "cannot register netdevice"
" with cfg80211\n");
goto err_init_fw;
}
rtnl_lock();
/* Create station interface by default */
if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
NL80211_IFTYPE_STATION, NULL, NULL)) {
rtnl_unlock();
dev_err(adapter->dev, "cannot create default station"
" interface\n");
goto err_add_intf;
}
rtnl_unlock();
up(sem); up(sem);
mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
dev_notice(adapter->dev, "driver_version = %s\n", fmt);
return 0; return 0;
err_add_intf:
rtnl_lock();
mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
rtnl_unlock();
err_init_fw: err_init_fw:
pr_debug("info: %s: unregister device\n", __func__); pr_debug("info: %s: unregister device\n", __func__);
adapter->if_ops.unregister_dev(adapter); adapter->if_ops.unregister_dev(adapter);
......
...@@ -655,6 +655,7 @@ struct mwifiex_adapter { ...@@ -655,6 +655,7 @@ struct mwifiex_adapter {
u8 scan_wait_q_woken; u8 scan_wait_q_woken;
struct cmd_ctrl_node *cmd_queued; struct cmd_ctrl_node *cmd_queued;
spinlock_t queue_lock; /* lock for tx queues */ spinlock_t queue_lock; /* lock for tx queues */
struct completion fw_load;
}; };
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
......
...@@ -119,6 +119,9 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) ...@@ -119,6 +119,9 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
if (!adapter || !adapter->priv_num) if (!adapter || !adapter->priv_num)
return; return;
/* In case driver is removed when asynchronous FW load is in progress */
wait_for_completion(&adapter->fw_load);
if (user_rmmod) { if (user_rmmod) {
#ifdef CONFIG_PM #ifdef CONFIG_PM
if (adapter->is_suspended) if (adapter->is_suspended)
......
...@@ -123,6 +123,9 @@ mwifiex_sdio_remove(struct sdio_func *func) ...@@ -123,6 +123,9 @@ mwifiex_sdio_remove(struct sdio_func *func)
if (!adapter || !adapter->priv_num) if (!adapter || !adapter->priv_num)
return; return;
/* In case driver is removed when asynchronous FW load is in progress */
wait_for_completion(&adapter->fw_load);
if (user_rmmod) { if (user_rmmod) {
if (adapter->is_suspended) if (adapter->is_suspended)
mwifiex_sdio_resume(adapter->dev); mwifiex_sdio_resume(adapter->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment