qtnfmac: drop unnecessary TLVs from scan command

Most part of scan command data is always present, so no need
to keep it in TLV. Simplify scan command processing moving
most part of its parameters into a fixed part of
qlink_cmd_scan message.

Use fixed dwell time values for normal scan when device is not
connected, and allow wireless card decide on dwell times by
itself if it's operating as a STA and is connected. When
connected, card can select dwell times dynamically based on
traffic conditions to get best results.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Igor Mitsyanko 2020-01-27 10:46:56 +00:00 committed by Kalle Valo
parent 5edadc5a3f
commit 501c3be1ec
3 changed files with 97 additions and 94 deletions

View File

@ -11,11 +11,11 @@
#include "bus.h"
#include "commands.h"
/* Let device itself to select best values for current conditions */
#define QTNF_SCAN_TIME_AUTO 0
/* Let device itself to select best values for current conditions */
#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT QTNF_SCAN_TIME_AUTO
#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT QTNF_SCAN_TIME_AUTO
#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT 90
#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT 100
#define QTNF_SCAN_SAMPLE_DURATION_DEFAULT QTNF_SCAN_TIME_AUTO
static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp,
@ -2011,108 +2011,90 @@ static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb,
memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN);
}
static void qtnf_cmd_scan_set_dwell(struct qtnf_wmac *mac,
struct sk_buff *cmd_skb)
{
struct cfg80211_scan_request *scan_req = mac->scan_req;
u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT;
u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT;
u16 duration = QTNF_SCAN_SAMPLE_DURATION_DEFAULT;
if (scan_req->duration) {
dwell_active = scan_req->duration;
dwell_passive = scan_req->duration;
}
pr_debug("MAC%u: %s scan dwell active=%u, passive=%u, duration=%u\n",
mac->macid,
scan_req->duration_mandatory ? "mandatory" : "max",
dwell_active, dwell_passive, duration);
qtnf_cmd_skb_put_tlv_u32(cmd_skb,
QTN_TLV_ID_SCAN_DWELL_ACTIVE,
dwell_active);
qtnf_cmd_skb_put_tlv_u32(cmd_skb,
QTN_TLV_ID_SCAN_DWELL_PASSIVE,
dwell_passive);
qtnf_cmd_skb_put_tlv_u32(cmd_skb,
QTN_TLV_ID_SCAN_SAMPLE_DURATION,
duration);
}
int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
{
struct sk_buff *cmd_skb;
struct ieee80211_channel *sc;
struct cfg80211_scan_request *scan_req = mac->scan_req;
int n_channels;
int count = 0;
u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT;
u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT;
struct wireless_dev *wdev = scan_req->wdev;
struct ieee80211_channel *sc;
struct qlink_cmd_scan *cmd;
struct sk_buff *cmd_skb;
int n_channels = 0;
u64 flags = 0;
int count;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
QLINK_CMD_SCAN,
sizeof(struct qlink_cmd));
sizeof(*cmd));
if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(mac->bus);
cmd = (struct qlink_cmd_scan *)cmd_skb->data;
if (scan_req->n_ssids != 0) {
while (count < scan_req->n_ssids) {
qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID,
scan_req->ssids[count].ssid,
scan_req->ssids[count].ssid_len);
count++;
}
if (scan_req->duration) {
dwell_active = scan_req->duration;
dwell_passive = scan_req->duration;
} else if (wdev->iftype == NL80211_IFTYPE_STATION &&
wdev->current_bss) {
/* let device select dwell based on traffic conditions */
dwell_active = QTNF_SCAN_TIME_AUTO;
dwell_passive = QTNF_SCAN_TIME_AUTO;
}
cmd->n_ssids = cpu_to_le16(scan_req->n_ssids);
for (count = 0; count < scan_req->n_ssids; ++count) {
qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID,
scan_req->ssids[count].ssid,
scan_req->ssids[count].ssid_len);
}
if (scan_req->ie_len != 0)
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ,
scan_req->ie, scan_req->ie_len);
if (scan_req->n_channels) {
n_channels = scan_req->n_channels;
count = 0;
for (count = 0; count < scan_req->n_channels; ++count) {
sc = scan_req->channels[count];
if (sc->flags & IEEE80211_CHAN_DISABLED)
continue;
while (n_channels != 0) {
sc = scan_req->channels[count];
if (sc->flags & IEEE80211_CHAN_DISABLED) {
n_channels--;
continue;
}
pr_debug("[MAC%u] scan chan=%d, freq=%d, flags=%#x\n",
mac->macid, sc->hw_value, sc->center_freq,
sc->flags);
pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n",
mac->macid, sc->hw_value, sc->center_freq,
sc->flags);
qtnf_cmd_channel_tlv_add(cmd_skb, sc);
n_channels--;
count++;
}
qtnf_cmd_channel_tlv_add(cmd_skb, sc);
++n_channels;
}
qtnf_cmd_scan_set_dwell(mac, cmd_skb);
if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH)
flags |= QLINK_SCAN_FLAG_FLUSH;
if (scan_req->duration_mandatory)
flags |= QLINK_SCAN_FLAG_DURATION_MANDATORY;
cmd->n_channels = cpu_to_le16(n_channels);
cmd->active_dwell = cpu_to_le16(dwell_active);
cmd->passive_dwell = cpu_to_le16(dwell_passive);
cmd->sample_duration = cpu_to_le16(QTNF_SCAN_SAMPLE_DURATION_DEFAULT);
cmd->flags = cpu_to_le64(flags);
pr_debug("[MAC%u] %s scan dwell active=%u passive=%u duration=%u\n",
mac->macid,
scan_req->duration_mandatory ? "mandatory" : "max",
dwell_active, dwell_passive,
QTNF_SCAN_SAMPLE_DURATION_DEFAULT);
if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
pr_debug("MAC%u: scan with random addr=%pM, mask=%pM\n",
pr_debug("[MAC%u] scan with random addr=%pM, mask=%pM\n",
mac->macid,
scan_req->mac_addr, scan_req->mac_addr_mask);
qtnf_cmd_randmac_tlv_add(cmd_skb, scan_req->mac_addr,
scan_req->mac_addr_mask);
}
if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) {
pr_debug("MAC%u: flush cache before scan\n", mac->macid);
qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH);
}
qtnf_bus_lock(mac->bus);
ret = qtnf_cmd_send(mac->bus, cmd_skb);
if (ret)
goto out;
out:
qtnf_bus_unlock(mac->bus);
return ret;

View File

@ -920,6 +920,46 @@ struct qlink_cmd_ndev_changeupper {
u8 rsvd[1];
} __packed;
/**
* enum qlink_scan_flags - scan request control flags
*
* Scan flags are used to control QLINK_CMD_SCAN behavior.
*
* @QLINK_SCAN_FLAG_FLUSH: flush cache before scanning.
*/
enum qlink_scan_flags {
QLINK_SCAN_FLAG_FLUSH = BIT(0),
QLINK_SCAN_FLAG_DURATION_MANDATORY = BIT(1),
};
/**
* struct qlink_cmd_scan - data for QLINK_CMD_SCAN command
*
* @flags: scan flags, a bitmap of &enum qlink_scan_flags.
* @n_ssids: number of WLAN_EID_SSID TLVs expected in variable portion of the
* command.
* @n_channels: number of QTN_TLV_ID_CHANNEL TLVs expected in variable payload.
* @active_dwell: time spent on a single channel for an active scan.
* @passive_dwell: time spent on a single channel for a passive scan.
* @sample_duration: total duration of sampling a single channel during a scan
* including off-channel dwell time and operating channel time.
* @bssid: specific BSSID to scan for or a broadcast BSSID.
* @scan_width: channel width to use, one of &enum qlink_channel_width.
*/
struct qlink_cmd_scan {
struct qlink_cmd chdr;
__le64 flags;
__le16 n_ssids;
__le16 n_channels;
__le16 active_dwell;
__le16 passive_dwell;
__le16 sample_duration;
u8 bssid[ETH_ALEN];
u8 scan_width;
u8 rsvd[3];
u8 var_info[0];
} __packed;
/* QLINK Command Responses messages related definitions
*/
@ -1407,13 +1447,6 @@ struct qlink_event_mic_failure {
* @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by
* &struct qlink_sta_stats. Valid values are marked as such in a bitmap
* carried by QTN_TLV_ID_BITMAP.
* @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active
* scan.
* @QTN_TLV_ID_SCAN_DWELL_PASSIVE: time spent on a single channel for a passive
* scan.
* @QTN_TLV_ID_SCAN_SAMPLE_DURATION: total duration of sampling a single channel
* during a scan including off-channel dwell time and operating channel
* time.
* @QTN_TLV_ID_IFTYPE_DATA: supported band data.
*/
enum qlink_tlv_id {
@ -1444,10 +1477,6 @@ enum qlink_tlv_id {
QTN_TLV_ID_RANDOM_MAC_ADDR = 0x0408,
QTN_TLV_ID_WOWLAN_CAPAB = 0x0410,
QTN_TLV_ID_WOWLAN_PATTERN = 0x0411,
QTN_TLV_ID_SCAN_FLUSH = 0x0412,
QTN_TLV_ID_SCAN_DWELL_ACTIVE = 0x0413,
QTN_TLV_ID_SCAN_DWELL_PASSIVE = 0x0416,
QTN_TLV_ID_SCAN_SAMPLE_DURATION = 0x0417,
QTN_TLV_ID_IFTYPE_DATA = 0x0418,
};

View File

@ -28,14 +28,6 @@ static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb,
memcpy(hdr->val, arr, arr_len);
}
static inline void qtnf_cmd_skb_put_tlv_tag(struct sk_buff *skb, u16 tlv_id)
{
struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr));
hdr->type = cpu_to_le16(tlv_id);
hdr->len = cpu_to_le16(0);
}
static inline void qtnf_cmd_skb_put_tlv_u32(struct sk_buff *skb,
u16 tlv_id, u32 value)
{