aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c27
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_gpio.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.c97
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.h7
7 files changed, 89 insertions, 57 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 133fc6dc3929..20511af33f5f 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -497,7 +497,8 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
497void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, 497void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
498 struct ieee80211_vif *vif); 498 struct ieee80211_vif *vif);
499void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); 499void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv);
500void ath9k_htc_swba(struct ath9k_htc_priv *priv); 500void ath9k_htc_swba(struct ath9k_htc_priv *priv,
501 struct wmi_event_swba *swba);
501 502
502void ath9k_htc_rxep(void *priv, struct sk_buff *skb, 503void ath9k_htc_rxep(void *priv, struct sk_buff *skb,
503 enum htc_endpoint_id ep_id); 504 enum htc_endpoint_id ep_id);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index 48bc28823f6f..2180a9da3801 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -401,10 +401,10 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
401 spin_unlock_bh(&priv->beacon_lock); 401 spin_unlock_bh(&priv->beacon_lock);
402} 402}
403 403
404static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv) 404static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
405 struct wmi_event_swba *swba)
405{ 406{
406 struct ath_common *common = ath9k_hw_common(priv->ah); 407 struct ath_common *common = ath9k_hw_common(priv->ah);
407 unsigned long flags;
408 u64 tsf; 408 u64 tsf;
409 u32 tsftu; 409 u32 tsftu;
410 u16 intval; 410 u16 intval;
@@ -412,10 +412,7 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv)
412 412
413 intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD; 413 intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD;
414 414
415 spin_lock_irqsave(&priv->wmi->wmi_lock, flags); 415 tsf = be64_to_cpu(swba->tsf);
416 tsf = priv->wmi->tsf;
417 spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
418
419 tsftu = TSF_TO_TU(tsf >> 32, tsf); 416 tsftu = TSF_TO_TU(tsf >> 32, tsf);
420 slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; 417 slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval;
421 slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; 418 slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1;
@@ -427,33 +424,31 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv)
427 return slot; 424 return slot;
428} 425}
429 426
430void ath9k_htc_swba(struct ath9k_htc_priv *priv) 427void ath9k_htc_swba(struct ath9k_htc_priv *priv,
428 struct wmi_event_swba *swba)
431{ 429{
432 struct ath_common *common = ath9k_hw_common(priv->ah); 430 struct ath_common *common = ath9k_hw_common(priv->ah);
433 unsigned long flags;
434 int slot; 431 int slot;
435 432
436 spin_lock_irqsave(&priv->wmi->wmi_lock, flags); 433 if (swba->beacon_pending != 0) {
437 if (priv->wmi->beacon_pending != 0) {
438 spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
439 priv->cur_beacon_conf.bmiss_cnt++; 434 priv->cur_beacon_conf.bmiss_cnt++;
440 if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { 435 if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) {
441 ath_dbg(common, ATH_DBG_BEACON, 436 ath_dbg(common, ATH_DBG_BSTUCK,
442 "Beacon stuck, HW reset\n"); 437 "Beacon stuck, HW reset\n");
443 ath9k_htc_reset(priv); 438 ieee80211_queue_work(priv->hw,
439 &priv->fatal_work);
444 } 440 }
445 return; 441 return;
446 } 442 }
447 spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
448 443
449 if (priv->cur_beacon_conf.bmiss_cnt) { 444 if (priv->cur_beacon_conf.bmiss_cnt) {
450 ath_dbg(common, ATH_DBG_BEACON, 445 ath_dbg(common, ATH_DBG_BSTUCK,
451 "Resuming beacon xmit after %u misses\n", 446 "Resuming beacon xmit after %u misses\n",
452 priv->cur_beacon_conf.bmiss_cnt); 447 priv->cur_beacon_conf.bmiss_cnt);
453 priv->cur_beacon_conf.bmiss_cnt = 0; 448 priv->cur_beacon_conf.bmiss_cnt = 0;
454 } 449 }
455 450
456 slot = ath9k_htc_choose_bslot(priv); 451 slot = ath9k_htc_choose_bslot(priv, swba);
457 spin_lock_bh(&priv->beacon_lock); 452 spin_lock_bh(&priv->beacon_lock);
458 if (priv->cur_beacon_conf.bslot[slot] == NULL) { 453 if (priv->cur_beacon_conf.bslot[slot] == NULL) {
459 spin_unlock_bh(&priv->beacon_lock); 454 spin_unlock_bh(&priv->beacon_lock);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index 7e630a81b453..459ba0d36f4c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -436,6 +436,9 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
436 /* Stop RX */ 436 /* Stop RX */
437 WMI_CMD(WMI_STOP_RECV_CMDID); 437 WMI_CMD(WMI_STOP_RECV_CMDID);
438 438
439 /* Clear the WMI event queue */
440 ath9k_wmi_event_drain(priv);
441
439 /* 442 /*
440 * The MIB counters have to be disabled here, 443 * The MIB counters have to be disabled here,
441 * since the target doesn't do it. 444 * since the target doesn't do it.
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index b1c68bff72a6..921d76f32016 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -676,8 +676,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
676 spin_lock_init(&priv->tx_lock); 676 spin_lock_init(&priv->tx_lock);
677 mutex_init(&priv->mutex); 677 mutex_init(&priv->mutex);
678 mutex_init(&priv->htc_pm_lock); 678 mutex_init(&priv->htc_pm_lock);
679 tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
680 (unsigned long)priv);
681 tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, 679 tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
682 (unsigned long)priv); 680 (unsigned long)priv);
683 tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, 681 tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 8f38075d1240..81dfe0782f74 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -202,6 +202,8 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
202 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); 202 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
203 WMI_CMD(WMI_STOP_RECV_CMDID); 203 WMI_CMD(WMI_STOP_RECV_CMDID);
204 204
205 ath9k_wmi_event_drain(priv);
206
205 caldata = &priv->caldata; 207 caldata = &priv->caldata;
206 ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); 208 ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
207 if (ret) { 209 if (ret) {
@@ -255,6 +257,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
255 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); 257 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
256 WMI_CMD(WMI_STOP_RECV_CMDID); 258 WMI_CMD(WMI_STOP_RECV_CMDID);
257 259
260 ath9k_wmi_event_drain(priv);
261
258 ath_dbg(common, ATH_DBG_CONFIG, 262 ath_dbg(common, ATH_DBG_CONFIG,
259 "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", 263 "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
260 priv->ah->curchan->channel, 264 priv->ah->curchan->channel,
@@ -1172,12 +1176,13 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
1172 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); 1176 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
1173 WMI_CMD(WMI_STOP_RECV_CMDID); 1177 WMI_CMD(WMI_STOP_RECV_CMDID);
1174 1178
1175 tasklet_kill(&priv->swba_tasklet);
1176 tasklet_kill(&priv->rx_tasklet); 1179 tasklet_kill(&priv->rx_tasklet);
1177 tasklet_kill(&priv->tx_tasklet); 1180 tasklet_kill(&priv->tx_tasklet);
1178 1181
1179 skb_queue_purge(&priv->tx_queue); 1182 skb_queue_purge(&priv->tx_queue);
1180 1183
1184 ath9k_wmi_event_drain(priv);
1185
1181 mutex_unlock(&priv->mutex); 1186 mutex_unlock(&priv->mutex);
1182 1187
1183 /* Cancel all the running timers/work .. */ 1188 /* Cancel all the running timers/work .. */
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index a39552b3077b..45784754dbc2 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -104,9 +104,12 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)
104 104
105 wmi->drv_priv = priv; 105 wmi->drv_priv = priv;
106 wmi->stopped = false; 106 wmi->stopped = false;
107 skb_queue_head_init(&wmi->wmi_event_queue);
107 mutex_init(&wmi->op_mutex); 108 mutex_init(&wmi->op_mutex);
108 mutex_init(&wmi->multi_write_mutex); 109 mutex_init(&wmi->multi_write_mutex);
109 init_completion(&wmi->cmd_wait); 110 init_completion(&wmi->cmd_wait);
111 tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet,
112 (unsigned long)wmi);
110 113
111 return wmi; 114 return wmi;
112} 115}
@@ -122,11 +125,64 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
122 kfree(priv->wmi); 125 kfree(priv->wmi);
123} 126}
124 127
125void ath9k_swba_tasklet(unsigned long data) 128void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv)
126{ 129{
127 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; 130 unsigned long flags;
128 131
129 ath9k_htc_swba(priv); 132 tasklet_kill(&priv->wmi->wmi_event_tasklet);
133 spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
134 __skb_queue_purge(&priv->wmi->wmi_event_queue);
135 spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
136}
137
138void ath9k_wmi_event_tasklet(unsigned long data)
139{
140 struct wmi *wmi = (struct wmi *)data;
141 struct ath9k_htc_priv *priv = wmi->drv_priv;
142 struct wmi_cmd_hdr *hdr;
143 void *wmi_event;
144 struct wmi_event_swba *swba;
145 struct sk_buff *skb = NULL;
146 unsigned long flags;
147 u16 cmd_id;
148#ifdef CONFIG_ATH9K_HTC_DEBUGFS
149 __be32 txrate;
150#endif
151
152 do {
153 spin_lock_irqsave(&wmi->wmi_lock, flags);
154 skb = __skb_dequeue(&wmi->wmi_event_queue);
155 if (!skb) {
156 spin_unlock_irqrestore(&wmi->wmi_lock, flags);
157 return;
158 }
159 spin_unlock_irqrestore(&wmi->wmi_lock, flags);
160
161 hdr = (struct wmi_cmd_hdr *) skb->data;
162 cmd_id = be16_to_cpu(hdr->command_id);
163 wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
164
165 switch (cmd_id) {
166 case WMI_SWBA_EVENTID:
167 swba = (struct wmi_event_swba *) wmi_event;
168 ath9k_htc_swba(priv, swba);
169 break;
170 case WMI_FATAL_EVENTID:
171 ieee80211_queue_work(wmi->drv_priv->hw,
172 &wmi->drv_priv->fatal_work);
173 break;
174 case WMI_TXRATE_EVENTID:
175#ifdef CONFIG_ATH9K_HTC_DEBUGFS
176 txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
177 wmi->drv_priv->debug.txrate = be32_to_cpu(txrate);
178#endif
179 break;
180 default:
181 break;
182 }
183
184 kfree_skb(skb);
185 } while (1);
130} 186}
131 187
132void ath9k_fatal_work(struct work_struct *work) 188void ath9k_fatal_work(struct work_struct *work)
@@ -155,11 +211,6 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
155 struct wmi *wmi = (struct wmi *) priv; 211 struct wmi *wmi = (struct wmi *) priv;
156 struct wmi_cmd_hdr *hdr; 212 struct wmi_cmd_hdr *hdr;
157 u16 cmd_id; 213 u16 cmd_id;
158 void *wmi_event;
159 struct wmi_event_swba *swba;
160#ifdef CONFIG_ATH9K_HTC_DEBUGFS
161 __be32 txrate;
162#endif
163 214
164 if (unlikely(wmi->stopped)) 215 if (unlikely(wmi->stopped))
165 goto free_skb; 216 goto free_skb;
@@ -168,32 +219,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
168 cmd_id = be16_to_cpu(hdr->command_id); 219 cmd_id = be16_to_cpu(hdr->command_id);
169 220
170 if (cmd_id & 0x1000) { 221 if (cmd_id & 0x1000) {
171 wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); 222 spin_lock(&wmi->wmi_lock);
172 switch (cmd_id) { 223 __skb_queue_tail(&wmi->wmi_event_queue, skb);
173 case WMI_SWBA_EVENTID: 224 spin_unlock(&wmi->wmi_lock);
174 swba = (struct wmi_event_swba *) wmi_event; 225 tasklet_schedule(&wmi->wmi_event_tasklet);
175
176 spin_lock(&wmi->wmi_lock);
177 wmi->tsf = be64_to_cpu(swba->tsf);
178 wmi->beacon_pending = swba->beacon_pending;
179 spin_unlock(&wmi->wmi_lock);
180
181 tasklet_schedule(&wmi->drv_priv->swba_tasklet);
182 break;
183 case WMI_FATAL_EVENTID:
184 ieee80211_queue_work(wmi->drv_priv->hw,
185 &wmi->drv_priv->fatal_work);
186 break;
187 case WMI_TXRATE_EVENTID:
188#ifdef CONFIG_ATH9K_HTC_DEBUGFS
189 txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
190 wmi->drv_priv->debug.txrate = be32_to_cpu(txrate);
191#endif
192 break;
193 default:
194 break;
195 }
196 kfree_skb(skb);
197 return; 226 return;
198 } 227 }
199 228
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index 2fa91a941a72..ff5ba2b30ecc 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -106,13 +106,13 @@ struct wmi {
106 struct mutex op_mutex; 106 struct mutex op_mutex;
107 struct completion cmd_wait; 107 struct completion cmd_wait;
108 enum wmi_cmd_id last_cmd_id; 108 enum wmi_cmd_id last_cmd_id;
109 struct sk_buff_head wmi_event_queue;
110 struct tasklet_struct wmi_event_tasklet;
109 u16 tx_seq_id; 111 u16 tx_seq_id;
110 u8 *cmd_rsp_buf; 112 u8 *cmd_rsp_buf;
111 u32 cmd_rsp_len; 113 u32 cmd_rsp_len;
112 bool stopped; 114 bool stopped;
113 115
114 u64 tsf;
115 u8 beacon_pending;
116 spinlock_t wmi_lock; 116 spinlock_t wmi_lock;
117 117
118 atomic_t mwrite_cnt; 118 atomic_t mwrite_cnt;
@@ -129,8 +129,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
129 u8 *cmd_buf, u32 cmd_len, 129 u8 *cmd_buf, u32 cmd_len,
130 u8 *rsp_buf, u32 rsp_len, 130 u8 *rsp_buf, u32 rsp_len,
131 u32 timeout); 131 u32 timeout);
132void ath9k_swba_tasklet(unsigned long data); 132void ath9k_wmi_event_tasklet(unsigned long data);
133void ath9k_fatal_work(struct work_struct *work); 133void ath9k_fatal_work(struct work_struct *work);
134void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);
134 135
135#define WMI_CMD(_wmi_cmd) \ 136#define WMI_CMD(_wmi_cmd) \
136 do { \ 137 do { \