Commit 762533ba authored by David Spinadel's avatar David Spinadel Committed by Emmanuel Grumbach

iwlwifi: mvm: don't use hardcoded num of scan channels

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