aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wil6210/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/main.c')
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c95
1 files changed, 80 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 6500caf8d609..6212983fede2 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -38,6 +38,35 @@ static unsigned int itr_trsh = WIL6210_ITR_TRSH_DEFAULT;
38module_param(itr_trsh, uint, S_IRUGO); 38module_param(itr_trsh, uint, S_IRUGO);
39MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs."); 39MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs.");
40 40
41/* We allow allocation of more than 1 page buffers to support large packets.
42 * It is suboptimal behavior performance wise in case MTU above page size.
43 */
44unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - ETH_HLEN;
45static int mtu_max_set(const char *val, const struct kernel_param *kp)
46{
47 int ret;
48
49 /* sets mtu_max directly. no need to restore it in case of
50 * illegal value since we assume this will fail insmod
51 */
52 ret = param_set_uint(val, kp);
53 if (ret)
54 return ret;
55
56 if (mtu_max < 68 || mtu_max > IEEE80211_MAX_DATA_LEN_DMG)
57 ret = -EINVAL;
58
59 return ret;
60}
61
62static struct kernel_param_ops mtu_max_ops = {
63 .set = mtu_max_set,
64 .get = param_get_uint,
65};
66
67module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO);
68MODULE_PARM_DESC(mtu_max, " Max MTU value.");
69
41#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ 70#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
42#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ 71#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
43 72
@@ -74,7 +103,8 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
74 __raw_writel(*s++, d++); 103 __raw_writel(*s++, d++);
75} 104}
76 105
77static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) 106static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
107 bool from_event)
78{ 108{
79 uint i; 109 uint i;
80 struct net_device *ndev = wil_to_ndev(wil); 110 struct net_device *ndev = wil_to_ndev(wil);
@@ -86,7 +116,10 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
86 116
87 sta->data_port_open = false; 117 sta->data_port_open = false;
88 if (sta->status != wil_sta_unused) { 118 if (sta->status != wil_sta_unused) {
89 wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING); 119 if (!from_event)
120 wmi_disconnect_sta(wil, sta->addr,
121 WLAN_REASON_DEAUTH_LEAVING);
122
90 switch (wdev->iftype) { 123 switch (wdev->iftype) {
91 case NL80211_IFTYPE_AP: 124 case NL80211_IFTYPE_AP:
92 case NL80211_IFTYPE_P2P_GO: 125 case NL80211_IFTYPE_P2P_GO:
@@ -118,7 +151,8 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
118 memset(&sta->stats, 0, sizeof(sta->stats)); 151 memset(&sta->stats, 0, sizeof(sta->stats));
119} 152}
120 153
121static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) 154static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
155 bool from_event)
122{ 156{
123 int cid = -ENOENT; 157 int cid = -ENOENT;
124 struct net_device *ndev = wil_to_ndev(wil); 158 struct net_device *ndev = wil_to_ndev(wil);
@@ -133,10 +167,10 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
133 } 167 }
134 168
135 if (cid >= 0) /* disconnect 1 peer */ 169 if (cid >= 0) /* disconnect 1 peer */
136 wil_disconnect_cid(wil, cid); 170 wil_disconnect_cid(wil, cid, from_event);
137 else /* disconnect all */ 171 else /* disconnect all */
138 for (cid = 0; cid < WIL6210_MAX_CID; cid++) 172 for (cid = 0; cid < WIL6210_MAX_CID; cid++)
139 wil_disconnect_cid(wil, cid); 173 wil_disconnect_cid(wil, cid, from_event);
140 174
141 /* link state */ 175 /* link state */
142 switch (wdev->iftype) { 176 switch (wdev->iftype) {
@@ -166,7 +200,7 @@ static void wil_disconnect_worker(struct work_struct *work)
166 struct wil6210_priv, disconnect_worker); 200 struct wil6210_priv, disconnect_worker);
167 201
168 mutex_lock(&wil->mutex); 202 mutex_lock(&wil->mutex);
169 _wil6210_disconnect(wil, NULL); 203 _wil6210_disconnect(wil, NULL, false);
170 mutex_unlock(&wil->mutex); 204 mutex_unlock(&wil->mutex);
171} 205}
172 206
@@ -223,6 +257,11 @@ static void wil_fw_error_worker(struct work_struct *work)
223 257
224 wil_dbg_misc(wil, "fw error worker\n"); 258 wil_dbg_misc(wil, "fw error worker\n");
225 259
260 if (!netif_running(wil_to_ndev(wil))) {
261 wil_info(wil, "No recovery - interface is down\n");
262 return;
263 }
264
226 /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO 265 /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO
227 * passed since last recovery attempt 266 * passed since last recovery attempt
228 */ 267 */
@@ -257,9 +296,12 @@ static void wil_fw_error_worker(struct work_struct *work)
257 break; 296 break;
258 case NL80211_IFTYPE_AP: 297 case NL80211_IFTYPE_AP:
259 case NL80211_IFTYPE_P2P_GO: 298 case NL80211_IFTYPE_P2P_GO:
299 wil_info(wil, "No recovery for AP-like interface\n");
260 /* recovery in these modes is done by upper layers */ 300 /* recovery in these modes is done by upper layers */
261 break; 301 break;
262 default: 302 default:
303 wil_err(wil, "No recovery - unknown interface type %d\n",
304 wdev->iftype);
263 break; 305 break;
264 } 306 }
265 mutex_unlock(&wil->mutex); 307 mutex_unlock(&wil->mutex);
@@ -346,12 +388,22 @@ int wil_priv_init(struct wil6210_priv *wil)
346 return 0; 388 return 0;
347} 389}
348 390
349void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) 391/**
392 * wil6210_disconnect - disconnect one connection
393 * @wil: driver context
394 * @bssid: peer to disconnect, NULL to disconnect all
395 * @from_event: whether is invoked from FW event handler
396 *
397 * Disconnect and release associated resources. If invoked not from the
398 * FW event handler, issue WMI command(s) to trigger MAC disconnect.
399 */
400void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
401 bool from_event)
350{ 402{
351 wil_dbg_misc(wil, "%s()\n", __func__); 403 wil_dbg_misc(wil, "%s()\n", __func__);
352 404
353 del_timer_sync(&wil->connect_timer); 405 del_timer_sync(&wil->connect_timer);
354 _wil6210_disconnect(wil, bssid); 406 _wil6210_disconnect(wil, bssid, from_event);
355} 407}
356 408
357void wil_priv_deinit(struct wil6210_priv *wil) 409void wil_priv_deinit(struct wil6210_priv *wil)
@@ -363,7 +415,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
363 cancel_work_sync(&wil->disconnect_worker); 415 cancel_work_sync(&wil->disconnect_worker);
364 cancel_work_sync(&wil->fw_error_worker); 416 cancel_work_sync(&wil->fw_error_worker);
365 mutex_lock(&wil->mutex); 417 mutex_lock(&wil->mutex);
366 wil6210_disconnect(wil, NULL); 418 wil6210_disconnect(wil, NULL, false);
367 mutex_unlock(&wil->mutex); 419 mutex_unlock(&wil->mutex);
368 wmi_event_flush(wil); 420 wmi_event_flush(wil);
369 destroy_workqueue(wil->wmi_wq_conn); 421 destroy_workqueue(wil->wmi_wq_conn);
@@ -395,7 +447,7 @@ static inline void wil_release_cpu(struct wil6210_priv *wil)
395static int wil_target_reset(struct wil6210_priv *wil) 447static int wil_target_reset(struct wil6210_priv *wil)
396{ 448{
397 int delay = 0; 449 int delay = 0;
398 u32 hw_state; 450 u32 x;
399 u32 rev_id; 451 u32 rev_id;
400 bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW); 452 bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
401 453
@@ -410,9 +462,22 @@ static int wil_target_reset(struct wil6210_priv *wil)
410 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST); 462 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST);
411 463
412 wil_halt_cpu(wil); 464 wil_halt_cpu(wil);
413 C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); /* 40 MHz */
414 465
415 if (is_sparrow) { 466 if (is_sparrow) {
467 S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN);
468 /* XTAL stabilization should take about 3ms */
469 usleep_range(5000, 7000);
470 x = R(RGF_CAF_PLL_LOCK_STATUS);
471 if (!(x & BIT_CAF_OSC_DIG_XTAL_STABLE)) {
472 wil_err(wil, "Xtal stabilization timeout\n"
473 "RGF_CAF_PLL_LOCK_STATUS = 0x%08x\n", x);
474 return -ETIME;
475 }
476 /* switch 10k to XTAL*/
477 C(RGF_USER_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF);
478 /* 40 MHz */
479 C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL);
480
416 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f); 481 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
417 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf); 482 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
418 } 483 }
@@ -453,13 +518,13 @@ static int wil_target_reset(struct wil6210_priv *wil)
453 /* wait until device ready. typical time is 200..250 msec */ 518 /* wait until device ready. typical time is 200..250 msec */
454 do { 519 do {
455 msleep(RST_DELAY); 520 msleep(RST_DELAY);
456 hw_state = R(RGF_USER_HW_MACHINE_STATE); 521 x = R(RGF_USER_HW_MACHINE_STATE);
457 if (delay++ > RST_COUNT) { 522 if (delay++ > RST_COUNT) {
458 wil_err(wil, "Reset not completed, hw_state 0x%08x\n", 523 wil_err(wil, "Reset not completed, hw_state 0x%08x\n",
459 hw_state); 524 x);
460 return -ETIME; 525 return -ETIME;
461 } 526 }
462 } while (hw_state != HW_MACHINE_BOOT_DONE); 527 } while (x != HW_MACHINE_BOOT_DONE);
463 528
464 /* TODO: Erez check rev_id != 1 */ 529 /* TODO: Erez check rev_id != 1 */
465 if (!is_sparrow && (rev_id != 1)) 530 if (!is_sparrow && (rev_id != 1))
@@ -535,7 +600,7 @@ int wil_reset(struct wil6210_priv *wil)
535 WARN_ON(test_bit(wil_status_napi_en, &wil->status)); 600 WARN_ON(test_bit(wil_status_napi_en, &wil->status));
536 601
537 cancel_work_sync(&wil->disconnect_worker); 602 cancel_work_sync(&wil->disconnect_worker);
538 wil6210_disconnect(wil, NULL); 603 wil6210_disconnect(wil, NULL, false);
539 604
540 wil->status = 0; /* prevent NAPI from being scheduled */ 605 wil->status = 0; /* prevent NAPI from being scheduled */
541 606