aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vasanth@atheros.com>2008-09-10 09:20:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-15 16:48:19 -0400
commit500c064d3a5f9c8aa604ef63a1346ab70eed443a (patch)
treed7345fa9f894bcbc21e80e886cc3f32589469bad
parent8feceb67929bd23bfca58d5f49df93d7fc315bb1 (diff)
ath9k: Add RF kill support
RF kill support is enabled when CONFIG_RFKILL is set. Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath9k/ath9k.h7
-rw-r--r--drivers/net/wireless/ath9k/core.h16
-rw-r--r--drivers/net/wireless/ath9k/hw.c70
-rw-r--r--drivers/net/wireless/ath9k/main.c266
4 files changed, 327 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index 28b8d84f49b4..0e897c276858 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -798,10 +798,11 @@ struct ath_hal {
798 struct ath9k_channel *ah_curchan; 798 struct ath9k_channel *ah_curchan;
799 u32 ah_nchan; 799 u32 ah_nchan;
800 800
801 u16 ah_rfsilent;
802 bool ah_rfkillEnabled;
803 bool ah_isPciExpress; 801 bool ah_isPciExpress;
804 u16 ah_txTrigLevel; 802 u16 ah_txTrigLevel;
803 u16 ah_rfsilent;
804 u32 ah_rfkill_gpio;
805 u32 ah_rfkill_polarity;
805 806
806#ifndef ATH_NF_PER_CHAN 807#ifndef ATH_NF_PER_CHAN
807 struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; 808 struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
@@ -1003,4 +1004,6 @@ bool ath9k_get_channel_edges(struct ath_hal *ah,
1003void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, 1004void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
1004 u32 ah_signal_type); 1005 u32 ah_signal_type);
1005void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value); 1006void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
1007u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
1008void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
1006#endif 1009#endif
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index 1faa1effa02c..b66de29cf662 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -40,6 +40,7 @@
40#include <asm/page.h> 40#include <asm/page.h>
41#include <net/mac80211.h> 41#include <net/mac80211.h>
42#include <linux/leds.h> 42#include <linux/leds.h>
43#include <linux/rfkill.h>
43 44
44#include "ath9k.h" 45#include "ath9k.h"
45#include "rc.h" 46#include "rc.h"
@@ -823,6 +824,15 @@ struct ath_led {
823 bool registered; 824 bool registered;
824}; 825};
825 826
827/* Rfkill */
828#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */
829
830struct ath_rfkill {
831 struct rfkill *rfkill;
832 struct delayed_work rfkill_poll;
833 char rfkill_name[32];
834};
835
826/********************/ 836/********************/
827/* Main driver core */ 837/* Main driver core */
828/********************/ 838/********************/
@@ -906,6 +916,9 @@ struct ath_ht_info {
906#define SC_OP_PROTECT_ENABLE BIT(8) 916#define SC_OP_PROTECT_ENABLE BIT(8)
907#define SC_OP_RXFLUSH BIT(9) 917#define SC_OP_RXFLUSH BIT(9)
908#define SC_OP_LED_ASSOCIATED BIT(10) 918#define SC_OP_LED_ASSOCIATED BIT(10)
919#define SC_OP_RFKILL_REGISTERED BIT(11)
920#define SC_OP_RFKILL_SW_BLOCKED BIT(12)
921#define SC_OP_RFKILL_HW_BLOCKED BIT(13)
909 922
910struct ath_softc { 923struct ath_softc {
911 struct ieee80211_hw *hw; 924 struct ieee80211_hw *hw;
@@ -1015,6 +1028,9 @@ struct ath_softc {
1015 struct ath_led assoc_led; 1028 struct ath_led assoc_led;
1016 struct ath_led tx_led; 1029 struct ath_led tx_led;
1017 struct ath_led rx_led; 1030 struct ath_led rx_led;
1031
1032 /* Rfkill */
1033 struct ath_rfkill rf_kill;
1018}; 1034};
1019 1035
1020int ath_init(u16 devid, struct ath_softc *sc); 1036int ath_init(u16 devid, struct ath_softc *sc);
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index 4ccbbc07cf1e..0251e59f2f84 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -2821,7 +2821,38 @@ void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
2821 AR_GPIO_BIT(gpio)); 2821 AR_GPIO_BIT(gpio));
2822} 2822}
2823 2823
2824static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) 2824/*
2825 * Configure GPIO Input lines
2826 */
2827void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio)
2828{
2829 u32 gpio_shift;
2830
2831 ASSERT(gpio < ah->ah_caps.num_gpio_pins);
2832
2833 gpio_shift = gpio << 1;
2834
2835 REG_RMW(ah,
2836 AR_GPIO_OE_OUT,
2837 (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
2838 (AR_GPIO_OE_OUT_DRV << gpio_shift));
2839}
2840
2841#ifdef CONFIG_RFKILL
2842static void ath9k_enable_rfkill(struct ath_hal *ah)
2843{
2844 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
2845 AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
2846
2847 REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
2848 AR_GPIO_INPUT_MUX2_RFSILENT);
2849
2850 ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio);
2851 REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
2852}
2853#endif
2854
2855u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
2825{ 2856{
2826 if (gpio >= ah->ah_caps.num_gpio_pins) 2857 if (gpio >= ah->ah_caps.num_gpio_pins)
2827 return 0xffffffff; 2858 return 0xffffffff;
@@ -3034,17 +3065,17 @@ static bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
3034 3065
3035 pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; 3066 pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
3036 3067
3068#ifdef CONFIG_RFKILL
3037 ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT); 3069 ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT);
3038 if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) { 3070 if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
3039 ahp->ah_gpioSelect = 3071 ah->ah_rfkill_gpio =
3040 MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL); 3072 MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
3041 ahp->ah_polarity = 3073 ah->ah_rfkill_polarity =
3042 MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY); 3074 MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
3043 3075
3044 ath9k_hw_setcapability(ah, ATH9K_CAP_RFSILENT, 1, true,
3045 NULL);
3046 pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; 3076 pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
3047 } 3077 }
3078#endif
3048 3079
3049 if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) || 3080 if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
3050 (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) || 3081 (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
@@ -5961,6 +5992,10 @@ bool ath9k_hw_reset(struct ath_hal *ah,
5961 ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode); 5992 ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode);
5962 ath9k_hw_init_qos(ah); 5993 ath9k_hw_init_qos(ah);
5963 5994
5995#ifdef CONFIG_RFKILL
5996 if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
5997 ath9k_enable_rfkill(ah);
5998#endif
5964 ath9k_hw_init_user_settings(ah); 5999 ath9k_hw_init_user_settings(ah);
5965 6000
5966 REG_WRITE(ah, AR_STA_ID1, 6001 REG_WRITE(ah, AR_STA_ID1,
@@ -6490,31 +6525,6 @@ ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask)
6490 return true; 6525 return true;
6491} 6526}
6492 6527
6493#ifdef CONFIG_ATH9K_RFKILL
6494static void ath9k_enable_rfkill(struct ath_hal *ah)
6495{
6496 struct ath_hal_5416 *ahp = AH5416(ah);
6497
6498 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
6499 AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
6500
6501 REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
6502 AR_GPIO_INPUT_MUX2_RFSILENT);
6503
6504 ath9k_hw_cfg_gpio_input(ah, ahp->ah_gpioSelect);
6505 REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
6506
6507 if (ahp->ah_gpioBit == ath9k_hw_gpio_get(ah, ahp->ah_gpioSelect)) {
6508
6509 ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect,
6510 !ahp->ah_gpioBit);
6511 } else {
6512 ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect,
6513 ahp->ah_gpioBit);
6514 }
6515}
6516#endif
6517
6518void 6528void
6519ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, 6529ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
6520 u16 assocId) 6530 u16 assocId)
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 07e5b5d877b6..b493dff5643e 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -672,6 +672,209 @@ fail:
672 ath_deinit_leds(sc); 672 ath_deinit_leds(sc);
673} 673}
674 674
675#ifdef CONFIG_RFKILL
676/*******************/
677/* Rfkill */
678/*******************/
679
680static void ath_radio_enable(struct ath_softc *sc)
681{
682 struct ath_hal *ah = sc->sc_ah;
683 int status;
684
685 spin_lock_bh(&sc->sc_resetlock);
686 if (!ath9k_hw_reset(ah, ah->ah_curchan,
687 sc->sc_ht_info.tx_chan_width,
688 sc->sc_tx_chainmask,
689 sc->sc_rx_chainmask,
690 sc->sc_ht_extprotspacing,
691 false, &status)) {
692 DPRINTF(sc, ATH_DBG_FATAL,
693 "%s: unable to reset channel %u (%uMhz) "
694 "flags 0x%x hal status %u\n", __func__,
695 ath9k_hw_mhz2ieee(ah,
696 ah->ah_curchan->channel,
697 ah->ah_curchan->channelFlags),
698 ah->ah_curchan->channel,
699 ah->ah_curchan->channelFlags, status);
700 }
701 spin_unlock_bh(&sc->sc_resetlock);
702
703 ath_update_txpow(sc);
704 if (ath_startrecv(sc) != 0) {
705 DPRINTF(sc, ATH_DBG_FATAL,
706 "%s: unable to restart recv logic\n", __func__);
707 return;
708 }
709
710 if (sc->sc_flags & SC_OP_BEACONS)
711 ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */
712
713 /* Re-Enable interrupts */
714 ath9k_hw_set_interrupts(ah, sc->sc_imask);
715
716 /* Enable LED */
717 ath9k_hw_cfg_output(ah, ATH_LED_PIN,
718 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
719 ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
720
721 ieee80211_wake_queues(sc->hw);
722}
723
724static void ath_radio_disable(struct ath_softc *sc)
725{
726 struct ath_hal *ah = sc->sc_ah;
727 int status;
728
729
730 ieee80211_stop_queues(sc->hw);
731
732 /* Disable LED */
733 ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1);
734 ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN);
735
736 /* Disable interrupts */
737 ath9k_hw_set_interrupts(ah, 0);
738
739 ath_draintxq(sc, false); /* clear pending tx frames */
740 ath_stoprecv(sc); /* turn off frame recv */
741 ath_flushrecv(sc); /* flush recv queue */
742
743 spin_lock_bh(&sc->sc_resetlock);
744 if (!ath9k_hw_reset(ah, ah->ah_curchan,
745 sc->sc_ht_info.tx_chan_width,
746 sc->sc_tx_chainmask,
747 sc->sc_rx_chainmask,
748 sc->sc_ht_extprotspacing,
749 false, &status)) {
750 DPRINTF(sc, ATH_DBG_FATAL,
751 "%s: unable to reset channel %u (%uMhz) "
752 "flags 0x%x hal status %u\n", __func__,
753 ath9k_hw_mhz2ieee(ah,
754 ah->ah_curchan->channel,
755 ah->ah_curchan->channelFlags),
756 ah->ah_curchan->channel,
757 ah->ah_curchan->channelFlags, status);
758 }
759 spin_unlock_bh(&sc->sc_resetlock);
760
761 ath9k_hw_phy_disable(ah);
762 ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
763}
764
765static bool ath_is_rfkill_set(struct ath_softc *sc)
766{
767 struct ath_hal *ah = sc->sc_ah;
768
769 return ath9k_hw_gpio_get(ah, ah->ah_rfkill_gpio) ==
770 ah->ah_rfkill_polarity;
771}
772
773/* h/w rfkill poll function */
774static void ath_rfkill_poll(struct work_struct *work)
775{
776 struct ath_softc *sc = container_of(work, struct ath_softc,
777 rf_kill.rfkill_poll.work);
778 bool radio_on;
779
780 if (sc->sc_flags & SC_OP_INVALID)
781 return;
782
783 radio_on = !ath_is_rfkill_set(sc);
784
785 /*
786 * enable/disable radio only when there is a
787 * state change in RF switch
788 */
789 if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) {
790 enum rfkill_state state;
791
792 if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) {
793 state = radio_on ? RFKILL_STATE_SOFT_BLOCKED
794 : RFKILL_STATE_HARD_BLOCKED;
795 } else if (radio_on) {
796 ath_radio_enable(sc);
797 state = RFKILL_STATE_UNBLOCKED;
798 } else {
799 ath_radio_disable(sc);
800 state = RFKILL_STATE_HARD_BLOCKED;
801 }
802
803 if (state == RFKILL_STATE_HARD_BLOCKED)
804 sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED;
805 else
806 sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED;
807
808 rfkill_force_state(sc->rf_kill.rfkill, state);
809 }
810
811 queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll,
812 msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL));
813}
814
815/* s/w rfkill handler */
816static int ath_sw_toggle_radio(void *data, enum rfkill_state state)
817{
818 struct ath_softc *sc = data;
819
820 switch (state) {
821 case RFKILL_STATE_SOFT_BLOCKED:
822 if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED |
823 SC_OP_RFKILL_SW_BLOCKED)))
824 ath_radio_disable(sc);
825 sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED;
826 return 0;
827 case RFKILL_STATE_UNBLOCKED:
828 if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) {
829 sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED;
830 if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) {
831 DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the"
832 "radio as it is disabled by h/w \n");
833 return -EPERM;
834 }
835 ath_radio_enable(sc);
836 }
837 return 0;
838 default:
839 return -EINVAL;
840 }
841}
842
843/* Init s/w rfkill */
844static int ath_init_sw_rfkill(struct ath_softc *sc)
845{
846 sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy),
847 RFKILL_TYPE_WLAN);
848 if (!sc->rf_kill.rfkill) {
849 DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n");
850 return -ENOMEM;
851 }
852
853 snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
854 "ath9k-%s:rfkill", wiphy_name(sc->hw->wiphy));
855 sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name;
856 sc->rf_kill.rfkill->data = sc;
857 sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
858 sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
859 sc->rf_kill.rfkill->user_claim_unsupported = 1;
860
861 return 0;
862}
863
864/* Deinitialize rfkill */
865static void ath_deinit_rfkill(struct ath_softc *sc)
866{
867 if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
868 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
869
870 if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) {
871 rfkill_unregister(sc->rf_kill.rfkill);
872 sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED;
873 sc->rf_kill.rfkill = NULL;
874 }
875}
876#endif /* CONFIG_RFKILL */
877
675static int ath_detach(struct ath_softc *sc) 878static int ath_detach(struct ath_softc *sc)
676{ 879{
677 struct ieee80211_hw *hw = sc->hw; 880 struct ieee80211_hw *hw = sc->hw;
@@ -681,6 +884,11 @@ static int ath_detach(struct ath_softc *sc)
681 /* Deinit LED control */ 884 /* Deinit LED control */
682 ath_deinit_leds(sc); 885 ath_deinit_leds(sc);
683 886
887#ifdef CONFIG_RFKILL
888 /* deinit rfkill */
889 ath_deinit_rfkill(sc);
890#endif
891
684 /* Unregister hw */ 892 /* Unregister hw */
685 893
686 ieee80211_unregister_hw(hw); 894 ieee80211_unregister_hw(hw);
@@ -777,6 +985,16 @@ static int ath_attach(u16 devid,
777 /* Initialize LED control */ 985 /* Initialize LED control */
778 ath_init_leds(sc); 986 ath_init_leds(sc);
779 987
988#ifdef CONFIG_RFKILL
989 /* Initialze h/w Rfkill */
990 if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
991 INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
992
993 /* Initialize s/w rfkill */
994 if (ath_init_sw_rfkill(sc))
995 goto detach;
996#endif
997
780 /* initialize tx/rx engine */ 998 /* initialize tx/rx engine */
781 999
782 error = ath_tx_init(sc, ATH_TXBUF); 1000 error = ath_tx_init(sc, ATH_TXBUF);
@@ -822,6 +1040,33 @@ static int ath9k_start(struct ieee80211_hw *hw)
822 return error; 1040 return error;
823 } 1041 }
824 1042
1043#ifdef CONFIG_RFKILL
1044 /* Start rfkill polling */
1045 if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1046 queue_delayed_work(sc->hw->workqueue,
1047 &sc->rf_kill.rfkill_poll, 0);
1048
1049 if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
1050 if (rfkill_register(sc->rf_kill.rfkill)) {
1051 DPRINTF(sc, ATH_DBG_FATAL,
1052 "Unable to register rfkill\n");
1053 rfkill_free(sc->rf_kill.rfkill);
1054
1055 /* Deinitialize the device */
1056 if (sc->pdev->irq)
1057 free_irq(sc->pdev->irq, sc);
1058 ath_detach(sc);
1059 pci_iounmap(sc->pdev, sc->mem);
1060 pci_release_region(sc->pdev, 0);
1061 pci_disable_device(sc->pdev);
1062 ieee80211_free_hw(hw);
1063 return -EIO;
1064 } else {
1065 sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
1066 }
1067 }
1068#endif
1069
825 ieee80211_wake_queues(hw); 1070 ieee80211_wake_queues(hw);
826 return 0; 1071 return 0;
827} 1072}
@@ -883,6 +1128,11 @@ static void ath9k_stop(struct ieee80211_hw *hw)
883 "%s: Device is no longer present\n", __func__); 1128 "%s: Device is no longer present\n", __func__);
884 1129
885 ieee80211_stop_queues(hw); 1130 ieee80211_stop_queues(hw);
1131
1132#ifdef CONFIG_RFKILL
1133 if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1134 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
1135#endif
886} 1136}
887 1137
888static int ath9k_add_interface(struct ieee80211_hw *hw, 1138static int ath9k_add_interface(struct ieee80211_hw *hw,
@@ -1554,6 +1804,12 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
1554 struct ath_softc *sc = hw->priv; 1804 struct ath_softc *sc = hw->priv;
1555 1805
1556 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); 1806 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
1807
1808#ifdef CONFIG_RFKILL
1809 if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1810 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
1811#endif
1812
1557 pci_save_state(pdev); 1813 pci_save_state(pdev);
1558 pci_disable_device(pdev); 1814 pci_disable_device(pdev);
1559 pci_set_power_state(pdev, 3); 1815 pci_set_power_state(pdev, 3);
@@ -1586,6 +1842,16 @@ static int ath_pci_resume(struct pci_dev *pdev)
1586 AR_GPIO_OUTPUT_MUX_AS_OUTPUT); 1842 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
1587 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); 1843 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
1588 1844
1845#ifdef CONFIG_RFKILL
1846 /*
1847 * check the h/w rfkill state on resume
1848 * and start the rfkill poll timer
1849 */
1850 if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1851 queue_delayed_work(sc->hw->workqueue,
1852 &sc->rf_kill.rfkill_poll, 0);
1853#endif
1854
1589 return 0; 1855 return 0;
1590} 1856}
1591 1857