diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-07-01 15:26:57 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-10 15:01:51 -0400 |
commit | bc92afd92088ab41223383cc6863ab4792533c54 (patch) | |
tree | a31d14843f5a63a4a4561bb2ac59e83f4550433c | |
parent | f21293549f60f88c74fcb9944737f11048896dc4 (diff) |
cfg80211: implement iwpower
Just on/off and timeout, and with a hacky cfg80211 method
until we figure out what we want, though this is probably
sufficient as we want to use pm_qos for wifi everywhere.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/cfg80211.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/wext.c | 47 | ||||
-rw-r--r-- | include/net/cfg80211.h | 13 | ||||
-rw-r--r-- | net/mac80211/Kconfig | 16 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 26 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 5 | ||||
-rw-r--r-- | net/mac80211/wext.c | 70 | ||||
-rw-r--r-- | net/wireless/Kconfig | 16 | ||||
-rw-r--r-- | net/wireless/core.c | 11 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 60 |
10 files changed, 151 insertions, 135 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index d0629d4757d7..54bebba8e27e 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -522,6 +522,27 @@ static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) | |||
522 | return 0; | 522 | return 0; |
523 | } | 523 | } |
524 | 524 | ||
525 | static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy, | ||
526 | struct net_device *dev, | ||
527 | bool enabled, int timeout) | ||
528 | { | ||
529 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | ||
530 | u32 power_index; | ||
531 | |||
532 | if (enabled) | ||
533 | power_index = IWM_POWER_INDEX_DEFAULT; | ||
534 | else | ||
535 | power_index = IWM_POWER_INDEX_MIN; | ||
536 | |||
537 | if (power_index == iwm->conf.power_index) | ||
538 | return 0; | ||
539 | |||
540 | iwm->conf.power_index = power_index; | ||
541 | |||
542 | return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, | ||
543 | CFG_POWER_INDEX, iwm->conf.power_index); | ||
544 | } | ||
545 | |||
525 | static struct cfg80211_ops iwm_cfg80211_ops = { | 546 | static struct cfg80211_ops iwm_cfg80211_ops = { |
526 | .change_virtual_intf = iwm_cfg80211_change_iface, | 547 | .change_virtual_intf = iwm_cfg80211_change_iface, |
527 | .add_key = iwm_cfg80211_add_key, | 548 | .add_key = iwm_cfg80211_add_key, |
@@ -534,6 +555,7 @@ static struct cfg80211_ops iwm_cfg80211_ops = { | |||
534 | .leave_ibss = iwm_cfg80211_leave_ibss, | 555 | .leave_ibss = iwm_cfg80211_leave_ibss, |
535 | .set_tx_power = iwm_cfg80211_set_txpower, | 556 | .set_tx_power = iwm_cfg80211_set_txpower, |
536 | .get_tx_power = iwm_cfg80211_get_txpower, | 557 | .get_tx_power = iwm_cfg80211_get_txpower, |
558 | .set_power_mgmt = iwm_cfg80211_set_power_mgmt, | ||
537 | }; | 559 | }; |
538 | 560 | ||
539 | struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) | 561 | struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) |
diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 973457383c11..2e7eaf96cf93 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c | |||
@@ -238,49 +238,6 @@ static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) | |||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | static int iwm_wext_siwpower(struct net_device *dev, | ||
242 | struct iw_request_info *info, | ||
243 | struct iw_param *wrq, char *extra) | ||
244 | { | ||
245 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
246 | u32 power_index; | ||
247 | |||
248 | if (wrq->disabled) { | ||
249 | power_index = IWM_POWER_INDEX_MIN; | ||
250 | goto set; | ||
251 | } else | ||
252 | power_index = IWM_POWER_INDEX_DEFAULT; | ||
253 | |||
254 | switch (wrq->flags & IW_POWER_MODE) { | ||
255 | case IW_POWER_ON: | ||
256 | case IW_POWER_MODE: | ||
257 | case IW_POWER_ALL_R: | ||
258 | break; | ||
259 | default: | ||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | set: | ||
264 | if (power_index == iwm->conf.power_index) | ||
265 | return 0; | ||
266 | |||
267 | iwm->conf.power_index = power_index; | ||
268 | |||
269 | return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, | ||
270 | CFG_POWER_INDEX, iwm->conf.power_index); | ||
271 | } | ||
272 | |||
273 | static int iwm_wext_giwpower(struct net_device *dev, | ||
274 | struct iw_request_info *info, | ||
275 | union iwreq_data *wrqu, char *extra) | ||
276 | { | ||
277 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
278 | |||
279 | wrqu->power.disabled = (iwm->conf.power_index == IWM_POWER_INDEX_MIN); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) | 241 | static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) |
285 | { | 242 | { |
286 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | 243 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; |
@@ -458,8 +415,8 @@ static const iw_handler iwm_handlers[] = | |||
458 | (iw_handler) NULL, /* SIOCGIWRETRY */ | 415 | (iw_handler) NULL, /* SIOCGIWRETRY */ |
459 | (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ | 416 | (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ |
460 | (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ | 417 | (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ |
461 | (iw_handler) iwm_wext_siwpower, /* SIOCSIWPOWER */ | 418 | (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */ |
462 | (iw_handler) iwm_wext_giwpower, /* SIOCGIWPOWER */ | 419 | (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ |
463 | (iw_handler) NULL, /* -- hole -- */ | 420 | (iw_handler) NULL, /* -- hole -- */ |
464 | (iw_handler) NULL, /* -- hole -- */ | 421 | (iw_handler) NULL, /* -- hole -- */ |
465 | (iw_handler) NULL, /* SIOCSIWGENIE */ | 422 | (iw_handler) NULL, /* SIOCSIWGENIE */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 07085216532d..82b7d804f6da 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1023,6 +1023,10 @@ struct cfg80211_ops { | |||
1023 | #ifdef CONFIG_NL80211_TESTMODE | 1023 | #ifdef CONFIG_NL80211_TESTMODE |
1024 | int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len); | 1024 | int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len); |
1025 | #endif | 1025 | #endif |
1026 | |||
1027 | /* some temporary stuff to finish wext */ | ||
1028 | int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, | ||
1029 | bool enabled, int timeout); | ||
1026 | }; | 1030 | }; |
1027 | 1031 | ||
1028 | /* | 1032 | /* |
@@ -1262,6 +1266,8 @@ struct wireless_dev { | |||
1262 | u8 bssid[ETH_ALEN]; | 1266 | u8 bssid[ETH_ALEN]; |
1263 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 1267 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
1264 | s8 default_key, default_mgmt_key; | 1268 | s8 default_key, default_mgmt_key; |
1269 | bool ps; | ||
1270 | int ps_timeout; | ||
1265 | } wext; | 1271 | } wext; |
1266 | #endif | 1272 | #endif |
1267 | }; | 1273 | }; |
@@ -1606,6 +1612,13 @@ int cfg80211_wext_giwtxpower(struct net_device *dev, | |||
1606 | struct iw_request_info *info, | 1612 | struct iw_request_info *info, |
1607 | union iwreq_data *data, char *keybuf); | 1613 | union iwreq_data *data, char *keybuf); |
1608 | 1614 | ||
1615 | int cfg80211_wext_siwpower(struct net_device *dev, | ||
1616 | struct iw_request_info *info, | ||
1617 | struct iw_param *wrq, char *extra); | ||
1618 | int cfg80211_wext_giwpower(struct net_device *dev, | ||
1619 | struct iw_request_info *info, | ||
1620 | struct iw_param *wrq, char *extra); | ||
1621 | |||
1609 | /* | 1622 | /* |
1610 | * callbacks for asynchronous cfg80211 methods, notification | 1623 | * callbacks for asynchronous cfg80211 methods, notification |
1611 | * functions and BSS handling helpers | 1624 | * functions and BSS handling helpers |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index ba2643a43c73..41a32cd919af 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -14,22 +14,6 @@ config MAC80211 | |||
14 | comment "CFG80211 needs to be enabled for MAC80211" | 14 | comment "CFG80211 needs to be enabled for MAC80211" |
15 | depends on CFG80211=n | 15 | depends on CFG80211=n |
16 | 16 | ||
17 | config MAC80211_DEFAULT_PS | ||
18 | bool "enable powersave by default" | ||
19 | depends on MAC80211 | ||
20 | default y | ||
21 | help | ||
22 | This option enables powersave mode by default. | ||
23 | |||
24 | If this causes your applications to misbehave you should fix your | ||
25 | applications instead -- they need to register their network | ||
26 | latency requirement, see Documentation/power/pm_qos_interface.txt. | ||
27 | |||
28 | config MAC80211_DEFAULT_PS_VALUE | ||
29 | int | ||
30 | default 1 if MAC80211_DEFAULT_PS | ||
31 | default 0 | ||
32 | |||
33 | menu "Rate control algorithm selection" | 17 | menu "Rate control algorithm selection" |
34 | depends on MAC80211 != n | 18 | depends on MAC80211 != n |
35 | 19 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 03de4024597a..8c7b2cdbeeda 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1388,6 +1388,31 @@ int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) | |||
1388 | } | 1388 | } |
1389 | #endif | 1389 | #endif |
1390 | 1390 | ||
1391 | static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | ||
1392 | bool enabled, int timeout) | ||
1393 | { | ||
1394 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1395 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1396 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1397 | |||
1398 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) | ||
1399 | return -EOPNOTSUPP; | ||
1400 | |||
1401 | if (enabled == sdata->u.mgd.powersave && | ||
1402 | timeout == conf->dynamic_ps_timeout) | ||
1403 | return 0; | ||
1404 | |||
1405 | sdata->u.mgd.powersave = enabled; | ||
1406 | conf->dynamic_ps_timeout = timeout; | ||
1407 | |||
1408 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | ||
1409 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
1410 | |||
1411 | ieee80211_recalc_ps(local, -1); | ||
1412 | |||
1413 | return 0; | ||
1414 | } | ||
1415 | |||
1391 | struct cfg80211_ops mac80211_config_ops = { | 1416 | struct cfg80211_ops mac80211_config_ops = { |
1392 | .add_virtual_intf = ieee80211_add_iface, | 1417 | .add_virtual_intf = ieee80211_add_iface, |
1393 | .del_virtual_intf = ieee80211_del_iface, | 1418 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1431,4 +1456,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1431 | .get_tx_power = ieee80211_get_tx_power, | 1456 | .get_tx_power = ieee80211_get_tx_power, |
1432 | .rfkill_poll = ieee80211_rfkill_poll, | 1457 | .rfkill_poll = ieee80211_rfkill_poll, |
1433 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) | 1458 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) |
1459 | .set_power_mgmt = ieee80211_set_power_mgmt, | ||
1434 | }; | 1460 | }; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fbb93a70ddc7..2a7860009f9c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2360,11 +2360,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2360 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; | 2360 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; |
2361 | 2361 | ||
2362 | hw_flags = sdata->local->hw.flags; | 2362 | hw_flags = sdata->local->hw.flags; |
2363 | |||
2364 | if (hw_flags & IEEE80211_HW_SUPPORTS_PS) { | ||
2365 | ifmgd->powersave = CONFIG_MAC80211_DEFAULT_PS_VALUE; | ||
2366 | sdata->local->hw.conf.dynamic_ps_timeout = 500; | ||
2367 | } | ||
2368 | } | 2363 | } |
2369 | 2364 | ||
2370 | /* configuration hooks */ | 2365 | /* configuration hooks */ |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index d4e61dc903e8..f77929802c7a 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -255,72 +255,6 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, | |||
255 | return 0; | 255 | return 0; |
256 | } | 256 | } |
257 | 257 | ||
258 | static int ieee80211_ioctl_siwpower(struct net_device *dev, | ||
259 | struct iw_request_info *info, | ||
260 | struct iw_param *wrq, | ||
261 | char *extra) | ||
262 | { | ||
263 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
264 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
265 | struct ieee80211_conf *conf = &local->hw.conf; | ||
266 | int timeout = 0; | ||
267 | bool ps; | ||
268 | |||
269 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) | ||
270 | return -EOPNOTSUPP; | ||
271 | |||
272 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
273 | return -EINVAL; | ||
274 | |||
275 | if (wrq->disabled) { | ||
276 | ps = false; | ||
277 | timeout = 0; | ||
278 | goto set; | ||
279 | } | ||
280 | |||
281 | switch (wrq->flags & IW_POWER_MODE) { | ||
282 | case IW_POWER_ON: /* If not specified */ | ||
283 | case IW_POWER_MODE: /* If set all mask */ | ||
284 | case IW_POWER_ALL_R: /* If explicitely state all */ | ||
285 | ps = true; | ||
286 | break; | ||
287 | default: /* Otherwise we ignore */ | ||
288 | return -EINVAL; | ||
289 | } | ||
290 | |||
291 | if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT)) | ||
292 | return -EINVAL; | ||
293 | |||
294 | if (wrq->flags & IW_POWER_TIMEOUT) | ||
295 | timeout = wrq->value / 1000; | ||
296 | |||
297 | set: | ||
298 | if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout) | ||
299 | return 0; | ||
300 | |||
301 | sdata->u.mgd.powersave = ps; | ||
302 | conf->dynamic_ps_timeout = timeout; | ||
303 | |||
304 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | ||
305 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
306 | |||
307 | ieee80211_recalc_ps(local, -1); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int ieee80211_ioctl_giwpower(struct net_device *dev, | ||
313 | struct iw_request_info *info, | ||
314 | union iwreq_data *wrqu, | ||
315 | char *extra) | ||
316 | { | ||
317 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
318 | |||
319 | wrqu->power.disabled = !sdata->u.mgd.powersave; | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ | 258 | /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ |
325 | static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev) | 259 | static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev) |
326 | { | 260 | { |
@@ -436,8 +370,8 @@ static const iw_handler ieee80211_handler[] = | |||
436 | (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ | 370 | (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ |
437 | (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ | 371 | (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ |
438 | (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ | 372 | (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ |
439 | (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ | 373 | (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */ |
440 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ | 374 | (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ |
441 | (iw_handler) NULL, /* -- hole -- */ | 375 | (iw_handler) NULL, /* -- hole -- */ |
442 | (iw_handler) NULL, /* -- hole -- */ | 376 | (iw_handler) NULL, /* -- hole -- */ |
443 | (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ | 377 | (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 040263118a20..c6031d5b135f 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -26,6 +26,22 @@ config CFG80211_REG_DEBUG | |||
26 | 26 | ||
27 | If unsure, say N. | 27 | If unsure, say N. |
28 | 28 | ||
29 | config CFG80211_DEFAULT_PS | ||
30 | bool "enable powersave by default" | ||
31 | depends on CFG80211 | ||
32 | default y | ||
33 | help | ||
34 | This option enables powersave mode by default. | ||
35 | |||
36 | If this causes your applications to misbehave you should fix your | ||
37 | applications instead -- they need to register their network | ||
38 | latency requirement, see Documentation/power/pm_qos_interface.txt. | ||
39 | |||
40 | config CFG80211_DEFAULT_PS_VALUE | ||
41 | int | ||
42 | default 1 if CFG80211_DEFAULT_PS | ||
43 | default 0 | ||
44 | |||
29 | config CFG80211_DEBUGFS | 45 | config CFG80211_DEBUGFS |
30 | bool "cfg80211 DebugFS entries" | 46 | bool "cfg80211 DebugFS entries" |
31 | depends on CFG80211 && DEBUG_FS | 47 | depends on CFG80211 && DEBUG_FS |
diff --git a/net/wireless/core.c b/net/wireless/core.c index e2f80dd0e4a6..413d291d07d7 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -550,12 +550,21 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
550 | } | 550 | } |
551 | wdev->netdev = dev; | 551 | wdev->netdev = dev; |
552 | wdev->sme_state = CFG80211_SME_IDLE; | 552 | wdev->sme_state = CFG80211_SME_IDLE; |
553 | mutex_unlock(&rdev->devlist_mtx); | ||
553 | #ifdef CONFIG_WIRELESS_EXT | 554 | #ifdef CONFIG_WIRELESS_EXT |
554 | wdev->wext.default_key = -1; | 555 | wdev->wext.default_key = -1; |
555 | wdev->wext.default_mgmt_key = -1; | 556 | wdev->wext.default_mgmt_key = -1; |
556 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 557 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
558 | wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE; | ||
559 | wdev->wext.ps_timeout = 500; | ||
560 | if (rdev->ops->set_power_mgmt) | ||
561 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, | ||
562 | wdev->wext.ps, | ||
563 | wdev->wext.ps_timeout)) { | ||
564 | /* assume this means it's off */ | ||
565 | wdev->wext.ps = false; | ||
566 | } | ||
557 | #endif | 567 | #endif |
558 | mutex_unlock(&rdev->devlist_mtx); | ||
559 | break; | 568 | break; |
560 | case NETDEV_GOING_DOWN: | 569 | case NETDEV_GOING_DOWN: |
561 | if (!wdev->ssid_len) | 570 | if (!wdev->ssid_len) |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 02f052fc1808..2e1ab78fb0d7 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -987,3 +987,63 @@ int cfg80211_wext_giwauth(struct net_device *dev, | |||
987 | return -EOPNOTSUPP; | 987 | return -EOPNOTSUPP; |
988 | } | 988 | } |
989 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth); | 989 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth); |
990 | |||
991 | int cfg80211_wext_siwpower(struct net_device *dev, | ||
992 | struct iw_request_info *info, | ||
993 | struct iw_param *wrq, char *extra) | ||
994 | { | ||
995 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
996 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
997 | bool ps = wdev->wext.ps; | ||
998 | int timeout = wdev->wext.ps_timeout; | ||
999 | int err; | ||
1000 | |||
1001 | if (wdev->iftype != NL80211_IFTYPE_STATION) | ||
1002 | return -EINVAL; | ||
1003 | |||
1004 | if (!rdev->ops->set_power_mgmt) | ||
1005 | return -EOPNOTSUPP; | ||
1006 | |||
1007 | if (wrq->disabled) { | ||
1008 | ps = false; | ||
1009 | } else { | ||
1010 | switch (wrq->flags & IW_POWER_MODE) { | ||
1011 | case IW_POWER_ON: /* If not specified */ | ||
1012 | case IW_POWER_MODE: /* If set all mask */ | ||
1013 | case IW_POWER_ALL_R: /* If explicitely state all */ | ||
1014 | ps = true; | ||
1015 | break; | ||
1016 | default: /* Otherwise we ignore */ | ||
1017 | return -EINVAL; | ||
1018 | } | ||
1019 | |||
1020 | if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT)) | ||
1021 | return -EINVAL; | ||
1022 | |||
1023 | if (wrq->flags & IW_POWER_TIMEOUT) | ||
1024 | timeout = wrq->value / 1000; | ||
1025 | } | ||
1026 | |||
1027 | err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout); | ||
1028 | if (err) | ||
1029 | return err; | ||
1030 | |||
1031 | wdev->wext.ps = ps; | ||
1032 | wdev->wext.ps_timeout = timeout; | ||
1033 | |||
1034 | return 0; | ||
1035 | |||
1036 | } | ||
1037 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower); | ||
1038 | |||
1039 | int cfg80211_wext_giwpower(struct net_device *dev, | ||
1040 | struct iw_request_info *info, | ||
1041 | struct iw_param *wrq, char *extra) | ||
1042 | { | ||
1043 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1044 | |||
1045 | wrq->disabled = !wdev->wext.ps; | ||
1046 | |||
1047 | return 0; | ||
1048 | } | ||
1049 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower); | ||