aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-11-08 14:54:47 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-09 16:13:24 -0500
commit4df3071ebd92ef7115b409da64d0eb405d24a631 (patch)
tree825eaecb9d9e8d0fde7f61e5f98fdd823ccef718 /drivers/net
parent790a11f268373b60069bc1371dc05143107c607c (diff)
ath9k_hw: optimize interrupt mask changes
OProfile showed that ath9k was spending way too much time in ath9k_hw_set_interrupts. Since most of the interrupt mask changes only need to globally enable/disable interrupts, it makes sense to split this part into separate functions, replacing all calls to ath9k_hw_set_interrupts(ah, 0) with ath9k_hw_disable_interrupts(ah). ath9k_hw_set_interrupts(ah, ah->imask) only gets changed to ath9k_hw_enable_interrupts(ah), whenever ah->imask was not changed since the point where interrupts were disabled. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c86
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c18
5 files changed, 68 insertions, 52 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 19891e7d49a..333da7bf2d7 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -503,7 +503,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
503 503
504 /* Set the computed AP beacon timers */ 504 /* Set the computed AP beacon timers */
505 505
506 ath9k_hw_set_interrupts(ah, 0); 506 ath9k_hw_disable_interrupts(ah);
507 ath9k_beacon_init(sc, nexttbtt, intval); 507 ath9k_beacon_init(sc, nexttbtt, intval);
508 sc->beacon.bmisscnt = 0; 508 sc->beacon.bmisscnt = 0;
509 ath9k_hw_set_interrupts(ah, ah->imask); 509 ath9k_hw_set_interrupts(ah, ah->imask);
@@ -638,7 +638,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
638 638
639 /* Set the computed STA beacon timers */ 639 /* Set the computed STA beacon timers */
640 640
641 ath9k_hw_set_interrupts(ah, 0); 641 ath9k_hw_disable_interrupts(ah);
642 ath9k_hw_set_sta_beacon_timers(ah, &bs); 642 ath9k_hw_set_sta_beacon_timers(ah, &bs);
643 ah->imask |= ATH9K_INT_BMISS; 643 ah->imask |= ATH9K_INT_BMISS;
644 ath9k_hw_set_interrupts(ah, ah->imask); 644 ath9k_hw_set_interrupts(ah, ah->imask);
@@ -686,7 +686,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
686 686
687 /* Set the computed ADHOC beacon timers */ 687 /* Set the computed ADHOC beacon timers */
688 688
689 ath9k_hw_set_interrupts(ah, 0); 689 ath9k_hw_disable_interrupts(ah);
690 ath9k_beacon_init(sc, nexttbtt, intval); 690 ath9k_beacon_init(sc, nexttbtt, intval);
691 sc->beacon.bmisscnt = 0; 691 sc->beacon.bmisscnt = 0;
692 ath9k_hw_set_interrupts(ah, ah->imask); 692 ath9k_hw_set_interrupts(ah, ah->imask);
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 4a9a68bba32..db9c6fed799 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -259,7 +259,7 @@ static void ath9k_gen_timer_start(struct ath_hw *ah,
259 ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); 259 ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
260 260
261 if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { 261 if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
262 ath9k_hw_set_interrupts(ah, 0); 262 ath9k_hw_disable_interrupts(ah);
263 ah->imask |= ATH9K_INT_GENTIMER; 263 ah->imask |= ATH9K_INT_GENTIMER;
264 ath9k_hw_set_interrupts(ah, ah->imask); 264 ath9k_hw_set_interrupts(ah, ah->imask);
265 } 265 }
@@ -273,7 +273,7 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
273 273
274 /* if no timer is enabled, turn off interrupt mask */ 274 /* if no timer is enabled, turn off interrupt mask */
275 if (timer_table->timer_mask.val == 0) { 275 if (timer_table->timer_mask.val == 0) {
276 ath9k_hw_set_interrupts(ah, 0); 276 ath9k_hw_disable_interrupts(ah);
277 ah->imask &= ~ATH9K_INT_GENTIMER; 277 ah->imask &= ~ATH9K_INT_GENTIMER;
278 ath9k_hw_set_interrupts(ah, ah->imask); 278 ath9k_hw_set_interrupts(ah, ah->imask);
279 } 279 }
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 8c13479b17c..65b1ee2a979 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -117,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending);
117bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) 117bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
118{ 118{
119 u32 txcfg, curLevel, newLevel; 119 u32 txcfg, curLevel, newLevel;
120 enum ath9k_int omask;
121 120
122 if (ah->tx_trig_level >= ah->config.max_txtrig_level) 121 if (ah->tx_trig_level >= ah->config.max_txtrig_level)
123 return false; 122 return false;
124 123
125 omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); 124 ath9k_hw_disable_interrupts(ah);
126 125
127 txcfg = REG_READ(ah, AR_TXCFG); 126 txcfg = REG_READ(ah, AR_TXCFG);
128 curLevel = MS(txcfg, AR_FTRIG); 127 curLevel = MS(txcfg, AR_FTRIG);
@@ -136,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
136 REG_WRITE(ah, AR_TXCFG, 135 REG_WRITE(ah, AR_TXCFG,
137 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); 136 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
138 137
139 ath9k_hw_set_interrupts(ah, omask); 138 ath9k_hw_enable_interrupts(ah);
140 139
141 ah->tx_trig_level = newLevel; 140 ah->tx_trig_level = newLevel;
142 141
@@ -849,28 +848,59 @@ bool ath9k_hw_intrpend(struct ath_hw *ah)
849} 848}
850EXPORT_SYMBOL(ath9k_hw_intrpend); 849EXPORT_SYMBOL(ath9k_hw_intrpend);
851 850
852enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, 851void ath9k_hw_disable_interrupts(struct ath_hw *ah)
853 enum ath9k_int ints) 852{
853 struct ath_common *common = ath9k_hw_common(ah);
854
855 ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
856 REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
857 (void) REG_READ(ah, AR_IER);
858 if (!AR_SREV_9100(ah)) {
859 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
860 (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
861
862 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
863 (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
864 }
865}
866EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
867
868void ath9k_hw_enable_interrupts(struct ath_hw *ah)
869{
870 struct ath_common *common = ath9k_hw_common(ah);
871
872 if (!(ah->imask & ATH9K_INT_GLOBAL))
873 return;
874
875 ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
876 REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
877 if (!AR_SREV_9100(ah)) {
878 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
879 AR_INTR_MAC_IRQ);
880 REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
881
882
883 REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
884 AR_INTR_SYNC_DEFAULT);
885 REG_WRITE(ah, AR_INTR_SYNC_MASK,
886 AR_INTR_SYNC_DEFAULT);
887 }
888 ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
889 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
890}
891EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
892
893void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
854{ 894{
855 enum ath9k_int omask = ah->imask; 895 enum ath9k_int omask = ah->imask;
856 u32 mask, mask2; 896 u32 mask, mask2;
857 struct ath9k_hw_capabilities *pCap = &ah->caps; 897 struct ath9k_hw_capabilities *pCap = &ah->caps;
858 struct ath_common *common = ath9k_hw_common(ah); 898 struct ath_common *common = ath9k_hw_common(ah);
859 899
860 ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); 900 if (!(ints & ATH9K_INT_GLOBAL))
861 901 ath9k_hw_enable_interrupts(ah);
862 if (omask & ATH9K_INT_GLOBAL) {
863 ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
864 REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
865 (void) REG_READ(ah, AR_IER);
866 if (!AR_SREV_9100(ah)) {
867 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
868 (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
869 902
870 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); 903 ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
871 (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
872 }
873 }
874 904
875 /* TODO: global int Ref count */ 905 /* TODO: global int Ref count */
876 mask = ints & ATH9K_INT_COMMON; 906 mask = ints & ATH9K_INT_COMMON;
@@ -946,24 +976,8 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
946 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); 976 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
947 } 977 }
948 978
949 if (ints & ATH9K_INT_GLOBAL) { 979 ath9k_hw_enable_interrupts(ah);
950 ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
951 REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
952 if (!AR_SREV_9100(ah)) {
953 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
954 AR_INTR_MAC_IRQ);
955 REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
956
957
958 REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
959 AR_INTR_SYNC_DEFAULT);
960 REG_WRITE(ah, AR_INTR_SYNC_MASK,
961 AR_INTR_SYNC_DEFAULT);
962 }
963 ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
964 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
965 }
966 980
967 return omask; 981 return;
968} 982}
969EXPORT_SYMBOL(ath9k_hw_set_interrupts); 983EXPORT_SYMBOL(ath9k_hw_set_interrupts);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 7c1a34d64f6..538c676e799 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -669,6 +669,7 @@ enum ath9k_key_type {
669 669
670struct ath_hw; 670struct ath_hw;
671struct ath9k_channel; 671struct ath9k_channel;
672enum ath9k_int;
672 673
673u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); 674u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
674void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); 675void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
@@ -700,8 +701,9 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah);
700 701
701/* Interrupt Handling */ 702/* Interrupt Handling */
702bool ath9k_hw_intrpend(struct ath_hw *ah); 703bool ath9k_hw_intrpend(struct ath_hw *ah);
703enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, 704void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
704 enum ath9k_int ints); 705void ath9k_hw_enable_interrupts(struct ath_hw *ah);
706void ath9k_hw_disable_interrupts(struct ath_hw *ah);
705 707
706void ar9002_hw_attach_mac_ops(struct ath_hw *ah); 708void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
707 709
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index b52f1cf8a60..ade9d7c1603 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -239,7 +239,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
239 * hardware at the new frequency, and then re-enable 239 * hardware at the new frequency, and then re-enable
240 * the relevant bits of the h/w. 240 * the relevant bits of the h/w.
241 */ 241 */
242 ath9k_hw_set_interrupts(ah, 0); 242 ath9k_hw_disable_interrupts(ah);
243 ath_drain_all_txq(sc, false); 243 ath_drain_all_txq(sc, false);
244 244
245 spin_lock_bh(&sc->rx.pcu_lock); 245 spin_lock_bh(&sc->rx.pcu_lock);
@@ -653,7 +653,7 @@ void ath9k_tasklet(unsigned long data)
653 ath_gen_timer_isr(sc->sc_ah); 653 ath_gen_timer_isr(sc->sc_ah);
654 654
655 /* re-enable hardware interrupt */ 655 /* re-enable hardware interrupt */
656 ath9k_hw_set_interrupts(ah, ah->imask); 656 ath9k_hw_enable_interrupts(ah);
657 ath9k_ps_restore(sc); 657 ath9k_ps_restore(sc);
658} 658}
659 659
@@ -752,7 +752,7 @@ irqreturn_t ath_isr(int irq, void *dev)
752 * interrupt; otherwise it will continue to 752 * interrupt; otherwise it will continue to
753 * fire. 753 * fire.
754 */ 754 */
755 ath9k_hw_set_interrupts(ah, 0); 755 ath9k_hw_disable_interrupts(ah);
756 /* 756 /*
757 * Let the hal handle the event. We assume 757 * Let the hal handle the event. We assume
758 * it will clear whatever condition caused 758 * it will clear whatever condition caused
@@ -761,7 +761,7 @@ irqreturn_t ath_isr(int irq, void *dev)
761 spin_lock(&common->cc_lock); 761 spin_lock(&common->cc_lock);
762 ath9k_hw_proc_mib_event(ah); 762 ath9k_hw_proc_mib_event(ah);
763 spin_unlock(&common->cc_lock); 763 spin_unlock(&common->cc_lock);
764 ath9k_hw_set_interrupts(ah, ah->imask); 764 ath9k_hw_enable_interrupts(ah);
765 } 765 }
766 766
767 if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) 767 if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
@@ -778,8 +778,8 @@ chip_reset:
778 ath_debug_stat_interrupt(sc, status); 778 ath_debug_stat_interrupt(sc, status);
779 779
780 if (sched) { 780 if (sched) {
781 /* turn off every interrupt except SWBA */ 781 /* turn off every interrupt */
782 ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA)); 782 ath9k_hw_disable_interrupts(ah);
783 tasklet_schedule(&sc->intr_tq); 783 tasklet_schedule(&sc->intr_tq);
784 } 784 }
785 785
@@ -937,7 +937,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
937 } 937 }
938 938
939 /* Disable interrupts */ 939 /* Disable interrupts */
940 ath9k_hw_set_interrupts(ah, 0); 940 ath9k_hw_disable_interrupts(ah);
941 941
942 ath_drain_all_txq(sc, false); /* clear pending tx frames */ 942 ath_drain_all_txq(sc, false); /* clear pending tx frames */
943 943
@@ -980,7 +980,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
980 980
981 ieee80211_stop_queues(hw); 981 ieee80211_stop_queues(hw);
982 982
983 ath9k_hw_set_interrupts(ah, 0); 983 ath9k_hw_disable_interrupts(ah);
984 ath_drain_all_txq(sc, retry_tx); 984 ath_drain_all_txq(sc, retry_tx);
985 985
986 spin_lock_bh(&sc->rx.pcu_lock); 986 spin_lock_bh(&sc->rx.pcu_lock);
@@ -1394,7 +1394,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
1394 1394
1395 /* make sure h/w will not generate any interrupt 1395 /* make sure h/w will not generate any interrupt
1396 * before setting the invalid flag. */ 1396 * before setting the invalid flag. */
1397 ath9k_hw_set_interrupts(ah, 0); 1397 ath9k_hw_disable_interrupts(ah);
1398 1398
1399 spin_lock_bh(&sc->rx.pcu_lock); 1399 spin_lock_bh(&sc->rx.pcu_lock);
1400 if (!(sc->sc_flags & SC_OP_INVALID)) { 1400 if (!(sc->sc_flags & SC_OP_INVALID)) {