Commit 501c3be1 authored by Igor Mitsyanko's avatar Igor Mitsyanko Committed by Kalle Valo

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: default avatarIgor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 5edadc5a
......@@ -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)
int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
{
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;
u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT;
struct wireless_dev *wdev = scan_req->wdev;
struct ieee80211_channel *sc;
struct cfg80211_scan_request *scan_req = mac->scan_req;
int n_channels;
int count = 0;
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;
while (n_channels != 0) {
sc = scan_req->channels[count];
if (sc->flags & IEEE80211_CHAN_DISABLED) {
n_channels--;
continue;
}
for (count = 0; count < scan_req->n_channels; ++count) {
sc = scan_req->channels[count];
if (sc->flags & IEEE80211_CHAN_DISABLED)
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;
......
......@@ -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,
};
......
......@@ -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)
{
......
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