linux/drivers/net/wireless/iwlwifi/mvm/ops.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * This file is provided under a dual BSD/GPLv2 license.  When using or
   4 * redistributing this file, you may do so under either license.
   5 *
   6 * GPL LICENSE SUMMARY
   7 *
   8 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of version 2 of the GNU General Public License as
  12 * published by the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful, but
  15 * WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  22 * USA
  23 *
  24 * The full GNU General Public License is included in this distribution
  25 * in the file called COPYING.
  26 *
  27 * Contact Information:
  28 *  Intel Linux Wireless <ilw@linux.intel.com>
  29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  30 *
  31 * BSD LICENSE
  32 *
  33 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
  34 * All rights reserved.
  35 *
  36 * Redistribution and use in source and binary forms, with or without
  37 * modification, are permitted provided that the following conditions
  38 * are met:
  39 *
  40 *  * Redistributions of source code must retain the above copyright
  41 *    notice, this list of conditions and the following disclaimer.
  42 *  * Redistributions in binary form must reproduce the above copyright
  43 *    notice, this list of conditions and the following disclaimer in
  44 *    the documentation and/or other materials provided with the
  45 *    distribution.
  46 *  * Neither the name Intel Corporation nor the names of its
  47 *    contributors may be used to endorse or promote products derived
  48 *    from this software without specific prior written permission.
  49 *
  50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61 *
  62 *****************************************************************************/
  63#include <linux/module.h>
  64#include <net/mac80211.h>
  65
  66#include "iwl-notif-wait.h"
  67#include "iwl-trans.h"
  68#include "iwl-op-mode.h"
  69#include "iwl-fw.h"
  70#include "iwl-debug.h"
  71#include "iwl-drv.h"
  72#include "iwl-modparams.h"
  73#include "mvm.h"
  74#include "iwl-phy-db.h"
  75#include "iwl-eeprom-parse.h"
  76#include "iwl-csr.h"
  77#include "iwl-io.h"
  78#include "iwl-prph.h"
  79#include "rs.h"
  80#include "fw-api-scan.h"
  81#include "time-event.h"
  82
  83/*
  84 * module name, copyright, version, etc.
  85 */
  86#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
  87
  88#define DRV_VERSION     IWLWIFI_VERSION
  89
  90MODULE_DESCRIPTION(DRV_DESCRIPTION);
  91MODULE_VERSION(DRV_VERSION);
  92MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
  93MODULE_LICENSE("GPL");
  94
  95static const struct iwl_op_mode_ops iwl_mvm_ops;
  96
  97struct iwl_mvm_mod_params iwlmvm_mod_params = {
  98        .power_scheme = IWL_POWER_SCHEME_BPS,
  99        /* rest of fields are 0 by default */
 100};
 101
 102module_param_named(init_dbg, iwlmvm_mod_params.init_dbg, bool, S_IRUGO);
 103MODULE_PARM_DESC(init_dbg,
 104                 "set to true to debug an ASSERT in INIT fw (default: false");
 105module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, S_IRUGO);
 106MODULE_PARM_DESC(power_scheme,
 107                 "power management scheme: 1-active, 2-balanced, 3-low power, default: 2");
 108
 109/*
 110 * module init and exit functions
 111 */
 112static int __init iwl_mvm_init(void)
 113{
 114        int ret;
 115
 116        ret = iwl_mvm_rate_control_register();
 117        if (ret) {
 118                pr_err("Unable to register rate control algorithm: %d\n", ret);
 119                return ret;
 120        }
 121
 122        ret = iwl_opmode_register("iwlmvm", &iwl_mvm_ops);
 123
 124        if (ret) {
 125                pr_err("Unable to register MVM op_mode: %d\n", ret);
 126                iwl_mvm_rate_control_unregister();
 127        }
 128
 129        return ret;
 130}
 131module_init(iwl_mvm_init);
 132
 133static void __exit iwl_mvm_exit(void)
 134{
 135        iwl_opmode_deregister("iwlmvm");
 136        iwl_mvm_rate_control_unregister();
 137}
 138module_exit(iwl_mvm_exit);
 139
 140static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
 141{
 142        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 143        u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
 144        u32 reg_val = 0;
 145
 146        radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >>
 147                          FW_PHY_CFG_RADIO_TYPE_POS;
 148        radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >>
 149                          FW_PHY_CFG_RADIO_STEP_POS;
 150        radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >>
 151                          FW_PHY_CFG_RADIO_DASH_POS;
 152
 153        /* SKU control */
 154        reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
 155                                CSR_HW_IF_CONFIG_REG_POS_MAC_STEP;
 156        reg_val |= CSR_HW_REV_DASH(mvm->trans->hw_rev) <<
 157                                CSR_HW_IF_CONFIG_REG_POS_MAC_DASH;
 158
 159        /* radio configuration */
 160        reg_val |= radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;
 161        reg_val |= radio_cfg_step << CSR_HW_IF_CONFIG_REG_POS_PHY_STEP;
 162        reg_val |= radio_cfg_dash << CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
 163
 164        WARN_ON((radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE) &
 165                 ~CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE);
 166
 167        /* silicon bits */
 168        reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
 169
 170        iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
 171                                CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
 172                                CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP |
 173                                CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
 174                                CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
 175                                CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH |
 176                                CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
 177                                CSR_HW_IF_CONFIG_REG_BIT_MAC_SI,
 178                                reg_val);
 179
 180        IWL_DEBUG_INFO(mvm, "Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type,
 181                       radio_cfg_step, radio_cfg_dash);
 182
 183        /*
 184         * W/A : NIC is stuck in a reset state after Early PCIe power off
 185         * (PCIe power is lost before PERST# is asserted), causing ME FW
 186         * to lose ownership and not being able to obtain it back.
 187         */
 188        iwl_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG,
 189                               APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
 190                               ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
 191}
 192
 193struct iwl_rx_handlers {
 194        u8 cmd_id;
 195        bool async;
 196        int (*fn)(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 197                  struct iwl_device_cmd *cmd);
 198};
 199
 200#define RX_HANDLER(_cmd_id, _fn, _async)        \
 201        { .cmd_id = _cmd_id , .fn = _fn , .async = _async }
 202
 203/*
 204 * Handlers for fw notifications
 205 * Convention: RX_HANDLER(CMD_NAME, iwl_mvm_rx_CMD_NAME
 206 * This list should be in order of frequency for performance purposes.
 207 *
 208 * The handler can be SYNC - this means that it will be called in the Rx path
 209 * which can't acquire mvm->mutex. If the handler needs to hold mvm->mutex (and
 210 * only in this case!), it should be set as ASYNC. In that case, it will be
 211 * called from a worker with mvm->mutex held.
 212 */
 213static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
 214        RX_HANDLER(REPLY_RX_MPDU_CMD, iwl_mvm_rx_rx_mpdu, false),
 215        RX_HANDLER(REPLY_RX_PHY_CMD, iwl_mvm_rx_rx_phy_cmd, false),
 216        RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, false),
 217        RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false),
 218        RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false),
 219
 220        RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
 221        RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
 222
 223        RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
 224        RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),
 225
 226        RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
 227        RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
 228
 229        RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false),
 230};
 231#undef RX_HANDLER
 232#define CMD(x) [x] = #x
 233
 234static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
 235        CMD(MVM_ALIVE),
 236        CMD(REPLY_ERROR),
 237        CMD(INIT_COMPLETE_NOTIF),
 238        CMD(PHY_CONTEXT_CMD),
 239        CMD(MGMT_MCAST_KEY),
 240        CMD(TX_CMD),
 241        CMD(TXPATH_FLUSH),
 242        CMD(MAC_CONTEXT_CMD),
 243        CMD(TIME_EVENT_CMD),
 244        CMD(TIME_EVENT_NOTIFICATION),
 245        CMD(BINDING_CONTEXT_CMD),
 246        CMD(TIME_QUOTA_CMD),
 247        CMD(RADIO_VERSION_NOTIFICATION),
 248        CMD(SCAN_REQUEST_CMD),
 249        CMD(SCAN_ABORT_CMD),
 250        CMD(SCAN_START_NOTIFICATION),
 251        CMD(SCAN_RESULTS_NOTIFICATION),
 252        CMD(SCAN_COMPLETE_NOTIFICATION),
 253        CMD(NVM_ACCESS_CMD),
 254        CMD(PHY_CONFIGURATION_CMD),
 255        CMD(CALIB_RES_NOTIF_PHY_DB),
 256        CMD(SET_CALIB_DEFAULT_CMD),
 257        CMD(CALIBRATION_COMPLETE_NOTIFICATION),
 258        CMD(ADD_STA),
 259        CMD(REMOVE_STA),
 260        CMD(LQ_CMD),
 261        CMD(SCAN_OFFLOAD_CONFIG_CMD),
 262        CMD(SCAN_OFFLOAD_REQUEST_CMD),
 263        CMD(SCAN_OFFLOAD_ABORT_CMD),
 264        CMD(SCAN_OFFLOAD_COMPLETE),
 265        CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
 266        CMD(POWER_TABLE_CMD),
 267        CMD(WEP_KEY),
 268        CMD(REPLY_RX_PHY_CMD),
 269        CMD(REPLY_RX_MPDU_CMD),
 270        CMD(BEACON_NOTIFICATION),
 271        CMD(BEACON_TEMPLATE_CMD),
 272        CMD(STATISTICS_NOTIFICATION),
 273        CMD(TX_ANT_CONFIGURATION_CMD),
 274        CMD(D3_CONFIG_CMD),
 275        CMD(PROT_OFFLOAD_CONFIG_CMD),
 276        CMD(OFFLOADS_QUERY_CMD),
 277        CMD(REMOTE_WAKE_CONFIG_CMD),
 278        CMD(WOWLAN_PATTERNS),
 279        CMD(WOWLAN_CONFIGURATION),
 280        CMD(WOWLAN_TSC_RSC_PARAM),
 281        CMD(WOWLAN_TKIP_PARAM),
 282        CMD(WOWLAN_KEK_KCK_MATERIAL),
 283        CMD(WOWLAN_GET_STATUSES),
 284        CMD(WOWLAN_TX_POWER_PER_DB),
 285        CMD(NET_DETECT_CONFIG_CMD),
 286        CMD(NET_DETECT_PROFILES_QUERY_CMD),
 287        CMD(NET_DETECT_PROFILES_CMD),
 288        CMD(NET_DETECT_HOTSPOTS_CMD),
 289        CMD(NET_DETECT_HOTSPOTS_QUERY_CMD),
 290        CMD(CARD_STATE_NOTIFICATION),
 291        CMD(BT_COEX_PRIO_TABLE),
 292        CMD(BT_COEX_PROT_ENV),
 293        CMD(BT_PROFILE_NOTIFICATION),
 294        CMD(BT_CONFIG),
 295        CMD(MCAST_FILTER_CMD),
 296};
 297#undef CMD
 298
 299/* this forward declaration can avoid to export the function */
 300static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
 301
 302static struct iwl_op_mode *
 303iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 304                      const struct iwl_fw *fw, struct dentry *dbgfs_dir)
 305{
 306        struct ieee80211_hw *hw;
 307        struct iwl_op_mode *op_mode;
 308        struct iwl_mvm *mvm;
 309        struct iwl_trans_config trans_cfg = {};
 310        static const u8 no_reclaim_cmds[] = {
 311                TX_CMD,
 312        };
 313        int err, scan_size;
 314
 315        /********************************
 316         * 1. Allocating and configuring HW data
 317         ********************************/
 318        hw = ieee80211_alloc_hw(sizeof(struct iwl_op_mode) +
 319                                sizeof(struct iwl_mvm),
 320                                &iwl_mvm_hw_ops);
 321        if (!hw)
 322                return NULL;
 323
 324        op_mode = hw->priv;
 325        op_mode->ops = &iwl_mvm_ops;
 326        op_mode->trans = trans;
 327
 328        mvm = IWL_OP_MODE_GET_MVM(op_mode);
 329        mvm->dev = trans->dev;
 330        mvm->trans = trans;
 331        mvm->cfg = cfg;
 332        mvm->fw = fw;
 333        mvm->hw = hw;
 334
 335        mutex_init(&mvm->mutex);
 336        spin_lock_init(&mvm->async_handlers_lock);
 337        INIT_LIST_HEAD(&mvm->time_event_list);
 338        INIT_LIST_HEAD(&mvm->async_handlers_list);
 339        spin_lock_init(&mvm->time_event_lock);
 340
 341        INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
 342        INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
 343        INIT_WORK(&mvm->sta_drained_wk, iwl_mvm_sta_drained_wk);
 344
 345        SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev);
 346
 347        /*
 348         * Populate the state variables that the transport layer needs
 349         * to know about.
 350         */
 351        trans_cfg.op_mode = op_mode;
 352        trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
 353        trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
 354        trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
 355
 356        if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE)
 357                trans_cfg.bc_table_dword = true;
 358
 359        if (!iwlwifi_mod_params.wd_disable)
 360                trans_cfg.queue_watchdog_timeout = cfg->base_params->wd_timeout;
 361        else
 362                trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED;
 363
 364        trans_cfg.command_names = iwl_mvm_cmd_strings;
 365
 366        trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE;
 367        trans_cfg.cmd_fifo = IWL_MVM_CMD_FIFO;
 368
 369        snprintf(mvm->hw->wiphy->fw_version,
 370                 sizeof(mvm->hw->wiphy->fw_version),
 371                 "%s", fw->fw_version);
 372
 373        /* Configure transport layer */
 374        iwl_trans_configure(mvm->trans, &trans_cfg);
 375
 376        trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
 377        trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
 378
 379        /* set up notification wait support */
 380        iwl_notification_wait_init(&mvm->notif_wait);
 381
 382        /* Init phy db */
 383        mvm->phy_db = iwl_phy_db_init(trans);
 384        if (!mvm->phy_db) {
 385                IWL_ERR(mvm, "Cannot init phy_db\n");
 386                goto out_free;
 387        }
 388
 389        IWL_INFO(mvm, "Detected %s, REV=0x%X\n",
 390                 mvm->cfg->name, mvm->trans->hw_rev);
 391
 392        err = iwl_trans_start_hw(mvm->trans);
 393        if (err)
 394                goto out_free;
 395
 396        mutex_lock(&mvm->mutex);
 397        err = iwl_run_init_mvm_ucode(mvm, true);
 398        mutex_unlock(&mvm->mutex);
 399        if (err && !iwlmvm_mod_params.init_dbg) {
 400                IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err);
 401                goto out_free;
 402        }
 403
 404        /* Stop the hw after the ALIVE and NVM has been read */
 405        if (!iwlmvm_mod_params.init_dbg)
 406                iwl_trans_stop_hw(mvm->trans, false);
 407
 408        scan_size = sizeof(struct iwl_scan_cmd) +
 409                mvm->fw->ucode_capa.max_probe_length +
 410                (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel));
 411        mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL);
 412        if (!mvm->scan_cmd)
 413                goto out_free;
 414
 415        err = iwl_mvm_mac_setup_register(mvm);
 416        if (err)
 417                goto out_free;
 418
 419        err = iwl_mvm_dbgfs_register(mvm, dbgfs_dir);
 420        if (err)
 421                goto out_unregister;
 422
 423        return op_mode;
 424
 425 out_unregister:
 426        ieee80211_unregister_hw(mvm->hw);
 427 out_free:
 428        iwl_phy_db_free(mvm->phy_db);
 429        kfree(mvm->scan_cmd);
 430        iwl_trans_stop_hw(trans, true);
 431        ieee80211_free_hw(mvm->hw);
 432        return NULL;
 433}
 434
 435static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
 436{
 437        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 438        int i;
 439
 440        iwl_mvm_leds_exit(mvm);
 441
 442        ieee80211_unregister_hw(mvm->hw);
 443
 444        kfree(mvm->scan_cmd);
 445
 446        iwl_trans_stop_hw(mvm->trans, true);
 447
 448        iwl_phy_db_free(mvm->phy_db);
 449        mvm->phy_db = NULL;
 450
 451        iwl_free_nvm_data(mvm->nvm_data);
 452        for (i = 0; i < NVM_NUM_OF_SECTIONS; i++)
 453                kfree(mvm->nvm_sections[i].data);
 454
 455        ieee80211_free_hw(mvm->hw);
 456}
 457
 458struct iwl_async_handler_entry {
 459        struct list_head list;
 460        struct iwl_rx_cmd_buffer rxb;
 461        int (*fn)(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 462                  struct iwl_device_cmd *cmd);
 463};
 464
 465void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm)
 466{
 467        struct iwl_async_handler_entry *entry, *tmp;
 468
 469        spin_lock_bh(&mvm->async_handlers_lock);
 470        list_for_each_entry_safe(entry, tmp, &mvm->async_handlers_list, list) {
 471                iwl_free_rxb(&entry->rxb);
 472                list_del(&entry->list);
 473                kfree(entry);
 474        }
 475        spin_unlock_bh(&mvm->async_handlers_lock);
 476}
 477
 478static void iwl_mvm_async_handlers_wk(struct work_struct *wk)
 479{
 480        struct iwl_mvm *mvm =
 481                container_of(wk, struct iwl_mvm, async_handlers_wk);
 482        struct iwl_async_handler_entry *entry, *tmp;
 483        struct list_head local_list;
 484
 485        INIT_LIST_HEAD(&local_list);
 486
 487        /* Ensure that we are not in stop flow (check iwl_mvm_mac_stop) */
 488        mutex_lock(&mvm->mutex);
 489
 490        /*
 491         * Sync with Rx path with a lock. Remove all the entries from this list,
 492         * add them to a local one (lock free), and then handle them.
 493         */
 494        spin_lock_bh(&mvm->async_handlers_lock);
 495        list_splice_init(&mvm->async_handlers_list, &local_list);
 496        spin_unlock_bh(&mvm->async_handlers_lock);
 497
 498        list_for_each_entry_safe(entry, tmp, &local_list, list) {
 499                if (entry->fn(mvm, &entry->rxb, NULL))
 500                        IWL_WARN(mvm,
 501                                 "returned value from ASYNC handlers are ignored\n");
 502                iwl_free_rxb(&entry->rxb);
 503                list_del(&entry->list);
 504                kfree(entry);
 505        }
 506        mutex_unlock(&mvm->mutex);
 507}
 508
 509static int iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode,
 510                               struct iwl_rx_cmd_buffer *rxb,
 511                               struct iwl_device_cmd *cmd)
 512{
 513        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 514        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 515        u8 i;
 516
 517        /*
 518         * Do the notification wait before RX handlers so
 519         * even if the RX handler consumes the RXB we have
 520         * access to it in the notification wait entry.
 521         */
 522        iwl_notification_wait_notify(&mvm->notif_wait, pkt);
 523
 524        for (i = 0; i < ARRAY_SIZE(iwl_mvm_rx_handlers); i++) {
 525                const struct iwl_rx_handlers *rx_h = &iwl_mvm_rx_handlers[i];
 526                struct iwl_async_handler_entry *entry;
 527
 528                if (rx_h->cmd_id != pkt->hdr.cmd)
 529                        continue;
 530
 531                if (!rx_h->async)
 532                        return rx_h->fn(mvm, rxb, cmd);
 533
 534                entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 535                /* we can't do much... */
 536                if (!entry)
 537                        return 0;
 538
 539                entry->rxb._page = rxb_steal_page(rxb);
 540                entry->rxb._offset = rxb->_offset;
 541                entry->rxb._rx_page_order = rxb->_rx_page_order;
 542                entry->fn = rx_h->fn;
 543                spin_lock(&mvm->async_handlers_lock);
 544                list_add_tail(&entry->list, &mvm->async_handlers_list);
 545                spin_unlock(&mvm->async_handlers_lock);
 546                schedule_work(&mvm->async_handlers_wk);
 547                break;
 548        }
 549
 550        return 0;
 551}
 552
 553static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
 554{
 555        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 556        int mq = mvm->queue_to_mac80211[queue];
 557
 558        if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
 559                return;
 560
 561        if (atomic_inc_return(&mvm->queue_stop_count[mq]) > 1) {
 562                IWL_DEBUG_TX_QUEUES(mvm,
 563                                    "queue %d (mac80211 %d) already stopped\n",
 564                                    queue, mq);
 565                return;
 566        }
 567
 568        set_bit(mq, &mvm->transport_queue_stop);
 569        ieee80211_stop_queue(mvm->hw, mq);
 570}
 571
 572static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
 573{
 574        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 575        int mq = mvm->queue_to_mac80211[queue];
 576
 577        if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
 578                return;
 579
 580        if (atomic_dec_return(&mvm->queue_stop_count[mq]) > 0) {
 581                IWL_DEBUG_TX_QUEUES(mvm,
 582                                    "queue %d (mac80211 %d) already awake\n",
 583                                    queue, mq);
 584                return;
 585        }
 586
 587        clear_bit(mq, &mvm->transport_queue_stop);
 588
 589        ieee80211_wake_queue(mvm->hw, mq);
 590}
 591
 592static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 593{
 594        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 595
 596        if (state)
 597                set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
 598        else
 599                clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
 600
 601        wiphy_rfkill_set_hw_state(mvm->hw->wiphy, state);
 602}
 603
 604static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
 605{
 606        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 607        struct ieee80211_tx_info *info;
 608
 609        info = IEEE80211_SKB_CB(skb);
 610        iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]);
 611        ieee80211_free_txskb(mvm->hw, skb);
 612}
 613
 614static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
 615{
 616        iwl_abort_notification_waits(&mvm->notif_wait);
 617
 618        /*
 619         * If we're restarting already, don't cycle restarts.
 620         * If INIT fw asserted, it will likely fail again.
 621         * If WoWLAN fw asserted, don't restart either, mac80211
 622         * can't recover this since we're already half suspended.
 623         */
 624        if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
 625                IWL_ERR(mvm, "Firmware error during reconfiguration! Abort.\n");
 626        } else if (mvm->cur_ucode == IWL_UCODE_REGULAR &&
 627                   iwlwifi_mod_params.restart_fw) {
 628                /*
 629                 * This is a bit racy, but worst case we tell mac80211 about
 630                 * a stopped/aborted (sched) scan when that was already done
 631                 * which is not a problem. It is necessary to abort any scan
 632                 * here because mac80211 requires having the scan cleared
 633                 * before restarting.
 634                 * We'll reset the scan_status to NONE in restart cleanup in
 635                 * the next start() call from mac80211.
 636                 */
 637                switch (mvm->scan_status) {
 638                case IWL_MVM_SCAN_NONE:
 639                        break;
 640                case IWL_MVM_SCAN_OS:
 641                        ieee80211_scan_completed(mvm->hw, true);
 642                        break;
 643                }
 644
 645                ieee80211_restart_hw(mvm->hw);
 646        }
 647}
 648
 649static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
 650{
 651        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 652
 653        iwl_mvm_dump_nic_error_log(mvm);
 654
 655        iwl_mvm_nic_restart(mvm);
 656}
 657
 658static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
 659{
 660        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 661
 662        WARN_ON(1);
 663        iwl_mvm_nic_restart(mvm);
 664}
 665
 666static const struct iwl_op_mode_ops iwl_mvm_ops = {
 667        .start = iwl_op_mode_mvm_start,
 668        .stop = iwl_op_mode_mvm_stop,
 669        .rx = iwl_mvm_rx_dispatch,
 670        .queue_full = iwl_mvm_stop_sw_queue,
 671        .queue_not_full = iwl_mvm_wake_sw_queue,
 672        .hw_rf_kill = iwl_mvm_set_hw_rfkill_state,
 673        .free_skb = iwl_mvm_free_skb,
 674        .nic_error = iwl_mvm_nic_error,
 675        .cmd_queue_full = iwl_mvm_cmd_queue_full,
 676        .nic_config = iwl_mvm_nic_config,
 677};
 678