/* * This function gets firmware and initializes it. * * The main initialization steps followed are - * - Download the correct firmware to card * - Issue the init commands to firmware */ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) { int ret; char fmt[64]; struct mwifiex_private *priv; struct mwifiex_adapter *adapter = context; struct mwifiex_fw_image fw; if (!firmware) { dev_err(adapter->dev, "Failed to get firmware %s\n", adapter->fw_name); goto done; } memset(&fw, 0, sizeof(struct mwifiex_fw_image)); adapter->firmware = firmware; fw.fw_buf = (u8 *) adapter->firmware->data; fw.fw_len = adapter->firmware->size; if (adapter->if_ops.dnld_fw) ret = adapter->if_ops.dnld_fw(adapter, &fw); else ret = mwifiex_dnld_fw(adapter, &fw); if (ret == -1) goto done; dev_notice(adapter->dev, "WLAN FW is active\n"); adapter->init_wait_q_woken = false; ret = mwifiex_init_fw(adapter); if (ret == -1) { goto done; } else if (!ret) { adapter->hw_status = MWIFIEX_HW_STATUS_READY; goto done; } /* Wait for mwifiex_init to complete */ wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) goto done; 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; } rtnl_lock(); /* Create station interface by default */ if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NL80211_IFTYPE_STATION, NULL, NULL)) { dev_err(adapter->dev, "cannot create default STA interface\n"); goto err_add_intf; } /* Create AP interface by default */ if (!mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NL80211_IFTYPE_AP, NULL, NULL)) { dev_err(adapter->dev, "cannot create default AP interface\n"); goto err_add_intf; } /* Create P2P interface by default */ if (!mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", NL80211_IFTYPE_P2P_CLIENT, NULL, NULL)) { dev_err(adapter->dev, "cannot create default P2P interface\n"); goto err_add_intf; } 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(adapter->wiphy, priv->wdev); rtnl_unlock(); err_init_fw: pr_debug("info: %s: unregister device\n", __func__); adapter->if_ops.unregister_dev(adapter); done: release_firmware(adapter->firmware); complete(&adapter->fw_load); return; }
/* * This function removes the card. * * This function follows the following major steps to remove the device - * - Stop data traffic * - Shutdown firmware * - Remove the logical interfaces * - Terminate the work queue * - Unregister the device * - Free the adapter structure */ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) { struct mwifiex_private *priv = NULL; int i; if (down_interruptible(sem)) goto exit_sem_err; if (!adapter) goto exit_remove; adapter->surprise_removed = true; /* Stop data */ for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (priv && priv->netdev) { mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); } } dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n"); adapter->init_wait_q_woken = false; if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n"); if (atomic_read(&adapter->rx_pending) || atomic_read(&adapter->tx_pending) || atomic_read(&adapter->cmd_pending)) { dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, " "cmd_pending=%d\n", atomic_read(&adapter->rx_pending), atomic_read(&adapter->tx_pending), atomic_read(&adapter->cmd_pending)); } for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (!priv) continue; rtnl_lock(); if (priv->wdev && priv->netdev) mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev); rtnl_unlock(); } priv = adapter->priv[0]; if (!priv || !priv->wdev) goto exit_remove; wiphy_unregister(priv->wdev->wiphy); wiphy_free(priv->wdev->wiphy); for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (priv) kfree(priv->wdev); } mwifiex_terminate_workqueue(adapter); /* Unregister device */ dev_dbg(adapter->dev, "info: unregister device\n"); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); /* Free adapter structure */ dev_dbg(adapter->dev, "info: free adapter\n"); mwifiex_free_adapter(adapter); exit_remove: up(sem); exit_sem_err: return 0; }
/* * This function removes the card. * * This function follows the following major steps to remove the device - * - Stop data traffic * - Shutdown firmware * - Remove the logical interfaces * - Terminate the work queue * - Unregister the device * - Free the adapter structure */ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) { struct mwifiex_private *priv = NULL; int i; if (down_trylock(sem)) goto exit_sem_err; if (!adapter) goto exit_remove; /* We can no longer handle interrupts once we start doing the teardown * below. */ if (adapter->if_ops.disable_int) adapter->if_ops.disable_int(adapter); adapter->surprise_removed = true; mwifiex_terminate_workqueue(adapter); /* Stop data */ for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (priv && priv->netdev) { mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); } } mwifiex_dbg(adapter, CMD, "cmd: calling mwifiex_shutdown_drv...\n"); adapter->init_wait_q_woken = false; if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); mwifiex_dbg(adapter, CMD, "cmd: mwifiex_shutdown_drv done\n"); if (atomic_read(&adapter->rx_pending) || atomic_read(&adapter->tx_pending) || atomic_read(&adapter->cmd_pending)) { mwifiex_dbg(adapter, ERROR, "rx_pending=%d, tx_pending=%d,\t" "cmd_pending=%d\n", atomic_read(&adapter->rx_pending), atomic_read(&adapter->tx_pending), atomic_read(&adapter->cmd_pending)); } for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (!priv) continue; rtnl_lock(); if (priv->netdev && priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev); rtnl_unlock(); } wiphy_unregister(adapter->wiphy); wiphy_free(adapter->wiphy); /* Unregister device */ mwifiex_dbg(adapter, INFO, "info: unregister device\n"); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); /* Free adapter structure */ mwifiex_dbg(adapter, INFO, "info: free adapter\n"); mwifiex_free_adapter(adapter); exit_remove: up(sem); exit_sem_err: return 0; }