Commit 06443e46 authored by Gertjan van Wingerde's avatar Gertjan van Wingerde Committed by Ivo van Doorn

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: default avatarGertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
parent 532bc2d5
...@@ -2531,11 +2531,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) ...@@ -2531,11 +2531,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
else else
spec->ht.ht_supported = false; spec->ht.ht_supported = false;
/*
* Don't set IEEE80211_HT_CAP_SUP_WIDTH_20_40 for now as it causes
* reception problems with HT40 capable 11n APs
*/
spec->ht.cap = spec->ht.cap =
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_40 |
......
...@@ -170,23 +170,27 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, ...@@ -170,23 +170,27 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
unsigned int ieee80211_flags) unsigned int ieee80211_flags)
{ {
struct rt2x00lib_conf libconf; struct rt2x00lib_conf libconf;
u16 hw_value;
memset(&libconf, 0, sizeof(libconf)); memset(&libconf, 0, sizeof(libconf));
libconf.conf = conf; libconf.conf = conf;
if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
if (conf_is_ht40(conf)) if (conf_is_ht40(conf)) {
__set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
else hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
} else {
__clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
hw_value = conf->channel->hw_value;
}
memcpy(&libconf.rf, memcpy(&libconf.rf,
&rt2x00dev->spec.channels[conf->channel->hw_value], &rt2x00dev->spec.channels[hw_value],
sizeof(libconf.rf)); sizeof(libconf.rf));
memcpy(&libconf.channel, memcpy(&libconf.channel,
&rt2x00dev->spec.channels_info[conf->channel->hw_value], &rt2x00dev->spec.channels_info[hw_value],
sizeof(libconf.channel)); sizeof(libconf.channel));
} }
......
...@@ -84,3 +84,31 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, ...@@ -84,3 +84,31 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
else else
txdesc->txop = TXOP_HTTXOP; txdesc->txop = TXOP_HTTXOP;
} }
u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
int center_channel;
u16 i;
/*
* Initialize center channel to current channel.
*/
center_channel = spec->channels[conf->channel->hw_value].channel;
/*
* Adjust center channel to HT40+ and HT40- operation.
*/
if (conf_is_ht40_plus(conf))
center_channel += 2;
else if (conf_is_ht40_minus(conf))
center_channel -= (center_channel == 14) ? 1 : 2;
for (i = 0; i < spec->num_channels; i++)
if (spec->channels[i].channel == center_channel)
return i;
WARN_ON(1);
return conf->channel->hw_value;
}
...@@ -367,12 +367,21 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, ...@@ -367,12 +367,21 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
struct txentry_desc *txdesc, struct txentry_desc *txdesc,
const struct rt2x00_rate *hwrate); const struct rt2x00_rate *hwrate);
u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf);
#else #else
static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
struct txentry_desc *txdesc, struct txentry_desc *txdesc,
const struct rt2x00_rate *hwrate) const struct rt2x00_rate *hwrate)
{ {
} }
static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf)
{
return conf->channel->hw_value;
}
#endif /* CONFIG_RT2X00_LIB_HT */ #endif /* CONFIG_RT2X00_LIB_HT */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment