aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>2014-10-28 10:50:08 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-10-30 15:26:50 -0400
commitb516fcc5542d41041156b8e5f93f47cbb603c4b7 (patch)
tree069bbaf83202f02857d068f30c247de475a50863 /drivers/net
parent48516298edb4260748c52064f828319c3bb15536 (diff)
wil6210: prevent double disconnect command issuing
Disconnect flow may be invoked either from upper layer request, or from event reported by the firmware. In case of firmware event, driver need to release resources for the station but not send another disconnect WMI command. In case of upper layer request, WMI_DISCONNECT_STA_CMDID command need to be issued for the firmware to perform disconnect on the MAC layer. Eventually, event is expected to confirm MAC disconnect, but it is better to not wait for firmware event and release station resources immediately. FW may fail to report disconnect for various reasons, so one could not rely on event always reported. Introduce parameter to distinguish 2 cases above to prevent double WMI command issuing. Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c35
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h3
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c2
4 files changed, 29 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index d9f4b30dd343..4248fb3352d2 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -797,7 +797,7 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy,
797 struct wil6210_priv *wil = wiphy_to_wil(wiphy); 797 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
798 798
799 mutex_lock(&wil->mutex); 799 mutex_lock(&wil->mutex);
800 wil6210_disconnect(wil, mac); 800 wil6210_disconnect(wil, mac, false);
801 mutex_unlock(&wil->mutex); 801 mutex_unlock(&wil->mutex);
802 802
803 return 0; 803 return 0;
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 0e95557e177f..b3a84ae04ce3 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -74,7 +74,8 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
74 __raw_writel(*s++, d++); 74 __raw_writel(*s++, d++);
75} 75}
76 76
77static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) 77static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
78 bool from_event)
78{ 79{
79 uint i; 80 uint i;
80 struct net_device *ndev = wil_to_ndev(wil); 81 struct net_device *ndev = wil_to_ndev(wil);
@@ -86,7 +87,10 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
86 87
87 sta->data_port_open = false; 88 sta->data_port_open = false;
88 if (sta->status != wil_sta_unused) { 89 if (sta->status != wil_sta_unused) {
89 wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING); 90 if (!from_event)
91 wmi_disconnect_sta(wil, sta->addr,
92 WLAN_REASON_DEAUTH_LEAVING);
93
90 switch (wdev->iftype) { 94 switch (wdev->iftype) {
91 case NL80211_IFTYPE_AP: 95 case NL80211_IFTYPE_AP:
92 case NL80211_IFTYPE_P2P_GO: 96 case NL80211_IFTYPE_P2P_GO:
@@ -118,7 +122,8 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
118 memset(&sta->stats, 0, sizeof(sta->stats)); 122 memset(&sta->stats, 0, sizeof(sta->stats));
119} 123}
120 124
121static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) 125static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
126 bool from_event)
122{ 127{
123 int cid = -ENOENT; 128 int cid = -ENOENT;
124 struct net_device *ndev = wil_to_ndev(wil); 129 struct net_device *ndev = wil_to_ndev(wil);
@@ -133,10 +138,10 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
133 } 138 }
134 139
135 if (cid >= 0) /* disconnect 1 peer */ 140 if (cid >= 0) /* disconnect 1 peer */
136 wil_disconnect_cid(wil, cid); 141 wil_disconnect_cid(wil, cid, from_event);
137 else /* disconnect all */ 142 else /* disconnect all */
138 for (cid = 0; cid < WIL6210_MAX_CID; cid++) 143 for (cid = 0; cid < WIL6210_MAX_CID; cid++)
139 wil_disconnect_cid(wil, cid); 144 wil_disconnect_cid(wil, cid, from_event);
140 145
141 /* link state */ 146 /* link state */
142 switch (wdev->iftype) { 147 switch (wdev->iftype) {
@@ -166,7 +171,7 @@ static void wil_disconnect_worker(struct work_struct *work)
166 struct wil6210_priv, disconnect_worker); 171 struct wil6210_priv, disconnect_worker);
167 172
168 mutex_lock(&wil->mutex); 173 mutex_lock(&wil->mutex);
169 _wil6210_disconnect(wil, NULL); 174 _wil6210_disconnect(wil, NULL, false);
170 mutex_unlock(&wil->mutex); 175 mutex_unlock(&wil->mutex);
171} 176}
172 177
@@ -351,12 +356,22 @@ int wil_priv_init(struct wil6210_priv *wil)
351 return 0; 356 return 0;
352} 357}
353 358
354void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) 359/**
360 * wil6210_disconnect - disconnect one connection
361 * @wil: driver context
362 * @bssid: peer to disconnect, NULL to disconnect all
363 * @from_event: whether is invoked from FW event handler
364 *
365 * Disconnect and release associated resources. If invoked not from the
366 * FW event handler, issue WMI command(s) to trigger MAC disconnect.
367 */
368void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
369 bool from_event)
355{ 370{
356 wil_dbg_misc(wil, "%s()\n", __func__); 371 wil_dbg_misc(wil, "%s()\n", __func__);
357 372
358 del_timer_sync(&wil->connect_timer); 373 del_timer_sync(&wil->connect_timer);
359 _wil6210_disconnect(wil, bssid); 374 _wil6210_disconnect(wil, bssid, from_event);
360} 375}
361 376
362void wil_priv_deinit(struct wil6210_priv *wil) 377void wil_priv_deinit(struct wil6210_priv *wil)
@@ -368,7 +383,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
368 cancel_work_sync(&wil->disconnect_worker); 383 cancel_work_sync(&wil->disconnect_worker);
369 cancel_work_sync(&wil->fw_error_worker); 384 cancel_work_sync(&wil->fw_error_worker);
370 mutex_lock(&wil->mutex); 385 mutex_lock(&wil->mutex);
371 wil6210_disconnect(wil, NULL); 386 wil6210_disconnect(wil, NULL, false);
372 mutex_unlock(&wil->mutex); 387 mutex_unlock(&wil->mutex);
373 wmi_event_flush(wil); 388 wmi_event_flush(wil);
374 destroy_workqueue(wil->wmi_wq_conn); 389 destroy_workqueue(wil->wmi_wq_conn);
@@ -553,7 +568,7 @@ int wil_reset(struct wil6210_priv *wil)
553 WARN_ON(test_bit(wil_status_napi_en, &wil->status)); 568 WARN_ON(test_bit(wil_status_napi_en, &wil->status));
554 569
555 cancel_work_sync(&wil->disconnect_worker); 570 cancel_work_sync(&wil->disconnect_worker);
556 wil6210_disconnect(wil, NULL); 571 wil6210_disconnect(wil, NULL, false);
557 572
558 wil->status = 0; /* prevent NAPI from being scheduled */ 573 wil->status = 0; /* prevent NAPI from being scheduled */
559 574
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 18f8729a6b2c..3674e2732192 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -584,7 +584,8 @@ void wil_wdev_free(struct wil6210_priv *wil);
584int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); 584int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
585int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); 585int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
586int wmi_pcp_stop(struct wil6210_priv *wil); 586int wmi_pcp_stop(struct wil6210_priv *wil);
587void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid); 587void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
588 bool from_event);
588 589
589int wil_rx_init(struct wil6210_priv *wil); 590int wil_rx_init(struct wil6210_priv *wil);
590void wil_rx_fini(struct wil6210_priv *wil); 591void wil_rx_fini(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 4311df982c60..9661fa150167 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -486,7 +486,7 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
486 wil->sinfo_gen++; 486 wil->sinfo_gen++;
487 487
488 mutex_lock(&wil->mutex); 488 mutex_lock(&wil->mutex);
489 wil6210_disconnect(wil, evt->bssid); 489 wil6210_disconnect(wil, evt->bssid, true);
490 mutex_unlock(&wil->mutex); 490 mutex_unlock(&wil->mutex);
491} 491}
492 492