aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/wext.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/wext.c')
-rw-r--r--drivers/net/wireless/libertas/wext.c363
1 files changed, 214 insertions, 149 deletions
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