Merge "wil6210: allow flashless boot when OTP is empty"

This commit is contained in:
qctecmdr 2019-12-17 01:57:45 -08:00 • committed by Gerrit - the friendly Code Review server
commit 6ee52846b9
7 changed files with 140 additions and 25 deletions

View file

@ -25,6 +25,9 @@
/* initial token to use on non-secure FTM measurement */
#define WIL_TOF_FTM_DEFAULT_INITIAL_TOKEN 2
/* maximum AOA burst period, limited by FW */
#define WIL_AOA_MAX_BURST_PERIOD 255
#define WIL_TOF_FTM_MAX_LCI_LENGTH (240)
#define WIL_TOF_FTM_MAX_LCR_LENGTH (240)
@ -53,6 +56,7 @@ nla_policy wil_nl80211_ftm_peer_policy[QCA_ATTR_FTM_PEER_MAX + 1] = {
[QCA_ATTR_FTM_PEER_MEAS_FLAGS] = { .type = NLA_U32 },
[QCA_ATTR_FTM_PEER_MEAS_PARAMS] = { .type = NLA_NESTED },
[QCA_ATTR_FTM_PEER_SEC_TOK_ID] = { .type = NLA_U8 },
[QCA_ATTR_FTM_PEER_AOA_BURST_PERIOD] = { .type = NLA_U16 },
[QCA_ATTR_FTM_PEER_FREQ] = { .type = NLA_U32 },
};
@ -351,6 +355,7 @@ wil_ftm_cfg80211_start_session(struct wil6210_vif *vif,
}
cmd->session_id = cpu_to_le32(WIL_FTM_FW_SESSION_ID);
cmd->aoa_type = request->aoa_type;
cmd->num_of_dest = cpu_to_le16(request->n_peers);
for (i = 0; i < request->n_peers; i++) {
ether_addr_copy(cmd->ftm_dest_info[i].dst_mac,
@ -393,6 +398,8 @@ wil_ftm_cfg80211_start_session(struct wil6210_vif *vif,
request->peers[i].params.burst_duration;
cmd->ftm_dest_info[i].burst_period =
cpu_to_le16(request->peers[i].params.burst_period);
cmd->ftm_dest_info[i].num_burst_per_aoa_meas =
request->peers[i].aoa_burst_period;
}
rc = wmi_send(wil, WMI_TOF_SESSION_START_CMDID, vif->mid,
@ -482,8 +489,8 @@ wil_aoa_cfg80211_start_measurement(struct wil6210_vif *vif,
mutex_lock(&vif->ftm.lock);
if (vif->ftm.aoa_started) {
wil_err(wil, "AOA measurement already running\n");
if (vif->ftm.aoa_started || vif->ftm.session_started) {
wil_err(wil, "AOA or FTM measurement already running\n");
rc = -EAGAIN;
goto out;
}
@ -525,8 +532,8 @@ void wil_aoa_cfg80211_meas_result(struct wil6210_vif *vif,
mutex_lock(&vif->ftm.lock);
if (!vif->ftm.aoa_started) {
wil_info(wil, "AOA not started, not sending result\n");
if (!vif->ftm.aoa_started && !vif->ftm.session_started) {
wil_info(wil, "AOA/FTM not started, not sending result\n");
goto out;
}
@ -681,6 +688,10 @@ void wil_aoa_evt_meas(struct wil6210_vif *vif,
int data_len = len - offsetof(struct wmi_aoa_meas_event, meas_data);
struct wil_aoa_meas_result *res;
if (data_len < 0) {
wil_err(wil, "AOA event too short (%d)\n", len);
return;
}
data_len = min_t(int, le16_to_cpu(evt->length), data_len);
res = kmalloc(sizeof(*res) + data_len, GFP_KERNEL);
@ -753,6 +764,7 @@ int wil_ftm_start_session(struct wiphy *wiphy, struct wireless_dev *wdev,
struct nlattr *tb2[QCA_ATTR_FTM_PEER_MAX + 1];
struct nlattr *peer;
int rc, n_peers = 0, index = 0, tmp;
u32 aoa_type = 0;
if (!test_bit(WMI_FW_CAPABILITY_FTM, wil->fw_capabilities))
return -ENOTSUPP;
@ -774,6 +786,14 @@ int wil_ftm_start_session(struct wiphy *wiphy, struct wireless_dev *wdev,
return -EINVAL;
}
if (tb[QCA_ATTR_AOA_TYPE]) {
aoa_type = nla_get_u32(tb[QCA_ATTR_AOA_TYPE]);
if (aoa_type >= QCA_ATTR_AOA_TYPE_MAX) {
wil_err(wil, "invalid AOA type: %d\n", aoa_type);
return -EINVAL;
}
}
nla_for_each_nested(peer, tb[QCA_ATTR_FTM_MEAS_PEERS],
tmp)
n_peers++;
@ -797,6 +817,7 @@ int wil_ftm_start_session(struct wiphy *wiphy, struct wireless_dev *wdev,
request->session_cookie =
nla_get_u64(tb[QCA_ATTR_FTM_SESSION_COOKIE]);
request->aoa_type = aoa_type;
request->n_peers = n_peers;
nla_for_each_nested(peer, tb[QCA_ATTR_FTM_MEAS_PEERS],
tmp) {
@ -825,6 +846,18 @@ int wil_ftm_start_session(struct wiphy *wiphy, struct wireless_dev *wdev,
if (tb2[QCA_ATTR_FTM_PEER_SEC_TOK_ID])
request->peers[index].secure_token_id =
nla_get_u8(tb2[QCA_ATTR_FTM_PEER_SEC_TOK_ID]);
if (tb2[QCA_ATTR_FTM_PEER_AOA_BURST_PERIOD]) {
request->peers[index].aoa_burst_period =
nla_get_u16(tb2[QCA_ATTR_FTM_PEER_AOA_BURST_PERIOD]);
if (request->peers[index].aoa_burst_period >
WIL_AOA_MAX_BURST_PERIOD) {
wil_err(wil, "Invalid AOA burst period at index: %d\n",
index);
rc = -EINVAL;
goto out;
}
}
rc =
wil_ftm_parse_meas_params(wil,
tb2[QCA_ATTR_FTM_PEER_MEAS_PARAMS],

View file

@ -421,12 +421,14 @@ struct wil_ftm_meas_peer_info {
u32 flags; /* enum qca_attr_ftm_peer_meas_flags */
struct wil_ftm_meas_params params;
u8 secure_token_id;
u16 aoa_burst_period; /* 0 if no AOA, >0 every <value> bursts */
};
/* session request, passed to wil_ftm_cfg80211_start_session */
struct wil_ftm_session_request {
u64 session_cookie;
u32 n_peers;
u32 aoa_type; /* enum qca_wlan_vendor_attr_aoa_type */
/* keep last, variable size according to n_peers */
struct wil_ftm_meas_peer_info peers[0];
};

View file

@ -1425,8 +1425,14 @@ static int wil_get_otp_info(struct wil6210_priv *wil)
}
if (!is_valid_ether_addr(mac)) {
wil_err(wil, "Invalid MAC %pM\n", mac);
return -EINVAL;
u8 dummy_mac[ETH_ALEN] = {
0x00, 0xde, 0xad, 0x12, 0x34, 0x56,
};
if (!test_bit(WMI_FW_CAPABILITY_WMI_ONLY, wil->fw_capabilities))
get_random_bytes(dummy_mac + 3, 3);
wil_err(wil, "Invalid MAC %pM, using random %pM\n", mac,
dummy_mac);
ether_addr_copy(mac, dummy_mac);
}
ether_addr_copy(ndev->perm_addr, mac);
@ -1768,14 +1774,18 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
return rc;
}
if (wil->tt_data_set)
wmi_set_tt_cfg(wil, &wil->tt_data);
wil_collect_fw_info(wil);
if (wil->ps_profile != WMI_PS_PROFILE_TYPE_DEFAULT)
wil_ps_update(wil, wil->ps_profile);
if (wil->tt_data_set)
wmi_set_tt_cfg(wil, &wil->tt_data);
if (wil->snr_thresh.enabled)
wmi_set_snr_thresh(wil, wil->snr_thresh.omni,
wil->snr_thresh.direct);
if (wil->platform_ops.notify) {
rc = wil->platform_ops.notify(wil->platform_handle,
WIL_PLATFORM_EVT_FW_RDY);

View file

@ -253,10 +253,47 @@ out:
static DEVICE_ATTR_RW(fst_link_loss);
static ssize_t
snr_thresh_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct wil6210_priv *wil = dev_get_drvdata(dev);
ssize_t len = 0;
if (wil->snr_thresh.enabled)
len = snprintf(buf, PAGE_SIZE, "omni=%d, direct=%d\n",
wil->snr_thresh.omni, wil->snr_thresh.direct);
return len;
}
static ssize_t
snr_thresh_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct wil6210_priv *wil = dev_get_drvdata(dev);
int rc;
short omni, direct;
/* to disable snr threshold, set both omni and direct to 0 */
if (sscanf(buf, "%hd %hd", &omni, &direct) != 2)
return -EINVAL;
rc = wmi_set_snr_thresh(wil, omni, direct);
if (!rc)
rc = count;
return rc;
}
static DEVICE_ATTR_RW(snr_thresh);
static struct attribute *wil6210_sysfs_entries[] = {
&dev_attr_ftm_txrx_offset.attr,
&dev_attr_thermal_throttling.attr,
&dev_attr_fst_link_loss.attr,
&dev_attr_snr_thresh.attr,
NULL
};

View file

@ -1039,6 +1039,11 @@ struct wil6210_priv {
int fw_calib_result;
u8 tt_data_set;
struct wmi_tt_data tt_data;
struct {
u8 enabled;
short omni;
short direct;
} snr_thresh;
struct notifier_block pm_notify;
@ -1440,6 +1445,8 @@ int wmi_link_maintain_cfg_write(struct wil6210_priv *wil,
const u8 *addr,
bool fst_link_loss);
int wmi_set_snr_thresh(struct wil6210_priv *wil, short omni, short direct);
int wmi_start_sched_scan(struct wil6210_priv *wil,
struct cfg80211_sched_scan_request *request);
int wmi_stop_sched_scan(struct wil6210_priv *wil);

View file

@ -826,7 +826,7 @@ static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
s32 signal;
__le16 fc;
u32 d_len;
u16 d_status;
s16 snr;
if (flen < 0) {
wil_err(wil, "MGMT Rx: short event, len %d\n", len);
@ -848,13 +848,13 @@ static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
signal = 100 * data->info.rssi;
else
signal = data->info.sqi;
d_status = le16_to_cpu(data->info.status);
snr = le16_to_cpu(data->info.snr); /* 1/4 dB units */
fc = rx_mgmt_frame->frame_control;
wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d RSSI %d SQI %d%%\n",
data->info.channel, data->info.mcs, data->info.rssi,
data->info.sqi);
wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
wil_dbg_wmi(wil, "snr %ddB len %d fc 0x%04x\n", snr / 4, d_len,
le16_to_cpu(fc));
wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
data->info.qid, data->info.mid, data->info.cid);
@ -888,6 +888,11 @@ static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
if (wil->snr_thresh.enabled && snr < wil->snr_thresh.omni) {
wil_dbg_wmi(wil, "snr below threshold. dropping\n");
return;
}
bss = cfg80211_inform_bss_frame_data(wiphy, &bss_data,
rx_mgmt_frame,
d_len, GFP_KERNEL);
@ -3579,6 +3584,37 @@ out:
return rc;
}
int wmi_set_snr_thresh(struct wil6210_priv *wil, short omni, short direct)
{
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
int rc;
struct wmi_set_connect_snr_thr_cmd cmd = {
.enable = true,
.omni_snr_thr = cpu_to_le16(omni),
.direct_snr_thr = cpu_to_le16(direct),
};
if (!test_bit(WMI_FW_CAPABILITY_CONNECT_SNR_THR, wil->fw_capabilities))
return -ENOTSUPP;
if (omni == 0 && direct == 0)
cmd.enable = false;
wil_dbg_wmi(wil, "%s snr thresh omni=%d, direct=%d (1/4 dB units)\n",
cmd.enable ? "enable" : "disable", omni, direct);
rc = wmi_send(wil, WMI_SET_CONNECT_SNR_THR_CMDID, vif->mid,
&cmd, sizeof(cmd));
if (rc)
return rc;
wil->snr_thresh.enabled = cmd.enable;
wil->snr_thresh.omni = omni;
wil->snr_thresh.direct = direct;
return 0;
}
static void
wmi_sched_scan_set_ssids(struct wil6210_priv *wil,
struct wmi_start_sched_scan_cmd *cmd,

View file

@ -1,19 +1,8 @@
/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2006-2012 Wilocity
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
@ -97,6 +86,7 @@ enum wmi_fw_capability {
WMI_FW_CAPABILITY_SET_SILENT_RSSI_TABLE = 13,
WMI_FW_CAPABILITY_LO_POWER_CALIB_FROM_OTP = 14,
WMI_FW_CAPABILITY_PNO = 15,
WMI_FW_CAPABILITY_CONNECT_SNR_THR = 16,
WMI_FW_CAPABILITY_CHANNEL_BONDING = 17,
WMI_FW_CAPABILITY_REF_CLOCK_CONTROL = 18,
WMI_FW_CAPABILITY_AP_SME_OFFLOAD_NONE = 19,
@ -2436,7 +2426,7 @@ struct wmi_rx_mgmt_info {
u8 range;
u8 sqi;
__le16 stype;
__le16 status;
__le16 snr;
__le32 len;
/* Not resolved when == 0xFFFFFFFF == > Broadcast to all MIDS */
u8 qid;