d6bc232b72c8e44db49f134980d03f4bd2cfc5f8
[openwrt/svn-archive/archive.git] / package / mac80211 / patches / 340-ath9k_ap_rc.patch
1 Hostapd now passes the HT parameters through the config()
2 callback, use these to set the appropriate channel in AP mode.
3
4 Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
5 ---
6 Note: This patch depends on [PATCHv2] nl80211: Add frequency configuration (including HT40)
7 posted by Jouni.
8
9 drivers/net/wireless/ath9k/main.c | 60 ++++++++++++++++++++++++++----------
10 drivers/net/wireless/ath9k/rc.c | 55 +++++++++++++++++++++++++++++----
11 2 files changed, 91 insertions(+), 24 deletions(-)
12
13 diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
14 index 6e103d5..d1ddb07 100644
15 --- a/drivers/net/wireless/ath9k/main.c
16 +++ b/drivers/net/wireless/ath9k/main.c
17 @@ -622,35 +622,35 @@ static int ath_get_channel(struct ath_softc *sc,
18 return -1;
19 }
20
21 +/* ext_chan_offset: (-1, 0, 1) (below, none, above) */
22 +
23 static u32 ath_get_extchanmode(struct ath_softc *sc,
24 struct ieee80211_channel *chan,
25 - struct ieee80211_bss_conf *bss_conf)
26 + int ext_chan_offset,
27 + enum ath9k_ht_macmode tx_chan_width)
28 {
29 u32 chanmode = 0;
30 - u8 ext_chan_offset = bss_conf->ht.secondary_channel_offset;
31 - enum ath9k_ht_macmode tx_chan_width = (bss_conf->ht.width_40_ok) ?
32 - ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20;
33
34 switch (chan->band) {
35 case IEEE80211_BAND_2GHZ:
36 - if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
37 + if ((ext_chan_offset == 0) &&
38 (tx_chan_width == ATH9K_HT_MACMODE_20))
39 chanmode = CHANNEL_G_HT20;
40 - if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
41 + if ((ext_chan_offset == 1) &&
42 (tx_chan_width == ATH9K_HT_MACMODE_2040))
43 chanmode = CHANNEL_G_HT40PLUS;
44 - if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
45 + if ((ext_chan_offset == -1) &&
46 (tx_chan_width == ATH9K_HT_MACMODE_2040))
47 chanmode = CHANNEL_G_HT40MINUS;
48 break;
49 case IEEE80211_BAND_5GHZ:
50 - if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
51 + if ((ext_chan_offset == 0) &&
52 (tx_chan_width == ATH9K_HT_MACMODE_20))
53 chanmode = CHANNEL_A_HT20;
54 - if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
55 + if ((ext_chan_offset == 1) &&
56 (tx_chan_width == ATH9K_HT_MACMODE_2040))
57 chanmode = CHANNEL_A_HT40PLUS;
58 - if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
59 + if ((ext_chan_offset == -1) &&
60 (tx_chan_width == ATH9K_HT_MACMODE_2040))
61 chanmode = CHANNEL_A_HT40MINUS;
62 break;
63 @@ -841,6 +841,18 @@ static void ath9k_ht_conf(struct ath_softc *sc,
64 }
65 }
66
67 +static inline int ath_sec_offset(u8 ext_offset)
68 +{
69 + if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE)
70 + return 0;
71 + else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
72 + return 1;
73 + else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
74 + return -1;
75 +
76 + return 0;
77 +}
78 +
79 static void ath9k_bss_assoc_info(struct ath_softc *sc,
80 struct ieee80211_vif *vif,
81 struct ieee80211_bss_conf *bss_conf)
82 @@ -893,13 +905,14 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
83 }
84
85 if (hw->conf.ht.enabled) {
86 - sc->sc_ah->ah_channels[pos].chanmode =
87 - ath_get_extchanmode(sc, curchan, bss_conf);
88 + int offset =
89 + ath_sec_offset(bss_conf->ht.secondary_channel_offset);
90 + sc->tx_chan_width = (bss_conf->ht.width_40_ok) ?
91 + ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20;
92
93 - if (bss_conf->ht.width_40_ok)
94 - sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
95 - else
96 - sc->tx_chan_width = ATH9K_HT_MACMODE_20;
97 + sc->sc_ah->ah_channels[pos].chanmode =
98 + ath_get_extchanmode(sc, curchan,
99 + offset, sc->tx_chan_width);
100 } else {
101 sc->sc_ah->ah_channels[pos].chanmode =
102 (curchan->band == IEEE80211_BAND_2GHZ) ?
103 @@ -2172,9 +2185,22 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
104 (curchan->band == IEEE80211_BAND_2GHZ) ?
105 CHANNEL_G : CHANNEL_A;
106
107 - if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
108 + if ((sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) &&
109 + (conf->ht.enabled)) {
110 + sc->tx_chan_width = (!!conf->ht.sec_chan_offset) ?
111 + ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20;
112 +
113 + sc->sc_ah->ah_channels[pos].chanmode =
114 + ath_get_extchanmode(sc, curchan,
115 + conf->ht.sec_chan_offset,
116 + sc->tx_chan_width);
117 + }
118 +
119 + if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) {
120 DPRINTF(sc, ATH_DBG_FATAL,
121 "%s: Unable to set channel\n", __func__);
122 + return -EINVAL;
123 + }
124 }
125
126 if (changed & IEEE80211_CONF_CHANGE_HT)
127 diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
128 index 93dfea8..7c08583 100644
129 --- a/drivers/net/wireless/ath9k/rc.c
130 +++ b/drivers/net/wireless/ath9k/rc.c
131 @@ -1304,6 +1304,38 @@ static void ath_rc_tx_status(struct ath_softc *sc,
132 xretries, long_retry);
133 }
134
135 +static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
136 + enum ieee80211_band band,
137 + bool is_ht, bool is_cw_40)
138 +{
139 + int mode = 0;
140 +
141 + switch(band) {
142 + case IEEE80211_BAND_2GHZ:
143 + mode = ATH9K_MODE_11G;
144 + if (is_ht)
145 + mode = ATH9K_MODE_11NG_HT20;
146 + if (is_cw_40)
147 + mode = ATH9K_MODE_11NG_HT40PLUS;
148 + break;
149 + case IEEE80211_BAND_5GHZ:
150 + mode = ATH9K_MODE_11A;
151 + if (is_ht)
152 + mode = ATH9K_MODE_11NA_HT20;
153 + if (is_cw_40)
154 + mode = ATH9K_MODE_11NA_HT40PLUS;
155 + break;
156 + default:
157 + DPRINTF(sc, ATH_DBG_RATE, "Invalid band\n");
158 + return NULL;
159 + }
160 +
161 + BUG_ON(mode >= ATH9K_MODE_MAX);
162 +
163 + DPRINTF(sc, ATH_DBG_RATE, "Choosing rate table for mode: %d\n", mode);
164 + return sc->hw_rate_table[mode];
165 +}
166 +
167 static void ath_rc_init(struct ath_softc *sc,
168 struct ath_rate_priv *ath_rc_priv,
169 struct ieee80211_supported_band *sband,
170 @@ -1314,16 +1346,25 @@ static void ath_rc_init(struct ath_softc *sc,
171 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
172 u8 i, j, k, hi = 0, hthi = 0;
173
174 - rate_table = sc->hw_rate_table[sc->sc_curmode];
175 + /* FIXME: Adhoc */
176 + if ((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
177 + (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)) {
178 + bool is_cw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
179 + rate_table = ath_choose_rate_table(sc, sband->band,
180 + sta->ht_cap.ht_supported,
181 + is_cw_40);
182 + } else if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
183 + /* sc_curmode would be set on init through config() */
184 + rate_table = sc->hw_rate_table[sc->sc_curmode];
185 + }
186
187 - if (sta->ht_cap.ht_supported) {
188 - if (sband->band == IEEE80211_BAND_2GHZ)
189 - rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
190 - else
191 - rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
192 + if (!rate_table) {
193 + DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n");
194 + return;
195 + }
196
197 + if (sta->ht_cap.ht_supported) {
198 ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG);
199 -
200 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
201 ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;
202 }
203 --
204 1.6.0.3
205
206 --
207 To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
208 the body of a message to majordomo@vger.kernel.org
209 More majordomo info at http://vger.kernel.org/majordomo-info.html
210