Merge tag 'iwlwifi-next-for-kalle-2016-09-19-2' of git://git.kernel.org/pub/scm/linux...
authorKalle Valo <kvalo@codeaurora.org>
Mon, 26 Sep 2016 11:10:31 +0000 (14:10 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 26 Sep 2016 11:10:31 +0000 (14:10 +0300)
* added support for MU-MIMO sniffer
* added support for RRM by scan
* added support for packet injection
* migrate to devm memory allocation handling
* some fixes, mostly in DQA and new HW support
* other generic cleanups

28 files changed:
drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c
drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
drivers/net/wireless/intel/iwlwifi/iwl-notif-wait.c
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
drivers/net/wireless/intel/iwlwifi/iwl-phy-db.c
drivers/net/wireless/intel/iwlwifi/iwl-trans.c
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/rx.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c

index 1d9dd15..50510fb 100644 (file)
@@ -33,9 +33,6 @@
 #define CREATE_TRACE_POINTS
 #include "iwl-devtrace.h"
 
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event);
index 1b1e045..94423f0 100644 (file)
@@ -256,6 +256,10 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t;
  *     instead of 3.
  * @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size
  *     (command version 3) that supports per-chain limits
+ * @IWL_UCODE_TLV_API_SCAN_TSF_REPORT: Scan start time reported in scan
+ *     iteration complete notification, and the timestamp reported for RX
+ *     received during scan, are reported in TSF of the mac specified in the
+ *     scan request.
  *
  * @NUM_IWL_UCODE_TLV_API: number of bits used
  */
@@ -267,6 +271,7 @@ enum iwl_ucode_tlv_api {
        IWL_UCODE_TLV_API_NEW_VERSION           = (__force iwl_ucode_tlv_api_t)20,
        IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY     = (__force iwl_ucode_tlv_api_t)24,
        IWL_UCODE_TLV_API_TX_POWER_CHAIN        = (__force iwl_ucode_tlv_api_t)27,
+       IWL_UCODE_TLV_API_SCAN_TSF_REPORT       = (__force iwl_ucode_tlv_api_t)28,
 
        NUM_IWL_UCODE_TLV_API
 #ifdef __CHECKER__
index 8aa1f2b..88f260d 100644 (file)
@@ -99,8 +99,12 @@ void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
                                continue;
 
                        for (i = 0; i < w->n_cmds; i++) {
-                               if (w->cmds[i] ==
-                                   WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) {
+                               u16 rec_id = WIDE_ID(pkt->hdr.group_id,
+                                                    pkt->hdr.cmd);
+
+                               if (w->cmds[i] == rec_id ||
+                                   (!iwl_cmd_groupid(w->cmds[i]) &&
+                                    DEF_ID(w->cmds[i]) == rec_id)) {
                                        found = true;
                                        break;
                                }
index 43f8f7d..3bd6fc1 100644 (file)
@@ -67,6 +67,7 @@
 #include <linux/export.h>
 #include <linux/etherdevice.h>
 #include <linux/pci.h>
+#include <linux/acpi.h>
 #include "iwl-drv.h"
 #include "iwl-modparams.h"
 #include "iwl-nvm-parse.h"
@@ -564,11 +565,16 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
        __le32 mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_STRAP));
        __le32 mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_STRAP));
 
-       /* If OEM did not fuse address - get it from OTP */
-       if (!mac_addr0 && !mac_addr1) {
-               mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_OTP));
-               mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_OTP));
-       }
+       iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
+       /*
+        * If the OEM fused a valid address, use it instead of the one in the
+        * OTP
+        */
+       if (is_valid_ether_addr(data->hw_addr))
+               return;
+
+       mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_OTP));
+       mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_OTP));
 
        iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
 }
@@ -899,3 +905,91 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
        return regd;
 }
 IWL_EXPORT_SYMBOL(iwl_parse_nvm_mcc_info);
+
+#ifdef CONFIG_ACPI
+#define WRDD_METHOD            "WRDD"
+#define WRDD_WIFI              (0x07)
+#define WRDD_WIGIG             (0x10)
+
+static u32 iwl_wrdd_get_mcc(struct device *dev, union acpi_object *wrdd)
+{
+       union acpi_object *mcc_pkg, *domain_type, *mcc_value;
+       u32 i;
+
+       if (wrdd->type != ACPI_TYPE_PACKAGE ||
+           wrdd->package.count < 2 ||
+           wrdd->package.elements[0].type != ACPI_TYPE_INTEGER ||
+           wrdd->package.elements[0].integer.value != 0) {
+               IWL_DEBUG_EEPROM(dev, "Unsupported wrdd structure\n");
+               return 0;
+       }
+
+       for (i = 1 ; i < wrdd->package.count ; ++i) {
+               mcc_pkg = &wrdd->package.elements[i];
+
+               if (mcc_pkg->type != ACPI_TYPE_PACKAGE ||
+                   mcc_pkg->package.count < 2 ||
+                   mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
+                   mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
+                       mcc_pkg = NULL;
+                       continue;
+               }
+
+               domain_type = &mcc_pkg->package.elements[0];
+               if (domain_type->integer.value == WRDD_WIFI)
+                       break;
+
+               mcc_pkg = NULL;
+       }
+
+       if (mcc_pkg) {
+               mcc_value = &mcc_pkg->package.elements[1];
+               return mcc_value->integer.value;
+       }
+
+       return 0;
+}
+
+int iwl_get_bios_mcc(struct device *dev, char *mcc)
+{
+       acpi_handle root_handle;
+       acpi_handle handle;
+       struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
+       acpi_status status;
+       u32 mcc_val;
+
+       root_handle = ACPI_HANDLE(dev);
+       if (!root_handle) {
+               IWL_DEBUG_EEPROM(dev,
+                                "Could not retrieve root port ACPI handle\n");
+               return -ENOENT;
+       }
+
+       /* Get the method's handle */
+       status = acpi_get_handle(root_handle, (acpi_string)WRDD_METHOD,
+                                &handle);
+       if (ACPI_FAILURE(status)) {
+               IWL_DEBUG_EEPROM(dev, "WRD method not found\n");
+               return -ENOENT;
+       }
+
+       /* Call WRDD with no arguments */
+       status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
+       if (ACPI_FAILURE(status)) {
+               IWL_DEBUG_EEPROM(dev, "WRDC invocation failed (0x%x)\n",
+                                status);
+               return -ENOENT;
+       }
+
+       mcc_val = iwl_wrdd_get_mcc(dev, wrdd.pointer);
+       kfree(wrdd.pointer);
+       if (!mcc_val)
+               return -ENOENT;
+
+       mcc[0] = (mcc_val >> 8) & 0xff;
+       mcc[1] = mcc_val & 0xff;
+       mcc[2] = '\0';
+       return 0;
+}
+IWL_EXPORT_SYMBOL(iwl_get_bios_mcc);
+#endif
index d704d52..7249e5b 100644 (file)
@@ -5,7 +5,8 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2016        Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -93,4 +94,21 @@ struct ieee80211_regdomain *
 iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
                       int num_of_ch, __le32 *channels, u16 fw_mcc);
 
+#ifdef CONFIG_ACPI
+/**
+ * iwl_get_bios_mcc - read MCC from BIOS, if available
+ *
+ * @dev: the struct device
+ * @mcc: output buffer (3 bytes) that will get the MCC
+ *
+ * This function tries to read the current MCC from ACPI if available.
+ */
+int iwl_get_bios_mcc(struct device *dev, char *mcc);
+#else
+static inline int iwl_get_bios_mcc(struct device *dev, char *mcc)
+{
+       return -ENOENT;
+}
+#endif
+
 #endif /* __iwl_nvm_parse_h__ */
index 7beba9a..2893826 100644 (file)
@@ -110,7 +110,7 @@ enum iwl_phy_db_section_type {
        IWL_PHY_DB_MAX
 };
 
-#define PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */
+#define PHY_DB_CMD 0x6c
 
 /*
  * phy db - configure operational ucode
index b0bd67c..d42cab2 100644 (file)
@@ -78,7 +78,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
        static struct lock_class_key __key;
 #endif
 
-       trans = kzalloc(sizeof(*trans) + priv_size, GFP_KERNEL);
+       trans = devm_kzalloc(dev, sizeof(*trans) + priv_size, GFP_KERNEL);
        if (!trans)
                return NULL;
 
@@ -103,18 +103,14 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
                                  SLAB_HWCACHE_ALIGN,
                                  NULL);
        if (!trans->dev_cmd_pool)
-               goto free;
+               return NULL;
 
        return trans;
- free:
-       kfree(trans);
-       return NULL;
 }
 
 void iwl_trans_free(struct iwl_trans *trans)
 {
        kmem_cache_destroy(trans->dev_cmd_pool);
-       kfree(trans);
 }
 
 int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
@@ -140,6 +136,9 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
        if (!(cmd->flags & CMD_ASYNC))
                lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
 
+       if (trans->wide_cmd_header && !iwl_cmd_groupid(cmd->id))
+               cmd->id = DEF_ID(cmd->id);
+
        ret = trans->ops->send_cmd(trans, cmd);
 
        if (!(cmd->flags & CMD_ASYNC))
index 04e998d..0296124 100644 (file)
@@ -153,6 +153,7 @@ static inline u32 iwl_cmd_id(u8 opcode, u8 groupid, u8 version)
 
 /* make u16 wide id out of u8 group and opcode */
 #define WIDE_ID(grp, opcode) ((grp << 8) | opcode)
+#define DEF_ID(opcode) ((1 << 8) | (opcode))
 
 /* due to the conversion, this group is special; new groups
  * should be defined in the appropriate fw-api header files
@@ -484,7 +485,6 @@ struct iwl_hcmd_arr {
  * @bc_table_dword: set to true if the BC table expects the byte count to be
  *     in DWORD (as opposed to bytes)
  * @scd_set_active: should the transport configure the SCD for HCMD queue
- * @wide_cmd_header: firmware supports wide host command header
  * @sw_csum_tx: transport should compute the TCP checksum
  * @command_groups: array of command groups, each member is an array of the
  *     commands in the group; for debugging only
@@ -506,7 +506,6 @@ struct iwl_trans_config {
        enum iwl_amsdu_size rx_buf_size;
        bool bc_table_dword;
        bool scd_set_active;
-       bool wide_cmd_header;
        bool sw_csum_tx;
        const struct iwl_hcmd_arr *command_groups;
        int command_groups_size;
@@ -770,6 +769,7 @@ enum iwl_plat_pm_mode {
  * @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
  * @ltr_enabled: set to true if the LTR is enabled
+ * @wide_cmd_header: true when ucode supports wide command header format
  * @num_rx_queues: number of RX queues allocated by the transport;
  *     the transport must set this before calling iwl_drv_start()
  * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
@@ -821,6 +821,7 @@ struct iwl_trans {
 
        const struct iwl_hcmd_arr *command_groups;
        int command_groups_size;
+       bool wide_cmd_header;
 
        u8 num_rx_queues;
 
index b232717..8ff1921 100644 (file)
@@ -504,6 +504,28 @@ static inline char *iwl_dbgfs_is_match(char *name, char *buf)
        return !strncmp(name, buf, len) ? buf + len : NULL;
 }
 
+static ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file,
+                                                char __user *user_buf,
+                                                size_t count, loff_t *ppos)
+{
+       struct ieee80211_vif *vif = file->private_data;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm *mvm = mvmvif->mvm;
+       u32 curr_gp2;
+       u64 curr_os;
+       s64 diff;
+       char buf[64];
+       const size_t bufsz = sizeof(buf);
+       int pos = 0;
+
+       iwl_mvm_get_sync_time(mvm, &curr_gp2, &curr_os);
+       do_div(curr_os, NSEC_PER_USEC);
+       diff = curr_os - curr_gp2;
+       pos += scnprintf(buf + pos, bufsz - pos, "diff=%lld\n", diff);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
 static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif,
                                          char *buf,
                                          size_t count, loff_t *ppos)
@@ -1530,6 +1552,8 @@ MVM_DEBUGFS_READ_FILE_OPS(tof_range_response);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
 MVM_DEBUGFS_WRITE_FILE_OPS(lqm_send_cmd, 64);
+MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
+
 
 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
@@ -1570,6 +1594,8 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
        MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir,
                                 S_IRUSR | S_IWUSR);
        MVM_DEBUGFS_ADD_FILE_VIF(lqm_send_cmd, mvmvif->dbgfs_dir, S_IWUSR);
+       MVM_DEBUGFS_ADD_FILE_VIF(os_device_timediff,
+                                mvmvif->dbgfs_dir, S_IRUSR);
 
        if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
            mvmvif == mvm->bf_allowed_vif)
index b344898..539d718 100644 (file)
@@ -917,6 +917,59 @@ static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
        return ret ?: count;
 }
 
+static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
+                                            char *buf, size_t count,
+                                            loff_t *ppos)
+{
+       struct iwl_rx_cmd_buffer rxb = {
+               ._rx_page_order = 0,
+               .truesize = 0, /* not used */
+               ._offset = 0,
+       };
+       struct iwl_rx_packet *pkt;
+       struct iwl_rx_mpdu_desc *desc;
+       int bin_len = count / 2;
+       int ret = -EINVAL;
+
+       /* supporting only 9000 descriptor */
+       if (!mvm->trans->cfg->mq_rx_supported)
+               return -ENOTSUPP;
+
+       rxb._page = alloc_pages(GFP_ATOMIC, 0);
+       if (!rxb._page)
+               return -ENOMEM;
+       pkt = rxb_addr(&rxb);
+
+       ret = hex2bin(page_address(rxb._page), buf, bin_len);
+       if (ret)
+               goto out;
+
+       /* avoid invalid memory access */
+       if (bin_len < sizeof(*pkt) + sizeof(*desc))
+               goto out;
+
+       /* check this is RX packet */
+       if (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd) !=
+           WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD))
+               goto out;
+
+       /* check the length in metadata matches actual received length */
+       desc = (void *)pkt->data;
+       if (le16_to_cpu(desc->mpdu_len) !=
+           (bin_len - sizeof(*desc) - sizeof(*pkt)))
+               goto out;
+
+       local_bh_disable();
+       iwl_mvm_rx_mpdu_mq(mvm, NULL, &rxb, 0);
+       local_bh_enable();
+       ret = 0;
+
+out:
+       iwl_free_rxb(&rxb);
+
+       return ret ?: count;
+}
+
 static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
                                          char __user *user_buf,
                                          size_t count, loff_t *ppos)
@@ -1454,6 +1507,7 @@ MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8);
 MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8);
 MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
                           (IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
+MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
 
 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
@@ -1464,6 +1518,132 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
 #endif
 
+static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct iwl_mvm *mvm = file->private_data;
+       struct iwl_dbg_mem_access_cmd cmd = {};
+       struct iwl_dbg_mem_access_rsp *rsp;
+       struct iwl_host_cmd hcmd = {
+               .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
+               .data = { &cmd, },
+               .len = { sizeof(cmd) },
+       };
+       size_t delta, len;
+       ssize_t ret;
+
+       hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
+                            DEBUG_GROUP, 0);
+       cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
+
+       /* Take care of alignment of both the position and the length */
+       delta = *ppos & 0x3;
+       cmd.addr = cpu_to_le32(*ppos - delta);
+       cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4,
+                                 (size_t)DEBUG_MEM_MAX_SIZE_DWORDS));
+
+       mutex_lock(&mvm->mutex);
+       ret = iwl_mvm_send_cmd(mvm, &hcmd);
+       mutex_unlock(&mvm->mutex);
+
+       if (ret < 0)
+               return ret;
+
+       rsp = (void *)hcmd.resp_pkt->data;
+       if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
+               ret = -ENXIO;
+               goto out;
+       }
+
+       len = min((size_t)le32_to_cpu(rsp->len) << 2,
+                 iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp));
+       len = min(len - delta, count);
+       if (len < 0) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       ret = len - copy_to_user(user_buf, (void *)rsp->data + delta, len);
+       *ppos += ret;
+
+out:
+       iwl_free_resp(&hcmd);
+       return ret;
+}
+
+static ssize_t iwl_dbgfs_mem_write(struct file *file,
+                                  const char __user *user_buf, size_t count,
+                                  loff_t *ppos)
+{
+       struct iwl_mvm *mvm = file->private_data;
+       struct iwl_dbg_mem_access_cmd *cmd;
+       struct iwl_dbg_mem_access_rsp *rsp;
+       struct iwl_host_cmd hcmd = {};
+       size_t cmd_size;
+       size_t data_size;
+       u32 op, len;
+       ssize_t ret;
+
+       hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
+                            DEBUG_GROUP, 0);
+
+       if (*ppos & 0x3 || count < 4) {
+               op = DEBUG_MEM_OP_WRITE_BYTES;
+               len = min(count, (size_t)(4 - (*ppos & 0x3)));
+               data_size = len;
+       } else {
+               op = DEBUG_MEM_OP_WRITE;
+               len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS);
+               data_size = len << 2;
+       }
+
+       cmd_size = sizeof(*cmd) + ALIGN(data_size, 4);
+       cmd = kzalloc(cmd_size, GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       cmd->op = cpu_to_le32(op);
+       cmd->len = cpu_to_le32(len);
+       cmd->addr = cpu_to_le32(*ppos);
+       if (copy_from_user((void *)cmd->data, user_buf, data_size)) {
+               kfree(cmd);
+               return -EFAULT;
+       }
+
+       hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
+       hcmd.data[0] = (void *)cmd;
+       hcmd.len[0] = cmd_size;
+
+       mutex_lock(&mvm->mutex);
+       ret = iwl_mvm_send_cmd(mvm, &hcmd);
+       mutex_unlock(&mvm->mutex);
+
+       kfree(cmd);
+
+       if (ret < 0)
+               return ret;
+
+       rsp = (void *)hcmd.resp_pkt->data;
+       if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
+               ret = -ENXIO;
+               goto out;
+       }
+
+       ret = data_size;
+       *ppos += ret;
+
+out:
+       iwl_free_resp(&hcmd);
+       return ret;
+}
+
+static const struct file_operations iwl_dbgfs_mem_ops = {
+       .read = iwl_dbgfs_mem_read,
+       .write = iwl_dbgfs_mem_write,
+       .open = simple_open,
+       .llseek = default_llseek,
+};
+
 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 {
        struct dentry *bcast_dir __maybe_unused;
@@ -1502,6 +1682,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
        MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR);
        MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR);
        MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR);
+       MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, S_IWUSR);
        if (!debugfs_create_bool("enable_scan_iteration_notif",
                                 S_IRUSR | S_IWUSR,
                                 mvm->debugfs_dir,
@@ -1560,6 +1741,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
                                 mvm->debugfs_dir, &mvm->nvm_phy_sku_blob))
                goto err;
 
+       debugfs_create_file("mem", S_IRUSR | S_IWUSR, dbgfs_dir, mvm,
+                           &iwl_dbgfs_mem_ops);
+
        /*
         * Create a symlink with mac80211. It will be removed when mac80211
         * exists (before the opmode exists which removes the target.)
index f01dab0..0c294c9 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -603,6 +604,8 @@ struct iwl_scan_req_umac_tail {
  * @uid: scan id, &enum iwl_umac_scan_uid_offsets
  * @ooc_priority: out of channel priority - &enum iwl_scan_priority
  * @general_flags: &enum iwl_umac_scan_general_flags
+ * @reserved2: for future use and alignment
+ * @scan_start_mac_id: report the scan start TSF time according to this mac TSF
  * @extended_dwell: dwell time for channels 1, 6 and 11
  * @active_dwell: dwell time for active scan
  * @passive_dwell: dwell time for passive scan
@@ -620,8 +623,10 @@ struct iwl_scan_req_umac {
        __le32 flags;
        __le32 uid;
        __le32 ooc_priority;
-       /* SCAN_GENERAL_PARAMS_API_S_VER_1 */
-       __le32 general_flags;
+       /* SCAN_GENERAL_PARAMS_API_S_VER_4 */
+       __le16 general_flags;
+       u8 reserved2;
+       u8 scan_start_mac_id;
        u8 extended_dwell;
        u8 active_dwell;
        u8 passive_dwell;
@@ -629,7 +634,7 @@ struct iwl_scan_req_umac {
        __le32 max_out_time;
        __le32 suspend_time;
        __le32 scan_priority;
-       /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */
+       /* SCAN_CHANNEL_PARAMS_API_S_VER_4 */
        u8 channel_flags;
        u8 n_channels;
        __le16 reserved;
@@ -718,8 +723,8 @@ struct iwl_scan_offload_profiles_query {
  * @status: one of SCAN_COMP_STATUS_*
  * @bt_status: BT on/off status
  * @last_channel: last channel that was scanned
- * @tsf_low: TSF timer (lower half) in usecs
- * @tsf_high: TSF timer (higher half) in usecs
+ * @start_tsf: TSF timer in usecs of the scan start time for the mac specified
+ *     in &struct iwl_scan_req_umac.
  * @results: array of scan results, only "scanned_channels" of them are valid
  */
 struct iwl_umac_scan_iter_complete_notif {
@@ -728,9 +733,8 @@ struct iwl_umac_scan_iter_complete_notif {
        u8 status;
        u8 bt_status;
        u8 last_channel;
-       __le32 tsf_low;
-       __le32 tsf_high;
+       __le64 start_tsf;
        struct iwl_scan_results_notif results[];
-} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_1 */
+} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_2 */
 
 #endif
index 2f92994..9763369 100644 (file)
@@ -205,7 +205,7 @@ enum {
        /* Phy */
        PHY_CONFIGURATION_CMD = 0x6a,
        CALIB_RES_NOTIF_PHY_DB = 0x6b,
-       /* PHY_DB_CMD = 0x6c, */
+       PHY_DB_CMD = 0x6c,
 
        /* ToF - 802.11mc FTM */
        TOF_CMD = 0x10,
@@ -340,6 +340,11 @@ enum iwl_prot_offload_subcmd_ids {
        STORED_BEACON_NTF = 0xFF,
 };
 
+enum iwl_fmac_debug_cmds {
+       LMAC_RD_WR = 0x0,
+       UMAC_RD_WR = 0x1,
+};
+
 /* command groups */
 enum {
        LEGACY_GROUP = 0x0,
@@ -349,6 +354,7 @@ enum {
        PHY_OPS_GROUP = 0x4,
        DATA_PATH_GROUP = 0x5,
        PROT_OFFLOAD_GROUP = 0xb,
+       DEBUG_GROUP = 0xf,
 };
 
 /**
@@ -2149,4 +2155,48 @@ struct iwl_channel_switch_noa_notif {
        __le32 id_and_color;
 } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
 
+/* Operation types for the debug mem access */
+enum {
+       DEBUG_MEM_OP_READ = 0,
+       DEBUG_MEM_OP_WRITE = 1,
+       DEBUG_MEM_OP_WRITE_BYTES = 2,
+};
+
+#define DEBUG_MEM_MAX_SIZE_DWORDS 32
+
+/**
+ * struct iwl_dbg_mem_access_cmd - Request the device to read/write memory
+ * @op: DEBUG_MEM_OP_*
+ * @addr: address to read/write from/to
+ * @len: in dwords, to read/write
+ * @data: for write opeations, contains the source buffer
+ */
+struct iwl_dbg_mem_access_cmd {
+       __le32 op;
+       __le32 addr;
+       __le32 len;
+       __le32 data[];
+} __packed; /* DEBUG_(U|L)MAC_RD_WR_CMD_API_S_VER_1 */
+
+/* Status responses for the debug mem access */
+enum {
+       DEBUG_MEM_STATUS_SUCCESS = 0x0,
+       DEBUG_MEM_STATUS_FAILED = 0x1,
+       DEBUG_MEM_STATUS_LOCKED = 0x2,
+       DEBUG_MEM_STATUS_HIDDEN = 0x3,
+       DEBUG_MEM_STATUS_LENGTH = 0x4,
+};
+
+/**
+ * struct iwl_dbg_mem_access_rsp - Response to debug mem commands
+ * @status: DEBUG_MEM_STATUS_*
+ * @len: read dwords (0 for write operations)
+ * @data: contains the read DWs
+ */
+struct iwl_dbg_mem_access_rsp {
+       __le32 status;
+       __le32 len;
+       __le32 data[];
+} __packed; /* DEBUG_(U|L)MAC_RD_WR_RSP_API_S_VER_1 */
+
 #endif /* __fw_api_h__ */
index 69c42ce..6b962d6 100644 (file)
@@ -539,6 +539,11 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                        iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
                                            IWL_MVM_OFFCHANNEL_QUEUE,
                                            IWL_MAX_TID_COUNT, 0);
+               else
+                       iwl_mvm_disable_txq(mvm,
+                                           IWL_MVM_DQA_P2P_DEVICE_QUEUE,
+                                           vif->hw_queue[0], IWL_MAX_TID_COUNT,
+                                           0);
 
                break;
        case NL80211_IFTYPE_AP:
@@ -769,26 +774,6 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
                cmd->ac[txf].fifos_mask = BIT(txf);
        }
 
-       if (vif->type == NL80211_IFTYPE_AP) {
-               /* in AP mode, the MCAST FIFO takes the EDCA params from VO */
-               cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |=
-                       BIT(IWL_MVM_TX_FIFO_MCAST);
-
-               /*
-                * in AP mode, pass probe requests and beacons from other APs
-                * (needed for ht protection); when there're no any associated
-                * station don't ask FW to pass beacons to prevent unnecessary
-                * wake-ups.
-                */
-               cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
-               if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
-                       cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
-                       IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
-               } else {
-                       IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
-               }
-       }
-
        if (vif->bss_conf.qos)
                cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
 
@@ -1186,6 +1171,7 @@ static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac,
  */
 static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
                                         struct ieee80211_vif *vif,
+                                        struct iwl_mac_ctx_cmd *cmd,
                                         struct iwl_mac_data_ap *ctxt_ap,
                                         bool add)
 {
@@ -1196,6 +1182,23 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
                .beacon_device_ts = 0
        };
 
+       /* in AP mode, the MCAST FIFO takes the EDCA params from VO */
+       cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
+
+       /*
+        * in AP mode, pass probe requests and beacons from other APs
+        * (needed for ht protection); when there're no any associated
+        * station don't ask FW to pass beacons to prevent unnecessary
+        * wake-ups.
+        */
+       cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
+       if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
+               cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
+               IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
+       } else {
+               IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
+       }
+
        ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
        ctxt_ap->bi_reciprocal =
                cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int));
@@ -1253,7 +1256,7 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
        iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
 
        /* Fill the data specific for ap mode */
-       iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
+       iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd, &cmd.ap,
                                     action == FW_CTXT_ACTION_ADD);
 
        return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
@@ -1272,7 +1275,7 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
        iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
 
        /* Fill the data specific for GO mode */
-       iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
+       iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd, &cmd.go.ap,
                                     action == FW_CTXT_ACTION_ADD);
 
        cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
index 9506e65..a5ede8c 100644 (file)
@@ -653,6 +653,16 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                        IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))
                hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES;
 
+       if (fw_has_api(&mvm->fw->ucode_capa,
+                      IWL_UCODE_TLV_API_SCAN_TSF_REPORT)) {
+               wiphy_ext_feature_set(hw->wiphy,
+                                     NL80211_EXT_FEATURE_SCAN_START_TIME);
+               wiphy_ext_feature_set(hw->wiphy,
+                                     NL80211_EXT_FEATURE_BSS_PARENT_TSF);
+               wiphy_ext_feature_set(hw->wiphy,
+                                     NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+       }
+
        mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 
 #ifdef CONFIG_PM_SLEEP
@@ -720,6 +730,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        if (ret)
                iwl_mvm_leds_exit(mvm);
 
+       if (mvm->cfg->vht_mu_mimo_supported)
+               wiphy_ext_feature_set(hw->wiphy,
+                                     NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
+
        return ret;
 }
 
@@ -2229,6 +2243,10 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
        case NL80211_IFTYPE_ADHOC:
                iwl_mvm_bss_info_changed_ap_ibss(mvm, vif, bss_conf, changes);
                break;
+       case NL80211_IFTYPE_MONITOR:
+               if (changes & BSS_CHANGED_MU_GROUPS)
+                       iwl_mvm_update_mu_groups(mvm, vif);
+               break;
        default:
                /* shouldn't happen */
                WARN_ON_ONCE(1);
index 83f3889..b7cfdcb 100644 (file)
@@ -821,6 +821,12 @@ struct iwl_mvm {
        /* UMAC scan tracking */
        u32 scan_uid_status[IWL_MVM_MAX_UMAC_SCANS];
 
+       /* start time of last scan in TSF of the mac that requested the scan */
+       u64 scan_start;
+
+       /* the vif that requested the current scan */
+       struct iwl_mvm_vif *scan_vif;
+
        /* rx chain antennas set through debugfs for the scan command */
        u8 scan_rx_ant;
 
@@ -1262,6 +1268,7 @@ u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
 void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
 u8 first_antenna(u8 mask);
 u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
+void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime);
 
 /* Tx / Host Commands */
 int __must_check iwl_mvm_send_cmd(struct iwl_mvm *mvm,
index 7a686f6..eade099 100644 (file)
@@ -66,7 +66,6 @@
  *****************************************************************************/
 #include <linux/firmware.h>
 #include <linux/rtnetlink.h>
-#include <linux/acpi.h>
 #include "iwl-trans.h"
 #include "iwl-csr.h"
 #include "mvm.h"
@@ -751,96 +750,6 @@ exit:
        return resp_cp;
 }
 
-#ifdef CONFIG_ACPI
-#define WRD_METHOD             "WRDD"
-#define WRDD_WIFI              (0x07)
-#define WRDD_WIGIG             (0x10)
-
-static u32 iwl_mvm_wrdd_get_mcc(struct iwl_mvm *mvm, union acpi_object *wrdd)
-{
-       union acpi_object *mcc_pkg, *domain_type, *mcc_value;
-       u32 i;
-
-       if (wrdd->type != ACPI_TYPE_PACKAGE ||
-           wrdd->package.count < 2 ||
-           wrdd->package.elements[0].type != ACPI_TYPE_INTEGER ||
-           wrdd->package.elements[0].integer.value != 0) {
-               IWL_DEBUG_LAR(mvm, "Unsupported wrdd structure\n");
-               return 0;
-       }
-
-       for (i = 1 ; i < wrdd->package.count ; ++i) {
-               mcc_pkg = &wrdd->package.elements[i];
-
-               if (mcc_pkg->type != ACPI_TYPE_PACKAGE ||
-                   mcc_pkg->package.count < 2 ||
-                   mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
-                   mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
-                       mcc_pkg = NULL;
-                       continue;
-               }
-
-               domain_type = &mcc_pkg->package.elements[0];
-               if (domain_type->integer.value == WRDD_WIFI)
-                       break;
-
-               mcc_pkg = NULL;
-       }
-
-       if (mcc_pkg) {
-               mcc_value = &mcc_pkg->package.elements[1];
-               return mcc_value->integer.value;
-       }
-
-       return 0;
-}
-
-static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc)
-{
-       acpi_handle root_handle;
-       acpi_handle handle;
-       struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
-       acpi_status status;
-       u32 mcc_val;
-
-       root_handle = ACPI_HANDLE(mvm->dev);
-       if (!root_handle) {
-               IWL_DEBUG_LAR(mvm,
-                             "Could not retrieve root port ACPI handle\n");
-               return -ENOENT;
-       }
-
-       /* Get the method's handle */
-       status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle);
-       if (ACPI_FAILURE(status)) {
-               IWL_DEBUG_LAR(mvm, "WRD method not found\n");
-               return -ENOENT;
-       }
-
-       /* Call WRDD with no arguments */
-       status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
-       if (ACPI_FAILURE(status)) {
-               IWL_DEBUG_LAR(mvm, "WRDC invocation failed (0x%x)\n", status);
-               return -ENOENT;
-       }
-
-       mcc_val = iwl_mvm_wrdd_get_mcc(mvm, wrdd.pointer);
-       kfree(wrdd.pointer);
-       if (!mcc_val)
-               return -ENOENT;
-
-       mcc[0] = (mcc_val >> 8) & 0xff;
-       mcc[1] = mcc_val & 0xff;
-       mcc[2] = '\0';
-       return 0;
-}
-#else /* CONFIG_ACPI */
-static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc)
-{
-       return -ENOENT;
-}
-#endif
-
 int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
 {
        bool tlv_lar;
@@ -884,7 +793,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
                return -EIO;
 
        if (iwl_mvm_is_wifi_mcc_supported(mvm) &&
-           !iwl_mvm_get_bios_mcc(mvm, mcc)) {
+           !iwl_get_bios_mcc(mvm->dev, mcc)) {
                kfree(regd);
                regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc,
                                             MCC_SOURCE_BIOS, NULL);
index 43ea1e5..75f3ca0 100644 (file)
@@ -359,6 +359,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
        HCMD_NAME(BT_COEX_CI),
        HCMD_NAME(PHY_CONFIGURATION_CMD),
        HCMD_NAME(CALIB_RES_NOTIF_PHY_DB),
+       HCMD_NAME(PHY_DB_CMD),
        HCMD_NAME(SCAN_OFFLOAD_COMPLETE),
        HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
        HCMD_NAME(SCAN_OFFLOAD_CONFIG_CMD),
@@ -652,8 +653,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        /* the hardware splits the A-MSDU */
        if (mvm->cfg->mq_rx_supported)
                trans_cfg.rx_buf_size = IWL_AMSDU_4K;
-       trans_cfg.wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
-                                              IWL_UCODE_TLV_API_WIDE_CMD_HDR);
+       trans->wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
+                                           IWL_UCODE_TLV_API_WIDE_CMD_HDR);
 
        if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE)
                trans_cfg.bc_table_dword = true;
@@ -857,9 +858,7 @@ static void iwl_mvm_async_handlers_wk(struct work_struct *wk)
        struct iwl_mvm *mvm =
                container_of(wk, struct iwl_mvm, async_handlers_wk);
        struct iwl_async_handler_entry *entry, *tmp;
-       struct list_head local_list;
-
-       INIT_LIST_HEAD(&local_list);
+       LIST_HEAD(local_list);
 
        /* Ensure that we are not in stop flow (check iwl_mvm_mac_stop) */
 
@@ -966,10 +965,11 @@ static void iwl_mvm_rx(struct iwl_op_mode *op_mode,
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+       u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
 
-       if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
+       if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
                iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
-       else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
+       else if (cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_PHY_CMD))
                iwl_mvm_rx_rx_phy_cmd(mvm, rxb);
        else
                iwl_mvm_rx_common(mvm, rxb, pkt);
@@ -981,13 +981,14 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+       u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
 
-       if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
+       if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
                iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0);
-       else if (unlikely(pkt->hdr.group_id == DATA_PATH_GROUP &&
-                         pkt->hdr.cmd == RX_QUEUES_NOTIFICATION))
+       else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
+                                        RX_QUEUES_NOTIFICATION)))
                iwl_mvm_rx_queue_notif(mvm, rxb, 0);
-       else if (pkt->hdr.cmd == FRAME_RELEASE)
+       else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
                iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
        else
                iwl_mvm_rx_common(mvm, rxb, pkt);
@@ -1666,13 +1667,14 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
 {
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
 
-       if (unlikely(pkt->hdr.cmd == FRAME_RELEASE))
+       if (unlikely(cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE)))
                iwl_mvm_rx_frame_release(mvm, napi, rxb, queue);
-       else if (unlikely(pkt->hdr.cmd == RX_QUEUES_NOTIFICATION &&
-                         pkt->hdr.group_id == DATA_PATH_GROUP))
+       else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
+                                        RX_QUEUES_NOTIFICATION)))
                iwl_mvm_rx_queue_notif(mvm, rxb, queue);
-       else if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
+       else if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
                iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, queue);
 }
 
index d6d9ec4..a57c6ef 100644 (file)
@@ -418,10 +418,11 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
 
                ssn = ieee80211_sn_inc(ssn);
 
-               /* holes are valid since nssn indicates frames were received. */
-               if (skb_queue_empty(skb_list) || !skb_peek_tail(skb_list))
-                       continue;
-               /* Empty the list. Will have more than one frame for A-MSDU */
+               /*
+                * Empty the list. Will have more than one frame for A-MSDU.
+                * Empty list is valid as well since nssn indicates frames were
+                * received.
+                */
                while ((skb = __skb_dequeue(skb_list))) {
                        iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
                                                        reorder_buf->queue,
@@ -434,7 +435,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
        if (reorder_buf->num_stored && !reorder_buf->removed) {
                u16 index = reorder_buf->head_sn % reorder_buf->buf_size;
 
-               while (!skb_peek_tail(&reorder_buf->entries[index]))
+               while (skb_queue_empty(&reorder_buf->entries[index]))
                        index = (index + 1) % reorder_buf->buf_size;
                /* modify timer to match next frame's expiration time */
                mod_timer(&reorder_buf->reorder_timer,
@@ -462,7 +463,7 @@ void iwl_mvm_reorder_timer_expired(unsigned long data)
        for (i = 0; i < buf->buf_size ; i++) {
                index = (buf->head_sn + i) % buf->buf_size;
 
-               if (!skb_peek_tail(&buf->entries[index]))
+               if (skb_queue_empty(&buf->entries[index]))
                        continue;
                if (!time_after(jiffies, buf->reorder_time[index] +
                                RX_REORDER_BUF_TIMEOUT_MQ))
@@ -590,6 +591,11 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
        baid = (reorder & IWL_RX_MPDU_REORDER_BAID_MASK) >>
                IWL_RX_MPDU_REORDER_BAID_SHIFT;
 
+       /*
+        * This also covers the case of receiving a Block Ack Request
+        * outside a BA session; we'll pass it to mac80211 and that
+        * then sends a delBA action frame.
+        */
        if (baid == IWL_RX_REORDER_DATA_INVALID_BAID)
                return false;
 
@@ -599,9 +605,10 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
 
        mvm_sta = iwl_mvm_sta_from_mac80211(sta);
 
-       /* not a data packet */
-       if (!ieee80211_is_data_qos(hdr->frame_control) ||
-           is_multicast_ether_addr(hdr->addr1))
+       /* not a data packet or a bar */
+       if (!ieee80211_is_back_req(hdr->frame_control) &&
+           (!ieee80211_is_data_qos(hdr->frame_control) ||
+            is_multicast_ether_addr(hdr->addr1)))
                return false;
 
        if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
@@ -625,6 +632,11 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
 
        spin_lock_bh(&buffer->lock);
 
+       if (ieee80211_is_back_req(hdr->frame_control)) {
+               iwl_mvm_release_frames(mvm, sta, napi, buffer, nssn);
+               goto drop;
+       }
+
        /*
         * If there was a significant jump in the nssn - adjust.
         * If the SN is smaller than the NSSN it might need to first go into
index dac120f..00b03fc 100644 (file)
@@ -141,6 +141,7 @@ struct iwl_mvm_scan_params {
        struct cfg80211_match_set *match_sets;
        int n_scan_plans;
        struct cfg80211_sched_scan_plan *scan_plans;
+       u32 measurement_dwell;
 };
 
 static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
@@ -232,6 +233,27 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
        return IWL_SCAN_TYPE_WILD;
 }
 
+static int
+iwl_mvm_get_measurement_dwell(struct iwl_mvm *mvm,
+                             struct cfg80211_scan_request *req,
+                             struct iwl_mvm_scan_params *params)
+{
+       if (!req->duration)
+               return 0;
+
+       if (req->duration_mandatory &&
+           req->duration > scan_timing[params->type].max_out_time) {
+               IWL_DEBUG_SCAN(mvm,
+                              "Measurement scan - too long dwell %hu (max out time %u)\n",
+                              req->duration,
+                              scan_timing[params->type].max_out_time);
+               return -EOPNOTSUPP;
+       }
+
+       return min_t(u32, (u32)req->duration,
+                    scan_timing[params->type].max_out_time);
+}
+
 static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm)
 {
        /* require rrm scan whenever the fw supports it */
@@ -1033,9 +1055,15 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
                                    struct iwl_scan_req_umac *cmd,
                                    struct iwl_mvm_scan_params *params)
 {
-       cmd->extended_dwell = scan_timing[params->type].dwell_extended;
-       cmd->active_dwell = scan_timing[params->type].dwell_active;
-       cmd->passive_dwell = scan_timing[params->type].dwell_passive;
+       if (params->measurement_dwell) {
+               cmd->active_dwell = params->measurement_dwell;
+               cmd->passive_dwell = params->measurement_dwell;
+               cmd->extended_dwell = params->measurement_dwell;
+       } else {
+               cmd->active_dwell = scan_timing[params->type].dwell_active;
+               cmd->passive_dwell = scan_timing[params->type].dwell_passive;
+               cmd->extended_dwell = scan_timing[params->type].dwell_extended;
+       }
        cmd->fragmented_dwell = scan_timing[params->type].dwell_fragmented;
        cmd->max_out_time = cpu_to_le32(scan_timing[params->type].max_out_time);
        cmd->suspend_time = cpu_to_le32(scan_timing[params->type].suspend_time);
@@ -1067,11 +1095,11 @@ iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
        }
 }
 
-static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
+static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
                                   struct iwl_mvm_scan_params *params,
                                   struct ieee80211_vif *vif)
 {
-       int flags = 0;
+       u16 flags = 0;
 
        if (params->n_ssids == 0)
                flags = IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE;
@@ -1093,6 +1121,9 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
        if (!iwl_mvm_is_regular_scan(params))
                flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
 
+       if (params->measurement_dwell)
+               flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        if (mvm->scan_iter_notif_enabled)
                flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
@@ -1119,6 +1150,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                        mvm->fw->ucode_capa.n_scan_channels;
        int uid, i;
        u32 ssid_bitmap = 0;
+       struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
 
        lockdep_assert_held(&mvm->mutex);
 
@@ -1136,8 +1168,9 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        mvm->scan_uid_status[uid] = type;
 
        cmd->uid = cpu_to_le32(uid);
-       cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params,
+       cmd->general_flags = cpu_to_le16(iwl_mvm_scan_umac_flags(mvm, params,
                                                                 vif));
+       cmd->scan_start_mac_id = scan_vif->id;
 
        if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT)
                cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
@@ -1289,6 +1322,12 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                iwl_mvm_get_scan_type(mvm,
                                      vif->type == NL80211_IFTYPE_P2P_DEVICE);
 
+       ret = iwl_mvm_get_measurement_dwell(mvm, req, &params);
+       if (ret < 0)
+               return ret;
+
+       params.measurement_dwell = ret;
+
        iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
 
        if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
@@ -1315,6 +1354,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
        mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
+       mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
        iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
 
        queue_delayed_work(system_wq, &mvm->scan_timeout_dwork,
@@ -1437,9 +1477,12 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
        if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {
                struct cfg80211_scan_info info = {
                        .aborted = aborted,
+                       .scan_start_tsf = mvm->scan_start,
                };
 
+               memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN);
                ieee80211_scan_completed(mvm->hw, &info);
+               mvm->scan_vif = NULL;
                iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
                cancel_delayed_work(&mvm->scan_timeout_dwork);
        } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
@@ -1473,6 +1516,8 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
        struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data;
        u8 buf[256];
 
+       mvm->scan_start = le64_to_cpu(notif->start_tsf);
+
        IWL_DEBUG_SCAN(mvm,
                       "UMAC Scan iteration complete: status=0x%x scanned_channels=%d channels list: %s\n",
                       notif->status, notif->scanned_channels,
@@ -1485,6 +1530,10 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
                ieee80211_sched_scan_results(mvm->hw);
                mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;
        }
+
+       IWL_DEBUG_SCAN(mvm,
+                      "UMAC Scan iteration complete: scan started at %llu (TSF)\n",
+                      mvm->scan_start);
 }
 
 static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type)
index 216aa54..258a234 100644 (file)
@@ -745,14 +745,14 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
                        .scd_queue = queue,
                        .action = SCD_CFG_DISABLE_QUEUE,
                };
-               u8 ac;
+               u8 txq_curr_ac;
 
                disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
 
                spin_lock_bh(&mvm->queue_info_lock);
-               ac = mvm->queue_info[queue].mac80211_ac;
+               txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
                cmd.sta_id = mvm->queue_info[queue].ra_sta_id;
-               cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[ac];
+               cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[txq_curr_ac];
                cmd.tid = mvm->queue_info[queue].txq_tid;
                spin_unlock_bh(&mvm->queue_info_lock);
 
@@ -1297,13 +1297,6 @@ err:
        return ret;
 }
 
-int iwl_mvm_update_sta(struct iwl_mvm *mvm,
-                      struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta)
-{
-       return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
-}
-
 int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
                      bool drain)
 {
index 709542b..e068d53 100644 (file)
@@ -473,9 +473,14 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 int iwl_mvm_add_sta(struct iwl_mvm *mvm,
                    struct ieee80211_vif *vif,
                    struct ieee80211_sta *sta);
-int iwl_mvm_update_sta(struct iwl_mvm *mvm,
-                      struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta);
+
+static inline int iwl_mvm_update_sta(struct iwl_mvm *mvm,
+                                    struct ieee80211_vif *vif,
+                                    struct ieee80211_sta *sta)
+{
+       return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
+}
+
 int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
                   struct ieee80211_vif *vif,
                   struct ieee80211_sta *sta);
index 1051777..e0c9065 100644 (file)
@@ -490,16 +490,34 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
 static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
                                      struct ieee80211_tx_info *info, __le16 fc)
 {
-       if (iwl_mvm_is_dqa_supported(mvm)) {
-               if (info->control.vif->type == NL80211_IFTYPE_AP &&
-                   ieee80211_is_probe_resp(fc))
+       if (!iwl_mvm_is_dqa_supported(mvm))
+               return info->hw_queue;
+
+       switch (info->control.vif->type) {
+       case NL80211_IFTYPE_AP:
+               /*
+                * handle legacy hostapd as well, where station may be added
+                * only after assoc.
+                */
+               if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc))
                        return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
-               else if (ieee80211_is_mgmt(fc) &&
-                        info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE)
+               if (info->hw_queue == info->control.vif->cab_queue)
+                       return info->hw_queue;
+
+               WARN_ON_ONCE(1);
+               return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
+       case NL80211_IFTYPE_P2P_DEVICE:
+               if (ieee80211_is_mgmt(fc))
                        return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
-       }
+               if (info->hw_queue == info->control.vif->cab_queue)
+                       return info->hw_queue;
 
-       return info->hw_queue;
+               WARN_ON_ONCE(1);
+               return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
+       default:
+               WARN_ONCE(1, "Not a ctrl vif, no available queue\n");
+               return -1;
+       }
 }
 
 int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
@@ -560,6 +578,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
                        sta_id = mvmvif->bcast_sta.sta_id;
                        queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info,
                                                           hdr->frame_control);
+                       if (queue < 0)
+                               return -1;
+
                } else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
                           is_multicast_ether_addr(hdr->addr1)) {
                        u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id);
index 7c138fe..9e366e2 100644 (file)
@@ -1225,6 +1225,28 @@ void iwl_mvm_inactivity_check(struct iwl_mvm *mvm)
        rcu_read_unlock();
 }
 
+void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime)
+{
+       bool ps_disabled;
+
+       lockdep_assert_held(&mvm->mutex);
+
+       /* Disable power save when reading GP2 */
+       ps_disabled = mvm->ps_disabled;
+       if (!ps_disabled) {
+               mvm->ps_disabled = true;
+               iwl_mvm_power_update_device(mvm);
+       }
+
+       *gp2 = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
+       *boottime = ktime_get_boot_ns();
+
+       if (!ps_disabled) {
+               mvm->ps_disabled = ps_disabled;
+               iwl_mvm_power_update_device(mvm);
+       }
+}
+
 int iwl_mvm_send_lqm_cmd(struct ieee80211_vif *vif,
                         enum iwl_lqm_cmd_operatrions operation,
                         u32 duration, u32 timeout)
index 14c6e94..3d766f2 100644 (file)
@@ -487,6 +487,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x24FD, 0x1130, iwl8265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x24FD, 0x0130, iwl8265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x24FD, 0x1010, iwl8265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x24FD, 0x10D0, iwl8265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x24FD, 0x0050, iwl8265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x24FD, 0x0150, iwl8265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x24FD, 0x9010, iwl8265_2ac_cfg)},
index 987a077..2d81630 100644 (file)
@@ -332,7 +332,6 @@ enum iwl_shared_irq_flags {
  * @rx_buf_size: Rx buffer size
  * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
  * @scd_set_active: should the transport configure the SCD for HCMD queue
- * @wide_cmd_header: true when ucode supports wide command header format
  * @sw_csum_tx: if true, then the transport will compute the csum of the TXed
  *     frame.
  * @rx_page_order: page order for receive buffer size
@@ -405,7 +404,6 @@ struct iwl_trans_pcie {
        enum iwl_amsdu_size rx_buf_size;
        bool bc_table_dword;
        bool scd_set_active;
-       bool wide_cmd_header;
        bool sw_csum_tx;
        u32 rx_page_order;
 
index 0b5b331..6fe5546 100644 (file)
@@ -487,15 +487,13 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
 
        while (pending) {
                int i;
-               struct list_head local_allocated;
+               LIST_HEAD(local_allocated);
                gfp_t gfp_mask = GFP_KERNEL;
 
                /* Do not post a warning if there are only a few requests */
                if (pending < RX_PENDING_WATERMARK)
                        gfp_mask |= __GFP_NOWARN;
 
-               INIT_LIST_HEAD(&local_allocated);
-
                for (i = 0; i < RX_CLAIM_REQ_ALLOC;) {
                        struct iwl_rx_mem_buffer *rxb;
                        struct page *page;
@@ -1108,13 +1106,14 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
                        FH_RSCSR_RXQ_POS != rxq->id);
 
                IWL_DEBUG_RX(trans,
-                            "cmd at offset %d: %s (0x%.2x, seq 0x%x)\n",
+                            "cmd at offset %d: %s (%.2x.%2x, seq 0x%x)\n",
                             rxcb._offset,
                             iwl_get_cmd_string(trans,
                                                iwl_cmd_id(pkt->hdr.cmd,
                                                           pkt->hdr.group_id,
                                                           0)),
-                            pkt->hdr.cmd, le16_to_cpu(pkt->hdr.sequence));
+                            pkt->hdr.group_id, pkt->hdr.cmd,
+                            le16_to_cpu(pkt->hdr.sequence));
 
                len = iwl_rx_packet_len(pkt);
                len += sizeof(u32); /* account for status word */
index 188b0de..ae95533 100644 (file)
@@ -1605,24 +1605,22 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
 
        for (i = 0; i < trans_pcie->alloc_vecs; i++) {
                int ret;
-
-               ret = request_threaded_irq(trans_pcie->msix_entries[i].vector,
-                                          iwl_pcie_msix_isr,
-                                          (i == trans_pcie->def_irq) ?
-                                          iwl_pcie_irq_msix_handler :
-                                          iwl_pcie_irq_rx_msix_handler,
-                                          IRQF_SHARED,
-                                          DRV_NAME,
-                                          &trans_pcie->msix_entries[i]);
+               struct msix_entry *msix_entry;
+
+               msix_entry = &trans_pcie->msix_entries[i];
+               ret = devm_request_threaded_irq(&pdev->dev,
+                                               msix_entry->vector,
+                                               iwl_pcie_msix_isr,
+                                               (i == trans_pcie->def_irq) ?
+                                               iwl_pcie_irq_msix_handler :
+                                               iwl_pcie_irq_rx_msix_handler,
+                                               IRQF_SHARED,
+                                               DRV_NAME,
+                                               msix_entry);
                if (ret) {
-                       int j;
-
                        IWL_ERR(trans_pcie->trans,
                                "Error allocating IRQ %d\n", i);
-                       for (j = 0; j < i; j++)
-                               free_irq(trans_pcie->msix_entries[j].vector,
-                                        &trans_pcie->msix_entries[j]);
-                       pci_disable_msix(pdev);
+
                        return ret;
                }
        }
@@ -1755,7 +1753,6 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
        trans_pcie->rx_page_order =
                iwl_trans_get_rb_size_order(trans_pcie->rx_buf_size);
 
-       trans_pcie->wide_cmd_header = trans_cfg->wide_cmd_header;
        trans_pcie->bc_table_dword = trans_cfg->bc_table_dword;
        trans_pcie->scd_set_active = trans_cfg->scd_set_active;
        trans_pcie->sw_csum_tx = trans_cfg->sw_csum_tx;
@@ -1790,23 +1787,12 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
                        irq_set_affinity_hint(
                                trans_pcie->msix_entries[i].vector,
                                NULL);
-
-                       free_irq(trans_pcie->msix_entries[i].vector,
-                                &trans_pcie->msix_entries[i]);
                }
 
-               pci_disable_msix(trans_pcie->pci_dev);
                trans_pcie->msix_enabled = false;
        } else {
-               free_irq(trans_pcie->pci_dev->irq, trans);
-
                iwl_pcie_free_ict(trans);
-
-               pci_disable_msi(trans_pcie->pci_dev);
        }
-       iounmap(trans_pcie->hw_base);
-       pci_release_regions(trans_pcie->pci_dev);
-       pci_disable_device(trans_pcie->pci_dev);
 
        iwl_pcie_free_fw_monitor(trans);
 
@@ -2913,6 +2899,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        struct iwl_trans *trans;
        int ret, addr_size;
 
+       ret = pcim_enable_device(pdev);
+       if (ret)
+               return ERR_PTR(ret);
+
        trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
                                &pdev->dev, cfg, &trans_ops_pcie, 0);
        if (!trans)
@@ -2931,9 +2921,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                goto out_no_pci;
        }
 
-       ret = pci_enable_device(pdev);
-       if (ret)
-               goto out_no_pci;
 
        if (!cfg->base_params->pcie_l1_allowed) {
                /*
@@ -2953,7 +2940,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 
        if (cfg->use_tfh) {
                trans_pcie->max_tbs = IWL_TFH_NUM_TBS;
-               trans_pcie->tfd_size = sizeof(struct iwl_tfh_tb);
+               trans_pcie->tfd_size = sizeof(struct iwl_tfh_tfd);
 
        } else {
                trans_pcie->max_tbs = IWL_NUM_OF_TBS;
@@ -2975,21 +2962,21 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                /* both attempts failed: */
                if (ret) {
                        dev_err(&pdev->dev, "No suitable DMA available\n");
-                       goto out_pci_disable_device;
+                       goto out_no_pci;
                }
        }
 
-       ret = pci_request_regions(pdev, DRV_NAME);
+       ret = pcim_iomap_regions_request_all(pdev, BIT(0), DRV_NAME);
        if (ret) {
-               dev_err(&pdev->dev, "pci_request_regions failed\n");
-               goto out_pci_disable_device;
+               dev_err(&pdev->dev, "pcim_iomap_regions_request_all failed\n");
+               goto out_no_pci;
        }
 
-       trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
+       trans_pcie->hw_base = pcim_iomap_table(pdev)[0];
        if (!trans_pcie->hw_base) {
-               dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
+               dev_err(&pdev->dev, "pcim_iomap_table failed\n");
                ret = -ENODEV;
-               goto out_pci_release_regions;
+               goto out_no_pci;
        }
 
        /* We disable the RETRY_TIMEOUT register (0x41) to keep
@@ -3016,7 +3003,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                ret = iwl_pcie_prepare_card_hw(trans);
                if (ret) {
                        IWL_WARN(trans, "Exit HW not ready\n");
-                       goto out_pci_disable_msi;
+                       goto out_no_pci;
                }
 
                /*
@@ -3033,7 +3020,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                                   25000);
                if (ret < 0) {
                        IWL_DEBUG_INFO(trans, "Failed to wake up the nic\n");
-                       goto out_pci_disable_msi;
+                       goto out_no_pci;
                }
 
                if (iwl_trans_grab_nic_access(trans, &flags)) {
@@ -3065,15 +3052,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 
        if (trans_pcie->msix_enabled) {
                if (iwl_pcie_init_msix_handler(pdev, trans_pcie))
-                       goto out_pci_release_regions;
+                       goto out_no_pci;
         } else {
                ret = iwl_pcie_alloc_ict(trans);
                if (ret)
-                       goto out_pci_disable_msi;
+                       goto out_no_pci;
 
-               ret = request_threaded_irq(pdev->irq, iwl_pcie_isr,
-                                          iwl_pcie_irq_handler,
-                                          IRQF_SHARED, DRV_NAME, trans);
+               ret = devm_request_threaded_irq(&pdev->dev, pdev->irq,
+                                               iwl_pcie_isr,
+                                               iwl_pcie_irq_handler,
+                                               IRQF_SHARED, DRV_NAME, trans);
                if (ret) {
                        IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq);
                        goto out_free_ict;
@@ -3091,12 +3079,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 
 out_free_ict:
        iwl_pcie_free_ict(trans);
-out_pci_disable_msi:
-       pci_disable_msi(pdev);
-out_pci_release_regions:
-       pci_release_regions(pdev);
-out_pci_disable_device:
-       pci_disable_device(pdev);
 out_no_pci:
        free_percpu(trans_pcie->tso_hdr_page);
        iwl_trans_free(trans);
index 0d156fd..e00e7d8 100644 (file)
@@ -1493,7 +1493,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
        u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
 
-       if (WARN(!trans_pcie->wide_cmd_header &&
+       if (WARN(!trans->wide_cmd_header &&
                 group_id > IWL_ALWAYS_LONG_GROUP,
                 "unsupported wide command %#x\n", cmd->id))
                return -EINVAL;