aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2008-10-13 12:13:56 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-10-13 12:13:56 -0400
commite758936e02700ff88a0b08b722a3847b95283ef2 (patch)
tree50c919bef1b459a778b85159d5929de95b6c4a01 /drivers/net/wireless/libertas
parent239cfbde1f5843c4a24199f117d5f67f637d72d5 (diff)
parent4480f15b3306f43bbb0310d461142b4e897ca45b (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: include/asm-x86/statfs.h
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/assoc.c750
-rw-r--r--drivers/net/wireless/libertas/assoc.h18
-rw-r--r--drivers/net/wireless/libertas/cmd.c430
-rw-r--r--drivers/net/wireless/libertas/cmd.h22
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c80
-rw-r--r--drivers/net/wireless/libertas/decl.h1
-rw-r--r--drivers/net/wireless/libertas/defs.h41
-rw-r--r--drivers/net/wireless/libertas/dev.h11
-rw-r--r--drivers/net/wireless/libertas/host.h51
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h84
-rw-r--r--drivers/net/wireless/libertas/if_cs.c15
-rw-r--r--drivers/net/wireless/libertas/if_usb.c182
-rw-r--r--drivers/net/wireless/libertas/if_usb.h5
-rw-r--r--drivers/net/wireless/libertas/main.c41
-rw-r--r--drivers/net/wireless/libertas/scan.c5
-rw-r--r--drivers/net/wireless/libertas/wext.c363
16 files changed, 1098 insertions, 1001 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index a267d6e65f03..92be60415d04 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -8,6 +8,7 @@
8#include "scan.h" 8#include "scan.h"
9#include "cmd.h" 9#include "cmd.h"
10 10
11static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp);
11 12
12static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = 13static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
13 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 14 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -20,12 +21,88 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
20#define CAPINFO_MASK (~(0xda00)) 21#define CAPINFO_MASK (~(0xda00))
21 22
22 23
24/**
25 * @brief This function finds common rates between rates and card rates.
26 *
27 * It will fill common rates in rates as output if found.
28 *
29 * NOTE: Setting the MSB of the basic rates need to be taken
30 * care, either before or after calling this function
31 *
32 * @param priv A pointer to struct lbs_private structure
33 * @param rates the buffer which keeps input and output
34 * @param rates_size the size of rate1 buffer; new size of buffer on return
35 *
36 * @return 0 on success, or -1 on error
37 */
38static int get_common_rates(struct lbs_private *priv,
39 u8 *rates,
40 u16 *rates_size)
41{
42 u8 *card_rates = lbs_bg_rates;
43 size_t num_card_rates = sizeof(lbs_bg_rates);
44 int ret = 0, i, j;
45 u8 tmp[30];
46 size_t tmp_size = 0;
47
48 /* For each rate in card_rates that exists in rate1, copy to tmp */
49 for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
50 for (j = 0; rates[j] && (j < *rates_size); j++) {
51 if (rates[j] == card_rates[i])
52 tmp[tmp_size++] = card_rates[i];
53 }
54 }
55
56 lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
57 lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
58 lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
59 lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
60
61 if (!priv->enablehwauto) {
62 for (i = 0; i < tmp_size; i++) {
63 if (tmp[i] == priv->cur_rate)
64 goto done;
65 }
66 lbs_pr_alert("Previously set fixed data rate %#x isn't "
67 "compatible with the network.\n", priv->cur_rate);
68 ret = -1;
69 goto done;
70 }
71 ret = 0;
72
73done:
74 memset(rates, 0, *rates_size);
75 *rates_size = min_t(int, tmp_size, *rates_size);
76 memcpy(rates, tmp, *rates_size);
77 return ret;
78}
79
80
81/**
82 * @brief Sets the MSB on basic rates as the firmware requires
83 *
84 * Scan through an array and set the MSB for basic data rates.
85 *
86 * @param rates buffer of data rates
87 * @param len size of buffer
88 */
89static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
90{
91 int i;
92
93 for (i = 0; i < len; i++) {
94 if (rates[i] == 0x02 || rates[i] == 0x04 ||
95 rates[i] == 0x0b || rates[i] == 0x16)
96 rates[i] |= 0x80;
97 }
98}
99
23 100
24/** 101/**
25 * @brief Associate to a specific BSS discovered in a scan 102 * @brief Associate to a specific BSS discovered in a scan
26 * 103 *
27 * @param priv A pointer to struct lbs_private structure 104 * @param priv A pointer to struct lbs_private structure
28 * @param pbssdesc Pointer to the BSS descriptor to associate with. 105 * @param assoc_req The association request describing the BSS to associate with
29 * 106 *
30 * @return 0-success, otherwise fail 107 * @return 0-success, otherwise fail
31 */ 108 */
@@ -33,29 +110,29 @@ static int lbs_associate(struct lbs_private *priv,
33 struct assoc_request *assoc_req) 110 struct assoc_request *assoc_req)
34{ 111{
35 int ret; 112 int ret;
113 u8 preamble = RADIO_PREAMBLE_LONG;
36 114
37 lbs_deb_enter(LBS_DEB_ASSOC); 115 lbs_deb_enter(LBS_DEB_ASSOC);
38 116
39 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, 117 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
40 0, CMD_OPTION_WAITFORRSP, 118 0, CMD_OPTION_WAITFORRSP,
41 0, assoc_req->bss.bssid); 119 0, assoc_req->bss.bssid);
42
43 if (ret) 120 if (ret)
44 goto done; 121 goto out;
45 122
46 /* set preamble to firmware */ 123 /* Use short preamble only when both the BSS and firmware support it */
47 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && 124 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
48 (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) 125 (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
49 priv->preamble = CMD_TYPE_SHORT_PREAMBLE; 126 preamble = RADIO_PREAMBLE_SHORT;
50 else
51 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
52 127
53 lbs_set_radio_control(priv); 128 ret = lbs_set_radio(priv, preamble, 1);
129 if (ret)
130 goto out;
54 131
55 ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, 132 ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
56 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); 133 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
57 134
58done: 135out:
59 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); 136 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
60 return ret; 137 return ret;
61} 138}
@@ -64,17 +141,22 @@ done:
64 * @brief Join an adhoc network found in a previous scan 141 * @brief Join an adhoc network found in a previous scan
65 * 142 *
66 * @param priv A pointer to struct lbs_private structure 143 * @param priv A pointer to struct lbs_private structure
67 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan 144 * @param assoc_req The association request describing the BSS to join
68 * to attempt to join
69 * 145 *
70 * @return 0--success, -1--fail 146 * @return 0 on success, error on failure
71 */ 147 */
72static int lbs_join_adhoc_network(struct lbs_private *priv, 148static int lbs_adhoc_join(struct lbs_private *priv,
73 struct assoc_request *assoc_req) 149 struct assoc_request *assoc_req)
74{ 150{
151 struct cmd_ds_802_11_ad_hoc_join cmd;
75 struct bss_descriptor *bss = &assoc_req->bss; 152 struct bss_descriptor *bss = &assoc_req->bss;
153 u8 preamble = RADIO_PREAMBLE_LONG;
154 DECLARE_MAC_BUF(mac);
155 u16 ratesize = 0;
76 int ret = 0; 156 int ret = 0;
77 157
158 lbs_deb_enter(LBS_DEB_ASSOC);
159
78 lbs_deb_join("current SSID '%s', ssid length %u\n", 160 lbs_deb_join("current SSID '%s', ssid length %u\n",
79 escape_essid(priv->curbssparams.ssid, 161 escape_essid(priv->curbssparams.ssid,
80 priv->curbssparams.ssid_len), 162 priv->curbssparams.ssid_len),
@@ -106,29 +188,106 @@ static int lbs_join_adhoc_network(struct lbs_private *priv,
106 goto out; 188 goto out;
107 } 189 }
108 190
109 /* Use shortpreamble only when both creator and card supports 191 /* Use short preamble only when both the BSS and firmware support it */
110 short preamble */ 192 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
111 if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) || 193 (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
112 !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
113 lbs_deb_join("AdhocJoin: Long preamble\n");
114 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
115 } else {
116 lbs_deb_join("AdhocJoin: Short preamble\n"); 194 lbs_deb_join("AdhocJoin: Short preamble\n");
117 priv->preamble = CMD_TYPE_SHORT_PREAMBLE; 195 preamble = RADIO_PREAMBLE_SHORT;
118 } 196 }
119 197
120 lbs_set_radio_control(priv); 198 ret = lbs_set_radio(priv, preamble, 1);
199 if (ret)
200 goto out;
121 201
122 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); 202 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
123 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); 203 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
124 204
125 priv->adhoccreate = 0; 205 priv->adhoccreate = 0;
206 priv->curbssparams.channel = bss->channel;
126 207
127 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN, 208 /* Build the join command */
128 0, CMD_OPTION_WAITFORRSP, 209 memset(&cmd, 0, sizeof(cmd));
129 OID_802_11_SSID, assoc_req); 210 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
211
212 cmd.bss.type = CMD_BSS_TYPE_IBSS;
213 cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
214
215 memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
216 memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
217
218 memcpy(&cmd.bss.phyparamset, &bss->phyparamset,
219 sizeof(union ieeetypes_phyparamset));
220
221 memcpy(&cmd.bss.ssparamset, &bss->ssparamset,
222 sizeof(union IEEEtypes_ssparamset));
223
224 cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
225 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
226 bss->capability, CAPINFO_MASK);
227
228 /* information on BSSID descriptor passed to FW */
229 lbs_deb_join("ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
230 print_mac(mac, cmd.bss.bssid), cmd.bss.ssid);
231
232 /* Only v8 and below support setting these */
233 if (priv->fwrelease < 0x09000000) {
234 /* failtimeout */
235 cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
236 /* probedelay */
237 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
238 }
239
240 /* Copy Data rates from the rates recorded in scan response */
241 memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
242 ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES);
243 memcpy(cmd.bss.rates, bss->rates, ratesize);
244 if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
245 lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
246 ret = -1;
247 goto out;
248 }
249
250 /* Copy the ad-hoc creation rates into Current BSS state structure */
251 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
252 memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize);
253
254 /* Set MSB on basic rates as the firmware requires, but _after_
255 * copying to current bss rates.
256 */
257 lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
258
259 cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow);
260
261 if (assoc_req->secinfo.wep_enabled) {
262 u16 tmp = le16_to_cpu(cmd.bss.capability);
263 tmp |= WLAN_CAPABILITY_PRIVACY;
264 cmd.bss.capability = cpu_to_le16(tmp);
265 }
266
267 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
268 __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM);
269
270 /* wake up first */
271 ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
272 CMD_ACT_SET, 0, 0,
273 &local_ps_mode);
274 if (ret) {
275 ret = -1;
276 goto out;
277 }
278 }
279
280 if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
281 ret = -1;
282 goto out;
283 }
284
285 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
286 if (ret == 0)
287 ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
130 288
131out: 289out:
290 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
132 return ret; 291 return ret;
133} 292}
134 293
@@ -136,39 +295,131 @@ out:
136 * @brief Start an Adhoc Network 295 * @brief Start an Adhoc Network
137 * 296 *
138 * @param priv A pointer to struct lbs_private structure 297 * @param priv A pointer to struct lbs_private structure
139 * @param adhocssid The ssid of the Adhoc Network 298 * @param assoc_req The association request describing the BSS to start
140 * @return 0--success, -1--fail 299 *
300 * @return 0 on success, error on failure
141 */ 301 */
142static int lbs_start_adhoc_network(struct lbs_private *priv, 302static int lbs_adhoc_start(struct lbs_private *priv,
143 struct assoc_request *assoc_req) 303 struct assoc_request *assoc_req)
144{ 304{
305 struct cmd_ds_802_11_ad_hoc_start cmd;
306 u8 preamble = RADIO_PREAMBLE_LONG;
307 size_t ratesize = 0;
308 u16 tmpcap = 0;
145 int ret = 0; 309 int ret = 0;
146 310
147 priv->adhoccreate = 1; 311 lbs_deb_enter(LBS_DEB_ASSOC);
148 312
149 if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { 313 if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
150 lbs_deb_join("AdhocStart: Short preamble\n"); 314 lbs_deb_join("ADHOC_START: Will use short preamble\n");
151 priv->preamble = CMD_TYPE_SHORT_PREAMBLE; 315 preamble = RADIO_PREAMBLE_SHORT;
152 } else {
153 lbs_deb_join("AdhocStart: Long preamble\n");
154 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
155 } 316 }
156 317
157 lbs_set_radio_control(priv); 318 ret = lbs_set_radio(priv, preamble, 1);
319 if (ret)
320 goto out;
158 321
159 lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel); 322 /* Build the start command */
160 lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band); 323 memset(&cmd, 0, sizeof(cmd));
324 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
161 325
162 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START, 326 memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
163 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); 327
328 lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
329 escape_essid(assoc_req->ssid, assoc_req->ssid_len),
330 assoc_req->ssid_len);
331
332 cmd.bsstype = CMD_BSS_TYPE_IBSS;
333
334 if (priv->beacon_period == 0)
335 priv->beacon_period = MRVDRV_BEACON_INTERVAL;
336 cmd.beaconperiod = cpu_to_le16(priv->beacon_period);
337
338 WARN_ON(!assoc_req->channel);
339
340 /* set Physical parameter set */
341 cmd.phyparamset.dsparamset.elementid = MFIE_TYPE_DS_SET;
342 cmd.phyparamset.dsparamset.len = 1;
343 cmd.phyparamset.dsparamset.currentchan = assoc_req->channel;
344
345 /* set IBSS parameter set */
346 cmd.ssparamset.ibssparamset.elementid = MFIE_TYPE_IBSS_SET;
347 cmd.ssparamset.ibssparamset.len = 2;
348 cmd.ssparamset.ibssparamset.atimwindow = 0;
349
350 /* set capability info */
351 tmpcap = WLAN_CAPABILITY_IBSS;
352 if (assoc_req->secinfo.wep_enabled) {
353 lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n");
354 tmpcap |= WLAN_CAPABILITY_PRIVACY;
355 } else
356 lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n");
357
358 cmd.capability = cpu_to_le16(tmpcap);
359
360 /* Only v8 and below support setting probe delay */
361 if (priv->fwrelease < 0x09000000)
362 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
363
364 ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates));
365 memcpy(cmd.rates, lbs_bg_rates, ratesize);
366
367 /* Copy the ad-hoc creating rates into Current BSS state structure */
368 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
369 memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize);
164 370
371 /* Set MSB on basic rates as the firmware requires, but _after_
372 * copying to current bss rates.
373 */
374 lbs_set_basic_rate_flags(cmd.rates, ratesize);
375
376 lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
377 cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
378
379 if (lbs_create_dnld_countryinfo_11d(priv)) {
380 lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n");
381 ret = -1;
382 goto out;
383 }
384
385 lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
386 assoc_req->channel, assoc_req->band);
387
388 priv->adhoccreate = 1;
389 priv->mode = IW_MODE_ADHOC;
390
391 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
392 if (ret == 0)
393 ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
394
395out:
396 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
165 return ret; 397 return ret;
166} 398}
167 399
168int lbs_stop_adhoc_network(struct lbs_private *priv) 400/**
401 * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode
402 *
403 * @param priv A pointer to struct lbs_private structure
404 * @return 0 on success, or an error
405 */
406int lbs_adhoc_stop(struct lbs_private *priv)
169{ 407{
170 return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP, 408 struct cmd_ds_802_11_ad_hoc_stop cmd;
171 0, CMD_OPTION_WAITFORRSP, 0, NULL); 409 int ret;
410
411 lbs_deb_enter(LBS_DEB_JOIN);
412
413 memset(&cmd, 0, sizeof (cmd));
414 cmd.hdr.size = cpu_to_le16 (sizeof (cmd));
415
416 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
417
418 /* Clean up everything even if there was an error */
419 lbs_mac_event_disconnected(priv);
420
421 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
422 return ret;
172} 423}
173 424
174static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, 425static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
@@ -480,14 +731,14 @@ static int assoc_helper_essid(struct lbs_private *priv,
480 if (bss != NULL) { 731 if (bss != NULL) {
481 lbs_deb_assoc("SSID found, will join\n"); 732 lbs_deb_assoc("SSID found, will join\n");
482 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); 733 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
483 lbs_join_adhoc_network(priv, assoc_req); 734 lbs_adhoc_join(priv, assoc_req);
484 } else { 735 } else {
485 /* else send START command */ 736 /* else send START command */
486 lbs_deb_assoc("SSID not found, creating adhoc network\n"); 737 lbs_deb_assoc("SSID not found, creating adhoc network\n");
487 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, 738 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
488 IW_ESSID_MAX_SIZE); 739 IW_ESSID_MAX_SIZE);
489 assoc_req->bss.ssid_len = assoc_req->ssid_len; 740 assoc_req->bss.ssid_len = assoc_req->ssid_len;
490 lbs_start_adhoc_network(priv, assoc_req); 741 lbs_adhoc_start(priv, assoc_req);
491 } 742 }
492 } 743 }
493 744
@@ -520,7 +771,7 @@ static int assoc_helper_bssid(struct lbs_private *priv,
520 ret = lbs_associate(priv, assoc_req); 771 ret = lbs_associate(priv, assoc_req);
521 lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret); 772 lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret);
522 } else if (assoc_req->mode == IW_MODE_ADHOC) { 773 } else if (assoc_req->mode == IW_MODE_ADHOC) {
523 lbs_join_adhoc_network(priv, assoc_req); 774 lbs_adhoc_join(priv, assoc_req);
524 } 775 }
525 776
526out: 777out:
@@ -572,11 +823,7 @@ static int assoc_helper_mode(struct lbs_private *priv,
572 } 823 }
573 824
574 priv->mode = assoc_req->mode; 825 priv->mode = assoc_req->mode;
575 ret = lbs_prepare_and_send_command(priv, 826 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode);
576 CMD_802_11_SNMP_MIB,
577 0, CMD_OPTION_WAITFORRSP,
578 OID_802_11_INFRASTRUCTURE_MODE,
579 /* Shoot me now */ (void *) (size_t) assoc_req->mode);
580 827
581done: 828done:
582 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); 829 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -1029,7 +1276,9 @@ void lbs_association_worker(struct work_struct *work)
1029 */ 1276 */
1030 if (priv->mode == IW_MODE_INFRA) { 1277 if (priv->mode == IW_MODE_INFRA) {
1031 if (should_deauth_infrastructure(priv, assoc_req)) { 1278 if (should_deauth_infrastructure(priv, assoc_req)) {
1032 ret = lbs_send_deauthentication(priv); 1279 ret = lbs_cmd_80211_deauthenticate(priv,
1280 priv->curbssparams.bssid,
1281 WLAN_REASON_DEAUTH_LEAVING);
1033 if (ret) { 1282 if (ret) {
1034 lbs_deb_assoc("Deauthentication due to new " 1283 lbs_deb_assoc("Deauthentication due to new "
1035 "configuration request failed: %d\n", 1284 "configuration request failed: %d\n",
@@ -1038,7 +1287,7 @@ void lbs_association_worker(struct work_struct *work)
1038 } 1287 }
1039 } else if (priv->mode == IW_MODE_ADHOC) { 1288 } else if (priv->mode == IW_MODE_ADHOC) {
1040 if (should_stop_adhoc(priv, assoc_req)) { 1289 if (should_stop_adhoc(priv, assoc_req)) {
1041 ret = lbs_stop_adhoc_network(priv); 1290 ret = lbs_adhoc_stop(priv);
1042 if (ret) { 1291 if (ret) {
1043 lbs_deb_assoc("Teardown of AdHoc network due to " 1292 lbs_deb_assoc("Teardown of AdHoc network due to "
1044 "new configuration request failed: %d\n", 1293 "new configuration request failed: %d\n",
@@ -1214,94 +1463,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
1214 1463
1215 1464
1216/** 1465/**
1217 * @brief This function finds common rates between rate1 and card rates.
1218 *
1219 * It will fill common rates in rate1 as output if found.
1220 *
1221 * NOTE: Setting the MSB of the basic rates need to be taken
1222 * care, either before or after calling this function
1223 *
1224 * @param priv A pointer to struct lbs_private structure
1225 * @param rate1 the buffer which keeps input and output
1226 * @param rate1_size the size of rate1 buffer; new size of buffer on return
1227 *
1228 * @return 0 or -1
1229 */
1230static int get_common_rates(struct lbs_private *priv,
1231 u8 *rates,
1232 u16 *rates_size)
1233{
1234 u8 *card_rates = lbs_bg_rates;
1235 size_t num_card_rates = sizeof(lbs_bg_rates);
1236 int ret = 0, i, j;
1237 u8 tmp[30];
1238 size_t tmp_size = 0;
1239
1240 /* For each rate in card_rates that exists in rate1, copy to tmp */
1241 for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
1242 for (j = 0; rates[j] && (j < *rates_size); j++) {
1243 if (rates[j] == card_rates[i])
1244 tmp[tmp_size++] = card_rates[i];
1245 }
1246 }
1247
1248 lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
1249 lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
1250 lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
1251 lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
1252
1253 if (!priv->enablehwauto) {
1254 for (i = 0; i < tmp_size; i++) {
1255 if (tmp[i] == priv->cur_rate)
1256 goto done;
1257 }
1258 lbs_pr_alert("Previously set fixed data rate %#x isn't "
1259 "compatible with the network.\n", priv->cur_rate);
1260 ret = -1;
1261 goto done;
1262 }
1263 ret = 0;
1264
1265done:
1266 memset(rates, 0, *rates_size);
1267 *rates_size = min_t(int, tmp_size, *rates_size);
1268 memcpy(rates, tmp, *rates_size);
1269 return ret;
1270}
1271
1272
1273/**
1274 * @brief Sets the MSB on basic rates as the firmware requires
1275 *
1276 * Scan through an array and set the MSB for basic data rates.
1277 *
1278 * @param rates buffer of data rates
1279 * @param len size of buffer
1280 */
1281static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
1282{
1283 int i;
1284
1285 for (i = 0; i < len; i++) {
1286 if (rates[i] == 0x02 || rates[i] == 0x04 ||
1287 rates[i] == 0x0b || rates[i] == 0x16)
1288 rates[i] |= 0x80;
1289 }
1290}
1291
1292/**
1293 * @brief Send Deauthentication Request
1294 *
1295 * @param priv A pointer to struct lbs_private structure
1296 * @return 0--success, -1--fail
1297 */
1298int lbs_send_deauthentication(struct lbs_private *priv)
1299{
1300 return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
1301 0, CMD_OPTION_WAITFORRSP, 0, NULL);
1302}
1303
1304/**
1305 * @brief This function prepares command of authenticate. 1466 * @brief This function prepares command of authenticate.
1306 * 1467 *
1307 * @param priv A pointer to struct lbs_private structure 1468 * @param priv A pointer to struct lbs_private structure
@@ -1353,26 +1514,37 @@ out:
1353 return ret; 1514 return ret;
1354} 1515}
1355 1516
1356int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, 1517/**
1357 struct cmd_ds_command *cmd) 1518 * @brief Deauthenticate from a specific BSS
1519 *
1520 * @param priv A pointer to struct lbs_private structure
1521 * @param bssid The specific BSS to deauthenticate from
1522 * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating
1523 *
1524 * @return 0 on success, error on failure
1525 */
1526int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN],
1527 u16 reason)
1358{ 1528{
1359 struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth; 1529 struct cmd_ds_802_11_deauthenticate cmd;
1530 int ret;
1360 1531
1361 lbs_deb_enter(LBS_DEB_JOIN); 1532 lbs_deb_enter(LBS_DEB_JOIN);
1362 1533
1363 cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE); 1534 memset(&cmd, 0, sizeof(cmd));
1364 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) + 1535 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1365 S_DS_GEN); 1536 memcpy(cmd.macaddr, &bssid[0], ETH_ALEN);
1537 cmd.reasoncode = cpu_to_le16(reason);
1366 1538
1367 /* set AP MAC address */ 1539 ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
1368 memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
1369 1540
1370 /* Reason code 3 = Station is leaving */ 1541 /* Clean up everything even if there was an error; can't assume that
1371#define REASON_CODE_STA_LEAVING 3 1542 * we're still authenticated to the AP after trying to deauth.
1372 dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING); 1543 */
1544 lbs_mac_event_disconnected(priv);
1373 1545
1374 lbs_deb_leave(LBS_DEB_JOIN); 1546 lbs_deb_leave(LBS_DEB_JOIN);
1375 return 0; 1547 return ret;
1376} 1548}
1377 1549
1378int lbs_cmd_80211_associate(struct lbs_private *priv, 1550int lbs_cmd_80211_associate(struct lbs_private *priv,
@@ -1489,231 +1661,6 @@ done:
1489 return ret; 1661 return ret;
1490} 1662}
1491 1663
1492int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
1493 struct cmd_ds_command *cmd, void *pdata_buf)
1494{
1495 struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
1496 int ret = 0;
1497 int cmdappendsize = 0;
1498 struct assoc_request *assoc_req = pdata_buf;
1499 u16 tmpcap = 0;
1500 size_t ratesize = 0;
1501
1502 lbs_deb_enter(LBS_DEB_JOIN);
1503
1504 if (!priv) {
1505 ret = -1;
1506 goto done;
1507 }
1508
1509 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
1510
1511 /*
1512 * Fill in the parameters for 2 data structures:
1513 * 1. cmd_ds_802_11_ad_hoc_start command
1514 * 2. priv->scantable[i]
1515 *
1516 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
1517 * probe delay, and cap info.
1518 *
1519 * Firmware will fill up beacon period, DTIM, Basic rates
1520 * and operational rates.
1521 */
1522
1523 memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
1524 memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
1525
1526 lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
1527 escape_essid(assoc_req->ssid, assoc_req->ssid_len),
1528 assoc_req->ssid_len);
1529
1530 /* set the BSS type */
1531 adhs->bsstype = CMD_BSS_TYPE_IBSS;
1532 priv->mode = IW_MODE_ADHOC;
1533 if (priv->beacon_period == 0)
1534 priv->beacon_period = MRVDRV_BEACON_INTERVAL;
1535 adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
1536
1537 /* set Physical param set */
1538#define DS_PARA_IE_ID 3
1539#define DS_PARA_IE_LEN 1
1540
1541 adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
1542 adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
1543
1544 WARN_ON(!assoc_req->channel);
1545
1546 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
1547 assoc_req->channel);
1548
1549 adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
1550
1551 /* set IBSS param set */
1552#define IBSS_PARA_IE_ID 6
1553#define IBSS_PARA_IE_LEN 2
1554
1555 adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
1556 adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
1557 adhs->ssparamset.ibssparamset.atimwindow = 0;
1558
1559 /* set capability info */
1560 tmpcap = WLAN_CAPABILITY_IBSS;
1561 if (assoc_req->secinfo.wep_enabled) {
1562 lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
1563 "setting privacy on\n");
1564 tmpcap |= WLAN_CAPABILITY_PRIVACY;
1565 } else {
1566 lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
1567 "setting privacy off\n");
1568 }
1569 adhs->capability = cpu_to_le16(tmpcap);
1570
1571 /* probedelay */
1572 adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1573
1574 memset(adhs->rates, 0, sizeof(adhs->rates));
1575 ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
1576 memcpy(adhs->rates, lbs_bg_rates, ratesize);
1577
1578 /* Copy the ad-hoc creating rates into Current BSS state structure */
1579 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1580 memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
1581
1582 /* Set MSB on basic rates as the firmware requires, but _after_
1583 * copying to current bss rates.
1584 */
1585 lbs_set_basic_rate_flags(adhs->rates, ratesize);
1586
1587 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
1588 adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
1589
1590 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
1591
1592 if (lbs_create_dnld_countryinfo_11d(priv)) {
1593 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
1594 ret = -1;
1595 goto done;
1596 }
1597
1598 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
1599 S_DS_GEN + cmdappendsize);
1600
1601 ret = 0;
1602done:
1603 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1604 return ret;
1605}
1606
1607int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
1608{
1609 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
1610 cmd->size = cpu_to_le16(S_DS_GEN);
1611
1612 return 0;
1613}
1614
1615int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
1616 struct cmd_ds_command *cmd, void *pdata_buf)
1617{
1618 struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
1619 struct assoc_request *assoc_req = pdata_buf;
1620 struct bss_descriptor *bss = &assoc_req->bss;
1621 int cmdappendsize = 0;
1622 int ret = 0;
1623 u16 ratesize = 0;
1624 DECLARE_MAC_BUF(mac);
1625
1626 lbs_deb_enter(LBS_DEB_JOIN);
1627
1628 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
1629
1630 join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
1631 join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
1632
1633 memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
1634 memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
1635
1636 memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
1637 sizeof(union ieeetypes_phyparamset));
1638
1639 memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
1640 sizeof(union IEEEtypes_ssparamset));
1641
1642 join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
1643 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
1644 bss->capability, CAPINFO_MASK);
1645
1646 /* information on BSSID descriptor passed to FW */
1647 lbs_deb_join(
1648 "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
1649 print_mac(mac, join_cmd->bss.bssid),
1650 join_cmd->bss.ssid);
1651
1652 /* failtimeout */
1653 join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
1654
1655 /* probedelay */
1656 join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1657
1658 priv->curbssparams.channel = bss->channel;
1659
1660 /* Copy Data rates from the rates recorded in scan response */
1661 memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
1662 ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
1663 memcpy(join_cmd->bss.rates, bss->rates, ratesize);
1664 if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
1665 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
1666 ret = -1;
1667 goto done;
1668 }
1669
1670 /* Copy the ad-hoc creating rates into Current BSS state structure */
1671 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1672 memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
1673
1674 /* Set MSB on basic rates as the firmware requires, but _after_
1675 * copying to current bss rates.
1676 */
1677 lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
1678
1679 join_cmd->bss.ssparamset.ibssparamset.atimwindow =
1680 cpu_to_le16(bss->atimwindow);
1681
1682 if (assoc_req->secinfo.wep_enabled) {
1683 u16 tmp = le16_to_cpu(join_cmd->bss.capability);
1684 tmp |= WLAN_CAPABILITY_PRIVACY;
1685 join_cmd->bss.capability = cpu_to_le16(tmp);
1686 }
1687
1688 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
1689 /* wake up first */
1690 __le32 Localpsmode;
1691
1692 Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
1693 ret = lbs_prepare_and_send_command(priv,
1694 CMD_802_11_PS_MODE,
1695 CMD_ACT_SET,
1696 0, 0, &Localpsmode);
1697
1698 if (ret) {
1699 ret = -1;
1700 goto done;
1701 }
1702 }
1703
1704 if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
1705 ret = -1;
1706 goto done;
1707 }
1708
1709 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
1710 S_DS_GEN + cmdappendsize);
1711
1712done:
1713 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1714 return ret;
1715}
1716
1717int lbs_ret_80211_associate(struct lbs_private *priv, 1664int lbs_ret_80211_associate(struct lbs_private *priv,
1718 struct cmd_ds_command *resp) 1665 struct cmd_ds_command *resp)
1719{ 1666{
@@ -1815,34 +1762,19 @@ done:
1815 return ret; 1762 return ret;
1816} 1763}
1817 1764
1818int lbs_ret_80211_disassociate(struct lbs_private *priv) 1765static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp)
1819{
1820 lbs_deb_enter(LBS_DEB_JOIN);
1821
1822 lbs_mac_event_disconnected(priv);
1823
1824 lbs_deb_leave(LBS_DEB_JOIN);
1825 return 0;
1826}
1827
1828int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
1829 struct cmd_ds_command *resp)
1830{ 1766{
1831 int ret = 0; 1767 int ret = 0;
1832 u16 command = le16_to_cpu(resp->command); 1768 u16 command = le16_to_cpu(resp->command);
1833 u16 result = le16_to_cpu(resp->result); 1769 u16 result = le16_to_cpu(resp->result);
1834 struct cmd_ds_802_11_ad_hoc_result *padhocresult; 1770 struct cmd_ds_802_11_ad_hoc_result *adhoc_resp;
1835 union iwreq_data wrqu; 1771 union iwreq_data wrqu;
1836 struct bss_descriptor *bss; 1772 struct bss_descriptor *bss;
1837 DECLARE_MAC_BUF(mac); 1773 DECLARE_MAC_BUF(mac);
1838 1774
1839 lbs_deb_enter(LBS_DEB_JOIN); 1775 lbs_deb_enter(LBS_DEB_JOIN);
1840 1776
1841 padhocresult = &resp->params.result; 1777 adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp;
1842
1843 lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
1844 lbs_deb_join("ADHOC_RESP: command = %x\n", command);
1845 lbs_deb_join("ADHOC_RESP: result = %x\n", result);
1846 1778
1847 if (!priv->in_progress_assoc_req) { 1779 if (!priv->in_progress_assoc_req) {
1848 lbs_deb_join("ADHOC_RESP: no in-progress association " 1780 lbs_deb_join("ADHOC_RESP: no in-progress association "
@@ -1856,26 +1788,19 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
1856 * Join result code 0 --> SUCCESS 1788 * Join result code 0 --> SUCCESS
1857 */ 1789 */
1858 if (result) { 1790 if (result) {
1859 lbs_deb_join("ADHOC_RESP: failed\n"); 1791 lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
1860 if (priv->connect_status == LBS_CONNECTED) 1792 if (priv->connect_status == LBS_CONNECTED)
1861 lbs_mac_event_disconnected(priv); 1793 lbs_mac_event_disconnected(priv);
1862 ret = -1; 1794 ret = -1;
1863 goto done; 1795 goto done;
1864 } 1796 }
1865 1797
1866 /*
1867 * Now the join cmd should be successful
1868 * If BSSID has changed use SSID to compare instead of BSSID
1869 */
1870 lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
1871 escape_essid(bss->ssid, bss->ssid_len));
1872
1873 /* Send a Media Connected event, according to the Spec */ 1798 /* Send a Media Connected event, according to the Spec */
1874 priv->connect_status = LBS_CONNECTED; 1799 priv->connect_status = LBS_CONNECTED;
1875 1800
1876 if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { 1801 if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
1877 /* Update the created network descriptor with the new BSSID */ 1802 /* Update the created network descriptor with the new BSSID */
1878 memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN); 1803 memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN);
1879 } 1804 }
1880 1805
1881 /* Set the BSSID from the joined/started descriptor */ 1806 /* Set the BSSID from the joined/started descriptor */
@@ -1894,22 +1819,13 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
1894 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 1819 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1895 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); 1820 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1896 1821
1897 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n"); 1822 lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %s, channel %d\n",
1898 lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel); 1823 escape_essid(bss->ssid, bss->ssid_len),
1899 lbs_deb_join("ADHOC_RESP: BSSID = %s\n", 1824 print_mac(mac, priv->curbssparams.bssid),
1900 print_mac(mac, padhocresult->bssid)); 1825 priv->curbssparams.channel);
1901 1826
1902done: 1827done:
1903 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); 1828 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1904 return ret; 1829 return ret;
1905} 1830}
1906 1831
1907int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
1908{
1909 lbs_deb_enter(LBS_DEB_JOIN);
1910
1911 lbs_mac_event_disconnected(priv);
1912
1913 lbs_deb_leave(LBS_DEB_JOIN);
1914 return 0;
1915}
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
index c516fbe518fd..8b7336dd02a3 100644
--- a/drivers/net/wireless/libertas/assoc.h
+++ b/drivers/net/wireless/libertas/assoc.h
@@ -12,28 +12,18 @@ struct cmd_ds_command;
12int lbs_cmd_80211_authenticate(struct lbs_private *priv, 12int lbs_cmd_80211_authenticate(struct lbs_private *priv,
13 struct cmd_ds_command *cmd, 13 struct cmd_ds_command *cmd,
14 void *pdata_buf); 14 void *pdata_buf);
15int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv, 15
16 struct cmd_ds_command *cmd, 16int lbs_adhoc_stop(struct lbs_private *priv);
17 void *pdata_buf); 17
18int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd);
19int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
20 struct cmd_ds_command *cmd,
21 void *pdata_buf);
22int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, 18int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
23 struct cmd_ds_command *cmd); 19 u8 bssid[ETH_ALEN], u16 reason);
24int lbs_cmd_80211_associate(struct lbs_private *priv, 20int lbs_cmd_80211_associate(struct lbs_private *priv,
25 struct cmd_ds_command *cmd, 21 struct cmd_ds_command *cmd,
26 void *pdata_buf); 22 void *pdata_buf);
27 23
28int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, 24int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
29 struct cmd_ds_command *resp); 25 struct cmd_ds_command *resp);
30int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv);
31int lbs_ret_80211_disassociate(struct lbs_private *priv);
32int lbs_ret_80211_associate(struct lbs_private *priv, 26int lbs_ret_80211_associate(struct lbs_private *priv,
33 struct cmd_ds_command *resp); 27 struct cmd_ds_command *resp);
34 28
35int lbs_stop_adhoc_network(struct lbs_private *priv);
36
37int lbs_send_deauthentication(struct lbs_private *priv);
38
39#endif /* _LBS_ASSOC_H */ 29#endif /* _LBS_ASSOC_H */
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 75427e61898d..a912fb68c099 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -480,181 +480,166 @@ int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
480 return ret; 480 return ret;
481} 481}
482 482
483static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action) 483/**
484{ 484 * @brief Set an SNMP MIB value
485 struct cmd_ds_802_11_reset *reset = &cmd->params.reset; 485 *
486 486 * @param priv A pointer to struct lbs_private structure
487 lbs_deb_enter(LBS_DEB_CMD); 487 * @param oid The OID to set in the firmware
488 488 * @param val Value to set the OID to
489 cmd->command = cpu_to_le16(CMD_802_11_RESET); 489 *
490 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN); 490 * @return 0 on success, error on failure
491 reset->action = cpu_to_le16(cmd_action); 491 */
492 492int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
493 lbs_deb_leave(LBS_DEB_CMD);
494 return 0;
495}
496
497static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
498 struct cmd_ds_command *cmd,
499 int cmd_action,
500 int cmd_oid, void *pdata_buf)
501{ 493{
502 struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib; 494 struct cmd_ds_802_11_snmp_mib cmd;
503 u8 ucTemp; 495 int ret;
504 496
505 lbs_deb_enter(LBS_DEB_CMD); 497 lbs_deb_enter(LBS_DEB_CMD);
506 498
507 lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); 499 memset(&cmd, 0, sizeof (cmd));
508 500 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
509 cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB); 501 cmd.action = cpu_to_le16(CMD_ACT_SET);
510 cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN); 502 cmd.oid = cpu_to_le16((u16) oid);
511
512 switch (cmd_oid) {
513 case OID_802_11_INFRASTRUCTURE_MODE:
514 {
515 u8 mode = (u8) (size_t) pdata_buf;
516 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
517 pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
518 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u8));
519 if (mode == IW_MODE_ADHOC) {
520 ucTemp = SNMP_MIB_VALUE_ADHOC;
521 } else {
522 /* Infra and Auto modes */
523 ucTemp = SNMP_MIB_VALUE_INFRA;
524 }
525
526 memmove(pSNMPMIB->value, &ucTemp, sizeof(u8));
527 503
504 switch (oid) {
505 case SNMP_MIB_OID_BSS_TYPE:
506 cmd.bufsize = cpu_to_le16(sizeof(u8));
507 cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1;
528 break; 508 break;
509 case SNMP_MIB_OID_11D_ENABLE:
510 case SNMP_MIB_OID_FRAG_THRESHOLD:
511 case SNMP_MIB_OID_RTS_THRESHOLD:
512 case SNMP_MIB_OID_SHORT_RETRY_LIMIT:
513 case SNMP_MIB_OID_LONG_RETRY_LIMIT:
514 cmd.bufsize = cpu_to_le16(sizeof(u16));
515 *((__le16 *)(&cmd.value)) = cpu_to_le16(val);
516 break;
517 default:
518 lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid);
519 ret = -EINVAL;
520 goto out;
529 } 521 }
530 522
531 case OID_802_11D_ENABLE: 523 lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n",
532 { 524 le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val);
533 u32 ulTemp;
534
535 pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
536
537 if (cmd_action == CMD_ACT_SET) {
538 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
539 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
540 ulTemp = *(u32 *)pdata_buf;
541 *((__le16 *)(pSNMPMIB->value)) =
542 cpu_to_le16((u16) ulTemp);
543 }
544 break;
545 }
546
547 case OID_802_11_FRAGMENTATION_THRESHOLD:
548 {
549 u32 ulTemp;
550
551 pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I);
552
553 if (cmd_action == CMD_ACT_GET) {
554 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
555 } else if (cmd_action == CMD_ACT_SET) {
556 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
557 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
558 ulTemp = *((u32 *) pdata_buf);
559 *((__le16 *)(pSNMPMIB->value)) =
560 cpu_to_le16((u16) ulTemp);
561 525
562 } 526 ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
563 527
564 break; 528out:
565 } 529 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
530 return ret;
531}
566 532
567 case OID_802_11_RTS_THRESHOLD: 533/**
568 { 534 * @brief Get an SNMP MIB value
535 *
536 * @param priv A pointer to struct lbs_private structure
537 * @param oid The OID to retrieve from the firmware
538 * @param out_val Location for the returned value
539 *
540 * @return 0 on success, error on failure
541 */
542int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
543{
544 struct cmd_ds_802_11_snmp_mib cmd;
545 int ret;
569 546
570 u32 ulTemp; 547 lbs_deb_enter(LBS_DEB_CMD);
571 pSNMPMIB->oid = cpu_to_le16(RTSTHRESH_I);
572 548
573 if (cmd_action == CMD_ACT_GET) { 549 memset(&cmd, 0, sizeof (cmd));
574 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET); 550 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
575 } else if (cmd_action == CMD_ACT_SET) { 551 cmd.action = cpu_to_le16(CMD_ACT_GET);
576 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET); 552 cmd.oid = cpu_to_le16(oid);
577 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
578 ulTemp = *((u32 *)pdata_buf);
579 *(__le16 *)(pSNMPMIB->value) =
580 cpu_to_le16((u16) ulTemp);
581 553
582 } 554 ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
583 break; 555 if (ret)
584 } 556 goto out;
585 case OID_802_11_TX_RETRYCOUNT:
586 pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I);
587
588 if (cmd_action == CMD_ACT_GET) {
589 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
590 } else if (cmd_action == CMD_ACT_SET) {
591 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
592 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
593 *((__le16 *)(pSNMPMIB->value)) =
594 cpu_to_le16((u16) priv->txretrycount);
595 }
596 557
558 switch (le16_to_cpu(cmd.bufsize)) {
559 case sizeof(u8):
560 if (oid == SNMP_MIB_OID_BSS_TYPE) {
561 if (cmd.value[0] == 2)
562 *out_val = IW_MODE_ADHOC;
563 else
564 *out_val = IW_MODE_INFRA;
565 } else
566 *out_val = cmd.value[0];
567 break;
568 case sizeof(u16):
569 *out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
597 break; 570 break;
598 default: 571 default:
572 lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n",
573 oid, le16_to_cpu(cmd.bufsize));
599 break; 574 break;
600 } 575 }
601 576
602 lbs_deb_cmd( 577out:
603 "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n", 578 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
604 le16_to_cpu(cmd->command), le16_to_cpu(cmd->size), 579 return ret;
605 le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
606
607 lbs_deb_cmd(
608 "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
609 le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
610 le16_to_cpu(pSNMPMIB->bufsize),
611 le16_to_cpu(*(__le16 *) pSNMPMIB->value));
612
613 lbs_deb_leave(LBS_DEB_CMD);
614 return 0;
615} 580}
616 581
617static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd, 582/**
618 u16 cmd_action, void *pdata_buf) 583 * @brief Get the min, max, and current TX power
584 *
585 * @param priv A pointer to struct lbs_private structure
586 * @param curlevel Current power level in dBm
587 * @param minlevel Minimum supported power level in dBm (optional)
588 * @param maxlevel Maximum supported power level in dBm (optional)
589 *
590 * @return 0 on success, error on failure
591 */
592int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
593 s16 *maxlevel)
619{ 594{
620 595 struct cmd_ds_802_11_rf_tx_power cmd;
621 struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp; 596 int ret;
622 597
623 lbs_deb_enter(LBS_DEB_CMD); 598 lbs_deb_enter(LBS_DEB_CMD);
624 599
625 cmd->size = 600 memset(&cmd, 0, sizeof(cmd));
626 cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN); 601 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
627 cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER); 602 cmd.action = cpu_to_le16(CMD_ACT_GET);
628 prtp->action = cpu_to_le16(cmd_action); 603
604 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
605 if (ret == 0) {
606 *curlevel = le16_to_cpu(cmd.curlevel);
607 if (minlevel)
608 *minlevel = le16_to_cpu(cmd.minlevel);
609 if (maxlevel)
610 *maxlevel = le16_to_cpu(cmd.maxlevel);
611 }
629 612
630 lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n", 613 lbs_deb_leave(LBS_DEB_CMD);
631 le16_to_cpu(cmd->size), le16_to_cpu(cmd->command), 614 return ret;
632 le16_to_cpu(prtp->action)); 615}
633 616
634 switch (cmd_action) { 617/**
635 case CMD_ACT_TX_POWER_OPT_GET: 618 * @brief Set the TX power
636 prtp->action = cpu_to_le16(CMD_ACT_GET); 619 *
637 prtp->currentlevel = 0; 620 * @param priv A pointer to struct lbs_private structure
638 break; 621 * @param dbm The desired power level in dBm
622 *
623 * @return 0 on success, error on failure
624 */
625int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
626{
627 struct cmd_ds_802_11_rf_tx_power cmd;
628 int ret;
639 629
640 case CMD_ACT_TX_POWER_OPT_SET_HIGH: 630 lbs_deb_enter(LBS_DEB_CMD);
641 prtp->action = cpu_to_le16(CMD_ACT_SET);
642 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
643 break;
644 631
645 case CMD_ACT_TX_POWER_OPT_SET_MID: 632 memset(&cmd, 0, sizeof(cmd));
646 prtp->action = cpu_to_le16(CMD_ACT_SET); 633 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
647 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID); 634 cmd.action = cpu_to_le16(CMD_ACT_SET);
648 break; 635 cmd.curlevel = cpu_to_le16(dbm);
649 636
650 case CMD_ACT_TX_POWER_OPT_SET_LOW: 637 lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm);
651 prtp->action = cpu_to_le16(CMD_ACT_SET); 638
652 prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf)); 639 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
653 break;
654 }
655 640
656 lbs_deb_leave(LBS_DEB_CMD); 641 lbs_deb_leave(LBS_DEB_CMD);
657 return 0; 642 return ret;
658} 643}
659 644
660static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, 645static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
@@ -1033,9 +1018,9 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
1033 return ret; 1018 return ret;
1034} 1019}
1035 1020
1036int lbs_mesh_config_send(struct lbs_private *priv, 1021static int __lbs_mesh_config_send(struct lbs_private *priv,
1037 struct cmd_ds_mesh_config *cmd, 1022 struct cmd_ds_mesh_config *cmd,
1038 uint16_t action, uint16_t type) 1023 uint16_t action, uint16_t type)
1039{ 1024{
1040 int ret; 1025 int ret;
1041 1026
@@ -1054,6 +1039,19 @@ int lbs_mesh_config_send(struct lbs_private *priv,
1054 return ret; 1039 return ret;
1055} 1040}
1056 1041
1042int lbs_mesh_config_send(struct lbs_private *priv,
1043 struct cmd_ds_mesh_config *cmd,
1044 uint16_t action, uint16_t type)
1045{
1046 int ret;
1047
1048 if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
1049 return -EOPNOTSUPP;
1050
1051 ret = __lbs_mesh_config_send(priv, cmd, action, type);
1052 return ret;
1053}
1054
1057/* This function is the CMD_MESH_CONFIG legacy function. It only handles the 1055/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
1058 * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG 1056 * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
1059 * are all handled by preparing a struct cmd_ds_mesh_config and passing it to 1057 * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
@@ -1095,7 +1093,7 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
1095 action, priv->mesh_tlv, chan, 1093 action, priv->mesh_tlv, chan,
1096 escape_essid(priv->mesh_ssid, priv->mesh_ssid_len)); 1094 escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
1097 1095
1098 return lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); 1096 return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
1099} 1097}
1100 1098
1101static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, 1099static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
@@ -1256,41 +1254,47 @@ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
1256 priv->cur_cmd = NULL; 1254 priv->cur_cmd = NULL;
1257} 1255}
1258 1256
1259int lbs_set_radio_control(struct lbs_private *priv) 1257int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
1260{ 1258{
1261 int ret = 0;
1262 struct cmd_ds_802_11_radio_control cmd; 1259 struct cmd_ds_802_11_radio_control cmd;
1260 int ret = -EINVAL;
1263 1261
1264 lbs_deb_enter(LBS_DEB_CMD); 1262 lbs_deb_enter(LBS_DEB_CMD);
1265 1263
1266 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 1264 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1267 cmd.action = cpu_to_le16(CMD_ACT_SET); 1265 cmd.action = cpu_to_le16(CMD_ACT_SET);
1268 1266
1269 switch (priv->preamble) { 1267 /* Only v8 and below support setting the preamble */
1270 case CMD_TYPE_SHORT_PREAMBLE: 1268 if (priv->fwrelease < 0x09000000) {
1271 cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE); 1269 switch (preamble) {
1272 break; 1270 case RADIO_PREAMBLE_SHORT:
1273 1271 if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
1274 case CMD_TYPE_LONG_PREAMBLE: 1272 goto out;
1275 cmd.control = cpu_to_le16(SET_LONG_PREAMBLE); 1273 /* Fall through */
1276 break; 1274 case RADIO_PREAMBLE_AUTO:
1275 case RADIO_PREAMBLE_LONG:
1276 cmd.control = cpu_to_le16(preamble);
1277 break;
1278 default:
1279 goto out;
1280 }
1281 }
1277 1282
1278 case CMD_TYPE_AUTO_PREAMBLE: 1283 if (radio_on)
1279 default: 1284 cmd.control |= cpu_to_le16(0x1);
1280 cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE); 1285 else {
1281 break; 1286 cmd.control &= cpu_to_le16(~0x1);
1287 priv->txpower_cur = 0;
1282 } 1288 }
1283 1289
1284 if (priv->radioon) 1290 lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n",
1285 cmd.control |= cpu_to_le16(TURN_ON_RF); 1291 radio_on ? "ON" : "OFF", preamble);
1286 else
1287 cmd.control &= cpu_to_le16(~TURN_ON_RF);
1288 1292
1289 lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon, 1293 priv->radio_on = radio_on;
1290 priv->preamble);
1291 1294
1292 ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); 1295 ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
1293 1296
1297out:
1294 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 1298 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1295 return ret; 1299 return ret;
1296} 1300}
@@ -1380,55 +1384,25 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1380 ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf); 1384 ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
1381 break; 1385 break;
1382 1386
1383 case CMD_802_11_DEAUTHENTICATE:
1384 ret = lbs_cmd_80211_deauthenticate(priv, cmdptr);
1385 break;
1386
1387 case CMD_802_11_AD_HOC_START:
1388 ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
1389 break;
1390
1391 case CMD_802_11_RESET:
1392 ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
1393 break;
1394
1395 case CMD_802_11_AUTHENTICATE: 1387 case CMD_802_11_AUTHENTICATE:
1396 ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf); 1388 ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
1397 break; 1389 break;
1398 1390
1399 case CMD_802_11_SNMP_MIB:
1400 ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
1401 cmd_action, cmd_oid, pdata_buf);
1402 break;
1403
1404 case CMD_MAC_REG_ACCESS: 1391 case CMD_MAC_REG_ACCESS:
1405 case CMD_BBP_REG_ACCESS: 1392 case CMD_BBP_REG_ACCESS:
1406 case CMD_RF_REG_ACCESS: 1393 case CMD_RF_REG_ACCESS:
1407 ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf); 1394 ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
1408 break; 1395 break;
1409 1396
1410 case CMD_802_11_RF_TX_POWER:
1411 ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
1412 cmd_action, pdata_buf);
1413 break;
1414
1415 case CMD_802_11_MONITOR_MODE: 1397 case CMD_802_11_MONITOR_MODE:
1416 ret = lbs_cmd_802_11_monitor_mode(cmdptr, 1398 ret = lbs_cmd_802_11_monitor_mode(cmdptr,
1417 cmd_action, pdata_buf); 1399 cmd_action, pdata_buf);
1418 break; 1400 break;
1419 1401
1420 case CMD_802_11_AD_HOC_JOIN:
1421 ret = lbs_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
1422 break;
1423
1424 case CMD_802_11_RSSI: 1402 case CMD_802_11_RSSI:
1425 ret = lbs_cmd_802_11_rssi(priv, cmdptr); 1403 ret = lbs_cmd_802_11_rssi(priv, cmdptr);
1426 break; 1404 break;
1427 1405
1428 case CMD_802_11_AD_HOC_STOP:
1429 ret = lbs_cmd_80211_ad_hoc_stop(cmdptr);
1430 break;
1431
1432 case CMD_802_11_SET_AFC: 1406 case CMD_802_11_SET_AFC:
1433 case CMD_802_11_GET_AFC: 1407 case CMD_802_11_GET_AFC:
1434 1408
@@ -1953,6 +1927,70 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
1953} 1927}
1954 1928
1955 1929
1930/**
1931 * @brief Configures the transmission power control functionality.
1932 *
1933 * @param priv A pointer to struct lbs_private structure
1934 * @param enable Transmission power control enable
1935 * @param p0 Power level when link quality is good (dBm).
1936 * @param p1 Power level when link quality is fair (dBm).
1937 * @param p2 Power level when link quality is poor (dBm).
1938 * @param usesnr Use Signal to Noise Ratio in TPC
1939 *
1940 * @return 0 on success
1941 */
1942int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
1943 int8_t p2, int usesnr)
1944{
1945 struct cmd_ds_802_11_tpc_cfg cmd;
1946 int ret;
1947
1948 memset(&cmd, 0, sizeof(cmd));
1949 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1950 cmd.action = cpu_to_le16(CMD_ACT_SET);
1951 cmd.enable = !!enable;
1952 cmd.usesnr = !!usesnr;
1953 cmd.P0 = p0;
1954 cmd.P1 = p1;
1955 cmd.P2 = p2;
1956
1957 ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd);
1958
1959 return ret;
1960}
1961
1962/**
1963 * @brief Configures the power adaptation settings.
1964 *
1965 * @param priv A pointer to struct lbs_private structure
1966 * @param enable Power adaptation enable
1967 * @param p0 Power level for 1, 2, 5.5 and 11 Mbps (dBm).
1968 * @param p1 Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm).
1969 * @param p2 Power level for 48 and 54 Mbps (dBm).
1970 *
1971 * @return 0 on Success
1972 */
1973
1974int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
1975 int8_t p1, int8_t p2)
1976{
1977 struct cmd_ds_802_11_pa_cfg cmd;
1978 int ret;
1979
1980 memset(&cmd, 0, sizeof(cmd));
1981 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1982 cmd.action = cpu_to_le16(CMD_ACT_SET);
1983 cmd.enable = !!enable;
1984 cmd.P0 = p0;
1985 cmd.P1 = p1;
1986 cmd.P2 = p2;
1987
1988 ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd);
1989
1990 return ret;
1991}
1992
1993
1956static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, 1994static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
1957 uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, 1995 uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
1958 int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), 1996 int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index a53b51f8bdb4..36be4c9703e0 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -26,6 +26,18 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
26 int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), 26 int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
27 unsigned long callback_arg); 27 unsigned long callback_arg);
28 28
29int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
30 int8_t p1, int8_t p2);
31
32int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
33 int8_t p2, int usesnr);
34
35int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
36 int8_t p1, int8_t p2);
37
38int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
39 int8_t p2, int usesnr);
40
29int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, 41int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
30 struct cmd_header *resp); 42 struct cmd_header *resp);
31 43
@@ -61,4 +73,14 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
61int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, 73int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
62 struct assoc_request *assoc); 74 struct assoc_request *assoc);
63 75
76int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
77 s16 *maxlevel);
78int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
79
80int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
81
82int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
83
84int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val);
85
64#endif /* _LBS_CMD_H */ 86#endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 24de3c3cf877..bcf2a9756fb6 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -146,63 +146,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
146 return ret; 146 return ret;
147} 147}
148 148
149static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
150 struct cmd_ds_command *resp)
151{
152 struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
153 u16 oid = le16_to_cpu(smib->oid);
154 u16 querytype = le16_to_cpu(smib->querytype);
155
156 lbs_deb_enter(LBS_DEB_CMD);
157
158 lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
159 querytype);
160 lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
161
162 if (querytype == CMD_ACT_GET) {
163 switch (oid) {
164 case FRAGTHRESH_I:
165 priv->fragthsd =
166 le16_to_cpu(*((__le16 *)(smib->value)));
167 lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
168 priv->fragthsd);
169 break;
170 case RTSTHRESH_I:
171 priv->rtsthsd =
172 le16_to_cpu(*((__le16 *)(smib->value)));
173 lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
174 priv->rtsthsd);
175 break;
176 case SHORT_RETRYLIM_I:
177 priv->txretrycount =
178 le16_to_cpu(*((__le16 *)(smib->value)));
179 lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
180 priv->rtsthsd);
181 break;
182 default:
183 break;
184 }
185 }
186
187 lbs_deb_enter(LBS_DEB_CMD);
188 return 0;
189}
190
191static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
192 struct cmd_ds_command *resp)
193{
194 struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
195
196 lbs_deb_enter(LBS_DEB_CMD);
197
198 priv->txpowerlevel = le16_to_cpu(rtp->currentlevel);
199
200 lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel);
201
202 lbs_deb_leave(LBS_DEB_CMD);
203 return 0;
204}
205
206static int lbs_ret_802_11_rssi(struct lbs_private *priv, 149static int lbs_ret_802_11_rssi(struct lbs_private *priv,
207 struct cmd_ds_command *resp) 150 struct cmd_ds_command *resp)
208{ 151{
@@ -273,24 +216,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
273 ret = lbs_ret_80211_associate(priv, resp); 216 ret = lbs_ret_80211_associate(priv, resp);
274 break; 217 break;
275 218
276 case CMD_RET(CMD_802_11_DISASSOCIATE):
277 case CMD_RET(CMD_802_11_DEAUTHENTICATE):
278 ret = lbs_ret_80211_disassociate(priv);
279 break;
280
281 case CMD_RET(CMD_802_11_AD_HOC_START):
282 case CMD_RET(CMD_802_11_AD_HOC_JOIN):
283 ret = lbs_ret_80211_ad_hoc_start(priv, resp);
284 break;
285
286 case CMD_RET(CMD_802_11_SNMP_MIB):
287 ret = lbs_ret_802_11_snmp_mib(priv, resp);
288 break;
289
290 case CMD_RET(CMD_802_11_RF_TX_POWER):
291 ret = lbs_ret_802_11_rf_tx_power(priv, resp);
292 break;
293
294 case CMD_RET(CMD_802_11_SET_AFC): 219 case CMD_RET(CMD_802_11_SET_AFC):
295 case CMD_RET(CMD_802_11_GET_AFC): 220 case CMD_RET(CMD_802_11_GET_AFC):
296 spin_lock_irqsave(&priv->driver_lock, flags); 221 spin_lock_irqsave(&priv->driver_lock, flags);
@@ -300,7 +225,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
300 225
301 break; 226 break;
302 227
303 case CMD_RET(CMD_802_11_RESET):
304 case CMD_RET(CMD_802_11_AUTHENTICATE): 228 case CMD_RET(CMD_802_11_AUTHENTICATE):
305 case CMD_RET(CMD_802_11_BEACON_STOP): 229 case CMD_RET(CMD_802_11_BEACON_STOP):
306 break; 230 break;
@@ -309,10 +233,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
309 ret = lbs_ret_802_11_rssi(priv, resp); 233 ret = lbs_ret_802_11_rssi(priv, resp);
310 break; 234 break;
311 235
312 case CMD_RET(CMD_802_11_AD_HOC_STOP):
313 ret = lbs_ret_80211_ad_hoc_stop(priv);
314 break;
315
316 case CMD_RET(CMD_802_11D_DOMAIN_INFO): 236 case CMD_RET(CMD_802_11D_DOMAIN_INFO):
317 ret = lbs_ret_802_11d_domain_info(resp); 237 ret = lbs_ret_802_11d_domain_info(resp);
318 break; 238 break;
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index a8ac974dacac..1a8888cceadc 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -34,7 +34,6 @@ int lbs_process_event(struct lbs_private *priv, u32 event);
34void lbs_queue_event(struct lbs_private *priv, u32 event); 34void lbs_queue_event(struct lbs_private *priv, u32 event);
35void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); 35void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
36 36
37int lbs_set_radio_control(struct lbs_private *priv);
38u32 lbs_fw_index_to_data_rate(u8 index); 37u32 lbs_fw_index_to_data_rate(u8 index);
39u8 lbs_data_rate_to_fw_index(u32 rate); 38u8 lbs_data_rate_to_fw_index(u32 rate);
40 39
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 12e687550bce..076a636e8f62 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -189,6 +189,14 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
189#define MRVDRV_CMD_UPLD_RDY 0x0008 189#define MRVDRV_CMD_UPLD_RDY 0x0008
190#define MRVDRV_CARDEVENT 0x0010 190#define MRVDRV_CARDEVENT 0x0010
191 191
192/* Automatic TX control default levels */
193#define POW_ADAPT_DEFAULT_P0 13
194#define POW_ADAPT_DEFAULT_P1 15
195#define POW_ADAPT_DEFAULT_P2 18
196#define TPC_DEFAULT_P0 5
197#define TPC_DEFAULT_P1 10
198#define TPC_DEFAULT_P2 13
199
192/** TxPD status */ 200/** TxPD status */
193 201
194/* Station firmware use TxPD status field to report final Tx transmit 202/* Station firmware use TxPD status field to report final Tx transmit
@@ -243,6 +251,9 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
243 251
244#define CMD_F_HOSTCMD (1 << 0) 252#define CMD_F_HOSTCMD (1 << 0)
245#define FW_CAPINFO_WPA (1 << 0) 253#define FW_CAPINFO_WPA (1 << 0)
254#define FW_CAPINFO_FIRMWARE_UPGRADE (1 << 13)
255#define FW_CAPINFO_BOOT2_UPGRADE (1<<14)
256#define FW_CAPINFO_PERSISTENT_CONFIG (1<<15)
246 257
247#define KEY_LEN_WPA_AES 16 258#define KEY_LEN_WPA_AES 16
248#define KEY_LEN_WPA_TKIP 32 259#define KEY_LEN_WPA_TKIP 32
@@ -316,7 +327,8 @@ enum PS_STATE {
316enum DNLD_STATE { 327enum DNLD_STATE {
317 DNLD_RES_RECEIVED, 328 DNLD_RES_RECEIVED,
318 DNLD_DATA_SENT, 329 DNLD_DATA_SENT,
319 DNLD_CMD_SENT 330 DNLD_CMD_SENT,
331 DNLD_BOOTCMD_SENT,
320}; 332};
321 333
322/** LBS_MEDIA_STATE */ 334/** LBS_MEDIA_STATE */
@@ -339,27 +351,6 @@ enum mv_ms_type {
339 MVMS_EVENT 351 MVMS_EVENT
340}; 352};
341 353
342/** SNMP_MIB_INDEX_e */
343enum SNMP_MIB_INDEX_e {
344 DESIRED_BSSTYPE_I = 0,
345 OP_RATESET_I,
346 BCNPERIOD_I,
347 DTIMPERIOD_I,
348 ASSOCRSP_TIMEOUT_I,
349 RTSTHRESH_I,
350 SHORT_RETRYLIM_I,
351 LONG_RETRYLIM_I,
352 FRAGTHRESH_I,
353 DOT11D_I,
354 DOT11H_I,
355 MANUFID_I,
356 PRODID_I,
357 MANUF_OUI_I,
358 MANUF_NAME_I,
359 MANUF_PRODNAME_I,
360 MANUF_PRODVER_I,
361};
362
363/** KEY_TYPE_ID */ 354/** KEY_TYPE_ID */
364enum KEY_TYPE_ID { 355enum KEY_TYPE_ID {
365 KEY_TYPE_ID_WEP = 0, 356 KEY_TYPE_ID_WEP = 0,
@@ -374,12 +365,6 @@ enum KEY_INFO_WPA {
374 KEY_INFO_WPA_ENABLED = 0x04 365 KEY_INFO_WPA_ENABLED = 0x04
375}; 366};
376 367
377/** SNMP_MIB_VALUE_e */
378enum SNMP_MIB_VALUE_e {
379 SNMP_MIB_VALUE_INFRA = 1,
380 SNMP_MIB_VALUE_ADHOC
381};
382
383/* Default values for fwt commands. */ 368/* Default values for fwt commands. */
384#define FWT_DEFAULT_METRIC 0 369#define FWT_DEFAULT_METRIC 0
385#define FWT_DEFAULT_DIR 1 370#define FWT_DEFAULT_DIR 1
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index f5bb40c54d85..f6f3753da303 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -58,6 +58,7 @@ struct lbs_802_11_security {
58 u8 WPA2enabled; 58 u8 WPA2enabled;
59 u8 wep_enabled; 59 u8 wep_enabled;
60 u8 auth_mode; 60 u8 auth_mode;
61 u32 key_mgmt;
61}; 62};
62 63
63/** Current Basic Service Set State Structure */ 64/** Current Basic Service Set State Structure */
@@ -240,9 +241,6 @@ struct lbs_private {
240 uint16_t enablehwauto; 241 uint16_t enablehwauto;
241 uint16_t ratebitmap; 242 uint16_t ratebitmap;
242 243
243 u32 fragthsd;
244 u32 rtsthsd;
245
246 u8 txretrycount; 244 u8 txretrycount;
247 245
248 /** Tx-related variables (for single packet tx) */ 246 /** Tx-related variables (for single packet tx) */
@@ -253,7 +251,9 @@ struct lbs_private {
253 u32 connect_status; 251 u32 connect_status;
254 u32 mesh_connect_status; 252 u32 mesh_connect_status;
255 u16 regioncode; 253 u16 regioncode;
256 u16 txpowerlevel; 254 s16 txpower_cur;
255 s16 txpower_min;
256 s16 txpower_max;
257 257
258 /** POWER MANAGEMENT AND PnP SUPPORT */ 258 /** POWER MANAGEMENT AND PnP SUPPORT */
259 u8 surpriseremoved; 259 u8 surpriseremoved;
@@ -291,8 +291,7 @@ struct lbs_private {
291 u16 nextSNRNF; 291 u16 nextSNRNF;
292 u16 numSNRNF; 292 u16 numSNRNF;
293 293
294 u8 radioon; 294 u8 radio_on;
295 u32 preamble;
296 295
297 /** data rate stuff */ 296 /** data rate stuff */
298 u8 cur_rate; 297 u8 cur_rate;
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index c92e41b4faf4..5004d7679c02 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -9,17 +9,6 @@
9#define DEFAULT_AD_HOC_CHANNEL 6 9#define DEFAULT_AD_HOC_CHANNEL 6
10#define DEFAULT_AD_HOC_CHANNEL_A 36 10#define DEFAULT_AD_HOC_CHANNEL_A 36
11 11
12/** IEEE 802.11 oids */
13#define OID_802_11_SSID 0x00008002
14#define OID_802_11_INFRASTRUCTURE_MODE 0x00008008
15#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008009
16#define OID_802_11_RTS_THRESHOLD 0x0000800A
17#define OID_802_11_TX_ANTENNA_SELECTED 0x0000800D
18#define OID_802_11_SUPPORTED_RATES 0x0000800E
19#define OID_802_11_STATISTICS 0x00008012
20#define OID_802_11_TX_RETRYCOUNT 0x0000801D
21#define OID_802_11D_ENABLE 0x00008020
22
23#define CMD_OPTION_WAITFORRSP 0x0002 12#define CMD_OPTION_WAITFORRSP 0x0002
24 13
25/** Host command IDs */ 14/** Host command IDs */
@@ -61,7 +50,6 @@
61#define CMD_RF_REG_MAP 0x0023 50#define CMD_RF_REG_MAP 0x0023
62#define CMD_802_11_DEAUTHENTICATE 0x0024 51#define CMD_802_11_DEAUTHENTICATE 0x0024
63#define CMD_802_11_REASSOCIATE 0x0025 52#define CMD_802_11_REASSOCIATE 0x0025
64#define CMD_802_11_DISASSOCIATE 0x0026
65#define CMD_MAC_CONTROL 0x0028 53#define CMD_MAC_CONTROL 0x0028
66#define CMD_802_11_AD_HOC_START 0x002b 54#define CMD_802_11_AD_HOC_START 0x002b
67#define CMD_802_11_AD_HOC_JOIN 0x002c 55#define CMD_802_11_AD_HOC_JOIN 0x002c
@@ -84,6 +72,7 @@
84#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067 72#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
85#define CMD_802_11_SLEEP_PERIOD 0x0068 73#define CMD_802_11_SLEEP_PERIOD 0x0068
86#define CMD_802_11_TPC_CFG 0x0072 74#define CMD_802_11_TPC_CFG 0x0072
75#define CMD_802_11_PA_CFG 0x0073
87#define CMD_802_11_FW_WAKE_METHOD 0x0074 76#define CMD_802_11_FW_WAKE_METHOD 0x0074
88#define CMD_802_11_SUBSCRIBE_EVENT 0x0075 77#define CMD_802_11_SUBSCRIBE_EVENT 0x0075
89#define CMD_802_11_RATE_ADAPT_RATESET 0x0076 78#define CMD_802_11_RATE_ADAPT_RATESET 0x0076
@@ -153,11 +142,6 @@
153#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 142#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
154#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 143#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
155 144
156/* Define action or option for CMD_802_11_RADIO_CONTROL */
157#define CMD_TYPE_AUTO_PREAMBLE 0x0001
158#define CMD_TYPE_SHORT_PREAMBLE 0x0002
159#define CMD_TYPE_LONG_PREAMBLE 0x0003
160
161/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */ 145/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
162#define CMD_SUBSCRIBE_RSSI_LOW 0x0001 146#define CMD_SUBSCRIBE_RSSI_LOW 0x0001
163#define CMD_SUBSCRIBE_SNR_LOW 0x0002 147#define CMD_SUBSCRIBE_SNR_LOW 0x0002
@@ -166,28 +150,14 @@
166#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010 150#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010
167#define CMD_SUBSCRIBE_SNR_HIGH 0x0020 151#define CMD_SUBSCRIBE_SNR_HIGH 0x0020
168 152
169#define TURN_ON_RF 0x01 153#define RADIO_PREAMBLE_LONG 0x00
170#define RADIO_ON 0x01 154#define RADIO_PREAMBLE_SHORT 0x02
171#define RADIO_OFF 0x00 155#define RADIO_PREAMBLE_AUTO 0x04
172
173#define SET_AUTO_PREAMBLE 0x05
174#define SET_SHORT_PREAMBLE 0x03
175#define SET_LONG_PREAMBLE 0x01
176 156
177/* Define action or option for CMD_802_11_RF_CHANNEL */ 157/* Define action or option for CMD_802_11_RF_CHANNEL */
178#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 158#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
179#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 159#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
180 160
181/* Define action or option for CMD_802_11_RF_TX_POWER */
182#define CMD_ACT_TX_POWER_OPT_GET 0x0000
183#define CMD_ACT_TX_POWER_OPT_SET_HIGH 0x8007
184#define CMD_ACT_TX_POWER_OPT_SET_MID 0x8004
185#define CMD_ACT_TX_POWER_OPT_SET_LOW 0x8000
186
187#define CMD_ACT_TX_POWER_INDEX_HIGH 0x0007
188#define CMD_ACT_TX_POWER_INDEX_MID 0x0004
189#define CMD_ACT_TX_POWER_INDEX_LOW 0x0000
190
191/* Define action or option for CMD_802_11_DATA_RATE */ 161/* Define action or option for CMD_802_11_DATA_RATE */
192#define CMD_ACT_SET_TX_AUTO 0x0000 162#define CMD_ACT_SET_TX_AUTO 0x0000
193#define CMD_ACT_SET_TX_FIX_RATE 0x0001 163#define CMD_ACT_SET_TX_FIX_RATE 0x0001
@@ -210,6 +180,19 @@
210#define CMD_WAKE_METHOD_COMMAND_INT 0x0001 180#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
211#define CMD_WAKE_METHOD_GPIO 0x0002 181#define CMD_WAKE_METHOD_GPIO 0x0002
212 182
183/* Object IDs for CMD_802_11_SNMP_MIB */
184#define SNMP_MIB_OID_BSS_TYPE 0x0000
185#define SNMP_MIB_OID_OP_RATE_SET 0x0001
186#define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */
187#define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */
188#define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */
189#define SNMP_MIB_OID_RTS_THRESHOLD 0x0005
190#define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006
191#define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007
192#define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008
193#define SNMP_MIB_OID_11D_ENABLE 0x0009
194#define SNMP_MIB_OID_11H_ENABLE 0x000A
195
213/* Define action or option for CMD_BT_ACCESS */ 196/* Define action or option for CMD_BT_ACCESS */
214enum cmd_bt_access_opts { 197enum cmd_bt_access_opts {
215 /* The bt commands start at 5 instead of 1 because the old dft commands 198 /* The bt commands start at 5 instead of 1 because the old dft commands
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index 913b480211a9..d9f9a12a739e 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -151,10 +151,6 @@ struct cmd_ds_get_hw_spec {
151 __le32 fwcapinfo; 151 __le32 fwcapinfo;
152} __attribute__ ((packed)); 152} __attribute__ ((packed));
153 153
154struct cmd_ds_802_11_reset {
155 __le16 action;
156};
157
158struct cmd_ds_802_11_subscribe_event { 154struct cmd_ds_802_11_subscribe_event {
159 struct cmd_header hdr; 155 struct cmd_header hdr;
160 156
@@ -232,7 +228,9 @@ struct cmd_ds_802_11_authenticate {
232}; 228};
233 229
234struct cmd_ds_802_11_deauthenticate { 230struct cmd_ds_802_11_deauthenticate {
235 u8 macaddr[6]; 231 struct cmd_header hdr;
232
233 u8 macaddr[ETH_ALEN];
236 __le16 reasoncode; 234 __le16 reasoncode;
237}; 235};
238 236
@@ -251,20 +249,10 @@ struct cmd_ds_802_11_associate {
251#endif 249#endif
252} __attribute__ ((packed)); 250} __attribute__ ((packed));
253 251
254struct cmd_ds_802_11_disassociate {
255 u8 destmacaddr[6];
256 __le16 reasoncode;
257};
258
259struct cmd_ds_802_11_associate_rsp { 252struct cmd_ds_802_11_associate_rsp {
260 struct ieeetypes_assocrsp assocRsp; 253 struct ieeetypes_assocrsp assocRsp;
261}; 254};
262 255
263struct cmd_ds_802_11_ad_hoc_result {
264 u8 pad[3];
265 u8 bssid[ETH_ALEN];
266};
267
268struct cmd_ds_802_11_set_wep { 256struct cmd_ds_802_11_set_wep {
269 struct cmd_header hdr; 257 struct cmd_header hdr;
270 258
@@ -309,7 +297,9 @@ struct cmd_ds_802_11_get_stat {
309}; 297};
310 298
311struct cmd_ds_802_11_snmp_mib { 299struct cmd_ds_802_11_snmp_mib {
312 __le16 querytype; 300 struct cmd_header hdr;
301
302 __le16 action;
313 __le16 oid; 303 __le16 oid;
314 __le16 bufsize; 304 __le16 bufsize;
315 u8 value[128]; 305 u8 value[128];
@@ -435,8 +425,12 @@ struct cmd_ds_802_11_mac_address {
435}; 425};
436 426
437struct cmd_ds_802_11_rf_tx_power { 427struct cmd_ds_802_11_rf_tx_power {
428 struct cmd_header hdr;
429
438 __le16 action; 430 __le16 action;
439 __le16 currentlevel; 431 __le16 curlevel;
432 s8 maxlevel;
433 s8 minlevel;
440}; 434};
441 435
442struct cmd_ds_802_11_rf_antenna { 436struct cmd_ds_802_11_rf_antenna {
@@ -507,10 +501,12 @@ struct cmd_ds_802_11_rate_adapt_rateset {
507}; 501};
508 502
509struct cmd_ds_802_11_ad_hoc_start { 503struct cmd_ds_802_11_ad_hoc_start {
504 struct cmd_header hdr;
505
510 u8 ssid[IW_ESSID_MAX_SIZE]; 506 u8 ssid[IW_ESSID_MAX_SIZE];
511 u8 bsstype; 507 u8 bsstype;
512 __le16 beaconperiod; 508 __le16 beaconperiod;
513 u8 dtimperiod; 509 u8 dtimperiod; /* Reserved on v9 and later */
514 union IEEEtypes_ssparamset ssparamset; 510 union IEEEtypes_ssparamset ssparamset;
515 union ieeetypes_phyparamset phyparamset; 511 union ieeetypes_phyparamset phyparamset;
516 __le16 probedelay; 512 __le16 probedelay;
@@ -519,9 +515,16 @@ struct cmd_ds_802_11_ad_hoc_start {
519 u8 tlv_memory_size_pad[100]; 515 u8 tlv_memory_size_pad[100];
520} __attribute__ ((packed)); 516} __attribute__ ((packed));
521 517
518struct cmd_ds_802_11_ad_hoc_result {
519 struct cmd_header hdr;
520
521 u8 pad[3];
522 u8 bssid[ETH_ALEN];
523};
524
522struct adhoc_bssdesc { 525struct adhoc_bssdesc {
523 u8 bssid[6]; 526 u8 bssid[ETH_ALEN];
524 u8 ssid[32]; 527 u8 ssid[IW_ESSID_MAX_SIZE];
525 u8 type; 528 u8 type;
526 __le16 beaconperiod; 529 __le16 beaconperiod;
527 u8 dtimperiod; 530 u8 dtimperiod;
@@ -539,10 +542,15 @@ struct adhoc_bssdesc {
539} __attribute__ ((packed)); 542} __attribute__ ((packed));
540 543
541struct cmd_ds_802_11_ad_hoc_join { 544struct cmd_ds_802_11_ad_hoc_join {
545 struct cmd_header hdr;
546
542 struct adhoc_bssdesc bss; 547 struct adhoc_bssdesc bss;
543 __le16 failtimeout; 548 __le16 failtimeout; /* Reserved on v9 and later */
544 __le16 probedelay; 549 __le16 probedelay; /* Reserved on v9 and later */
550} __attribute__ ((packed));
545 551
552struct cmd_ds_802_11_ad_hoc_stop {
553 struct cmd_header hdr;
546} __attribute__ ((packed)); 554} __attribute__ ((packed));
547 555
548struct cmd_ds_802_11_enable_rsn { 556struct cmd_ds_802_11_enable_rsn {
@@ -597,14 +605,28 @@ struct cmd_ds_802_11_eeprom_access {
597} __attribute__ ((packed)); 605} __attribute__ ((packed));
598 606
599struct cmd_ds_802_11_tpc_cfg { 607struct cmd_ds_802_11_tpc_cfg {
608 struct cmd_header hdr;
609
600 __le16 action; 610 __le16 action;
601 u8 enable; 611 uint8_t enable;
602 s8 P0; 612 int8_t P0;
603 s8 P1; 613 int8_t P1;
604 s8 P2; 614 int8_t P2;
605 u8 usesnr; 615 uint8_t usesnr;
606} __attribute__ ((packed)); 616} __attribute__ ((packed));
607 617
618
619struct cmd_ds_802_11_pa_cfg {
620 struct cmd_header hdr;
621
622 __le16 action;
623 uint8_t enable;
624 int8_t P0;
625 int8_t P1;
626 int8_t P2;
627} __attribute__ ((packed));
628
629
608struct cmd_ds_802_11_led_ctrl { 630struct cmd_ds_802_11_led_ctrl {
609 __le16 action; 631 __le16 action;
610 __le16 numled; 632 __le16 numled;
@@ -693,21 +715,13 @@ struct cmd_ds_command {
693 union { 715 union {
694 struct cmd_ds_802_11_ps_mode psmode; 716 struct cmd_ds_802_11_ps_mode psmode;
695 struct cmd_ds_802_11_associate associate; 717 struct cmd_ds_802_11_associate associate;
696 struct cmd_ds_802_11_deauthenticate deauth;
697 struct cmd_ds_802_11_ad_hoc_start ads;
698 struct cmd_ds_802_11_reset reset;
699 struct cmd_ds_802_11_ad_hoc_result result;
700 struct cmd_ds_802_11_authenticate auth; 718 struct cmd_ds_802_11_authenticate auth;
701 struct cmd_ds_802_11_get_stat gstat; 719 struct cmd_ds_802_11_get_stat gstat;
702 struct cmd_ds_802_3_get_stat gstat_8023; 720 struct cmd_ds_802_3_get_stat gstat_8023;
703 struct cmd_ds_802_11_snmp_mib smib;
704 struct cmd_ds_802_11_rf_tx_power txp;
705 struct cmd_ds_802_11_rf_antenna rant; 721 struct cmd_ds_802_11_rf_antenna rant;
706 struct cmd_ds_802_11_monitor_mode monitor; 722 struct cmd_ds_802_11_monitor_mode monitor;
707 struct cmd_ds_802_11_ad_hoc_join adj;
708 struct cmd_ds_802_11_rssi rssi; 723 struct cmd_ds_802_11_rssi rssi;
709 struct cmd_ds_802_11_rssi_rsp rssirsp; 724 struct cmd_ds_802_11_rssi_rsp rssirsp;
710 struct cmd_ds_802_11_disassociate dassociate;
711 struct cmd_ds_mac_reg_access macreg; 725 struct cmd_ds_mac_reg_access macreg;
712 struct cmd_ds_bbp_reg_access bbpreg; 726 struct cmd_ds_bbp_reg_access bbpreg;
713 struct cmd_ds_rf_reg_access rfreg; 727 struct cmd_ds_rf_reg_access rfreg;
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 04d7a251e3f0..e3505c110af6 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -595,7 +595,7 @@ static int if_cs_prog_helper(struct if_cs_card *card)
595 if (ret < 0) { 595 if (ret < 0) {
596 lbs_pr_err("can't download helper at 0x%x, ret %d\n", 596 lbs_pr_err("can't download helper at 0x%x, ret %d\n",
597 sent, ret); 597 sent, ret);
598 goto done; 598 goto err_release;
599 } 599 }
600 600
601 if (count == 0) 601 if (count == 0)
@@ -604,9 +604,8 @@ static int if_cs_prog_helper(struct if_cs_card *card)
604 sent += count; 604 sent += count;
605 } 605 }
606 606
607err_release:
607 release_firmware(fw); 608 release_firmware(fw);
608 ret = 0;
609
610done: 609done:
611 lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); 610 lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
612 return ret; 611 return ret;
@@ -676,14 +675,8 @@ static int if_cs_prog_real(struct if_cs_card *card)
676 } 675 }
677 676
678 ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a); 677 ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
679 if (ret < 0) { 678 if (ret < 0)
680 lbs_pr_err("firmware download failed\n"); 679 lbs_pr_err("firmware download failed\n");
681 goto err_release;
682 }
683
684 ret = 0;
685 goto done;
686
687 680
688err_release: 681err_release:
689 release_firmware(fw); 682 release_firmware(fw);
@@ -720,7 +713,7 @@ static int if_cs_host_to_card(struct lbs_private *priv,
720 ret = if_cs_send_cmd(priv, buf, nb); 713 ret = if_cs_send_cmd(priv, buf, nb);
721 break; 714 break;
722 default: 715 default:
723 lbs_pr_err("%s: unsupported type %d\n", __FUNCTION__, type); 716 lbs_pr_err("%s: unsupported type %d\n", __func__, type);
724 } 717 }
725 718
726 lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); 719 lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 632c291404ab..cafbccb74143 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -39,7 +39,10 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
39 39
40static void if_usb_receive(struct urb *urb); 40static void if_usb_receive(struct urb *urb);
41static void if_usb_receive_fwload(struct urb *urb); 41static void if_usb_receive_fwload(struct urb *urb);
42static int if_usb_prog_firmware(struct if_usb_card *cardp); 42static int __if_usb_prog_firmware(struct if_usb_card *cardp,
43 const char *fwname, int cmd);
44static int if_usb_prog_firmware(struct if_usb_card *cardp,
45 const char *fwname, int cmd);
43static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, 46static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
44 uint8_t *payload, uint16_t nb); 47 uint8_t *payload, uint16_t nb);
45static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, 48static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
@@ -48,6 +51,62 @@ static void if_usb_free(struct if_usb_card *cardp);
48static int if_usb_submit_rx_urb(struct if_usb_card *cardp); 51static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
49static int if_usb_reset_device(struct if_usb_card *cardp); 52static int if_usb_reset_device(struct if_usb_card *cardp);
50 53
54/* sysfs hooks */
55
56/**
57 * Set function to write firmware to device's persistent memory
58 */
59static ssize_t if_usb_firmware_set(struct device *dev,
60 struct device_attribute *attr, const char *buf, size_t count)
61{
62 struct lbs_private *priv = to_net_dev(dev)->priv;
63 struct if_usb_card *cardp = priv->card;
64 char fwname[FIRMWARE_NAME_MAX];
65 int ret;
66
67 sscanf(buf, "%29s", fwname); /* FIRMWARE_NAME_MAX - 1 = 29 */
68 ret = if_usb_prog_firmware(cardp, fwname, BOOT_CMD_UPDATE_FW);
69 if (ret == 0)
70 return count;
71
72 return ret;
73}
74
75/**
76 * lbs_flash_fw attribute to be exported per ethX interface through sysfs
77 * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to
78 * the device's persistent memory:
79 * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_fw
80 */
81static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set);
82
83/**
84 * Set function to write firmware to device's persistent memory
85 */
86static ssize_t if_usb_boot2_set(struct device *dev,
87 struct device_attribute *attr, const char *buf, size_t count)
88{
89 struct lbs_private *priv = to_net_dev(dev)->priv;
90 struct if_usb_card *cardp = priv->card;
91 char fwname[FIRMWARE_NAME_MAX];
92 int ret;
93
94 sscanf(buf, "%29s", fwname); /* FIRMWARE_NAME_MAX - 1 = 29 */
95 ret = if_usb_prog_firmware(cardp, fwname, BOOT_CMD_UPDATE_BOOT2);
96 if (ret == 0)
97 return count;
98
99 return ret;
100}
101
102/**
103 * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs
104 * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware
105 * to the device's persistent memory:
106 * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_boot2
107 */
108static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set);
109
51/** 110/**
52 * @brief call back function to handle the status of the URB 111 * @brief call back function to handle the status of the URB
53 * @param urb pointer to urb structure 112 * @param urb pointer to urb structure
@@ -66,10 +125,10 @@ static void if_usb_write_bulk_callback(struct urb *urb)
66 lbs_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n", 125 lbs_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
67 urb->actual_length); 126 urb->actual_length);
68 127
69 /* Used for both firmware TX and regular TX. priv isn't 128 /* Boot commands such as UPDATE_FW and UPDATE_BOOT2 are not
70 * valid at firmware load time. 129 * passed up to the lbs level.
71 */ 130 */
72 if (priv) 131 if (priv && priv->dnld_sent != DNLD_BOOTCMD_SENT)
73 lbs_host_to_card_done(priv); 132 lbs_host_to_card_done(priv);
74 } else { 133 } else {
75 /* print the failure status number for debug */ 134 /* print the failure status number for debug */
@@ -231,7 +290,7 @@ static int if_usb_probe(struct usb_interface *intf,
231 } 290 }
232 291
233 /* Upload firmware */ 292 /* Upload firmware */
234 if (if_usb_prog_firmware(cardp)) { 293 if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) {
235 lbs_deb_usbd(&udev->dev, "FW upload failed\n"); 294 lbs_deb_usbd(&udev->dev, "FW upload failed\n");
236 goto err_prog_firmware; 295 goto err_prog_firmware;
237 } 296 }
@@ -260,6 +319,12 @@ static int if_usb_probe(struct usb_interface *intf,
260 usb_get_dev(udev); 319 usb_get_dev(udev);
261 usb_set_intfdata(intf, cardp); 320 usb_set_intfdata(intf, cardp);
262 321
322 if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw))
323 lbs_pr_err("cannot register lbs_flash_fw attribute\n");
324
325 if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2))
326 lbs_pr_err("cannot register lbs_flash_boot2 attribute\n");
327
263 return 0; 328 return 0;
264 329
265err_start_card: 330err_start_card:
@@ -285,6 +350,9 @@ static void if_usb_disconnect(struct usb_interface *intf)
285 350
286 lbs_deb_enter(LBS_DEB_MAIN); 351 lbs_deb_enter(LBS_DEB_MAIN);
287 352
353 device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2);
354 device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_fw);
355
288 cardp->surprise_removed = 1; 356 cardp->surprise_removed = 1;
289 357
290 if (priv) { 358 if (priv) {
@@ -371,11 +439,10 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
371 *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); 439 *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
372 440
373 cmd->command = cpu_to_le16(CMD_802_11_RESET); 441 cmd->command = cpu_to_le16(CMD_802_11_RESET);
374 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN); 442 cmd->size = cpu_to_le16(sizeof(struct cmd_header));
375 cmd->result = cpu_to_le16(0); 443 cmd->result = cpu_to_le16(0);
376 cmd->seqnum = cpu_to_le16(0x5a5a); 444 cmd->seqnum = cpu_to_le16(0x5a5a);
377 cmd->params.reset.action = cpu_to_le16(CMD_ACT_HALT); 445 usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header));
378 usb_tx_block(cardp, cardp->ep_out_buf, 4 + S_DS_GEN + sizeof(struct cmd_ds_802_11_reset));
379 446
380 msleep(100); 447 msleep(100);
381 ret = usb_reset_device(cardp->udev); 448 ret = usb_reset_device(cardp->udev);
@@ -510,7 +577,7 @@ static void if_usb_receive_fwload(struct urb *urb)
510 if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) { 577 if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
511 kfree_skb(skb); 578 kfree_skb(skb);
512 if_usb_submit_rx_urb_fwload(cardp); 579 if_usb_submit_rx_urb_fwload(cardp);
513 cardp->bootcmdresp = 1; 580 cardp->bootcmdresp = BOOT_CMD_RESP_OK;
514 lbs_deb_usbd(&cardp->udev->dev, 581 lbs_deb_usbd(&cardp->udev->dev,
515 "Received valid boot command response\n"); 582 "Received valid boot command response\n");
516 return; 583 return;
@@ -526,7 +593,9 @@ static void if_usb_receive_fwload(struct urb *urb)
526 lbs_pr_info("boot cmd response wrong magic number (0x%x)\n", 593 lbs_pr_info("boot cmd response wrong magic number (0x%x)\n",
527 le32_to_cpu(bootcmdresp.magic)); 594 le32_to_cpu(bootcmdresp.magic));
528 } 595 }
529 } else if (bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) { 596 } else if ((bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) &&
597 (bootcmdresp.cmd != BOOT_CMD_UPDATE_FW) &&
598 (bootcmdresp.cmd != BOOT_CMD_UPDATE_BOOT2)) {
530 lbs_pr_info("boot cmd response cmd_tag error (%d)\n", 599 lbs_pr_info("boot cmd response cmd_tag error (%d)\n",
531 bootcmdresp.cmd); 600 bootcmdresp.cmd);
532 } else if (bootcmdresp.result != BOOT_CMD_RESP_OK) { 601 } else if (bootcmdresp.result != BOOT_CMD_RESP_OK) {
@@ -564,8 +633,8 @@ static void if_usb_receive_fwload(struct urb *urb)
564 633
565 kfree_skb(skb); 634 kfree_skb(skb);
566 635
567 /* reschedule timer for 200ms hence */ 636 /* Give device 5s to either write firmware to its RAM or eeprom */
568 mod_timer(&cardp->fw_timeout, jiffies + (HZ/5)); 637 mod_timer(&cardp->fw_timeout, jiffies + (HZ*5));
569 638
570 if (cardp->fwfinalblk) { 639 if (cardp->fwfinalblk) {
571 cardp->fwdnldover = 1; 640 cardp->fwdnldover = 1;
@@ -809,7 +878,54 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
809} 878}
810 879
811 880
812static int if_usb_prog_firmware(struct if_usb_card *cardp) 881/**
882* @brief This function programs the firmware subject to cmd
883*
884* @param cardp the if_usb_card descriptor
885* fwname firmware or boot2 image file name
886* cmd either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW,
887* or BOOT_CMD_UPDATE_BOOT2.
888* @return 0 or error code
889*/
890static int if_usb_prog_firmware(struct if_usb_card *cardp,
891 const char *fwname, int cmd)
892{
893 struct lbs_private *priv = cardp->priv;
894 unsigned long flags, caps;
895 int ret;
896
897 caps = priv->fwcapinfo;
898 if (((cmd == BOOT_CMD_UPDATE_FW) && !(caps & FW_CAPINFO_FIRMWARE_UPGRADE)) ||
899 ((cmd == BOOT_CMD_UPDATE_BOOT2) && !(caps & FW_CAPINFO_BOOT2_UPGRADE)))
900 return -EOPNOTSUPP;
901
902 /* Ensure main thread is idle. */
903 spin_lock_irqsave(&priv->driver_lock, flags);
904 while (priv->cur_cmd != NULL || priv->dnld_sent != DNLD_RES_RECEIVED) {
905 spin_unlock_irqrestore(&priv->driver_lock, flags);
906 if (wait_event_interruptible(priv->waitq,
907 (priv->cur_cmd == NULL &&
908 priv->dnld_sent == DNLD_RES_RECEIVED))) {
909 return -ERESTARTSYS;
910 }
911 spin_lock_irqsave(&priv->driver_lock, flags);
912 }
913 priv->dnld_sent = DNLD_BOOTCMD_SENT;
914 spin_unlock_irqrestore(&priv->driver_lock, flags);
915
916 ret = __if_usb_prog_firmware(cardp, fwname, cmd);
917
918 spin_lock_irqsave(&priv->driver_lock, flags);
919 priv->dnld_sent = DNLD_RES_RECEIVED;
920 spin_unlock_irqrestore(&priv->driver_lock, flags);
921
922 wake_up_interruptible(&priv->waitq);
923
924 return ret;
925}
926
927static int __if_usb_prog_firmware(struct if_usb_card *cardp,
928 const char *fwname, int cmd)
813{ 929{
814 int i = 0; 930 int i = 0;
815 static int reset_count = 10; 931 static int reset_count = 10;
@@ -817,20 +933,32 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
817 933
818 lbs_deb_enter(LBS_DEB_USB); 934 lbs_deb_enter(LBS_DEB_USB);
819 935
820 if ((ret = request_firmware(&cardp->fw, lbs_fw_name, 936 ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
821 &cardp->udev->dev)) < 0) { 937 if (ret < 0) {
822 lbs_pr_err("request_firmware() failed with %#x\n", ret); 938 lbs_pr_err("request_firmware() failed with %#x\n", ret);
823 lbs_pr_err("firmware %s not found\n", lbs_fw_name); 939 lbs_pr_err("firmware %s not found\n", fwname);
824 goto done; 940 goto done;
825 } 941 }
826 942
827 if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) 943 if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
944 ret = -EINVAL;
828 goto release_fw; 945 goto release_fw;
946 }
947
948 /* Cancel any pending usb business */
949 usb_kill_urb(cardp->rx_urb);
950 usb_kill_urb(cardp->tx_urb);
951
952 cardp->fwlastblksent = 0;
953 cardp->fwdnldover = 0;
954 cardp->totalbytes = 0;
955 cardp->fwfinalblk = 0;
956 cardp->bootcmdresp = 0;
829 957
830restart: 958restart:
831 if (if_usb_submit_rx_urb_fwload(cardp) < 0) { 959 if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
832 lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); 960 lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
833 ret = -1; 961 ret = -EIO;
834 goto release_fw; 962 goto release_fw;
835 } 963 }
836 964
@@ -838,8 +966,7 @@ restart:
838 do { 966 do {
839 int j = 0; 967 int j = 0;
840 i++; 968 i++;
841 /* Issue Boot command = 1, Boot from Download-FW */ 969 if_usb_issue_boot_command(cardp, cmd);
842 if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
843 /* wait for command response */ 970 /* wait for command response */
844 do { 971 do {
845 j++; 972 j++;
@@ -847,12 +974,21 @@ restart:
847 } while (cardp->bootcmdresp == 0 && j < 10); 974 } while (cardp->bootcmdresp == 0 && j < 10);
848 } while (cardp->bootcmdresp == 0 && i < 5); 975 } while (cardp->bootcmdresp == 0 && i < 5);
849 976
850 if (cardp->bootcmdresp <= 0) { 977 if (cardp->bootcmdresp == BOOT_CMD_RESP_NOT_SUPPORTED) {
978 /* Return to normal operation */
979 ret = -EOPNOTSUPP;
980 usb_kill_urb(cardp->rx_urb);
981 usb_kill_urb(cardp->tx_urb);
982 if (if_usb_submit_rx_urb(cardp) < 0)
983 ret = -EIO;
984 goto release_fw;
985 } else if (cardp->bootcmdresp <= 0) {
851 if (--reset_count >= 0) { 986 if (--reset_count >= 0) {
852 if_usb_reset_device(cardp); 987 if_usb_reset_device(cardp);
853 goto restart; 988 goto restart;
854 } 989 }
855 return -1; 990 ret = -EIO;
991 goto release_fw;
856 } 992 }
857 993
858 i = 0; 994 i = 0;
@@ -882,7 +1018,7 @@ restart:
882 } 1018 }
883 1019
884 lbs_pr_info("FW download failure, time = %d ms\n", i * 100); 1020 lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
885 ret = -1; 1021 ret = -EIO;
886 goto release_fw; 1022 goto release_fw;
887 } 1023 }
888 1024
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index 5771a83a43f0..5ba0aee0eb2f 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -30,6 +30,7 @@ struct bootcmd
30 30
31#define BOOT_CMD_RESP_OK 0x0001 31#define BOOT_CMD_RESP_OK 0x0001
32#define BOOT_CMD_RESP_FAIL 0x0000 32#define BOOT_CMD_RESP_FAIL 0x0000
33#define BOOT_CMD_RESP_NOT_SUPPORTED 0x0002
33 34
34struct bootcmdresp 35struct bootcmdresp
35{ 36{
@@ -50,6 +51,10 @@ struct if_usb_card {
50 uint8_t ep_in; 51 uint8_t ep_in;
51 uint8_t ep_out; 52 uint8_t ep_out;
52 53
54 /* bootcmdresp == 0 means command is pending
55 * bootcmdresp < 0 means error
56 * bootcmdresp > 0 is a BOOT_CMD_RESP_* from firmware
57 */
53 int8_t bootcmdresp; 58 int8_t bootcmdresp;
54 59
55 int ep_in_size; 60 int ep_in_size;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index bd32ac0b4e07..73dc8c72402a 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -291,9 +291,11 @@ static ssize_t lbs_rtap_set(struct device *dev,
291 if (priv->infra_open || priv->mesh_open) 291 if (priv->infra_open || priv->mesh_open)
292 return -EBUSY; 292 return -EBUSY;
293 if (priv->mode == IW_MODE_INFRA) 293 if (priv->mode == IW_MODE_INFRA)
294 lbs_send_deauthentication(priv); 294 lbs_cmd_80211_deauthenticate(priv,
295 priv->curbssparams.bssid,
296 WLAN_REASON_DEAUTH_LEAVING);
295 else if (priv->mode == IW_MODE_ADHOC) 297 else if (priv->mode == IW_MODE_ADHOC)
296 lbs_stop_adhoc_network(priv); 298 lbs_adhoc_stop(priv);
297 lbs_add_rtap(priv); 299 lbs_add_rtap(priv);
298 } 300 }
299 priv->monitormode = monitor_mode; 301 priv->monitormode = monitor_mode;
@@ -956,17 +958,24 @@ EXPORT_SYMBOL_GPL(lbs_resume);
956static int lbs_setup_firmware(struct lbs_private *priv) 958static int lbs_setup_firmware(struct lbs_private *priv)
957{ 959{
958 int ret = -1; 960 int ret = -1;
961 s16 curlevel = 0, minlevel = 0, maxlevel = 0;
959 962
960 lbs_deb_enter(LBS_DEB_FW); 963 lbs_deb_enter(LBS_DEB_FW);
961 964
962 /* 965 /* Read MAC address from firmware */
963 * Read MAC address from HW
964 */
965 memset(priv->current_addr, 0xff, ETH_ALEN); 966 memset(priv->current_addr, 0xff, ETH_ALEN);
966 ret = lbs_update_hw_spec(priv); 967 ret = lbs_update_hw_spec(priv);
967 if (ret) 968 if (ret)
968 goto done; 969 goto done;
969 970
971 /* Read power levels if available */
972 ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel);
973 if (ret == 0) {
974 priv->txpower_cur = curlevel;
975 priv->txpower_min = minlevel;
976 priv->txpower_max = maxlevel;
977 }
978
970 lbs_set_mac_control(priv); 979 lbs_set_mac_control(priv);
971done: 980done:
972 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 981 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
@@ -1042,7 +1051,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
1042 priv->mode = IW_MODE_INFRA; 1051 priv->mode = IW_MODE_INFRA;
1043 priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; 1052 priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
1044 priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; 1053 priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
1045 priv->radioon = RADIO_ON; 1054 priv->radio_on = 1;
1046 priv->enablehwauto = 1; 1055 priv->enablehwauto = 1;
1047 priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; 1056 priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
1048 priv->psmode = LBS802_11POWERMODECAM; 1057 priv->psmode = LBS802_11POWERMODECAM;
@@ -1196,7 +1205,13 @@ void lbs_remove_card(struct lbs_private *priv)
1196 cancel_delayed_work_sync(&priv->scan_work); 1205 cancel_delayed_work_sync(&priv->scan_work);
1197 cancel_delayed_work_sync(&priv->assoc_work); 1206 cancel_delayed_work_sync(&priv->assoc_work);
1198 cancel_work_sync(&priv->mcast_work); 1207 cancel_work_sync(&priv->mcast_work);
1208
1209 /* worker thread destruction blocks on the in-flight command which
1210 * should have been cleared already in lbs_stop_card().
1211 */
1212 lbs_deb_main("destroying worker thread\n");
1199 destroy_workqueue(priv->work_thread); 1213 destroy_workqueue(priv->work_thread);
1214 lbs_deb_main("done destroying worker thread\n");
1200 1215
1201 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { 1216 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
1202 priv->psmode = LBS802_11POWERMODECAM; 1217 priv->psmode = LBS802_11POWERMODECAM;
@@ -1314,14 +1329,26 @@ void lbs_stop_card(struct lbs_private *priv)
1314 device_remove_file(&dev->dev, &dev_attr_lbs_rtap); 1329 device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
1315 } 1330 }
1316 1331
1317 /* Flush pending command nodes */ 1332 /* Delete the timeout of the currently processing command */
1318 del_timer_sync(&priv->command_timer); 1333 del_timer_sync(&priv->command_timer);
1334
1335 /* Flush pending command nodes */
1319 spin_lock_irqsave(&priv->driver_lock, flags); 1336 spin_lock_irqsave(&priv->driver_lock, flags);
1337 lbs_deb_main("clearing pending commands\n");
1320 list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { 1338 list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
1321 cmdnode->result = -ENOENT; 1339 cmdnode->result = -ENOENT;
1322 cmdnode->cmdwaitqwoken = 1; 1340 cmdnode->cmdwaitqwoken = 1;
1323 wake_up_interruptible(&cmdnode->cmdwait_q); 1341 wake_up_interruptible(&cmdnode->cmdwait_q);
1324 } 1342 }
1343
1344 /* Flush the command the card is currently processing */
1345 if (priv->cur_cmd) {
1346 lbs_deb_main("clearing current command\n");
1347 priv->cur_cmd->result = -ENOENT;
1348 priv->cur_cmd->cmdwaitqwoken = 1;
1349 wake_up_interruptible(&priv->cur_cmd->cmdwait_q);
1350 }
1351 lbs_deb_main("done clearing commands\n");
1325 spin_unlock_irqrestore(&priv->driver_lock, flags); 1352 spin_unlock_irqrestore(&priv->driver_lock, flags);
1326 1353
1327 unregister_netdev(dev); 1354 unregister_netdev(dev);
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 4b274562f965..8f66903641b9 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -944,6 +944,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
944 944
945 lbs_deb_enter(LBS_DEB_WEXT); 945 lbs_deb_enter(LBS_DEB_WEXT);
946 946
947 if (!priv->radio_on) {
948 ret = -EINVAL;
949 goto out;
950 }
951
947 if (!netif_running(dev)) { 952 if (!netif_running(dev)) {
948 ret = -ENETDOWN; 953 ret = -ENETDOWN;
949 goto out; 954 goto out;
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 8b3ed77860b3..82c3e5a50ea6 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -30,6 +30,14 @@ static inline void lbs_postpone_association_work(struct lbs_private *priv)
30 queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2); 30 queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
31} 31}
32 32
33static inline void lbs_do_association_work(struct lbs_private *priv)
34{
35 if (priv->surpriseremoved)
36 return;
37 cancel_delayed_work(&priv->assoc_work);
38 queue_delayed_work(priv->work_thread, &priv->assoc_work, 0);
39}
40
33static inline void lbs_cancel_association_work(struct lbs_private *priv) 41static inline void lbs_cancel_association_work(struct lbs_private *priv)
34{ 42{
35 cancel_delayed_work(&priv->assoc_work); 43 cancel_delayed_work(&priv->assoc_work);
@@ -120,34 +128,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(
120 return cfp; 128 return cfp;
121} 129}
122 130
123
124/**
125 * @brief Set Radio On/OFF
126 *
127 * @param priv A pointer to struct lbs_private structure
128 * @option Radio Option
129 * @return 0 --success, otherwise fail
130 */
131static int lbs_radio_ioctl(struct lbs_private *priv, u8 option)
132{
133 int ret = 0;
134
135 lbs_deb_enter(LBS_DEB_WEXT);
136
137 if (priv->radioon != option) {
138 lbs_deb_wext("switching radio %s\n", option ? "on" : "off");
139 priv->radioon = option;
140
141 ret = lbs_prepare_and_send_command(priv,
142 CMD_802_11_RADIO_CONTROL,
143 CMD_ACT_SET,
144 CMD_OPTION_WAITFORRSP, 0, NULL);
145 }
146
147 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
148 return ret;
149}
150
151/** 131/**
152 * @brief Copy active data rates based on adapter mode and status 132 * @brief Copy active data rates based on adapter mode and status
153 * 133 *
@@ -294,21 +274,17 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
294{ 274{
295 int ret = 0; 275 int ret = 0;
296 struct lbs_private *priv = dev->priv; 276 struct lbs_private *priv = dev->priv;
297 u32 rthr = vwrq->value; 277 u32 val = vwrq->value;
298 278
299 lbs_deb_enter(LBS_DEB_WEXT); 279 lbs_deb_enter(LBS_DEB_WEXT);
300 280
301 if (vwrq->disabled) { 281 if (vwrq->disabled)
302 priv->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE; 282 val = MRVDRV_RTS_MAX_VALUE;
303 } else { 283
304 if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE) 284 if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */
305 return -EINVAL; 285 return -EINVAL;
306 priv->rtsthsd = rthr;
307 }
308 286
309 ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, 287 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val);
310 CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
311 OID_802_11_RTS_THRESHOLD, &rthr);
312 288
313 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 289 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
314 return ret; 290 return ret;
@@ -317,21 +293,18 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
317static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, 293static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
318 struct iw_param *vwrq, char *extra) 294 struct iw_param *vwrq, char *extra)
319{ 295{
320 int ret = 0;
321 struct lbs_private *priv = dev->priv; 296 struct lbs_private *priv = dev->priv;
297 int ret = 0;
298 u16 val = 0;
322 299
323 lbs_deb_enter(LBS_DEB_WEXT); 300 lbs_deb_enter(LBS_DEB_WEXT);
324 301
325 priv->rtsthsd = 0; 302 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
326 ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
327 CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
328 OID_802_11_RTS_THRESHOLD, NULL);
329 if (ret) 303 if (ret)
330 goto out; 304 goto out;
331 305
332 vwrq->value = priv->rtsthsd; 306 vwrq->value = val;
333 vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE) 307 vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */
334 || (vwrq->value > MRVDRV_RTS_MAX_VALUE));
335 vwrq->fixed = 1; 308 vwrq->fixed = 1;
336 309
337out: 310out:
@@ -342,24 +315,19 @@ out:
342static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, 315static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
343 struct iw_param *vwrq, char *extra) 316 struct iw_param *vwrq, char *extra)
344{ 317{
345 int ret = 0;
346 u32 fthr = vwrq->value;
347 struct lbs_private *priv = dev->priv; 318 struct lbs_private *priv = dev->priv;
319 int ret = 0;
320 u32 val = vwrq->value;
348 321
349 lbs_deb_enter(LBS_DEB_WEXT); 322 lbs_deb_enter(LBS_DEB_WEXT);
350 323
351 if (vwrq->disabled) { 324 if (vwrq->disabled)
352 priv->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE; 325 val = MRVDRV_FRAG_MAX_VALUE;
353 } else { 326
354 if (fthr < MRVDRV_FRAG_MIN_VALUE 327 if (val < MRVDRV_FRAG_MIN_VALUE || val > MRVDRV_FRAG_MAX_VALUE)
355 || fthr > MRVDRV_FRAG_MAX_VALUE) 328 return -EINVAL;
356 return -EINVAL;
357 priv->fragthsd = fthr;
358 }
359 329
360 ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, 330 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, (u16) val);
361 CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
362 OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
363 331
364 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 332 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
365 return ret; 333 return ret;
@@ -368,22 +336,19 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
368static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, 336static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
369 struct iw_param *vwrq, char *extra) 337 struct iw_param *vwrq, char *extra)
370{ 338{
371 int ret = 0;
372 struct lbs_private *priv = dev->priv; 339 struct lbs_private *priv = dev->priv;
340 int ret = 0;
341 u16 val = 0;
373 342
374 lbs_deb_enter(LBS_DEB_WEXT); 343 lbs_deb_enter(LBS_DEB_WEXT);
375 344
376 priv->fragthsd = 0; 345 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
377 ret = lbs_prepare_and_send_command(priv,
378 CMD_802_11_SNMP_MIB,
379 CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
380 OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
381 if (ret) 346 if (ret)
382 goto out; 347 goto out;
383 348
384 vwrq->value = priv->fragthsd; 349 vwrq->value = val;
385 vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE) 350 vwrq->disabled = ((val < MRVDRV_FRAG_MIN_VALUE)
386 || (vwrq->value > MRVDRV_FRAG_MAX_VALUE)); 351 || (val > MRVDRV_FRAG_MAX_VALUE));
387 vwrq->fixed = 1; 352 vwrq->fixed = 1;
388 353
389out: 354out:
@@ -410,7 +375,7 @@ static int mesh_wlan_get_mode(struct net_device *dev,
410{ 375{
411 lbs_deb_enter(LBS_DEB_WEXT); 376 lbs_deb_enter(LBS_DEB_WEXT);
412 377
413 *uwrq = IW_MODE_REPEAT ; 378 *uwrq = IW_MODE_REPEAT;
414 379
415 lbs_deb_leave(LBS_DEB_WEXT); 380 lbs_deb_leave(LBS_DEB_WEXT);
416 return 0; 381 return 0;
@@ -420,28 +385,30 @@ static int lbs_get_txpow(struct net_device *dev,
420 struct iw_request_info *info, 385 struct iw_request_info *info,
421 struct iw_param *vwrq, char *extra) 386 struct iw_param *vwrq, char *extra)
422{ 387{
423 int ret = 0;
424 struct lbs_private *priv = dev->priv; 388 struct lbs_private *priv = dev->priv;
389 s16 curlevel = 0;
390 int ret = 0;
425 391
426 lbs_deb_enter(LBS_DEB_WEXT); 392 lbs_deb_enter(LBS_DEB_WEXT);
427 393
428 ret = lbs_prepare_and_send_command(priv, 394 if (!priv->radio_on) {
429 CMD_802_11_RF_TX_POWER, 395 lbs_deb_wext("tx power off\n");
430 CMD_ACT_TX_POWER_OPT_GET, 396 vwrq->value = 0;
431 CMD_OPTION_WAITFORRSP, 0, NULL); 397 vwrq->disabled = 1;
398 goto out;
399 }
432 400
401 ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL);
433 if (ret) 402 if (ret)
434 goto out; 403 goto out;
435 404
436 lbs_deb_wext("tx power level %d dbm\n", priv->txpowerlevel); 405 lbs_deb_wext("tx power level %d dbm\n", curlevel);
437 vwrq->value = priv->txpowerlevel; 406 priv->txpower_cur = curlevel;
407
408 vwrq->value = curlevel;
438 vwrq->fixed = 1; 409 vwrq->fixed = 1;
439 if (priv->radioon) { 410 vwrq->disabled = 0;
440 vwrq->disabled = 0; 411 vwrq->flags = IW_TXPOW_DBM;
441 vwrq->flags = IW_TXPOW_DBM;
442 } else {
443 vwrq->disabled = 1;
444 }
445 412
446out: 413out:
447 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 414 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
@@ -451,31 +418,44 @@ out:
451static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, 418static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
452 struct iw_param *vwrq, char *extra) 419 struct iw_param *vwrq, char *extra)
453{ 420{
454 int ret = 0;
455 struct lbs_private *priv = dev->priv; 421 struct lbs_private *priv = dev->priv;
422 int ret = 0;
423 u16 slimit = 0, llimit = 0;
456 424
457 lbs_deb_enter(LBS_DEB_WEXT); 425 lbs_deb_enter(LBS_DEB_WEXT);
458 426
459 if (vwrq->flags == IW_RETRY_LIMIT) { 427 if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
460 /* The MAC has a 4-bit Total_Tx_Count register 428 return -EOPNOTSUPP;
461 Total_Tx_Count = 1 + Tx_Retry_Count */ 429
430 /* The MAC has a 4-bit Total_Tx_Count register
431 Total_Tx_Count = 1 + Tx_Retry_Count */
462#define TX_RETRY_MIN 0 432#define TX_RETRY_MIN 0
463#define TX_RETRY_MAX 14 433#define TX_RETRY_MAX 14
464 if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX) 434 if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
465 return -EINVAL; 435 return -EINVAL;
466 436
467 /* Adding 1 to convert retry count to try count */ 437 /* Add 1 to convert retry count to try count */
468 priv->txretrycount = vwrq->value + 1; 438 if (vwrq->flags & IW_RETRY_SHORT)
439 slimit = (u16) (vwrq->value + 1);
440 else if (vwrq->flags & IW_RETRY_LONG)
441 llimit = (u16) (vwrq->value + 1);
442 else
443 slimit = llimit = (u16) (vwrq->value + 1); /* set both */
469 444
470 ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, 445 if (llimit) {
471 CMD_ACT_SET, 446 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT,
472 CMD_OPTION_WAITFORRSP, 447 llimit);
473 OID_802_11_TX_RETRYCOUNT, NULL); 448 if (ret)
449 goto out;
450 }
474 451
452 if (slimit) {
453 /* txretrycount follows the short retry limit */
454 priv->txretrycount = slimit;
455 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT,
456 slimit);
475 if (ret) 457 if (ret)
476 goto out; 458 goto out;
477 } else {
478 return -EOPNOTSUPP;
479 } 459 }
480 460
481out: 461out:
@@ -488,22 +468,30 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
488{ 468{
489 struct lbs_private *priv = dev->priv; 469 struct lbs_private *priv = dev->priv;
490 int ret = 0; 470 int ret = 0;
471 u16 val = 0;
491 472
492 lbs_deb_enter(LBS_DEB_WEXT); 473 lbs_deb_enter(LBS_DEB_WEXT);
493 474
494 priv->txretrycount = 0;
495 ret = lbs_prepare_and_send_command(priv,
496 CMD_802_11_SNMP_MIB,
497 CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
498 OID_802_11_TX_RETRYCOUNT, NULL);
499 if (ret)
500 goto out;
501
502 vwrq->disabled = 0; 475 vwrq->disabled = 0;
503 if (!vwrq->flags) { 476
504 vwrq->flags = IW_RETRY_LIMIT; 477 if (vwrq->flags & IW_RETRY_LONG) {
478 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, &val);
479 if (ret)
480 goto out;
481
482 /* Subtract 1 to convert try count to retry count */
483 vwrq->value = val - 1;
484 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
485 } else {
486 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, &val);
487 if (ret)
488 goto out;
489
490 /* txretry count follows the short retry limit */
491 priv->txretrycount = val;
505 /* Subtract 1 to convert try count to retry count */ 492 /* Subtract 1 to convert try count to retry count */
506 vwrq->value = priv->txretrycount - 1; 493 vwrq->value = val - 1;
494 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
507 } 495 }
508 496
509out: 497out:
@@ -693,22 +681,12 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
693 681
694 range->sensitivity = 0; 682 range->sensitivity = 0;
695 683
696 /* 684 /* Setup the supported power level ranges */
697 * Setup the supported power level ranges
698 */
699 memset(range->txpower, 0, sizeof(range->txpower)); 685 memset(range->txpower, 0, sizeof(range->txpower));
700 range->txpower[0] = 5; 686 range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
701 range->txpower[1] = 7; 687 range->txpower[0] = priv->txpower_min;
702 range->txpower[2] = 9; 688 range->txpower[1] = priv->txpower_max;
703 range->txpower[3] = 11; 689 range->num_txpower = 2;
704 range->txpower[4] = 13;
705 range->txpower[5] = 15;
706 range->txpower[6] = 17;
707 range->txpower[7] = 19;
708
709 range->num_txpower = 8;
710 range->txpower_capa = IW_TXPOW_DBM;
711 range->txpower_capa |= IW_TXPOW_RANGE;
712 690
713 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | 691 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
714 IW_EVENT_CAPA_MASK(SIOCGIWAP) | 692 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
@@ -998,9 +976,11 @@ static int lbs_mesh_set_freq(struct net_device *dev,
998 if (fwrq->m != priv->curbssparams.channel) { 976 if (fwrq->m != priv->curbssparams.channel) {
999 lbs_deb_wext("mesh channel change forces eth disconnect\n"); 977 lbs_deb_wext("mesh channel change forces eth disconnect\n");
1000 if (priv->mode == IW_MODE_INFRA) 978 if (priv->mode == IW_MODE_INFRA)
1001 lbs_send_deauthentication(priv); 979 lbs_cmd_80211_deauthenticate(priv,
980 priv->curbssparams.bssid,
981 WLAN_REASON_DEAUTH_LEAVING);
1002 else if (priv->mode == IW_MODE_ADHOC) 982 else if (priv->mode == IW_MODE_ADHOC)
1003 lbs_stop_adhoc_network(priv); 983 lbs_adhoc_stop(priv);
1004 } 984 }
1005 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m); 985 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m);
1006 lbs_update_channel(priv); 986 lbs_update_channel(priv);
@@ -1045,6 +1025,18 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
1045 new_rate); 1025 new_rate);
1046 goto out; 1026 goto out;
1047 } 1027 }
1028 if (priv->fwrelease < 0x09000000) {
1029 ret = lbs_set_power_adapt_cfg(priv, 0,
1030 POW_ADAPT_DEFAULT_P0,
1031 POW_ADAPT_DEFAULT_P1,
1032 POW_ADAPT_DEFAULT_P2);
1033 if (ret)
1034 goto out;
1035 }
1036 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
1037 TPC_DEFAULT_P2, 1);
1038 if (ret)
1039 goto out;
1048 } 1040 }
1049 1041
1050 /* Try the newer command first (Firmware Spec 5.1 and above) */ 1042 /* Try the newer command first (Firmware Spec 5.1 and above) */
@@ -1612,12 +1604,26 @@ static int lbs_set_encodeext(struct net_device *dev,
1612 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); 1604 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1613 } 1605 }
1614 1606
1615 disable_wep (assoc_req); 1607 /* Only disable wep if necessary: can't waste time here. */
1608 if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE)
1609 disable_wep(assoc_req);
1616 } 1610 }
1617 1611
1618out: 1612out:
1619 if (ret == 0) { 1613 if (ret == 0) {
1620 lbs_postpone_association_work(priv); 1614 /* 802.1x and WPA rekeying must happen as quickly as possible,
1615 * especially during the 4-way handshake; thus if in
1616 * infrastructure mode, and either (a) 802.1x is enabled or
1617 * (b) WPA is being used, set the key right away.
1618 */
1619 if (assoc_req->mode == IW_MODE_INFRA &&
1620 ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) ||
1621 (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) ||
1622 assoc_req->secinfo.WPAenabled ||
1623 assoc_req->secinfo.WPA2enabled)) {
1624 lbs_do_association_work(priv);
1625 } else
1626 lbs_postpone_association_work(priv);
1621 } else { 1627 } else {
1622 lbs_cancel_association_work(priv); 1628 lbs_cancel_association_work(priv);
1623 } 1629 }
@@ -1725,13 +1731,17 @@ static int lbs_set_auth(struct net_device *dev,
1725 case IW_AUTH_TKIP_COUNTERMEASURES: 1731 case IW_AUTH_TKIP_COUNTERMEASURES:
1726 case IW_AUTH_CIPHER_PAIRWISE: 1732 case IW_AUTH_CIPHER_PAIRWISE:
1727 case IW_AUTH_CIPHER_GROUP: 1733 case IW_AUTH_CIPHER_GROUP:
1728 case IW_AUTH_KEY_MGMT:
1729 case IW_AUTH_DROP_UNENCRYPTED: 1734 case IW_AUTH_DROP_UNENCRYPTED:
1730 /* 1735 /*
1731 * libertas does not use these parameters 1736 * libertas does not use these parameters
1732 */ 1737 */
1733 break; 1738 break;
1734 1739
1740 case IW_AUTH_KEY_MGMT:
1741 assoc_req->secinfo.key_mgmt = dwrq->value;
1742 updated = 1;
1743 break;
1744
1735 case IW_AUTH_WPA_VERSION: 1745 case IW_AUTH_WPA_VERSION:
1736 if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { 1746 if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
1737 assoc_req->secinfo.WPAenabled = 0; 1747 assoc_req->secinfo.WPAenabled = 0;
@@ -1811,6 +1821,10 @@ static int lbs_get_auth(struct net_device *dev,
1811 lbs_deb_enter(LBS_DEB_WEXT); 1821 lbs_deb_enter(LBS_DEB_WEXT);
1812 1822
1813 switch (dwrq->flags & IW_AUTH_INDEX) { 1823 switch (dwrq->flags & IW_AUTH_INDEX) {
1824 case IW_AUTH_KEY_MGMT:
1825 dwrq->value = priv->secinfo.key_mgmt;
1826 break;
1827
1814 case IW_AUTH_WPA_VERSION: 1828 case IW_AUTH_WPA_VERSION:
1815 dwrq->value = 0; 1829 dwrq->value = 0;
1816 if (priv->secinfo.WPAenabled) 1830 if (priv->secinfo.WPAenabled)
@@ -1844,39 +1858,77 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
1844{ 1858{
1845 int ret = 0; 1859 int ret = 0;
1846 struct lbs_private *priv = dev->priv; 1860 struct lbs_private *priv = dev->priv;
1847 1861 s16 dbm = (s16) vwrq->value;
1848 u16 dbm;
1849 1862
1850 lbs_deb_enter(LBS_DEB_WEXT); 1863 lbs_deb_enter(LBS_DEB_WEXT);
1851 1864
1852 if (vwrq->disabled) { 1865 if (vwrq->disabled) {
1853 lbs_radio_ioctl(priv, RADIO_OFF); 1866 lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
1854 return 0; 1867 goto out;
1855 } 1868 }
1856 1869
1857 priv->preamble = CMD_TYPE_AUTO_PREAMBLE; 1870 if (vwrq->fixed == 0) {
1858 1871 /* User requests automatic tx power control, however there are
1859 lbs_radio_ioctl(priv, RADIO_ON); 1872 * many auto tx settings. For now use firmware defaults until
1873 * we come up with a good way to expose these to the user. */
1874 if (priv->fwrelease < 0x09000000) {
1875 ret = lbs_set_power_adapt_cfg(priv, 1,
1876 POW_ADAPT_DEFAULT_P0,
1877 POW_ADAPT_DEFAULT_P1,
1878 POW_ADAPT_DEFAULT_P2);
1879 if (ret)
1880 goto out;
1881 }
1882 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
1883 TPC_DEFAULT_P2, 1);
1884 if (ret)
1885 goto out;
1886 dbm = priv->txpower_max;
1887 } else {
1888 /* Userspace check in iwrange if it should use dBm or mW,
1889 * therefore this should never happen... Jean II */
1890 if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
1891 ret = -EOPNOTSUPP;
1892 goto out;
1893 }
1860 1894
1861 /* Userspace check in iwrange if it should use dBm or mW, 1895 /* Validate requested power level against firmware allowed
1862 * therefore this should never happen... Jean II */ 1896 * levels */
1863 if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) { 1897 if (priv->txpower_min && (dbm < priv->txpower_min)) {
1864 return -EOPNOTSUPP; 1898 ret = -EINVAL;
1865 } else 1899 goto out;
1866 dbm = (u16) vwrq->value; 1900 }
1867 1901
1868 /* auto tx power control */ 1902 if (priv->txpower_max && (dbm > priv->txpower_max)) {
1903 ret = -EINVAL;
1904 goto out;
1905 }
1906 if (priv->fwrelease < 0x09000000) {
1907 ret = lbs_set_power_adapt_cfg(priv, 0,
1908 POW_ADAPT_DEFAULT_P0,
1909 POW_ADAPT_DEFAULT_P1,
1910 POW_ADAPT_DEFAULT_P2);
1911 if (ret)
1912 goto out;
1913 }
1914 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
1915 TPC_DEFAULT_P2, 1);
1916 if (ret)
1917 goto out;
1918 }
1869 1919
1870 if (vwrq->fixed == 0) 1920 /* If the radio was off, turn it on */
1871 dbm = 0xffff; 1921 if (!priv->radio_on) {
1922 ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1);
1923 if (ret)
1924 goto out;
1925 }
1872 1926
1873 lbs_deb_wext("txpower set %d dbm\n", dbm); 1927 lbs_deb_wext("txpower set %d dBm\n", dbm);
1874 1928
1875 ret = lbs_prepare_and_send_command(priv, 1929 ret = lbs_set_tx_power(priv, dbm);
1876 CMD_802_11_RF_TX_POWER,
1877 CMD_ACT_TX_POWER_OPT_SET_LOW,
1878 CMD_OPTION_WAITFORRSP, 0, (void *)&dbm);
1879 1930
1931out:
1880 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1932 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1881 return ret; 1933 return ret;
1882} 1934}
@@ -1928,6 +1980,11 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
1928 1980
1929 lbs_deb_enter(LBS_DEB_WEXT); 1981 lbs_deb_enter(LBS_DEB_WEXT);
1930 1982
1983 if (!priv->radio_on) {
1984 ret = -EINVAL;
1985 goto out;
1986 }
1987
1931 /* Check the size of the string */ 1988 /* Check the size of the string */
1932 if (in_ssid_len > IW_ESSID_MAX_SIZE) { 1989 if (in_ssid_len > IW_ESSID_MAX_SIZE) {
1933 ret = -E2BIG; 1990 ret = -E2BIG;
@@ -2005,6 +2062,11 @@ static int lbs_mesh_set_essid(struct net_device *dev,
2005 2062
2006 lbs_deb_enter(LBS_DEB_WEXT); 2063 lbs_deb_enter(LBS_DEB_WEXT);
2007 2064
2065 if (!priv->radio_on) {
2066 ret = -EINVAL;
2067 goto out;
2068 }
2069
2008 /* Check the size of the string */ 2070 /* Check the size of the string */
2009 if (dwrq->length > IW_ESSID_MAX_SIZE) { 2071 if (dwrq->length > IW_ESSID_MAX_SIZE) {
2010 ret = -E2BIG; 2072 ret = -E2BIG;
@@ -2046,6 +2108,9 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
2046 2108
2047 lbs_deb_enter(LBS_DEB_WEXT); 2109 lbs_deb_enter(LBS_DEB_WEXT);
2048 2110
2111 if (!priv->radio_on)
2112 return -EINVAL;
2113
2049 if (awrq->sa_family != ARPHRD_ETHER) 2114 if (awrq->sa_family != ARPHRD_ETHER)
2050 return -EINVAL; 2115 return -EINVAL;
2051 2116