summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/wil6210/cfg80211.c
diff options
context:
space:
mode:
authorLior David <liord@codeaurora.org>2018-02-26 20:12:15 +0200
committerKalle Valo <kvalo@codeaurora.org>2018-02-27 18:50:33 +0200
commit3ada9314b4ea06e656ebb8f5806ff97596a3d548 (patch)
treece6e920ec37e7be83246f59114cf8a1924cf9918 /drivers/net/wireless/ath/wil6210/cfg80211.c
parent4aebd3bdbd8a26ebcd2398289e2379472d17825f (diff)
wil6210: multiple VIFs support for start/stop AP
Add support for multiple VIFs in the cfg80211 operations start_ap, stop_ap and change_beacon. This change allows starting multiple APs using virtual interfaces. The data path and most other operations are still working only on the main interface. 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/cfg80211.c')
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index ce20ee47a258..a3ad3f42c693 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -544,8 +544,9 @@ out:
return ERR_PTR(rc);
}
-int wil_vif_prepare_stop(struct wil6210_priv *wil, struct wil6210_vif *vif)
+int wil_vif_prepare_stop(struct wil6210_vif *vif)
{
+ struct wil6210_priv *wil = vif_to_wil(vif);
struct wireless_dev *wdev = vif_to_wdev(vif);
struct net_device *ndev;
int rc;
@@ -561,6 +562,7 @@ int wil_vif_prepare_stop(struct wil6210_priv *wil, struct wil6210_vif *vif)
rc);
/* continue */
}
+ wil_bcast_fini(vif);
netif_carrier_off(ndev);
}
@@ -593,7 +595,7 @@ static int wil_cfg80211_del_iface(struct wiphy *wiphy,
return -EINVAL;
}
- rc = wil_vif_prepare_stop(wil, vif);
+ rc = wil_vif_prepare_stop(vif);
if (rc)
goto out;
@@ -614,6 +616,7 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy,
struct wil6210_vif *vif = ndev_to_vif(ndev);
struct wireless_dev *wdev = vif_to_wdev(vif);
int rc;
+ bool fw_reset = false;
wil_dbg_misc(wil, "change_iface: type=%d\n", type);
@@ -628,7 +631,7 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy,
/* do not reset FW when there are active VIFs,
* because it can cause significant disruption
*/
- if (!wil_has_other_up_ifaces(wil, ndev) &&
+ if (!wil_has_other_active_ifaces(wil, ndev, true, false) &&
netif_running(ndev) && !wil_is_recovery_blocked(wil)) {
wil_dbg_misc(wil, "interface is up. resetting...\n");
mutex_lock(&wil->mutex);
@@ -638,6 +641,7 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy,
if (rc)
return rc;
+ fw_reset = true;
}
switch (type) {
@@ -654,8 +658,9 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy,
return -EOPNOTSUPP;
}
- if (vif->mid != 0 && wil_has_up_ifaces(wil)) {
- wil_vif_prepare_stop(wil, vif);
+ if (vif->mid != 0 && wil_has_active_ifaces(wil, true, false)) {
+ if (!fw_reset)
+ wil_vif_prepare_stop(vif);
rc = wmi_port_delete(wil, vif->mid);
if (rc)
return rc;
@@ -1530,10 +1535,12 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
mutex_lock(&wil->mutex);
- __wil_down(wil);
- rc = __wil_up(wil);
- if (rc)
- goto out;
+ if (!wil_has_other_active_ifaces(wil, ndev, true, false)) {
+ __wil_down(wil);
+ rc = __wil_up(wil);
+ if (rc)
+ goto out;
+ }
rc = wmi_set_ssid(vif, ssid_len, ssid);
if (rc)
@@ -1549,7 +1556,8 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
vif->pbss = pbss;
netif_carrier_on(ndev);
- wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
+ if (!wil_has_other_active_ifaces(wil, ndev, false, true))
+ wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, hidden_ssid, is_go);
if (rc)
@@ -1565,7 +1573,8 @@ err_bcast:
wmi_pcp_stop(vif);
err_pcp_start:
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);
out:
mutex_unlock(&wil->mutex);
return rc;
@@ -1670,20 +1679,26 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
struct wil6210_vif *vif = ndev_to_vif(ndev);
+ bool last;
- wil_dbg_misc(wil, "stop_ap\n");
+ wil_dbg_misc(wil, "stop_ap, mid=%d\n", vif->mid);
netif_carrier_off(ndev);
- wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
- wil_set_recovery_state(wil, fw_recovery_idle);
-
- set_bit(wil_status_resetting, wil->status);
+ last = !wil_has_other_active_ifaces(wil, ndev, false, true);
+ if (last) {
+ wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
+ wil_set_recovery_state(wil, fw_recovery_idle);
+ set_bit(wil_status_resetting, wil->status);
+ }
mutex_lock(&wil->mutex);
wmi_pcp_stop(vif);
- __wil_down(wil);
+ if (last)
+ __wil_down(wil);
+ else
+ wil_bcast_fini(vif);
mutex_unlock(&wil->mutex);