Commit a6aa5da3 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: re-work scan start command building

This gets rid of the ugly scan structure building
and uses a saner way to do it.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent b34d2b3d
...@@ -3165,52 +3165,50 @@ int ath10k_wmi_cmd_init(struct ath10k *ar) ...@@ -3165,52 +3165,50 @@ int ath10k_wmi_cmd_init(struct ath10k *ar)
return ret; return ret;
} }
static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, static int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
const struct wmi_start_scan_arg *arg)
{ {
int len; if (arg->ie_len && !arg->ie)
return -EINVAL;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) if (arg->n_channels && !arg->channels)
len = sizeof(struct wmi_start_scan_cmd_10x); return -EINVAL;
else if (arg->n_ssids && !arg->ssids)
len = sizeof(struct wmi_start_scan_cmd);
if (arg->ie_len) {
if (!arg->ie)
return -EINVAL; return -EINVAL;
if (arg->n_bssids && !arg->bssids)
return -EINVAL;
if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
return -EINVAL; return -EINVAL;
if (arg->n_channels > ARRAY_SIZE(arg->channels))
return -EINVAL;
if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
return -EINVAL;
if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
return -EINVAL;
return 0;
}
static size_t
ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg)
{
int len = 0;
if (arg->ie_len) {
len += sizeof(struct wmi_ie_data); len += sizeof(struct wmi_ie_data);
len += roundup(arg->ie_len, 4); len += roundup(arg->ie_len, 4);
} }
if (arg->n_channels) { if (arg->n_channels) {
if (!arg->channels)
return -EINVAL;
if (arg->n_channels > ARRAY_SIZE(arg->channels))
return -EINVAL;
len += sizeof(struct wmi_chan_list); len += sizeof(struct wmi_chan_list);
len += sizeof(__le32) * arg->n_channels; len += sizeof(__le32) * arg->n_channels;
} }
if (arg->n_ssids) { if (arg->n_ssids) {
if (!arg->ssids)
return -EINVAL;
if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
return -EINVAL;
len += sizeof(struct wmi_ssid_list); len += sizeof(struct wmi_ssid_list);
len += sizeof(struct wmi_ssid) * arg->n_ssids; len += sizeof(struct wmi_ssid) * arg->n_ssids;
} }
if (arg->n_bssids) { if (arg->n_bssids) {
if (!arg->bssids)
return -EINVAL;
if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
return -EINVAL;
len += sizeof(struct wmi_bssid_list); len += sizeof(struct wmi_bssid_list);
len += sizeof(struct wmi_mac_addr) * arg->n_bssids; len += sizeof(struct wmi_mac_addr) * arg->n_bssids;
} }
...@@ -3218,28 +3216,12 @@ static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, ...@@ -3218,28 +3216,12 @@ static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar,
return len; return len;
} }
int ath10k_wmi_start_scan(struct ath10k *ar, static void
ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
const struct wmi_start_scan_arg *arg) const struct wmi_start_scan_arg *arg)
{ {
struct wmi_start_scan_cmd *cmd;
struct sk_buff *skb;
struct wmi_ie_data *ie;
struct wmi_chan_list *channels;
struct wmi_ssid_list *ssids;
struct wmi_bssid_list *bssids;
u32 scan_id; u32 scan_id;
u32 scan_req_id; u32 scan_req_id;
int off;
int len = 0;
int i;
len = ath10k_wmi_start_scan_calc_len(ar, arg);
if (len < 0)
return len; /* len contains error code here */
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
return -ENOMEM;
scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX;
scan_id |= arg->scan_id; scan_id |= arg->scan_id;
...@@ -3247,35 +3229,36 @@ int ath10k_wmi_start_scan(struct ath10k *ar, ...@@ -3247,35 +3229,36 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
scan_req_id |= arg->scan_req_id; scan_req_id |= arg->scan_req_id;
cmd = (struct wmi_start_scan_cmd *)skb->data; cmn->scan_id = __cpu_to_le32(scan_id);
cmd->scan_id = __cpu_to_le32(scan_id); cmn->scan_req_id = __cpu_to_le32(scan_req_id);
cmd->scan_req_id = __cpu_to_le32(scan_req_id); cmn->vdev_id = __cpu_to_le32(arg->vdev_id);
cmd->vdev_id = __cpu_to_le32(arg->vdev_id); cmn->scan_priority = __cpu_to_le32(arg->scan_priority);
cmd->scan_priority = __cpu_to_le32(arg->scan_priority); cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); cmn->dwell_time_active = __cpu_to_le32(arg->dwell_time_active);
cmd->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); cmn->min_rest_time = __cpu_to_le32(arg->min_rest_time);
cmd->min_rest_time = __cpu_to_le32(arg->min_rest_time); cmn->max_rest_time = __cpu_to_le32(arg->max_rest_time);
cmd->max_rest_time = __cpu_to_le32(arg->max_rest_time); cmn->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time);
cmd->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); cmn->idle_time = __cpu_to_le32(arg->idle_time);
cmd->idle_time = __cpu_to_le32(arg->idle_time); cmn->max_scan_time = __cpu_to_le32(arg->max_scan_time);
cmd->max_scan_time = __cpu_to_le32(arg->max_scan_time); cmn->probe_delay = __cpu_to_le32(arg->probe_delay);
cmd->probe_delay = __cpu_to_le32(arg->probe_delay); cmn->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags);
cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); }
/* TLV list starts after fields included in the struct */ static void
/* There's just one filed that differes the two start_scan ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs,
* structures - burst_duration, which we are not using btw, const struct wmi_start_scan_arg *arg)
no point to make the split here, just shift the buffer to fit with {
given FW */ struct wmi_ie_data *ie;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) struct wmi_chan_list *channels;
off = sizeof(struct wmi_start_scan_cmd_10x); struct wmi_ssid_list *ssids;
else struct wmi_bssid_list *bssids;
off = sizeof(struct wmi_start_scan_cmd); void *ptr = tlvs->tlvs;
int i;
if (arg->n_channels) { if (arg->n_channels) {
channels = (void *)skb->data + off; channels = ptr;
channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG);
channels->num_chan = __cpu_to_le32(arg->n_channels); channels->num_chan = __cpu_to_le32(arg->n_channels);
...@@ -3283,12 +3266,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar, ...@@ -3283,12 +3266,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
channels->channel_list[i].freq = channels->channel_list[i].freq =
__cpu_to_le16(arg->channels[i]); __cpu_to_le16(arg->channels[i]);
off += sizeof(*channels); ptr += sizeof(*channels);
off += sizeof(__le32) * arg->n_channels; ptr += sizeof(__le32) * arg->n_channels;
} }
if (arg->n_ssids) { if (arg->n_ssids) {
ssids = (void *)skb->data + off; ssids = ptr;
ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG);
ssids->num_ssids = __cpu_to_le32(arg->n_ssids); ssids->num_ssids = __cpu_to_le32(arg->n_ssids);
...@@ -3300,12 +3283,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar, ...@@ -3300,12 +3283,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
arg->ssids[i].len); arg->ssids[i].len);
} }
off += sizeof(*ssids); ptr += sizeof(*ssids);
off += sizeof(struct wmi_ssid) * arg->n_ssids; ptr += sizeof(struct wmi_ssid) * arg->n_ssids;
} }
if (arg->n_bssids) { if (arg->n_bssids) {
bssids = (void *)skb->data + off; bssids = ptr;
bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG);
bssids->num_bssid = __cpu_to_le32(arg->n_bssids); bssids->num_bssid = __cpu_to_le32(arg->n_bssids);
...@@ -3314,23 +3297,57 @@ int ath10k_wmi_start_scan(struct ath10k *ar, ...@@ -3314,23 +3297,57 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
arg->bssids[i].bssid, arg->bssids[i].bssid,
ETH_ALEN); ETH_ALEN);
off += sizeof(*bssids); ptr += sizeof(*bssids);
off += sizeof(struct wmi_mac_addr) * arg->n_bssids; ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids;
} }
if (arg->ie_len) { if (arg->ie_len) {
ie = (void *)skb->data + off; ie = ptr;
ie->tag = __cpu_to_le32(WMI_IE_TAG); ie->tag = __cpu_to_le32(WMI_IE_TAG);
ie->ie_len = __cpu_to_le32(arg->ie_len); ie->ie_len = __cpu_to_le32(arg->ie_len);
memcpy(ie->ie_data, arg->ie, arg->ie_len); memcpy(ie->ie_data, arg->ie, arg->ie_len);
off += sizeof(*ie); ptr += sizeof(*ie);
off += roundup(arg->ie_len, 4); ptr += roundup(arg->ie_len, 4);
} }
}
if (off != skb->len) { int ath10k_wmi_start_scan(struct ath10k *ar,
dev_kfree_skb(skb); const struct wmi_start_scan_arg *arg)
return -EINVAL; {
struct sk_buff *skb;
size_t len;
int ret;
ret = ath10k_wmi_start_scan_verify(arg);
if (ret)
return ret;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
len = sizeof(struct wmi_start_scan_cmd) +
ath10k_wmi_start_scan_tlvs_len(arg);
else
len = sizeof(struct wmi_10x_start_scan_cmd) +
ath10k_wmi_start_scan_tlvs_len(arg);
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
return -ENOMEM;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
struct wmi_10x_start_scan_cmd *cmd;
cmd = (struct wmi_10x_start_scan_cmd *)skb->data;
ath10k_wmi_put_start_scan_common(&cmd->common, arg);
ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
} else {
struct wmi_start_scan_cmd *cmd;
cmd = (struct wmi_start_scan_cmd *)skb->data;
cmd->burst_duration_ms = __cpu_to_le32(0);
ath10k_wmi_put_start_scan_common(&cmd->common, arg);
ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
} }
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n"); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n");
......
...@@ -1962,7 +1962,7 @@ enum wmi_scan_priority { ...@@ -1962,7 +1962,7 @@ enum wmi_scan_priority {
WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */ WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */
}; };
struct wmi_start_scan_cmd { struct wmi_start_scan_common {
/* Scan ID */ /* Scan ID */
__le32 scan_id; __le32 scan_id;
/* Scan requestor ID */ /* Scan requestor ID */
...@@ -2020,95 +2020,25 @@ struct wmi_start_scan_cmd { ...@@ -2020,95 +2020,25 @@ struct wmi_start_scan_cmd {
__le32 probe_delay; __le32 probe_delay;
/* Scan control flags */ /* Scan control flags */
__le32 scan_ctrl_flags; __le32 scan_ctrl_flags;
/* Burst duration time in msecs */
__le32 burst_duration;
/*
* TLV (tag length value ) paramerters follow the scan_cmd structure.
* TLV can contain channel list, bssid list, ssid list and
* ie. the TLV tags are defined above;
*/
} __packed; } __packed;
/* This is the definition from 10.X firmware branch */ struct wmi_start_scan_tlvs {
struct wmi_start_scan_cmd_10x { /* TLV parameters. These includes channel list, ssid list, bssid list,
/* Scan ID */ * extra ies.
__le32 scan_id;
/* Scan requestor ID */
__le32 scan_req_id;
/* VDEV id(interface) that is requesting scan */
__le32 vdev_id;
/* Scan Priority, input to scan scheduler */
__le32 scan_priority;
/* Scan events subscription */
__le32 notify_scan_events;
/* dwell time in msec on active channels */
__le32 dwell_time_active;
/* dwell time in msec on passive channels */
__le32 dwell_time_passive;
/*
* min time in msec on the BSS channel,only valid if atleast one
* VDEV is active
*/
__le32 min_rest_time;
/*
* max rest time in msec on the BSS channel,only valid if at least
* one VDEV is active
*/
/*
* the scanner will rest on the bss channel at least min_rest_time
* after min_rest_time the scanner will start checking for tx/rx
* activity on all VDEVs. if there is no activity the scanner will
* switch to off channel. if there is activity the scanner will let
* the radio on the bss channel until max_rest_time expires.at
* max_rest_time scanner will switch to off channel irrespective of
* activity. activity is determined by the idle_time parameter.
*/
__le32 max_rest_time;
/*
* time before sending next set of probe requests.
* The scanner keeps repeating probe requests transmission with
* period specified by repeat_probe_time.
* The number of probe requests specified depends on the ssid_list
* and bssid_list
*/
__le32 repeat_probe_time;
/* time in msec between 2 consequetive probe requests with in a set. */
__le32 probe_spacing_time;
/*
* data inactivity time in msec on bss channel that will be used by
* scanner for measuring the inactivity.
*/
__le32 idle_time;
/* maximum time in msec allowed for scan */
__le32 max_scan_time;
/*
* delay in msec before sending first probe request after switching
* to a channel
*/ */
__le32 probe_delay; u8 tlvs[0];
} __packed;
/* Scan control flags */ struct wmi_start_scan_cmd {
__le32 scan_ctrl_flags; struct wmi_start_scan_common common;
__le32 burst_duration_ms;
struct wmi_start_scan_tlvs tlvs;
} __packed;
/* /* This is the definition from 10.X firmware branch */
* TLV (tag length value ) paramerters follow the scan_cmd structure. struct wmi_10x_start_scan_cmd {
* TLV can contain channel list, bssid list, ssid list and struct wmi_start_scan_common common;
* ie. the TLV tags are defined above; struct wmi_start_scan_tlvs tlvs;
*/
} __packed; } __packed;
struct wmi_ssid_arg { struct wmi_ssid_arg {
......
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