diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2010-06-15 00:54:37 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-06-15 16:02:22 -0400 |
commit | d7ca21393d39cb2e73dfc4c516e7be37ba01789e (patch) | |
tree | 35c2afd019f0274a2b812f091742c1d53823f155 /drivers/net | |
parent | 9a2af8892a74573cec4bea2149843a93442a12de (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.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_init.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 93 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 21 |
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 | ||
226 | struct 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 | ||
340 | struct ath9k_htc_priv { | 330 | struct 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 | ||
441 | static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, | 441 | int 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 | ||
493 | void 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 | ||
1801 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | 1756 | static 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 | ||
190 | static 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 | |||
190 | void ath9k_tx_tasklet(unsigned long data) | 203 | void 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 | } |