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;
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];
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,
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;
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;
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;
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;
}
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];
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;
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;
}
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];
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);
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)
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)
return -ENOMEM;
mld->scan.cmd_size = scan_cmd_size;
+ mld->scan.cmd_ver = scan_cmd_ver;
return 0;
}