Commit 9e52b062 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

ar9170: support HT receive and channel config

This patch adds support for configuring HT40 channels
and receiving HT40 to ar9170. Receiving aggregation
doesn't seem to work right now, so it's not enabled.
Same goes for TX aggregation, but that probably needs
even more work.

With this, I can receive roughly 33 Mbits/sec.

The HT capabilities are a little odd, I tried following
otus here -- in particular having SGI_40 but not SGI_20
is a little weird but afaict that's what otus does.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 314bd750
...@@ -60,6 +60,21 @@ enum ar9170_bw { ...@@ -60,6 +60,21 @@ enum ar9170_bw {
__AR9170_NUM_BW, __AR9170_NUM_BW,
}; };
static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type)
{
switch (type) {
case NL80211_CHAN_NO_HT:
case NL80211_CHAN_HT20:
return AR9170_BW_20;
case NL80211_CHAN_HT40MINUS:
return AR9170_BW_40_BELOW;
case NL80211_CHAN_HT40PLUS:
return AR9170_BW_40_ABOVE;
default:
BUG();
}
}
enum ar9170_rf_init_mode { enum ar9170_rf_init_mode {
AR9170_RFI_NONE, AR9170_RFI_NONE,
AR9170_RFI_WARM, AR9170_RFI_WARM,
......
...@@ -142,11 +142,36 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = { ...@@ -142,11 +142,36 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = {
}; };
#undef CHAN #undef CHAN
#define AR9170_HT_CAP \
{ \
.ht_supported = true, \
.cap = IEEE80211_HT_CAP_MAX_AMSDU | \
IEEE80211_HT_CAP_SM_PS | \
IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
IEEE80211_HT_CAP_SGI_40 | \
IEEE80211_HT_CAP_DSSSCCK40 | \
IEEE80211_HT_CAP_SM_PS, \
.ampdu_factor = 3, /* ?? */ \
.ampdu_density = 7, /* ?? */ \
.mcs = { \
.rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }, \
}, \
}
static struct ieee80211_supported_band ar9170_band_2GHz = { static struct ieee80211_supported_band ar9170_band_2GHz = {
.channels = ar9170_2ghz_chantable, .channels = ar9170_2ghz_chantable,
.n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable),
.bitrates = ar9170_g_ratetable, .bitrates = ar9170_g_ratetable,
.n_bitrates = ar9170_g_ratetable_size, .n_bitrates = ar9170_g_ratetable_size,
.ht_cap = AR9170_HT_CAP,
};
static struct ieee80211_supported_band ar9170_band_5GHz = {
.channels = ar9170_5ghz_chantable,
.n_channels = ARRAY_SIZE(ar9170_5ghz_chantable),
.bitrates = ar9170_a_ratetable,
.n_bitrates = ar9170_a_ratetable_size,
.ht_cap = AR9170_HT_CAP,
}; };
#ifdef AR9170_QUEUE_DEBUG #ifdef AR9170_QUEUE_DEBUG
...@@ -190,13 +215,6 @@ static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar, ...@@ -190,13 +215,6 @@ static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar,
} }
#endif /* AR9170_QUEUE_DEBUG */ #endif /* AR9170_QUEUE_DEBUG */
static struct ieee80211_supported_band ar9170_band_5GHz = {
.channels = ar9170_5ghz_chantable,
.n_channels = ARRAY_SIZE(ar9170_5ghz_chantable),
.bitrates = ar9170_a_ratetable,
.n_bitrates = ar9170_a_ratetable_size,
};
void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
bool valid_status, u16 tx_status) bool valid_status, u16 tx_status)
{ {
...@@ -1077,7 +1095,8 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1077,7 +1095,8 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
err = ar9170_set_channel(ar, hw->conf.channel, err = ar9170_set_channel(ar, hw->conf.channel,
AR9170_RFI_NONE, AR9170_BW_20); AR9170_RFI_NONE,
nl80211_to_ar9170(hw->conf.channel_type));
if (err) if (err)
goto out; goto out;
/* adjust slot time for 5 GHz */ /* adjust slot time for 5 GHz */
...@@ -1499,6 +1518,24 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, ...@@ -1499,6 +1518,24 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
return ret; return ret;
} }
static int ar9170_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
switch (action) {
case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP:
/*
* Something goes wrong -- RX locks up
* after a while of receiving aggregated
* frames -- not enabling for now.
*/
return -EOPNOTSUPP;
default:
return -EOPNOTSUPP;
}
}
static const struct ieee80211_ops ar9170_ops = { static const struct ieee80211_ops ar9170_ops = {
.start = ar9170_op_start, .start = ar9170_op_start,
.stop = ar9170_op_stop, .stop = ar9170_op_stop,
...@@ -1515,6 +1552,7 @@ static const struct ieee80211_ops ar9170_ops = { ...@@ -1515,6 +1552,7 @@ static const struct ieee80211_ops ar9170_ops = {
.sta_notify = ar9170_sta_notify, .sta_notify = ar9170_sta_notify,
.get_stats = ar9170_get_stats, .get_stats = ar9170_get_stats,
.get_tx_stats = ar9170_get_tx_stats, .get_tx_stats = ar9170_get_tx_stats,
.ampdu_action = ar9170_ampdu_action,
}; };
void *ar9170_alloc(size_t priv_size) void *ar9170_alloc(size_t priv_size)
......
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