提交 e00243fa 编写于 作者: L Lior David 提交者: Kalle Valo

wil6210: infrastructure for multiple virtual interfaces

Simple infrastructure changes for supporting multiple
virtual interfaces (multiple VIFs).
It is still not possible to add new VIFs so the only VIF
belongs to the main interface.
Main changes:
1. Add MAC ID(mid) argument to wmi_send and wmi_call to
allow invoking WMI commands on different VIFs.
2. Similarly, in WMI event handler look at the mid reported
by FW and extract VIF structure (currently only for main
interface). All WMI event handlers operate on wil6210_vif
structure so they know on which VIF they were called.
3. Trivial changes to use wil6210_vif structure and MID
throughout the code.
4. Various changes to logging to report MID.

More complete multiple VIFs support will be added gradually
in next patches.
Signed-off-by: NLior David <liord@codeaurora.org>
Signed-off-by: NMaya Erez <merez@codeaurora.org>
Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
上级 7bfe9e22
/*
* Copyright (c) 2013,2016 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -25,7 +26,7 @@ void __wil_err(struct wil6210_priv *wil, const char *fmt, ...)
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
netdev_err(wil_to_ndev(wil), "%pV", &vaf);
netdev_err(wil->main_ndev, "%pV", &vaf);
trace_wil6210_log_err(&vaf);
va_end(args);
}
......@@ -41,7 +42,7 @@ void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
netdev_err(wil_to_ndev(wil), "%pV", &vaf);
netdev_err(wil->main_ndev, "%pV", &vaf);
trace_wil6210_log_err(&vaf);
va_end(args);
}
......@@ -57,7 +58,7 @@ void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...)
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
netdev_dbg(wil_to_ndev(wil), "%pV", &vaf);
netdev_dbg(wil->main_ndev, "%pV", &vaf);
trace_wil6210_log_dbg(&vaf);
va_end(args);
}
......@@ -70,7 +71,7 @@ void __wil_info(struct wil6210_priv *wil, const char *fmt, ...)
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
netdev_info(wil_to_ndev(wil), "%pV", &vaf);
netdev_info(wil->main_ndev, "%pV", &vaf);
trace_wil6210_log_info(&vaf);
va_end(args);
}
......
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -621,7 +622,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
size_t len, loff_t *ppos)
{
struct wil6210_priv *wil = file->private_data;
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
/**
* BUG:
......@@ -716,27 +717,44 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf,
if (rc < 2)
return -EINVAL;
if (0 == strcmp(cmd, "add")) {
if (rc < 3) {
wil_err(wil, "BACK: add require at least 2 params\n");
if ((strcmp(cmd, "add") == 0) ||
(strcmp(cmd, "del_tx") == 0)) {
struct vring_tx_data *txdata;
if (p1 < 0 || p1 >= WIL6210_MAX_TX_RINGS) {
wil_err(wil, "BACK: invalid ring id %d\n", p1);
return -EINVAL;
}
if (rc < 4)
p3 = 0;
wmi_addba(wil, p1, p2, p3);
} else if (0 == strcmp(cmd, "del_tx")) {
if (rc < 3)
p2 = WLAN_REASON_QSTA_LEAVE_QBSS;
wmi_delba_tx(wil, p1, p2);
} else if (0 == strcmp(cmd, "del_rx")) {
txdata = &wil->vring_tx_data[p1];
if (strcmp(cmd, "add") == 0) {
if (rc < 3) {
wil_err(wil, "BACK: add require at least 2 params\n");
return -EINVAL;
}
if (rc < 4)
p3 = 0;
wmi_addba(wil, txdata->mid, p1, p2, p3);
} else {
if (rc < 3)
p2 = WLAN_REASON_QSTA_LEAVE_QBSS;
wmi_delba_tx(wil, txdata->mid, p1, p2);
}
} else if (strcmp(cmd, "del_rx") == 0) {
struct wil_sta_info *sta;
if (rc < 3) {
wil_err(wil,
"BACK: del_rx require at least 2 params\n");
return -EINVAL;
}
if (p1 < 0 || p1 >= WIL6210_MAX_CID) {
wil_err(wil, "BACK: invalid CID %d\n", p1);
return -EINVAL;
}
if (rc < 4)
p3 = WLAN_REASON_QSTA_LEAVE_QBSS;
wmi_delba_rx(wil, mk_cidxtid(p1, p2), p3);
sta = &wil->sta[p1];
wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3);
} else {
wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd);
return -EINVAL;
......@@ -855,7 +873,7 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
{
struct wil6210_priv *wil = file->private_data;
struct wiphy *wiphy = wil_to_wiphy(wil);
struct wireless_dev *wdev = wil_to_wdev(wil);
struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
struct cfg80211_mgmt_tx_params params;
int rc;
void *frame;
......@@ -890,6 +908,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
size_t len, loff_t *ppos)
{
struct wil6210_priv *wil = file->private_data;
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
struct wmi_cmd_hdr *wmi;
void *cmd;
int cmdlen = len - sizeof(struct wmi_cmd_hdr);
......@@ -912,7 +931,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
cmd = (cmdlen > 0) ? &wmi[1] : NULL;
cmdid = le16_to_cpu(wmi->command_id);
rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
rc1 = wmi_send(wil, cmdid, vif->mid, cmd, cmdlen);
kfree(wmi);
wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1);
......@@ -1050,6 +1069,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data)
int rc;
int i;
struct wil6210_priv *wil = s->private;
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
struct wmi_notify_req_cmd cmd = {
.interval_usec = 0,
};
......@@ -1062,7 +1082,8 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data)
u32 status;
cmd.cid = i;
rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid,
&cmd, sizeof(cmd),
WMI_NOTIFY_REQ_DONE_EVENTID, &reply,
sizeof(reply), 20);
/* if reply is all-0, ignore this CID */
......@@ -1155,7 +1176,7 @@ static const struct file_operations fops_temp = {
static int wil_freq_debugfs_show(struct seq_file *s, void *data)
{
struct wil6210_priv *wil = s->private;
struct wireless_dev *wdev = wil_to_wdev(wil);
struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
seq_printf(s, "Freq = %d\n", freq);
......@@ -1180,6 +1201,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data)
{
struct wil6210_priv *wil = s->private;
struct station_info sinfo;
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
int i, rc;
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
......@@ -1200,7 +1222,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data)
seq_printf(s, "[%d] %pM %s\n", i, p->addr, status);
if (p->status == wil_sta_connected) {
rc = wil_cid_fill_sinfo(wil, i, &sinfo);
rc = wil_cid_fill_sinfo(vif, i, &sinfo);
if (rc)
return rc;
......@@ -1229,7 +1251,7 @@ static const struct file_operations fops_link = {
static int wil_info_debugfs_show(struct seq_file *s, void *data)
{
struct wil6210_priv *wil = s->private;
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
int is_ac = power_supply_is_system_supplied();
int rx = atomic_xchg(&wil->isr_count_rx, 0);
int tx = atomic_xchg(&wil->isr_count_tx, 0);
......@@ -1773,11 +1795,9 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil,
/* fields in struct wil6210_priv */
static const struct dbg_off dbg_wil_off[] = {
WIL_FIELD(privacy, 0444, doff_u32),
WIL_FIELD(status[0], 0644, doff_ulong),
WIL_FIELD(hw_version, 0444, doff_x32),
WIL_FIELD(recovery_count, 0444, doff_u32),
WIL_FIELD(ap_isolate, 0444, doff_u32),
WIL_FIELD(discovery_mode, 0644, doff_u8),
WIL_FIELD(chip_revision, 0444, doff_u8),
WIL_FIELD(abft_len, 0644, doff_u8),
......
/*
* Copyright (c) 2014,2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -74,12 +75,13 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev,
struct ethtool_coalesce *cp)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
struct wireless_dev *wdev = ndev->ieee80211_ptr;
int ret;
wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n",
cp->rx_coalesce_usecs, cp->tx_coalesce_usecs);
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n");
return -EINVAL;
}
......
......@@ -188,12 +188,14 @@ void wil_unmask_irq(struct wil6210_priv *wil)
void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
{
struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
wil_dbg_irq(wil, "configure_interrupt_moderation\n");
/* disable interrupt moderation for monitor
* to get better timestamp precision
*/
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR)
if (wdev->iftype == NL80211_IFTYPE_MONITOR)
return;
/* Disable and clear tx counter before (re)configuration */
......@@ -340,7 +342,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
static void wil_notify_fw_error(struct wil6210_priv *wil)
{
struct device *dev = &wil_to_ndev(wil)->dev;
struct device *dev = &wil->main_ndev->dev;
char *envp[3] = {
[0] = "SOURCE=wil6210",
[1] = "EVENT=FW_ERROR",
......
......@@ -160,24 +160,25 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
}
}
static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
static void wil_disconnect_cid(struct wil6210_vif *vif, int cid,
u16 reason_code, bool from_event)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
uint i;
struct net_device *ndev = wil_to_ndev(wil);
struct wireless_dev *wdev = wil->wdev;
struct wil6210_priv *wil = vif_to_wil(vif);
struct net_device *ndev = vif_to_ndev(vif);
struct wireless_dev *wdev = vif_to_wdev(vif);
struct wil_sta_info *sta = &wil->sta[cid];
might_sleep();
wil_dbg_misc(wil, "disconnect_cid: CID %d, status %d\n",
cid, sta->status);
wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n",
cid, sta->mid, sta->status);
/* inform upper/lower layers */
if (sta->status != wil_sta_unused) {
if (!from_event) {
bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ?
disable_ap_sme : false;
wmi_disconnect_sta(wil, sta->addr, reason_code,
wmi_disconnect_sta(vif, sta->addr, reason_code,
true, del_sta);
}
......@@ -191,6 +192,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
break;
}
sta->status = wil_sta_unused;
sta->mid = U8_MAX;
}
/* reorder buffers */
for (i = 0; i < WIL_STA_TID_NUM; i++) {
......@@ -216,28 +218,33 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
memset(&sta->stats, 0, sizeof(sta->stats));
}
static bool wil_is_connected(struct wil6210_priv *wil)
static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid)
{
int i;
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
if (wil->sta[i].status == wil_sta_connected)
if (wil->sta[i].mid == mid &&
wil->sta[i].status == wil_sta_connected)
return true;
}
return false;
}
static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
u16 reason_code, bool from_event)
{
struct wil6210_priv *wil = vif_to_wil(vif);
int cid = -ENOENT;
struct net_device *ndev = wil_to_ndev(wil);
struct wireless_dev *wdev = wil->wdev;
struct net_device *ndev;
struct wireless_dev *wdev;
if (unlikely(!ndev))
if (unlikely(!vif))
return;
ndev = vif_to_ndev(vif);
wdev = vif_to_wdev(vif);
might_sleep();
wil_info(wil, "bssid=%pM, reason=%d, ev%s\n", bssid,
reason_code, from_event ? "+" : "-");
......@@ -254,22 +261,22 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
*/
if (bssid && !is_broadcast_ether_addr(bssid) &&
!ether_addr_equal_unaligned(ndev->dev_addr, bssid)) {
cid = wil_find_cid(wil, bssid);
cid = wil_find_cid(wil, vif->mid, bssid);
wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n",
bssid, cid, reason_code);
if (cid >= 0) /* disconnect 1 peer */
wil_disconnect_cid(wil, cid, reason_code, from_event);
wil_disconnect_cid(vif, cid, reason_code, from_event);
} else { /* all */
wil_dbg_misc(wil, "Disconnect all\n");
for (cid = 0; cid < WIL6210_MAX_CID; cid++)
wil_disconnect_cid(wil, cid, reason_code, from_event);
wil_disconnect_cid(vif, cid, reason_code, from_event);
}
/* link state */
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
wil_bcast_fini(wil);
wil_bcast_fini(vif);
wil_update_net_queues_bh(wil, NULL, true);
netif_carrier_off(ndev);
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
......@@ -278,20 +285,20 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
clear_bit(wil_status_fwconnected, wil->status);
cfg80211_disconnected(ndev, reason_code,
NULL, 0,
wil->locally_generated_disc,
vif->locally_generated_disc,
GFP_KERNEL);
wil->locally_generated_disc = false;
vif->locally_generated_disc = false;
} else if (test_bit(wil_status_fwconnecting, wil->status)) {
cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
wil->bss = NULL;
vif->bss = NULL;
}
clear_bit(wil_status_fwconnecting, wil->status);
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
if (!wil_is_connected(wil)) {
if (!wil_vif_is_connected(wil, vif->mid)) {
wil_update_net_queues_bh(wil, NULL, true);
clear_bit(wil_status_fwconnected, wil->status);
} else {
......@@ -303,11 +310,12 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
}
}
static void wil_disconnect_worker(struct work_struct *work)
void wil_disconnect_worker(struct work_struct *work)
{
struct wil6210_priv *wil = container_of(work,
struct wil6210_priv, disconnect_worker);
struct net_device *ndev = wil_to_ndev(wil);
struct wil6210_vif *vif = container_of(work,
struct wil6210_vif, disconnect_worker);
struct wil6210_priv *wil = vif_to_wil(vif);
struct net_device *ndev = vif_to_ndev(vif);
int rc;
struct {
struct wmi_cmd_hdr wmi;
......@@ -322,7 +330,7 @@ static void wil_disconnect_worker(struct work_struct *work)
/* already disconnected */
return;
rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0,
WMI_DISCONNECT_EVENTID, &reply, sizeof(reply),
WIL6210_DISCONNECT_TO_MS);
if (rc) {
......@@ -337,30 +345,6 @@ static void wil_disconnect_worker(struct work_struct *work)
clear_bit(wil_status_fwconnecting, wil->status);
}
static void wil_connect_timer_fn(struct timer_list *t)
{
struct wil6210_priv *wil = from_timer(wil, t, connect_timer);
bool q;
wil_err(wil, "Connect timeout detected, disconnect station\n");
/* reschedule to thread context - disconnect won't
* run from atomic context.
* queue on wmi_wq to prevent race with connect event.
*/
q = queue_work(wil->wmi_wq, &wil->disconnect_worker);
wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q);
}
static void wil_scan_timer_fn(struct timer_list *t)
{
struct wil6210_priv *wil = from_timer(wil, t, scan_timer);
clear_bit(wil_status_fwready, wil->status);
wil_err(wil, "Scan timeout detected, start fw error recovery\n");
wil_fw_error_recovery(wil);
}
static int wil_wait_for_recovery(struct wil6210_priv *wil)
{
if (wait_event_interruptible(wil->wq, wil->recovery_state !=
......@@ -394,12 +378,12 @@ static void wil_fw_error_worker(struct work_struct *work)
{
struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
fw_error_worker);
struct wireless_dev *wdev = wil->wdev;
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct wireless_dev *wdev = ndev->ieee80211_ptr;
wil_dbg_misc(wil, "fw error worker\n");
if (!(ndev->flags & IFF_UP)) {
if (!ndev || !(ndev->flags & IFF_UP)) {
wil_info(wil, "No recovery - interface is down\n");
return;
}
......@@ -429,6 +413,10 @@ static void wil_fw_error_worker(struct work_struct *work)
return;
mutex_lock(&wil->mutex);
/* Needs adaptation for multiple VIFs
* need to go over all VIFs and consider the appropriate
* recovery.
*/
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
......@@ -461,8 +449,9 @@ static int wil_find_free_vring(struct wil6210_priv *wil)
return -EINVAL;
}
int wil_tx_init(struct wil6210_priv *wil, int cid)
int wil_tx_init(struct wil6210_vif *vif, int cid)
{
struct wil6210_priv *wil = vif_to_wil(vif);
int rc = -EINVAL, ringid;
if (cid < 0) {
......@@ -475,21 +464,22 @@ int wil_tx_init(struct wil6210_priv *wil, int cid)
goto out;
}
wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n",
cid, ringid);
wil_dbg_wmi(wil, "Configure for connection CID %d MID %d vring %d\n",
cid, vif->mid, ringid);
rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
rc = wil_vring_init_tx(vif, ringid, 1 << tx_ring_order, cid, 0);
if (rc)
wil_err(wil, "wil_vring_init_tx for CID %d vring %d failed\n",
cid, ringid);
wil_err(wil, "init TX for CID %d MID %d vring %d failed\n",
cid, vif->mid, ringid);
out:
return rc;
}
int wil_bcast_init(struct wil6210_priv *wil)
int wil_bcast_init(struct wil6210_vif *vif)
{
int ri = wil->bcast_vring, rc;
struct wil6210_priv *wil = vif_to_wil(vif);
int ri = vif->bcast_vring, rc;
if ((ri >= 0) && wil->vring_tx[ri].va)
return 0;
......@@ -498,22 +488,23 @@ int wil_bcast_init(struct wil6210_priv *wil)
if (ri < 0)
return ri;
wil->bcast_vring = ri;
rc = wil_vring_init_bcast(wil, ri, 1 << bcast_ring_order);
vif->bcast_vring = ri;
rc = wil_vring_init_bcast(vif, ri, 1 << bcast_ring_order);
if (rc)
wil->bcast_vring = -1;
vif->bcast_vring = -1;
return rc;
}
void wil_bcast_fini(struct wil6210_priv *wil)
void wil_bcast_fini(struct wil6210_vif *vif)
{
int ri = wil->bcast_vring;
struct wil6210_priv *wil = vif_to_wil(vif);
int ri = vif->bcast_vring;
if (ri < 0)
return;
wil->bcast_vring = -1;
vif->bcast_vring = -1;
wil_vring_fini_tx(wil, ri);
}
......@@ -524,15 +515,16 @@ int wil_priv_init(struct wil6210_priv *wil)
wil_dbg_misc(wil, "priv_init\n");
memset(wil->sta, 0, sizeof(wil->sta));
for (i = 0; i < WIL6210_MAX_CID; i++)
for (i = 0; i < WIL6210_MAX_CID; i++) {
spin_lock_init(&wil->sta[i].tid_rx_lock);
wil->sta[i].mid = U8_MAX;
}
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++)
spin_lock_init(&wil->vring_tx_data[i].lock);
mutex_init(&wil->mutex);
mutex_init(&wil->wmi_mutex);
mutex_init(&wil->probe_client_mutex);
mutex_init(&wil->p2p_wdev_mutex);
mutex_init(&wil->halp.lock);
......@@ -540,22 +532,12 @@ int wil_priv_init(struct wil6210_priv *wil)
init_completion(&wil->wmi_call);
init_completion(&wil->halp.comp);
wil->bcast_vring = -1;
timer_setup(&wil->connect_timer, wil_connect_timer_fn, 0);
timer_setup(&wil->scan_timer, wil_scan_timer_fn, 0);
timer_setup(&wil->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0);
INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker);
INIT_WORK(&wil->p2p.delayed_listen_work, wil_p2p_delayed_listen_work);
INIT_LIST_HEAD(&wil->pending_wmi_ev);
INIT_LIST_HEAD(&wil->probe_client_pending);
spin_lock_init(&wil->wmi_ev_lock);
spin_lock_init(&wil->net_queue_lock);
wil->net_queue_stopped = 1;
init_waitqueue_head(&wil->wq);
wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi");
......@@ -582,6 +564,8 @@ int wil_priv_init(struct wil6210_priv *wil)
memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
wil->vring_idle_trsh = 16;
wil->reply_mid = U8_MAX;
return 0;
out_wmi_wq:
......@@ -600,7 +584,7 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
/**
* wil6210_disconnect - disconnect one connection
* @wil: driver context
* @vif: virtual interface context
* @bssid: peer to disconnect, NULL to disconnect all
* @reason_code: Reason code for the Disassociation frame
* @from_event: whether is invoked from FW event handler
......@@ -608,13 +592,15 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
* Disconnect and release associated resources. If invoked not from the
* FW event handler, issue WMI command(s) to trigger MAC disconnect.
*/
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
u16 reason_code, bool from_event)
{
struct wil6210_priv *wil = vif_to_wil(vif);
wil_dbg_misc(wil, "disconnect\n");
del_timer_sync(&wil->connect_timer);
_wil6210_disconnect(wil, bssid, reason_code, from_event);
del_timer_sync(&vif->connect_timer);
_wil6210_disconnect(vif, bssid, reason_code, from_event);
}
void wil_priv_deinit(struct wil6210_priv *wil)
......@@ -622,18 +608,8 @@ void wil_priv_deinit(struct wil6210_priv *wil)
wil_dbg_misc(wil, "priv_deinit\n");
wil_set_recovery_state(wil, fw_recovery_idle);
del_timer_sync(&wil->scan_timer);
del_timer_sync(&wil->p2p.discovery_timer);
cancel_work_sync(&wil->disconnect_worker);
cancel_work_sync(&wil->fw_error_worker);
cancel_work_sync(&wil->p2p.discovery_expired_work);
cancel_work_sync(&wil->p2p.delayed_listen_work);
mutex_lock(&wil->mutex);
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
mutex_unlock(&wil->mutex);
wmi_event_flush(wil);
wil_probe_client_flush(wil);
cancel_work_sync(&wil->probe_client_worker);
destroy_workqueue(wil->wq_service);
destroy_workqueue(wil->wmi_wq);
}
......@@ -943,7 +919,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
static int wil_get_bl_info(struct wil6210_priv *wil)
{
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct wiphy *wiphy = wil_to_wiphy(wil);
union {
struct bl_dedicated_registers_v0 bl0;
......@@ -1035,7 +1011,7 @@ static void wil_bl_crash_info(struct wil6210_priv *wil, bool is_err)
static int wil_get_otp_info(struct wil6210_priv *wil)
{
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct wiphy *wiphy = wil_to_wiphy(wil);
u8 mac[8];
......@@ -1069,8 +1045,9 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
return 0;
}
void wil_abort_scan(struct wil6210_priv *wil, bool sync)
void wil_abort_scan(struct wil6210_vif *vif, bool sync)
{
struct wil6210_priv *wil = vif_to_wil(vif);
int rc;
struct cfg80211_scan_info info = {
.aborted = true,
......@@ -1078,22 +1055,22 @@ void wil_abort_scan(struct wil6210_priv *wil, bool sync)
lockdep_assert_held(&wil->p2p_wdev_mutex);
if (!wil->scan_request)
if (!vif->scan_request)
return;
wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request);
del_timer_sync(&wil->scan_timer);
wil_dbg_misc(wil, "Abort scan_request 0x%p\n", vif->scan_request);
del_timer_sync(&vif->scan_timer);
mutex_unlock(&wil->p2p_wdev_mutex);
rc = wmi_abort_scan(wil);
rc = wmi_abort_scan(vif);
if (!rc && sync)
wait_event_interruptible_timeout(wil->wq, !wil->scan_request,
wait_event_interruptible_timeout(wil->wq, !vif->scan_request,
msecs_to_jiffies(
WAIT_FOR_SCAN_ABORT_MS));
mutex_lock(&wil->p2p_wdev_mutex);
if (wil->scan_request) {
cfg80211_scan_done(wil->scan_request, &info);
wil->scan_request = NULL;
if (vif->scan_request) {
cfg80211_scan_done(vif->scan_request, &info);
vif->scan_request = NULL;
}
}
......@@ -1148,6 +1125,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
int rc;
unsigned long status_flags = BIT(wil_status_resetting);
int no_flash;
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
wil_dbg_misc(wil, "reset\n");
......@@ -1158,7 +1136,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
static const u8 mac[ETH_ALEN] = {
0x00, 0xde, 0xad, 0x12, 0x34, 0x56,
};
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
ether_addr_copy(ndev->perm_addr, mac);
ether_addr_copy(ndev->dev_addr, ndev->perm_addr);
......@@ -1196,15 +1174,15 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
goto out;
}
cancel_work_sync(&wil->disconnect_worker);
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
wil_bcast_fini(wil);
cancel_work_sync(&vif->disconnect_worker);
wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
wil_bcast_fini(vif);
/* Disable device led before reset*/
wmi_led_cfg(wil, false);
mutex_lock(&wil->p2p_wdev_mutex);
wil_abort_scan(wil, false);
wil_abort_scan(vif, false);
mutex_unlock(&wil->p2p_wdev_mutex);
/* prevent NAPI from being scheduled and prevent wmi commands */
......@@ -1276,7 +1254,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
}
/* init after reset */
wil->ap_isolate = 0;
vif->ap_isolate = 0;
reinit_completion(&wil->wmi_ready);
reinit_completion(&wil->wmi_call);
reinit_completion(&wil->halp.comp);
......@@ -1337,8 +1315,8 @@ void wil_fw_error_recovery(struct wil6210_priv *wil)
int __wil_up(struct wil6210_priv *wil)
{
struct net_device *ndev = wil_to_ndev(wil);
struct wireless_dev *wdev = wil->wdev;
struct net_device *ndev = wil->main_ndev;
struct wireless_dev *wdev = ndev->ieee80211_ptr;
int rc;
WARN_ON(!mutex_is_locked(&wil->mutex));
......@@ -1422,7 +1400,7 @@ int __wil_down(struct wil6210_priv *wil)
mutex_lock(&wil->p2p_wdev_mutex);
wil_p2p_stop_radio_operations(wil);
wil_abort_scan(wil, false);
wil_abort_scan(ndev_to_vif(wil->main_ndev), false);
mutex_unlock(&wil->p2p_wdev_mutex);
return wil_reset(wil, false);
......@@ -1442,13 +1420,14 @@ int wil_down(struct wil6210_priv *wil)
return rc;
}
int wil_find_cid(struct wil6210_priv *wil, const u8 *mac)
int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac)
{
int i;
int rc = -ENOENT;
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
if ((wil->sta[i].status != wil_sta_unused) &&
if (wil->sta[i].mid == mid &&
wil->sta[i].status != wil_sta_unused &&
ether_addr_equal(wil->sta[i].addr, mac)) {
rc = i;
break;
......
......@@ -122,6 +122,85 @@ static void wil_dev_setup(struct net_device *dev)
dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;
}
static void wil_vif_deinit(struct wil6210_vif *vif)
{
del_timer_sync(&vif->scan_timer);
del_timer_sync(&vif->p2p.discovery_timer);
cancel_work_sync(&vif->disconnect_worker);
cancel_work_sync(&vif->p2p.discovery_expired_work);
cancel_work_sync(&vif->p2p.delayed_listen_work);
wil_probe_client_flush(vif);
cancel_work_sync(&vif->probe_client_worker);
}
void wil_vif_free(struct wil6210_vif *vif)
{
struct net_device *ndev = vif_to_ndev(vif);
wil_vif_deinit(vif);
free_netdev(ndev);
}
static void wil_ndev_destructor(struct net_device *ndev)
{
struct wil6210_vif *vif = ndev_to_vif(ndev);
wil_vif_deinit(vif);
}
static void wil_connect_timer_fn(struct timer_list *t)
{
struct wil6210_vif *vif = from_timer(vif, t, connect_timer);
struct wil6210_priv *wil = vif_to_wil(vif);
bool q;
wil_err(wil, "Connect timeout detected, disconnect station\n");
/* reschedule to thread context - disconnect won't
* run from atomic context.
* queue on wmi_wq to prevent race with connect event.
*/
q = queue_work(wil->wmi_wq, &vif->disconnect_worker);
wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q);
}
static void wil_scan_timer_fn(struct timer_list *t)
{
struct wil6210_vif *vif = from_timer(vif, t, scan_timer);
struct wil6210_priv *wil = vif_to_wil(vif);
clear_bit(wil_status_fwready, wil->status);
wil_err(wil, "Scan timeout detected, start fw error recovery\n");
wil_fw_error_recovery(wil);
}
static void wil_p2p_discovery_timer_fn(struct timer_list *t)
{
struct wil6210_vif *vif = from_timer(vif, t, p2p.discovery_timer);
struct wil6210_priv *wil = vif_to_wil(vif);
wil_dbg_misc(wil, "p2p_discovery_timer_fn\n");
schedule_work(&vif->p2p.discovery_expired_work);
}
static void wil_vif_init(struct wil6210_vif *vif)
{
vif->bcast_vring = -1;
mutex_init(&vif->probe_client_mutex);
timer_setup(&vif->connect_timer, wil_connect_timer_fn, 0);
timer_setup(&vif->scan_timer, wil_scan_timer_fn, 0);
timer_setup(&vif->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0);
INIT_WORK(&vif->probe_client_worker, wil_probe_client_worker);
INIT_WORK(&vif->disconnect_worker, wil_disconnect_worker);
INIT_WORK(&vif->p2p.delayed_listen_work, wil_p2p_delayed_listen_work);
INIT_LIST_HEAD(&vif->probe_client_pending);
}
struct wil6210_vif *
wil_vif_alloc(struct wil6210_priv *wil, const char *name,
unsigned char name_assign_type, enum nl80211_iftype iftype,
......@@ -138,10 +217,12 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name,
return ERR_PTR(-ENOMEM);
}
if (mid == 0)
wil->ndev = ndev;
wil->main_ndev = ndev;
vif = ndev_to_vif(ndev);
vif->ndev = ndev;
vif->wil = wil;
vif->mid = mid;
wil_vif_init(vif);
wdev = &vif->wdev;
wdev->wiphy = wil->wiphy;
......@@ -163,7 +244,6 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name,
void *wil_if_alloc(struct device *dev)
{
struct wireless_dev *wdev;
struct wil6210_priv *wil;
struct wil6210_vif *vif;
int rc = 0;
......@@ -190,9 +270,7 @@ void *wil_if_alloc(struct device *dev)
goto out_priv;
}
wdev = &vif->wdev;
wil->wdev = wdev;
wil->radio_wdev = wdev;
wil->radio_wdev = vif_to_wdev(vif);
return wil;
......@@ -207,7 +285,7 @@ void *wil_if_alloc(struct device *dev)
void wil_if_free(struct wil6210_priv *wil)
{
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
wil_dbg_misc(wil, "if_free\n");
......@@ -216,7 +294,8 @@ void wil_if_free(struct wil6210_priv *wil)
wil_priv_deinit(wil);
wil_to_ndev(wil) = NULL;
wil->main_ndev = NULL;
wil_ndev_destructor(ndev);
free_netdev(ndev);
wil_cfg80211_deinit(wil);
......@@ -224,9 +303,8 @@ void wil_if_free(struct wil6210_priv *wil)
int wil_if_add(struct wil6210_priv *wil)
{
struct wireless_dev *wdev = wil_to_wdev(wil);
struct wiphy *wiphy = wil->wiphy;
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
int rc;
wil_dbg_misc(wil, "entered");
......@@ -255,14 +333,14 @@ int wil_if_add(struct wil6210_priv *wil)
return 0;
out_wiphy:
wiphy_unregister(wdev->wiphy);
wiphy_unregister(wiphy);
return rc;
}
void wil_if_remove(struct wil6210_priv *wil)
{
struct net_device *ndev = wil_to_ndev(wil);
struct wireless_dev *wdev = wil_to_wdev(wil);
struct net_device *ndev = wil->main_ndev;
struct wireless_dev *wdev = ndev->ieee80211_ptr;
wil_dbg_misc(wil, "if_remove\n");
......
/*
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -22,27 +23,28 @@
#define P2P_SEARCH_DURATION_MS 500
#define P2P_DEFAULT_BI 100
static int wil_p2p_start_listen(struct wil6210_priv *wil)
static int wil_p2p_start_listen(struct wil6210_vif *vif)
{
struct wil_p2p_info *p2p = &wil->p2p;
struct wil6210_priv *wil = vif_to_wil(vif);
struct wil_p2p_info *p2p = &vif->p2p;
u8 channel = p2p->listen_chan.hw_value;
int rc;
lockdep_assert_held(&wil->mutex);
rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI);
rc = wmi_p2p_cfg(vif, channel, P2P_DEFAULT_BI);
if (rc) {
wil_err(wil, "wmi_p2p_cfg failed\n");
goto out;
}
rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
rc = wmi_set_ssid(vif, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
if (rc) {
wil_err(wil, "wmi_set_ssid failed\n");
goto out_stop;
}
rc = wmi_start_listen(wil);
rc = wmi_start_listen(vif);
if (rc) {
wil_err(wil, "wmi_start_listen failed\n");
goto out_stop;
......@@ -53,7 +55,7 @@ static int wil_p2p_start_listen(struct wil6210_priv *wil)
jiffies + msecs_to_jiffies(p2p->listen_duration));
out_stop:
if (rc)
wmi_stop_discovery(wil);
wmi_stop_discovery(vif);
out:
return rc;
......@@ -65,20 +67,12 @@ bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request)
(request->channels[0]->hw_value == P2P_DMG_SOCIAL_CHANNEL);
}
void wil_p2p_discovery_timer_fn(struct timer_list *t)
{
struct wil6210_priv *wil = from_timer(wil, t, p2p.discovery_timer);
wil_dbg_misc(wil, "p2p_discovery_timer_fn\n");
schedule_work(&wil->p2p.discovery_expired_work);
}
int wil_p2p_search(struct wil6210_priv *wil,
int wil_p2p_search(struct wil6210_vif *vif,
struct cfg80211_scan_request *request)
{
struct wil6210_priv *wil = vif_to_wil(vif);
int rc;
struct wil_p2p_info *p2p = &wil->p2p;
struct wil_p2p_info *p2p = &vif->p2p;
wil_dbg_misc(wil, "p2p_search: channel %d\n", P2P_DMG_SOCIAL_CHANNEL);
......@@ -90,20 +84,20 @@ int wil_p2p_search(struct wil6210_priv *wil,
goto out;
}
rc = wmi_p2p_cfg(wil, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI);
rc = wmi_p2p_cfg(vif, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI);
if (rc) {
wil_err(wil, "wmi_p2p_cfg failed\n");
goto out;
}
rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
rc = wmi_set_ssid(vif, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
if (rc) {
wil_err(wil, "wmi_set_ssid failed\n");
goto out_stop;
}
/* Set application IE to probe request and probe response */
rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ,
rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ,
request->ie_len, request->ie);
if (rc) {
wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n");
......@@ -113,14 +107,14 @@ int wil_p2p_search(struct wil6210_priv *wil,
/* supplicant doesn't provide Probe Response IEs. As a workaround -
* re-use Probe Request IEs
*/
rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP,
rc = wmi_set_ie(vif, WMI_FRAME_PROBE_RESP,
request->ie_len, request->ie);
if (rc) {
wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n");
goto out_stop;
}
rc = wmi_start_search(wil);
rc = wmi_start_search(vif);
if (rc) {
wil_err(wil, "wmi_start_search failed\n");
goto out_stop;
......@@ -133,7 +127,7 @@ int wil_p2p_search(struct wil6210_priv *wil,
out_stop:
if (rc)
wmi_stop_discovery(wil);
wmi_stop_discovery(vif);
out:
return rc;
......@@ -143,7 +137,8 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
unsigned int duration, struct ieee80211_channel *chan,
u64 *cookie)
{
struct wil_p2p_info *p2p = &wil->p2p;
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
struct wil_p2p_info *p2p = &vif->p2p;
int rc;
if (!chan)
......@@ -164,7 +159,7 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
p2p->listen_duration = duration;
mutex_lock(&wil->p2p_wdev_mutex);
if (wil->scan_request) {
if (vif->scan_request) {
wil_dbg_misc(wil, "Delaying p2p listen until scan done\n");
p2p->pending_listen_wdev = wdev;
p2p->discovery_started = 1;
......@@ -174,12 +169,13 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
}
mutex_unlock(&wil->p2p_wdev_mutex);
rc = wil_p2p_start_listen(wil);
rc = wil_p2p_start_listen(vif);
if (rc)
goto out;
p2p->discovery_started = 1;
wil->radio_wdev = wdev;
if (vif->mid == 0)
wil->radio_wdev = wdev;
cfg80211_ready_on_channel(wdev, *cookie, chan, duration,
GFP_KERNEL);
......@@ -189,9 +185,9 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
return rc;
}
u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)
u8 wil_p2p_stop_discovery(struct wil6210_vif *vif)
{
struct wil_p2p_info *p2p = &wil->p2p;
struct wil_p2p_info *p2p = &vif->p2p;
u8 started = p2p->discovery_started;
if (p2p->discovery_started) {
......@@ -200,7 +196,7 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)
p2p->pending_listen_wdev = NULL;
} else {
del_timer_sync(&p2p->discovery_timer);
wmi_stop_discovery(wil);
wmi_stop_discovery(vif);
}
p2p->discovery_started = 0;
}
......@@ -208,9 +204,10 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)
return started;
}
int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie)
int wil_p2p_cancel_listen(struct wil6210_vif *vif, u64 cookie)
{
struct wil_p2p_info *p2p = &wil->p2p;
struct wil6210_priv *wil = vif_to_wil(vif);
struct wil_p2p_info *p2p = &vif->p2p;
u8 started;
mutex_lock(&wil->mutex);
......@@ -222,7 +219,7 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie)
return -ENOENT;
}
started = wil_p2p_stop_discovery(wil);
started = wil_p2p_stop_discovery(vif);
mutex_unlock(&wil->mutex);
......@@ -232,11 +229,12 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie)
}
mutex_lock(&wil->p2p_wdev_mutex);
cfg80211_remain_on_channel_expired(wil->radio_wdev,
cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil, vif),
p2p->cookie,
&p2p->listen_chan,
GFP_KERNEL);
wil->radio_wdev = wil->wdev;
if (vif->mid == 0)
wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
mutex_unlock(&wil->p2p_wdev_mutex);
return 0;
}
......@@ -245,40 +243,43 @@ void wil_p2p_listen_expired(struct work_struct *work)
{
struct wil_p2p_info *p2p = container_of(work,
struct wil_p2p_info, discovery_expired_work);
struct wil6210_priv *wil = container_of(p2p,
struct wil6210_priv, p2p);
struct wil6210_vif *vif = container_of(p2p,
struct wil6210_vif, p2p);
struct wil6210_priv *wil = vif_to_wil(vif);
u8 started;
wil_dbg_misc(wil, "p2p_listen_expired\n");
mutex_lock(&wil->mutex);
started = wil_p2p_stop_discovery(wil);
started = wil_p2p_stop_discovery(vif);
mutex_unlock(&wil->mutex);
if (started) {
mutex_lock(&wil->p2p_wdev_mutex);
cfg80211_remain_on_channel_expired(wil->radio_wdev,
p2p->cookie,
&p2p->listen_chan,
GFP_KERNEL);
wil->radio_wdev = wil->wdev;
mutex_unlock(&wil->p2p_wdev_mutex);
}
if (!started)
return;
mutex_lock(&wil->p2p_wdev_mutex);
cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil, vif),
p2p->cookie,
&p2p->listen_chan,
GFP_KERNEL);
if (vif->mid == 0)
wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
mutex_unlock(&wil->p2p_wdev_mutex);
}
void wil_p2p_search_expired(struct work_struct *work)
{
struct wil_p2p_info *p2p = container_of(work,
struct wil_p2p_info, discovery_expired_work);
struct wil6210_priv *wil = container_of(p2p,
struct wil6210_priv, p2p);
struct wil6210_vif *vif = container_of(p2p,
struct wil6210_vif, p2p);
struct wil6210_priv *wil = vif_to_wil(vif);
u8 started;
wil_dbg_misc(wil, "p2p_search_expired\n");
mutex_lock(&wil->mutex);
started = wil_p2p_stop_discovery(wil);
started = wil_p2p_stop_discovery(vif);
mutex_unlock(&wil->mutex);
if (started) {
......@@ -287,10 +288,12 @@ void wil_p2p_search_expired(struct work_struct *work)
};
mutex_lock(&wil->p2p_wdev_mutex);
if (wil->scan_request) {
cfg80211_scan_done(wil->scan_request, &info);
wil->scan_request = NULL;
wil->radio_wdev = wil->wdev;
if (vif->scan_request) {
cfg80211_scan_done(vif->scan_request, &info);
vif->scan_request = NULL;
if (vif->mid == 0)
wil->radio_wdev =
wil->main_ndev->ieee80211_ptr;
}
mutex_unlock(&wil->p2p_wdev_mutex);
}
......@@ -300,8 +303,9 @@ void wil_p2p_delayed_listen_work(struct work_struct *work)
{
struct wil_p2p_info *p2p = container_of(work,
struct wil_p2p_info, delayed_listen_work);
struct wil6210_priv *wil = container_of(p2p,
struct wil6210_priv, p2p);
struct wil6210_vif *vif = container_of(p2p,
struct wil6210_vif, p2p);
struct wil6210_priv *wil = vif_to_wil(vif);
int rc;
mutex_lock(&wil->mutex);
......@@ -311,14 +315,14 @@ void wil_p2p_delayed_listen_work(struct work_struct *work)
goto out;
mutex_lock(&wil->p2p_wdev_mutex);
if (wil->scan_request) {
if (vif->scan_request) {
/* another scan started, wait again... */
mutex_unlock(&wil->p2p_wdev_mutex);
goto out;
}
mutex_unlock(&wil->p2p_wdev_mutex);
rc = wil_p2p_start_listen(wil);
rc = wil_p2p_start_listen(vif);
mutex_lock(&wil->p2p_wdev_mutex);
if (rc) {
......@@ -326,12 +330,14 @@ void wil_p2p_delayed_listen_work(struct work_struct *work)
p2p->cookie,
&p2p->listen_chan,
GFP_KERNEL);
wil->radio_wdev = wil->wdev;
if (vif->mid == 0)
wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
} else {
cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie,
&p2p->listen_chan,
p2p->listen_duration, GFP_KERNEL);
wil->radio_wdev = p2p->pending_listen_wdev;
if (vif->mid == 0)
wil->radio_wdev = p2p->pending_listen_wdev;
}
p2p->pending_listen_wdev = NULL;
mutex_unlock(&wil->p2p_wdev_mutex);
......@@ -342,7 +348,8 @@ void wil_p2p_delayed_listen_work(struct work_struct *work)
void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
{
struct wil_p2p_info *p2p = &wil->p2p;
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
struct wil_p2p_info *p2p = &vif->p2p;
struct cfg80211_scan_info info = {
.aborted = true,
};
......@@ -355,21 +362,21 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
if (!p2p->discovery_started) {
/* Regular scan on the p2p device */
if (wil->scan_request &&
wil->scan_request->wdev == wil->p2p_wdev)
wil_abort_scan(wil, true);
if (vif->scan_request &&
vif->scan_request->wdev == wil->p2p_wdev)
wil_abort_scan(vif, true);
goto out;
}
/* Search or listen on p2p device */
mutex_unlock(&wil->p2p_wdev_mutex);
wil_p2p_stop_discovery(wil);
wil_p2p_stop_discovery(vif);
mutex_lock(&wil->p2p_wdev_mutex);
if (wil->scan_request) {
if (vif->scan_request) {
/* search */
cfg80211_scan_done(wil->scan_request, &info);
wil->scan_request = NULL;
cfg80211_scan_done(vif->scan_request, &info);
vif->scan_request = NULL;
} else {
/* listen */
cfg80211_remain_on_channel_expired(wil->radio_wdev,
......@@ -379,5 +386,5 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
}
out:
wil->radio_wdev = wil->wdev;
wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
}
......@@ -425,7 +425,7 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
int rc = 0;
struct pci_dev *pdev = to_pci_dev(dev);
struct wil6210_priv *wil = pci_get_drvdata(pdev);
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
bool keep_radio_on = ndev->flags & IFF_UP &&
wil->keep_radio_on_during_sleep;
......@@ -457,7 +457,7 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
int rc = 0;
struct pci_dev *pdev = to_pci_dev(dev);
struct wil6210_priv *wil = pci_get_drvdata(pdev);
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
bool keep_radio_on = ndev->flags & IFF_UP &&
wil->keep_radio_on_during_sleep;
......
/*
* Copyright (c) 2014,2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -23,8 +24,8 @@
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
{
int rc = 0;
struct wireless_dev *wdev = wil->wdev;
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct wireless_dev *wdev = ndev->ieee80211_ptr;
bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY,
wil->fw_capabilities);
......@@ -258,7 +259,7 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
static int wil_suspend_radio_off(struct wil6210_priv *wil)
{
int rc = 0;
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
wil_dbg_pm(wil, "suspend radio off\n");
......@@ -306,7 +307,7 @@ static int wil_suspend_radio_off(struct wil6210_priv *wil)
static int wil_resume_radio_off(struct wil6210_priv *wil)
{
int rc = 0;
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
wil_enable_irq(wil);
......
/*
* Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -53,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
u32 i;
struct pmc_ctx *pmc = &wil->pmc;
struct device *dev = wil_to_dev(wil);
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
struct wmi_pmc_cmd pmc_cmd = {0};
int last_cmd_err = -ENOMEM;
......@@ -186,6 +188,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n");
pmc->last_cmd_status = wmi_send(wil,
WMI_PMC_CMDID,
vif->mid,
&pmc_cmd,
sizeof(pmc_cmd));
if (pmc->last_cmd_status) {
......@@ -236,6 +239,7 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
{
struct pmc_ctx *pmc = &wil->pmc;
struct device *dev = wil_to_dev(wil);
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
struct wmi_pmc_cmd pmc_cmd = {0};
mutex_lock(&pmc->lock);
......@@ -254,8 +258,8 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n");
pmc_cmd.op = WMI_PMC_RELEASE;
pmc->last_cmd_status =
wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd,
sizeof(pmc_cmd));
wmi_send(wil, WMI_PMC_CMDID, vif->mid,
&pmc_cmd, sizeof(pmc_cmd));
if (pmc->last_cmd_status) {
wil_err(wil,
"WMI_PMC_CMD with RELEASE op failed, status %d",
......
/*
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -44,7 +45,7 @@ static void wil_release_reorder_frame(struct wil6210_priv *wil,
struct wil_tid_ampdu_rx *r,
int index)
{
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct sk_buff *skb = r->reorder_buf[index];
if (!skb)
......@@ -93,7 +94,7 @@ static void wil_reorder_release(struct wil6210_priv *wil,
void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
int tid = wil_rxdesc_tid(d);
int cid = wil_rxdesc_cid(d);
......@@ -292,8 +293,8 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize)
}
/* Block Ack - Rx side (recipient) */
int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
u8 dialog_token, __le16 ba_param_set,
int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
__le16 ba_timeout, __le16 ba_seq_ctrl)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
......@@ -354,7 +355,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
}
}
rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status,
rc = wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token, status,
agg_amsdu, agg_wsize, agg_timeout);
if (rc || (status != WLAN_STATUS_SUCCESS)) {
wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc,
......@@ -393,7 +394,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
goto out;
}
txdata->addba_in_progress = true;
rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout);
rc = wmi_addba(wil, txdata->mid, ringid, agg_wsize, agg_timeout);
if (rc) {
wil_err(wil, "wmi_addba failed, rc (%d)", rc);
txdata->addba_in_progress = false;
......
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -474,7 +475,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
struct vring *vring)
{
struct device *dev = wil_to_dev(wil);
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
volatile struct vring_rx_desc *_d;
struct vring_rx_desc *d;
struct sk_buff *skb;
......@@ -624,7 +625,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
*/
static int wil_rx_refill(struct wil6210_priv *wil, int count)
{
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct vring *v = &wil->vring_rx;
u32 next_tail;
int rc = 0;
......@@ -713,8 +714,9 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
{
gro_result_t rc = GRO_NORMAL;
struct wil6210_vif *vif = ndev_to_vif(ndev);
struct wil6210_priv *wil = ndev_to_wil(ndev);
struct wireless_dev *wdev = wil_to_wdev(wil);
struct wireless_dev *wdev = vif_to_wdev(vif);
unsigned int len = skb->len;
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */
......@@ -751,14 +753,15 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
goto stats;
}
if (wdev->iftype == NL80211_IFTYPE_AP && !wil->ap_isolate) {
if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) {
if (mcast) {
/* send multicast frames both to higher layers in
* local net stack and back to the wireless medium
*/
xmit_skb = skb_copy(skb, GFP_ATOMIC);
} else {
int xmit_cid = wil_find_cid(wil, eth->h_dest);
int xmit_cid = wil_find_cid(wil, vif->mid,
eth->h_dest);
if (xmit_cid >= 0) {
/* The destination station is associated to
......@@ -815,7 +818,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
*/
void wil_rx_handle(struct wil6210_priv *wil, int *quota)
{
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct wireless_dev *wdev = ndev->ieee80211_ptr;
struct vring *v = &wil->vring_rx;
struct sk_buff *skb;
......@@ -827,7 +831,8 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota)
while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) {
(*quota)--;
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
/* monitor is currently supported on main interface only */
if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
skb->dev = ndev;
skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
......@@ -911,12 +916,14 @@ static inline void wil_tx_data_init(struct vring_tx_data *txdata)
txdata->agg_timeout = 0;
txdata->agg_amsdu = 0;
txdata->addba_in_progress = false;
txdata->mid = U8_MAX;
spin_unlock_bh(&txdata->lock);
}
int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
int cid, int tid)
{
struct wil6210_priv *wil = vif_to_wil(vif);
int rc;
struct wmi_vring_cfg_cmd cmd = {
.action = cpu_to_le32(WMI_VRING_CMD_ADD),
......@@ -966,9 +973,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
if (!wil->privacy)
if (!vif->privacy)
txdata->dot1x_open = true;
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
if (rc)
goto out_free;
......@@ -982,6 +989,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
spin_lock_bh(&txdata->lock);
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
txdata->mid = vif->mid;
txdata->enabled = 1;
spin_unlock_bh(&txdata->lock);
......@@ -1003,8 +1011,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
return rc;
}
int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size)
{
struct wil6210_priv *wil = vif_to_wil(vif);
int rc;
struct wmi_bcast_vring_cfg_cmd cmd = {
.action = cpu_to_le32(WMI_VRING_CMD_ADD),
......@@ -1046,9 +1055,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
if (!wil->privacy)
if (!vif->privacy)
txdata->dot1x_open = true;
rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, &cmd, sizeof(cmd),
rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, vif->mid,
&cmd, sizeof(cmd),
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
if (rc)
goto out_free;
......@@ -1062,6 +1072,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
spin_lock_bh(&txdata->lock);
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
txdata->mid = vif->mid;
txdata->enabled = 1;
spin_unlock_bh(&txdata->lock);
......@@ -1091,6 +1102,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
spin_lock_bh(&txdata->lock);
txdata->dot1x_open = false;
txdata->mid = U8_MAX;
txdata->enabled = 0; /* no Tx can be in progress or start anew */
spin_unlock_bh(&txdata->lock);
/* napi_synchronize waits for completion of the current NAPI but will
......@@ -1108,11 +1120,12 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
}
static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
struct wil6210_vif *vif,
struct sk_buff *skb)
{
int i;
struct ethhdr *eth = (void *)skb->data;
int cid = wil_find_cid(wil, eth->h_dest);
int cid = wil_find_cid(wil, vif->mid, eth->h_dest);
if (cid < 0)
return NULL;
......@@ -1142,10 +1155,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
return NULL;
}
static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
struct sk_buff *skb);
static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif,
struct vring *vring, struct sk_buff *skb);
static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
struct wil6210_vif *vif,
struct sk_buff *skb)
{
struct vring *v;
......@@ -1160,7 +1174,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
v = &wil->vring_tx[i];
txdata = &wil->vring_tx_data[i];
if (!v->va || !txdata->enabled)
if (!v->va || !txdata->enabled || txdata->mid != vif->mid)
continue;
cid = wil->vring2cid_tid[i][0];
......@@ -1193,11 +1207,12 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
* - for PBSS
*/
static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
struct wil6210_vif *vif,
struct sk_buff *skb)
{
struct vring *v;
struct vring_tx_data *txdata;
int i = wil->bcast_vring;
int i = vif->bcast_vring;
if (i < 0)
return NULL;
......@@ -1222,6 +1237,7 @@ static void wil_set_da_for_vring(struct wil6210_priv *wil,
}
static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
struct wil6210_vif *vif,
struct sk_buff *skb)
{
struct vring *v, *v2;
......@@ -1230,13 +1246,13 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
u8 cid;
struct ethhdr *eth = (void *)skb->data;
char *src = eth->h_source;
struct vring_tx_data *txdata;
struct vring_tx_data *txdata, *txdata2;
/* find 1-st vring eligible for data */
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
v = &wil->vring_tx[i];
txdata = &wil->vring_tx_data[i];
if (!v->va || !txdata->enabled)
if (!v->va || !txdata->enabled || txdata->mid != vif->mid)
continue;
cid = wil->vring2cid_tid[i][0];
......@@ -1264,7 +1280,8 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
/* find other active vrings and duplicate skb for each */
for (i++; i < WIL6210_MAX_TX_RINGS; i++) {
v2 = &wil->vring_tx[i];
if (!v2->va)
txdata2 = &wil->vring_tx_data[i];
if (!v2->va || txdata2->mid != vif->mid)
continue;
cid = wil->vring2cid_tid[i][0];
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
......@@ -1280,7 +1297,7 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
if (skb2) {
wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i);
wil_set_da_for_vring(wil, skb2, i);
wil_tx_vring(wil, v2, skb2);
wil_tx_vring(wil, vif, v2, skb2);
} else {
wil_err(wil, "skb_copy failed\n");
}
......@@ -1417,8 +1434,8 @@ static inline void wil_set_tx_desc_last_tso(volatile struct vring_tx_desc *d)
DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS;
}
static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
struct sk_buff *skb)
static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif,
struct vring *vring, struct sk_buff *skb)
{
struct device *dev = wil_to_dev(wil);
......@@ -1710,8 +1727,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
return rc;
}
static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
struct sk_buff *skb)
static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif,
struct vring *vring, struct sk_buff *skb)
{
struct device *dev = wil_to_dev(wil);
struct vring_tx_desc dd, *d = &dd;
......@@ -1725,7 +1742,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
uint i = swhead;
dma_addr_t pa;
int used;
bool mcast = (vring_index == wil->bcast_vring);
bool mcast = (vring_index == vif->bcast_vring);
uint len = skb_headlen(skb);
wil_dbg_txrx(wil, "tx_vring: %d bytes to vring %d\n", skb->len,
......@@ -1860,8 +1877,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
return -EINVAL;
}
static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
struct sk_buff *skb)
static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif,
struct vring *vring, struct sk_buff *skb)
{
int vring_index = vring - wil->vring_tx;
struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
......@@ -1879,7 +1896,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
}
rc = (skb_is_gso(skb) ? __wil_tx_vring_tso : __wil_tx_vring)
(wil, vring, skb);
(wil, vif, vring, skb);
spin_unlock(&txdata->lock);
......@@ -1923,7 +1940,7 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil,
if (check_stop) {
if (!vring || unlikely(wil_vring_avail_low(vring))) {
/* not enough room in the vring */
netif_tx_stop_all_queues(wil_to_ndev(wil));
netif_tx_stop_all_queues(wil->main_ndev);
wil->net_queue_stopped = true;
wil_dbg_txrx(wil, "netif_tx_stop called\n");
}
......@@ -1953,7 +1970,7 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil,
if (!vring || wil_vring_avail_high(vring)) {
/* enough room in the vring */
wil_dbg_txrx(wil, "calling netif_tx_wake\n");
netif_tx_wake_all_queues(wil_to_ndev(wil));
netif_tx_wake_all_queues(wil->main_ndev);
wil->net_queue_stopped = false;
}
}
......@@ -1976,7 +1993,8 @@ void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring,
netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
struct wil6210_vif *vif = ndev_to_vif(ndev);
struct wil6210_priv *wil = vif_to_wil(vif);
struct ethhdr *eth = (void *)skb->data;
bool bcast = is_multicast_ether_addr(eth->h_dest);
struct vring *vring;
......@@ -1995,40 +2013,40 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
wil_dbg_ratelimited(wil, "FW not connected, packet dropped\n");
goto drop;
}
if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) {
if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_MONITOR)) {
wil_err(wil, "Xmit in monitor mode not supported\n");
goto drop;
}
pr_once_fw = false;
/* find vring */
if (wil->wdev->iftype == NL80211_IFTYPE_STATION && !wil->pbss) {
if (vif->wdev.iftype == NL80211_IFTYPE_STATION && !vif->pbss) {
/* in STA mode (ESS), all to same VRING (to AP) */
vring = wil_find_tx_vring_sta(wil, skb);
vring = wil_find_tx_vring_sta(wil, vif, skb);
} else if (bcast) {
if (wil->pbss)
if (vif->pbss)
/* in pbss, no bcast VRING - duplicate skb in
* all stations VRINGs
*/
vring = wil_find_tx_bcast_2(wil, skb);
else if (wil->wdev->iftype == NL80211_IFTYPE_AP)
vring = wil_find_tx_bcast_2(wil, vif, skb);
else if (vif->wdev.iftype == NL80211_IFTYPE_AP)
/* AP has a dedicated bcast VRING */
vring = wil_find_tx_bcast_1(wil, skb);
vring = wil_find_tx_bcast_1(wil, vif, skb);
else
/* unexpected combination, fallback to duplicating
* the skb in all stations VRINGs
*/
vring = wil_find_tx_bcast_2(wil, skb);
vring = wil_find_tx_bcast_2(wil, vif, skb);
} else {
/* unicast, find specific VRING by dest. address */
vring = wil_find_tx_ucast(wil, skb);
vring = wil_find_tx_ucast(wil, vif, skb);
}
if (unlikely(!vring)) {
wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest);
goto drop;
}
/* set up vring entry */
rc = wil_tx_vring(wil, vring, skb);
rc = wil_tx_vring(wil, vif, vring, skb);
switch (rc) {
case 0:
......@@ -2074,7 +2092,7 @@ static inline void wil_consume_skb(struct sk_buff *skb, bool acked)
*/
int wil_tx_complete(struct wil6210_priv *wil, int ringid)
{
struct net_device *ndev = wil_to_ndev(wil);
struct net_device *ndev = wil->main_ndev;
struct device *dev = wil_to_dev(wil);
struct vring *vring = &wil->vring_tx[ringid];
struct vring_tx_data *txdata = &wil->vring_tx_data[ringid];
......
......@@ -464,6 +464,7 @@ struct vring_tx_data {
u16 agg_timeout;
u8 agg_amsdu;
bool addba_in_progress; /* if set, agg_xxx is for request in progress */
u8 mid;
spinlock_t lock;
};
......@@ -542,7 +543,6 @@ struct wil_tid_crypto_rx {
struct wil_p2p_info {
struct ieee80211_channel listen_chan;
u8 discovery_started;
u8 p2p_dev_started;
u64 cookie;
struct wireless_dev *pending_listen_wdev;
unsigned int listen_duration;
......@@ -585,6 +585,7 @@ struct wil_net_stats {
*/
struct wil_sta_info {
u8 addr[ETH_ALEN];
u8 mid;
enum wil_sta_status status;
struct wil_net_stats stats;
/* Rx BACK */
......@@ -672,16 +673,34 @@ extern u8 led_polarity;
struct wil6210_vif {
struct wireless_dev wdev;
struct net_device *ndev;
struct wil6210_priv *wil;
u8 mid;
u32 privacy; /* secure connection? */
u16 channel; /* relevant in AP mode */
u8 hidden_ssid; /* relevant in AP mode */
u32 ap_isolate; /* no intra-BSS communication */
bool pbss;
int bcast_vring;
struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */
int locally_generated_disc; /* relevant in STA mode */
struct timer_list connect_timer;
struct work_struct disconnect_worker;
/* scan */
struct cfg80211_scan_request *scan_request;
struct timer_list scan_timer; /* detect scan timeout */
struct wil_p2p_info p2p;
/* keep alive */
struct list_head probe_client_pending;
struct mutex probe_client_mutex; /* protect @probe_client_pending */
struct work_struct probe_client_worker;
};
struct wil6210_priv {
struct pci_dev *pdev;
u32 bar_size;
struct wiphy *wiphy;
struct wireless_dev *wdev;
struct net_device *ndev;
struct net_device *main_ndev;
void __iomem *csr;
DECLARE_BITMAP(status, wil_status_last);
u8 fw_version[ETHTOOL_FWVERS_LEN];
......@@ -703,13 +722,7 @@ struct wil6210_priv {
/* profile */
struct cfg80211_chan_def monitor_chandef;
u32 monitor_flags;
u32 privacy; /* secure connection? */
u8 hidden_ssid; /* relevant in AP mode */
u16 channel; /* relevant in AP mode */
int sinfo_gen;
u32 ap_isolate; /* no intra-BSS communication */
struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */
int locally_generated_disc; /* relevant in STA mode */
/* interrupt moderation */
u32 tx_max_burst_duration;
u32 tx_interframe_timeout;
......@@ -724,15 +737,13 @@ struct wil6210_priv {
struct completion wmi_call;
u16 wmi_seq;
u16 reply_id; /**< wait for this WMI event */
u8 reply_mid;
void *reply_buf;
u16 reply_size;
struct workqueue_struct *wmi_wq; /* for deferred calls */
struct work_struct wmi_event_worker;
struct workqueue_struct *wq_service;
struct work_struct disconnect_worker;
struct work_struct fw_error_worker; /* for FW error recovery */
struct timer_list connect_timer;
struct timer_list scan_timer; /* detect scan timeout */
struct list_head pending_wmi_ev;
/*
* protect pending_wmi_ev
......@@ -744,10 +755,6 @@ struct wil6210_priv {
int net_queue_stopped; /* netif_tx_stop_all_queues invoked */
struct napi_struct napi_rx;
struct napi_struct napi_tx;
/* keep alive */
struct list_head probe_client_pending;
struct mutex probe_client_mutex; /* protect @probe_client_pending */
struct work_struct probe_client_worker;
/* DMA related */
struct vring vring_rx;
unsigned int rx_buf_len;
......@@ -755,11 +762,8 @@ struct wil6210_priv {
struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS];
u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
struct wil_sta_info sta[WIL6210_MAX_CID];
int bcast_vring;
u32 vring_idle_trsh; /* HW fetches up to 16 descriptors at once */
u32 dma_addr_size; /* indicates dma addr size */
/* scan */
struct cfg80211_scan_request *scan_request;
struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */
/* statistics */
......@@ -779,9 +783,7 @@ struct wil6210_priv {
struct pmc_ctx pmc;
bool pbss;
struct wil_p2p_info p2p;
u8 p2p_dev_started;
/* P2P_DEVICE vif */
struct wireless_dev *p2p_wdev;
......@@ -810,12 +812,32 @@ struct wil6210_priv {
#define wil_to_wiphy(i) (i->wiphy)
#define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i)))
#define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w))
#define wil_to_wdev(i) (i->wdev)
#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w))
#define wil_to_ndev(i) (i->ndev)
#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
#define ndev_to_vif(n) (struct wil6210_vif *)(netdev_priv(n))
#define wdev_to_vif(w) (container_of(w, struct wil6210_vif, wdev))
#define vif_to_wil(v) (v->wil)
#define vif_to_ndev(v) (v->ndev)
#define vif_to_wdev(v) (&v->wdev)
static inline struct wil6210_vif *wdev_to_vif(struct wil6210_priv *wil,
struct wireless_dev *wdev)
{
/* main interface is shared with P2P device */
if (wdev == wil->p2p_wdev)
return ndev_to_vif(wil->main_ndev);
else
return container_of(wdev, struct wil6210_vif, wdev);
}
static inline struct wireless_dev *
vif_to_radio_wdev(struct wil6210_priv *wil, struct wil6210_vif *vif)
{
/* main interface is shared with P2P device */
if (vif->mid)
return vif_to_wdev(vif);
else
return wil->radio_wdev;
}
__printf(2, 3)
void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
......@@ -828,7 +850,7 @@ void __wil_info(struct wil6210_priv *wil, const char *fmt, ...);
__printf(2, 3)
void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...);
#define wil_dbg(wil, fmt, arg...) do { \
netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \
netdev_dbg(wil->main_ndev, fmt, ##arg); \
wil_dbg_trace(wil, fmt, ##arg); \
} while (0)
......@@ -933,7 +955,7 @@ int wil_down(struct wil6210_priv *wil);
int __wil_down(struct wil6210_priv *wil);
void wil_refresh_fw_capabilities(struct wil6210_priv *wil);
void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r);
int wil_find_cid(struct wil6210_priv *wil, const u8 *mac);
int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac);
void wil_set_ethtoolops(struct net_device *ndev);
struct fw_map *wil_find_fw_mapping(const char *section);
......@@ -942,40 +964,42 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr);
void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr);
int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
struct wil6210_mbox_hdr *hdr);
int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len);
int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len);
void wmi_recv_cmd(struct wil6210_priv *wil);
int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
u16 reply_id, void *reply, u8 reply_size, int to_msec);
void wmi_event_worker(struct work_struct *work);
void wmi_event_flush(struct wil6210_priv *wil);
int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid);
int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid);
int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid);
int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid);
int wmi_set_channel(struct wil6210_priv *wil, int channel);
int wmi_get_channel(struct wil6210_priv *wil, int *channel);
int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index,
const void *mac_addr, int key_usage);
int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index,
const void *mac_addr, int key_len, const void *key,
int key_usage);
int wmi_echo(struct wil6210_priv *wil);
int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie);
int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
int wmi_rxon(struct wil6210_priv *wil, bool on);
int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r);
int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac,
u16 reason, bool full_disconnect, bool del_sta);
int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout);
int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason);
int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason);
int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
int wmi_addba(struct wil6210_priv *wil, u8 mid,
u8 ringid, u8 size, u16 timeout);
int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason);
int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason);
int wmi_addba_rx_resp(struct wil6210_priv *wil,
u8 mid, u8 cid, u8 tid, u8 token,
u16 status, bool amsdu, u16 agg_wsize, u16 timeout);
int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
enum wmi_ps_profile_type ps_profile);
int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short);
int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short);
int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid);
int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
u8 dialog_token, __le16 ba_param_set,
int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid);
int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
__le16 ba_timeout, __le16 ba_seq_ctrl);
int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
......@@ -991,24 +1015,23 @@ void wil6210_mask_halp(struct wil6210_priv *wil);
/* P2P */
bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request);
void wil_p2p_discovery_timer_fn(struct timer_list *t);
int wil_p2p_search(struct wil6210_priv *wil,
int wil_p2p_search(struct wil6210_vif *vif,
struct cfg80211_scan_request *request);
int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
unsigned int duration, struct ieee80211_channel *chan,
u64 *cookie);
u8 wil_p2p_stop_discovery(struct wil6210_priv *wil);
int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie);
u8 wil_p2p_stop_discovery(struct wil6210_vif *vif);
int wil_p2p_cancel_listen(struct wil6210_vif *vif, u64 cookie);
void wil_p2p_listen_expired(struct work_struct *work);
void wil_p2p_search_expired(struct work_struct *work);
void wil_p2p_stop_radio_operations(struct wil6210_priv *wil);
void wil_p2p_delayed_listen_work(struct work_struct *work);
/* WMI for P2P */
int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi);
int wmi_start_listen(struct wil6210_priv *wil);
int wmi_start_search(struct wil6210_priv *wil);
int wmi_stop_discovery(struct wil6210_priv *wil);
int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi);
int wmi_start_listen(struct wil6210_vif *vif);
int wmi_start_search(struct wil6210_vif *vif);
int wmi_stop_discovery(struct wil6210_vif *vif);
int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params,
......@@ -1025,7 +1048,7 @@ static inline int wil6210_debugfs_init(struct wil6210_priv *wil) { return 0; }
static inline void wil6210_debugfs_remove(struct wil6210_priv *wil) {}
#endif
int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
struct station_info *sinfo);
struct wil6210_priv *wil_cfg80211_init(struct device *dev);
......@@ -1033,29 +1056,30 @@ void wil_cfg80211_deinit(struct wil6210_priv *wil);
void wil_p2p_wdev_free(struct wil6210_priv *wil);
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
u8 chan, u8 hidden_ssid, u8 is_go);
int wmi_pcp_stop(struct wil6210_priv *wil);
int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype, u8 chan,
u8 hidden_ssid, u8 is_go);
int wmi_pcp_stop(struct wil6210_vif *vif);
int wmi_led_cfg(struct wil6210_priv *wil, bool enable);
int wmi_abort_scan(struct wil6210_priv *wil);
void wil_abort_scan(struct wil6210_priv *wil, bool sync);
int wmi_abort_scan(struct wil6210_vif *vif);
void wil_abort_scan(struct wil6210_vif *vif, bool sync);
void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps);
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
u16 reason_code, bool from_event);
void wil_probe_client_flush(struct wil6210_priv *wil);
void wil_probe_client_flush(struct wil6210_vif *vif);
void wil_probe_client_worker(struct work_struct *work);
void wil_disconnect_worker(struct work_struct *work);
int wil_rx_init(struct wil6210_priv *wil, u16 size);
void wil_rx_fini(struct wil6210_priv *wil);
/* TX API */
int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
int cid, int tid);
void wil_vring_fini_tx(struct wil6210_priv *wil, int id);
int wil_tx_init(struct wil6210_priv *wil, int cid);
int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size);
int wil_bcast_init(struct wil6210_priv *wil);
void wil_bcast_fini(struct wil6210_priv *wil);
int wil_tx_init(struct wil6210_vif *vif, int cid);
int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size);
int wil_bcast_init(struct wil6210_vif *vif);
void wil_bcast_fini(struct wil6210_vif *vif);
void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring,
bool should_stop);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册