diff options
author | Lior David <liord@codeaurora.org> | 2018-02-26 19:12:17 +0100 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-02-27 17:50:47 +0100 |
commit | 5bd6098252104f1007882805e9d7c36924ff6a81 (patch) | |
tree | e6f10f5974e65f600faba84b9e3d2540f5aa0ce4 /drivers/net/wireless/ath/wil6210/main.c | |
parent | wil6210: rename p2p_wdev_mutex to vif_mutex (diff) | |
download | linux-5bd6098252104f1007882805e9d7c36924ff6a81.tar.xz linux-5bd6098252104f1007882805e9d7c36924ff6a81.zip |
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/main.c')
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 78 |
1 files changed, 55 insertions, 23 deletions
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 9a2a8663b66a..a4b413e8d55a 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -175,6 +175,15 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) cid, sta->mid, sta->status); /* inform upper/lower layers */ if (sta->status != wil_sta_unused) { + if (vif->mid != sta->mid) { + wil_err(wil, "STA MID mismatch with VIF MID(%d)\n", + vif->mid); + /* let FW override sta->mid but be more strict with + * user space requests + */ + if (!from_event) + return; + } if (!from_event) { bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? disable_ap_sme : false; @@ -277,32 +286,35 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: wil_bcast_fini(vif); - wil_update_net_queues_bh(wil, NULL, true); + wil_update_net_queues_bh(wil, vif, NULL, true); netif_carrier_off(ndev); - wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); + if (!wil_has_other_active_ifaces(wil, ndev, false, true)) + wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); - if (test_bit(wil_status_fwconnected, wil->status)) { - clear_bit(wil_status_fwconnected, wil->status); + if (test_and_clear_bit(wil_vif_fwconnected, vif->status)) { + atomic_dec(&wil->connected_vifs); cfg80211_disconnected(ndev, reason_code, NULL, 0, vif->locally_generated_disc, GFP_KERNEL); vif->locally_generated_disc = false; - } else if (test_bit(wil_status_fwconnecting, wil->status)) { + } else if (test_bit(wil_vif_fwconnecting, vif->status)) { cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); vif->bss = NULL; } - clear_bit(wil_status_fwconnecting, wil->status); + clear_bit(wil_vif_fwconnecting, vif->status); break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: if (!wil_vif_is_connected(wil, vif->mid)) { - wil_update_net_queues_bh(wil, NULL, true); - clear_bit(wil_status_fwconnected, wil->status); + wil_update_net_queues_bh(wil, vif, NULL, true); + if (test_and_clear_bit(wil_vif_fwconnected, + vif->status)) + atomic_dec(&wil->connected_vifs); } else { - wil_update_net_queues_bh(wil, NULL, false); + wil_update_net_queues_bh(wil, vif, NULL, false); } break; default: @@ -322,11 +334,11 @@ void wil_disconnect_worker(struct work_struct *work) struct wmi_disconnect_event evt; } __packed reply; - if (test_bit(wil_status_fwconnected, wil->status)) + if (test_bit(wil_vif_fwconnected, vif->status)) /* connect succeeded after all */ return; - if (!test_bit(wil_status_fwconnecting, wil->status)) + if (!test_bit(wil_vif_fwconnecting, vif->status)) /* already disconnected */ return; @@ -338,11 +350,11 @@ void wil_disconnect_worker(struct work_struct *work) return; } - wil_update_net_queues_bh(wil, NULL, true); + wil_update_net_queues_bh(wil, vif, NULL, true); netif_carrier_off(ndev); cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); - clear_bit(wil_status_fwconnecting, wil->status); + clear_bit(wil_vif_fwconnecting, vif->status); } static int wil_wait_for_recovery(struct wil6210_priv *wil) @@ -1087,6 +1099,20 @@ void wil_abort_scan(struct wil6210_vif *vif, bool sync) } } +void wil_abort_scan_all_vifs(struct wil6210_priv *wil, bool sync) +{ + int i; + + lockdep_assert_held(&wil->vif_mutex); + + for (i = 0; i < wil->max_vifs; i++) { + struct wil6210_vif *vif = wil->vifs[i]; + + if (vif) + wil_abort_scan(vif, sync); + } +} + int wil_ps_update(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile) { int rc; @@ -1139,6 +1165,7 @@ static int wil_restore_vifs(struct wil6210_priv *wil) vif = wil->vifs[i]; if (!vif) continue; + vif->ap_isolate = 0; if (vif->mid) { ndev = vif_to_ndev(vif); wdev = vif_to_wdev(vif); @@ -1162,10 +1189,10 @@ static int wil_restore_vifs(struct wil6210_priv *wil) */ int wil_reset(struct wil6210_priv *wil, bool load_fw) { - int rc; + int rc, i; unsigned long status_flags = BIT(wil_status_resetting); int no_flash; - struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); + struct wil6210_vif *vif; wil_dbg_misc(wil, "reset\n"); @@ -1214,17 +1241,23 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) goto out; } - cancel_work_sync(&vif->disconnect_worker); - wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); + mutex_lock(&wil->vif_mutex); + wil_abort_scan_all_vifs(wil, false); + mutex_unlock(&wil->vif_mutex); + + for (i = 0; i < wil->max_vifs; i++) { + vif = wil->vifs[i]; + if (vif) { + cancel_work_sync(&vif->disconnect_worker); + wil6210_disconnect(vif, NULL, + WLAN_REASON_DEAUTH_LEAVING, false); + } + } wil_bcast_fini_all(wil); /* Disable device led before reset*/ wmi_led_cfg(wil, false); - mutex_lock(&wil->vif_mutex); - wil_abort_scan(vif, false); - mutex_unlock(&wil->vif_mutex); - /* prevent NAPI from being scheduled and prevent wmi commands */ mutex_lock(&wil->wmi_mutex); if (test_bit(wil_status_suspending, wil->status)) @@ -1294,7 +1327,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) } /* init after reset */ - vif->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); reinit_completion(&wil->halp.comp); @@ -1446,7 +1478,7 @@ int __wil_down(struct wil6210_priv *wil) mutex_lock(&wil->vif_mutex); wil_p2p_stop_radio_operations(wil); - wil_abort_scan(ndev_to_vif(wil->main_ndev), false); + wil_abort_scan_all_vifs(wil, false); mutex_unlock(&wil->vif_mutex); return wil_reset(wil, false); |