aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r--drivers/net/wireless/libertas/scan.c273
1 files changed, 209 insertions, 64 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 6c95af3023cc..24cd54b3a806 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -4,6 +4,7 @@
4 * IOCTL handlers as well as command preperation and response routines 4 * IOCTL handlers as well as command preperation and response routines
5 * for sending scan commands to the firmware. 5 * for sending scan commands to the firmware.
6 */ 6 */
7#include <linux/slab.h>
7#include <linux/types.h> 8#include <linux/types.h>
8#include <linux/kernel.h> 9#include <linux/kernel.h>
9#include <linux/etherdevice.h> 10#include <linux/etherdevice.h>
@@ -12,18 +13,19 @@
12#include <net/lib80211.h> 13#include <net/lib80211.h>
13 14
14#include "host.h" 15#include "host.h"
15#include "decl.h"
16#include "dev.h" 16#include "dev.h"
17#include "scan.h" 17#include "scan.h"
18#include "assoc.h"
19#include "wext.h"
18#include "cmd.h" 20#include "cmd.h"
19 21
20//! Approximate amount of data needed to pass a scan result back to iwlist 22//! Approximate amount of data needed to pass a scan result back to iwlist
21#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ 23#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
22 + IW_ESSID_MAX_SIZE \ 24 + IEEE80211_MAX_SSID_LEN \
23 + IW_EV_UINT_LEN \ 25 + IW_EV_UINT_LEN \
24 + IW_EV_FREQ_LEN \ 26 + IW_EV_FREQ_LEN \
25 + IW_EV_QUAL_LEN \ 27 + IW_EV_QUAL_LEN \
26 + IW_ESSID_MAX_SIZE \ 28 + IEEE80211_MAX_SSID_LEN \
27 + IW_EV_PARAM_LEN \ 29 + IW_EV_PARAM_LEN \
28 + 40) /* 40 for WPAIE */ 30 + 40) /* 40 for WPAIE */
29 31
@@ -121,6 +123,189 @@ static inline int is_same_network(struct bss_descriptor *src,
121 123
122 124
123 125
126/*********************************************************************/
127/* */
128/* Region channel support */
129/* */
130/*********************************************************************/
131
132#define LBS_TX_PWR_DEFAULT 20 /*100mW */
133#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
134#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
135#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */
136#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */
137
138/* Format { channel, frequency (MHz), maxtxpower } */
139/* band: 'B/G', region: USA FCC/Canada IC */
140static struct chan_freq_power channel_freq_power_US_BG[] = {
141 {1, 2412, LBS_TX_PWR_US_DEFAULT},
142 {2, 2417, LBS_TX_PWR_US_DEFAULT},
143 {3, 2422, LBS_TX_PWR_US_DEFAULT},
144 {4, 2427, LBS_TX_PWR_US_DEFAULT},
145 {5, 2432, LBS_TX_PWR_US_DEFAULT},
146 {6, 2437, LBS_TX_PWR_US_DEFAULT},
147 {7, 2442, LBS_TX_PWR_US_DEFAULT},
148 {8, 2447, LBS_TX_PWR_US_DEFAULT},
149 {9, 2452, LBS_TX_PWR_US_DEFAULT},
150 {10, 2457, LBS_TX_PWR_US_DEFAULT},
151 {11, 2462, LBS_TX_PWR_US_DEFAULT}
152};
153
154/* band: 'B/G', region: Europe ETSI */
155static struct chan_freq_power channel_freq_power_EU_BG[] = {
156 {1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
157 {2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
158 {3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
159 {4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
160 {5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
161 {6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
162 {7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
163 {8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
164 {9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
165 {10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
166 {11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
167 {12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
168 {13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
169};
170
171/* band: 'B/G', region: Spain */
172static struct chan_freq_power channel_freq_power_SPN_BG[] = {
173 {10, 2457, LBS_TX_PWR_DEFAULT},
174 {11, 2462, LBS_TX_PWR_DEFAULT}
175};
176
177/* band: 'B/G', region: France */
178static struct chan_freq_power channel_freq_power_FR_BG[] = {
179 {10, 2457, LBS_TX_PWR_FR_DEFAULT},
180 {11, 2462, LBS_TX_PWR_FR_DEFAULT},
181 {12, 2467, LBS_TX_PWR_FR_DEFAULT},
182 {13, 2472, LBS_TX_PWR_FR_DEFAULT}
183};
184
185/* band: 'B/G', region: Japan */
186static struct chan_freq_power channel_freq_power_JPN_BG[] = {
187 {1, 2412, LBS_TX_PWR_JP_DEFAULT},
188 {2, 2417, LBS_TX_PWR_JP_DEFAULT},
189 {3, 2422, LBS_TX_PWR_JP_DEFAULT},
190 {4, 2427, LBS_TX_PWR_JP_DEFAULT},
191 {5, 2432, LBS_TX_PWR_JP_DEFAULT},
192 {6, 2437, LBS_TX_PWR_JP_DEFAULT},
193 {7, 2442, LBS_TX_PWR_JP_DEFAULT},
194 {8, 2447, LBS_TX_PWR_JP_DEFAULT},
195 {9, 2452, LBS_TX_PWR_JP_DEFAULT},
196 {10, 2457, LBS_TX_PWR_JP_DEFAULT},
197 {11, 2462, LBS_TX_PWR_JP_DEFAULT},
198 {12, 2467, LBS_TX_PWR_JP_DEFAULT},
199 {13, 2472, LBS_TX_PWR_JP_DEFAULT},
200 {14, 2484, LBS_TX_PWR_JP_DEFAULT}
201};
202
203/**
204 * the structure for channel, frequency and power
205 */
206struct region_cfp_table {
207 u8 region;
208 struct chan_freq_power *cfp_BG;
209 int cfp_no_BG;
210};
211
212/**
213 * the structure for the mapping between region and CFP
214 */
215static struct region_cfp_table region_cfp_table[] = {
216 {0x10, /*US FCC */
217 channel_freq_power_US_BG,
218 ARRAY_SIZE(channel_freq_power_US_BG),
219 }
220 ,
221 {0x20, /*CANADA IC */
222 channel_freq_power_US_BG,
223 ARRAY_SIZE(channel_freq_power_US_BG),
224 }
225 ,
226 {0x30, /*EU*/ channel_freq_power_EU_BG,
227 ARRAY_SIZE(channel_freq_power_EU_BG),
228 }
229 ,
230 {0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
231 ARRAY_SIZE(channel_freq_power_SPN_BG),
232 }
233 ,
234 {0x32, /*FRANCE*/ channel_freq_power_FR_BG,
235 ARRAY_SIZE(channel_freq_power_FR_BG),
236 }
237 ,
238 {0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
239 ARRAY_SIZE(channel_freq_power_JPN_BG),
240 }
241 ,
242/*Add new region here */
243};
244
245/**
246 * @brief This function finds the CFP in
247 * region_cfp_table based on region and band parameter.
248 *
249 * @param region The region code
250 * @param band The band
251 * @param cfp_no A pointer to CFP number
252 * @return A pointer to CFP
253 */
254static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
255{
256 int i, end;
257
258 lbs_deb_enter(LBS_DEB_MAIN);
259
260 end = ARRAY_SIZE(region_cfp_table);
261
262 for (i = 0; i < end ; i++) {
263 lbs_deb_main("region_cfp_table[i].region=%d\n",
264 region_cfp_table[i].region);
265 if (region_cfp_table[i].region == region) {
266 *cfp_no = region_cfp_table[i].cfp_no_BG;
267 lbs_deb_leave(LBS_DEB_MAIN);
268 return region_cfp_table[i].cfp_BG;
269 }
270 }
271
272 lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
273 return NULL;
274}
275
276int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
277{
278 int ret = 0;
279 int i = 0;
280
281 struct chan_freq_power *cfp;
282 int cfp_no;
283
284 lbs_deb_enter(LBS_DEB_MAIN);
285
286 memset(priv->region_channel, 0, sizeof(priv->region_channel));
287
288 cfp = lbs_get_region_cfp_table(region, &cfp_no);
289 if (cfp != NULL) {
290 priv->region_channel[i].nrcfp = cfp_no;
291 priv->region_channel[i].CFP = cfp;
292 } else {
293 lbs_deb_main("wrong region code %#x in band B/G\n",
294 region);
295 ret = -1;
296 goto out;
297 }
298 priv->region_channel[i].valid = 1;
299 priv->region_channel[i].region = region;
300 priv->region_channel[i].band = band;
301 i++;
302out:
303 lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
304 return ret;
305}
306
307
308
124 309
125/*********************************************************************/ 310/*********************************************************************/
126/* */ 311/* */
@@ -161,31 +346,15 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
161 scantype = CMD_SCAN_TYPE_ACTIVE; 346 scantype = CMD_SCAN_TYPE_ACTIVE;
162 347
163 for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { 348 for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
164 if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) 349 if (!priv->region_channel[rgnidx].valid)
165 && (priv->mesh_connect_status != LBS_CONNECTED)) { 350 continue;
166 /* Scan all the supported chan for the first scan */ 351 scanregion = &priv->region_channel[rgnidx];
167 if (!priv->universal_channel[rgnidx].valid)
168 continue;
169 scanregion = &priv->universal_channel[rgnidx];
170
171 /* clear the parsed_region_chan for the first scan */
172 memset(&priv->parsed_region_chan, 0x00,
173 sizeof(priv->parsed_region_chan));
174 } else {
175 if (!priv->region_channel[rgnidx].valid)
176 continue;
177 scanregion = &priv->region_channel[rgnidx];
178 }
179 352
180 for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { 353 for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
181 struct chanscanparamset *chan = &scanchanlist[chanidx]; 354 struct chanscanparamset *chan = &scanchanlist[chanidx];
182 355
183 cfp = scanregion->CFP + nextchan; 356 cfp = scanregion->CFP + nextchan;
184 357
185 if (priv->enable11d)
186 scantype = lbs_get_scan_type_11d(cfp->channel,
187 &priv->parsed_region_chan);
188
189 if (scanregion->band == BAND_B || scanregion->band == BAND_G) 358 if (scanregion->band == BAND_B || scanregion->band == BAND_G)
190 chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; 359 chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
191 360
@@ -399,11 +568,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan)
399 chan_count = lbs_scan_create_channel_list(priv, chan_list); 568 chan_count = lbs_scan_create_channel_list(priv, chan_list);
400 569
401 netif_stop_queue(priv->dev); 570 netif_stop_queue(priv->dev);
402 netif_carrier_off(priv->dev); 571 if (priv->mesh_dev)
403 if (priv->mesh_dev) {
404 netif_stop_queue(priv->mesh_dev); 572 netif_stop_queue(priv->mesh_dev);
405 netif_carrier_off(priv->mesh_dev);
406 }
407 573
408 /* Prepare to continue an interrupted scan */ 574 /* Prepare to continue an interrupted scan */
409 lbs_deb_scan("chan_count %d, scan_channel %d\n", 575 lbs_deb_scan("chan_count %d, scan_channel %d\n",
@@ -467,16 +633,13 @@ out2:
467 priv->scan_channel = 0; 633 priv->scan_channel = 0;
468 634
469out: 635out:
470 if (priv->connect_status == LBS_CONNECTED) { 636 if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
471 netif_carrier_on(priv->dev); 637 netif_wake_queue(priv->dev);
472 if (!priv->tx_pending_len) 638
473 netif_wake_queue(priv->dev); 639 if (priv->mesh_dev && lbs_mesh_connected(priv) &&
474 } 640 !priv->tx_pending_len)
475 if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) { 641 netif_wake_queue(priv->mesh_dev);
476 netif_carrier_on(priv->mesh_dev); 642
477 if (!priv->tx_pending_len)
478 netif_wake_queue(priv->mesh_dev);
479 }
480 kfree(chan_list); 643 kfree(chan_list);
481 644
482 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); 645 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
@@ -519,7 +682,6 @@ static int lbs_process_bss(struct bss_descriptor *bss,
519 struct ieee_ie_cf_param_set *cf; 682 struct ieee_ie_cf_param_set *cf;
520 struct ieee_ie_ibss_param_set *ibss; 683 struct ieee_ie_ibss_param_set *ibss;
521 DECLARE_SSID_BUF(ssid); 684 DECLARE_SSID_BUF(ssid);
522 struct ieee_ie_country_info_set *pcountryinfo;
523 uint8_t *pos, *end, *p; 685 uint8_t *pos, *end, *p;
524 uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; 686 uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
525 uint16_t beaconsize = 0; 687 uint16_t beaconsize = 0;
@@ -642,26 +804,6 @@ static int lbs_process_bss(struct bss_descriptor *bss,
642 lbs_deb_scan("got IBSS IE\n"); 804 lbs_deb_scan("got IBSS IE\n");
643 break; 805 break;
644 806
645 case WLAN_EID_COUNTRY:
646 pcountryinfo = (struct ieee_ie_country_info_set *) pos;
647 lbs_deb_scan("got COUNTRY IE\n");
648 if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode)
649 || pcountryinfo->header.len > 254) {
650 lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n",
651 __func__,
652 pcountryinfo->header.len,
653 sizeof(pcountryinfo->countrycode));
654 ret = -1;
655 goto done;
656 }
657
658 memcpy(&bss->countryinfo, pcountryinfo,
659 pcountryinfo->header.len + 2);
660 lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
661 (uint8_t *) pcountryinfo,
662 (int) (pcountryinfo->header.len + 2));
663 break;
664
665 case WLAN_EID_EXT_SUPP_RATES: 807 case WLAN_EID_EXT_SUPP_RATES:
666 /* only process extended supported rate if data rate is 808 /* only process extended supported rate if data rate is
667 * already found. Data rate IE should come before 809 * already found. Data rate IE should come before
@@ -812,7 +954,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
812 /* SSID */ 954 /* SSID */
813 iwe.cmd = SIOCGIWESSID; 955 iwe.cmd = SIOCGIWESSID;
814 iwe.u.data.flags = 1; 956 iwe.u.data.flags = 1;
815 iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); 957 iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN);
816 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); 958 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
817 959
818 /* Mode */ 960 /* Mode */
@@ -1022,9 +1164,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1022 return -EAGAIN; 1164 return -EAGAIN;
1023 1165
1024 /* Update RSSI if current BSS is a locally created ad-hoc BSS */ 1166 /* Update RSSI if current BSS is a locally created ad-hoc BSS */
1025 if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) 1167 if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
1026 lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, 1168 err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
1027 CMD_OPTION_WAITFORRSP, 0, NULL); 1169 CMD_OPTION_WAITFORRSP, 0, NULL);
1170 if (err)
1171 goto out;
1172 }
1028 1173
1029 mutex_lock(&priv->lock); 1174 mutex_lock(&priv->lock);
1030 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { 1175 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
@@ -1058,7 +1203,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1058 1203
1059 dwrq->length = (ev - extra); 1204 dwrq->length = (ev - extra);
1060 dwrq->flags = 0; 1205 dwrq->flags = 0;
1061 1206out:
1062 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); 1207 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
1063 return err; 1208 return err;
1064} 1209}
@@ -1141,11 +1286,11 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
1141 /* The size of the TLV buffer is equal to the entire command response 1286 /* The size of the TLV buffer is equal to the entire command response
1142 * size (scanrespsize) minus the fixed fields (sizeof()'s), the 1287 * size (scanrespsize) minus the fixed fields (sizeof()'s), the
1143 * BSS Descriptions (bssdescriptsize as bytesLef) and the command 1288 * BSS Descriptions (bssdescriptsize as bytesLef) and the command
1144 * response header (S_DS_GEN) 1289 * response header (sizeof(struct cmd_header))
1145 */ 1290 */
1146 tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) 1291 tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
1147 + sizeof(scanresp->nr_sets) 1292 + sizeof(scanresp->nr_sets)
1148 + S_DS_GEN); 1293 + sizeof(struct cmd_header));
1149 1294
1150 /* 1295 /*
1151 * Process each scan response returned (scanresp->nr_sets). Save 1296 * Process each scan response returned (scanresp->nr_sets). Save