root/drivers/net/wireless/marvell/mwifiex/init.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mwifiex_add_bss_prio_tbl
  2. wakeup_timer_fn
  3. fw_dump_timer_fn
  4. mwifiex_init_priv
  5. mwifiex_allocate_adapter
  6. mwifiex_init_adapter
  7. mwifiex_set_trans_start
  8. mwifiex_wake_up_net_dev_queue
  9. mwifiex_stop_net_dev_queue
  10. mwifiex_invalidate_lists
  11. mwifiex_adapter_cleanup
  12. mwifiex_free_cmd_buffers
  13. mwifiex_init_lock_list
  14. mwifiex_init_fw
  15. mwifiex_delete_bss_prio_tbl
  16. mwifiex_free_priv
  17. mwifiex_shutdown_drv
  18. mwifiex_dnld_fw

   1 /*
   2  * Marvell Wireless LAN device driver: HW/FW Initialization
   3  *
   4  * Copyright (C) 2011-2014, Marvell International Ltd.
   5  *
   6  * This software file (the "File") is distributed by Marvell International
   7  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
   8  * (the "License").  You may use, redistribute and/or modify this File in
   9  * accordance with the terms and conditions of the License, a copy of which
  10  * is available by writing to the Free Software Foundation, Inc.,
  11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
  12  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  13  *
  14  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
  17  * this warranty disclaimer.
  18  */
  19 
  20 #include "decl.h"
  21 #include "ioctl.h"
  22 #include "util.h"
  23 #include "fw.h"
  24 #include "main.h"
  25 #include "wmm.h"
  26 #include "11n.h"
  27 
  28 /*
  29  * This function adds a BSS priority table to the table list.
  30  *
  31  * The function allocates a new BSS priority table node and adds it to
  32  * the end of BSS priority table list, kept in driver memory.
  33  */
  34 static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
  35 {
  36         struct mwifiex_adapter *adapter = priv->adapter;
  37         struct mwifiex_bss_prio_node *bss_prio;
  38         struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
  39 
  40         bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL);
  41         if (!bss_prio)
  42                 return -ENOMEM;
  43 
  44         bss_prio->priv = priv;
  45         INIT_LIST_HEAD(&bss_prio->list);
  46 
  47         spin_lock_bh(&tbl[priv->bss_priority].bss_prio_lock);
  48         list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
  49         spin_unlock_bh(&tbl[priv->bss_priority].bss_prio_lock);
  50 
  51         return 0;
  52 }
  53 
  54 static void wakeup_timer_fn(struct timer_list *t)
  55 {
  56         struct mwifiex_adapter *adapter = from_timer(adapter, t, wakeup_timer);
  57 
  58         mwifiex_dbg(adapter, ERROR, "Firmware wakeup failed\n");
  59         adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
  60         mwifiex_cancel_all_pending_cmd(adapter);
  61 
  62         if (adapter->if_ops.card_reset)
  63                 adapter->if_ops.card_reset(adapter);
  64 }
  65 
  66 static void fw_dump_timer_fn(struct timer_list *t)
  67 {
  68         struct mwifiex_adapter *adapter = from_timer(adapter, t, devdump_timer);
  69 
  70         mwifiex_upload_device_dump(adapter);
  71 }
  72 
  73 /*
  74  * This function initializes the private structure and sets default
  75  * values to the members.
  76  *
  77  * Additionally, it also initializes all the locks and sets up all the
  78  * lists.
  79  */
  80 int mwifiex_init_priv(struct mwifiex_private *priv)
  81 {
  82         u32 i;
  83 
  84         priv->media_connected = false;
  85         eth_broadcast_addr(priv->curr_addr);
  86         priv->port_open = false;
  87         priv->usb_port = MWIFIEX_USB_EP_DATA;
  88         priv->pkt_tx_ctrl = 0;
  89         priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
  90         priv->data_rate = 0;    /* Initially indicate the rate as auto */
  91         priv->is_data_rate_auto = true;
  92         priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
  93         priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
  94 
  95         priv->sec_info.wep_enabled = 0;
  96         priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
  97         priv->sec_info.encryption_mode = 0;
  98         for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++)
  99                 memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key));
 100         priv->wep_key_curr_index = 0;
 101         priv->curr_pkt_filter = HostCmd_ACT_MAC_DYNAMIC_BW_ENABLE |
 102                                 HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
 103                                 HostCmd_ACT_MAC_ETHERNETII_ENABLE;
 104 
 105         priv->beacon_period = 100; /* beacon interval */
 106         priv->attempted_bss_desc = NULL;
 107         memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params));
 108         priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL;
 109 
 110         memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid));
 111         memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid));
 112         memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
 113         priv->assoc_rsp_size = 0;
 114         priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
 115         priv->atim_window = 0;
 116         priv->adhoc_state = ADHOC_IDLE;
 117         priv->tx_power_level = 0;
 118         priv->max_tx_power_level = 0;
 119         priv->min_tx_power_level = 0;
 120         priv->tx_ant = 0;
 121         priv->rx_ant = 0;
 122         priv->tx_rate = 0;
 123         priv->rxpd_htinfo = 0;
 124         priv->rxpd_rate = 0;
 125         priv->rate_bitmap = 0;
 126         priv->data_rssi_last = 0;
 127         priv->data_rssi_avg = 0;
 128         priv->data_nf_avg = 0;
 129         priv->data_nf_last = 0;
 130         priv->bcn_rssi_last = 0;
 131         priv->bcn_rssi_avg = 0;
 132         priv->bcn_nf_avg = 0;
 133         priv->bcn_nf_last = 0;
 134         memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie));
 135         memset(&priv->aes_key, 0, sizeof(priv->aes_key));
 136         priv->wpa_ie_len = 0;
 137         priv->wpa_is_gtk_set = false;
 138 
 139         memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf));
 140         priv->assoc_tlv_buf_len = 0;
 141         memset(&priv->wps, 0, sizeof(priv->wps));
 142         memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
 143         priv->gen_ie_buf_len = 0;
 144         memset(priv->vs_ie, 0, sizeof(priv->vs_ie));
 145 
 146         priv->wmm_required = true;
 147         priv->wmm_enabled = false;
 148         priv->wmm_qosinfo = 0;
 149         priv->curr_bcn_buf = NULL;
 150         priv->curr_bcn_size = 0;
 151         priv->wps_ie = NULL;
 152         priv->wps_ie_len = 0;
 153         priv->ap_11n_enabled = 0;
 154         memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg));
 155 
 156         priv->scan_block = false;
 157 
 158         priv->csa_chan = 0;
 159         priv->csa_expire_time = 0;
 160         priv->del_list_idx = 0;
 161         priv->hs2_enabled = false;
 162         priv->check_tdls_tx = false;
 163         memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID);
 164 
 165         mwifiex_init_11h_params(priv);
 166 
 167         return mwifiex_add_bss_prio_tbl(priv);
 168 }
 169 
 170 /*
 171  * This function allocates buffers for members of the adapter
 172  * structure.
 173  *
 174  * The memory allocated includes scan table, command buffers, and
 175  * sleep confirm command buffer. In addition, the queues are
 176  * also initialized.
 177  */
 178 static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
 179 {
 180         int ret;
 181 
 182         /* Allocate command buffer */
 183         ret = mwifiex_alloc_cmd_buffer(adapter);
 184         if (ret) {
 185                 mwifiex_dbg(adapter, ERROR,
 186                             "%s: failed to alloc cmd buffer\n",
 187                             __func__);
 188                 return -1;
 189         }
 190 
 191         adapter->sleep_cfm =
 192                 dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
 193                               + INTF_HEADER_LEN);
 194 
 195         if (!adapter->sleep_cfm) {
 196                 mwifiex_dbg(adapter, ERROR,
 197                             "%s: failed to alloc sleep cfm\t"
 198                             " cmd buffer\n", __func__);
 199                 return -1;
 200         }
 201         skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN);
 202 
 203         return 0;
 204 }
 205 
 206 /*
 207  * This function initializes the adapter structure and sets default
 208  * values to the members of adapter.
 209  *
 210  * This also initializes the WMM related parameters in the driver private
 211  * structures.
 212  */
 213 static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
 214 {
 215         struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = NULL;
 216 
 217         skb_put(adapter->sleep_cfm, sizeof(struct mwifiex_opt_sleep_confirm));
 218 
 219         adapter->cmd_sent = false;
 220 
 221         if (adapter->iface_type == MWIFIEX_SDIO)
 222                 adapter->data_sent = true;
 223         else
 224                 adapter->data_sent = false;
 225 
 226         if (adapter->iface_type == MWIFIEX_USB)
 227                 adapter->intf_hdr_len = 0;
 228         else
 229                 adapter->intf_hdr_len = INTF_HEADER_LEN;
 230 
 231         adapter->cmd_resp_received = false;
 232         adapter->event_received = false;
 233         adapter->data_received = false;
 234 
 235         clear_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags);
 236 
 237         adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
 238 
 239         adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
 240         adapter->ps_state = PS_STATE_AWAKE;
 241         adapter->need_to_wakeup = false;
 242 
 243         adapter->scan_mode = HostCmd_BSS_MODE_ANY;
 244         adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME;
 245         adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
 246         adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
 247         adapter->scan_chan_gap_time = MWIFIEX_DEF_SCAN_CHAN_GAP_TIME;
 248 
 249         adapter->scan_probes = 1;
 250 
 251         adapter->multiple_dtim = 1;
 252 
 253         adapter->local_listen_interval = 0;     /* default value in firmware
 254                                                    will be used */
 255 
 256         adapter->is_deep_sleep = false;
 257 
 258         adapter->delay_null_pkt = false;
 259         adapter->delay_to_ps = 1000;
 260         adapter->enhanced_ps_mode = PS_MODE_AUTO;
 261 
 262         adapter->gen_null_pkt = false;  /* Disable NULL Pkg generation by
 263                                            default */
 264         adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by
 265                                            default */
 266         adapter->pm_wakeup_card_req = false;
 267 
 268         adapter->pm_wakeup_fw_try = false;
 269 
 270         adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
 271 
 272         clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags);
 273         adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF);
 274         adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF;
 275         adapter->hs_cfg.gap = HS_CFG_GAP_DEF;
 276         adapter->hs_activated = false;
 277 
 278         memset(adapter->event_body, 0, sizeof(adapter->event_body));
 279         adapter->hw_dot_11n_dev_cap = 0;
 280         adapter->hw_dev_mcs_support = 0;
 281         adapter->sec_chan_offset = 0;
 282         adapter->adhoc_11n_enabled = false;
 283 
 284         mwifiex_wmm_init(adapter);
 285         atomic_set(&adapter->tx_hw_pending, 0);
 286 
 287         sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
 288                                         adapter->sleep_cfm->data;
 289         memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len);
 290         sleep_cfm_buf->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
 291         sleep_cfm_buf->size = cpu_to_le16(adapter->sleep_cfm->len);
 292         sleep_cfm_buf->result = 0;
 293         sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM);
 294         sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED);
 295 
 296         memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params));
 297         memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period));
 298         adapter->tx_lock_flag = false;
 299         adapter->null_pkt_interval = 0;
 300         adapter->fw_bands = 0;
 301         adapter->config_bands = 0;
 302         adapter->adhoc_start_band = 0;
 303         adapter->scan_channels = NULL;
 304         adapter->fw_release_number = 0;
 305         adapter->fw_cap_info = 0;
 306         memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf));
 307         adapter->event_cause = 0;
 308         adapter->region_code = 0;
 309         adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
 310         adapter->adhoc_awake_period = 0;
 311         memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
 312         adapter->arp_filter_size = 0;
 313         adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
 314         adapter->mfg_mode = mfg_mode;
 315         adapter->key_api_major_ver = 0;
 316         adapter->key_api_minor_ver = 0;
 317         eth_broadcast_addr(adapter->perm_addr);
 318         adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
 319         adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
 320         adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
 321         adapter->active_scan_triggered = false;
 322         timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
 323         adapter->devdump_len = 0;
 324         timer_setup(&adapter->devdump_timer, fw_dump_timer_fn, 0);
 325 }
 326 
 327 /*
 328  * This function sets trans_start per tx_queue
 329  */
 330 void mwifiex_set_trans_start(struct net_device *dev)
 331 {
 332         int i;
 333 
 334         for (i = 0; i < dev->num_tx_queues; i++)
 335                 netdev_get_tx_queue(dev, i)->trans_start = jiffies;
 336 
 337         netif_trans_update(dev);
 338 }
 339 
 340 /*
 341  * This function wakes up all queues in net_device
 342  */
 343 void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
 344                                         struct mwifiex_adapter *adapter)
 345 {
 346         spin_lock_bh(&adapter->queue_lock);
 347         netif_tx_wake_all_queues(netdev);
 348         spin_unlock_bh(&adapter->queue_lock);
 349 }
 350 
 351 /*
 352  * This function stops all queues in net_device
 353  */
 354 void mwifiex_stop_net_dev_queue(struct net_device *netdev,
 355                                         struct mwifiex_adapter *adapter)
 356 {
 357         spin_lock_bh(&adapter->queue_lock);
 358         netif_tx_stop_all_queues(netdev);
 359         spin_unlock_bh(&adapter->queue_lock);
 360 }
 361 
 362 /*
 363  * This function invalidates the list heads.
 364  */
 365 static void mwifiex_invalidate_lists(struct mwifiex_adapter *adapter)
 366 {
 367         struct mwifiex_private *priv;
 368         s32 i, j;
 369 
 370         list_del(&adapter->cmd_free_q);
 371         list_del(&adapter->cmd_pending_q);
 372         list_del(&adapter->scan_pending_q);
 373 
 374         for (i = 0; i < adapter->priv_num; i++)
 375                 list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
 376 
 377         for (i = 0; i < adapter->priv_num; i++) {
 378                 if (adapter->priv[i]) {
 379                         priv = adapter->priv[i];
 380                         for (j = 0; j < MAX_NUM_TID; ++j)
 381                                 list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
 382                         list_del(&priv->tx_ba_stream_tbl_ptr);
 383                         list_del(&priv->rx_reorder_tbl_ptr);
 384                         list_del(&priv->sta_list);
 385                         list_del(&priv->auto_tdls_list);
 386                 }
 387         }
 388 }
 389 
 390 /*
 391  * This function performs cleanup for adapter structure.
 392  *
 393  * The cleanup is done recursively, by canceling all pending
 394  * commands, freeing the member buffers previously allocated
 395  * (command buffers, scan table buffer, sleep confirm command
 396  * buffer), stopping the timers and calling the cleanup routines
 397  * for every interface.
 398  */
 399 static void
 400 mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
 401 {
 402         del_timer(&adapter->wakeup_timer);
 403         del_timer_sync(&adapter->devdump_timer);
 404         mwifiex_cancel_all_pending_cmd(adapter);
 405         wake_up_interruptible(&adapter->cmd_wait_q.wait);
 406         wake_up_interruptible(&adapter->hs_activate_wait_q);
 407 }
 408 
 409 void mwifiex_free_cmd_buffers(struct mwifiex_adapter *adapter)
 410 {
 411         mwifiex_invalidate_lists(adapter);
 412 
 413         /* Free command buffer */
 414         mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n");
 415         mwifiex_free_cmd_buffer(adapter);
 416 
 417         if (adapter->sleep_cfm)
 418                 dev_kfree_skb_any(adapter->sleep_cfm);
 419 }
 420 
 421 /*
 422  *  This function intializes the lock variables and
 423  *  the list heads.
 424  */
 425 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
 426 {
 427         struct mwifiex_private *priv;
 428         s32 i, j;
 429 
 430         spin_lock_init(&adapter->int_lock);
 431         spin_lock_init(&adapter->main_proc_lock);
 432         spin_lock_init(&adapter->mwifiex_cmd_lock);
 433         spin_lock_init(&adapter->queue_lock);
 434         for (i = 0; i < adapter->priv_num; i++) {
 435                 if (adapter->priv[i]) {
 436                         priv = adapter->priv[i];
 437                         spin_lock_init(&priv->wmm.ra_list_spinlock);
 438                         spin_lock_init(&priv->curr_bcn_buf_lock);
 439                         spin_lock_init(&priv->sta_list_spinlock);
 440                         spin_lock_init(&priv->auto_tdls_lock);
 441                 }
 442         }
 443 
 444         /* Initialize cmd_free_q */
 445         INIT_LIST_HEAD(&adapter->cmd_free_q);
 446         /* Initialize cmd_pending_q */
 447         INIT_LIST_HEAD(&adapter->cmd_pending_q);
 448         /* Initialize scan_pending_q */
 449         INIT_LIST_HEAD(&adapter->scan_pending_q);
 450 
 451         spin_lock_init(&adapter->cmd_free_q_lock);
 452         spin_lock_init(&adapter->cmd_pending_q_lock);
 453         spin_lock_init(&adapter->scan_pending_q_lock);
 454         spin_lock_init(&adapter->rx_proc_lock);
 455 
 456         skb_queue_head_init(&adapter->rx_data_q);
 457         skb_queue_head_init(&adapter->tx_data_q);
 458 
 459         for (i = 0; i < adapter->priv_num; ++i) {
 460                 INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
 461                 spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock);
 462         }
 463 
 464         for (i = 0; i < adapter->priv_num; i++) {
 465                 if (!adapter->priv[i])
 466                         continue;
 467                 priv = adapter->priv[i];
 468                 for (j = 0; j < MAX_NUM_TID; ++j)
 469                         INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list);
 470                 INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
 471                 INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
 472                 INIT_LIST_HEAD(&priv->sta_list);
 473                 INIT_LIST_HEAD(&priv->auto_tdls_list);
 474                 skb_queue_head_init(&priv->tdls_txq);
 475                 skb_queue_head_init(&priv->bypass_txq);
 476 
 477                 spin_lock_init(&priv->tx_ba_stream_tbl_lock);
 478                 spin_lock_init(&priv->rx_reorder_tbl_lock);
 479 
 480                 spin_lock_init(&priv->ack_status_lock);
 481                 idr_init(&priv->ack_status_frames);
 482         }
 483 
 484         return 0;
 485 }
 486 
 487 /*
 488  * This function initializes the firmware.
 489  *
 490  * The following operations are performed sequentially -
 491  *      - Allocate adapter structure
 492  *      - Initialize the adapter structure
 493  *      - Initialize the private structure
 494  *      - Add BSS priority tables to the adapter structure
 495  *      - For each interface, send the init commands to firmware
 496  *      - Send the first command in command pending queue, if available
 497  */
 498 int mwifiex_init_fw(struct mwifiex_adapter *adapter)
 499 {
 500         int ret;
 501         struct mwifiex_private *priv;
 502         u8 i, first_sta = true;
 503         int is_cmd_pend_q_empty;
 504 
 505         adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
 506 
 507         /* Allocate memory for member of adapter structure */
 508         ret = mwifiex_allocate_adapter(adapter);
 509         if (ret)
 510                 return -1;
 511 
 512         /* Initialize adapter structure */
 513         mwifiex_init_adapter(adapter);
 514 
 515         for (i = 0; i < adapter->priv_num; i++) {
 516                 if (adapter->priv[i]) {
 517                         priv = adapter->priv[i];
 518 
 519                         /* Initialize private structure */
 520                         ret = mwifiex_init_priv(priv);
 521                         if (ret)
 522                                 return -1;
 523                 }
 524         }
 525         if (adapter->mfg_mode) {
 526                 adapter->hw_status = MWIFIEX_HW_STATUS_READY;
 527                 ret = -EINPROGRESS;
 528         } else {
 529                 for (i = 0; i < adapter->priv_num; i++) {
 530                         if (adapter->priv[i]) {
 531                                 ret = mwifiex_sta_init_cmd(adapter->priv[i],
 532                                                            first_sta, true);
 533                                 if (ret == -1)
 534                                         return -1;
 535 
 536                                 first_sta = false;
 537                         }
 538 
 539 
 540 
 541                 }
 542         }
 543 
 544         spin_lock_bh(&adapter->cmd_pending_q_lock);
 545         is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
 546         spin_unlock_bh(&adapter->cmd_pending_q_lock);
 547         if (!is_cmd_pend_q_empty) {
 548                 /* Send the first command in queue and return */
 549                 if (mwifiex_main_process(adapter) != -1)
 550                         ret = -EINPROGRESS;
 551         } else {
 552                 adapter->hw_status = MWIFIEX_HW_STATUS_READY;
 553         }
 554 
 555         return ret;
 556 }
 557 
 558 /*
 559  * This function deletes the BSS priority tables.
 560  *
 561  * The function traverses through all the allocated BSS priority nodes
 562  * in every BSS priority table and frees them.
 563  */
 564 static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
 565 {
 566         int i;
 567         struct mwifiex_adapter *adapter = priv->adapter;
 568         struct mwifiex_bss_prio_node *bssprio_node, *tmp_node;
 569         struct list_head *head;
 570         spinlock_t *lock; /* bss priority lock */
 571 
 572         for (i = 0; i < adapter->priv_num; ++i) {
 573                 head = &adapter->bss_prio_tbl[i].bss_prio_head;
 574                 lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
 575                 mwifiex_dbg(adapter, INFO,
 576                             "info: delete BSS priority table,\t"
 577                             "bss_type = %d, bss_num = %d, i = %d,\t"
 578                             "head = %p\n",
 579                             priv->bss_type, priv->bss_num, i, head);
 580 
 581                 {
 582                         spin_lock_bh(lock);
 583                         list_for_each_entry_safe(bssprio_node, tmp_node, head,
 584                                                  list) {
 585                                 if (bssprio_node->priv == priv) {
 586                                         mwifiex_dbg(adapter, INFO,
 587                                                     "info: Delete\t"
 588                                                     "node %p, next = %p\n",
 589                                                     bssprio_node, tmp_node);
 590                                         list_del(&bssprio_node->list);
 591                                         kfree(bssprio_node);
 592                                 }
 593                         }
 594                         spin_unlock_bh(lock);
 595                 }
 596         }
 597 }
 598 
 599 /*
 600  * This function frees the private structure, including cleans
 601  * up the TX and RX queues and frees the BSS priority tables.
 602  */
 603 void mwifiex_free_priv(struct mwifiex_private *priv)
 604 {
 605         mwifiex_clean_txrx(priv);
 606         mwifiex_delete_bss_prio_tbl(priv);
 607         mwifiex_free_curr_bcn(priv);
 608 }
 609 
 610 /*
 611  * This function is used to shutdown the driver.
 612  *
 613  * The following operations are performed sequentially -
 614  *      - Check if already shut down
 615  *      - Make sure the main process has stopped
 616  *      - Clean up the Tx and Rx queues
 617  *      - Delete BSS priority tables
 618  *      - Free the adapter
 619  *      - Notify completion
 620  */
 621 void
 622 mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
 623 {
 624         struct mwifiex_private *priv;
 625         s32 i;
 626         struct sk_buff *skb;
 627 
 628         /* mwifiex already shutdown */
 629         if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)
 630                 return;
 631 
 632         /* cancel current command */
 633         if (adapter->curr_cmd) {
 634                 mwifiex_dbg(adapter, WARN,
 635                             "curr_cmd is still in processing\n");
 636                 del_timer_sync(&adapter->cmd_timer);
 637                 mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
 638                 adapter->curr_cmd = NULL;
 639         }
 640 
 641         /* shut down mwifiex */
 642         mwifiex_dbg(adapter, MSG,
 643                     "info: shutdown mwifiex...\n");
 644 
 645         /* Clean up Tx/Rx queues and delete BSS priority table */
 646         for (i = 0; i < adapter->priv_num; i++) {
 647                 if (adapter->priv[i]) {
 648                         priv = adapter->priv[i];
 649 
 650                         mwifiex_clean_auto_tdls(priv);
 651                         mwifiex_abort_cac(priv);
 652                         mwifiex_free_priv(priv);
 653                 }
 654         }
 655 
 656         atomic_set(&adapter->tx_queued, 0);
 657         while ((skb = skb_dequeue(&adapter->tx_data_q)))
 658                 mwifiex_write_data_complete(adapter, skb, 0, 0);
 659 
 660         spin_lock_bh(&adapter->rx_proc_lock);
 661 
 662         while ((skb = skb_dequeue(&adapter->rx_data_q))) {
 663                 struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
 664 
 665                 atomic_dec(&adapter->rx_pending);
 666                 priv = adapter->priv[rx_info->bss_num];
 667                 if (priv)
 668                         priv->stats.rx_dropped++;
 669 
 670                 dev_kfree_skb_any(skb);
 671         }
 672 
 673         spin_unlock_bh(&adapter->rx_proc_lock);
 674 
 675         mwifiex_adapter_cleanup(adapter);
 676 
 677         adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY;
 678 }
 679 
 680 /*
 681  * This function downloads the firmware to the card.
 682  *
 683  * The actual download is preceded by two sanity checks -
 684  *      - Check if firmware is already running
 685  *      - Check if the interface is the winner to download the firmware
 686  *
 687  * ...and followed by another -
 688  *      - Check if the firmware is downloaded successfully
 689  *
 690  * After download is successfully completed, the host interrupts are enabled.
 691  */
 692 int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
 693                     struct mwifiex_fw_image *pmfw)
 694 {
 695         int ret;
 696         u32 poll_num = 1;
 697 
 698         if (adapter->if_ops.check_fw_status) {
 699                 /* check if firmware is already running */
 700                 ret = adapter->if_ops.check_fw_status(adapter, poll_num);
 701                 if (!ret) {
 702                         mwifiex_dbg(adapter, MSG,
 703                                     "WLAN FW already running! Skip FW dnld\n");
 704                         return 0;
 705                 }
 706         }
 707 
 708         /* check if we are the winner for downloading FW */
 709         if (adapter->if_ops.check_winner_status) {
 710                 adapter->winner = 0;
 711                 ret = adapter->if_ops.check_winner_status(adapter);
 712 
 713                 poll_num = MAX_FIRMWARE_POLL_TRIES;
 714                 if (ret) {
 715                         mwifiex_dbg(adapter, MSG,
 716                                     "WLAN read winner status failed!\n");
 717                         return ret;
 718                 }
 719 
 720                 if (!adapter->winner) {
 721                         mwifiex_dbg(adapter, MSG,
 722                                     "WLAN is not the winner! Skip FW dnld\n");
 723                         goto poll_fw;
 724                 }
 725         }
 726 
 727         if (pmfw) {
 728                 /* Download firmware with helper */
 729                 ret = adapter->if_ops.prog_fw(adapter, pmfw);
 730                 if (ret) {
 731                         mwifiex_dbg(adapter, ERROR,
 732                                     "prog_fw failed ret=%#x\n", ret);
 733                         return ret;
 734                 }
 735         }
 736 
 737 poll_fw:
 738         /* Check if the firmware is downloaded successfully or not */
 739         ret = adapter->if_ops.check_fw_status(adapter, poll_num);
 740         if (ret)
 741                 mwifiex_dbg(adapter, ERROR,
 742                             "FW failed to be active in time\n");
 743 
 744         return ret;
 745 }
 746 EXPORT_SYMBOL_GPL(mwifiex_dnld_fw);

/* [<][>][^][v][top][bottom][index][help] */