From: Ilan Peer Date: Thu, 19 Mar 2026 09:09:19 +0000 (+0200) Subject: wifi: iwlwifi: mld: Refactor scan command handling X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b6045c899e371dda801ae33727c9da112f422645;p=thirdparty%2Flinux.git wifi: iwlwifi: mld: Refactor scan command handling As a preparation for a new scan command version, refactor the scan command building such that it would allow introducing new scan command structures in a simpler way. Signed-off-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20260319110722.a3e9589769f0.If458023e234ed79db7474107d98f0b6e28e565e5@changeid --- diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index a1a4cf3ab3d31..7f4679134defc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -116,6 +116,13 @@ struct iwl_mld_scan_params { u8 bssid[ETH_ALEN] __aligned(2); }; +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_periodic_parms_v1 *periodic_params; + struct iwl_scan_probe_params_v4 *probe_params; +}; + struct iwl_mld_scan_respect_p2p_go_iter_data { struct ieee80211_vif *current_vif; bool p2p_go; @@ -512,9 +519,10 @@ iwl_mld_scan_get_cmd_gen_flags2(struct iwl_mld *mld, static void iwl_mld_scan_cmd_set_dwell(struct iwl_mld *mld, - struct iwl_scan_general_params_v11 *gp, - struct iwl_mld_scan_params *params) + struct iwl_mld_scan_params *params, + struct iwl_scan_req_params_ptrs *scan_ptrs) { + struct iwl_scan_general_params_v11 *gp = scan_ptrs->general_params; const struct iwl_mld_scan_timing_params *timing = &scan_timing[params->type]; @@ -551,9 +559,10 @@ static void iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld, struct iwl_mld_scan_params *params, struct ieee80211_vif *vif, - struct iwl_scan_general_params_v11 *gp, + struct iwl_scan_req_params_ptrs *scan_ptrs, enum iwl_mld_scan_status scan_status) { + struct iwl_scan_general_params_v11 *gp = scan_ptrs->general_params; u16 gen_flags = iwl_mld_scan_get_cmd_gen_flags(mld, params, vif, scan_status); u8 gen_flags2 = iwl_mld_scan_get_cmd_gen_flags2(mld, params, vif, @@ -566,7 +575,7 @@ iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld, gp->flags = cpu_to_le16(gen_flags); gp->flags2 = gen_flags2; - iwl_mld_scan_cmd_set_dwell(mld, gp, params); + iwl_mld_scan_cmd_set_dwell(mld, params, scan_ptrs); if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1) gp->num_of_fragments[SCAN_LB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; @@ -577,9 +586,12 @@ iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld, static int iwl_mld_scan_cmd_set_sched_params(struct iwl_mld_scan_params *params, - struct iwl_scan_umac_schedule *schedule, - __le16 *delay) + struct iwl_scan_req_params_ptrs *scan_ptrs) { + struct iwl_scan_umac_schedule *schedule = + scan_ptrs->periodic_params->schedule; + __le16 *delay = &scan_ptrs->periodic_params->delay; + if (WARN_ON(!params->n_scan_plans || params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) return -EINVAL; @@ -657,11 +669,12 @@ iwl_mld_scan_cmd_build_ssids(struct iwl_mld_scan_params *params, static void iwl_mld_scan_fill_6g_chan_list(struct iwl_mld_scan_params *params, - struct iwl_scan_probe_params_v4 *pp) + struct iwl_scan_req_params_ptrs *scan_ptrs) { int j, idex_s = 0, idex_b = 0; struct cfg80211_scan_6ghz_params *scan_6ghz_params = params->scan_6ghz_params; + struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params; for (j = 0; j < params->n_ssids && idex_s < SCAN_SHORT_SSID_MAX_SIZE; @@ -725,13 +738,15 @@ iwl_mld_scan_fill_6g_chan_list(struct iwl_mld_scan_params *params, static void iwl_mld_scan_cmd_set_probe_params(struct iwl_mld_scan_params *params, - struct iwl_scan_probe_params_v4 *pp, + struct iwl_scan_req_params_ptrs *scan_ptrs, u32 *bitmap_ssid) { + struct iwl_scan_probe_params_v4 *pp = scan_ptrs->probe_params; + pp->preq = params->preq; if (params->scan_6ghz) { - iwl_mld_scan_fill_6g_chan_list(params, pp); + iwl_mld_scan_fill_6g_chan_list(params, scan_ptrs); return; } @@ -821,10 +836,12 @@ static u32 iwl_mld_scan_ch_n_aps_flag(enum nl80211_iftype vif_type, u8 ch_id) static void iwl_mld_scan_cmd_set_channels(struct iwl_mld *mld, struct ieee80211_channel **channels, - struct iwl_scan_channel_params_v7 *cp, + struct iwl_scan_req_params_ptrs *scan_ptrs, int n_channels, u32 flags, enum nl80211_iftype vif_type) { + struct iwl_scan_channel_params_v7 *cp = scan_ptrs->channel_params; + for (int i = 0; i < n_channels; i++) { enum nl80211_band band = channels[i]->band; struct iwl_scan_channel_cfg_umac *cfg = &cp->channel_config[i]; @@ -862,10 +879,11 @@ static u8 iwl_mld_scan_cfg_channels_6g(struct iwl_mld *mld, struct iwl_mld_scan_params *params, u32 n_channels, - struct iwl_scan_probe_params_v4 *pp, - struct iwl_scan_channel_params_v7 *cp, + struct iwl_scan_req_params_ptrs *scan_ptrs, 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 cfg80211_scan_6ghz_params *scan_6ghz_params = params->scan_6ghz_params; u32 i; @@ -1063,25 +1081,23 @@ static int iwl_mld_scan_cmd_set_6ghz_chan_params(struct iwl_mld *mld, struct iwl_mld_scan_params *params, struct ieee80211_vif *vif, - struct iwl_scan_req_params_v17 *scan_p) + struct iwl_scan_req_params_ptrs *scan_ptrs) { - struct iwl_scan_channel_params_v7 *chan_p = &scan_p->channel_params; - struct iwl_scan_probe_params_v4 *probe_p = &scan_p->probe_params; + struct iwl_scan_channel_params_v7 *cp = scan_ptrs->channel_params; /* Explicitly clear the flags since most of them are not * relevant for 6 GHz scan. */ - chan_p->flags = 0; - chan_p->count = iwl_mld_scan_cfg_channels_6g(mld, params, - params->n_channels, - probe_p, chan_p, - vif->type); - if (!chan_p->count) + cp->flags = 0; + cp->count = iwl_mld_scan_cfg_channels_6g(mld, params, + params->n_channels, + scan_ptrs, vif->type); + if (!cp->count) return -EINVAL; if (!params->n_ssids || (params->n_ssids == 1 && !params->ssids[0].ssid_len)) - chan_p->flags |= IWL_SCAN_CHANNEL_FLAG_6G_PSC_NO_FILTER; + cp->flags |= IWL_SCAN_CHANNEL_FLAG_6G_PSC_NO_FILTER; return 0; } @@ -1090,12 +1106,12 @@ static int iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld, struct iwl_mld_scan_params *params, struct ieee80211_vif *vif, - struct iwl_scan_req_params_v17 *scan_p, + struct iwl_scan_req_params_ptrs *scan_ptrs, bool low_latency, enum iwl_mld_scan_status scan_status, u32 channel_cfg_flags) { - struct iwl_scan_channel_params_v7 *cp = &scan_p->channel_params; + struct iwl_scan_channel_params_v7 *cp = scan_ptrs->channel_params; struct ieee80211_supported_band *sband = &mld->nvm_data->bands[NL80211_BAND_6GHZ]; @@ -1107,14 +1123,14 @@ iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld, if (params->scan_6ghz) return iwl_mld_scan_cmd_set_6ghz_chan_params(mld, params, - vif, scan_p); + vif, scan_ptrs); /* relevant only for 2.4 GHz/5 GHz scan */ cp->flags = iwl_mld_scan_cmd_set_chan_flags(mld, params, vif, low_latency); cp->count = params->n_channels; - iwl_mld_scan_cmd_set_channels(mld, params->channels, cp, + iwl_mld_scan_cmd_set_channels(mld, params->channels, scan_ptrs, params->n_channels, channel_cfg_flags, vif->type); @@ -1144,41 +1160,50 @@ iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld, return 0; } -static int -iwl_mld_scan_build_cmd(struct iwl_mld *mld, struct ieee80211_vif *vif, +struct iwl_scan_umac_handler { + u8 version; + int (*handler)(struct iwl_mld *mld, struct ieee80211_vif *vif, struct iwl_mld_scan_params *params, enum iwl_mld_scan_status scan_status, - bool low_latency) + int uid, u32 ooc_priority, bool low_latency); +}; + +#define IWL_SCAN_UMAC_HANDLER(_ver) { \ + .version = _ver, \ + .handler = iwl_mld_scan_umac_v##_ver, \ +} + +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, + int uid, u32 ooc_priority, bool low_latency) { struct iwl_scan_req_umac_v17 *cmd = mld->scan.cmd; - struct iwl_scan_req_params_v17 *scan_p = &cmd->scan_params; + 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 + }; u32 bitmap_ssid = 0; - int uid, ret; - - memset(mld->scan.cmd, 0, mld->scan.cmd_size); + int ret; - /* find a free UID entry */ - uid = iwl_mld_scan_uid_by_status(mld, IWL_MLD_SCAN_NONE); - if (uid < 0) - return uid; + if (WARN_ON(params->n_channels > SCAN_MAX_NUM_CHANS_V3)) + return -EINVAL; cmd->uid = cpu_to_le32(uid); - cmd->ooc_priority = - cpu_to_le32(iwl_mld_scan_ooc_priority(scan_status)); + cmd->ooc_priority = cpu_to_le32(ooc_priority); - iwl_mld_scan_cmd_set_gen_params(mld, params, vif, - &scan_p->general_params, scan_status); + iwl_mld_scan_cmd_set_gen_params(mld, params, vif, &scan_ptrs, + scan_status); - ret = iwl_mld_scan_cmd_set_sched_params(params, - scan_p->periodic_params.schedule, - &scan_p->periodic_params.delay); + ret = iwl_mld_scan_cmd_set_sched_params(params, &scan_ptrs); if (ret) return ret; - iwl_mld_scan_cmd_set_probe_params(params, &scan_p->probe_params, - &bitmap_ssid); + iwl_mld_scan_cmd_set_probe_params(params, &scan_ptrs, &bitmap_ssid); - ret = iwl_mld_scan_cmd_set_chan_params(mld, params, vif, scan_p, + ret = iwl_mld_scan_cmd_set_chan_params(mld, params, vif, &scan_ptrs, low_latency, scan_status, bitmap_ssid); if (ret) @@ -1187,6 +1212,45 @@ iwl_mld_scan_build_cmd(struct iwl_mld *mld, struct ieee80211_vif *vif, return uid; } +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(17), +}; + +static int +iwl_mld_scan_build_cmd(struct iwl_mld *mld, struct ieee80211_vif *vif, + struct iwl_mld_scan_params *params, + enum iwl_mld_scan_status scan_status, + bool low_latency) +{ + int uid, err; + u32 ooc_priority; + + memset(mld->scan.cmd, 0, mld->scan.cmd_size); + uid = iwl_mld_scan_uid_by_status(mld, IWL_MLD_SCAN_NONE); + if (uid < 0) + return uid; + + ooc_priority = iwl_mld_scan_ooc_priority(scan_status); + + for (size_t i = 0; i < ARRAY_SIZE(iwl_scan_umac_handlers); i++) { + const struct iwl_scan_umac_handler *ver_handler = + &iwl_scan_umac_handlers[i]; + + if (ver_handler->version != mld->scan.cmd_ver) + continue; + + err = ver_handler->handler(mld, vif, params, scan_status, + uid, ooc_priority, low_latency); + return err ? : uid; + } + + IWL_ERR(mld, "No handler for UMAC scan cmd version %d\n", + mld->scan.cmd_ver); + + return -EINVAL; +} + static bool iwl_mld_scan_pass_all(struct iwl_mld *mld, struct cfg80211_sched_scan_request *req) @@ -2041,6 +2105,7 @@ int iwl_mld_alloc_scan_cmd(struct iwl_mld *mld) return -ENOMEM; mld->scan.cmd_size = scan_cmd_size; + mld->scan.cmd_ver = scan_cmd_ver; return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.h b/drivers/net/wireless/intel/iwlwifi/mld/scan.h index 69110f0cfc8e2..772b3a02c4c4d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.h @@ -109,6 +109,7 @@ enum iwl_mld_traffic_load { * @traffic_load.status: The current traffic load status, see * &enum iwl_mld_traffic_load * @cmd_size: size of %cmd. + * @cmd_ver: version of the scan command format. * @cmd: pointer to scan cmd buffer (allocated once in op mode start). * @last_6ghz_passive_jiffies: stores the last 6GHz passive scan time * in jiffies. @@ -134,6 +135,7 @@ struct iwl_mld_scan { /* And here fields that survive a fw restart */ size_t cmd_size; void *cmd; + u8 cmd_ver; unsigned long last_6ghz_passive_jiffies; unsigned long last_start_time_jiffies; u64 last_mlo_scan_time;