diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/init.c')
| -rw-r--r-- | drivers/net/wireless/mwifiex/init.c | 220 |
1 files changed, 134 insertions, 86 deletions
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 1d0ec57a014..4ecd0b208ac 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -35,28 +35,19 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) { struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_bss_prio_node *bss_prio; + struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl; unsigned long flags; bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL); - if (!bss_prio) { - dev_err(adapter->dev, "%s: failed to alloc bss_prio\n", - __func__); + if (!bss_prio) return -ENOMEM; - } bss_prio->priv = priv; INIT_LIST_HEAD(&bss_prio->list); - if (!adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur) - adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = - bss_prio; - - spin_lock_irqsave(&adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_lock, flags); - list_add_tail(&bss_prio->list, - &adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_head); - spin_unlock_irqrestore(&adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_lock, flags); + + spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags); + list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head); + spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags); return 0; } @@ -68,7 +59,7 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) * Additionally, it also initializes all the locks and sets up all the * lists. */ -static int mwifiex_init_priv(struct mwifiex_private *priv) +int mwifiex_init_priv(struct mwifiex_private *priv) { u32 i; @@ -82,7 +73,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; - priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; + priv->sec_info.wep_enabled = 0; priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; priv->sec_info.encryption_mode = 0; for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++) @@ -135,9 +126,19 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) priv->wmm_qosinfo = 0; priv->curr_bcn_buf = NULL; priv->curr_bcn_size = 0; + priv->wps_ie = NULL; + priv->wps_ie_len = 0; + priv->ap_11n_enabled = 0; + memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg)); priv->scan_block = false; + priv->csa_chan = 0; + priv->csa_expire_time = 0; + priv->del_list_idx = 0; + priv->hs2_enabled = false; + memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); + return mwifiex_add_bss_prio_tbl(priv); } @@ -157,13 +158,13 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) ret = mwifiex_alloc_cmd_buffer(adapter); if (ret) { dev_err(adapter->dev, "%s: failed to alloc cmd buffer\n", - __func__); + __func__); return -1; } adapter->sleep_cfm = dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm) - + INTF_HEADER_LEN); + + INTF_HEADER_LEN); if (!adapter->sleep_cfm) { dev_err(adapter->dev, "%s: failed to alloc sleep cfm" @@ -190,10 +191,10 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->cmd_sent = false; - if (adapter->iface_type == MWIFIEX_PCIE) - adapter->data_sent = false; - else + if (adapter->iface_type == MWIFIEX_SDIO) adapter->data_sent = true; + else + adapter->data_sent = false; adapter->cmd_resp_received = false; adapter->event_received = false; @@ -233,14 +234,12 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->pm_wakeup_fw_try = false; - adapter->max_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; adapter->is_hs_configured = false; - adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF); - adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF; - adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF; + adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF); + adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF; + adapter->hs_cfg.gap = HS_CFG_GAP_DEF; adapter->hs_activated = false; memset(adapter->event_body, 0, sizeof(adapter->event_body)); @@ -280,6 +279,11 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->adhoc_awake_period = 0; memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); adapter->arp_filter_size = 0; + adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; + adapter->empty_tx_q_cnt = 0; + adapter->ext_scan = true; + adapter->fw_key_api_major_ver = 0; + adapter->fw_key_api_minor_ver = 0; } /* @@ -302,9 +306,17 @@ void mwifiex_wake_up_net_dev_queue(struct net_device *netdev, struct mwifiex_adapter *adapter) { unsigned long dev_queue_flags; + unsigned int i; spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags); - netif_tx_wake_all_queues(netdev); + + for (i = 0; i < netdev->num_tx_queues; i++) { + struct netdev_queue *txq = netdev_get_tx_queue(netdev, i); + + if (netif_tx_queue_stopped(txq)) + netif_tx_wake_queue(txq); + } + spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags); } @@ -315,9 +327,17 @@ void mwifiex_stop_net_dev_queue(struct net_device *netdev, struct mwifiex_adapter *adapter) { unsigned long dev_queue_flags; + unsigned int i; spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags); - netif_tx_stop_all_queues(netdev); + + for (i = 0; i < netdev->num_tx_queues; i++) { + struct netdev_queue *txq = netdev_get_tx_queue(netdev, i); + + if (!netif_tx_queue_stopped(txq)) + netif_tx_stop_queue(txq); + } + spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags); } @@ -345,22 +365,22 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) list_del(&priv->wmm.tid_tbl_ptr[j].ra_list); list_del(&priv->tx_ba_stream_tbl_ptr); list_del(&priv->rx_reorder_tbl_ptr); + list_del(&priv->sta_list); } } } /* - * This function frees the adapter structure. + * This function performs cleanup for adapter structure. * - * The freeing operation is done recursively, by canceling all - * pending commands, freeing the member buffers previously - * allocated (command buffers, scan table buffer, sleep confirm - * command buffer), stopping the timers and calling the cleanup - * routines for every interface, before the actual adapter - * structure is freed. + * The cleanup is done recursively, by canceling all pending + * commands, freeing the member buffers previously allocated + * (command buffers, scan table buffer, sleep confirm command + * buffer), stopping the timers and calling the cleanup routines + * for every interface. */ static void -mwifiex_free_adapter(struct mwifiex_adapter *adapter) +mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter) { if (!adapter) { pr_err("%s: adapter is NULL\n", __func__); @@ -376,12 +396,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter) dev_dbg(adapter->dev, "info: free cmd buffer\n"); mwifiex_free_cmd_buffer(adapter); - del_timer(&adapter->cmd_timer); - dev_dbg(adapter->dev, "info: free scan table\n"); - adapter->if_ops.cleanup_if(adapter); - if (adapter->sleep_cfm) dev_kfree_skb_any(adapter->sleep_cfm); } @@ -406,6 +422,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) spin_lock_init(&priv->rx_pkt_lock); spin_lock_init(&priv->wmm.ra_list_spinlock); spin_lock_init(&priv->curr_bcn_buf_lock); + spin_lock_init(&priv->sta_list_spinlock); } } @@ -420,9 +437,10 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) spin_lock_init(&adapter->cmd_pending_q_lock); spin_lock_init(&adapter->scan_pending_q_lock); + skb_queue_head_init(&adapter->usb_rx_data_q); + for (i = 0; i < adapter->priv_num; ++i) { INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); - adapter->bss_prio_tbl[i].bss_prio_cur = NULL; spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock); } @@ -430,12 +448,12 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) if (!adapter->priv[i]) continue; priv = adapter->priv[i]; - for (j = 0; j < MAX_NUM_TID; ++j) { + for (j = 0; j < MAX_NUM_TID; ++j) INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); - spin_lock_init(&priv->wmm.tid_tbl_ptr[j].tid_tbl_lock); - } INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); + INIT_LIST_HEAD(&priv->sta_list); + skb_queue_head_init(&priv->tdls_txq); spin_lock_init(&priv->tx_ba_stream_tbl_lock); spin_lock_init(&priv->rx_reorder_tbl_lock); @@ -483,6 +501,12 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter) return -1; } } + + if (adapter->if_ops.init_fw_port) { + if (adapter->if_ops.init_fw_port(adapter)) + return -1; + } + for (i = 0; i < adapter->priv_num; i++) { if (adapter->priv[i]) { ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta); @@ -517,46 +541,52 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) { int i; struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bss_prio_node *bssprio_node, *tmp_node, **cur; + struct mwifiex_bss_prio_node *bssprio_node, *tmp_node; struct list_head *head; - spinlock_t *lock; + spinlock_t *lock; /* bss priority lock */ unsigned long flags; for (i = 0; i < adapter->priv_num; ++i) { head = &adapter->bss_prio_tbl[i].bss_prio_head; - cur = &adapter->bss_prio_tbl[i].bss_prio_cur; lock = &adapter->bss_prio_tbl[i].bss_prio_lock; dev_dbg(adapter->dev, "info: delete BSS priority table," - " index = %d, i = %d, head = %p, cur = %p\n", - priv->bss_index, i, head, *cur); - if (*cur) { + " bss_type = %d, bss_num = %d, i = %d," + " head = %p\n", + priv->bss_type, priv->bss_num, i, head); + + { spin_lock_irqsave(lock, flags); if (list_empty(head)) { spin_unlock_irqrestore(lock, flags); continue; } - bssprio_node = list_first_entry(head, - struct mwifiex_bss_prio_node, list); - spin_unlock_irqrestore(lock, flags); - list_for_each_entry_safe(bssprio_node, tmp_node, head, list) { if (bssprio_node->priv == priv) { dev_dbg(adapter->dev, "info: Delete " "node %p, next = %p\n", bssprio_node, tmp_node); - spin_lock_irqsave(lock, flags); list_del(&bssprio_node->list); - spin_unlock_irqrestore(lock, flags); kfree(bssprio_node); } } - *cur = (struct mwifiex_bss_prio_node *)head; + spin_unlock_irqrestore(lock, flags); } } } /* + * This function frees the private structure, including cleans + * up the TX and RX queues and frees the BSS priority tables. + */ +void mwifiex_free_priv(struct mwifiex_private *priv) +{ + mwifiex_clean_txrx(priv); + mwifiex_delete_bss_prio_tbl(priv); + mwifiex_free_curr_bcn(priv); +} + +/* * This function is used to shutdown the driver. * * The following operations are performed sequentially - @@ -573,7 +603,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) int ret = -EINPROGRESS; struct mwifiex_private *priv; s32 i; - unsigned long flags; + struct sk_buff *skb; /* mwifiex already shutdown */ if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY) @@ -586,6 +616,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) return ret; } + /* cancel current command */ + if (adapter->curr_cmd) { + dev_warn(adapter->dev, "curr_cmd is still in processing\n"); + del_timer_sync(&adapter->cmd_timer); + mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); + adapter->curr_cmd = NULL; + } + /* shut down mwifiex */ dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); @@ -599,12 +637,24 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) } } - spin_lock_irqsave(&adapter->mwifiex_lock, flags); + spin_lock(&adapter->mwifiex_lock); + + if (adapter->if_ops.data_complete) { + while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) { + struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); + + priv = adapter->priv[rx_info->bss_num]; + if (priv) + priv->stats.rx_dropped++; + + dev_kfree_skb_any(skb); + adapter->if_ops.data_complete(adapter); + } + } - /* Free adapter structure */ - mwifiex_free_adapter(adapter); + mwifiex_adapter_cleanup(adapter); - spin_unlock_irqrestore(&adapter->mwifiex_lock, flags); + spin_unlock(&adapter->mwifiex_lock); /* Notify completion */ ret = mwifiex_shutdown_fw_complete(adapter); @@ -630,25 +680,27 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, int ret; u32 poll_num = 1; - adapter->winner = 0; + if (adapter->if_ops.check_fw_status) { + adapter->winner = 0; - /* Check if firmware is already running */ - ret = adapter->if_ops.check_fw_status(adapter, poll_num); - if (!ret) { - dev_notice(adapter->dev, - "WLAN FW already running! Skip FW download\n"); - goto done; - } - poll_num = MAX_FIRMWARE_POLL_TRIES; - - /* Check if we are the winner for downloading FW */ - if (!adapter->winner) { - dev_notice(adapter->dev, - "Other interface already running!" - " Skip FW download\n"); - poll_num = MAX_MULTI_INTERFACE_POLL_TRIES; - goto poll_fw; + /* check if firmware is already running */ + ret = adapter->if_ops.check_fw_status(adapter, poll_num); + if (!ret) { + dev_notice(adapter->dev, + "WLAN FW already running! Skip FW dnld\n"); + return 0; + } + + poll_num = MAX_FIRMWARE_POLL_TRIES; + + /* check if we are the winner for downloading FW */ + if (!adapter->winner) { + dev_notice(adapter->dev, + "FW already running! Skip FW dnld\n"); + goto poll_fw; + } } + if (pmfw) { /* Download firmware with helper */ ret = adapter->if_ops.prog_fw(adapter, pmfw); @@ -661,12 +713,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, poll_fw: /* Check if the firmware is downloaded successfully or not */ ret = adapter->if_ops.check_fw_status(adapter, poll_num); - if (ret) { + if (ret) dev_err(adapter->dev, "FW failed to be active in time\n"); - return -1; - } -done: - /* re-enable host interrupt for mwifiex after fw dnld is successful */ - adapter->if_ops.enable_int(adapter); + return ret; } |
