aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
authorGertjan van Wingerde <gwingerde@gmail.com>2010-06-03 04:52:08 -0400
committerIvo van Doorn <IvDoorn@gmail.com>2010-06-03 04:52:08 -0400
commit06443e46c65915d74b03fe1de10c00748e4706ee (patch)
tree0abaa34fb1a4b263a121decc61a742e35df58566 /drivers/net/wireless/rt2x00
parent532bc2d5244bd32d321da457d8e3919a1ed00c2e (diff)
rt2x00: Fix HT40 operation in rt2800.
Closer inspection of the legacy Ralink driver reveals that in case of HT40+ or HT40- we must adjust the frequency settings that we program to the device. Implement the same adjustment in the rt2x00 code. With this HT40 seems to work for all devices supported by rt2800pci and rt2800usb. Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c12
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00ht.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h9
4 files changed, 46 insertions, 8 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 9aa480117172..bebbda5ffaab 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2531,11 +2531,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2531 else 2531 else
2532 spec->ht.ht_supported = false; 2532 spec->ht.ht_supported = false;
2533 2533
2534 /*
2535 * Don't set IEEE80211_HT_CAP_SUP_WIDTH_20_40 for now as it causes
2536 * reception problems with HT40 capable 11n APs
2537 */
2538 spec->ht.cap = 2534 spec->ht.cap =
2535 IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
2539 IEEE80211_HT_CAP_GRN_FLD | 2536 IEEE80211_HT_CAP_GRN_FLD |
2540 IEEE80211_HT_CAP_SGI_20 | 2537 IEEE80211_HT_CAP_SGI_20 |
2541 IEEE80211_HT_CAP_SGI_40 | 2538 IEEE80211_HT_CAP_SGI_40 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 098315a271ca..8dbd634dae27 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -170,23 +170,27 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
170 unsigned int ieee80211_flags) 170 unsigned int ieee80211_flags)
171{ 171{
172 struct rt2x00lib_conf libconf; 172 struct rt2x00lib_conf libconf;
173 u16 hw_value;
173 174
174 memset(&libconf, 0, sizeof(libconf)); 175 memset(&libconf, 0, sizeof(libconf));
175 176
176 libconf.conf = conf; 177 libconf.conf = conf;
177 178
178 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { 179 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
179 if (conf_is_ht40(conf)) 180 if (conf_is_ht40(conf)) {
180 __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); 181 __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
181 else 182 hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
183 } else {
182 __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); 184 __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
185 hw_value = conf->channel->hw_value;
186 }
183 187
184 memcpy(&libconf.rf, 188 memcpy(&libconf.rf,
185 &rt2x00dev->spec.channels[conf->channel->hw_value], 189 &rt2x00dev->spec.channels[hw_value],
186 sizeof(libconf.rf)); 190 sizeof(libconf.rf));
187 191
188 memcpy(&libconf.channel, 192 memcpy(&libconf.channel,
189 &rt2x00dev->spec.channels_info[conf->channel->hw_value], 193 &rt2x00dev->spec.channels_info[hw_value],
190 sizeof(libconf.channel)); 194 sizeof(libconf.channel));
191 } 195 }
192 196
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
index 5a407602ce3e..c4b749da4302 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
@@ -84,3 +84,31 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
84 else 84 else
85 txdesc->txop = TXOP_HTTXOP; 85 txdesc->txop = TXOP_HTTXOP;
86} 86}
87
88u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
89 struct ieee80211_conf *conf)
90{
91 struct hw_mode_spec *spec = &rt2x00dev->spec;
92 int center_channel;
93 u16 i;
94
95 /*
96 * Initialize center channel to current channel.
97 */
98 center_channel = spec->channels[conf->channel->hw_value].channel;
99
100 /*
101 * Adjust center channel to HT40+ and HT40- operation.
102 */
103 if (conf_is_ht40_plus(conf))
104 center_channel += 2;
105 else if (conf_is_ht40_minus(conf))
106 center_channel -= (center_channel == 14) ? 1 : 2;
107
108 for (i = 0; i < spec->num_channels; i++)
109 if (spec->channels[i].channel == center_channel)
110 return i;
111
112 WARN_ON(1);
113 return conf->channel->hw_value;
114}
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 822affc9b4ca..ed27de1de57b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -367,12 +367,21 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
367void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, 367void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
368 struct txentry_desc *txdesc, 368 struct txentry_desc *txdesc,
369 const struct rt2x00_rate *hwrate); 369 const struct rt2x00_rate *hwrate);
370
371u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
372 struct ieee80211_conf *conf);
370#else 373#else
371static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, 374static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
372 struct txentry_desc *txdesc, 375 struct txentry_desc *txdesc,
373 const struct rt2x00_rate *hwrate) 376 const struct rt2x00_rate *hwrate)
374{ 377{
375} 378}
379
380static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
381 struct ieee80211_conf *conf)
382{
383 return conf->channel->hw_value;
384}
376#endif /* CONFIG_RT2X00_LIB_HT */ 385#endif /* CONFIG_RT2X00_LIB_HT */
377 386
378/* 387/*