diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 60f0a4924ddf..c2bb400c834c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -985,6 +985,7 @@ struct iwl_scan_probe_params_v4 { } __packed; /* SCAN_PROBE_PARAMS_API_S_VER_4 */ #define SCAN_MAX_NUM_CHANS_V3 67 +#define SCAN_MAX_NUM_CHANS_V4 68 /** * struct iwl_scan_channel_params_v4 - channel params @@ -1027,6 +1028,24 @@ struct iwl_scan_channel_params_v7 { struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V3]; } __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */ +/** + * struct iwl_scan_channel_params_v8 - channel params + * @flags: channel flags &enum iwl_scan_channel_flags + * @count: num of channels in scan request + * @n_aps_override: override the number of APs the FW uses to calculate dwell + * time when adaptive dwell is used. + * Channel k will use n_aps_override[i] when BIT(20 + i) is set in + * channel_config[k].flags + * @channel_config: array of explicit channel configurations + * for 2.4Ghz and 5.2Ghz bands + */ +struct iwl_scan_channel_params_v8 { + u8 flags; + u8 count; + u8 n_aps_override[2]; + struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V4]; +} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_8 */ + /** * struct iwl_scan_general_params_v11 - channel params * @flags: &enum iwl_umac_scan_general_flags_v2 @@ -1109,6 +1128,20 @@ struct iwl_scan_req_params_v17 { struct iwl_scan_probe_params_v4 probe_params; } __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */ +/** + * struct iwl_scan_req_params_v18 - scan request parameters (v18) + * @general_params: &struct iwl_scan_general_params_v11 + * @channel_params: &struct iwl_scan_channel_params_v8 + * @periodic_params: &struct iwl_scan_periodic_parms_v1 + * @probe_params: &struct iwl_scan_probe_params_v4 + */ +struct iwl_scan_req_params_v18 { + struct iwl_scan_general_params_v11 general_params; + struct iwl_scan_channel_params_v8 channel_params; + struct iwl_scan_periodic_parms_v1 periodic_params; + struct iwl_scan_probe_params_v4 probe_params; +} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_18 */ + /** * struct iwl_scan_req_umac_v12 - scan request command (v12) * @uid: scan id, &enum iwl_umac_scan_uid_offsets @@ -1133,6 +1166,18 @@ struct iwl_scan_req_umac_v17 { struct iwl_scan_req_params_v17 scan_params; } __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */ +/** + * struct iwl_scan_req_umac_v18 - scan request command (v18) + * @uid: scan id, &enum iwl_umac_scan_uid_offsets + * @ooc_priority: out of channel priority - &enum iwl_scan_priority + * @scan_params: scan parameters + */ +struct iwl_scan_req_umac_v18 { + __le32 uid; + __le32 ooc_priority; + struct iwl_scan_req_params_v18 scan_params; +} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_18 */ + /** * struct iwl_umac_scan_abort - scan abort command * @uid: scan id, &enum iwl_umac_scan_uid_offsets diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index 7f4679134def..96cd970cceb4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -118,7 +118,7 @@ struct iwl_mld_scan_params { struct iwl_scan_req_params_ptrs { struct iwl_scan_general_params_v11 *general_params; - struct iwl_scan_channel_params_v7 *channel_params; + struct iwl_scan_channel_params_v8 *channel_params; struct iwl_scan_periodic_parms_v1 *periodic_params; struct iwl_scan_probe_params_v4 *probe_params; }; @@ -840,7 +840,7 @@ iwl_mld_scan_cmd_set_channels(struct iwl_mld *mld, int n_channels, u32 flags, enum nl80211_iftype vif_type) { - struct iwl_scan_channel_params_v7 *cp = scan_ptrs->channel_params; + struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params; for (int i = 0; i < n_channels; i++) { enum nl80211_band band = channels[i]->band; @@ -883,7 +883,7 @@ iwl_mld_scan_cfg_channels_6g(struct iwl_mld *mld, enum nl80211_iftype vif_type) { struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params; - struct iwl_scan_channel_params_v7 *cp = scan_ptrs->channel_params; + struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params; struct cfg80211_scan_6ghz_params *scan_6ghz_params = params->scan_6ghz_params; u32 i; @@ -1083,7 +1083,7 @@ iwl_mld_scan_cmd_set_6ghz_chan_params(struct iwl_mld *mld, struct ieee80211_vif *vif, struct iwl_scan_req_params_ptrs *scan_ptrs) { - struct iwl_scan_channel_params_v7 *cp = scan_ptrs->channel_params; + struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params; /* Explicitly clear the flags since most of them are not * relevant for 6 GHz scan. @@ -1111,7 +1111,7 @@ iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld, enum iwl_mld_scan_status scan_status, u32 channel_cfg_flags) { - struct iwl_scan_channel_params_v7 *cp = scan_ptrs->channel_params; + struct iwl_scan_channel_params_v8 *cp = scan_ptrs->channel_params; struct ieee80211_supported_band *sband = &mld->nvm_data->bands[NL80211_BAND_6GHZ]; @@ -1173,6 +1173,58 @@ struct iwl_scan_umac_handler { .handler = iwl_mld_scan_umac_v##_ver, \ } +static int iwl_mld_scan_umac_common(struct iwl_mld *mld, + struct ieee80211_vif *vif, + struct iwl_mld_scan_params *params, + struct iwl_scan_req_params_ptrs *scan_ptrs, + enum iwl_mld_scan_status scan_status, + bool low_latency) +{ + u32 bitmap_ssid = 0; + int ret; + + iwl_mld_scan_cmd_set_gen_params(mld, params, vif, scan_ptrs, + scan_status); + + ret = iwl_mld_scan_cmd_set_sched_params(params, scan_ptrs); + if (ret) + return ret; + + iwl_mld_scan_cmd_set_probe_params(params, scan_ptrs, &bitmap_ssid); + + return iwl_mld_scan_cmd_set_chan_params(mld, params, vif, scan_ptrs, + low_latency, scan_status, + bitmap_ssid); +} + +static int iwl_mld_scan_umac_v18(struct iwl_mld *mld, struct ieee80211_vif *vif, + struct iwl_mld_scan_params *params, + enum iwl_mld_scan_status scan_status, + int uid, u32 ooc_priority, bool low_latency) +{ + struct iwl_scan_req_umac_v18 *cmd = mld->scan.cmd; + struct iwl_scan_req_params_ptrs scan_ptrs = { + .general_params = &cmd->scan_params.general_params, + .probe_params = &cmd->scan_params.probe_params, + .channel_params = &cmd->scan_params.channel_params, + .periodic_params = &cmd->scan_params.periodic_params + }; + int ret; + + if (WARN_ON(params->n_channels > SCAN_MAX_NUM_CHANS_V4)) + return -EINVAL; + + cmd->uid = cpu_to_le32(uid); + cmd->ooc_priority = cpu_to_le32(ooc_priority); + + ret = iwl_mld_scan_umac_common(mld, vif, params, &scan_ptrs, + scan_status, low_latency); + if (ret) + return ret; + + return uid; +} + static int iwl_mld_scan_umac_v17(struct iwl_mld *mld, struct ieee80211_vif *vif, struct iwl_mld_scan_params *params, enum iwl_mld_scan_status scan_status, @@ -1182,10 +1234,18 @@ static int iwl_mld_scan_umac_v17(struct iwl_mld *mld, struct ieee80211_vif *vif, struct iwl_scan_req_params_ptrs scan_ptrs = { .general_params = &cmd->scan_params.general_params, .probe_params = &cmd->scan_params.probe_params, - .channel_params = &cmd->scan_params.channel_params, + + /* struct iwl_scan_channel_params_v8 and struct + * iwl_scan_channel_params_v7 are almost identical. The only + * difference is that the newer version allows configuration of + * more channels. So casting here is ok as long as we ensure + * that we don't exceed the max number of channels supported by + * the older version (see the WARN_ON below). + */ + .channel_params = (struct iwl_scan_channel_params_v8 *) + &cmd->scan_params.channel_params, .periodic_params = &cmd->scan_params.periodic_params }; - u32 bitmap_ssid = 0; int ret; if (WARN_ON(params->n_channels > SCAN_MAX_NUM_CHANS_V3)) @@ -1194,18 +1254,8 @@ static int iwl_mld_scan_umac_v17(struct iwl_mld *mld, struct ieee80211_vif *vif, cmd->uid = cpu_to_le32(uid); cmd->ooc_priority = cpu_to_le32(ooc_priority); - iwl_mld_scan_cmd_set_gen_params(mld, params, vif, &scan_ptrs, - scan_status); - - ret = iwl_mld_scan_cmd_set_sched_params(params, &scan_ptrs); - if (ret) - return ret; - - iwl_mld_scan_cmd_set_probe_params(params, &scan_ptrs, &bitmap_ssid); - - ret = iwl_mld_scan_cmd_set_chan_params(mld, params, vif, &scan_ptrs, - low_latency, scan_status, - bitmap_ssid); + ret = iwl_mld_scan_umac_common(mld, vif, params, &scan_ptrs, + scan_status, low_latency); if (ret) return ret; @@ -1214,6 +1264,7 @@ static int iwl_mld_scan_umac_v17(struct iwl_mld *mld, struct ieee80211_vif *vif, static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = { /* set the newest version first to shorten the list traverse time */ + IWL_SCAN_UMAC_HANDLER(18), IWL_SCAN_UMAC_HANDLER(17), }; @@ -2095,6 +2146,8 @@ int iwl_mld_alloc_scan_cmd(struct iwl_mld *mld) if (scan_cmd_ver == 17) { scan_cmd_size = sizeof(struct iwl_scan_req_umac_v17); + } else if (scan_cmd_ver == 18) { + scan_cmd_size = sizeof(struct iwl_scan_req_umac_v18); } else { IWL_ERR(mld, "Unexpected scan cmd version %d\n", scan_cmd_ver); return -EINVAL;