diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2008-10-29 00:47:13 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-10 15:16:06 -0500 |
commit | 9c84b7978f1b99048bf31be5a0218cd509e74148 (patch) | |
tree | 91f60b0986c75c6536c467a475568e33ff757245 /drivers/net/wireless/ath9k/main.c | |
parent | 50fdae2c7bcb6417997f90c3d9853a59a9ed06ce (diff) |
ath9k: Streamline attach/detach
Simplify attach and detach routines by consolidating
the stop and suspend functions.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 185 |
1 files changed, 79 insertions, 106 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 0194e44034e0..0d6000205548 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -616,6 +616,7 @@ fail: | |||
616 | } | 616 | } |
617 | 617 | ||
618 | #ifdef CONFIG_RFKILL | 618 | #ifdef CONFIG_RFKILL |
619 | |||
619 | /*******************/ | 620 | /*******************/ |
620 | /* Rfkill */ | 621 | /* Rfkill */ |
621 | /*******************/ | 622 | /*******************/ |
@@ -816,43 +817,72 @@ static void ath_deinit_rfkill(struct ath_softc *sc) | |||
816 | sc->rf_kill.rfkill = NULL; | 817 | sc->rf_kill.rfkill = NULL; |
817 | } | 818 | } |
818 | } | 819 | } |
820 | |||
821 | static int ath_start_rfkill_poll(struct ath_softc *sc) | ||
822 | { | ||
823 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
824 | queue_delayed_work(sc->hw->workqueue, | ||
825 | &sc->rf_kill.rfkill_poll, 0); | ||
826 | |||
827 | if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { | ||
828 | if (rfkill_register(sc->rf_kill.rfkill)) { | ||
829 | DPRINTF(sc, ATH_DBG_FATAL, | ||
830 | "Unable to register rfkill\n"); | ||
831 | rfkill_free(sc->rf_kill.rfkill); | ||
832 | |||
833 | /* Deinitialize the device */ | ||
834 | if (sc->pdev->irq) | ||
835 | free_irq(sc->pdev->irq, sc); | ||
836 | ath_detach(sc); | ||
837 | pci_iounmap(sc->pdev, sc->mem); | ||
838 | pci_release_region(sc->pdev, 0); | ||
839 | pci_disable_device(sc->pdev); | ||
840 | ieee80211_free_hw(hw); | ||
841 | return -EIO; | ||
842 | } else { | ||
843 | sc->sc_flags |= SC_OP_RFKILL_REGISTERED; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | return 0; | ||
848 | } | ||
819 | #endif /* CONFIG_RFKILL */ | 849 | #endif /* CONFIG_RFKILL */ |
820 | 850 | ||
821 | static int ath_detach(struct ath_softc *sc) | 851 | static void ath_detach(struct ath_softc *sc) |
822 | { | 852 | { |
823 | struct ieee80211_hw *hw = sc->hw; | 853 | struct ieee80211_hw *hw = sc->hw; |
854 | int i = 0; | ||
824 | 855 | ||
825 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); | 856 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); |
826 | 857 | ||
827 | /* Deinit LED control */ | 858 | ieee80211_unregister_hw(hw); |
859 | |||
828 | ath_deinit_leds(sc); | 860 | ath_deinit_leds(sc); |
829 | 861 | ||
830 | #ifdef CONFIG_RFKILL | 862 | #ifdef CONFIG_RFKILL |
831 | /* deinit rfkill */ | ||
832 | ath_deinit_rfkill(sc); | 863 | ath_deinit_rfkill(sc); |
833 | #endif | 864 | #endif |
834 | |||
835 | /* Unregister hw */ | ||
836 | |||
837 | ieee80211_unregister_hw(hw); | ||
838 | |||
839 | /* unregister Rate control */ | ||
840 | ath_rate_control_unregister(); | 865 | ath_rate_control_unregister(); |
841 | 866 | ath_rate_detach(sc->sc_rc); | |
842 | /* tx/rx cleanup */ | ||
843 | 867 | ||
844 | ath_rx_cleanup(sc); | 868 | ath_rx_cleanup(sc); |
845 | ath_tx_cleanup(sc); | 869 | ath_tx_cleanup(sc); |
846 | 870 | ||
847 | /* Deinit */ | 871 | tasklet_kill(&sc->intr_tq); |
872 | tasklet_kill(&sc->bcon_tasklet); | ||
848 | 873 | ||
849 | ath_deinit(sc); | 874 | if (!(sc->sc_flags & SC_OP_INVALID)) |
875 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | ||
850 | 876 | ||
851 | return 0; | 877 | /* cleanup tx queues */ |
878 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
879 | if (ATH_TXQ_SETUP(sc, i)) | ||
880 | ath_tx_cleanupq(sc, &sc->sc_txq[i]); | ||
881 | |||
882 | ath9k_hw_detach(sc->sc_ah); | ||
852 | } | 883 | } |
853 | 884 | ||
854 | static int ath_attach(u16 devid, | 885 | static int ath_attach(u16 devid, struct ath_softc *sc) |
855 | struct ath_softc *sc) | ||
856 | { | 886 | { |
857 | struct ieee80211_hw *hw = sc->hw; | 887 | struct ieee80211_hw *hw = sc->hw; |
858 | int error = 0; | 888 | int error = 0; |
@@ -867,36 +897,15 @@ static int ath_attach(u16 devid, | |||
867 | 897 | ||
868 | SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); | 898 | SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); |
869 | 899 | ||
870 | /* setup channels and rates */ | 900 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
871 | 901 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | |
872 | sc->sbands[IEEE80211_BAND_2GHZ].channels = | 902 | IEEE80211_HW_SIGNAL_DBM | |
873 | sc->channels[IEEE80211_BAND_2GHZ]; | 903 | IEEE80211_HW_AMPDU_AGGREGATION; |
874 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = | ||
875 | sc->rates[IEEE80211_BAND_2GHZ]; | ||
876 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
877 | |||
878 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) | ||
879 | /* Setup HT capabilities for 2.4Ghz*/ | ||
880 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | ||
881 | |||
882 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
883 | &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
884 | |||
885 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { | ||
886 | sc->sbands[IEEE80211_BAND_5GHZ].channels = | ||
887 | sc->channels[IEEE80211_BAND_5GHZ]; | ||
888 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = | ||
889 | sc->rates[IEEE80211_BAND_5GHZ]; | ||
890 | sc->sbands[IEEE80211_BAND_5GHZ].band = | ||
891 | IEEE80211_BAND_5GHZ; | ||
892 | |||
893 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) | ||
894 | /* Setup HT capabilities for 5Ghz*/ | ||
895 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); | ||
896 | 904 | ||
897 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 905 | hw->wiphy->interface_modes = |
898 | &sc->sbands[IEEE80211_BAND_5GHZ]; | 906 | BIT(NL80211_IFTYPE_AP) | |
899 | } | 907 | BIT(NL80211_IFTYPE_STATION) | |
908 | BIT(NL80211_IFTYPE_ADHOC); | ||
900 | 909 | ||
901 | hw->queues = 4; | 910 | hw->queues = 4; |
902 | hw->sta_data_size = sizeof(struct ath_node); | 911 | hw->sta_data_size = sizeof(struct ath_node); |
@@ -913,6 +922,17 @@ static int ath_attach(u16 devid, | |||
913 | goto bad; | 922 | goto bad; |
914 | } | 923 | } |
915 | 924 | ||
925 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
926 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | ||
927 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) | ||
928 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); | ||
929 | } | ||
930 | |||
931 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
932 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) | ||
933 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
934 | &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
935 | |||
916 | error = ieee80211_register_hw(hw); | 936 | error = ieee80211_register_hw(hw); |
917 | if (error != 0) { | 937 | if (error != 0) { |
918 | ath_rate_control_unregister(); | 938 | ath_rate_control_unregister(); |
@@ -963,49 +983,26 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
963 | pos = ath_get_channel(sc, curchan); | 983 | pos = ath_get_channel(sc, curchan); |
964 | if (pos == -1) { | 984 | if (pos == -1) { |
965 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); | 985 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); |
966 | return -EINVAL; | 986 | error = -EINVAL; |
987 | goto exit; | ||
967 | } | 988 | } |
968 | 989 | ||
969 | sc->sc_ah->ah_channels[pos].chanmode = | 990 | sc->sc_ah->ah_channels[pos].chanmode = |
970 | (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; | 991 | (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; |
971 | 992 | ||
972 | /* open ath_dev */ | ||
973 | error = ath_open(sc, &sc->sc_ah->ah_channels[pos]); | 993 | error = ath_open(sc, &sc->sc_ah->ah_channels[pos]); |
974 | if (error) { | 994 | if (error) { |
975 | DPRINTF(sc, ATH_DBG_FATAL, | 995 | DPRINTF(sc, ATH_DBG_FATAL, |
976 | "%s: Unable to complete ath_open\n", __func__); | 996 | "%s: Unable to complete ath_open\n", __func__); |
977 | return error; | 997 | goto exit; |
978 | } | 998 | } |
979 | 999 | ||
980 | #ifdef CONFIG_RFKILL | 1000 | #ifdef CONFIG_RFKILL |
981 | /* Start rfkill polling */ | 1001 | error = ath_start_rfkill_poll(sc); |
982 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
983 | queue_delayed_work(sc->hw->workqueue, | ||
984 | &sc->rf_kill.rfkill_poll, 0); | ||
985 | |||
986 | if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { | ||
987 | if (rfkill_register(sc->rf_kill.rfkill)) { | ||
988 | DPRINTF(sc, ATH_DBG_FATAL, | ||
989 | "Unable to register rfkill\n"); | ||
990 | rfkill_free(sc->rf_kill.rfkill); | ||
991 | |||
992 | /* Deinitialize the device */ | ||
993 | if (sc->pdev->irq) | ||
994 | free_irq(sc->pdev->irq, sc); | ||
995 | ath_detach(sc); | ||
996 | pci_iounmap(sc->pdev, sc->mem); | ||
997 | pci_release_region(sc->pdev, 0); | ||
998 | pci_disable_device(sc->pdev); | ||
999 | ieee80211_free_hw(hw); | ||
1000 | return -EIO; | ||
1001 | } else { | ||
1002 | sc->sc_flags |= SC_OP_RFKILL_REGISTERED; | ||
1003 | } | ||
1004 | } | ||
1005 | #endif | 1002 | #endif |
1006 | 1003 | ||
1007 | ieee80211_wake_queues(hw); | 1004 | exit: |
1008 | return 0; | 1005 | return error; |
1009 | } | 1006 | } |
1010 | 1007 | ||
1011 | static int ath9k_tx(struct ieee80211_hw *hw, | 1008 | static int ath9k_tx(struct ieee80211_hw *hw, |
@@ -1065,21 +1062,15 @@ exit: | |||
1065 | static void ath9k_stop(struct ieee80211_hw *hw) | 1062 | static void ath9k_stop(struct ieee80211_hw *hw) |
1066 | { | 1063 | { |
1067 | struct ath_softc *sc = hw->priv; | 1064 | struct ath_softc *sc = hw->priv; |
1068 | int error; | ||
1069 | 1065 | ||
1070 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); | 1066 | if (sc->sc_flags & SC_OP_INVALID) { |
1071 | 1067 | DPRINTF(sc, ATH_DBG_ANY, "%s: Device not present\n", __func__); | |
1072 | error = ath_suspend(sc); | 1068 | return; |
1073 | if (error) | 1069 | } |
1074 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
1075 | "%s: Device is no longer present\n", __func__); | ||
1076 | 1070 | ||
1077 | ieee80211_stop_queues(hw); | 1071 | ath_stop(sc); |
1078 | 1072 | ||
1079 | #ifdef CONFIG_RFKILL | 1073 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); |
1080 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
1081 | cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); | ||
1082 | #endif | ||
1083 | } | 1074 | } |
1084 | 1075 | ||
1085 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 1076 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
@@ -1643,17 +1634,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1643 | goto bad2; | 1634 | goto bad2; |
1644 | } | 1635 | } |
1645 | 1636 | ||
1646 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | ||
1647 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
1648 | IEEE80211_HW_SIGNAL_DBM | | ||
1649 | IEEE80211_HW_NOISE_DBM | | ||
1650 | IEEE80211_HW_AMPDU_AGGREGATION; | ||
1651 | |||
1652 | hw->wiphy->interface_modes = | ||
1653 | BIT(NL80211_IFTYPE_AP) | | ||
1654 | BIT(NL80211_IFTYPE_STATION) | | ||
1655 | BIT(NL80211_IFTYPE_ADHOC); | ||
1656 | |||
1657 | SET_IEEE80211_DEV(hw, &pdev->dev); | 1637 | SET_IEEE80211_DEV(hw, &pdev->dev); |
1658 | pci_set_drvdata(pdev, hw); | 1638 | pci_set_drvdata(pdev, hw); |
1659 | 1639 | ||
@@ -1701,17 +1681,10 @@ static void ath_pci_remove(struct pci_dev *pdev) | |||
1701 | { | 1681 | { |
1702 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 1682 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
1703 | struct ath_softc *sc = hw->priv; | 1683 | struct ath_softc *sc = hw->priv; |
1704 | enum ath9k_int status; | ||
1705 | 1684 | ||
1706 | if (pdev->irq) { | ||
1707 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | ||
1708 | /* clear the ISR */ | ||
1709 | ath9k_hw_getisr(sc->sc_ah, &status); | ||
1710 | sc->sc_flags |= SC_OP_INVALID; | ||
1711 | free_irq(pdev->irq, sc); | ||
1712 | } | ||
1713 | ath_detach(sc); | 1685 | ath_detach(sc); |
1714 | 1686 | if (pdev->irq) | |
1687 | free_irq(pdev->irq, sc); | ||
1715 | pci_iounmap(pdev, sc->mem); | 1688 | pci_iounmap(pdev, sc->mem); |
1716 | pci_release_region(pdev, 0); | 1689 | pci_release_region(pdev, 0); |
1717 | pci_disable_device(pdev); | 1690 | pci_disable_device(pdev); |