aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-01 15:26:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:01:51 -0400
commitbc92afd92088ab41223383cc6863ab4792533c54 (patch)
treea31d14843f5a63a4a4561bb2ac59e83f4550433c
parentf21293549f60f88c74fcb9944737f11048896dc4 (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.c22
-rw-r--r--drivers/net/wireless/iwmc3200wifi/wext.c47
-rw-r--r--include/net/cfg80211.h13
-rw-r--r--net/mac80211/Kconfig16
-rw-r--r--net/mac80211/cfg.c26
-rw-r--r--net/mac80211/mlme.c5
-rw-r--r--net/mac80211/wext.c70
-rw-r--r--net/wireless/Kconfig16
-rw-r--r--net/wireless/core.c11
-rw-r--r--net/wireless/wext-compat.c60
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
525static 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
525static struct cfg80211_ops iwm_cfg80211_ops = { 546static 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
539struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) 561struct 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
241static 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
273static 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
284static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) 241static 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
1615int cfg80211_wext_siwpower(struct net_device *dev,
1616 struct iw_request_info *info,
1617 struct iw_param *wrq, char *extra);
1618int 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
14comment "CFG80211 needs to be enabled for MAC80211" 14comment "CFG80211 needs to be enabled for MAC80211"
15 depends on CFG80211=n 15 depends on CFG80211=n
16 16
17config 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
28config MAC80211_DEFAULT_PS_VALUE
29 int
30 default 1 if MAC80211_DEFAULT_PS
31 default 0
32
33menu "Rate control algorithm selection" 17menu "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
1391static 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
1391struct cfg80211_ops mac80211_config_ops = { 1416struct 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
258static 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
312static 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 */
325static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev) 259static 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
29config 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
40config CFG80211_DEFAULT_PS_VALUE
41 int
42 default 1 if CFG80211_DEFAULT_PS
43 default 0
44
29config CFG80211_DEBUGFS 45config 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}
989EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth); 989EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
990
991int 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}
1037EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower);
1038
1039int 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}
1049EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);