Merge tag 'iwlwifi-next-for-kalle-2015-04-02' of https://git.kernel.org/pub/scm/linux...
authorKalle Valo <kvalo@codeaurora.org>
Tue, 7 Apr 2015 16:55:57 +0000 (19:55 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 7 Apr 2015 16:55:57 +0000 (19:55 +0300)
* some more work on LAR
* fixes for UMAC scan
* more work on debugging framework
* more work for 8000 devices
* cleanups and small bugfixes

38 files changed:
drivers/net/wireless/iwlwifi/iwl-8000.c
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-drv.h
drivers/net/wireless/iwlwifi/iwl-eeprom-read.c
drivers/net/wireless/iwlwifi/iwl-fh.h
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
drivers/net/wireless/iwlwifi/iwl-fw-file.h
drivers/net/wireless/iwlwifi/iwl-io.c
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
drivers/net/wireless/iwlwifi/iwl-op-mode.h
drivers/net/wireless/iwlwifi/iwl-phy-db.c
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/nvm.c
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/rx.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.h
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/time-event.h
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c

index 9c396a42aec8ba708fcab1e81b69567c23f055ba..ce6321b7d24156269fd553f4409078b1c3fb24df 100644 (file)
@@ -94,8 +94,8 @@
        IWL8000_FW_PRE "-" __stringify(api) ".ucode"
 
 #define NVM_HW_SECTION_NUM_FAMILY_8000         10
-#define DEFAULT_NVM_FILE_FAMILY_8000A          "iwl_nvm_8000.bin"
-#define DEFAULT_NVM_FILE_FAMILY_8000           "iwl_nvm_8000B.bin"
+#define DEFAULT_NVM_FILE_FAMILY_8000B          "nvmData-8000B"
+#define DEFAULT_NVM_FILE_FAMILY_8000C          "nvmData-8000C"
 
 /* Max SDIO RX aggregation size of the ADDBA request/response */
 #define MAX_RX_AGG_SIZE_8260_SDIO      28
@@ -177,8 +177,8 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
        .ht_params = &iwl8000_ht_params,
        .nvm_ver = IWL8000_NVM_VERSION,
        .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
-       .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
-       .default_nvm_file_8000A = DEFAULT_NVM_FILE_FAMILY_8000A,
+       .default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B,
+       .default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C,
        .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
        .disable_dummy_notification = true,
        .max_ht_ampdu_exponent  = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
@@ -192,8 +192,8 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
        .ht_params = &iwl8000_ht_params,
        .nvm_ver = IWL8000_NVM_VERSION,
        .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
-       .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
-       .default_nvm_file_8000A = DEFAULT_NVM_FILE_FAMILY_8000A,
+       .default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B,
+       .default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C,
        .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
        .bt_shared_single_ant = true,
        .disable_dummy_notification = true,
index 4b190d98a1ec0c3f98427c3efaab9e0162eb80f3..07e999a32a7fcb28c08f77a9553fa94c8ffcaacc 100644 (file)
@@ -228,7 +228,7 @@ struct iwl_pwr_tx_backoff {
 
 /**
  * struct iwl_cfg
- * @name: Offical name of the device
+ * @name: Official name of the device
  * @fw_name_pre: Firmware filename prefix. The api version and extension
  *     (.ucode) will be added to filename before loading from disk. The
  *     filename is constructed as fw_name_pre<api>.ucode.
@@ -303,8 +303,8 @@ struct iwl_cfg {
        bool lp_xtal_workaround;
        const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
        bool no_power_up_nic_in_init;
-       const char *default_nvm_file;
-       const char *default_nvm_file_8000A;
+       const char *default_nvm_file_B_step;
+       const char *default_nvm_file_C_step;
        unsigned int max_rx_agg_size;
        bool disable_dummy_notification;
        unsigned int max_tx_agg_size;
index aefdd9b7c1051f70abcf85597cf6966606f99b7f..7267152e7dc7705aaa514237c17ed908b9e4919d 100644 (file)
@@ -145,7 +145,7 @@ static struct iwlwifi_opmode_table {
 #define IWL_DEFAULT_SCAN_CHANNELS 40
 
 /*
- * struct fw_sec: Just for the image parsing proccess.
+ * struct fw_sec: Just for the image parsing process.
  * For the fw storage we are using struct fw_desc.
  */
 struct fw_sec {
@@ -241,16 +241,10 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
         * previous name and uses the new format.
         */
        if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
-               char rev_step[2] = {
-                       'A' + CSR_HW_REV_STEP(drv->trans->hw_rev), 0
-               };
-
-               /* A-step doesn't have an indication */
-               if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP)
-                       rev_step[0] = 0;
+               char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev);
 
                snprintf(drv->firmware_name, sizeof(drv->firmware_name),
-                        "%s%s-%s.ucode", name_pre, rev_step, tag);
+                        "%s%c-%s.ucode", name_pre, rev_step, tag);
        }
 
        IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",
@@ -1108,6 +1102,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
        const unsigned int api_max = drv->cfg->ucode_api_max;
        unsigned int api_ok = drv->cfg->ucode_api_ok;
        const unsigned int api_min = drv->cfg->ucode_api_min;
+       size_t trigger_tlv_sz[FW_DBG_TRIGGER_MAX];
        u32 api_ver;
        int i;
        bool load_module = false;
@@ -1227,8 +1222,37 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
                }
        }
 
+       memset(&trigger_tlv_sz, 0xff, sizeof(trigger_tlv_sz));
+
+       trigger_tlv_sz[FW_DBG_TRIGGER_MISSED_BEACONS] =
+               sizeof(struct iwl_fw_dbg_trigger_missed_bcon);
+       trigger_tlv_sz[FW_DBG_TRIGGER_CHANNEL_SWITCH] = 0;
+       trigger_tlv_sz[FW_DBG_TRIGGER_FW_NOTIF] =
+               sizeof(struct iwl_fw_dbg_trigger_cmd);
+       trigger_tlv_sz[FW_DBG_TRIGGER_MLME] =
+               sizeof(struct iwl_fw_dbg_trigger_mlme);
+       trigger_tlv_sz[FW_DBG_TRIGGER_STATS] =
+               sizeof(struct iwl_fw_dbg_trigger_stats);
+       trigger_tlv_sz[FW_DBG_TRIGGER_RSSI] =
+               sizeof(struct iwl_fw_dbg_trigger_low_rssi);
+       trigger_tlv_sz[FW_DBG_TRIGGER_TXQ_TIMERS] =
+               sizeof(struct iwl_fw_dbg_trigger_txq_timer);
+       trigger_tlv_sz[FW_DBG_TRIGGER_TIME_EVENT] =
+               sizeof(struct iwl_fw_dbg_trigger_time_event);
+
        for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) {
                if (pieces->dbg_trigger_tlv[i]) {
+                       /*
+                        * If the trigger isn't long enough, WARN and exit.
+                        * Someone is trying to debug something and he won't
+                        * be able to catch the bug he is trying to chase.
+                        * We'd better be noisy to be sure he knows what's
+                        * going on.
+                        */
+                       if (WARN_ON(pieces->dbg_trigger_tlv_len[i] <
+                                   (trigger_tlv_sz[i] +
+                                    sizeof(struct iwl_fw_dbg_trigger_tlv))))
+                               goto out_free_fw;
                        drv->fw.dbg_trigger_tlv_len[i] =
                                pieces->dbg_trigger_tlv_len[i];
                        drv->fw.dbg_trigger_tlv[i] =
index 67a3a241b331cd08180bbfe888d7707ad7dc149b..cda746b33db1f60e228cde9c90f5e040847cc0ae 100644 (file)
@@ -123,7 +123,7 @@ struct iwl_cfg;
  * starts the driver: fetches the firmware. This should be called by bus
  * specific system flows implementations. For example, the bus specific probe
  * function should do bus related operations only, and then call to this
- * function. It returns the driver object or %NULL if an error occured.
+ * function. It returns the driver object or %NULL if an error occurred.
  */
 struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
                              const struct iwl_cfg *cfg);
index 25d0105741dbee2b1a292d10c1b6cc56ce3f41d5..219ca8acca6281f02abb2c44abc066e730360848 100644 (file)
@@ -248,7 +248,7 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
        otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
        if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
                /* stop in this case */
-               /* set the uncorrectable OTP ECC bit for acknowledgement */
+               /* set the uncorrectable OTP ECC bit for acknowledgment */
                iwl_set_bit(trans, CSR_OTP_GP_REG,
                            CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
                IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n");
@@ -256,7 +256,7 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
        }
        if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
                /* continue in this case */
-               /* set the correctable OTP ECC bit for acknowledgement */
+               /* set the correctable OTP ECC bit for acknowledgment */
                iwl_set_bit(trans, CSR_OTP_GP_REG,
                            CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
                IWL_ERR(trans, "Correctable OTP ECC error, continue read\n");
index 1f7f15eb86da208df591ae8e7ca27e52c5921acf..d45dc021cda2c0715b8d7e740ff90b46589ae141 100644 (file)
@@ -445,7 +445,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
 #define RX_LOW_WATERMARK 8
 
 /**
- * struct iwl_rb_status - reseve buffer status
+ * struct iwl_rb_status - reserve buffer status
  *     host memory mapped FH registers
  * @closed_rb_num [0:11] - Indicates the index of the RB which was closed
  * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
index 37b38a585dd182f8fa1c44256f4a16ecc008d3df..251bf8dc4a12133b4ae77757170436c67219afc9 100644 (file)
@@ -183,7 +183,7 @@ struct iwl_fw_error_dump_info {
  * struct iwl_fw_error_dump_fw_mon - FW monitor data
  * @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer
  * @fw_mon_base_ptr: base pointer of the data
- * @fw_mon_cycle_cnt: number of wrap arounds
+ * @fw_mon_cycle_cnt: number of wraparounds
  * @reserved: for future use
  * @data: captured data
  */
@@ -246,10 +246,14 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
  * @FW_DBG_TRIGGER_CHANNEL_SWITCH: trigger log collection upon channel switch.
  * @FW_DBG_TRIGGER_FW_NOTIF: trigger log collection when the firmware sends a
  *     command response or a notification.
- * @FW_DB_TRIGGER_RESERVED: reserved
+ * @FW_DBG_TRIGGER_MLME: trigger log collection upon MLME event.
  * @FW_DBG_TRIGGER_STATS: trigger log collection upon statistics threshold.
  * @FW_DBG_TRIGGER_RSSI: trigger log collection when the rssi of the beacon
  *     goes below a threshold.
+ * @FW_DBG_TRIGGER_TXQ_TIMERS: configures the timers for the Tx queue hang
+ *     detection.
+ * @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
+ *     events.
  */
 enum iwl_fw_dbg_trigger {
        FW_DBG_TRIGGER_INVALID = 0,
@@ -258,9 +262,11 @@ enum iwl_fw_dbg_trigger {
        FW_DBG_TRIGGER_MISSED_BEACONS,
        FW_DBG_TRIGGER_CHANNEL_SWITCH,
        FW_DBG_TRIGGER_FW_NOTIF,
-       FW_DB_TRIGGER_RESERVED,
+       FW_DBG_TRIGGER_MLME,
        FW_DBG_TRIGGER_STATS,
        FW_DBG_TRIGGER_RSSI,
+       FW_DBG_TRIGGER_TXQ_TIMERS,
+       FW_DBG_TRIGGER_TIME_EVENT,
 
        /* must be last */
        FW_DBG_TRIGGER_MAX,
index 291a3382aa3fc5596e243ff3a4e93d7cd44557ba..bfdf3faa6c470dafbd9a66672b2f55e38b0872bc 100644 (file)
@@ -191,7 +191,7 @@ struct iwl_ucode_capa {
  * enum iwl_ucode_tlv_flag - ucode API flags
  * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
  *     was a separate TLV but moved here to save space.
- * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
+ * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behavior on hidden SSID,
  *     treats good CRC threshold as a boolean
  * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
  * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
@@ -290,6 +290,10 @@ enum iwl_ucode_tlv_api {
  * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command
  * @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics
  * @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running
+ * @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different
+ *     sources for the MCC. This TLV bit is a future replacement to
+ *     IWL_UCODE_TLV_API_WIFI_MCC_UPDATE. When either is set, multi-source LAR
+ *     is supported.
  * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
  */
 enum iwl_ucode_tlv_capa {
@@ -307,6 +311,7 @@ enum iwl_ucode_tlv_capa {
        IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT              = BIT(18),
        IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS           = BIT(22),
        IWL_UCODE_TLV_CAPA_BT_COEX_PLCR                 = BIT(28),
+       IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC                = BIT(29),
        IWL_UCODE_TLV_CAPA_BT_COEX_RRC                  = BIT(30),
 };
 
@@ -573,6 +578,84 @@ struct iwl_fw_dbg_trigger_low_rssi {
        __le32 rssi;
 } __packed;
 
+/**
+ * struct iwl_fw_dbg_trigger_mlme - configures trigger for mlme events
+ * @stop_auth_denied: number of denied authentication to collect
+ * @stop_auth_timeout: number of authentication timeout to collect
+ * @stop_rx_deauth: number of Rx deauth before to collect
+ * @stop_tx_deauth: number of Tx deauth before to collect
+ * @stop_assoc_denied: number of denied association to collect
+ * @stop_assoc_timeout: number of association timeout to collect
+ * @stop_connection_loss: number of connection loss to collect
+ * @start_auth_denied: number of denied authentication to start recording
+ * @start_auth_timeout: number of authentication timeout to start recording
+ * @start_rx_deauth: number of Rx deauth to start recording
+ * @start_tx_deauth: number of Tx deauth to start recording
+ * @start_assoc_denied: number of denied association to start recording
+ * @start_assoc_timeout: number of association timeout to start recording
+ * @start_connection_loss: number of connection loss to start recording
+ */
+struct iwl_fw_dbg_trigger_mlme {
+       u8 stop_auth_denied;
+       u8 stop_auth_timeout;
+       u8 stop_rx_deauth;
+       u8 stop_tx_deauth;
+
+       u8 stop_assoc_denied;
+       u8 stop_assoc_timeout;
+       u8 stop_connection_loss;
+       u8 reserved;
+
+       u8 start_auth_denied;
+       u8 start_auth_timeout;
+       u8 start_rx_deauth;
+       u8 start_tx_deauth;
+
+       u8 start_assoc_denied;
+       u8 start_assoc_timeout;
+       u8 start_connection_loss;
+       u8 reserved2;
+} __packed;
+
+/**
+ * struct iwl_fw_dbg_trigger_txq_timer - configures the Tx queue's timer
+ * @command_queue: timeout for the command queue in ms
+ * @bss: timeout for the queues of a BSS (except for TDLS queues) in ms
+ * @softap: timeout for the queues of a softAP in ms
+ * @p2p_go: timeout for the queues of a P2P GO in ms
+ * @p2p_client: timeout for the queues of a P2P client in ms
+ * @p2p_device: timeout for the queues of a P2P device in ms
+ * @ibss: timeout for the queues of an IBSS in ms
+ * @tdls: timeout for the queues of a TDLS station in ms
+ */
+struct iwl_fw_dbg_trigger_txq_timer {
+       __le32 command_queue;
+       __le32 bss;
+       __le32 softap;
+       __le32 p2p_go;
+       __le32 p2p_client;
+       __le32 p2p_device;
+       __le32 ibss;
+       __le32 tdls;
+       __le32 reserved[4];
+} __packed;
+
+/**
+ * struct iwl_fw_dbg_trigger_time_event - configures a time event trigger
+ * time_Events: a list of tuples <id, action_bitmap>. The driver will issue a
+ *     trigger each time a time event notification that relates to time event
+ *     id with one of the actions in the bitmap is received and
+ *     BIT(notif->status) is set in status_bitmap.
+ *
+ */
+struct iwl_fw_dbg_trigger_time_event {
+       struct {
+               __le32 id;
+               __le32 action_bitmap;
+               __le32 status_bitmap;
+       } __packed time_events[16];
+} __packed;
+
 /**
  * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
  * @id: conf id
index 78cac43e2bcd163997006065d112b1a61a6f6643..27c66e477833f7747d621fabe489b5d687a3120d 100644 (file)
@@ -186,21 +186,14 @@ IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
 
 void iwl_force_nmi(struct iwl_trans *trans)
 {
-       /*
-        * In HW previous to the 8000 HW family, and in the 8000 HW family
-        * itself when the revision step==0, the DEVICE_SET_NMI_REG is used
-        * to force an NMI. Otherwise, a different register -
-        * DEVICE_SET_NMI_8000B_REG - is used.
-        */
-       if ((trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) ||
-           (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP)) {
+       if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
                iwl_write_prph(trans, DEVICE_SET_NMI_REG,
                               DEVICE_SET_NMI_VAL_DRV);
                iwl_write_prph(trans, DEVICE_SET_NMI_REG,
                               DEVICE_SET_NMI_VAL_HW);
        } else {
-               iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG,
-                              DEVICE_SET_NMI_8000B_VAL);
+               iwl_write_prph(trans, DEVICE_SET_NMI_8000_REG,
+                              DEVICE_SET_NMI_8000_VAL);
                iwl_write_prph(trans, DEVICE_SET_NMI_REG,
                               DEVICE_SET_NMI_VAL_DRV);
        }
index 774637746427ccce154a236b186fa7c79ffdc514..83903a5025c2e69779554e7bcf980aff48b3d080 100644 (file)
@@ -99,14 +99,9 @@ enum family_8000_nvm_offsets {
        /* NVM SW-Section offset (in words) definitions */
        NVM_SW_SECTION_FAMILY_8000 = 0x1C0,
        NVM_VERSION_FAMILY_8000 = 0,
-       RADIO_CFG_FAMILY_8000 = 2,
-       SKU_FAMILY_8000 = 4,
-       N_HW_ADDRS_FAMILY_8000 = 5,
-
-       /* NVM PHY-SKU-Section offset (in words) for B0 */
-       RADIO_CFG_FAMILY_8000_B0 = 0,
-       SKU_FAMILY_8000_B0 = 2,
-       N_HW_ADDRS_FAMILY_8000_B0 = 3,
+       RADIO_CFG_FAMILY_8000 = 0,
+       SKU_FAMILY_8000 = 2,
+       N_HW_ADDRS_FAMILY_8000 = 3,
 
        /* NVM REGULATORY -Section offset (in words) definitions */
        NVM_CHANNELS_FAMILY_8000 = 0,
@@ -446,22 +441,16 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
                            n_used, n_channels);
 }
 
-static int iwl_get_sku(const struct iwl_cfg *cfg,
-                      const __le16 *nvm_sw, const __le16 *phy_sku,
-                      bool is_family_8000_a_step)
+static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
+                      const __le16 *phy_sku)
 {
        if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
                return le16_to_cpup(nvm_sw + SKU);
 
-       if (!is_family_8000_a_step)
-               return le32_to_cpup((__le32 *)(phy_sku +
-                                              SKU_FAMILY_8000_B0));
-       else
-               return le32_to_cpup((__le32 *)(nvm_sw + SKU_FAMILY_8000));
+       return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000));
 }
 
-static int iwl_get_nvm_version(const struct iwl_cfg *cfg,
-                              const __le16 *nvm_sw)
+static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
 {
        if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
                return le16_to_cpup(nvm_sw + NVM_VERSION);
@@ -470,35 +459,24 @@ static int iwl_get_nvm_version(const struct iwl_cfg *cfg,
                                               NVM_VERSION_FAMILY_8000));
 }
 
-static int iwl_get_radio_cfg(const struct iwl_cfg *cfg,
-                            const __le16 *nvm_sw, const __le16 *phy_sku,
-                            bool is_family_8000_a_step)
+static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
+                            const __le16 *phy_sku)
 {
        if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
                return le16_to_cpup(nvm_sw + RADIO_CFG);
 
-       if (!is_family_8000_a_step)
-               return le32_to_cpup((__le32 *)(phy_sku +
-                                              RADIO_CFG_FAMILY_8000_B0));
-       else
-               return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000));
+       return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000));
 
 }
 
-static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg,
-                             const __le16 *nvm_sw, bool is_family_8000_a_step)
+static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
 {
        int n_hw_addr;
 
        if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
                return le16_to_cpup(nvm_sw + N_HW_ADDRS);
 
-       if (!is_family_8000_a_step)
-               n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw +
-                                                   N_HW_ADDRS_FAMILY_8000_B0));
-       else
-               n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw +
-                                                   N_HW_ADDRS_FAMILY_8000));
+       n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000));
 
        return n_hw_addr & N_HW_ADDR_MASK;
 }
@@ -594,8 +572,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
                   const __le16 *nvm_hw, const __le16 *nvm_sw,
                   const __le16 *nvm_calib, const __le16 *regulatory,
                   const __le16 *mac_override, const __le16 *phy_sku,
-                  u8 tx_chains, u8 rx_chains,
-                  bool lar_fw_supported, bool is_family_8000_a_step,
+                  u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
                   u32 mac_addr0, u32 mac_addr1)
 {
        struct iwl_nvm_data *data;
@@ -618,15 +595,14 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
 
        data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw);
 
-       radio_cfg =
-               iwl_get_radio_cfg(cfg, nvm_sw, phy_sku, is_family_8000_a_step);
+       radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw, phy_sku);
        iwl_set_radio_cfg(cfg, data, radio_cfg);
        if (data->valid_tx_ant)
                tx_chains &= data->valid_tx_ant;
        if (data->valid_rx_ant)
                rx_chains &= data->valid_rx_ant;
 
-       sku = iwl_get_sku(cfg, nvm_sw, phy_sku, is_family_8000_a_step);
+       sku = iwl_get_sku(cfg, nvm_sw, phy_sku);
        data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
        data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
        data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
@@ -635,8 +611,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
        data->sku_cap_11ac_enable = data->sku_cap_11n_enable &&
                                    (sku & NVM_SKU_CAP_11AC_ENABLE);
 
-       data->n_hw_addrs =
-               iwl_get_n_hw_addrs(cfg, nvm_sw, is_family_8000_a_step);
+       data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
 
        if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
                /* Checking for required sections */
index c995d2cee3f691c6dbe2c3592856d155d4e98f90..822ba52e0e5af537e42262ee4106af53d0b37f04 100644 (file)
@@ -78,8 +78,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
                   const __le16 *nvm_hw, const __le16 *nvm_sw,
                   const __le16 *nvm_calib, const __le16 *regulatory,
                   const __le16 *mac_override, const __le16 *phy_sku,
-                  u8 tx_chains, u8 rx_chains,
-                  bool lar_fw_supported, bool is_family_8000_a_step,
+                  u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
                   u32 mac_addr0, u32 mac_addr1);
 
 /**
index 17de6d46222ae7c803605017c066453d73076f01..ce1cdd7604e8a156cf7356466b9232bdc176d9db 100644 (file)
@@ -94,7 +94,7 @@ struct iwl_cfg;
  * The operational mode has a very simple life cycle.
  *
  *     1) The driver layer (iwl-drv.c) chooses the op_mode based on the
- *        capabilities advertized by the fw file (in TLV format).
+ *        capabilities advertised by the fw file (in TLV format).
  *     2) The driver layer starts the op_mode (ops->start)
  *     3) The op_mode registers mac80211
  *     4) The op_mode is governed by mac80211
@@ -116,7 +116,7 @@ struct iwl_cfg;
  *     May sleep
  * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
  *     HCMD this Rx responds to. Can't sleep.
- * @napi_add: NAPI initialisation. The transport is fully responsible for NAPI,
+ * @napi_add: NAPI initialization. The transport is fully responsible for NAPI,
  *     but the higher layers need to know about it (in particular mac80211 to
  *     to able to call the right NAPI RX functions); this function is needed
  *     to eventually call netif_napi_add() with higher layer involvement.
index e893c6eb260cd4866b7c7d03c1437b9d479ad9de..a105455b6a2469c2afb07e1b04e4949d8e1184f9 100644 (file)
@@ -125,7 +125,7 @@ struct iwl_phy_db_chg_txp {
 } __packed;
 
 /*
- * phy db - Receieve phy db chunk after calibrations
+ * phy db - Receive phy db chunk after calibrations
  */
 struct iwl_calib_res_notif_phy_db {
        __le16 type;
index bc962888c5836435450882a0d535c8d9534d14e7..88a57e6e232ff318dea917d0856da781662bc5eb 100644 (file)
 #define DEVICE_SET_NMI_REG 0x00a01c30
 #define DEVICE_SET_NMI_VAL_HW BIT(0)
 #define DEVICE_SET_NMI_VAL_DRV BIT(7)
-#define DEVICE_SET_NMI_8000B_REG 0x00a01c24
-#define DEVICE_SET_NMI_8000B_VAL 0x1000000
+#define DEVICE_SET_NMI_8000_REG 0x00a01c24
+#define DEVICE_SET_NMI_8000_VAL 0x1000000
 
 /* Shared registers (0x0..0x3ff, via target indirect or periphery */
 #define SHR_BASE       0x00a10000
 #define OSC_CLK                                (0xa04068)
 #define OSC_CLK_FORCE_CONTROL          (0x8)
 
-/* SECURE boot registers */
-#define LMPM_SECURE_BOOT_CONFIG_ADDR   (0x100)
-enum secure_boot_config_reg {
-       LMPM_SECURE_BOOT_CONFIG_INSPECTOR_BURNED_IN_OTP = 0x00000001,
-       LMPM_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ       = 0x00000002,
-};
-
-#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0   (0xA01E30)
-#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR      (0x1E30)
-#define LMPM_SECURE_BOOT_CPU2_STATUS_ADDR      (0x1E34)
-enum secure_boot_status_reg {
-       LMPM_SECURE_BOOT_CPU_STATUS_VERF_STATUS         = 0x00000001,
-       LMPM_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED      = 0x00000002,
-       LMPM_SECURE_BOOT_CPU_STATUS_VERF_SUCCESS        = 0x00000004,
-       LMPM_SECURE_BOOT_CPU_STATUS_VERF_FAIL           = 0x00000008,
-       LMPM_SECURE_BOOT_CPU_STATUS_SIGN_VERF_FAIL      = 0x00000010,
-       LMPM_SECURE_BOOT_STATUS_SUCCESS                 = 0x00000003,
-};
-
 #define FH_UCODE_LOAD_STATUS           (0x1AF0)
 #define CSR_UCODE_LOAD_STATUS_ADDR     (0x1E70)
 enum secure_load_status_reg {
@@ -334,8 +315,6 @@ enum secure_load_status_reg {
 #define LMPM_SECURE_CPU1_HDR_MEM_SPACE         (0x420000)
 #define LMPM_SECURE_CPU2_HDR_MEM_SPACE         (0x420400)
 
-#define LMPM_SECURE_TIME_OUT   (100) /* 10 micro */
-
 /* Rx FIFO */
 #define RXF_SIZE_ADDR                  (0xa00c88)
 #define RXF_RD_D_SPACE                 (0xa00c40)
index 11ac5c58527f6f92b5980b15f43defa9ad5822c9..6dfed1259260f06d23feb544d78ce6484c01fb36 100644 (file)
 /**
  * DOC: Transport layer - what is it ?
  *
- * The tranport layer is the layer that deals with the HW directly. It provides
+ * The transport layer is the layer that deals with the HW directly. It provides
  * an abstraction of the underlying HW to the upper layer. The transport layer
  * doesn't provide any policy, algorithm or anything of this kind, but only
- * mechanisms to make the HW do something.It is not completely stateless but
+ * mechanisms to make the HW do something. It is not completely stateless but
  * close to it.
  * We will have an implementation for each different supported bus.
  */
 /**
  * DOC: Host command section
  *
- * A host command is a commaned issued by the upper layer to the fw. There are
+ * A host command is a command issued by the upper layer to the fw. There are
  * several versions of fw that have several APIs. The transport layer is
  * completely agnostic to these differences.
- * The transport does provide helper functionnality (i.e. SYNC / ASYNC mode),
+ * The transport does provide helper functionality (i.e. SYNC / ASYNC mode),
  */
 #define SEQ_TO_QUEUE(s)        (((s) >> 8) & 0x1f)
 #define QUEUE_TO_SEQ(q)        (((q) & 0x1f) << 8)
@@ -195,7 +195,7 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
  * @CMD_WANT_SKB: Not valid with CMD_ASYNC. The caller needs the buffer of
  *     the response. The caller needs to call iwl_free_resp when done.
  * @CMD_HIGH_PRIO: The command is high priority - it goes to the front of the
- *     command queue, but after other high priority commands. valid only
+ *     command queue, but after other high priority commands. Valid only
  *     with CMD_ASYNC.
  * @CMD_SEND_IN_IDLE: The command should be sent even when the trans is idle.
  * @CMD_MAKE_TRANS_IDLE: The command response should mark the trans as idle.
@@ -582,7 +582,7 @@ enum iwl_d0i3_mode {
  * @cfg - pointer to the configuration
  * @status: a bit-mask of transport status flags
  * @dev - pointer to struct device * that represents the device
- * @hw_id: a u32 with the ID of the device / subdevice.
+ * @hw_id: a u32 with the ID of the device / sub-device.
  *     Set during transport allocation.
  * @hw_id_str: a string with info about HW ID. Set during transport allocation.
  * @pm_support: set to true in start_hw if link pm is supported
index 5f8afa5f11a35f8da4761fb638d76f34f4f0a9eb..a6c48c7b1e1683fdbdcb99fd0e4f971cf6ad66d2 100644 (file)
@@ -1131,6 +1131,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
        iwl_trans_d3_suspend(mvm->trans, test);
  out:
        if (ret < 0) {
+               iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
                ieee80211_restart_hw(mvm->hw);
                iwl_mvm_free_nd(mvm);
        }
@@ -1725,6 +1726,10 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
        results->matched_profiles = le32_to_cpu(query->matched_profiles);
        memcpy(results->matches, query->matches, sizeof(results->matches));
 
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
+       mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done);
+#endif
+
 out_free_resp:
        iwl_free_resp(&cmd);
        return ret;
@@ -2016,6 +2021,7 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
        __iwl_mvm_resume(mvm, true);
        rtnl_unlock();
        iwl_abort_notification_waits(&mvm->notif_wait);
+       iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
        ieee80211_restart_hw(mvm->hw);
 
        /* wait for restart and disconnect all interfaces */
index 8c5229892e573aa58234e4e64893ddee0c89253e..9ac04c1ea7063d985980a5237fe705c1bba7186c 100644 (file)
@@ -1473,26 +1473,6 @@ out:
        return count;
 }
 
-static ssize_t iwl_dbgfs_enable_scan_iteration_notif_write(struct iwl_mvm *mvm,
-                                                          char *buf,
-                                                          size_t count,
-                                                          loff_t *ppos)
-{
-       int val;
-
-       mutex_lock(&mvm->mutex);
-
-       if (kstrtoint(buf, 10, &val)) {
-               mutex_unlock(&mvm->mutex);
-               return -EINVAL;
-       }
-
-       mvm->scan_iter_notif_enabled = val;
-       mutex_unlock(&mvm->mutex);
-
-       return count;
-}
-
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
 
 /* Device wide debugfs entries */
@@ -1515,7 +1495,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
 MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 8);
-MVM_DEBUGFS_WRITE_FILE_OPS(enable_scan_iteration_notif, 8);
 
 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
@@ -1559,8 +1538,11 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
        MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
        MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
        MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR);
-       MVM_DEBUGFS_ADD_FILE(enable_scan_iteration_notif, mvm->debugfs_dir,
-                            S_IWUSR);
+       if (!debugfs_create_bool("enable_scan_iteration_notif",
+                                S_IRUSR | S_IWUSR,
+                                mvm->debugfs_dir,
+                                &mvm->scan_iter_notif_enabled))
+               goto err;
 
 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
        if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
@@ -1587,6 +1569,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
        if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
                                 mvm->debugfs_dir, &mvm->d3_wake_sysassert))
                goto err;
+       if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR,
+                               mvm->debugfs_dir, &mvm->last_netdetect_scans))
+               goto err;
        MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
 #endif
 
index 6d3bea5c59d1eb8ab42bca2f0c1a4523a23b8291..d7658d16e965c835144d8804d4e7185d605e8bfd 100644 (file)
@@ -132,7 +132,7 @@ struct iwl_proto_offload_cmd_common {
  * @solicited_node_ipv6_addr: broken -- solicited node address exists
  *     for each target address
  * @target_ipv6_addr: our target addresses
- * @ndp_mac_addr: neighbor soliciation response MAC address
+ * @ndp_mac_addr: neighbor solicitation response MAC address
  */
 struct iwl_proto_offload_cmd_v1 {
        struct iwl_proto_offload_cmd_common common;
@@ -150,7 +150,7 @@ struct iwl_proto_offload_cmd_v1 {
  * @solicited_node_ipv6_addr: broken -- solicited node address exists
  *     for each target address
  * @target_ipv6_addr: our target addresses
- * @ndp_mac_addr: neighbor soliciation response MAC address
+ * @ndp_mac_addr: neighbor solicitation response MAC address
  */
 struct iwl_proto_offload_cmd_v2 {
        struct iwl_proto_offload_cmd_common common;
index aabaedd3b3ee1c6e3deeadc1ec7a9a9fe6059b83..f3f3ee0a766bd21645e26fe4c671caa8e15e71c0 100644 (file)
@@ -255,7 +255,7 @@ struct iwl_mac_data_p2p_dev {
 /**
  * enum iwl_mac_filter_flags - MAC context filter flags
  * @MAC_FILTER_IN_PROMISC: accept all data frames
- * @MAC_FILTER_IN_CONTROL_AND_MGMT: pass all mangement and
+ * @MAC_FILTER_IN_CONTROL_AND_MGMT: pass all management and
  *     control frames to the host
  * @MAC_FILTER_ACCEPT_GRP: accept multicast frames
  * @MAC_FILTER_DIS_DECRYPT: don't decrypt unicast frames
index a5fbbd637070795b97fafde922aabb50d7bcaf4c..4f81dcf57a736e7409087f4b3193809c3570db6f 100644 (file)
@@ -103,7 +103,7 @@ struct iwl_ssid_ie {
  * @SCAN_COMP_STATUS_ERR_COEX: medium was lost ot WiMax
  * @SCAN_COMP_STATUS_P2P_ACTION_OK: P2P public action frame TX was successful
  *     (not an error!)
- * @SCAN_COMP_STATUS_ITERATION_END: indicates end of one repeatition the driver
+ * @SCAN_COMP_STATUS_ITERATION_END: indicates end of one repetition the driver
  *     asked for
  * @SCAN_COMP_STATUS_ERR_ALLOC_TE: scan could not allocate time events
 */
@@ -187,11 +187,11 @@ enum scan_framework_client {
  * struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6
  * @scan_flags:                see enum iwl_scan_flags
  * @channel_count:     channels in channel list
- * @quiet_time:                dwell time, in milisiconds, on quiet channel
+ * @quiet_time:                dwell time, in milliseconds, on quiet channel
  * @quiet_plcp_th:     quiet channel num of packets threshold
  * @good_CRC_th:       passive to active promotion threshold
  * @rx_chain:          RXON rx chain.
- * @max_out_time:      max TUs to be out of assoceated channel
+ * @max_out_time:      max TUs to be out of associated channel
  * @suspend_time:      pause scan this TUs when returning to service channel
  * @flags:             RXON flags
  * @filter_flags:      RXONfilter
@@ -232,7 +232,7 @@ enum iwl_scan_offload_channel_flags {
  *     see enum iwl_scan_offload_channel_flags.
  * __le16 channel_number: channel number 1-13 etc.
  * __le16 iter_count: repetition count for the channel.
- * __le32 iter_interval: interval between two innteration on one channel.
+ * __le32 iter_interval: interval between two iterations on one channel.
  * u8 active_dwell.
  * u8 passive_dwell.
  */
@@ -275,8 +275,8 @@ enum iwl_scan_offload_band_selection {
 /**
  * iwl_scan_offload_profile - SCAN_OFFLOAD_PROFILE_S
  * @ssid_index:                index to ssid list in fixed part
- * @unicast_cipher:    encryption olgorithm to match - bitmap
- * @aut_alg:           authentication olgorithm to match - bitmap
+ * @unicast_cipher:    encryption algorithm to match - bitmap
+ * @aut_alg:           authentication algorithm to match - bitmap
  * @network_type:      enum iwl_scan_offload_network_type
  * @band_selection:    enum iwl_scan_offload_band_selection
  * @client_bitmap:     clients waiting for match - enum scan_framework_client
@@ -748,7 +748,7 @@ enum iwl_umac_scan_general_flags {
  * @flags:             bitmap - 0-19:  directed scan to i'th ssid.
  * @channel_num:       channel number 1-13 etc.
  * @iter_count:                repetition count for the channel.
- * @iter_interval:     interval between two scan interations on one channel.
+ * @iter_interval:     interval between two scan iterations on one channel.
  */
 struct iwl_scan_channel_cfg_umac {
        __le32 flags;
index 6cf7d9837ca54e938500302cd013a8a4a396be5d..bc5eac4960e18a79a211da2a2bf6492b1a39e570 100644 (file)
@@ -526,16 +526,33 @@ int iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm, enum iwl_fw_dbg_trigger trig,
 
 int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
                                struct iwl_fw_dbg_trigger_tlv *trigger,
-                               const char *str, size_t len)
+                               const char *fmt, ...)
 {
        unsigned int delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay));
        u16 occurrences = le16_to_cpu(trigger->occurrences);
-       int ret;
+       int ret, len = 0;
+       char buf[64];
 
        if (!occurrences)
                return 0;
 
-       ret = iwl_mvm_fw_dbg_collect(mvm, le32_to_cpu(trigger->id), str,
+       if (fmt) {
+               va_list ap;
+
+               buf[sizeof(buf) - 1] = '\0';
+
+               va_start(ap, fmt);
+               vsnprintf(buf, sizeof(buf), fmt, ap);
+               va_end(ap);
+
+               /* check for truncation */
+               if (WARN_ON_ONCE(buf[sizeof(buf) - 1]))
+                       buf[sizeof(buf) - 1] = '\0';
+
+               len = strlen(buf) + 1;
+       }
+
+       ret = iwl_mvm_fw_dbg_collect(mvm, le32_to_cpu(trigger->id), buf,
                                     len, delay);
        if (ret)
                return ret;
index 581b3b8f29f9b6d7460b98eeb9ee54e3b9612c35..8088c7137f7c9462417ffdfc07a30dcc37be6ec2 100644 (file)
@@ -470,9 +470,8 @@ exit_fail:
 
 int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
-       unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
-                                       mvm->cfg->base_params->wd_timeout :
-                                       IWL_WATCHDOG_DISABLED;
+       unsigned int wdg_timeout =
+               iwl_mvm_get_wd_timeout(mvm, vif, false, false);
        u32 ac;
        int ret;
 
@@ -1413,7 +1412,7 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
 
        if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx ||
            rx_missed_bcon >= stop_trig_missed_bcon)
-               iwl_mvm_fw_dbg_collect_trig(mvm, trigger, NULL, 0);
+               iwl_mvm_fw_dbg_collect_trig(mvm, trigger, NULL);
 }
 
 int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
index 302c8cc50f25a695c40ce59555f8a05bf58cae2d..84555170b6f751bb4f0925bf5c85319de76293b6 100644 (file)
@@ -379,11 +379,13 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
 {
        enum iwl_mcc_source used_src;
        struct ieee80211_regdomain *regd;
+       int ret;
+       bool changed;
        const struct ieee80211_regdomain *r =
                        rtnl_dereference(mvm->hw->wiphy->regd);
 
        if (!r)
-               return 0;
+               return -ENOENT;
 
        /* save the last source in case we overwrite it below */
        used_src = mvm->mcc_src;
@@ -395,14 +397,19 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
        }
 
        /* Now set our last stored MCC and source */
-       regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, r->alpha2, used_src, NULL);
+       regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, r->alpha2, used_src,
+                                    &changed);
        if (IS_ERR_OR_NULL(regd))
                return -EIO;
 
-       regulatory_set_wiphy_regd(mvm->hw->wiphy, regd);
-       kfree(regd);
+       /* update cfg80211 if the regdomain was changed */
+       if (changed)
+               ret = regulatory_set_wiphy_regd_sync_rtnl(mvm->hw->wiphy, regd);
+       else
+               ret = 0;
 
-       return 0;
+       kfree(regd);
+       return ret;
 }
 
 int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
@@ -1007,6 +1014,9 @@ void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm)
        mvm->fw_dump_desc = NULL;
 }
 
+#define IWL8260_ICCM_OFFSET            0x44000 /* Only for B-step */
+#define IWL8260_ICCM_LEN               0xC000 /* Only for B-step */
+
 void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 {
        struct iwl_fw_error_dump_file *dump_file;
@@ -1022,16 +1032,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 
        lockdep_assert_held(&mvm->mutex);
 
-       /* W/A for 8000 HW family A-step */
-       if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
-           CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP) {
-               if (smem_len)
-                       smem_len = 0x38000;
-
-               if (sram2_len)
-                       sram2_len = 0x10000;
-       }
-
        fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
        if (!fw_error_dump)
                return;
@@ -1083,6 +1083,14 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
                   fifo_data_len +
                   sizeof(*dump_info);
 
+       /*
+        * In 8000 HW family B-step include the ICCM (which resides separately)
+        */
+       if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
+           CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP)
+               file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
+                           IWL8260_ICCM_LEN;
+
        if (mvm->fw_dump_desc)
                file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
                            mvm->fw_dump_desc->len;
@@ -1170,6 +1178,19 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
                                         dump_mem->data, sram2_len);
        }
 
+       if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
+           CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP) {
+               dump_data = iwl_fw_error_next_data(dump_data);
+               dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
+               dump_data->len = cpu_to_le32(IWL8260_ICCM_LEN +
+                                            sizeof(*dump_mem));
+               dump_mem = (void *)dump_data->data;
+               dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
+               dump_mem->offset = cpu_to_le32(IWL8260_ICCM_OFFSET);
+               iwl_trans_read_mem_bytes(mvm->trans, IWL8260_ICCM_OFFSET,
+                                        dump_mem->data, IWL8260_ICCM_LEN);
+       }
+
        fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans);
        fw_error_dump->op_mode_len = file_len;
        if (fw_error_dump->trans_ptr)
@@ -1399,6 +1420,20 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
         */
        clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
 
+       /* We shouldn't have any UIDs still set.  Loop over all the UIDs to
+        * make sure there's nothing left there and warn if any is found.
+        */
+       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
+               int i;
+
+               for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++) {
+                       if (WARN_ONCE(mvm->scan_uid[i],
+                                     "UMAC scan UID %d was not cleaned\n",
+                                     mvm->scan_uid[i]))
+                               mvm->scan_uid[i] = 0;
+               }
+       }
+
        mvm->ucode_loaded = false;
 }
 
@@ -1595,9 +1630,33 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
        u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
 
        if (tfd_msk) {
+               /*
+                * mac80211 first removes all the stations of the vif and
+                * then removes the vif. When it removes a station it also
+                * flushes the AMPDU session. So by now, all the AMPDU sessions
+                * of all the stations of this vif are closed, and the queues
+                * of these AMPDU sessions are properly closed.
+                * We still need to take care of the shared queues of the vif.
+                * Flush them here.
+                */
                mutex_lock(&mvm->mutex);
                iwl_mvm_flush_tx_path(mvm, tfd_msk, true);
                mutex_unlock(&mvm->mutex);
+
+               /*
+                * There are transports that buffer a few frames in the host.
+                * For these, the flush above isn't enough since while we were
+                * flushing, the transport might have sent more frames to the
+                * device. To solve this, wait here until the transport is
+                * empty. Technically, this could have replaced the flush
+                * above, but flush is much faster than draining. So flush
+                * first, and drain to make sure we have no frames in the
+                * transport anymore.
+                * If a station still had frames on the shared queues, it is
+                * already marked as draining, so to complete the draining, we
+                * just need to wait until the transport is empty.
+                */
+               iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_msk);
        }
 
        if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
@@ -2167,8 +2226,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
        if (iwl_mvm_phy_ctx_count(mvm) > 1)
                iwl_mvm_teardown_tdls_peers(mvm);
 
-       mutex_unlock(&mvm->mutex);
-       return 0;
+       goto out_unlock;
 
 out_quota_failed:
        iwl_mvm_power_update_mac(mvm);
@@ -3022,6 +3080,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
        IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
                           duration, type);
 
+       flush_work(&mvm->roc_done_wk);
+
        mutex_lock(&mvm->mutex);
 
        switch (vif->type) {
@@ -3646,11 +3706,12 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
 
        mutex_lock(&mvm->mutex);
 
+       mvmvif->csa_failed = false;
+
        IWL_DEBUG_MAC80211(mvm, "pre CSA to freq %d\n",
                           chsw->chandef.center_freq1);
 
-       iwl_fw_dbg_trigger_simple_stop(mvm, vif, FW_DBG_TRIGGER_CHANNEL_SWITCH,
-                                      NULL, 0);
+       iwl_fw_dbg_trigger_simple_stop(mvm, vif, FW_DBG_TRIGGER_CHANNEL_SWITCH);
 
        switch (vif->type) {
        case NL80211_IFTYPE_AP:
@@ -3721,6 +3782,12 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
 
        mutex_lock(&mvm->mutex);
 
+       if (mvmvif->csa_failed) {
+               mvmvif->csa_failed = false;
+               ret = -EIO;
+               goto out_unlock;
+       }
+
        if (vif->type == NL80211_IFTYPE_STATION) {
                struct iwl_mvm_sta *mvmsta;
 
@@ -3844,6 +3911,7 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
                            mvm->radio_stats.on_time_scan;
        do_div(survey->time_scan, USEC_PER_MSEC);
 
+       ret = 0;
  out:
        mutex_unlock(&mvm->mutex);
        return ret;
@@ -3889,6 +3957,64 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
        mutex_unlock(&mvm->mutex);
 }
 
+static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      const struct ieee80211_event *event)
+{
+#define CHECK_MLME_TRIGGER(_mvm, _trig, _buf, _cnt, _fmt...)   \
+       do {                                                    \
+               if ((_cnt) && --(_cnt))                         \
+                       break;                                  \
+               iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt);\
+       } while (0)
+
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_mlme *trig_mlme;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME))
+               return;
+
+       if (event->u.mlme.status == MLME_SUCCESS)
+               return;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);
+       trig_mlme = (void *)trig->data;
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
+               return;
+
+       if (event->u.mlme.data == ASSOC_EVENT) {
+               if (event->u.mlme.status == MLME_DENIED)
+                       CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                          trig_mlme->stop_assoc_denied,
+                                          "DENIED ASSOC: reason %d",
+                                           event->u.mlme.reason);
+               else if (event->u.mlme.status == MLME_TIMEOUT)
+                       CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                          trig_mlme->stop_assoc_timeout,
+                                          "ASSOC TIMEOUT");
+       } else if (event->u.mlme.data == AUTH_EVENT) {
+               if (event->u.mlme.status == MLME_DENIED)
+                       CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                          trig_mlme->stop_auth_denied,
+                                          "DENIED AUTH: reason %d",
+                                          event->u.mlme.reason);
+               else if (event->u.mlme.status == MLME_TIMEOUT)
+                       CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                          trig_mlme->stop_auth_timeout,
+                                          "AUTH TIMEOUT");
+       } else if (event->u.mlme.data == DEAUTH_RX_EVENT) {
+               CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                  trig_mlme->stop_rx_deauth,
+                                  "DEAUTH RX %d", event->u.mlme.reason);
+       } else if (event->u.mlme.data == DEAUTH_TX_EVENT) {
+               CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                  trig_mlme->stop_tx_deauth,
+                                  "DEAUTH TX %d", event->u.mlme.reason);
+       }
+#undef CHECK_MLME_TRIGGER
+}
+
 const struct ieee80211_ops iwl_mvm_hw_ops = {
        .tx = iwl_mvm_mac_tx,
        .ampdu_action = iwl_mvm_mac_ampdu_action,
@@ -3942,6 +4068,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
        .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
        .tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
 
+       .event_callback = iwl_mvm_mac_event_callback,
+
        CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
 
 #ifdef CONFIG_PM_SLEEP
index 4b5c8f66df8baa865c7f6d0f8f3f885c9193ceef..d5522a16124292cd6cab36159851a8446b5e2d95 100644 (file)
@@ -349,11 +349,12 @@ struct iwl_mvm_vif_bf_data {
  * @bcast_sta: station used for broadcast packets. Used by the following
  *  vifs: P2P_DEVICE, GO and AP.
  * @beacon_skb: the skb used to hold the AP/GO beacon template
- * @smps_requests: the SMPS requests of differents parts of the driver,
+ * @smps_requests: the SMPS requests of different parts of the driver,
  *     combined on update to yield the overall request to mac80211.
  * @beacon_stats: beacon statistics, containing the # of received beacons,
  *     # of received beacons accumulated over FW restart, and the current
  *     average signal of beacons retrieved from the firmware
+ * @csa_failed: CSA failed to schedule time event, report an error later
  */
 struct iwl_mvm_vif {
        struct iwl_mvm *mvm;
@@ -433,6 +434,7 @@ struct iwl_mvm_vif {
 
        /* Indicates that CSA countdown may be started */
        bool csa_countdown;
+       bool csa_failed;
 };
 
 static inline struct iwl_mvm_vif *
@@ -686,7 +688,7 @@ struct iwl_mvm {
        bool disable_power_off;
        bool disable_power_off_d3;
 
-       bool scan_iter_notif_enabled;
+       u32 scan_iter_notif_enabled; /* must be u32 for debugfs_create_bool */
 
        struct debugfs_blob_wrapper nvm_hw_blob;
        struct debugfs_blob_wrapper nvm_sw_blob;
@@ -746,6 +748,7 @@ struct iwl_mvm {
        void *d3_resume_sram;
        u32 d3_test_pme_ptr;
        struct ieee80211_vif *keep_vif;
+       u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */
 #endif
 #endif
 
@@ -934,7 +937,8 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
 
 static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm)
 {
-       return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WIFI_MCC_UPDATE;
+       return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WIFI_MCC_UPDATE ||
+              mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC;
 }
 
 static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm)
@@ -1146,6 +1150,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, bool force_upload,
 int iwl_mvm_scan_size(struct iwl_mvm *mvm);
 int iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
 int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm, bool is_sched_scan);
+void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm);
 
 /* Scheduled scan */
 int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
@@ -1475,8 +1480,12 @@ int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
 void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm);
 int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
                                struct iwl_fw_dbg_trigger_tlv *trigger,
-                               const char *str, size_t len);
-
+                               const char *fmt, ...) __printf(3, 4);
+unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
+                                   struct ieee80211_vif *vif,
+                                   bool tdls, bool cmd_q);
+void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                            const char *errmsg);
 static inline bool
 iwl_fw_dbg_trigger_vif_match(struct iwl_fw_dbg_trigger_tlv *trig,
                             struct ieee80211_vif *vif)
@@ -1509,8 +1518,7 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_mvm *mvm,
 static inline void
 iwl_fw_dbg_trigger_simple_stop(struct iwl_mvm *mvm,
                               struct ieee80211_vif *vif,
-                              enum iwl_fw_dbg_trigger trig,
-                              const char *str, size_t len)
+                              enum iwl_fw_dbg_trigger trig)
 {
        struct iwl_fw_dbg_trigger_tlv *trigger;
 
@@ -1521,7 +1529,7 @@ iwl_fw_dbg_trigger_simple_stop(struct iwl_mvm *mvm,
        if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trigger))
                return;
 
-       iwl_mvm_fw_dbg_collect_trig(mvm, trigger, str, len);
+       iwl_mvm_fw_dbg_collect_trig(mvm, trigger, NULL);
 }
 
 #endif /* __IWL_MVM_H__ */
index 123e0a16aea88d185656b160c241763fd8b91d1b..87b2a30a2308439c4e7a3f3bd80e419f9583af5a 100644 (file)
@@ -77,8 +77,7 @@
 /* Default NVM size to read */
 #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
 #define IWL_MAX_NVM_SECTION_SIZE       0x1b58
-#define IWL_MAX_NVM_8000A_SECTION_SIZE 0xffc
-#define IWL_MAX_NVM_8000B_SECTION_SIZE 0x1ffc
+#define IWL_MAX_NVM_8000_SECTION_SIZE  0x1ffc
 
 #define NVM_WRITE_OPCODE 1
 #define NVM_READ_OPCODE 0
@@ -267,7 +266,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
 {
        struct iwl_nvm_section *sections = mvm->nvm_sections;
        const __le16 *hw, *sw, *calib, *regulatory, *mac_override, *phy_sku;
-       bool is_family_8000_a_step = false, lar_enabled;
+       bool lar_enabled;
        u32 mac_addr0, mac_addr1;
 
        /* Checking for required sections */
@@ -293,12 +292,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
                        return NULL;
                }
 
-               if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP)
-                       is_family_8000_a_step = true;
-
                /* PHY_SKU section is mandatory in B0 */
-               if (!is_family_8000_a_step &&
-                   !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
+               if (!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
                        IWL_ERR(mvm,
                                "Can't parse phy_sku in B0, empty sections\n");
                        return NULL;
@@ -327,8 +322,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
        return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
                                  regulatory, mac_override, phy_sku,
                                  mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant,
-                                 lar_enabled, is_family_8000_a_step,
-                                 mac_addr0, mac_addr1);
+                                 lar_enabled, mac_addr0, mac_addr1);
 }
 
 #define MAX_NVM_FILE_LEN       16384
@@ -381,10 +375,8 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
        /* Maximal size depends on HW family and step */
        if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
                max_section_size = IWL_MAX_NVM_SECTION_SIZE;
-       else if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP)
-               max_section_size = IWL_MAX_NVM_8000A_SECTION_SIZE;
-       else /* Family 8000 B-step or C-step */
-               max_section_size = IWL_MAX_NVM_8000B_SECTION_SIZE;
+       else
+               max_section_size = IWL_MAX_NVM_8000_SECTION_SIZE;
 
        /*
         * Obtain NVM image via request_firmware. Since we already used
@@ -426,6 +418,15 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
                IWL_INFO(mvm, "NVM Version %08X\n", le32_to_cpu(dword_buff[2]));
                IWL_INFO(mvm, "NVM Manufacturing date %08X\n",
                         le32_to_cpu(dword_buff[3]));
+
+               /* nvm file validation, dword_buff[2] holds the file version */
+               if ((CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_C_STEP &&
+                    le32_to_cpu(dword_buff[2]) < 0xE4A) ||
+                   (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP &&
+                    le32_to_cpu(dword_buff[2]) >= 0xE4A)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
        } else {
                file_sec = (void *)fw_entry->data;
        }
@@ -524,6 +525,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
        int ret, section;
        u32 size_read = 0;
        u8 *nvm_buffer, *temp;
+       const char *nvm_file_B = mvm->cfg->default_nvm_file_B_step;
+       const char *nvm_file_C = mvm->cfg->default_nvm_file_C_step;
 
        if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
                return -EINVAL;
@@ -582,10 +585,27 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
 
        /* load external NVM if configured */
        if (mvm->nvm_file_name) {
-               /* move to External NVM flow */
+               /* read External NVM file - take the default */
                ret = iwl_mvm_read_external_nvm(mvm);
-               if (ret)
-                       return ret;
+               if (ret) {
+                       /* choose the nvm_file name according to the
+                        * HW step
+                        */
+                       if (CSR_HW_REV_STEP(mvm->trans->hw_rev) ==
+                           SILICON_B_STEP)
+                               mvm->nvm_file_name = nvm_file_B;
+                       else
+                               mvm->nvm_file_name = nvm_file_C;
+
+                       if (ret == -EFAULT && mvm->nvm_file_name) {
+                               /* in case nvm file was failed try again */
+                               ret = iwl_mvm_read_external_nvm(mvm);
+                               if (ret)
+                                       return ret;
+                       } else {
+                               return ret;
+                       }
+               }
        }
 
        /* parse the relevant nvm sections */
@@ -786,13 +806,12 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
                return 0;
 
        /*
-        * During HW restart, only replay the last set MCC to FW. Otherwise,
+        * try to replay the last set MCC to FW. If it doesn't exist,
         * queue an update to cfg80211 to retrieve the default alpha2 from FW.
         */
-       if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
-               /* This should only be called during vif up and hold RTNL */
-               return iwl_mvm_init_fw_regd(mvm);
-       }
+       retval = iwl_mvm_init_fw_regd(mvm);
+       if (retval != -ENOENT)
+               return retval;
 
        /*
         * Driver regulatory hint for initial update, this also informs the
index 80121e41ca22f3aca2a09c59ba30016e9872caae..a08b03d58d4bf0f3ebd4773a7fdb6e07cc8406b8 100644 (file)
@@ -488,8 +488,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
        /* Set a short watchdog for the command queue */
        trans_cfg.cmd_q_wdg_timeout =
-               iwlmvm_mod_params.tfd_q_hang_detect ? IWL_DEF_WD_TIMEOUT :
-                                                     IWL_WATCHDOG_DISABLED;
+               iwl_mvm_get_wd_timeout(mvm, NULL, false, true);
 
        snprintf(mvm->hw->wiphy->fw_version,
                 sizeof(mvm->hw->wiphy->fw_version),
@@ -524,12 +523,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        /* set the nvm_file_name according to priority */
        if (iwlwifi_mod_params.nvm_file) {
                mvm->nvm_file_name = iwlwifi_mod_params.nvm_file;
-       } else {
-               if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) &&
-                   (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP))
-                       mvm->nvm_file_name = mvm->cfg->default_nvm_file_8000A;
+       } else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+               if (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_B_STEP)
+                       mvm->nvm_file_name = mvm->cfg->default_nvm_file_B_step;
                else
-                       mvm->nvm_file_name = mvm->cfg->default_nvm_file;
+                       mvm->nvm_file_name = mvm->cfg->default_nvm_file_C_step;
        }
 
        if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name,
@@ -691,7 +689,6 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
 {
        struct iwl_fw_dbg_trigger_tlv *trig;
        struct iwl_fw_dbg_trigger_cmd *cmds_trig;
-       char buf[32];
        int i;
 
        if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_FW_NOTIF))
@@ -711,9 +708,9 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
                if (cmds_trig->cmds[i].cmd_id != pkt->hdr.cmd)
                        continue;
 
-               memset(buf, 0, sizeof(buf));
-               snprintf(buf, sizeof(buf), "CMD 0x%02x received", pkt->hdr.cmd);
-               iwl_mvm_fw_dbg_collect_trig(mvm, trig, buf, sizeof(buf));
+               iwl_mvm_fw_dbg_collect_trig(mvm, trig,
+                                           "CMD 0x%02x received",
+                                           pkt->hdr.cmd);
                break;
        }
 }
@@ -894,18 +891,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
         * the next start() call from mac80211. If restart isn't called
         * (no fw restart) scan status will stay busy.
         */
-       switch (mvm->scan_status) {
-       case IWL_MVM_SCAN_NONE:
-               break;
-       case IWL_MVM_SCAN_OS:
-               ieee80211_scan_completed(mvm->hw, true);
-               break;
-       case IWL_MVM_SCAN_SCHED:
-               /* Sched scan will be restarted by mac80211 in restart_hw. */
-               if (!mvm->restart_fw)
-                       ieee80211_sched_scan_stopped(mvm->hw);
-               break;
-       }
+       iwl_mvm_report_scan_aborted(mvm);
 
        /*
         * If we're restarting already, don't cycle restarts.
@@ -1175,7 +1161,7 @@ static void iwl_mvm_d0i3_disconnect_iter(void *data, u8 *mac,
 
        if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc &&
            mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
-               ieee80211_connection_loss(vif);
+               iwl_mvm_connection_loss(mvm, vif, "D0i3");
 }
 
 void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq)
index 192b74bc8cf67270a7db805f846f16abf7a23081..e68a475e307194cd140a2708fc664e8a8f7f6f11 100644 (file)
@@ -67,7 +67,7 @@
 #include "fw-api.h"
 #include "mvm.h"
 
-/* Maps the driver specific channel width definition to the the fw values */
+/* Maps the driver specific channel width definition to the fw values */
 u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
 {
        switch (chandef->width) {
index 9140b0b701c75cd316c8d1063fdc1e4286339f7c..f9928f2c125f726bbf89474096bd47990bfb86eb 100644 (file)
@@ -1277,9 +1277,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                                        info->status.ampdu_ack_len);
                }
        } else {
-       /*
-        * For legacy, update frame history with for each Tx retry.
-        */
+               /* For legacy, update frame history with for each Tx retry. */
                retries = info->status.rates[0].count - 1;
                /* HW doesn't send more than 15 retries */
                retries = min(retries, 15);
@@ -1615,9 +1613,9 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
 static void rs_update_rate_tbl(struct iwl_mvm *mvm,
                               struct ieee80211_sta *sta,
                               struct iwl_lq_sta *lq_sta,
-                              struct rs_rate *rate)
+                              struct iwl_scale_tbl_info *tbl)
 {
-       rs_fill_lq_cmd(mvm, sta, lq_sta, rate);
+       rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate);
        iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
 }
 
@@ -2147,7 +2145,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                        rate->type = LQ_NONE;
                        lq_sta->search_better_tbl = 0;
                        tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-                       rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate);
+                       rs_update_rate_tbl(mvm, sta, lq_sta, tbl);
                }
                return;
        }
@@ -2310,7 +2308,7 @@ lq_update:
        /* Replace uCode's rate table for the destination station. */
        if (update_lq) {
                tbl->rate.index = index;
-               rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate);
+               rs_update_rate_tbl(mvm, sta, lq_sta, tbl);
        }
 
        rs_stay_in_table(lq_sta, false);
@@ -2357,8 +2355,7 @@ lq_update:
 
                        rs_dump_rate(mvm, &tbl->rate,
                                     "Switch to SEARCH TABLE:");
-                       rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate);
-                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
+                       rs_update_rate_tbl(mvm, sta, lq_sta, tbl);
                } else {
                        done_search = 1;
                }
@@ -3238,7 +3235,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
        lq_cmd->agg_frame_cnt_limit = mvmsta->max_agg_bufsize;
 
        /*
-        * In case of low latency, tell the firwmare to leave a frame in the
+        * In case of low latency, tell the firmware to leave a frame in the
         * Tx Fifo so that it can start a transaction in the same TxOP. This
         * basically allows the firmware to send bursts.
         */
@@ -3745,7 +3742,7 @@ void iwl_mvm_rate_control_unregister(void)
 
 /**
  * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable
- * Tx protection, according to this rquest and previous requests,
+ * Tx protection, according to this request and previous requests,
  * and send the LQ command.
  * @mvmsta: The station
  * @enable: Enable Tx protection?
index 6177e24f4c016d09c8496186d65c394d05bb5eb3..78ec7db64ba59e886e2a7b18a3df64f70a4ea29c 100644 (file)
@@ -362,7 +362,7 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
                                iwl_fw_dbg_trigger_check_stop(mvm, mvmsta->vif,
                                                              trig);
                        if (trig_check && rx_status->signal < rssi)
-                               iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL, 0);
+                               iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL);
                }
        }
 
@@ -552,7 +552,7 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
        if (le32_to_cpup((__le32 *) (pkt->data + trig_offset)) < trig_thold)
                return;
 
-       iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL, 0);
+       iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL);
 }
 
 void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
index a75bb150ea275ef18fd6449e8c1d5543fc466bf6..74e1c86289dcbcedc1f5c7b963e468095de7cf25 100644 (file)
@@ -935,6 +935,8 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
 
        cmd->n_channels = (u8)req->n_channels;
 
+       cmd->delay = cpu_to_le32(req->delay);
+
        if (iwl_mvm_scan_pass_all(mvm, req))
                flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
        else
@@ -1177,6 +1179,18 @@ static bool iwl_mvm_find_scan_type(struct iwl_mvm *mvm,
        return false;
 }
 
+static int iwl_mvm_find_first_scan(struct iwl_mvm *mvm,
+                                  enum iwl_umac_scan_uid_type type)
+{
+       int i;
+
+       for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++)
+               if (mvm->scan_uid[i] & type)
+                       return i;
+
+       return i;
+}
+
 static u32 iwl_generate_scan_uid(struct iwl_mvm *mvm,
                                 enum iwl_umac_scan_uid_type type)
 {
@@ -1436,7 +1450,13 @@ int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                                cpu_to_le16(req->interval / MSEC_PER_SEC);
        sec_part->schedule[0].iter_count = 0xff;
 
-       sec_part->delay = 0;
+       if (req->delay > U16_MAX) {
+               IWL_DEBUG_SCAN(mvm,
+                              "delay value is > 16-bits, set to max possible\n");
+               sec_part->delay = cpu_to_le16(U16_MAX);
+       } else {
+               sec_part->delay = cpu_to_le16(req->delay);
+       }
 
        iwl_mvm_build_unified_scan_probe(mvm, vif, ies, &sec_part->preq,
                req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
@@ -1613,3 +1633,54 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm)
                mvm->fw->ucode_capa.n_scan_channels +
                sizeof(struct iwl_scan_probe_req);
 }
+
+/*
+ * This function is used in nic restart flow, to inform mac80211 about scans
+ * that was aborted by restart flow or by an assert.
+ */
+void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
+{
+       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
+               u32 uid, i;
+
+               uid = iwl_mvm_find_first_scan(mvm, IWL_UMAC_SCAN_UID_REG_SCAN);
+               if (uid < IWL_MVM_MAX_SIMULTANEOUS_SCANS) {
+                       ieee80211_scan_completed(mvm->hw, true);
+                       mvm->scan_uid[uid] = 0;
+               }
+               uid = iwl_mvm_find_first_scan(mvm,
+                                             IWL_UMAC_SCAN_UID_SCHED_SCAN);
+               if (uid < IWL_MVM_MAX_SIMULTANEOUS_SCANS && !mvm->restart_fw) {
+                       ieee80211_sched_scan_stopped(mvm->hw);
+                       mvm->scan_uid[uid] = 0;
+               }
+
+               /* We shouldn't have any UIDs still set.  Loop over all the
+                * UIDs to make sure there's nothing left there and warn if
+                * any is found.
+                */
+               for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++) {
+                       if (WARN_ONCE(mvm->scan_uid[i],
+                                     "UMAC scan UID %d was not cleaned\n",
+                                     mvm->scan_uid[i]))
+                               mvm->scan_uid[i] = 0;
+               }
+       } else {
+               switch (mvm->scan_status) {
+               case IWL_MVM_SCAN_NONE:
+                       break;
+               case IWL_MVM_SCAN_OS:
+                       ieee80211_scan_completed(mvm->hw, true);
+                       break;
+               case IWL_MVM_SCAN_SCHED:
+                       /*
+                        * Sched scan will be restarted by mac80211 in
+                        * restart_hw, so do not report if FW is about to be
+                        * restarted.
+                        */
+                       if (!mvm->restart_fw)
+                               ieee80211_sched_scan_stopped(mvm->hw);
+                       break;
+               }
+       }
+}
index 50f9288368af169fe4eb5c31b8316f46dfd35c97..1845b79487c81b446e0432bc385e9fc12884ff68 100644 (file)
@@ -209,9 +209,8 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm,
 {
        unsigned long used_hw_queues;
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-       unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
-                                       mvm->cfg->base_params->wd_timeout :
-                                       IWL_WATCHDOG_DISABLED;
+       unsigned int wdg_timeout =
+               iwl_mvm_get_wd_timeout(mvm, NULL, true, false);
        u32 ac;
 
        lockdep_assert_held(&mvm->mutex);
@@ -491,8 +490,18 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 
        if (vif->type == NL80211_IFTYPE_STATION &&
            mvmvif->ap_sta_id == mvm_sta->sta_id) {
+               ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
+               if (ret)
+                       return ret;
                /* flush its queues here since we are freeing mvm_sta */
                ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
+               if (ret)
+                       return ret;
+               ret = iwl_trans_wait_tx_queue_empty(mvm->trans,
+                                                   mvm_sta->tfd_queue_msk);
+               if (ret)
+                       return ret;
+               ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
 
                /* if we are associated - we can't remove the AP STA now */
                if (vif->bss_conf.assoc)
@@ -971,9 +980,8 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 {
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
-       unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
-                                       mvm->cfg->base_params->wd_timeout :
-                                       IWL_WATCHDOG_DISABLED;
+       unsigned int wdg_timeout =
+               iwl_mvm_get_wd_timeout(mvm, vif, sta->tdls, false);
        int queue, fifo, ret;
        u16 ssn;
 
@@ -1120,8 +1128,12 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        spin_unlock_bh(&mvmsta->lock);
 
        if (old_state >= IWL_AGG_ON) {
+               iwl_mvm_drain_sta(mvm, mvmsta, true);
                if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
                        IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
+               iwl_trans_wait_tx_queue_empty(mvm->trans,
+                                             mvmsta->tfd_queue_msk);
+               iwl_mvm_drain_sta(mvm, mvmsta, false);
 
                iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
 
@@ -1702,8 +1714,8 @@ void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
        mvm_sta->disable_tx = disable;
 
        /*
-        * Tell mac80211 to start/stop queueing tx for this station,
-        * but don't stop queueing if there are still pending frames
+        * Tell mac80211 to start/stop queuing tx for this station,
+        * but don't stop queuing if there are still pending frames
         * for this station.
         */
        if (disable || !atomic_read(&mvm->pending_frames[mvm_sta->sta_id]))
index d8f48975ad087db1fad57b9f764fcb137416e2d0..748f5dc3f9f4337952efc84fe93e5bfb89f97c81 100644 (file)
@@ -150,7 +150,7 @@ struct iwl_mvm_vif;
  * DOC: station table - AP Station in STA mode
  *
  * %iwl_mvm_vif includes the index of the AP station in the fw's STA table:
- * %ap_sta_id. To get the point to the coresponsding %ieee80211_sta,
+ * %ap_sta_id. To get the point to the corresponding %ieee80211_sta,
  * &fw_id_to_mac_id can be used. Due to the way the fw works, we must not remove
  * the AP station from the fw before setting the MAC context as unassociated.
  * Hence, %fw_id_to_mac_id[%ap_sta_id] will be NULLed when the AP station is
@@ -209,14 +209,14 @@ struct iwl_mvm_vif;
  * When a trigger frame is received, mac80211 tells the driver to send frames
  * from the AMPDU queues or sends frames to non-aggregation queues itself,
  * depending on which ACs are delivery-enabled and what TID has frames to
- * transmit. Note that mac80211 has all the knowledege since all the non-agg
+ * transmit. Note that mac80211 has all the knowledge since all the non-agg
  * frames are buffered / filtered, and the driver tells mac80211 about agg
  * frames). The driver needs to tell the fw to let frames out even if the
  * station is asleep. This is done by %iwl_mvm_sta_modify_sleep_tx_count.
  *
  * When we receive a frame from that station with PM bit unset, the driver
  * needs to let the fw know that this station isn't asleep any more. This is
- * done by %iwl_mvm_sta_modify_ps_wake in response to mac80211 signalling the
+ * done by %iwl_mvm_sta_modify_ps_wake in response to mac80211 signaling the
  * station's wakeup.
  *
  * For a GO, the Service Period might be cut short due to an absence period
index 8d179ab67cc237026e8653d18e791d826d9ee0e4..fd7b0d36f9a620b8e99dcc7b643806b76f09af4d 100644 (file)
@@ -119,7 +119,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
 
        /*
         * Flush the offchannel queue -- this is called when the time
-        * event finishes or is cancelled, so that frames queued for it
+        * event finishes or is canceled, so that frames queued for it
         * won't get stuck on the queue and be transmitted in the next
         * time event.
         * We have to send the command asynchronously since this cannot
@@ -187,7 +187,8 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
                return false;
        if (errmsg)
                IWL_ERR(mvm, "%s\n", errmsg);
-       ieee80211_connection_loss(vif);
+
+       iwl_mvm_connection_loss(mvm, vif, errmsg);
        return true;
 }
 
@@ -196,19 +197,24 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm,
                             struct iwl_mvm_time_event_data *te_data,
                             struct iwl_time_event_notif *notif)
 {
-       if (!le32_to_cpu(notif->status)) {
-               if (te_data->vif->type == NL80211_IFTYPE_STATION)
-                       ieee80211_connection_loss(te_data->vif);
+       struct ieee80211_vif *vif = te_data->vif;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       if (!notif->status)
                IWL_DEBUG_TE(mvm, "CSA time event failed to start\n");
-               iwl_mvm_te_clear_data(mvm, te_data);
-               return;
-       }
 
        switch (te_data->vif->type) {
        case NL80211_IFTYPE_AP:
+               if (!notif->status)
+                       mvmvif->csa_failed = true;
                iwl_mvm_csa_noa_start(mvm);
                break;
        case NL80211_IFTYPE_STATION:
+               if (!notif->status) {
+                       iwl_mvm_connection_loss(mvm, vif,
+                                               "CSA TE failed to start");
+                       break;
+               }
                iwl_mvm_csa_client_absent(mvm, te_data->vif);
                ieee80211_chswitch_done(te_data->vif, true);
                break;
@@ -222,6 +228,44 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm,
        iwl_mvm_te_clear_data(mvm, te_data);
 }
 
+static void iwl_mvm_te_check_trigger(struct iwl_mvm *mvm,
+                                    struct iwl_time_event_notif *notif,
+                                    struct iwl_mvm_time_event_data *te_data)
+{
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_time_event *te_trig;
+       int i;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT))
+               return;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT);
+       te_trig = (void *)trig->data;
+
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, te_data->vif, trig))
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(te_trig->time_events); i++) {
+               u32 trig_te_id = le32_to_cpu(te_trig->time_events[i].id);
+               u32 trig_action_bitmap =
+                       le32_to_cpu(te_trig->time_events[i].action_bitmap);
+               u32 trig_status_bitmap =
+                       le32_to_cpu(te_trig->time_events[i].status_bitmap);
+
+               if (trig_te_id != te_data->id ||
+                   !(trig_action_bitmap & le32_to_cpu(notif->action)) ||
+                   !(trig_status_bitmap & BIT(le32_to_cpu(notif->status))))
+                       continue;
+
+               iwl_mvm_fw_dbg_collect_trig(mvm, trig,
+                                           "Time event %d Action 0x%x received status: %d",
+                                           te_data->id,
+                                           le32_to_cpu(notif->action),
+                                           le32_to_cpu(notif->status));
+               break;
+       }
+}
+
 /*
  * Handles a FW notification for an event that is known to the driver.
  *
@@ -239,6 +283,8 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
                     le32_to_cpu(notif->unique_id),
                     le32_to_cpu(notif->action));
 
+       iwl_mvm_te_check_trigger(mvm, notif, te_data);
+
        /*
         * The FW sends the start/end time event notifications even for events
         * that it fails to schedule. This is indicated in the status field of
@@ -248,11 +294,16 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
         * events in the system).
         */
        if (!le32_to_cpu(notif->status)) {
-               bool start = le32_to_cpu(notif->action) &
-                               TE_V2_NOTIF_HOST_EVENT_START;
-               IWL_WARN(mvm, "Time Event %s notification failure\n",
-                        start ? "start" : "end");
-               if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
+               const char *msg;
+
+               if (notif->action & cpu_to_le32(TE_V2_NOTIF_HOST_EVENT_START))
+                       msg = "Time Event start notification failure";
+               else
+                       msg = "Time Event end notification failure";
+
+               IWL_DEBUG_TE(mvm, "%s\n", msg);
+
+               if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, msg)) {
                        iwl_mvm_te_clear_data(mvm, te_data);
                        return;
                }
@@ -315,6 +366,8 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
        if (!aux_roc_te) /* Not a Aux ROC time event */
                return -EINVAL;
 
+       iwl_mvm_te_check_trigger(mvm, notif, te_data);
+
        if (!le32_to_cpu(notif->status)) {
                IWL_DEBUG_TE(mvm,
                             "ERROR: Aux ROC Time Event %s notification failure\n",
@@ -769,7 +822,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
         * Iterate over the list of aux roc time events and find the time
         * event that is associated with a BSS interface.
         * This assumes that a BSS interface can have only a single time
-        * event at any given time and this time event coresponds to a ROC
+        * event at any given time and this time event corresponds to a ROC
         * request
         */
        list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
index 6f6b35db3ab8eb9b71c8bf178d7227254340a41a..de4fbc6d57f150130e095fbec5471e9149d951bf 100644 (file)
@@ -147,7 +147,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
  * @vif: the virtual interface for which the session is issued
  *
  * This functions cancels the session protection which is an act of good
- * citizenship. If it is not needed any more it should be cancelled because
+ * citizenship. If it is not needed any more it should be canceled because
  * the other bindings wait for the medium during that time.
  * This funtions doesn't sleep.
  */
@@ -162,7 +162,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
                                struct iwl_device_cmd *cmd);
 
 /**
- * iwl_mvm_start_p2p_roc - start remain on channel for p2p device functionlity
+ * iwl_mvm_start_p2p_roc - start remain on channel for p2p device functionality
  * @mvm: the mvm component
  * @vif: the virtual interface for which the roc is requested. It is assumed
  * that the vif type is NL80211_IFTYPE_P2P_DEVICE
index ba34dda1ae36bc8ca562f2cbae7a443bf3bf1868..ef32e177f662b3ba03772e02b1c9b9e512bcd64f 100644 (file)
@@ -1049,6 +1049,14 @@ out:
        return 0;
 }
 
+/*
+ * Note that there are transports that buffer frames before they reach
+ * the firmware. This means that after flush_tx_path is called, the
+ * queue might not be empty. The race-free way to handle this is to:
+ * 1) set the station as draining
+ * 2) flush the Tx path
+ * 3) wait for the transport queues to be empty
+ */
 int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync)
 {
        int ret;
index 435faee0a28eee1d674d95f07fc934baef2e13b0..bc55a8b82db6d88ad42ef1151e0c5c53c2cbf64c 100644 (file)
@@ -122,7 +122,7 @@ int iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u8 id,
 }
 
 /*
- * We assume that the caller set the status to the sucess value
+ * We assume that the caller set the status to the success value
  */
 int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd,
                            u32 *status)
@@ -737,7 +737,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init)
 }
 
 /**
- * iwl_mvm_update_smps - Get a requst to change the SMPS mode
+ * iwl_mvm_update_smps - Get a request to change the SMPS mode
  * @req_type: The part of the driver who call for a change.
  * @smps_requests: The request to change the SMPS mode.
  *
@@ -921,3 +921,71 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
 
        return bss_iter_data.vif;
 }
+
+unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
+                                   struct ieee80211_vif *vif,
+                                   bool tdls, bool cmd_q)
+{
+       struct iwl_fw_dbg_trigger_tlv *trigger;
+       struct iwl_fw_dbg_trigger_txq_timer *txq_timer;
+       unsigned int default_timeout =
+               cmd_q ? IWL_DEF_WD_TIMEOUT : mvm->cfg->base_params->wd_timeout;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS))
+               return iwlmvm_mod_params.tfd_q_hang_detect ?
+                       default_timeout : IWL_WATCHDOG_DISABLED;
+
+       trigger = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS);
+       txq_timer = (void *)trigger->data;
+
+       if (tdls)
+               return le32_to_cpu(txq_timer->tdls);
+
+       if (cmd_q)
+               return le32_to_cpu(txq_timer->command_queue);
+
+       if (WARN_ON(!vif))
+               return default_timeout;
+
+       switch (ieee80211_vif_type_p2p(vif)) {
+       case NL80211_IFTYPE_ADHOC:
+               return le32_to_cpu(txq_timer->ibss);
+       case NL80211_IFTYPE_STATION:
+               return le32_to_cpu(txq_timer->bss);
+       case NL80211_IFTYPE_AP:
+               return le32_to_cpu(txq_timer->softap);
+       case NL80211_IFTYPE_P2P_CLIENT:
+               return le32_to_cpu(txq_timer->p2p_client);
+       case NL80211_IFTYPE_P2P_GO:
+               return le32_to_cpu(txq_timer->p2p_go);
+       case NL80211_IFTYPE_P2P_DEVICE:
+               return le32_to_cpu(txq_timer->p2p_device);
+       default:
+               WARN_ON(1);
+               return mvm->cfg->base_params->wd_timeout;
+       }
+}
+
+void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                            const char *errmsg)
+{
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_mlme *trig_mlme;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME))
+               goto out;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);
+       trig_mlme = (void *)trig->data;
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
+               goto out;
+
+       if (trig_mlme->stop_connection_loss &&
+           --trig_mlme->stop_connection_loss)
+               goto out;
+
+       iwl_mvm_fw_dbg_collect_trig(mvm, trig, "%s", errmsg);
+
+out:
+       ieee80211_connection_loss(vif);
+}
index 7b7e2f223fb230fad922e7fcaec08ec8ae7eb5ac..7ff69c642103f1febeea67d9c082a035039b4121 100644 (file)
@@ -600,9 +600,11 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
                if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID))
                        break;
 
-               IWL_DEBUG_RX(trans, "cmd at offset %d: %s (0x%.2x)\n",
-                       rxcb._offset, get_cmd_string(trans_pcie, pkt->hdr.cmd),
-                       pkt->hdr.cmd);
+               IWL_DEBUG_RX(trans,
+                            "cmd at offset %d: %s (0x%.2x, seq 0x%x)\n",
+                            rxcb._offset,
+                            get_cmd_string(trans_pcie, pkt->hdr.cmd),
+                            pkt->hdr.cmd, le16_to_cpu(pkt->hdr.sequence));
 
                len = iwl_rx_packet_len(pkt);
                len += sizeof(u32); /* account for status word */
index dc247325d8d7f9ebd11472bcf6c64e9a48d7bb14..2de8fbfe4edf4d6c6997307fb91052177fd7e6e4 100644 (file)
@@ -691,11 +691,15 @@ static int iwl_pcie_rsa_race_bug_wa(struct iwl_trans *trans)
 {
        u32 val, loop = 1000;
 
-       /* Check the RSA semaphore is accessible - if not, we are in trouble */
+       /*
+        * Check the RSA semaphore is accessible.
+        * If the HW isn't locked and the rsa semaphore isn't accessible,
+        * we are in trouble.
+        */
        val = iwl_read_prph(trans, PREG_AUX_BUS_WPROT_0);
        if (val & (BIT(1) | BIT(17))) {
-               IWL_ERR(trans,
-                       "can't access the RSA semaphore it is write protected\n");
+               IWL_INFO(trans,
+                        "can't access the RSA semaphore it is write protected\n");
                return 0;
        }
 
@@ -719,10 +723,10 @@ static int iwl_pcie_rsa_race_bug_wa(struct iwl_trans *trans)
        return -EIO;
 }
 
-static int iwl_pcie_load_cpu_sections_8000b(struct iwl_trans *trans,
-                                           const struct fw_img *image,
-                                           int cpu,
-                                           int *first_ucode_section)
+static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
+                                          const struct fw_img *image,
+                                          int cpu,
+                                          int *first_ucode_section)
 {
        int shift_param;
        int i, ret = 0, sec_num = 0x1;
@@ -917,20 +921,16 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
        }
 
        /* release CPU reset */
-       if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
-               iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
-       else
-               iwl_write32(trans, CSR_RESET, 0);
+       iwl_write32(trans, CSR_RESET, 0);
 
        return 0;
 }
 
-static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
-                                          const struct fw_img *image)
+static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
+                                         const struct fw_img *image)
 {
        int ret = 0;
        int first_ucode_section;
-       u32 reg;
 
        IWL_DEBUG_FW(trans, "working with %s CPU\n",
                     image->is_dual_cpus ? "Dual" : "Single");
@@ -948,38 +948,23 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
        iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
 
        /* load to FW the binary Secured sections of CPU1 */
-       ret = iwl_pcie_load_cpu_sections_8000b(trans, image, 1,
-                                              &first_ucode_section);
+       ret = iwl_pcie_load_cpu_sections_8000(trans, image, 1,
+                                             &first_ucode_section);
        if (ret)
                return ret;
 
        /* load to FW the binary sections of CPU2 */
-       ret = iwl_pcie_load_cpu_sections_8000b(trans, image, 2,
-                                              &first_ucode_section);
+       ret = iwl_pcie_load_cpu_sections_8000(trans, image, 2,
+                                             &first_ucode_section);
        if (ret)
                return ret;
 
-       /* wait for image verification to complete  */
-       ret = iwl_poll_prph_bit(trans, LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0,
-                               LMPM_SECURE_BOOT_STATUS_SUCCESS,
-                               LMPM_SECURE_BOOT_STATUS_SUCCESS,
-                               LMPM_SECURE_TIME_OUT);
-       if (ret < 0) {
-               reg = iwl_read_prph(trans,
-                                   LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0);
-
-               IWL_ERR(trans, "Timeout on secure boot process, reg = %x\n",
-                       reg);
-               return ret;
-       }
-
        return 0;
 }
 
 static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
                                   const struct fw_img *fw, bool run_in_rfkill)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        int ret;
        bool hw_rfkill;
 
@@ -1009,9 +994,6 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
                return ret;
        }
 
-       /* init ref_count to 1 (should be cleared when ucode is loaded) */
-       trans_pcie->ref_count = 1;
-
        /* make sure rfkill handshake bits are cleared */
        iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
        iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
@@ -1026,9 +1008,8 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
        iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 
        /* Load the given image to the HW */
-       if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) &&
-           (CSR_HW_REV_STEP(trans->hw_rev) != SILICON_A_STEP))
-               return iwl_pcie_load_given_ucode_8000b(trans, fw);
+       if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+               return iwl_pcie_load_given_ucode_8000(trans, fw);
        else
                return iwl_pcie_load_given_ucode(trans, fw);
 }
@@ -1330,6 +1311,9 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
        trans_pcie->bc_table_dword = trans_cfg->bc_table_dword;
        trans_pcie->scd_set_active = trans_cfg->scd_set_active;
 
+       /* init ref_count to 1 (should be cleared when ucode is loaded) */
+       trans_pcie->ref_count = 1;
+
        /* Initialize NAPI here - it should be before registering to mac80211
         * in the opmode but after the HW struct is allocated.
         * As this function may be called again in some corner cases don't