diff options
author | Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> | 2008-02-03 21:51:04 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-02-29 15:19:35 -0500 |
commit | d8ee398d183df36083e41e9162b0cf014f38f482 (patch) | |
tree | ee5c10f61aadd7ef8d78a06c3a48151b00ff0945 /drivers/net/wireless/ath5k/base.c | |
parent | 406f2388cc1f6e6c176305bd325cef230ce1afdd (diff) |
ath5k: Port to new bitrate/channel API
Author: Nick Kossifidis <mickflemm@gmail.com>
Tested on 5211, 5213+5112, 5213A+2112A and it wors fine.
Also i figured out a way to process rate vallue found
on status descriptors, it's still buggy but we are getting
closer (i think it improved stability a little).
Changes to hw.c, initvals.c, phy.c
Changes-licensed-under: ISC
Changes to ath5k.h, base.c, base.h
Changes-licensed-under: 3-Clause-BSD
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k/base.c')
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 346 |
1 files changed, 191 insertions, 155 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index bef967ce34a6..52e55f67b735 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -240,6 +240,8 @@ static int ath5k_chan_set(struct ath5k_softc *sc, | |||
240 | static void ath5k_setcurmode(struct ath5k_softc *sc, | 240 | static void ath5k_setcurmode(struct ath5k_softc *sc, |
241 | unsigned int mode); | 241 | unsigned int mode); |
242 | static void ath5k_mode_setup(struct ath5k_softc *sc); | 242 | static void ath5k_mode_setup(struct ath5k_softc *sc); |
243 | static void ath5k_set_total_hw_rates(struct ath5k_softc *sc); | ||
244 | |||
243 | /* Descriptor setup */ | 245 | /* Descriptor setup */ |
244 | static int ath5k_desc_alloc(struct ath5k_softc *sc, | 246 | static int ath5k_desc_alloc(struct ath5k_softc *sc, |
245 | struct pci_dev *pdev); | 247 | struct pci_dev *pdev); |
@@ -515,12 +517,12 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
515 | /* Single chip radio (!RF5111) */ | 517 | /* Single chip radio (!RF5111) */ |
516 | if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) { | 518 | if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) { |
517 | /* No 5GHz support -> report 2GHz radio */ | 519 | /* No 5GHz support -> report 2GHz radio */ |
518 | if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){ | 520 | if(!test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)){ |
519 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | 521 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", |
520 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), | 522 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), |
521 | sc->ah->ah_radio_5ghz_revision); | 523 | sc->ah->ah_radio_5ghz_revision); |
522 | /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */ | 524 | /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */ |
523 | } else if(!test_bit(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){ | 525 | } else if(!test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)){ |
524 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | 526 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", |
525 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), | 527 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), |
526 | sc->ah->ah_radio_5ghz_revision); | 528 | sc->ah->ah_radio_5ghz_revision); |
@@ -693,11 +695,14 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
693 | goto err; | 695 | goto err; |
694 | } | 696 | } |
695 | 697 | ||
698 | /* Set *_rates so we can map hw rate index */ | ||
699 | ath5k_set_total_hw_rates(sc); | ||
700 | |||
696 | /* NB: setup here so ath5k_rate_update is happy */ | 701 | /* NB: setup here so ath5k_rate_update is happy */ |
697 | if (test_bit(MODE_IEEE80211A, ah->ah_modes)) | 702 | if (test_bit(AR5K_MODE_11A, ah->ah_modes)) |
698 | ath5k_setcurmode(sc, MODE_IEEE80211A); | 703 | ath5k_setcurmode(sc, AR5K_MODE_11A); |
699 | else | 704 | else |
700 | ath5k_setcurmode(sc, MODE_IEEE80211B); | 705 | ath5k_setcurmode(sc, AR5K_MODE_11B); |
701 | 706 | ||
702 | /* | 707 | /* |
703 | * Allocate tx+rx descriptors and populate the lists. | 708 | * Allocate tx+rx descriptors and populate the lists. |
@@ -837,12 +842,9 @@ ath5k_copy_rates(struct ieee80211_rate *rates, | |||
837 | return 0; | 842 | return 0; |
838 | 843 | ||
839 | for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) { | 844 | for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) { |
840 | if (!rt->rates[i].valid) | 845 | rates[count].bitrate = rt->rates[i].rate_kbps / 100; |
841 | continue; | 846 | rates[count].hw_value = rt->rates[i].rate_code; |
842 | rates->rate = rt->rates[i].rate_kbps / 100; | 847 | rates[count].flags = rt->rates[i].modulation; |
843 | rates->val = rt->rates[i].rate_code; | ||
844 | rates->flags = rt->rates[i].modulation; | ||
845 | rates++; | ||
846 | count++; | 848 | count++; |
847 | max--; | 849 | max--; |
848 | } | 850 | } |
@@ -856,43 +858,22 @@ ath5k_copy_channels(struct ath5k_hw *ah, | |||
856 | unsigned int mode, | 858 | unsigned int mode, |
857 | unsigned int max) | 859 | unsigned int max) |
858 | { | 860 | { |
859 | static const struct { unsigned int mode, mask, chan; } map[] = { | 861 | unsigned int i, count, size, chfreq, freq, ch; |
860 | [MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A }, | ||
861 | [MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T }, | ||
862 | [MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B }, | ||
863 | [MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G }, | ||
864 | [MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG }, | ||
865 | }; | ||
866 | static const struct ath5k_regchannel chans_2ghz[] = | ||
867 | IEEE80211_CHANNELS_2GHZ; | ||
868 | static const struct ath5k_regchannel chans_5ghz[] = | ||
869 | IEEE80211_CHANNELS_5GHZ; | ||
870 | const struct ath5k_regchannel *chans; | ||
871 | enum ath5k_regdom dmn; | ||
872 | unsigned int i, count, size, chfreq, all, f, ch; | ||
873 | 862 | ||
874 | if (!test_bit(mode, ah->ah_modes)) | 863 | if (!test_bit(mode, ah->ah_modes)) |
875 | return 0; | 864 | return 0; |
876 | 865 | ||
877 | all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1; | ||
878 | |||
879 | switch (mode) { | 866 | switch (mode) { |
880 | case MODE_IEEE80211A: | 867 | case AR5K_MODE_11A: |
881 | case MODE_ATHEROS_TURBO: | 868 | case AR5K_MODE_11A_TURBO: |
882 | /* 1..220, but 2GHz frequencies are filtered by check_channel */ | 869 | /* 1..220, but 2GHz frequencies are filtered by check_channel */ |
883 | size = all ? 220 : ARRAY_SIZE(chans_5ghz); | 870 | size = 220 ; |
884 | chans = chans_5ghz; | ||
885 | dmn = ath5k_regdom2flag(ah->ah_regdomain, | ||
886 | IEEE80211_CHANNELS_5GHZ_MIN); | ||
887 | chfreq = CHANNEL_5GHZ; | 871 | chfreq = CHANNEL_5GHZ; |
888 | break; | 872 | break; |
889 | case MODE_IEEE80211B: | 873 | case AR5K_MODE_11B: |
890 | case MODE_IEEE80211G: | 874 | case AR5K_MODE_11G: |
891 | case MODE_ATHEROS_TURBOG: | 875 | case AR5K_MODE_11G_TURBO: |
892 | size = all ? 26 : ARRAY_SIZE(chans_2ghz); | 876 | size = 26; |
893 | chans = chans_2ghz; | ||
894 | dmn = ath5k_regdom2flag(ah->ah_regdomain, | ||
895 | IEEE80211_CHANNELS_2GHZ_MIN); | ||
896 | chfreq = CHANNEL_2GHZ; | 877 | chfreq = CHANNEL_2GHZ; |
897 | break; | 878 | break; |
898 | default: | 879 | default: |
@@ -901,25 +882,26 @@ ath5k_copy_channels(struct ath5k_hw *ah, | |||
901 | } | 882 | } |
902 | 883 | ||
903 | for (i = 0, count = 0; i < size && max > 0; i++) { | 884 | for (i = 0, count = 0; i < size && max > 0; i++) { |
904 | ch = all ? i + 1 : chans[i].chan; | 885 | ch = i + 1 ; |
905 | f = ath5k_ieee2mhz(ch); | 886 | freq = ath5k_ieee2mhz(ch); |
906 | /* Check if channel is supported by the chipset */ | ||
907 | if (!ath5k_channel_ok(ah, f, chfreq)) | ||
908 | continue; | ||
909 | 887 | ||
910 | /* Match regulation domain */ | 888 | /* Check if channel is supported by the chipset */ |
911 | if (!all && !(IEEE80211_DMN(chans[i].domain) & | 889 | if (!ath5k_channel_ok(ah, freq, chfreq)) |
912 | IEEE80211_DMN(dmn))) | ||
913 | continue; | 890 | continue; |
914 | 891 | ||
915 | if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode) | 892 | /* Write channel info and increment counter */ |
916 | continue; | 893 | channels[count].center_freq = freq; |
894 | |||
895 | if((mode == AR5K_MODE_11A) || | ||
896 | (mode == AR5K_MODE_11G)){ | ||
897 | channels[count].hw_value = chfreq|CHANNEL_OFDM; | ||
898 | } else if((mode == AR5K_MODE_11A_TURBO) || | ||
899 | (mode == AR5K_MODE_11G_TURBO)){ | ||
900 | channels[count].hw_value = chfreq|CHANNEL_OFDM|CHANNEL_TURBO; | ||
901 | }if(mode == AR5K_MODE_11B) { | ||
902 | channels[count].hw_value = CHANNEL_B; | ||
903 | } | ||
917 | 904 | ||
918 | /* Write channel and increment counter */ | ||
919 | channels->chan = ch; | ||
920 | channels->freq = f; | ||
921 | channels->val = map[mode].chan; | ||
922 | channels++; | ||
923 | count++; | 905 | count++; |
924 | max--; | 906 | max--; |
925 | } | 907 | } |
@@ -927,95 +909,76 @@ ath5k_copy_channels(struct ath5k_hw *ah, | |||
927 | return count; | 909 | return count; |
928 | } | 910 | } |
929 | 911 | ||
930 | /* Only tries to register modes our EEPROM says it can support */ | 912 | static int |
931 | #define REGISTER_MODE(m) do { \ | 913 | ath5k_getchannels(struct ieee80211_hw *hw) |
932 | ret = ath5k_register_mode(hw, m); \ | ||
933 | if (ret) \ | ||
934 | return ret; \ | ||
935 | } while (0) \ | ||
936 | |||
937 | static inline int | ||
938 | ath5k_register_mode(struct ieee80211_hw *hw, u8 m) | ||
939 | { | 914 | { |
940 | struct ath5k_softc *sc = hw->priv; | 915 | struct ath5k_softc *sc = hw->priv; |
941 | struct ieee80211_hw_mode *modes = sc->modes; | 916 | struct ath5k_hw *ah = sc->ah; |
942 | unsigned int i; | 917 | struct ieee80211_supported_band *sbands = sc->sbands; |
943 | int ret; | 918 | const struct ath5k_rate_table *hw_rates; |
919 | unsigned int max_r, max_c, count_r, count_c; | ||
920 | int mode2g = AR5K_MODE_11G; | ||
944 | 921 | ||
945 | if (!test_bit(m, sc->ah->ah_capabilities.cap_mode)) | 922 | BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS); |
946 | return 0; | ||
947 | 923 | ||
948 | for (i = 0; i < NUM_DRIVER_MODES; i++) { | 924 | max_r = ARRAY_SIZE(sc->rates); |
949 | if (modes[i].mode != m || !modes[i].num_channels) | 925 | max_c = ARRAY_SIZE(sc->channels); |
950 | continue; | 926 | count_r = count_c = 0; |
951 | ret = ieee80211_register_hwmode(hw, &modes[i]); | 927 | |
952 | if (ret) { | 928 | /* 2GHz band */ |
953 | ATH5K_ERR(sc, "can't register hwmode %u\n", m); | 929 | if(!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)){ |
954 | return ret; | 930 | mode2g = AR5K_MODE_11B; |
931 | if(!test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)){ | ||
932 | mode2g = -1; | ||
955 | } | 933 | } |
956 | return 0; | ||
957 | } | 934 | } |
958 | BUG(); | ||
959 | } | ||
960 | 935 | ||
961 | static int | 936 | if(mode2g > 0){ |
962 | ath5k_getchannels(struct ieee80211_hw *hw) | 937 | struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_2GHZ]; |
963 | { | ||
964 | struct ath5k_softc *sc = hw->priv; | ||
965 | struct ath5k_hw *ah = sc->ah; | ||
966 | struct ieee80211_hw_mode *modes = sc->modes; | ||
967 | unsigned int i, max_r, max_c; | ||
968 | int ret; | ||
969 | 938 | ||
970 | BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3); | 939 | sband->bitrates = sc->rates; |
940 | sband->channels = sc->channels; | ||
971 | 941 | ||
972 | /* The order here does not matter */ | 942 | sband->band = IEEE80211_BAND_2GHZ; |
973 | modes[0].mode = MODE_IEEE80211G; | 943 | sband->n_channels = ath5k_copy_channels(ah, sband->channels, |
974 | modes[1].mode = MODE_IEEE80211B; | 944 | mode2g, max_c); |
975 | modes[2].mode = MODE_IEEE80211A; | ||
976 | 945 | ||
977 | max_r = ARRAY_SIZE(sc->rates); | 946 | hw_rates = ath5k_hw_get_rate_table(ah, mode2g); |
978 | max_c = ARRAY_SIZE(sc->channels); | 947 | sband->n_bitrates = ath5k_copy_rates(sband->bitrates, |
948 | hw_rates,max_r); | ||
979 | 949 | ||
980 | for (i = 0; i < NUM_DRIVER_MODES; i++) { | 950 | count_c = sband->n_channels; |
981 | struct ieee80211_hw_mode *mode = &modes[i]; | 951 | count_r = sband->n_bitrates; |
982 | const struct ath5k_rate_table *hw_rates; | ||
983 | 952 | ||
984 | if (i == 0) { | 953 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; |
985 | modes[0].rates = sc->rates; | 954 | |
986 | modes->channels = sc->channels; | 955 | max_r -= count_r; |
987 | } else { | 956 | max_c -= count_c; |
988 | struct ieee80211_hw_mode *prev_mode = &modes[i-1]; | ||
989 | int prev_num_r = prev_mode->num_rates; | ||
990 | int prev_num_c = prev_mode->num_channels; | ||
991 | mode->rates = &prev_mode->rates[prev_num_r]; | ||
992 | mode->channels = &prev_mode->channels[prev_num_c]; | ||
993 | } | ||
994 | 957 | ||
995 | hw_rates = ath5k_hw_get_rate_table(ah, mode->mode); | ||
996 | mode->num_rates = ath5k_copy_rates(mode->rates, hw_rates, | ||
997 | max_r); | ||
998 | mode->num_channels = ath5k_copy_channels(ah, mode->channels, | ||
999 | mode->mode, max_c); | ||
1000 | max_r -= mode->num_rates; | ||
1001 | max_c -= mode->num_channels; | ||
1002 | } | 958 | } |
1003 | 959 | ||
1004 | /* We try to register all modes this driver supports. We don't bother | 960 | /* 5GHz band */ |
1005 | * with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts | ||
1006 | * for that as per mac80211. Then, REGISTER_MODE() will will actually | ||
1007 | * check the eeprom reading for more reliable capability information. | ||
1008 | * Order matters here as per mac80211's latest preference. This will | ||
1009 | * all hopefullly soon go away. */ | ||
1010 | 961 | ||
1011 | REGISTER_MODE(MODE_IEEE80211G); | 962 | if(test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)){ |
1012 | if (ah->ah_version != AR5K_AR5212) | 963 | struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_5GHZ]; |
1013 | REGISTER_MODE(MODE_IEEE80211B); | ||
1014 | REGISTER_MODE(MODE_IEEE80211A); | ||
1015 | 964 | ||
1016 | ath5k_debug_dump_modes(sc, modes); | 965 | sband->bitrates = &sc->rates[count_r]; |
966 | sband->channels = &sc->channels[count_c]; | ||
1017 | 967 | ||
1018 | return ret; | 968 | sband->band = IEEE80211_BAND_5GHZ; |
969 | sband->n_channels = ath5k_copy_channels(ah, sband->channels, | ||
970 | AR5K_MODE_11A, max_c); | ||
971 | |||
972 | hw_rates = ath5k_hw_get_rate_table(ah, AR5K_MODE_11A); | ||
973 | sband->n_bitrates = ath5k_copy_rates(sband->bitrates, | ||
974 | hw_rates,max_r); | ||
975 | |||
976 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; | ||
977 | } | ||
978 | |||
979 | /* FIXME: ath5k_debug_dump_modes(sc, modes); */ | ||
980 | |||
981 | return 0; | ||
1019 | } | 982 | } |
1020 | 983 | ||
1021 | /* | 984 | /* |
@@ -1030,11 +993,15 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
1030 | struct ath5k_hw *ah = sc->ah; | 993 | struct ath5k_hw *ah = sc->ah; |
1031 | int ret; | 994 | int ret; |
1032 | 995 | ||
1033 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n", | 996 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", |
1034 | sc->curchan->chan, sc->curchan->freq, | 997 | sc->curchan->center_freq, chan->center_freq); |
1035 | chan->chan, chan->freq); | 998 | |
999 | if (chan->center_freq != sc->curchan->center_freq || | ||
1000 | chan->hw_value != sc->curchan->hw_value) { | ||
1001 | |||
1002 | sc->curchan = chan; | ||
1003 | sc->curband = &sc->sbands[chan->band]; | ||
1036 | 1004 | ||
1037 | if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) { | ||
1038 | /* | 1005 | /* |
1039 | * To switch channels clear any pending DMA operations; | 1006 | * To switch channels clear any pending DMA operations; |
1040 | * wait long enough for the RX fifo to drain, reset the | 1007 | * wait long enough for the RX fifo to drain, reset the |
@@ -1044,13 +1011,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
1044 | ath5k_hw_set_intr(ah, 0); /* disable interrupts */ | 1011 | ath5k_hw_set_intr(ah, 0); /* disable interrupts */ |
1045 | ath5k_txq_cleanup(sc); /* clear pending tx frames */ | 1012 | ath5k_txq_cleanup(sc); /* clear pending tx frames */ |
1046 | ath5k_rx_stop(sc); /* turn off frame recv */ | 1013 | ath5k_rx_stop(sc); /* turn off frame recv */ |
1047 | ret = ath5k_hw_reset(ah, sc->opmode, chan, true); | 1014 | ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true); |
1048 | if (ret) { | 1015 | if (ret) { |
1049 | ATH5K_ERR(sc, "%s: unable to reset channel %u " | 1016 | ATH5K_ERR(sc, "%s: unable to reset channel " |
1050 | "(%u Mhz)\n", __func__, chan->chan, chan->freq); | 1017 | "(%u Mhz)\n", __func__, chan->center_freq); |
1051 | return ret; | 1018 | return ret; |
1052 | } | 1019 | } |
1053 | sc->curchan = chan; | 1020 | |
1054 | ath5k_hw_set_txpower_limit(sc->ah, 0); | 1021 | ath5k_hw_set_txpower_limit(sc->ah, 0); |
1055 | 1022 | ||
1056 | /* | 1023 | /* |
@@ -1081,6 +1048,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
1081 | return 0; | 1048 | return 0; |
1082 | } | 1049 | } |
1083 | 1050 | ||
1051 | /* | ||
1052 | * TODO: CLEAN THIS !!! | ||
1053 | */ | ||
1084 | static void | 1054 | static void |
1085 | ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) | 1055 | ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) |
1086 | { | 1056 | { |
@@ -1121,10 +1091,6 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) | |||
1121 | continue; | 1091 | continue; |
1122 | } | 1092 | } |
1123 | sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD; | 1093 | sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD; |
1124 | if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation == | ||
1125 | IEEE80211_RATE_OFDM) | ||
1126 | sc->hwmap[i].txflags |= | ||
1127 | IEEE80211_RADIOTAP_F_SHORTPRE; | ||
1128 | /* receive frames include FCS */ | 1094 | /* receive frames include FCS */ |
1129 | sc->hwmap[i].rxflags = sc->hwmap[i].txflags | | 1095 | sc->hwmap[i].rxflags = sc->hwmap[i].txflags | |
1130 | IEEE80211_RADIOTAP_F_FCS; | 1096 | IEEE80211_RADIOTAP_F_FCS; |
@@ -1142,6 +1108,12 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) | |||
1142 | } | 1108 | } |
1143 | 1109 | ||
1144 | sc->curmode = mode; | 1110 | sc->curmode = mode; |
1111 | |||
1112 | if(mode == AR5K_MODE_11A){ | ||
1113 | sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
1114 | } else { | ||
1115 | sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
1116 | } | ||
1145 | } | 1117 | } |
1146 | 1118 | ||
1147 | static void | 1119 | static void |
@@ -1164,6 +1136,72 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1164 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); | 1136 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); |
1165 | } | 1137 | } |
1166 | 1138 | ||
1139 | /* | ||
1140 | * Match the hw provided rate index (through descriptors) | ||
1141 | * to an index for sc->curband->bitrates, so it can be used | ||
1142 | * by the stack. | ||
1143 | * | ||
1144 | * This one is a little bit tricky but i think i'm right | ||
1145 | * about this... | ||
1146 | * | ||
1147 | * We have 4 rate tables in the following order: | ||
1148 | * XR (4 rates) | ||
1149 | * 802.11a (8 rates) | ||
1150 | * 802.11b (4 rates) | ||
1151 | * 802.11g (12 rates) | ||
1152 | * that make the hw rate table. | ||
1153 | * | ||
1154 | * Lets take a 5211 for example that supports a and b modes only. | ||
1155 | * First comes the 802.11a table and then 802.11b (total 12 rates). | ||
1156 | * When hw returns eg. 11 it points to the last 802.11b rate (11Mbit), | ||
1157 | * if it returns 2 it points to the second 802.11a rate etc. | ||
1158 | * | ||
1159 | * Same goes for 5212 who has xr/a/b/g support (total 28 rates). | ||
1160 | * First comes the XR table, then 802.11a, 802.11b and 802.11g. | ||
1161 | * When hw returns eg. 27 it points to the last 802.11g rate (54Mbits) etc | ||
1162 | */ | ||
1163 | static void | ||
1164 | ath5k_set_total_hw_rates(struct ath5k_softc *sc){ | ||
1165 | |||
1166 | struct ath5k_hw *ah = sc->ah; | ||
1167 | |||
1168 | if(test_bit(AR5K_MODE_11A, ah->ah_modes)) | ||
1169 | sc->a_rates = 8; | ||
1170 | |||
1171 | if(test_bit(AR5K_MODE_11B, ah->ah_modes)) | ||
1172 | sc->b_rates = 4; | ||
1173 | |||
1174 | if(test_bit(AR5K_MODE_11G, ah->ah_modes)) | ||
1175 | sc->g_rates = 12; | ||
1176 | |||
1177 | /* XXX: Need to see what what happens when | ||
1178 | xr disable bits in eeprom are set */ | ||
1179 | if(ah->ah_version >= AR5K_AR5212) | ||
1180 | sc->xr_rates = 4; | ||
1181 | |||
1182 | } | ||
1183 | |||
1184 | static inline int | ||
1185 | ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix){ | ||
1186 | |||
1187 | int mac80211_rix; | ||
1188 | |||
1189 | if(sc->curband->band == IEEE80211_BAND_2GHZ){ | ||
1190 | /* We setup a g ratetable for both b/g modes */ | ||
1191 | mac80211_rix = hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates; | ||
1192 | } else { | ||
1193 | mac80211_rix = hw_rix - sc->xr_rates; | ||
1194 | } | ||
1195 | |||
1196 | /* Something went wrong, fallback to basic rate for this band */ | ||
1197 | if((mac80211_rix >= sc->curband->n_bitrates) || | ||
1198 | (mac80211_rix <= 0 )){ | ||
1199 | mac80211_rix = 1; | ||
1200 | } | ||
1201 | |||
1202 | return mac80211_rix; | ||
1203 | } | ||
1204 | |||
1167 | 1205 | ||
1168 | 1206 | ||
1169 | 1207 | ||
@@ -1268,7 +1306,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1268 | 1306 | ||
1269 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1307 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1270 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, | 1308 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, |
1271 | (ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0); | 1309 | (sc->power_level * 2), ctl->tx_rate->hw_value, ctl->retry_limit, keyidx, 0, flags, 0, 0); |
1272 | if (ret) | 1310 | if (ret) |
1273 | goto err_unmap; | 1311 | goto err_unmap; |
1274 | 1312 | ||
@@ -1791,9 +1829,8 @@ accept: | |||
1791 | rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp); | 1829 | rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp); |
1792 | rxs.flag |= RX_FLAG_TSFT; | 1830 | rxs.flag |= RX_FLAG_TSFT; |
1793 | 1831 | ||
1794 | rxs.freq = sc->curchan->freq; | 1832 | rxs.freq = sc->curchan->center_freq; |
1795 | rxs.channel = sc->curchan->chan; | 1833 | rxs.band = sc->curband->band; |
1796 | rxs.phymode = sc->curmode; | ||
1797 | 1834 | ||
1798 | /* | 1835 | /* |
1799 | * signal quality: | 1836 | * signal quality: |
@@ -1811,7 +1848,7 @@ accept: | |||
1811 | rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64; | 1848 | rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64; |
1812 | 1849 | ||
1813 | rxs.antenna = ds->ds_rxstat.rs_antenna; | 1850 | rxs.antenna = ds->ds_rxstat.rs_antenna; |
1814 | rxs.rate = ds->ds_rxstat.rs_rate; | 1851 | rxs.rate_idx = ath5k_hw_to_driver_rix(sc,ds->ds_rxstat.rs_rate); |
1815 | rxs.flag |= ath5k_rx_decrypted(sc, ds, skb); | 1852 | rxs.flag |= ath5k_rx_decrypted(sc, ds, skb); |
1816 | 1853 | ||
1817 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 1854 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); |
@@ -1958,7 +1995,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1958 | ds->ds_data = bf->skbaddr; | 1995 | ds->ds_data = bf->skbaddr; |
1959 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, | 1996 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, |
1960 | ieee80211_get_hdrlen_from_skb(skb), | 1997 | ieee80211_get_hdrlen_from_skb(skb), |
1961 | AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1, | 1998 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), ctl->tx_rate->hw_value, 1, |
1962 | AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); | 1999 | AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); |
1963 | if (ret) | 2000 | if (ret) |
1964 | goto err_unmap; | 2001 | goto err_unmap; |
@@ -2211,7 +2248,8 @@ ath5k_init(struct ath5k_softc *sc) | |||
2211 | * be followed by initialization of the appropriate bits | 2248 | * be followed by initialization of the appropriate bits |
2212 | * and then setup of the interrupt mask. | 2249 | * and then setup of the interrupt mask. |
2213 | */ | 2250 | */ |
2214 | sc->curchan = sc->hw->conf.chan; | 2251 | sc->curchan = sc->hw->conf.channel; |
2252 | sc->curband = &sc->sbands[sc->curchan->band]; | ||
2215 | ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false); | 2253 | ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false); |
2216 | if (ret) { | 2254 | if (ret) { |
2217 | ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret); | 2255 | ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret); |
@@ -2448,7 +2486,7 @@ ath5k_calibrate(unsigned long data) | |||
2448 | struct ath5k_hw *ah = sc->ah; | 2486 | struct ath5k_hw *ah = sc->ah; |
2449 | 2487 | ||
2450 | ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", | 2488 | ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", |
2451 | sc->curchan->chan, sc->curchan->val); | 2489 | ieee80211_frequency_to_channel(sc->curchan->center_freq), sc->curchan->hw_value); |
2452 | 2490 | ||
2453 | if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) { | 2491 | if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) { |
2454 | /* | 2492 | /* |
@@ -2460,7 +2498,7 @@ ath5k_calibrate(unsigned long data) | |||
2460 | } | 2498 | } |
2461 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) | 2499 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) |
2462 | ATH5K_ERR(sc, "calibration of channel %u failed\n", | 2500 | ATH5K_ERR(sc, "calibration of channel %u failed\n", |
2463 | sc->curchan->chan); | 2501 | ieee80211_frequency_to_channel(sc->curchan->center_freq)); |
2464 | 2502 | ||
2465 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + | 2503 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + |
2466 | msecs_to_jiffies(ath5k_calinterval * 1000))); | 2504 | msecs_to_jiffies(ath5k_calinterval * 1000))); |
@@ -2558,7 +2596,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2558 | memmove(skb->data, skb->data+pad, hdrlen); | 2596 | memmove(skb->data, skb->data+pad, hdrlen); |
2559 | } | 2597 | } |
2560 | 2598 | ||
2561 | sc->led_txrate = ctl->tx_rate; | 2599 | sc->led_txrate = ctl->tx_rate->hw_value; |
2562 | 2600 | ||
2563 | spin_lock_irqsave(&sc->txbuflock, flags); | 2601 | spin_lock_irqsave(&sc->txbuflock, flags); |
2564 | if (list_empty(&sc->txbuf)) { | 2602 | if (list_empty(&sc->txbuf)) { |
@@ -2597,11 +2635,6 @@ ath5k_reset(struct ieee80211_hw *hw) | |||
2597 | int ret; | 2635 | int ret; |
2598 | 2636 | ||
2599 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); | 2637 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); |
2600 | /* | ||
2601 | * Convert to a hw channel description with the flags | ||
2602 | * constrained to reflect the current operating mode. | ||
2603 | */ | ||
2604 | sc->curchan = hw->conf.chan; | ||
2605 | 2638 | ||
2606 | ath5k_hw_set_intr(ah, 0); | 2639 | ath5k_hw_set_intr(ah, 0); |
2607 | ath5k_txq_cleanup(sc); | 2640 | ath5k_txq_cleanup(sc); |
@@ -2692,6 +2725,9 @@ end: | |||
2692 | mutex_unlock(&sc->lock); | 2725 | mutex_unlock(&sc->lock); |
2693 | } | 2726 | } |
2694 | 2727 | ||
2728 | /* | ||
2729 | * TODO: Phy disable/diversity etc | ||
2730 | */ | ||
2695 | static int | 2731 | static int |
2696 | ath5k_config(struct ieee80211_hw *hw, | 2732 | ath5k_config(struct ieee80211_hw *hw, |
2697 | struct ieee80211_conf *conf) | 2733 | struct ieee80211_conf *conf) |
@@ -2699,9 +2735,9 @@ ath5k_config(struct ieee80211_hw *hw, | |||
2699 | struct ath5k_softc *sc = hw->priv; | 2735 | struct ath5k_softc *sc = hw->priv; |
2700 | 2736 | ||
2701 | sc->bintval = conf->beacon_int; | 2737 | sc->bintval = conf->beacon_int; |
2702 | ath5k_setcurmode(sc, conf->phymode); | 2738 | sc->power_level = conf->power_level; |
2703 | 2739 | ||
2704 | return ath5k_chan_set(sc, conf->chan); | 2740 | return ath5k_chan_set(sc, conf->channel); |
2705 | } | 2741 | } |
2706 | 2742 | ||
2707 | static int | 2743 | static int |