aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-06-02 13:01:39 +0200
committerJohn W. Linville <linville@tuxdriver.com>2009-06-03 14:06:14 -0400
commit7643a2c3fcc13cd6fbd731f214463547383418ae (patch)
treee2e41315f0d38a8627456303820b5c1c2a9b54a6 /net
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>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c54
-rw-r--r--net/mac80211/wext.c80
-rw-r--r--net/wireless/wext-compat.c80
3 files changed, 136 insertions, 78 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d2fc18c1ae0..81258acf48b 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)
return 0;
}
+static int ieee80211_set_tx_power(struct wiphy *wiphy,
+ enum tx_power_setting type, int dbm)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_channel *chan = local->hw.conf.channel;
+ u32 changes = 0;
+ bool radio_enabled = true;
+
+ switch (type) {
+ case TX_POWER_AUTOMATIC:
+ local->user_power_level = -1;
+ break;
+ case TX_POWER_LIMITED:
+ if (dbm < 0)
+ return -EINVAL;
+ local->user_power_level = dbm;
+ break;
+ case TX_POWER_FIXED:
+ if (dbm < 0)
+ return -EINVAL;
+ /* TODO: move to cfg80211 when it knows the channel */
+ if (dbm > chan->max_power)
+ return -EINVAL;
+ local->user_power_level = dbm;
+ break;
+ case TX_POWER_OFF:
+ radio_enabled = false;
+ break;
+ }
+
+ if (radio_enabled != local->hw.conf.radio_enabled) {
+ changes |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
+ local->hw.conf.radio_enabled = radio_enabled;
+ }
+
+ ieee80211_hw_config(local, changes);
+
+ return 0;
+}
+
+static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+
+ *dbm = local->hw.conf.power_level;
+
+ if (!local->hw.conf.radio_enabled)
+ return -ENETDOWN;
+
+ return 0;
+}
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -1373,4 +1425,6 @@ struct cfg80211_ops mac80211_config_ops = {
.join_ibss = ieee80211_join_ibss,
.leave_ibss = ieee80211_leave_ibss,
.set_wiphy_params = ieee80211_set_wiphy_params,
+ .set_tx_power = ieee80211_set_tx_power,
+ .get_tx_power = ieee80211_get_tx_power,
};
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index a01154e127f..d2d81b10334 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -306,82 +306,6 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev,
return 0;
}
-static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *data, char *extra)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_channel* chan = local->hw.conf.channel;
- bool reconf = false;
- u32 reconf_flags = 0;
- int new_power_level;
-
- if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
- return -EINVAL;
- if (data->txpower.flags & IW_TXPOW_RANGE)
- return -EINVAL;
- if (!chan)
- return -EINVAL;
-
- /* only change when not disabling */
- if (!data->txpower.disabled) {
- if (data->txpower.fixed) {
- if (data->txpower.value < 0)
- return -EINVAL;
- new_power_level = data->txpower.value;
- /*
- * Debatable, but we cannot do a fixed power
- * level above the regulatory constraint.
- * Use "iwconfig wlan0 txpower 15dBm" instead.
- */
- if (new_power_level > chan->max_power)
- return -EINVAL;
- } else {
- /*
- * Automatic power level setting, max being the value
- * passed in from userland.
- */
- if (data->txpower.value < 0)
- new_power_level = -1;
- else
- new_power_level = data->txpower.value;
- }
-
- reconf = true;
-
- /*
- * ieee80211_hw_config() will limit to the channel's
- * max power and possibly power constraint from AP.
- */
- local->user_power_level = new_power_level;
- }
-
- if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
- local->hw.conf.radio_enabled = !(data->txpower.disabled);
- reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
- ieee80211_led_radio(local, local->hw.conf.radio_enabled);
- }
-
- if (reconf || reconf_flags)
- ieee80211_hw_config(local, reconf_flags);
-
- return 0;
-}
-
-static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *data, char *extra)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-
- data->txpower.fixed = 1;
- data->txpower.disabled = !(local->hw.conf.radio_enabled);
- data->txpower.value = local->hw.conf.power_level;
- data->txpower.flags = IW_TXPOW_DBM;
-
- return 0;
-}
-
static int ieee80211_ioctl_siwpower(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *wrq,
@@ -658,8 +582,8 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
(iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
(iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
- (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */
- (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
+ (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */
+ (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */
(iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
(iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
(iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 711e00a0c9b..9fbfb8536e7 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,
return err;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
+
+int cfg80211_wext_siwtxpower(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *data, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ enum tx_power_setting type;
+ int dbm = 0;
+
+ if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
+ return -EINVAL;
+ if (data->txpower.flags & IW_TXPOW_RANGE)
+ return -EINVAL;
+
+ if (!rdev->ops->set_tx_power)
+ return -EOPNOTSUPP;
+
+ /* only change when not disabling */
+ if (!data->txpower.disabled) {
+ if (data->txpower.fixed) {
+ /*
+ * wext doesn't support negative values, see
+ * below where it's for automatic
+ */
+ if (data->txpower.value < 0)
+ return -EINVAL;
+ dbm = data->txpower.value;
+ type = TX_POWER_FIXED;
+ /* TODO: do regulatory check! */
+ } else {
+ /*
+ * Automatic power level setting, max being the value
+ * passed in from userland.
+ */
+ if (data->txpower.value < 0) {
+ type = TX_POWER_AUTOMATIC;
+ } else {
+ dbm = data->txpower.value;
+ type = TX_POWER_LIMITED;
+ }
+ }
+ } else {
+ type = TX_POWER_OFF;
+ }
+
+ return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
+
+int cfg80211_wext_giwtxpower(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *data, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ int err, val;
+
+ if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
+ return -EINVAL;
+ if (data->txpower.flags & IW_TXPOW_RANGE)
+ return -EINVAL;
+
+ if (!rdev->ops->get_tx_power)
+ return -EOPNOTSUPP;
+
+ err = rdev->ops->get_tx_power(wdev->wiphy, &val);
+ /* HACK!!! */
+ if (err && err != -ENETDOWN)
+ return err;
+
+ /* well... oh well */
+ data->txpower.fixed = 1;
+ data->txpower.disabled = err == -ENETDOWN;
+ data->txpower.value = val;
+ data->txpower.flags = IW_TXPOW_DBM;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);