summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/wil6210/netdev.c
diff options
context:
space:
mode:
authorLior David <liord@codeaurora.org>2018-02-26 21:12:17 +0300
committerKalle Valo <kvalo@codeaurora.org>2018-02-27 19:50:47 +0300
commit5bd6098252104f1007882805e9d7c36924ff6a81 (patch)
treee6f10f5974e65f600faba84b9e3d2540f5aa0ce4 /drivers/net/wireless/ath/wil6210/netdev.c
parent404bbb3cca3c269ef392017053a8d4cb83e0cc77 (diff)
downloadlinux-5bd6098252104f1007882805e9d7c36924ff6a81.tar.xz
wil6210: multiple VIFs support for connections and data path
Track the connection status per-VIF. The data path code is also updated to support multiple VIFs. This includes RX and TX VRING management, NAPI poll loops, RX reordering and related code. Power management code used to check if the main interface is up or based on connection state of the main interface, adapt this code to take all VIFs into account. Signed-off-by: Lior David <liord@codeaurora.org> Signed-off-by: Maya Erez <merez@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/netdev.c')
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 87956c0f7c79..05e9408e7ea3 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -43,6 +43,7 @@ bool wil_has_other_active_ifaces(struct wil6210_priv *wil,
bool wil_has_active_ifaces(struct wil6210_priv *wil, bool up, bool ok)
{
+ /* use NULL ndev argument to check all interfaces */
return wil_has_other_active_ifaces(wil, NULL, up, ok);
}
@@ -130,11 +131,19 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
struct vring *vring = &wil->vring_tx[i];
struct vring_tx_data *txdata = &wil->vring_tx_data[i];
+ struct wil6210_vif *vif;
- if (!vring->va || !txdata->enabled)
+ if (!vring->va || !txdata->enabled ||
+ txdata->mid >= wil->max_vifs)
continue;
- tx_done += wil_tx_complete(wil, i);
+ vif = wil->vifs[txdata->mid];
+ if (unlikely(!vif)) {
+ wil_dbg_txrx(wil, "Invalid MID %d\n", txdata->mid);
+ continue;
+ }
+
+ tx_done += wil_tx_complete(vif, i);
}
if (tx_done < budget) {
@@ -232,6 +241,8 @@ static void wil_vif_init(struct wil6210_vif *vif)
INIT_WORK(&vif->p2p.delayed_listen_work, wil_p2p_delayed_listen_work);
INIT_LIST_HEAD(&vif->probe_client_pending);
+
+ vif->net_queue_stopped = 1;
}
static u8 wil_vif_find_free_mid(struct wil6210_priv *wil)
@@ -406,12 +417,14 @@ int wil_if_add(struct wil6210_priv *wil)
return rc;
}
- netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
+ init_dummy_netdev(&wil->napi_ndev);
+ netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
WIL6210_NAPI_BUDGET);
- netif_tx_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx,
+ netif_tx_napi_add(&wil->napi_ndev,
+ &wil->napi_tx, wil6210_netdev_poll_tx,
WIL6210_NAPI_BUDGET);
- wil_update_net_queues_bh(wil, NULL, true);
+ wil_update_net_queues_bh(wil, vif, NULL, true);
rtnl_lock();
rc = wil_vif_add(wil, vif);
@@ -450,10 +463,29 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid)
*/
unregister_netdevice(ndev);
+ mutex_lock(&wil->mutex);
+ wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
+ mutex_unlock(&wil->mutex);
+
if (any_active && vif->mid != 0)
wmi_port_delete(wil, vif->mid);
+ /* make sure no one is accessing the VIF before removing */
+ mutex_lock(&wil->vif_mutex);
wil->vifs[mid] = NULL;
+ /* ensure NAPI code will see the NULL VIF */
+ wmb();
+ if (test_bit(wil_status_napi_en, wil->status)) {
+ napi_synchronize(&wil->napi_rx);
+ napi_synchronize(&wil->napi_tx);
+ }
+ mutex_unlock(&wil->vif_mutex);
+
+ flush_work(&wil->wmi_event_worker);
+ del_timer_sync(&vif->connect_timer);
+ cancel_work_sync(&vif->disconnect_worker);
+ wil_probe_client_flush(vif);
+ cancel_work_sync(&vif->probe_client_worker);
/* for VIFs, ndev will be freed by destructor after RTNL is unlocked.
* the main interface will be freed in wil_if_free, we need to keep it
* a bit longer so logging macros will work.
@@ -470,5 +502,9 @@ void wil_if_remove(struct wil6210_priv *wil)
rtnl_lock();
wil_vif_remove(wil, 0);
rtnl_unlock();
+
+ netif_napi_del(&wil->napi_tx);
+ netif_napi_del(&wil->napi_rx);
+
wiphy_unregister(wdev->wiphy);
}