Commit 18357850 authored by Shahar Levi's avatar Shahar Levi Committed by John W. Linville

wl1271: 11n Support, functionality and configuration ability

Add 11n ability in scan, connection and using MCS rates.
The configuration is temporary due to the code incomplete and
still in testing process. That plans to be remove in the future.
Signed-off-by: default avatarShahar Levi <shahar_levi@ti.com>
Reviewed-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
parent c4db1c87
...@@ -18,6 +18,16 @@ config WL1271 ...@@ -18,6 +18,16 @@ config WL1271
If you choose to build a module, it'll be called wl1271. Say N if If you choose to build a module, it'll be called wl1271. Say N if
unsure. unsure.
config WL1271_HT
bool "TI wl1271 802.11 HT support (EXPERIMENTAL)"
depends on WL1271 && EXPERIMENTAL
default n
---help---
This will enable 802.11 HT support for TI wl1271 chipset.
That configuration is temporary due to the code incomplete and
still in testing process.
config WL1271_SPI config WL1271_SPI
tristate "TI wl1271 SPI support" tristate "TI wl1271 SPI support"
depends on WL1271 && SPI_MASTER depends on WL1271 && SPI_MASTER
......
...@@ -861,12 +861,32 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ...@@ -861,12 +861,32 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct ieee80211_sta *sta = txinfo->control.sta; struct ieee80211_sta *sta = txinfo->control.sta;
unsigned long flags; unsigned long flags;
/* peek into the rates configured in the STA entry */ /*
* peek into the rates configured in the STA entry.
* The rates set after connection stage, The first block only BG sets:
* the compare is for bit 0-16 of sta_rate_set. The second block add
* HT rates in case of HT supported.
*/
spin_lock_irqsave(&wl->wl_lock, flags); spin_lock_irqsave(&wl->wl_lock, flags);
if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { if (sta &&
(sta->supp_rates[conf->channel->band] !=
(wl->sta_rate_set & HW_BG_RATES_MASK))) {
wl->sta_rate_set = sta->supp_rates[conf->channel->band]; wl->sta_rate_set = sta->supp_rates[conf->channel->band];
set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
} }
#ifdef CONFIG_WL1271_HT
if (sta &&
sta->ht_cap.ht_supported &&
((wl->sta_rate_set >> HW_HT_RATES_OFFSET) !=
sta->ht_cap.mcs.rx_mask[0])) {
/* Clean MCS bits before setting them */
wl->sta_rate_set &= HW_BG_RATES_MASK;
wl->sta_rate_set |=
(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
}
#endif
spin_unlock_irqrestore(&wl->wl_lock, flags); spin_unlock_irqrestore(&wl->wl_lock, flags);
/* queue the packet */ /* queue the packet */
...@@ -1720,6 +1740,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1720,6 +1740,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
{ {
enum wl1271_cmd_ps_mode mode; enum wl1271_cmd_ps_mode mode;
struct wl1271 *wl = hw->priv; struct wl1271 *wl = hw->priv;
struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid);
bool do_join = false; bool do_join = false;
bool set_assoc = false; bool set_assoc = false;
int ret; int ret;
...@@ -1938,6 +1959,37 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1938,6 +1959,37 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
} }
} }
/*
* Takes care of: New association with HT enable,
* HT information change in beacon.
*/
if (sta &&
(changed & BSS_CHANGED_HT) &&
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true);
if (ret < 0) {
wl1271_warning("Set ht cap true failed %d", ret);
goto out_sleep;
}
ret = wl1271_acx_set_ht_information(wl,
bss_conf->ht_operation_mode);
if (ret < 0) {
wl1271_warning("Set ht information failed %d", ret);
goto out_sleep;
}
}
/*
* Takes care of: New association without HT,
* Disassociation.
*/
else if (sta && (changed & BSS_CHANGED_ASSOC)) {
ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, false);
if (ret < 0) {
wl1271_warning("Set ht cap false failed %d", ret);
goto out_sleep;
}
}
if (changed & BSS_CHANGED_ARP_FILTER) { if (changed & BSS_CHANGED_ARP_FILTER) {
__be32 addr = bss_conf->arp_addr_list[0]; __be32 addr = bss_conf->arp_addr_list[0];
WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
...@@ -2118,14 +2170,14 @@ static struct ieee80211_channel wl1271_channels[] = { ...@@ -2118,14 +2170,14 @@ static struct ieee80211_channel wl1271_channels[] = {
/* mapping to indexes for wl1271_rates */ /* mapping to indexes for wl1271_rates */
static const u8 wl1271_rate_to_idx_2ghz[] = { static const u8 wl1271_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */ /* MCS rates are used only with 11n */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ 7, /* CONF_HW_RXTX_RATE_MCS7 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ 6, /* CONF_HW_RXTX_RATE_MCS6 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ 5, /* CONF_HW_RXTX_RATE_MCS5 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ 4, /* CONF_HW_RXTX_RATE_MCS4 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ 3, /* CONF_HW_RXTX_RATE_MCS3 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ 2, /* CONF_HW_RXTX_RATE_MCS2 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ 1, /* CONF_HW_RXTX_RATE_MCS1 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ 0, /* CONF_HW_RXTX_RATE_MCS0 */
11, /* CONF_HW_RXTX_RATE_54 */ 11, /* CONF_HW_RXTX_RATE_54 */
10, /* CONF_HW_RXTX_RATE_48 */ 10, /* CONF_HW_RXTX_RATE_48 */
...@@ -2148,6 +2200,7 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { ...@@ -2148,6 +2200,7 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
/* 11n STA capabilities */ /* 11n STA capabilities */
#define HW_RX_HIGHEST_RATE 72 #define HW_RX_HIGHEST_RATE 72
#ifdef CONFIG_WL1271_HT
#define WL1271_HT_CAP { \ #define WL1271_HT_CAP { \
.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \
.ht_supported = true, \ .ht_supported = true, \
...@@ -2159,6 +2212,11 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { ...@@ -2159,6 +2212,11 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
.tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
}, \ }, \
} }
#else
#define WL1271_HT_CAP { \
.ht_supported = false, \
}
#endif
/* can't be const, mac80211 writes to this */ /* can't be const, mac80211 writes to this */
static struct ieee80211_supported_band wl1271_band_2ghz = { static struct ieee80211_supported_band wl1271_band_2ghz = {
...@@ -2166,6 +2224,7 @@ static struct ieee80211_supported_band wl1271_band_2ghz = { ...@@ -2166,6 +2224,7 @@ static struct ieee80211_supported_band wl1271_band_2ghz = {
.n_channels = ARRAY_SIZE(wl1271_channels), .n_channels = ARRAY_SIZE(wl1271_channels),
.bitrates = wl1271_rates, .bitrates = wl1271_rates,
.n_bitrates = ARRAY_SIZE(wl1271_rates), .n_bitrates = ARRAY_SIZE(wl1271_rates),
.ht_cap = WL1271_HT_CAP,
}; };
/* 5 GHz data rates for WL1273 */ /* 5 GHz data rates for WL1273 */
...@@ -2248,14 +2307,14 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { ...@@ -2248,14 +2307,14 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = {
/* mapping to indexes for wl1271_rates_5ghz */ /* mapping to indexes for wl1271_rates_5ghz */
static const u8 wl1271_rate_to_idx_5ghz[] = { static const u8 wl1271_rate_to_idx_5ghz[] = {
/* MCS rates are used only with 11n */ /* MCS rates are used only with 11n */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ 7, /* CONF_HW_RXTX_RATE_MCS7 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ 6, /* CONF_HW_RXTX_RATE_MCS6 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ 5, /* CONF_HW_RXTX_RATE_MCS5 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ 4, /* CONF_HW_RXTX_RATE_MCS4 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ 3, /* CONF_HW_RXTX_RATE_MCS3 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ 2, /* CONF_HW_RXTX_RATE_MCS2 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ 1, /* CONF_HW_RXTX_RATE_MCS1 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ 0, /* CONF_HW_RXTX_RATE_MCS0 */
7, /* CONF_HW_RXTX_RATE_54 */ 7, /* CONF_HW_RXTX_RATE_54 */
6, /* CONF_HW_RXTX_RATE_48 */ 6, /* CONF_HW_RXTX_RATE_48 */
...@@ -2280,6 +2339,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { ...@@ -2280,6 +2339,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = {
.n_channels = ARRAY_SIZE(wl1271_channels_5ghz), .n_channels = ARRAY_SIZE(wl1271_channels_5ghz),
.bitrates = wl1271_rates_5ghz, .bitrates = wl1271_rates_5ghz,
.n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
.ht_cap = WL1271_HT_CAP,
}; };
static const u8 *wl1271_band_rate_to_idx[] = { static const u8 *wl1271_band_rate_to_idx[] = {
......
...@@ -53,6 +53,12 @@ static void wl1271_rx_status(struct wl1271 *wl, ...@@ -53,6 +53,12 @@ static void wl1271_rx_status(struct wl1271 *wl,
status->band = wl->band; status->band = wl->band;
status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); status->rate_idx = wl1271_rate_to_idx(wl, desc->rate);
#ifdef CONFIG_WL1271_HT
/* 11n support */
if (desc->rate <= CONF_HW_RXTX_RATE_MCS0)
status->flag |= RX_FLAG_HT;
#endif
status->signal = desc->rssi; status->signal = desc->rssi;
/* /*
......
...@@ -209,6 +209,17 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) ...@@ -209,6 +209,17 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
rate_set >>= 1; rate_set >>= 1;
} }
#ifdef CONFIG_WL1271_HT
/* MCS rates indication are on bits 16 - 23 */
rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates;
for (bit = 0; bit < 8; bit++) {
if (rate_set & 0x1)
enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit);
rate_set >>= 1;
}
#endif
return enabled_rates; return enabled_rates;
} }
......
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