summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/wl1271/0004-wl1271-11n-Support-functionality-and-configuration-a.patch
blob: 17ed6e63d751908ab1e5aa9d7b0ae8d50dd195c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
From 9685ab91494ae35d2cb7e0033c5ee1bf3cdf0c64 Mon Sep 17 00:00:00 2001
From: Shahar Levi <shahar_levi@ti.com>
Date: Wed, 13 Oct 2010 16:09:41 +0200
Subject: [PATCH 04/15] 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: Shahar Levi <shahar_levi@ti.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/Kconfig       |   10 +++
 drivers/net/wireless/wl12xx/wl1271_main.c |   96 +++++++++++++++++++++++------
 drivers/net/wireless/wl12xx/wl1271_rx.c   |    6 ++
 drivers/net/wireless/wl12xx/wl1271_tx.c   |   11 +++
 4 files changed, 105 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index b447559..1b3b7bd 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -18,6 +18,16 @@ config WL1271
 	  If you choose to build a module, it'll be called wl1271. Say N if
 	  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
 	tristate "TI wl1271 SPI support"
 	depends on WL1271 && SPI_MASTER
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 785b73c..49ec0ef 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -851,12 +851,32 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	struct ieee80211_sta *sta = txinfo->control.sta;
 	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);
-	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];
 		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);
 
 	/* queue the packet */
@@ -1709,6 +1729,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 {
 	enum wl1271_cmd_ps_mode mode;
 	struct wl1271 *wl = hw->priv;
+	struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid);
 	bool do_join = false;
 	bool set_assoc = false;
 	int ret;
@@ -1927,6 +1948,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) {
 		__be32 addr = bss_conf->arp_addr_list[0];
 		WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
@@ -2107,14 +2159,14 @@ static struct ieee80211_channel wl1271_channels[] = {
 /* mapping to indexes for wl1271_rates */
 static const u8 wl1271_rate_to_idx_2ghz[] = {
 	/* MCS rates are used only with 11n */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */
+	7,                            /* CONF_HW_RXTX_RATE_MCS7 */
+	6,                            /* CONF_HW_RXTX_RATE_MCS6 */
+	5,                            /* CONF_HW_RXTX_RATE_MCS5 */
+	4,                            /* CONF_HW_RXTX_RATE_MCS4 */
+	3,                            /* CONF_HW_RXTX_RATE_MCS3 */
+	2,                            /* CONF_HW_RXTX_RATE_MCS2 */
+	1,                            /* CONF_HW_RXTX_RATE_MCS1 */
+	0,                            /* CONF_HW_RXTX_RATE_MCS0 */
 
 	11,                            /* CONF_HW_RXTX_RATE_54   */
 	10,                            /* CONF_HW_RXTX_RATE_48   */
@@ -2137,6 +2189,7 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
 /* 11n STA capabilities */
 #define HW_RX_HIGHEST_RATE	72
 
+#ifdef CONFIG_WL1271_HT
 #define WL1271_HT_CAP { \
 	.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \
 	.ht_supported = true, \
@@ -2148,6 +2201,11 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
 		.tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
 		}, \
 }
+#else
+#define WL1271_HT_CAP { \
+	.ht_supported = false, \
+}
+#endif
 
 /* can't be const, mac80211 writes to this */
 static struct ieee80211_supported_band wl1271_band_2ghz = {
@@ -2155,6 +2213,7 @@ static struct ieee80211_supported_band wl1271_band_2ghz = {
 	.n_channels = ARRAY_SIZE(wl1271_channels),
 	.bitrates = wl1271_rates,
 	.n_bitrates = ARRAY_SIZE(wl1271_rates),
+	.ht_cap	= WL1271_HT_CAP,
 };
 
 /* 5 GHz data rates for WL1273 */
@@ -2237,14 +2296,14 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = {
 /* mapping to indexes for wl1271_rates_5ghz */
 static const u8 wl1271_rate_to_idx_5ghz[] = {
 	/* MCS rates are used only with 11n */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */
-	CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */
+	7,                            /* CONF_HW_RXTX_RATE_MCS7 */
+	6,                            /* CONF_HW_RXTX_RATE_MCS6 */
+	5,                            /* CONF_HW_RXTX_RATE_MCS5 */
+	4,                            /* CONF_HW_RXTX_RATE_MCS4 */
+	3,                            /* CONF_HW_RXTX_RATE_MCS3 */
+	2,                            /* CONF_HW_RXTX_RATE_MCS2 */
+	1,                            /* CONF_HW_RXTX_RATE_MCS1 */
+	0,                            /* CONF_HW_RXTX_RATE_MCS0 */
 
 	7,                             /* CONF_HW_RXTX_RATE_54   */
 	6,                             /* CONF_HW_RXTX_RATE_48   */
@@ -2269,6 +2328,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = {
 	.n_channels = ARRAY_SIZE(wl1271_channels_5ghz),
 	.bitrates = wl1271_rates_5ghz,
 	.n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
+	.ht_cap	= WL1271_HT_CAP,
 };
 
 static const u8 *wl1271_band_rate_to_idx[] = {
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index bea133b..ac13f7d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -53,6 +53,12 @@ static void wl1271_rx_status(struct wl1271 *wl,
 	status->band = wl->band;
 	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;
 
 	/*
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index e3dc13c..6a87633 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -201,6 +201,17 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
 		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;
 }
 
-- 
1.6.6.1