From cbfe89c67b58e2bd1b47f6986b3b793f06f3d9b0 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 24 Jun 2009 18:58:47 +0530 Subject: ath9k: Fix leak in tx descriptor When we reclaim the tx desc, we always assume that the last desc is a holding desc, which is not true, and skip it. If the tx queue is drained during channel change, internal reset and etc, the last descriptor may not be the holding descriptor and we fail to reclaim them. This results in the following two issues. 1. Tx stuck - We drop all the frames coming from upper layer due to shortage in tx desc. 2. Crash - If we fail to reclaim a tx descriptor, we miss to update the tx BA window with the seq number of the frame associated to that desc, which, at some point, result in the following crash due to an assert failure in ath_tx_addto_baw(). This patch fixes these two issues. kernel BUG at ../drivers/net/wireless/ath/ath9k/xmit.c:180! [155064.304164] invalid opcode: 0000 [#1] SMP Call Trace: [] ? ath9k_tx+0xeb/0x160 [ath9k] [] ipv6? __ieee80211_tx+0x41/0x120 [mac80211] [] ? aes_i586ieee80211_master_start_xmit+0x28e/0x560 [mac80211] [] aes_generic? _spin_lock_irqsave+0x31/0x40 [] ? dev_hard_start_xmit+0x16b/0x1c0 [] ? __qdisc_run+0x1b5/0x200 [] ? af_packetieee80211_select_queue+0xa/0x100 [mac80211] [] ? i915dev_queue_xmit+0x2e7/0x3f0 [] ? ieee80211_subif_start_xmit+0x369/0x7a0 [mac80211] [] ? ip_output+0x55/0xb0 [] ? show_memcpy_count+0x18/0x60 [] ? __kfree_skb+0x36/0x90 [] ? binfmt_miscdev_queue_xmit_nit+0xd2/0x110 [] ? dev_hard_start_xmit+0x16b/0x1c0 [] ? __qdisc_run+0x1b5/0x200 [] ? scoarp_create+0x57/0x2a0 [] ? bridgedev_queue_xmit+0x2e7/0x3f0 [] ? eth_header+0x0/0xc0 [] stp? arp_xmit+0x5f/0x70 [] ? arp_send+0x5f/0x70 [] bnep? arp_solicit+0x105/0x210 [] ? neigh_timer_handler+0x19a/0x390 [] ? run_timer_softirq+0x138/0x210 [] ? ppdevneigh_timer_handler+0x0/0x390 [] ? neigh_timer_handler+0x0/0x390 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b61a071788a..4ccf48e396d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -355,7 +355,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } if (bf_next == NULL) { - INIT_LIST_HEAD(&bf_head); + /* + * Make sure the last desc is reclaimed if it + * not a holding desc. + */ + if (!bf_last->bf_stale) + list_move_tail(&bf->list, &bf_head); + else + INIT_LIST_HEAD(&bf_head); } else { ASSERT(!list_empty(bf_q)); list_move_tail(&bf->list, &bf_head); -- cgit v1.2.3 From c66284f2a421f6aebbafd56cb8b90b8e6a9cb2de Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Jul 2009 10:17:35 -0700 Subject: ath9k: Tune ANI function processing on AP mode during ANI reset For AP mode we must tune ANI specially for 2 GHz and for 5 GHz. We mask in only the flags we want to toggle on ath9k_hw_ani_control() through the ah->ani_function bitmask, this will take care of ignoring changes during ANI reset which we were disabling before. Testedy-by: Steven Luo Cc: Bennyam Malavazi Cc: Jouni Malinen Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 1aeafb511dd..aad259b4c19 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -478,6 +478,18 @@ void ath9k_ani_reset(struct ath_hw *ah) "Reset ANI state opmode %u\n", ah->opmode); ah->stats.ast_ani_reset++; + if (ah->opmode == NL80211_IFTYPE_AP) { + /* + * ath9k_hw_ani_control() will only process items set on + * ah->ani_function + */ + if (IS_CHAN_2GHZ(chan)) + ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | + ATH9K_ANI_FIRSTEP_LEVEL); + else + ah->ani_function = 0; + } + ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0); ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); -- cgit v1.2.3 From 008749fc9917b799c469478141ddd1a4c81d06ca Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 25 Jul 2009 23:21:22 +0200 Subject: ath9k: Read outside array bounds Incorrect limits leads to reads outside array bounds. Signed-off-by: Roel Kluin Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index a2fda702b62..ce0e86c36a8 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -460,7 +460,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) integer = swab32(eep->modalHeader.antCtrlCommon); eep->modalHeader.antCtrlCommon = integer; - for (i = 0; i < AR5416_MAX_CHAINS; i++) { + for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { integer = swab32(eep->modalHeader.antCtrlChain[i]); eep->modalHeader.antCtrlChain[i] = integer; } @@ -914,7 +914,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ctlMode, numCtlModes, isHt40CtlMode, (pCtlMode[ctlMode] & EXT_ADDITIVE)); - for (i = 0; (i < AR5416_NUM_CTLS) && + for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " -- cgit v1.2.3