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 /net | |
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>
Diffstat (limited to 'net')
-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 |
7 files changed, 114 insertions, 90 deletions
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); | ||