{
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 (!chan)
return -EINVAL;
- if (data->txpower.fixed)
- new_power_level = min(data->txpower.value, chan->max_power);
- else /* Automatic power level setting */
- new_power_level = chan->max_power;
+ /* 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;
+ }
- local->user_power_level = new_power_level;
- if (local->hw.conf.power_level != new_power_level)
- reconf_flags |= IEEE80211_CONF_CHANGE_POWER;
+ 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);
ieee80211_led_radio(local, local->hw.conf.radio_enabled);
}
- if (reconf_flags)
+ if (reconf || reconf_flags)
ieee80211_hw_config(local, reconf_flags);
return 0;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
frag->value = local->fragmentation_threshold;
- frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
+ frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD);
frag->fixed = 1;
return 0;
!sdata->default_key,
keybuf, erq->length);
- if (!ret) {
+ if (!ret && sdata->vif.type == NL80211_IFTYPE_STATION) {
if (remove)
sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED;
else
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_conf *conf = &local->hw.conf;
- int ret = 0, timeout = 0;
+ int timeout = 0;
bool ps;
if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
timeout = wrq->value / 1000;
set:
- if (ps == local->powersave && timeout == conf->dynamic_ps_timeout)
- return ret;
+ if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout)
+ return 0;
- local->powersave = ps;
+ sdata->u.mgd.powersave = ps;
conf->dynamic_ps_timeout = timeout;
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
- ret = ieee80211_hw_config(local,
- IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
+ ieee80211_hw_config(local,
+ IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
- if (!(sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED))
- return ret;
+ ieee80211_recalc_ps(local);
- if (conf->dynamic_ps_timeout > 0 &&
- !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
- mod_timer(&local->dynamic_ps_timer, jiffies +
- msecs_to_jiffies(conf->dynamic_ps_timeout));
- } else {
- if (local->powersave) {
- if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
- ieee80211_send_nullfunc(local, sdata, 1);
- conf->flags |= IEEE80211_CONF_PS;
- ret = ieee80211_hw_config(local,
- IEEE80211_CONF_CHANGE_PS);
- } else {
- conf->flags &= ~IEEE80211_CONF_PS;
- ret = ieee80211_hw_config(local,
- IEEE80211_CONF_CHANGE_PS);
- if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
- ieee80211_send_nullfunc(local, sdata, 0);
- del_timer_sync(&local->dynamic_ps_timer);
- cancel_work_sync(&local->dynamic_ps_enable_work);
- }
- }
-
- return ret;
+ return 0;
}
static int ieee80211_ioctl_giwpower(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- wrqu->power.disabled = !local->powersave;
+ wrqu->power.disabled = !sdata->u.mgd.powersave;
return 0;
}