iwlwifi: mvm: don't use hardcoded num of scan channels
authorDavid Spinadel <david.spinadel@intel.com>
Thu, 5 Jun 2014 08:20:43 +0000 (11:20 +0300)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 24 Jun 2014 18:55:24 +0000 (21:55 +0300)
Use num of scan channels as advertised by fw TLV.

Signed-off-by: David Spinadel <david.spinadel@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-fw-file.h
drivers/net/wireless/iwlwifi/iwl-fw.h
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/scan.c

index f2a5c12269a3ed7de811399580c9ea908bc89173..bf584d3fe8ec0ec2c55dc63fb097a3f8f2a31332 100644 (file)
@@ -155,6 +155,8 @@ static struct iwlwifi_opmode_table {
        [MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL },
 };
 
+#define IWL_DEFAULT_SCAN_CHANNELS 40
+
 /*
  * struct fw_sec: Just for the image parsing proccess.
  * For the fw storage we are using struct fw_desc.
@@ -819,6 +821,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                        if (iwl_store_cscheme(&drv->fw, tlv_data, tlv_len))
                                goto invalid_tlv_len;
                        break;
+               case IWL_UCODE_TLV_N_SCAN_CHANNELS:
+                       if (tlv_len != sizeof(u32))
+                               goto invalid_tlv_len;
+                       capa->n_scan_channels =
+                               le32_to_cpup((__le32 *)tlv_data);
+                       break;
                default:
                        IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
                        break;
@@ -973,6 +981,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
        fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
        fw->ucode_capa.standard_phy_calibration_size =
                        IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+       fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
 
        if (!api_ok)
                api_ok = api_max;
index b45e576a4b57feb01982edb99191a65a3ae38bca..9e6ba1e7fd21dc92e56c73fd17368f4b1fb067c5 100644 (file)
@@ -128,6 +128,7 @@ enum iwl_ucode_tlv_type {
        IWL_UCODE_TLV_CSCHEME           = 28,
        IWL_UCODE_TLV_API_CHANGES_SET   = 29,
        IWL_UCODE_TLV_ENABLED_CAPABILITIES      = 30,
+       IWL_UCODE_TLV_N_SCAN_CHANNELS           = 31,
 };
 
 struct iwl_ucode_tlv {
index 0aa7c0085c9fd04554b1a3314a2212638f920a78..de975cd4d73a862e3602286029b5376b856448d0 100644 (file)
@@ -178,6 +178,7 @@ enum iwl_ucode_sec {
 
 struct iwl_ucode_capabilities {
        u32 max_probe_length;
+       u32 n_scan_channels;
        u32 standard_phy_calibration_size;
        u32 flags;
        u32 api[IWL_API_ARRAY_SIZE];
index 6959fda3fe09d09e34d5fe19c7ded403fba79c37..1d586923d5b767c0aaaf34b09705c835829d4082 100644 (file)
@@ -169,19 +169,13 @@ enum iwl_scan_type {
        SCAN_TYPE_DISCOVERY_FORCED      = 6,
 }; /* SCAN_ACTIVITY_TYPE_E_VER_1 */
 
-/**
- * Maximal number of channels to scan
- * it should be equal to:
- * max(IWL_NUM_CHANNELS, IWL_NUM_CHANNELS_FAMILY_8000)
- */
-#define MAX_NUM_SCAN_CHANNELS 50
-
 /**
  * struct iwl_scan_cmd - scan request command
  * ( SCAN_REQUEST_CMD = 0x80 )
  * @len: command length in bytes
  * @scan_flags: scan flags from SCAN_FLAGS_*
- * @channel_count: num of channels in channel list (1 - MAX_NUM_SCAN_CHANNELS)
+ * @channel_count: num of channels in channel list
+ *     (1 - ucode_capa.n_scan_channels)
  * @quiet_time: in msecs, dwell this time for active scan on quiet channels
  * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
  *     this number of packets were received (typically 1)
@@ -345,7 +339,7 @@ struct iwl_scan_results_notif {
  * @last_channel: last channel that was scanned
  * @tsf_low: TSF timer (lower half) in usecs
  * @tsf_high: TSF timer (higher half) in usecs
- * @results: all scan results, only "scanned_channels" of them are valid
+ * @results: array of scan results, only "scanned_channels" of them are valid
  */
 struct iwl_scan_complete_notif {
        u8 scanned_channels;
@@ -354,11 +348,10 @@ struct iwl_scan_complete_notif {
        u8 last_channel;
        __le32 tsf_low;
        __le32 tsf_high;
-       struct iwl_scan_results_notif results[MAX_NUM_SCAN_CHANNELS];
+       struct iwl_scan_results_notif results[];
 } __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */
 
 /* scan offload */
-#define IWL_MAX_SCAN_CHANNELS          40
 #define IWL_SCAN_MAX_BLACKLIST_LEN     64
 #define IWL_SCAN_SHORT_BLACKLIST_LEN   16
 #define IWL_SCAN_MAX_PROFILES          11
@@ -423,36 +416,24 @@ enum iwl_scan_offload_channel_flags {
        IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL        = BIT(25),
 };
 
-/**
- * iwl_scan_channel_cfg - SCAN_CHANNEL_CFG_S
- * @type:              bitmap - see enum iwl_scan_offload_channel_flags.
- *                     0:      passive (0) or active (1) scan.
- *                     1-20:   directed scan to i'th ssid.
- *                     22:     channel width configuation - 1 for narrow.
- *                     24:     full scan.
- *                     25:     partial scan.
- * @channel_number:    channel number 1-13 etc.
- * @iter_count:                repetition count for the channel.
- * @iter_interval:     interval between two innteration on one channel.
- * @dwell_time:        entry 0 - active scan, entry 1 - passive scan.
+/* channel configuration for struct iwl_scan_offload_cfg. Each channels needs:
+ * __le32 type:        bitmap; bits 1-20 are for directed scan to i'th ssid and
+ *     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.
+ * u8 active_dwell.
+ * u8 passive_dwell.
  */
-struct iwl_scan_channel_cfg {
-       __le32 type[IWL_MAX_SCAN_CHANNELS];
-       __le16 channel_number[IWL_MAX_SCAN_CHANNELS];
-       __le16 iter_count[IWL_MAX_SCAN_CHANNELS];
-       __le32 iter_interval[IWL_MAX_SCAN_CHANNELS];
-       u8 dwell_time[IWL_MAX_SCAN_CHANNELS][2];
-} __packed;
+#define IWL_SCAN_CHAN_SIZE 14
 
 /**
  * iwl_scan_offload_cfg - SCAN_OFFLOAD_CONFIG_API_S
  * @scan_cmd:          scan command fixed part
- * @channel_cfg:       scan channel configuration
- * @data:              probe request frames (one per band)
+ * @data:              scan channel configuration and probe request frames
  */
 struct iwl_scan_offload_cfg {
        struct iwl_scan_offload_cmd scan_cmd;
-       struct iwl_scan_channel_cfg channel_cfg;
        u8 data[0];
 } __packed;
 
index 41c0aace3e8494e82d1a245b1cfb27223d5d9d2c..f22be88c038740d3d1790f2061ee61ca9f77bc2f 100644 (file)
@@ -1543,7 +1543,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        int ret;
 
-       if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS)
+       if (req->n_channels == 0 ||
+           req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
                return -EINVAL;
 
        mutex_lock(&mvm->mutex);
index cc2f7de396deb396d2b20e261b4c2877137dfa3e..a46f0289a3c1e1ef81585f160533e702ab82f85c 100644 (file)
@@ -504,7 +504,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
        scan_size = sizeof(struct iwl_scan_cmd) +
                mvm->fw->ucode_capa.max_probe_length +
-               (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel));
+               (mvm->fw->ucode_capa.n_scan_channels *
+                                       sizeof(struct iwl_scan_channel));
        mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL);
        if (!mvm->scan_cmd)
                goto out_free;
index 40c112f136dc519cd8a7fda5595dc309106d1309..349d8e67118b3108e95a4ebc10e582114e882526 100644 (file)
@@ -666,12 +666,19 @@ static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req,
 
 static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
                                  struct cfg80211_sched_scan_request *req,
-                                 struct iwl_scan_channel_cfg *channels,
+                                 u8 *channels_buffer,
                                  enum ieee80211_band band,
                                  int *head,
                                  u32 ssid_bitmap,
                                  struct iwl_mvm_scan_params *params)
 {
+       u32 n_channels = mvm->fw->ucode_capa.n_scan_channels;
+       __le32 *type = (__le32 *)channels_buffer;
+       __le16 *channel_number = (__le16 *)(type + n_channels);
+       __le16 *iter_count = channel_number + n_channels;
+       __le32 *iter_interval = (__le32 *)(iter_count + n_channels);
+       u8 *active_dwell = (u8 *)(iter_interval + n_channels);
+       u8 *passive_dwell = active_dwell + n_channels;
        int i, index = 0;
 
        for (i = 0; i < req->n_channels; i++) {
@@ -683,27 +690,26 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
                index = *head;
                (*head)++;
 
-               channels->channel_number[index] = cpu_to_le16(chan->hw_value);
-               channels->dwell_time[index][0] = params->dwell[band].active;
-               channels->dwell_time[index][1] = params->dwell[band].passive;
+               channel_number[index] = cpu_to_le16(chan->hw_value);
+               active_dwell[index] = params->dwell[band].active;
+               passive_dwell[index] = params->dwell[band].passive;
 
-               channels->iter_count[index] = cpu_to_le16(1);
-               channels->iter_interval[index] = 0;
+               iter_count[index] = cpu_to_le16(1);
+               iter_interval[index] = 0;
 
                if (!(chan->flags & IEEE80211_CHAN_NO_IR))
-                       channels->type[index] |=
+                       type[index] |=
                                cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE);
 
-               channels->type[index] |=
-                               cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL |
-                                           IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL);
+               type[index] |= cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL |
+                                          IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL);
 
                if (chan->flags & IEEE80211_CHAN_NO_HT40)
-                       channels->type[index] |=
+                       type[index] |=
                                cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_NARROW);
 
                /* scan for all SSIDs from req->ssids */
-               channels->type[index] |= cpu_to_le32(ssid_bitmap);
+               type[index] |= cpu_to_le32(ssid_bitmap);
        }
 }
 
@@ -718,6 +724,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
        u32 ssid_bitmap;
        int cmd_len;
        int ret;
+       u8 *probes;
 
        struct iwl_scan_offload_cfg *scan_cfg;
        struct iwl_host_cmd cmd = {
@@ -728,12 +735,16 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
        lockdep_assert_held(&mvm->mutex);
 
        cmd_len = sizeof(struct iwl_scan_offload_cfg) +
+                 mvm->fw->ucode_capa.n_scan_channels * IWL_SCAN_CHAN_SIZE +
                  2 * SCAN_OFFLOAD_PROBE_REQ_SIZE;
 
        scan_cfg = kzalloc(cmd_len, GFP_KERNEL);
        if (!scan_cfg)
                return -ENOMEM;
 
+       probes = scan_cfg->data +
+               mvm->fw->ucode_capa.n_scan_channels * IWL_SCAN_CHAN_SIZE;
+
        iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, 0, &params);
        iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd, &params);
        scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len);
@@ -744,8 +755,8 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
                iwl_scan_offload_build_tx_cmd(mvm, vif, ies,
                                              IEEE80211_BAND_2GHZ,
                                              &scan_cfg->scan_cmd.tx_cmd[0],
-                                             scan_cfg->data);
-               iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg,
+                                             probes);
+               iwl_build_channel_cfg(mvm, req, scan_cfg->data,
                                      IEEE80211_BAND_2GHZ, &head,
                                      ssid_bitmap, &params);
        }
@@ -753,9 +764,9 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
                iwl_scan_offload_build_tx_cmd(mvm, vif, ies,
                                              IEEE80211_BAND_5GHZ,
                                              &scan_cfg->scan_cmd.tx_cmd[1],
-                                             scan_cfg->data +
+                                             probes +
                                                SCAN_OFFLOAD_PROBE_REQ_SIZE);
-               iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg,
+               iwl_build_channel_cfg(mvm, req, scan_cfg->data,
                                      IEEE80211_BAND_5GHZ, &head,
                                      ssid_bitmap, &params);
        }