aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2010-06-15 00:54:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-15 16:02:22 -0400
commitd7ca21393d39cb2e73dfc4c516e7be37ba01789e (patch)
tree35c2afd019f0274a2b812f091742c1d53823f155 /drivers/net
parent9a2af8892a74573cec4bea2149843a93442a12de (diff)
ath9k_htc: Fix ampdu_action callback
Now that ampdu_action() can sleep, remove all the driver hacks and just issue WMI commands to the target. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h20
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c93
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c21
4 files changed, 45 insertions, 92 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index c584fbd2fe51..58f52a1dc7ea 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -223,15 +223,6 @@ struct ath9k_htc_sta {
223 enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; 223 enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID];
224}; 224};
225 225
226struct ath9k_htc_aggr_work {
227 u16 tid;
228 u8 sta_addr[ETH_ALEN];
229 struct ieee80211_hw *hw;
230 struct ieee80211_vif *vif;
231 enum ieee80211_ampdu_mlme_action action;
232 struct mutex mutex;
233};
234
235#define ATH9K_HTC_RXBUF 256 226#define ATH9K_HTC_RXBUF 256
236#define HTC_RX_FRAME_HEADER_SIZE 40 227#define HTC_RX_FRAME_HEADER_SIZE 40
237 228
@@ -331,11 +322,10 @@ struct htc_beacon_config {
331#define OP_LED_ON BIT(4) 322#define OP_LED_ON BIT(4)
332#define OP_PREAMBLE_SHORT BIT(5) 323#define OP_PREAMBLE_SHORT BIT(5)
333#define OP_PROTECT_ENABLE BIT(6) 324#define OP_PROTECT_ENABLE BIT(6)
334#define OP_TXAGGR BIT(7) 325#define OP_ASSOCIATED BIT(7)
335#define OP_ASSOCIATED BIT(8) 326#define OP_ENABLE_BEACON BIT(8)
336#define OP_ENABLE_BEACON BIT(9) 327#define OP_LED_DEINIT BIT(9)
337#define OP_LED_DEINIT BIT(10) 328#define OP_UNPLUGGED BIT(10)
338#define OP_UNPLUGGED BIT(11)
339 329
340struct ath9k_htc_priv { 330struct ath9k_htc_priv {
341 struct device *dev; 331 struct device *dev;
@@ -376,8 +366,6 @@ struct ath9k_htc_priv {
376 struct ath9k_htc_rx rx; 366 struct ath9k_htc_rx rx;
377 struct tasklet_struct tx_tasklet; 367 struct tasklet_struct tx_tasklet;
378 struct sk_buff_head tx_queue; 368 struct sk_buff_head tx_queue;
379 struct ath9k_htc_aggr_work aggr_work;
380 struct delayed_work ath9k_aggr_work;
381 struct delayed_work ath9k_ani_work; 369 struct delayed_work ath9k_ani_work;
382 struct work_struct ps_work; 370 struct work_struct ps_work;
383 371
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index d339e5f92216..a63ae88abf3e 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -606,7 +606,6 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
606 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) 606 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
607 memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); 607 memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
608 608
609 priv->op_flags |= OP_TXAGGR;
610 priv->ah->opmode = NL80211_IFTYPE_STATION; 609 priv->ah->opmode = NL80211_IFTYPE_STATION;
611} 610}
612 611
@@ -638,14 +637,12 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid)
638 spin_lock_init(&priv->beacon_lock); 637 spin_lock_init(&priv->beacon_lock);
639 spin_lock_init(&priv->tx_lock); 638 spin_lock_init(&priv->tx_lock);
640 mutex_init(&priv->mutex); 639 mutex_init(&priv->mutex);
641 mutex_init(&priv->aggr_work.mutex);
642 mutex_init(&priv->htc_pm_lock); 640 mutex_init(&priv->htc_pm_lock);
643 tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, 641 tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
644 (unsigned long)priv); 642 (unsigned long)priv);
645 tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, 643 tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
646 (unsigned long)priv); 644 (unsigned long)priv);
647 tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); 645 tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
648 INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work);
649 INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); 646 INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
650 INIT_WORK(&priv->ps_work, ath9k_ps_work); 647 INIT_WORK(&priv->ps_work, ath9k_ps_work);
651 648
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index b9206e412cab..05445d8a9818 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -438,13 +438,13 @@ static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv,
438 bss_conf->bssid, be32_to_cpu(trate.capflags)); 438 bss_conf->bssid, be32_to_cpu(trate.capflags));
439} 439}
440 440
441static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, 441int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
442 struct ieee80211_vif *vif, 442 struct ieee80211_vif *vif,
443 u8 *sta_addr, u8 tid, bool oper) 443 struct ieee80211_sta *sta,
444 enum ieee80211_ampdu_mlme_action action, u16 tid)
444{ 445{
445 struct ath_common *common = ath9k_hw_common(priv->ah); 446 struct ath_common *common = ath9k_hw_common(priv->ah);
446 struct ath9k_htc_target_aggr aggr; 447 struct ath9k_htc_target_aggr aggr;
447 struct ieee80211_sta *sta = NULL;
448 struct ath9k_htc_sta *ista; 448 struct ath9k_htc_sta *ista;
449 int ret = 0; 449 int ret = 0;
450 u8 cmd_rsp; 450 u8 cmd_rsp;
@@ -453,72 +453,28 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv,
453 return -EINVAL; 453 return -EINVAL;
454 454
455 memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); 455 memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));
456
457 rcu_read_lock();
458
459 /* Check if we are able to retrieve the station */
460 sta = ieee80211_find_sta(vif, sta_addr);
461 if (!sta) {
462 rcu_read_unlock();
463 return -EINVAL;
464 }
465
466 ista = (struct ath9k_htc_sta *) sta->drv_priv; 456 ista = (struct ath9k_htc_sta *) sta->drv_priv;
467 457
468 if (oper)
469 ista->tid_state[tid] = AGGR_START;
470 else
471 ista->tid_state[tid] = AGGR_STOP;
472
473 aggr.sta_index = ista->index; 458 aggr.sta_index = ista->index;
474 459 aggr.tidno = tid & 0xf;
475 rcu_read_unlock(); 460 aggr.aggr_enable = (action == IEEE80211_AMPDU_TX_START) ? true : false;
476
477 aggr.tidno = tid;
478 aggr.aggr_enable = oper;
479 461
480 WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); 462 WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr);
481 if (ret) 463 if (ret)
482 ath_print(common, ATH_DBG_CONFIG, 464 ath_print(common, ATH_DBG_CONFIG,
483 "Unable to %s TX aggregation for (%pM, %d)\n", 465 "Unable to %s TX aggregation for (%pM, %d)\n",
484 (oper) ? "start" : "stop", sta->addr, tid); 466 (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid);
485 else 467 else
486 ath_print(common, ATH_DBG_CONFIG, 468 ath_print(common, ATH_DBG_CONFIG,
487 "%s aggregation for (%pM, %d)\n", 469 "%s TX aggregation for (%pM, %d)\n",
488 (oper) ? "Starting" : "Stopping", sta->addr, tid); 470 (aggr.aggr_enable) ? "Starting" : "Stopping",
489 471 sta->addr, tid);
490 return ret;
491}
492 472
493void ath9k_htc_aggr_work(struct work_struct *work) 473 spin_lock_bh(&priv->tx_lock);
494{ 474 ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP;
495 int ret = 0; 475 spin_unlock_bh(&priv->tx_lock);
496 struct ath9k_htc_priv *priv =
497 container_of(work, struct ath9k_htc_priv,
498 ath9k_aggr_work.work);
499 struct ath9k_htc_aggr_work *wk = &priv->aggr_work;
500
501 mutex_lock(&wk->mutex);
502
503 switch (wk->action) {
504 case IEEE80211_AMPDU_TX_START:
505 ret = ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr,
506 wk->tid, true);
507 if (!ret)
508 ieee80211_start_tx_ba_cb_irqsafe(wk->vif, wk->sta_addr,
509 wk->tid);
510 break;
511 case IEEE80211_AMPDU_TX_STOP:
512 ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr,
513 wk->tid, false);
514 ieee80211_stop_tx_ba_cb_irqsafe(wk->vif, wk->sta_addr, wk->tid);
515 break;
516 default:
517 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL,
518 "Unknown AMPDU action\n");
519 }
520 476
521 mutex_unlock(&wk->mutex); 477 return ret;
522} 478}
523 479
524/*********/ 480/*********/
@@ -1266,7 +1222,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
1266 /* Cancel all the running timers/work .. */ 1222 /* Cancel all the running timers/work .. */
1267 cancel_work_sync(&priv->ps_work); 1223 cancel_work_sync(&priv->ps_work);
1268 cancel_delayed_work_sync(&priv->ath9k_ani_work); 1224 cancel_delayed_work_sync(&priv->ath9k_ani_work);
1269 cancel_delayed_work_sync(&priv->ath9k_aggr_work);
1270 cancel_delayed_work_sync(&priv->ath9k_led_blink_work); 1225 cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
1271 ath9k_led_stop_brightness(priv); 1226 ath9k_led_stop_brightness(priv);
1272 1227
@@ -1767,8 +1722,8 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
1767 u16 tid, u16 *ssn) 1722 u16 tid, u16 *ssn)
1768{ 1723{
1769 struct ath9k_htc_priv *priv = hw->priv; 1724 struct ath9k_htc_priv *priv = hw->priv;
1770 struct ath9k_htc_aggr_work *work = &priv->aggr_work;
1771 struct ath9k_htc_sta *ista; 1725 struct ath9k_htc_sta *ista;
1726 int ret = 0;
1772 1727
1773 switch (action) { 1728 switch (action) {
1774 case IEEE80211_AMPDU_RX_START: 1729 case IEEE80211_AMPDU_RX_START:
@@ -1776,26 +1731,26 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
1776 case IEEE80211_AMPDU_RX_STOP: 1731 case IEEE80211_AMPDU_RX_STOP:
1777 break; 1732 break;
1778 case IEEE80211_AMPDU_TX_START: 1733 case IEEE80211_AMPDU_TX_START:
1734 ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
1735 if (!ret)
1736 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1737 break;
1779 case IEEE80211_AMPDU_TX_STOP: 1738 case IEEE80211_AMPDU_TX_STOP:
1780 if (!(priv->op_flags & OP_TXAGGR)) 1739 ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
1781 return -ENOTSUPP; 1740 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1782 memcpy(work->sta_addr, sta->addr, ETH_ALEN);
1783 work->hw = hw;
1784 work->vif = vif;
1785 work->action = action;
1786 work->tid = tid;
1787 ieee80211_queue_delayed_work(hw, &priv->ath9k_aggr_work, 0);
1788 break; 1741 break;
1789 case IEEE80211_AMPDU_TX_OPERATIONAL: 1742 case IEEE80211_AMPDU_TX_OPERATIONAL:
1790 ista = (struct ath9k_htc_sta *) sta->drv_priv; 1743 ista = (struct ath9k_htc_sta *) sta->drv_priv;
1744 spin_lock_bh(&priv->tx_lock);
1791 ista->tid_state[tid] = AGGR_OPERATIONAL; 1745 ista->tid_state[tid] = AGGR_OPERATIONAL;
1746 spin_unlock_bh(&priv->tx_lock);
1792 break; 1747 break;
1793 default: 1748 default:
1794 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, 1749 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL,
1795 "Unknown AMPDU action\n"); 1750 "Unknown AMPDU action\n");
1796 } 1751 }
1797 1752
1798 return 0; 1753 return ret;
1799} 1754}
1800 1755
1801static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) 1756static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 89d38486650d..bd0b4acc3ece 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -187,6 +187,19 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
187 return htc_send(priv->htc, skb, epid, &tx_ctl); 187 return htc_send(priv->htc, skb, epid, &tx_ctl);
188} 188}
189 189
190static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
191 struct ath9k_htc_sta *ista, u8 tid)
192{
193 bool ret = false;
194
195 spin_lock_bh(&priv->tx_lock);
196 if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP))
197 ret = true;
198 spin_unlock_bh(&priv->tx_lock);
199
200 return ret;
201}
202
190void ath9k_tx_tasklet(unsigned long data) 203void ath9k_tx_tasklet(unsigned long data)
191{ 204{
192 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; 205 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
@@ -216,8 +229,7 @@ void ath9k_tx_tasklet(unsigned long data)
216 /* Check if we need to start aggregation */ 229 /* Check if we need to start aggregation */
217 230
218 if (sta && conf_is_ht(&priv->hw->conf) && 231 if (sta && conf_is_ht(&priv->hw->conf) &&
219 (priv->op_flags & OP_TXAGGR) 232 !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
220 && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
221 if (ieee80211_is_data_qos(fc)) { 233 if (ieee80211_is_data_qos(fc)) {
222 u8 *qc, tid; 234 u8 *qc, tid;
223 struct ath9k_htc_sta *ista; 235 struct ath9k_htc_sta *ista;
@@ -226,10 +238,11 @@ void ath9k_tx_tasklet(unsigned long data)
226 tid = qc[0] & 0xf; 238 tid = qc[0] & 0xf;
227 ista = (struct ath9k_htc_sta *)sta->drv_priv; 239 ista = (struct ath9k_htc_sta *)sta->drv_priv;
228 240
229 if ((tid < ATH9K_HTC_MAX_TID) && 241 if (ath9k_htc_check_tx_aggr(priv, ista, tid)) {
230 ista->tid_state[tid] == AGGR_STOP) {
231 ieee80211_start_tx_ba_session(sta, tid); 242 ieee80211_start_tx_ba_session(sta, tid);
243 spin_lock_bh(&priv->tx_lock);
232 ista->tid_state[tid] = AGGR_PROGRESS; 244 ista->tid_state[tid] = AGGR_PROGRESS;
245 spin_unlock_bh(&priv->tx_lock);
233 } 246 }
234 } 247 }
235 } 248 }