diff options
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/sysfs.c | 65 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.c | 55 |
4 files changed, 126 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 01a27335ec34..9ce3224fcdd3 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -207,6 +207,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) break; } sta->status = wil_sta_unused; + sta->fst_link_loss = false; } /* reorder buffers */ for (i = 0; i < WIL_STA_TID_NUM; i++) { diff --git a/drivers/net/wireless/ath/wil6210/sysfs.c b/drivers/net/wireless/ath/wil6210/sysfs.c index a3689738a070..b4c4d09011b4 100644 --- a/drivers/net/wireless/ath/wil6210/sysfs.c +++ b/drivers/net/wireless/ath/wil6210/sysfs.c @@ -204,9 +204,74 @@ out: static DEVICE_ATTR(thermal_throttling, 0644, wil_tt_sysfs_show, wil_tt_sysfs_store); +static ssize_t +wil_fst_link_loss_sysfs_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct wil6210_priv *wil = dev_get_drvdata(dev); + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(wil->sta); i++) + if (wil->sta[i].status == wil_sta_connected) + len += snprintf(buf + len, PAGE_SIZE - len, + "[%d] %pM %s\n", i, wil->sta[i].addr, + wil->sta[i].fst_link_loss ? + "On" : "Off"); + + return len; +} + +static ssize_t +wil_fst_link_loss_sysfs_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wil6210_priv *wil = dev_get_drvdata(dev); + u8 addr[ETH_ALEN]; + char *token, *dupbuf, *tmp; + int rc = -EINVAL; + bool fst_link_loss; + + tmp = kmemdup(buf, count + 1, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + tmp[count] = '\0'; + dupbuf = tmp; + + token = strsep(&dupbuf, " "); + if (!token) + goto out; + + /* mac address */ + if (sscanf(token, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &addr[0], &addr[1], &addr[2], + &addr[3], &addr[4], &addr[5]) != 6) + goto out; + + /* On/Off */ + if (strtobool(dupbuf, &fst_link_loss)) + goto out; + + wil_dbg_misc(wil, "set [%pM] with %d\n", addr, fst_link_loss); + + rc = wmi_link_maintain_cfg_write(wil, addr, fst_link_loss); + if (!rc) + rc = count; + +out: + kfree(tmp); + return rc; +} + +static DEVICE_ATTR(fst_link_loss, 0644, + wil_fst_link_loss_sysfs_show, + wil_fst_link_loss_sysfs_store); + static struct attribute *wil6210_sysfs_entries[] = { &dev_attr_ftm_txrx_offset.attr, &dev_attr_thermal_throttling.attr, + &dev_attr_fst_link_loss.attr, NULL }; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f64323b03a3b..e324fb79dd65 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -532,6 +532,7 @@ struct wil_sta_info { struct wil_tid_crypto_rx tid_crypto_rx[WIL_STA_TID_NUM]; struct wil_tid_crypto_rx group_crypto_rx; u8 aid; /* 1-254; 0 if unknown/not reported */ + bool fst_link_loss; }; enum { @@ -980,5 +981,9 @@ void wil_ftm_evt_per_dest_res(struct wil6210_priv *wil, void wil_aoa_evt_meas(struct wil6210_priv *wil, struct wmi_aoa_meas_event *evt, int len); +/* link loss */ +int wmi_link_maintain_cfg_write(struct wil6210_priv *wil, + const u8 *addr, + bool fst_link_loss); #endif /* __WIL6210_H__ */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 6a6ba02beba0..3f2038863271 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1841,6 +1841,61 @@ void wmi_event_flush(struct wil6210_priv *wil) spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); } +int wmi_link_maintain_cfg_write(struct wil6210_priv *wil, + const u8 *addr, + bool fst_link_loss) +{ + int rc; + int cid = wil_find_cid(wil, addr); + u32 cfg_type; + struct wmi_link_maintain_cfg_write_cmd cmd; + struct { + struct wmi_cmd_hdr wmi; + struct wmi_link_maintain_cfg_write_done_event evt; + } __packed reply; + + if (cid < 0) + return cid; + + switch (wil->wdev->iftype) { + case NL80211_IFTYPE_STATION: + cfg_type = fst_link_loss ? + WMI_LINK_MAINTAIN_CFG_TYPE_DEFAULT_FST_STA : + WMI_LINK_MAINTAIN_CFG_TYPE_DEFAULT_NORMAL_STA; + break; + case NL80211_IFTYPE_AP: + cfg_type = fst_link_loss ? + WMI_LINK_MAINTAIN_CFG_TYPE_DEFAULT_FST_AP : + WMI_LINK_MAINTAIN_CFG_TYPE_DEFAULT_NORMAL_AP; + break; + default: + wil_err(wil, "Unsupported for iftype %d", wil->wdev->iftype); + return -EINVAL; + } + + wil_dbg_misc(wil, "Setting cid:%d with cfg_type:%d\n", cid, cfg_type); + + cmd.cfg_type = cpu_to_le32(cfg_type); + cmd.cid = cpu_to_le32(cid); + + reply.evt.status = cpu_to_le32(WMI_FW_STATUS_FAILURE); + + rc = wmi_call(wil, WMI_LINK_MAINTAIN_CFG_WRITE_CMDID, &cmd, sizeof(cmd), + WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID, &reply, + sizeof(reply), 250); + if (rc) { + wil_err(wil, "Failed to %s FST link loss", + fst_link_loss ? "enable" : "disable"); + } else if (reply.evt.status == WMI_FW_STATUS_SUCCESS) { + wil->sta[cid].fst_link_loss = fst_link_loss; + } else { + wil_err(wil, "WMI_LINK_MAINTAIN_CFG_WRITE_CMDID returned status %d", + reply.evt.status); + rc = -EINVAL; + } + return rc; +} + static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, void *d, int len) { |
