aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-04-07 09:22:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-16 10:39:08 -0400
commit47afbaf5af9454a7a1a64591e20cbfcc27ca67a8 (patch)
treede3a92c6fa90d0b7830bbb538869b8ff41e8b0ea /net
parent853da11b94e674445e93660f47a5f0aeeea09623 (diff)
mac80211: correct wext transmit power handler
Wext makes no assumptions about the contents of data->txpower.fixed and data->txpower.value when data->txpower.disabled is set, so do not update the user-requested power level while disabling. Also, when wext configures a really _fixed_ power output [1], we should reject it instead of limiting it to the regulatory constraint. If the user wants to set a _limit_ [2] then we should honour that. [1] iwconfig wlan0 txpower 20dBm fixed [2] iwconfig wlan0 txpower 10dBm This fixes http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1942 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/main.c2
-rw-r--r--net/mac80211/wext.c41
2 files changed, 34 insertions, 9 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index a6f1d8a869bc..fbcbed6cad01 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -258,7 +258,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
258 (chan->max_power - local->power_constr_level) : 258 (chan->max_power - local->power_constr_level) :
259 chan->max_power; 259 chan->max_power;
260 260
261 if (local->user_power_level) 261 if (local->user_power_level >= 0)
262 power = min(power, local->user_power_level); 262 power = min(power, local->user_power_level);
263 263
264 if (local->hw.conf.power_level != power) { 264 if (local->hw.conf.power_level != power) {
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index deb4ecec122a..ce9115c18152 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -417,6 +417,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
417{ 417{
418 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 418 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
419 struct ieee80211_channel* chan = local->hw.conf.channel; 419 struct ieee80211_channel* chan = local->hw.conf.channel;
420 bool reconf = false;
420 u32 reconf_flags = 0; 421 u32 reconf_flags = 0;
421 int new_power_level; 422 int new_power_level;
422 423
@@ -427,14 +428,38 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
427 if (!chan) 428 if (!chan)
428 return -EINVAL; 429 return -EINVAL;
429 430
430 if (data->txpower.fixed) 431 /* only change when not disabling */
431 new_power_level = min(data->txpower.value, chan->max_power); 432 if (!data->txpower.disabled) {
432 else /* Automatic power level setting */ 433 if (data->txpower.fixed) {
433 new_power_level = chan->max_power; 434 if (data->txpower.value < 0)
435 return -EINVAL;
436 new_power_level = data->txpower.value;
437 /*
438 * Debatable, but we cannot do a fixed power
439 * level above the regulatory constraint.
440 * Use "iwconfig wlan0 txpower 15dBm" instead.
441 */
442 if (new_power_level > chan->max_power)
443 return -EINVAL;
444 } else {
445 /*
446 * Automatic power level setting, max being the value
447 * passed in from userland.
448 */
449 if (data->txpower.value < 0)
450 new_power_level = -1;
451 else
452 new_power_level = data->txpower.value;
453 }
454
455 reconf = true;
434 456
435 local->user_power_level = new_power_level; 457 /*
436 if (local->hw.conf.power_level != new_power_level) 458 * ieee80211_hw_config() will limit to the channel's
437 reconf_flags |= IEEE80211_CONF_CHANGE_POWER; 459 * max power and possibly power constraint from AP.
460 */
461 local->user_power_level = new_power_level;
462 }
438 463
439 if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { 464 if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
440 local->hw.conf.radio_enabled = !(data->txpower.disabled); 465 local->hw.conf.radio_enabled = !(data->txpower.disabled);
@@ -442,7 +467,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
442 ieee80211_led_radio(local, local->hw.conf.radio_enabled); 467 ieee80211_led_radio(local, local->hw.conf.radio_enabled);
443 } 468 }
444 469
445 if (reconf_flags) 470 if (reconf || reconf_flags)
446 ieee80211_hw_config(local, reconf_flags); 471 ieee80211_hw_config(local, reconf_flags);
447 472
448 return 0; 473 return 0;