aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/wext.c
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2009-09-30 23:04:38 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:43 -0400
commit4912545472d71e3dd546b18b397aec4c89fd7403 (patch)
treeb7b0d520cdbee35303caf69881f7898e38966bc7 /drivers/net/wireless/libertas/wext.c
parent125b181aec7a67c71234284ecf6d9c729d05deda (diff)
libertas: Add auto deep sleep support for SD8385/SD8686/SD8688
Add timer based auto deep sleep feature in libertas driver which can be configured using iwconfig command. This is tested on SD8688, SD8686 cards with firmware versions 10.38.1.p25, 9.70.4.p0 respectively on 32-bit and 64-bit platforms. Tests have been done for USB/CS cards to make sure that the patch won't break USB/CS code. We didn't test the if_spi driver. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/wext.c')
-rw-r--r--drivers/net/wireless/libertas/wext.c185
1 files changed, 183 insertions, 2 deletions
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index be837a0d2517..38a451edb703 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -45,6 +45,31 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv)
45 priv->pending_assoc_req = NULL; 45 priv->pending_assoc_req = NULL;
46} 46}
47 47
48/**
49 * @brief This function checks if the command is allowed.
50 *
51 * @param priv A pointer to lbs_private structure
52 * @return allowed or not allowed.
53 */
54
55int lbs_is_cmd_allowed(struct lbs_private *priv)
56{
57 int ret = 1;
58
59 lbs_deb_enter(LBS_DEB_WEXT);
60
61 if (!priv->is_auto_deep_sleep_enabled) {
62 if (priv->is_deep_sleep) {
63 lbs_deb_wext("IOCTLS called when station"
64 "is in deep sleep\n");
65 ret = 0;
66 }
67 }
68
69 lbs_deb_leave(LBS_DEB_WEXT);
70 return ret;
71}
72
48 73
49/** 74/**
50 * @brief Find the channel frequency power info with specific channel 75 * @brief Find the channel frequency power info with specific channel
@@ -168,6 +193,11 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
168 193
169 lbs_deb_enter(LBS_DEB_WEXT); 194 lbs_deb_enter(LBS_DEB_WEXT);
170 195
196 if (!lbs_is_cmd_allowed(priv)) {
197 lbs_deb_leave(LBS_DEB_WEXT);
198 return -EBUSY;
199 }
200
171 cfp = lbs_find_cfp_by_band_and_channel(priv, 0, 201 cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
172 priv->curbssparams.channel); 202 priv->curbssparams.channel);
173 203
@@ -278,6 +308,12 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
278 308
279 lbs_deb_enter(LBS_DEB_WEXT); 309 lbs_deb_enter(LBS_DEB_WEXT);
280 310
311 if (!lbs_is_cmd_allowed(priv)) {
312 ret = -EBUSY;
313 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
314 return ret;
315 }
316
281 if (vwrq->disabled) 317 if (vwrq->disabled)
282 val = MRVDRV_RTS_MAX_VALUE; 318 val = MRVDRV_RTS_MAX_VALUE;
283 319
@@ -299,6 +335,11 @@ static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
299 335
300 lbs_deb_enter(LBS_DEB_WEXT); 336 lbs_deb_enter(LBS_DEB_WEXT);
301 337
338 if (!lbs_is_cmd_allowed(priv)) {
339 ret = -EBUSY;
340 goto out;
341 }
342
302 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val); 343 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
303 if (ret) 344 if (ret)
304 goto out; 345 goto out;
@@ -321,6 +362,12 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
321 362
322 lbs_deb_enter(LBS_DEB_WEXT); 363 lbs_deb_enter(LBS_DEB_WEXT);
323 364
365 if (!lbs_is_cmd_allowed(priv)) {
366 ret = -EBUSY;
367 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
368 return ret;
369 }
370
324 if (vwrq->disabled) 371 if (vwrq->disabled)
325 val = MRVDRV_FRAG_MAX_VALUE; 372 val = MRVDRV_FRAG_MAX_VALUE;
326 373
@@ -342,6 +389,11 @@ static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
342 389
343 lbs_deb_enter(LBS_DEB_WEXT); 390 lbs_deb_enter(LBS_DEB_WEXT);
344 391
392 if (!lbs_is_cmd_allowed(priv)) {
393 ret = -EBUSY;
394 goto out;
395 }
396
345 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val); 397 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
346 if (ret) 398 if (ret)
347 goto out; 399 goto out;
@@ -391,6 +443,11 @@ static int lbs_get_txpow(struct net_device *dev,
391 443
392 lbs_deb_enter(LBS_DEB_WEXT); 444 lbs_deb_enter(LBS_DEB_WEXT);
393 445
446 if (!lbs_is_cmd_allowed(priv)) {
447 ret = -EBUSY;
448 goto out;
449 }
450
394 if (!priv->radio_on) { 451 if (!priv->radio_on) {
395 lbs_deb_wext("tx power off\n"); 452 lbs_deb_wext("tx power off\n");
396 vwrq->value = 0; 453 vwrq->value = 0;
@@ -424,6 +481,11 @@ static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
424 481
425 lbs_deb_enter(LBS_DEB_WEXT); 482 lbs_deb_enter(LBS_DEB_WEXT);
426 483
484 if (!lbs_is_cmd_allowed(priv)) {
485 ret = -EBUSY;
486 goto out;
487 }
488
427 if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) 489 if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
428 return -EOPNOTSUPP; 490 return -EOPNOTSUPP;
429 491
@@ -472,6 +534,11 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
472 534
473 lbs_deb_enter(LBS_DEB_WEXT); 535 lbs_deb_enter(LBS_DEB_WEXT);
474 536
537 if (!lbs_is_cmd_allowed(priv)) {
538 ret = -EBUSY;
539 goto out;
540 }
541
475 vwrq->disabled = 0; 542 vwrq->disabled = 0;
476 543
477 if (vwrq->flags & IW_RETRY_LONG) { 544 if (vwrq->flags & IW_RETRY_LONG) {
@@ -709,6 +776,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
709 struct iw_param *vwrq, char *extra) 776 struct iw_param *vwrq, char *extra)
710{ 777{
711 struct lbs_private *priv = dev->ml_priv; 778 struct lbs_private *priv = dev->ml_priv;
779 int ret = 0;
712 780
713 lbs_deb_enter(LBS_DEB_WEXT); 781 lbs_deb_enter(LBS_DEB_WEXT);
714 782
@@ -737,8 +805,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
737 "setting power timeout is not supported\n"); 805 "setting power timeout is not supported\n");
738 return -EINVAL; 806 return -EINVAL;
739 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { 807 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
740 lbs_deb_wext("setting power period not supported\n"); 808 vwrq->value = vwrq->value / 1000;
741 return -EINVAL; 809 if (!priv->enter_deep_sleep) {
810 lbs_pr_err("deep sleep feature is not implemented "
811 "for this interface driver\n");
812 return -EINVAL;
813 }
814
815 if (priv->connect_status == LBS_CONNECTED) {
816 if ((priv->is_auto_deep_sleep_enabled) &&
817 (vwrq->value == -1000)) {
818 lbs_exit_auto_deep_sleep(priv);
819 return 0;
820 } else {
821 lbs_pr_err("can't use deep sleep cmd in "
822 "connected state\n");
823 return -EINVAL;
824 }
825 }
826
827 if ((vwrq->value < 0) && (vwrq->value != -1000)) {
828 lbs_pr_err("unknown option\n");
829 return -EINVAL;
830 }
831
832 if (vwrq->value > 0) {
833 if (!priv->is_auto_deep_sleep_enabled) {
834 priv->is_activity_detected = 0;
835 priv->auto_deep_sleep_timeout = vwrq->value;
836 lbs_enter_auto_deep_sleep(priv);
837 } else {
838 priv->auto_deep_sleep_timeout = vwrq->value;
839 lbs_deb_debugfs("auto deep sleep: "
840 "already enabled\n");
841 }
842 return 0;
843 } else {
844 if (priv->is_auto_deep_sleep_enabled) {
845 lbs_exit_auto_deep_sleep(priv);
846 /* Try to exit deep sleep if auto */
847 /*deep sleep disabled */
848 ret = lbs_set_deep_sleep(priv, 0);
849 }
850 if (vwrq->value == 0)
851 ret = lbs_set_deep_sleep(priv, 1);
852 else if (vwrq->value == -1000)
853 ret = lbs_set_deep_sleep(priv, 0);
854 return ret;
855 }
742 } 856 }
743 857
744 if (priv->psmode != LBS802_11POWERMODECAM) { 858 if (priv->psmode != LBS802_11POWERMODECAM) {
@@ -752,6 +866,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
752 } 866 }
753 867
754 lbs_deb_leave(LBS_DEB_WEXT); 868 lbs_deb_leave(LBS_DEB_WEXT);
869
755 return 0; 870 return 0;
756} 871}
757 872
@@ -792,6 +907,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
792 907
793 lbs_deb_enter(LBS_DEB_WEXT); 908 lbs_deb_enter(LBS_DEB_WEXT);
794 909
910 if (!lbs_is_cmd_allowed(priv))
911 return NULL;
912
795 priv->wstats.status = priv->mode; 913 priv->wstats.status = priv->mode;
796 914
797 /* If we're not associated, all quality values are meaningless */ 915 /* If we're not associated, all quality values are meaningless */
@@ -892,6 +1010,12 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
892 1010
893 lbs_deb_enter(LBS_DEB_WEXT); 1011 lbs_deb_enter(LBS_DEB_WEXT);
894 1012
1013 if (!lbs_is_cmd_allowed(priv)) {
1014 ret = -EBUSY;
1015 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1016 return ret;
1017 }
1018
895 mutex_lock(&priv->lock); 1019 mutex_lock(&priv->lock);
896 assoc_req = lbs_get_association_request(priv); 1020 assoc_req = lbs_get_association_request(priv);
897 if (!assoc_req) { 1021 if (!assoc_req) {
@@ -1000,6 +1124,12 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
1000 u8 rates[MAX_RATES + 1]; 1124 u8 rates[MAX_RATES + 1];
1001 1125
1002 lbs_deb_enter(LBS_DEB_WEXT); 1126 lbs_deb_enter(LBS_DEB_WEXT);
1127
1128 if (!lbs_is_cmd_allowed(priv)) {
1129 ret = -EBUSY;
1130 goto out;
1131 }
1132
1003 lbs_deb_wext("vwrq->value %d\n", vwrq->value); 1133 lbs_deb_wext("vwrq->value %d\n", vwrq->value);
1004 lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); 1134 lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
1005 1135
@@ -1058,6 +1188,11 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
1058 1188
1059 lbs_deb_enter(LBS_DEB_WEXT); 1189 lbs_deb_enter(LBS_DEB_WEXT);
1060 1190
1191 if (!lbs_is_cmd_allowed(priv)) {
1192 lbs_deb_leave(LBS_DEB_WEXT);
1193 return -EBUSY;
1194 }
1195
1061 if (priv->connect_status == LBS_CONNECTED) { 1196 if (priv->connect_status == LBS_CONNECTED) {
1062 vwrq->value = priv->cur_rate * 500000; 1197 vwrq->value = priv->cur_rate * 500000;
1063 1198
@@ -1084,6 +1219,11 @@ static int lbs_set_mode(struct net_device *dev,
1084 1219
1085 lbs_deb_enter(LBS_DEB_WEXT); 1220 lbs_deb_enter(LBS_DEB_WEXT);
1086 1221
1222 if (!lbs_is_cmd_allowed(priv)) {
1223 ret = -EBUSY;
1224 goto out;
1225 }
1226
1087 if ( (*uwrq != IW_MODE_ADHOC) 1227 if ( (*uwrq != IW_MODE_ADHOC)
1088 && (*uwrq != IW_MODE_INFRA) 1228 && (*uwrq != IW_MODE_INFRA)
1089 && (*uwrq != IW_MODE_AUTO)) { 1229 && (*uwrq != IW_MODE_AUTO)) {
@@ -1325,6 +1465,12 @@ static int lbs_set_encode(struct net_device *dev,
1325 1465
1326 lbs_deb_enter(LBS_DEB_WEXT); 1466 lbs_deb_enter(LBS_DEB_WEXT);
1327 1467
1468 if (!lbs_is_cmd_allowed(priv)) {
1469 ret = -EBUSY;
1470 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1471 return ret;
1472 }
1473
1328 mutex_lock(&priv->lock); 1474 mutex_lock(&priv->lock);
1329 assoc_req = lbs_get_association_request(priv); 1475 assoc_req = lbs_get_association_request(priv);
1330 if (!assoc_req) { 1476 if (!assoc_req) {
@@ -1508,6 +1654,12 @@ static int lbs_set_encodeext(struct net_device *dev,
1508 1654
1509 lbs_deb_enter(LBS_DEB_WEXT); 1655 lbs_deb_enter(LBS_DEB_WEXT);
1510 1656
1657 if (!lbs_is_cmd_allowed(priv)) {
1658 ret = -EBUSY;
1659 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1660 return ret;
1661 }
1662
1511 mutex_lock(&priv->lock); 1663 mutex_lock(&priv->lock);
1512 assoc_req = lbs_get_association_request(priv); 1664 assoc_req = lbs_get_association_request(priv);
1513 if (!assoc_req) { 1665 if (!assoc_req) {
@@ -1720,6 +1872,12 @@ static int lbs_set_auth(struct net_device *dev,
1720 1872
1721 lbs_deb_enter(LBS_DEB_WEXT); 1873 lbs_deb_enter(LBS_DEB_WEXT);
1722 1874
1875 if (!lbs_is_cmd_allowed(priv)) {
1876 ret = -EBUSY;
1877 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1878 return ret;
1879 }
1880
1723 mutex_lock(&priv->lock); 1881 mutex_lock(&priv->lock);
1724 assoc_req = lbs_get_association_request(priv); 1882 assoc_req = lbs_get_association_request(priv);
1725 if (!assoc_req) { 1883 if (!assoc_req) {
@@ -1822,6 +1980,12 @@ static int lbs_get_auth(struct net_device *dev,
1822 1980
1823 lbs_deb_enter(LBS_DEB_WEXT); 1981 lbs_deb_enter(LBS_DEB_WEXT);
1824 1982
1983 if (!lbs_is_cmd_allowed(priv)) {
1984 ret = -EBUSY;
1985 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1986 return ret;
1987 }
1988
1825 switch (dwrq->flags & IW_AUTH_INDEX) { 1989 switch (dwrq->flags & IW_AUTH_INDEX) {
1826 case IW_AUTH_KEY_MGMT: 1990 case IW_AUTH_KEY_MGMT:
1827 dwrq->value = priv->secinfo.key_mgmt; 1991 dwrq->value = priv->secinfo.key_mgmt;
@@ -1864,6 +2028,11 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
1864 2028
1865 lbs_deb_enter(LBS_DEB_WEXT); 2029 lbs_deb_enter(LBS_DEB_WEXT);
1866 2030
2031 if (!lbs_is_cmd_allowed(priv)) {
2032 ret = -EBUSY;
2033 goto out;
2034 }
2035
1867 if (vwrq->disabled) { 2036 if (vwrq->disabled) {
1868 lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0); 2037 lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
1869 goto out; 2038 goto out;
@@ -1983,6 +2152,12 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
1983 2152
1984 lbs_deb_enter(LBS_DEB_WEXT); 2153 lbs_deb_enter(LBS_DEB_WEXT);
1985 2154
2155 if (!lbs_is_cmd_allowed(priv)) {
2156 ret = -EBUSY;
2157 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2158 return ret;
2159 }
2160
1986 if (!priv->radio_on) { 2161 if (!priv->radio_on) {
1987 ret = -EINVAL; 2162 ret = -EINVAL;
1988 goto out; 2163 goto out;
@@ -2110,6 +2285,12 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
2110 2285
2111 lbs_deb_enter(LBS_DEB_WEXT); 2286 lbs_deb_enter(LBS_DEB_WEXT);
2112 2287
2288 if (!lbs_is_cmd_allowed(priv)) {
2289 ret = -EBUSY;
2290 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2291 return ret;
2292 }
2293
2113 if (!priv->radio_on) 2294 if (!priv->radio_on)
2114 return -EINVAL; 2295 return -EINVAL;
2115 2296