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: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
b34d2b3d7d
commit
a6aa5da302
2 changed files with 118 additions and 171 deletions
|
@ -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)
|
||||||
|
|
||||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
|
|
||||||
len = sizeof(struct wmi_start_scan_cmd_10x);
|
|
||||||
else
|
|
||||||
len = sizeof(struct wmi_start_scan_cmd);
|
|
||||||
|
|
||||||
if (arg->ie_len) {
|
|
||||||
if (!arg->ie)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (arg->n_channels && !arg->channels)
|
||||||
|
return -EINVAL;
|
||||||
|
if (arg->n_ssids && !arg->ssids)
|
||||||
|
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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 {
|
||||||
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 {
|
||||||
__le32 probe_delay;
|
__le32 probe_delay;
|
||||||
/* Scan control flags */
|
/* Scan control flags */
|
||||||
__le32 scan_ctrl_flags;
|
__le32 scan_ctrl_flags;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/* Burst duration time in msecs */
|
struct wmi_start_scan_tlvs {
|
||||||
__le32 burst_duration;
|
/* TLV parameters. These includes channel list, ssid list, bssid list,
|
||||||
/*
|
* extra ies.
|
||||||
* 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;
|
|
||||||
*/
|
*/
|
||||||
|
u8 tlvs[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct wmi_start_scan_cmd {
|
||||||
|
struct wmi_start_scan_common common;
|
||||||
|
__le32 burst_duration_ms;
|
||||||
|
struct wmi_start_scan_tlvs tlvs;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* This is the definition from 10.X firmware branch */
|
/* This is the definition from 10.X firmware branch */
|
||||||
struct wmi_start_scan_cmd_10x {
|
struct wmi_10x_start_scan_cmd {
|
||||||
/* Scan ID */
|
struct wmi_start_scan_common common;
|
||||||
__le32 scan_id;
|
struct wmi_start_scan_tlvs tlvs;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/* Scan control flags */
|
|
||||||
__le32 scan_ctrl_flags;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
||||||
|
|
||||||
struct wmi_ssid_arg {
|
struct wmi_ssid_arg {
|
||||||
|
|
Loading…
Add table
Reference in a new issue