aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-06-02 07:01:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-06-03 14:06:14 -0400
commit7643a2c3fcc13cd6fbd731f214463547383418ae (patch)
treee2e41315f0d38a8627456303820b5c1c2a9b54a6
parentc64fb01627e24725d1f9d535e4426475a4415753 (diff)
cfg80211: move txpower wext from mac80211
This patch introduces new cfg80211 API to set the TX power via cfg80211, puts the wext code into cfg80211 and updates mac80211 to use all that. The -ENETDOWN bits are a hack but will go away soon. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/cfg80211.h30
-rw-r--r--net/mac80211/cfg.c54
-rw-r--r--net/mac80211/wext.c80
-rw-r--r--net/wireless/wext-compat.c80
4 files changed, 166 insertions, 78 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f20da7d63b1e..8b8e4b893625 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -752,6 +752,21 @@ enum wiphy_params_flags {
752}; 752};
753 753
754/** 754/**
755 * enum tx_power_setting - TX power adjustment
756 *
757 * @TX_POWER_AUTOMATIC: the dbm parameter is ignored
758 * @TX_POWER_LIMITED: limit TX power by the dbm parameter
759 * @TX_POWER_FIXED: fix TX power to the dbm parameter
760 * @TX_POWER_OFF: turn off completely (will go away)
761 */
762enum tx_power_setting {
763 TX_POWER_AUTOMATIC,
764 TX_POWER_LIMITED,
765 TX_POWER_FIXED,
766 TX_POWER_OFF,
767};
768
769/**
755 * struct cfg80211_ops - backend description for wireless configuration 770 * struct cfg80211_ops - backend description for wireless configuration
756 * 771 *
757 * This struct is registered by fullmac card drivers and/or wireless stacks 772 * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -837,6 +852,11 @@ enum wiphy_params_flags {
837 * @changed bitfield (see &enum wiphy_params_flags) describes which values 852 * @changed bitfield (see &enum wiphy_params_flags) describes which values
838 * have changed. The actual parameter values are available in 853 * have changed. The actual parameter values are available in
839 * struct wiphy. If returning an error, no value should be changed. 854 * struct wiphy. If returning an error, no value should be changed.
855 *
856 * @set_tx_power: set the transmit power according to the parameters
857 * @get_tx_power: store the current TX power into the dbm variable;
858 * return 0 if successful; or -ENETDOWN if successful but power
859 * is disabled (this will go away)
840 */ 860 */
841struct cfg80211_ops { 861struct cfg80211_ops {
842 int (*suspend)(struct wiphy *wiphy); 862 int (*suspend)(struct wiphy *wiphy);
@@ -928,6 +948,10 @@ struct cfg80211_ops {
928 int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev); 948 int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
929 949
930 int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed); 950 int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
951
952 int (*set_tx_power)(struct wiphy *wiphy,
953 enum tx_power_setting type, int dbm);
954 int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
931}; 955};
932 956
933/* 957/*
@@ -1451,6 +1475,12 @@ int cfg80211_wext_siwencode(struct net_device *dev,
1451int cfg80211_wext_giwencode(struct net_device *dev, 1475int cfg80211_wext_giwencode(struct net_device *dev,
1452 struct iw_request_info *info, 1476 struct iw_request_info *info,
1453 struct iw_point *erq, char *keybuf); 1477 struct iw_point *erq, char *keybuf);
1478int cfg80211_wext_siwtxpower(struct net_device *dev,
1479 struct iw_request_info *info,
1480 union iwreq_data *data, char *keybuf);
1481int cfg80211_wext_giwtxpower(struct net_device *dev,
1482 struct iw_request_info *info,
1483 union iwreq_data *data, char *keybuf);
1454 1484
1455/* 1485/*
1456 * callbacks for asynchronous cfg80211 methods, notification 1486 * callbacks for asynchronous cfg80211 methods, notification
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d2fc18c1ae0d..81258acf48bc 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1334,6 +1334,58 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1334 return 0; 1334 return 0;
1335} 1335}
1336 1336
1337static int ieee80211_set_tx_power(struct wiphy *wiphy,
1338 enum tx_power_setting type, int dbm)
1339{
1340 struct ieee80211_local *local = wiphy_priv(wiphy);
1341 struct ieee80211_channel *chan = local->hw.conf.channel;
1342 u32 changes = 0;
1343 bool radio_enabled = true;
1344
1345 switch (type) {
1346 case TX_POWER_AUTOMATIC:
1347 local->user_power_level = -1;
1348 break;
1349 case TX_POWER_LIMITED:
1350 if (dbm < 0)
1351 return -EINVAL;
1352 local->user_power_level = dbm;
1353 break;
1354 case TX_POWER_FIXED:
1355 if (dbm < 0)
1356 return -EINVAL;
1357 /* TODO: move to cfg80211 when it knows the channel */
1358 if (dbm > chan->max_power)
1359 return -EINVAL;
1360 local->user_power_level = dbm;
1361 break;
1362 case TX_POWER_OFF:
1363 radio_enabled = false;
1364 break;
1365 }
1366
1367 if (radio_enabled != local->hw.conf.radio_enabled) {
1368 changes |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
1369 local->hw.conf.radio_enabled = radio_enabled;
1370 }
1371
1372 ieee80211_hw_config(local, changes);
1373
1374 return 0;
1375}
1376
1377static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)
1378{
1379 struct ieee80211_local *local = wiphy_priv(wiphy);
1380
1381 *dbm = local->hw.conf.power_level;
1382
1383 if (!local->hw.conf.radio_enabled)
1384 return -ENETDOWN;
1385
1386 return 0;
1387}
1388
1337struct cfg80211_ops mac80211_config_ops = { 1389struct cfg80211_ops mac80211_config_ops = {
1338 .add_virtual_intf = ieee80211_add_iface, 1390 .add_virtual_intf = ieee80211_add_iface,
1339 .del_virtual_intf = ieee80211_del_iface, 1391 .del_virtual_intf = ieee80211_del_iface,
@@ -1373,4 +1425,6 @@ struct cfg80211_ops mac80211_config_ops = {
1373 .join_ibss = ieee80211_join_ibss, 1425 .join_ibss = ieee80211_join_ibss,
1374 .leave_ibss = ieee80211_leave_ibss, 1426 .leave_ibss = ieee80211_leave_ibss,
1375 .set_wiphy_params = ieee80211_set_wiphy_params, 1427 .set_wiphy_params = ieee80211_set_wiphy_params,
1428 .set_tx_power = ieee80211_set_tx_power,
1429 .get_tx_power = ieee80211_get_tx_power,
1376}; 1430};
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index a01154e127f0..d2d81b103341 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -306,82 +306,6 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev,
306 return 0; 306 return 0;
307} 307}
308 308
309static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
310 struct iw_request_info *info,
311 union iwreq_data *data, char *extra)
312{
313 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
314 struct ieee80211_channel* chan = local->hw.conf.channel;
315 bool reconf = false;
316 u32 reconf_flags = 0;
317 int new_power_level;
318
319 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
320 return -EINVAL;
321 if (data->txpower.flags & IW_TXPOW_RANGE)
322 return -EINVAL;
323 if (!chan)
324 return -EINVAL;
325
326 /* only change when not disabling */
327 if (!data->txpower.disabled) {
328 if (data->txpower.fixed) {
329 if (data->txpower.value < 0)
330 return -EINVAL;
331 new_power_level = data->txpower.value;
332 /*
333 * Debatable, but we cannot do a fixed power
334 * level above the regulatory constraint.
335 * Use "iwconfig wlan0 txpower 15dBm" instead.
336 */
337 if (new_power_level > chan->max_power)
338 return -EINVAL;
339 } else {
340 /*
341 * Automatic power level setting, max being the value
342 * passed in from userland.
343 */
344 if (data->txpower.value < 0)
345 new_power_level = -1;
346 else
347 new_power_level = data->txpower.value;
348 }
349
350 reconf = true;
351
352 /*
353 * ieee80211_hw_config() will limit to the channel's
354 * max power and possibly power constraint from AP.
355 */
356 local->user_power_level = new_power_level;
357 }
358
359 if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
360 local->hw.conf.radio_enabled = !(data->txpower.disabled);
361 reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
362 ieee80211_led_radio(local, local->hw.conf.radio_enabled);
363 }
364
365 if (reconf || reconf_flags)
366 ieee80211_hw_config(local, reconf_flags);
367
368 return 0;
369}
370
371static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
372 struct iw_request_info *info,
373 union iwreq_data *data, char *extra)
374{
375 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
376
377 data->txpower.fixed = 1;
378 data->txpower.disabled = !(local->hw.conf.radio_enabled);
379 data->txpower.value = local->hw.conf.power_level;
380 data->txpower.flags = IW_TXPOW_DBM;
381
382 return 0;
383}
384
385static int ieee80211_ioctl_siwpower(struct net_device *dev, 309static int ieee80211_ioctl_siwpower(struct net_device *dev,
386 struct iw_request_info *info, 310 struct iw_request_info *info,
387 struct iw_param *wrq, 311 struct iw_param *wrq,
@@ -658,8 +582,8 @@ static const iw_handler ieee80211_handler[] =
658 (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ 582 (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
659 (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ 583 (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
660 (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */ 584 (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
661 (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */ 585 (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */
662 (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ 586 (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */
663 (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ 587 (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
664 (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ 588 (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
665 (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ 589 (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 711e00a0c9b5..9fbfb8536e75 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -744,3 +744,83 @@ int cfg80211_wext_giwencode(struct net_device *dev,
744 return err; 744 return err;
745} 745}
746EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); 746EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
747
748int cfg80211_wext_siwtxpower(struct net_device *dev,
749 struct iw_request_info *info,
750 union iwreq_data *data, char *extra)
751{
752 struct wireless_dev *wdev = dev->ieee80211_ptr;
753 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
754 enum tx_power_setting type;
755 int dbm = 0;
756
757 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
758 return -EINVAL;
759 if (data->txpower.flags & IW_TXPOW_RANGE)
760 return -EINVAL;
761
762 if (!rdev->ops->set_tx_power)
763 return -EOPNOTSUPP;
764
765 /* only change when not disabling */
766 if (!data->txpower.disabled) {
767 if (data->txpower.fixed) {
768 /*
769 * wext doesn't support negative values, see
770 * below where it's for automatic
771 */
772 if (data->txpower.value < 0)
773 return -EINVAL;
774 dbm = data->txpower.value;
775 type = TX_POWER_FIXED;
776 /* TODO: do regulatory check! */
777 } else {
778 /*
779 * Automatic power level setting, max being the value
780 * passed in from userland.
781 */
782 if (data->txpower.value < 0) {
783 type = TX_POWER_AUTOMATIC;
784 } else {
785 dbm = data->txpower.value;
786 type = TX_POWER_LIMITED;
787 }
788 }
789 } else {
790 type = TX_POWER_OFF;
791 }
792
793 return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);;
794}
795EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
796
797int cfg80211_wext_giwtxpower(struct net_device *dev,
798 struct iw_request_info *info,
799 union iwreq_data *data, char *extra)
800{
801 struct wireless_dev *wdev = dev->ieee80211_ptr;
802 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
803 int err, val;
804
805 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
806 return -EINVAL;
807 if (data->txpower.flags & IW_TXPOW_RANGE)
808 return -EINVAL;
809
810 if (!rdev->ops->get_tx_power)
811 return -EOPNOTSUPP;
812
813 err = rdev->ops->get_tx_power(wdev->wiphy, &val);
814 /* HACK!!! */
815 if (err && err != -ENETDOWN)
816 return err;
817
818 /* well... oh well */
819 data->txpower.fixed = 1;
820 data->txpower.disabled = err == -ENETDOWN;
821 data->txpower.value = val;
822 data->txpower.flags = IW_TXPOW_DBM;
823
824 return 0;
825}
826EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);