Commit 75848d33 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

John W. Linville says:

====================
This is a batch of fixes intended for the 3.11 queue...

Regarding the mac80211 (and related) bits, Johannes says:

"I have a fix from Chris for an infinite loop along with fixes from
myself to prevent it entering the loop to start with (continue using
disabled channels, many thanks to Chris for his debug/test help) and a
workaround for broken APs that advertise a bad HT primary channel in
their beacons. Additionally, a fix for another attrbuf race in mac80211
and a fix to clean up properly while P2P GO interfaces go down."

Along with that...

Solomon Peachy corrects a range check in cw1200 that would lead to
a BUG_ON when starting AP mode.

Stanislaw Gruszka provides an iwl4965 patch to power-up the device
earlier (avoiding microcode errors), and another iwl4965 fix that
resets the firmware after turning rfkill off (resolving a bug in the
Red Hat Bugzilla).

Please let me know if there are problems!
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3e3be275 1826ff23
...@@ -1406,11 +1406,8 @@ static void cw1200_do_unjoin(struct cw1200_common *priv) ...@@ -1406,11 +1406,8 @@ static void cw1200_do_unjoin(struct cw1200_common *priv)
if (!priv->join_status) if (!priv->join_status)
goto done; goto done;
if (priv->join_status > CW1200_JOIN_STATUS_IBSS) { if (priv->join_status == CW1200_JOIN_STATUS_AP)
wiphy_err(priv->hw->wiphy, "Unexpected: join status: %d\n", goto done;
priv->join_status);
BUG_ON(1);
}
cancel_work_sync(&priv->update_filtering_work); cancel_work_sync(&priv->update_filtering_work);
cancel_work_sync(&priv->set_beacon_wakeup_period_work); cancel_work_sync(&priv->set_beacon_wakeup_period_work);
......
...@@ -4460,12 +4460,12 @@ il4965_irq_tasklet(struct il_priv *il) ...@@ -4460,12 +4460,12 @@ il4965_irq_tasklet(struct il_priv *il)
* is killed. Hence update the killswitch state here. The * is killed. Hence update the killswitch state here. The
* rfkill handler will care about restarting if needed. * rfkill handler will care about restarting if needed.
*/ */
if (!test_bit(S_ALIVE, &il->status)) { if (hw_rf_kill) {
if (hw_rf_kill)
set_bit(S_RFKILL, &il->status); set_bit(S_RFKILL, &il->status);
else } else {
clear_bit(S_RFKILL, &il->status); clear_bit(S_RFKILL, &il->status);
wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
il_force_reset(il, true);
} }
handled |= CSR_INT_BIT_RF_KILL; handled |= CSR_INT_BIT_RF_KILL;
...@@ -5334,6 +5334,9 @@ il4965_alive_start(struct il_priv *il) ...@@ -5334,6 +5334,9 @@ il4965_alive_start(struct il_priv *il)
il->active_rate = RATES_MASK; il->active_rate = RATES_MASK;
il_power_update_mode(il, true);
D_INFO("Updated power mode\n");
if (il_is_associated(il)) { if (il_is_associated(il)) {
struct il_rxon_cmd *active_rxon = struct il_rxon_cmd *active_rxon =
(struct il_rxon_cmd *)&il->active; (struct il_rxon_cmd *)&il->active;
...@@ -5364,9 +5367,6 @@ il4965_alive_start(struct il_priv *il) ...@@ -5364,9 +5367,6 @@ il4965_alive_start(struct il_priv *il)
D_INFO("ALIVE processing complete.\n"); D_INFO("ALIVE processing complete.\n");
wake_up(&il->wait_command_queue); wake_up(&il->wait_command_queue);
il_power_update_mode(il, true);
D_INFO("Updated power mode\n");
return; return;
restart: restart:
......
...@@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external) ...@@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external)
return 0; return 0;
} }
EXPORT_SYMBOL(il_force_reset);
int int
il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
......
...@@ -31,10 +31,12 @@ ...@@ -31,10 +31,12 @@
#include "led.h" #include "led.h"
#define IEEE80211_AUTH_TIMEOUT (HZ / 5) #define IEEE80211_AUTH_TIMEOUT (HZ / 5)
#define IEEE80211_AUTH_TIMEOUT_LONG (HZ / 2)
#define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) #define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10)
#define IEEE80211_AUTH_MAX_TRIES 3 #define IEEE80211_AUTH_MAX_TRIES 3
#define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5)
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) #define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
#define IEEE80211_ASSOC_TIMEOUT_LONG (HZ / 2)
#define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10) #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10)
#define IEEE80211_ASSOC_MAX_TRIES 3 #define IEEE80211_ASSOC_MAX_TRIES 3
...@@ -209,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -209,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel, struct ieee80211_channel *channel,
const struct ieee80211_ht_operation *ht_oper, const struct ieee80211_ht_operation *ht_oper,
const struct ieee80211_vht_operation *vht_oper, const struct ieee80211_vht_operation *vht_oper,
struct cfg80211_chan_def *chandef, bool verbose) struct cfg80211_chan_def *chandef, bool tracking)
{ {
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct cfg80211_chan_def vht_chandef; struct cfg80211_chan_def vht_chandef;
u32 ht_cfreq, ret; u32 ht_cfreq, ret;
...@@ -229,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -229,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
channel->band); channel->band);
/* check that channel matches the right operating channel */ /* check that channel matches the right operating channel */
if (channel->center_freq != ht_cfreq) { if (!tracking && channel->center_freq != ht_cfreq) {
/* /*
* It's possible that some APs are confused here; * It's possible that some APs are confused here;
* Netgear WNDR3700 sometimes reports 4 higher than * Netgear WNDR3700 sometimes reports 4 higher than
...@@ -237,7 +240,6 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -237,7 +240,6 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
* since we look at probe response/beacon data here * since we look at probe response/beacon data here
* it should be OK. * it should be OK.
*/ */
if (verbose)
sdata_info(sdata, sdata_info(sdata,
"Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
channel->center_freq, ht_cfreq, channel->center_freq, ht_cfreq,
...@@ -295,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -295,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
channel->band); channel->band);
break; break;
default: default:
if (verbose) if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
sdata_info(sdata, sdata_info(sdata,
"AP VHT operation IE has invalid channel width (%d), disable VHT\n", "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
vht_oper->chan_width); vht_oper->chan_width);
...@@ -304,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -304,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
} }
if (!cfg80211_chandef_valid(&vht_chandef)) { if (!cfg80211_chandef_valid(&vht_chandef)) {
if (verbose) if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
sdata_info(sdata, sdata_info(sdata,
"AP VHT information is invalid, disable VHT\n"); "AP VHT information is invalid, disable VHT\n");
ret = IEEE80211_STA_DISABLE_VHT; ret = IEEE80211_STA_DISABLE_VHT;
...@@ -317,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -317,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
} }
if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
if (verbose) if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
sdata_info(sdata, sdata_info(sdata,
"AP VHT information doesn't match HT, disable VHT\n"); "AP VHT information doesn't match HT, disable VHT\n");
ret = IEEE80211_STA_DISABLE_VHT; ret = IEEE80211_STA_DISABLE_VHT;
...@@ -333,18 +335,27 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -333,18 +335,27 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
if (ret & IEEE80211_STA_DISABLE_VHT) if (ret & IEEE80211_STA_DISABLE_VHT)
vht_chandef = *chandef; vht_chandef = *chandef;
/*
* Ignore the DISABLED flag when we're already connected and only
* tracking the APs beacon for bandwidth changes - otherwise we
* might get disconnected here if we connect to an AP, update our
* regulatory information based on the AP's country IE and the
* information we have is wrong/outdated and disables the channel
* that we're actually using for the connection to the AP.
*/
while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
tracking ? 0 :
IEEE80211_CHAN_DISABLED)) { IEEE80211_CHAN_DISABLED)) {
if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
ret = IEEE80211_STA_DISABLE_HT | ret = IEEE80211_STA_DISABLE_HT |
IEEE80211_STA_DISABLE_VHT; IEEE80211_STA_DISABLE_VHT;
goto out; break;
} }
ret |= chandef_downgrade(chandef); ret |= chandef_downgrade(chandef);
} }
if (chandef->width != vht_chandef.width && verbose) if (chandef->width != vht_chandef.width && !tracking)
sdata_info(sdata, sdata_info(sdata,
"capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
...@@ -384,7 +395,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, ...@@ -384,7 +395,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
/* calculate new channel (type) based on HT/VHT operation IEs */ /* calculate new channel (type) based on HT/VHT operation IEs */
flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
vht_oper, &chandef, false); vht_oper, &chandef, true);
/* /*
* Downgrade the new channel if we associated with restricted * Downgrade the new channel if we associated with restricted
...@@ -3394,10 +3405,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) ...@@ -3394,10 +3405,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
if (tx_flags == 0) { if (tx_flags == 0) {
auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
ifmgd->auth_data->timeout_started = true; auth_data->timeout_started = true;
run_again(sdata, auth_data->timeout); run_again(sdata, auth_data->timeout);
} else { } else {
auth_data->timeout_started = false; auth_data->timeout =
round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
auth_data->timeout_started = true;
run_again(sdata, auth_data->timeout);
} }
return 0; return 0;
...@@ -3434,7 +3448,11 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -3434,7 +3448,11 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
assoc_data->timeout_started = true; assoc_data->timeout_started = true;
run_again(sdata, assoc_data->timeout); run_again(sdata, assoc_data->timeout);
} else { } else {
assoc_data->timeout_started = false; assoc_data->timeout =
round_jiffies_up(jiffies +
IEEE80211_ASSOC_TIMEOUT_LONG);
assoc_data->timeout_started = true;
run_again(sdata, assoc_data->timeout);
} }
return 0; return 0;
...@@ -3829,7 +3847,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ...@@ -3829,7 +3847,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
cbss->channel, cbss->channel,
ht_oper, vht_oper, ht_oper, vht_oper,
&chandef, true); &chandef, false);
sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
local->rx_chains); local->rx_chains);
......
...@@ -765,6 +765,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, ...@@ -765,6 +765,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
cfg80211_leave_mesh(rdev, dev); cfg80211_leave_mesh(rdev, dev);
break; break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
cfg80211_stop_ap(rdev, dev); cfg80211_stop_ap(rdev, dev);
break; break;
default: default:
......
...@@ -441,10 +441,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, ...@@ -441,10 +441,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
goto out_unlock; goto out_unlock;
} }
*rdev = wiphy_to_dev((*wdev)->wiphy); *rdev = wiphy_to_dev((*wdev)->wiphy);
cb->args[0] = (*rdev)->wiphy_idx; /* 0 is the first index - add 1 to parse only once */
cb->args[0] = (*rdev)->wiphy_idx + 1;
cb->args[1] = (*wdev)->identifier; cb->args[1] = (*wdev)->identifier;
} else { } else {
struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]); /* subtract the 1 again here */
struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
struct wireless_dev *tmp; struct wireless_dev *tmp;
if (!wiphy) { if (!wiphy) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment