aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/cfp.c
diff options
context:
space:
mode:
authorBing Zhao <bzhao@marvell.com>2011-03-21 21:00:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-03-30 14:15:17 -0400
commit5e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4e (patch)
treede22c4c414412501e62894de65040bf30db28c64 /drivers/net/wireless/mwifiex/cfp.c
parent903946e6e21ef4dd678acafb8881cabde9182caf (diff)
wireless: mwifiex: initial commit for Marvell mwifiex driver
This driver adds WiFi support for Marvell 802.11n based chipsets with SDIO interface. Currently only SD8787 is supported. More chipsets will be supported later. drivers/net/wireless/mwifiex/ Signed-off-by: Nishant Sarmukadam <nishants@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Kiran Divekar <dkiran@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com> Signed-off-by: Marc Yang <yangyang@marvell.com> Signed-off-by: Ramesh Radhakrishnan <rramesh@marvell.com> Signed-off-by: Frank Huang <frankh@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwifiex/cfp.c')
-rw-r--r--drivers/net/wireless/mwifiex/cfp.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
new file mode 100644
index 000000000000..999ed81512fa
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/cfp.c
@@ -0,0 +1,368 @@
1/*
2 * Marvell Wireless LAN device driver: Channel, Frequence and Power
3 *
4 * Copyright (C) 2011, Marvell International Ltd.
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#include "decl.h"
21#include "ioctl.h"
22#include "util.h"
23#include "fw.h"
24#include "main.h"
25#include "cfg80211.h"
26
27/* 100mW */
28#define MWIFIEX_TX_PWR_DEFAULT 20
29/* 100mW */
30#define MWIFIEX_TX_PWR_US_DEFAULT 20
31/* 50mW */
32#define MWIFIEX_TX_PWR_JP_DEFAULT 16
33/* 100mW */
34#define MWIFIEX_TX_PWR_FR_100MW 20
35/* 10mW */
36#define MWIFIEX_TX_PWR_FR_10MW 10
37/* 100mW */
38#define MWIFIEX_TX_PWR_EMEA_DEFAULT 20
39
40static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
41
42static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
43 0xb0, 0x48, 0x60, 0x6c, 0 };
44
45static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96,
46 0x0c, 0x12, 0x18, 0x24,
47 0x30, 0x48, 0x60, 0x6c, 0 };
48
49static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
50 0xb0, 0x48, 0x60, 0x6c, 0 };
51u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
52 0xb0, 0x48, 0x60, 0x6c, 0 };
53static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,
54 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18,
55 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
56 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68,
57 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51,
58 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 };
59
60u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };
61
62u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
63 0x30, 0x48, 0x60, 0x6c, 0 };
64
65u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
66 0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
67 0x60, 0x6c, 0 };
68
69u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30,
70 0x32, 0x40, 0x41, 0xff };
71
72u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
73
74/*
75 * This function maps an index in supported rates table into
76 * the corresponding data rate.
77 */
78u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index,
79 u8 ht_info)
80{
81 u16 mcs_rate[4][8] = {
82 {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e}
83 , /* LG 40M */
84 {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c}
85 , /* SG 40M */
86 {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82}
87 , /* LG 20M */
88 {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90}
89 }; /* SG 20M */
90
91 u32 rate;
92
93 if (ht_info & BIT(0)) {
94 if (index == MWIFIEX_RATE_BITMAP_MCS0) {
95 if (ht_info & BIT(2))
96 rate = 0x0D; /* MCS 32 SGI rate */
97 else
98 rate = 0x0C; /* MCS 32 LGI rate */
99 } else if (index < 8) {
100 if (ht_info & BIT(1)) {
101 if (ht_info & BIT(2))
102 /* SGI, 40M */
103 rate = mcs_rate[1][index];
104 else
105 /* LGI, 40M */
106 rate = mcs_rate[0][index];
107 } else {
108 if (ht_info & BIT(2))
109 /* SGI, 20M */
110 rate = mcs_rate[3][index];
111 else
112 /* LGI, 20M */
113 rate = mcs_rate[2][index];
114 }
115 } else
116 rate = mwifiex_data_rates[0];
117 } else {
118 if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
119 index = 0;
120 rate = mwifiex_data_rates[index];
121 }
122 return rate;
123}
124
125/*
126 * This function maps a data rate value into corresponding index in supported
127 * rates table.
128 */
129u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate)
130{
131 u16 *ptr;
132
133 if (rate) {
134 ptr = memchr(mwifiex_data_rates, rate,
135 sizeof(mwifiex_data_rates));
136 if (ptr)
137 return (u8) (ptr - mwifiex_data_rates);
138 }
139 return 0;
140}
141
142/*
143 * This function returns the current active data rates.
144 *
145 * The result may vary depending upon connection status.
146 */
147u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates)
148{
149 u32 k;
150
151 if (!priv->media_connected)
152 k = mwifiex_get_supported_rates(priv, rates);
153 else
154 k = mwifiex_copy_rates(rates, 0,
155 priv->curr_bss_params.data_rates,
156 priv->curr_bss_params.num_of_rates);
157
158 return k;
159}
160
161/*
162 * This function locates the Channel-Frequency-Power triplet based upon
163 * band and channel parameters.
164 */
165struct mwifiex_chan_freq_power *
166mwifiex_get_cfp_by_band_and_channel_from_cfg80211(struct mwifiex_private
167 *priv, u8 band, u16 channel)
168{
169 struct mwifiex_chan_freq_power *cfp = NULL;
170 struct ieee80211_supported_band *sband;
171 struct ieee80211_channel *ch;
172 int i;
173
174 if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG)
175 sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
176 else
177 sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
178
179 if (!sband) {
180 dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
181 " & channel %d\n", __func__, band, channel);
182 return cfp;
183 }
184
185 for (i = 0; i < sband->n_channels; i++) {
186 ch = &sband->channels[i];
187 if (((ch->hw_value == channel) ||
188 (channel == FIRST_VALID_CHANNEL))
189 && !(ch->flags & IEEE80211_CHAN_DISABLED)) {
190 priv->cfp.channel = channel;
191 priv->cfp.freq = ch->center_freq;
192 priv->cfp.max_tx_power = ch->max_power;
193 cfp = &priv->cfp;
194 break;
195 }
196 }
197 if (i == sband->n_channels)
198 dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
199 " & channel %d\n", __func__, band, channel);
200
201 return cfp;
202}
203
204/*
205 * This function locates the Channel-Frequency-Power triplet based upon
206 * band and frequency parameters.
207 */
208struct mwifiex_chan_freq_power *
209mwifiex_get_cfp_by_band_and_freq_from_cfg80211(struct mwifiex_private *priv,
210 u8 band, u32 freq)
211{
212 struct mwifiex_chan_freq_power *cfp = NULL;
213 struct ieee80211_supported_band *sband;
214 struct ieee80211_channel *ch;
215 int i;
216
217 if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG)
218 sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
219 else
220 sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
221
222 if (!sband) {
223 dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
224 " & freq %d\n", __func__, band, freq);
225 return cfp;
226 }
227
228 for (i = 0; i < sband->n_channels; i++) {
229 ch = &sband->channels[i];
230 if ((ch->center_freq == freq) &&
231 !(ch->flags & IEEE80211_CHAN_DISABLED)) {
232 priv->cfp.channel = ch->hw_value;
233 priv->cfp.freq = freq;
234 priv->cfp.max_tx_power = ch->max_power;
235 cfp = &priv->cfp;
236 break;
237 }
238 }
239 if (i == sband->n_channels)
240 dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
241 " & freq %d\n", __func__, band, freq);
242
243 return cfp;
244}
245
246/*
247 * This function checks if the data rate is set to auto.
248 */
249u8
250mwifiex_is_rate_auto(struct mwifiex_private *priv)
251{
252 u32 i;
253 int rate_num = 0;
254
255 for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++)
256 if (priv->bitmap_rates[i])
257 rate_num++;
258
259 if (rate_num > 1)
260 return true;
261 else
262 return false;
263}
264
265/*
266 * This function converts rate bitmap into rate index.
267 */
268int
269mwifiex_get_rate_index(struct mwifiex_adapter *adapter, u16 *rate_bitmap,
270 int size)
271{
272 int i;
273
274 for (i = 0; i < size * 8; i++)
275 if (rate_bitmap[i / 16] & (1 << (i % 16)))
276 return i;
277
278 return 0;
279}
280
281/*
282 * This function gets the supported data rates.
283 *
284 * The function works in both Ad-Hoc and infra mode by printing the
285 * band and returning the data rates.
286 */
287u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
288{
289 u32 k = 0;
290 struct mwifiex_adapter *adapter = priv->adapter;
291 if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) {
292 /* Infra. mode */
293 switch (adapter->config_bands) {
294 case BAND_B:
295 dev_dbg(adapter->dev, "info: infra band=%d "
296 "supported_rates_b\n", adapter->config_bands);
297 k = mwifiex_copy_rates(rates, k, supported_rates_b,
298 sizeof(supported_rates_b));
299 break;
300 case BAND_G:
301 case BAND_G | BAND_GN:
302 dev_dbg(adapter->dev, "info: infra band=%d "
303 "supported_rates_g\n", adapter->config_bands);
304 k = mwifiex_copy_rates(rates, k, supported_rates_g,
305 sizeof(supported_rates_g));
306 break;
307 case BAND_B | BAND_G:
308 case BAND_A | BAND_B | BAND_G:
309 case BAND_A | BAND_B:
310 case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
311 case BAND_B | BAND_G | BAND_GN:
312 dev_dbg(adapter->dev, "info: infra band=%d "
313 "supported_rates_bg\n", adapter->config_bands);
314 k = mwifiex_copy_rates(rates, k, supported_rates_bg,
315 sizeof(supported_rates_bg));
316 break;
317 case BAND_A:
318 case BAND_A | BAND_G:
319 dev_dbg(adapter->dev, "info: infra band=%d "
320 "supported_rates_a\n", adapter->config_bands);
321 k = mwifiex_copy_rates(rates, k, supported_rates_a,
322 sizeof(supported_rates_a));
323 break;
324 case BAND_A | BAND_AN:
325 case BAND_A | BAND_G | BAND_AN | BAND_GN:
326 dev_dbg(adapter->dev, "info: infra band=%d "
327 "supported_rates_a\n", adapter->config_bands);
328 k = mwifiex_copy_rates(rates, k, supported_rates_a,
329 sizeof(supported_rates_a));
330 break;
331 case BAND_GN:
332 dev_dbg(adapter->dev, "info: infra band=%d "
333 "supported_rates_n\n", adapter->config_bands);
334 k = mwifiex_copy_rates(rates, k, supported_rates_n,
335 sizeof(supported_rates_n));
336 break;
337 }
338 } else {
339 /* Ad-hoc mode */
340 switch (adapter->adhoc_start_band) {
341 case BAND_B:
342 dev_dbg(adapter->dev, "info: adhoc B\n");
343 k = mwifiex_copy_rates(rates, k, adhoc_rates_b,
344 sizeof(adhoc_rates_b));
345 break;
346 case BAND_G:
347 case BAND_G | BAND_GN:
348 dev_dbg(adapter->dev, "info: adhoc G only\n");
349 k = mwifiex_copy_rates(rates, k, adhoc_rates_g,
350 sizeof(adhoc_rates_g));
351 break;
352 case BAND_B | BAND_G:
353 case BAND_B | BAND_G | BAND_GN:
354 dev_dbg(adapter->dev, "info: adhoc BG\n");
355 k = mwifiex_copy_rates(rates, k, adhoc_rates_bg,
356 sizeof(adhoc_rates_bg));
357 break;
358 case BAND_A:
359 case BAND_A | BAND_AN:
360 dev_dbg(adapter->dev, "info: adhoc A\n");
361 k = mwifiex_copy_rates(rates, k, adhoc_rates_a,
362 sizeof(adhoc_rates_a));
363 break;
364 }
365 }
366
367 return k;
368}