Commit 48235515 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:

====================
Please pull this batch of fixes intended for the 3.14 stream...

For the mac80211 bits, Johannes says:

"This time I have a fix to get out of an 'infinite error state' in case
regulatory domain updates failed and two fixes for VHT associations: one
to not disconnect immediately when the AP uses more bandwidth than the
new regdomain would allow after a change due to association country
information getting used, and one for an issue in the code where
mac80211 doesn't correctly ignore a reserved field and then uses an HT
instead of VHT association."

For the iwlwifi bits, Emmanuel says:

"Johannes fixes a long standing bug in the AMPDU status reporting.
Max fixes the listen time which was way too long and causes trouble
to several APs."

Along with those, Bing Zhao marks the mwifiex_usb driver as _not_
supporting USB autosuspend after a number of problems with that have
been reported.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ec0223ec 0c6a4812
...@@ -1291,8 +1291,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, ...@@ -1291,8 +1291,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data; struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data;
struct iwl_ht_agg *agg; struct iwl_ht_agg *agg;
struct sk_buff_head reclaimed_skbs; struct sk_buff_head reclaimed_skbs;
struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr;
struct sk_buff *skb; struct sk_buff *skb;
int sta_id; int sta_id;
int tid; int tid;
...@@ -1379,22 +1377,28 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, ...@@ -1379,22 +1377,28 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
freed = 0; freed = 0;
skb_queue_walk(&reclaimed_skbs, skb) { skb_queue_walk(&reclaimed_skbs, skb) {
hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (ieee80211_is_data_qos(hdr->frame_control)) if (ieee80211_is_data_qos(hdr->frame_control))
freed++; freed++;
else else
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
info = IEEE80211_SKB_CB(skb);
iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
memset(&info->status, 0, sizeof(info->status));
/* Packet was transmitted successfully, failures come as single
* frames because before failing a frame the firmware transmits
* it without aggregation at least once.
*/
info->flags |= IEEE80211_TX_STAT_ACK;
if (freed == 1) { if (freed == 1) {
/* this is the first skb we deliver in this batch */ /* this is the first skb we deliver in this batch */
/* put the rate scaling data there */ /* put the rate scaling data there */
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
memset(&info->status, 0, sizeof(info->status)); memset(&info->status, 0, sizeof(info->status));
info->flags |= IEEE80211_TX_STAT_ACK;
info->flags |= IEEE80211_TX_STAT_AMPDU; info->flags |= IEEE80211_TX_STAT_AMPDU;
info->status.ampdu_ack_len = ba_resp->txed_2_done; info->status.ampdu_ack_len = ba_resp->txed_2_done;
info->status.ampdu_len = ba_resp->txed; info->status.ampdu_len = ba_resp->txed;
......
...@@ -152,7 +152,7 @@ enum iwl_power_scheme { ...@@ -152,7 +152,7 @@ enum iwl_power_scheme {
IWL_POWER_SCHEME_LP IWL_POWER_SCHEME_LP
}; };
#define IWL_CONN_MAX_LISTEN_INTERVAL 70 #define IWL_CONN_MAX_LISTEN_INTERVAL 10
#define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ #define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\ IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\ IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
......
...@@ -822,16 +822,12 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, ...@@ -822,16 +822,12 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_mvm_ba_notif *ba_notif = (void *)pkt->data; struct iwl_mvm_ba_notif *ba_notif = (void *)pkt->data;
struct sk_buff_head reclaimed_skbs; struct sk_buff_head reclaimed_skbs;
struct iwl_mvm_tid_data *tid_data; struct iwl_mvm_tid_data *tid_data;
struct ieee80211_tx_info *info;
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
struct iwl_mvm_sta *mvmsta; struct iwl_mvm_sta *mvmsta;
struct ieee80211_hdr *hdr;
struct sk_buff *skb; struct sk_buff *skb;
int sta_id, tid, freed; int sta_id, tid, freed;
/* "flow" corresponds to Tx queue */ /* "flow" corresponds to Tx queue */
u16 scd_flow = le16_to_cpu(ba_notif->scd_flow); u16 scd_flow = le16_to_cpu(ba_notif->scd_flow);
/* "ssn" is start of block-ack Tx window, corresponds to index /* "ssn" is start of block-ack Tx window, corresponds to index
* (in Tx queue's circular buffer) of first TFD/frame in window */ * (in Tx queue's circular buffer) of first TFD/frame in window */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_notif->scd_ssn); u16 ba_resp_scd_ssn = le16_to_cpu(ba_notif->scd_ssn);
...@@ -888,22 +884,26 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, ...@@ -888,22 +884,26 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
freed = 0; freed = 0;
skb_queue_walk(&reclaimed_skbs, skb) { skb_queue_walk(&reclaimed_skbs, skb) {
hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (ieee80211_is_data_qos(hdr->frame_control)) if (ieee80211_is_data_qos(hdr->frame_control))
freed++; freed++;
else else
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
info = IEEE80211_SKB_CB(skb);
iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]);
memset(&info->status, 0, sizeof(info->status));
/* Packet was transmitted successfully, failures come as single
* frames because before failing a frame the firmware transmits
* it without aggregation at least once.
*/
info->flags |= IEEE80211_TX_STAT_ACK;
if (freed == 1) { if (freed == 1) {
/* this is the first skb we deliver in this batch */ /* this is the first skb we deliver in this batch */
/* put the rate scaling data there */ /* put the rate scaling data there */
info = IEEE80211_SKB_CB(skb);
memset(&info->status, 0, sizeof(info->status));
info->flags |= IEEE80211_TX_STAT_ACK;
info->flags |= IEEE80211_TX_STAT_AMPDU; info->flags |= IEEE80211_TX_STAT_AMPDU;
info->status.ampdu_ack_len = ba_notif->txed_2_done; info->status.ampdu_ack_len = ba_notif->txed_2_done;
info->status.ampdu_len = ba_notif->txed; info->status.ampdu_len = ba_notif->txed;
......
...@@ -525,13 +525,6 @@ static int mwifiex_usb_resume(struct usb_interface *intf) ...@@ -525,13 +525,6 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
MWIFIEX_BSS_ROLE_ANY), MWIFIEX_BSS_ROLE_ANY),
MWIFIEX_ASYNC_CMD); MWIFIEX_ASYNC_CMD);
#ifdef CONFIG_PM
/* Resume handler may be called due to remote wakeup,
* force to exit suspend anyway
*/
usb_disable_autosuspend(card->udev);
#endif /* CONFIG_PM */
return 0; return 0;
} }
...@@ -571,7 +564,6 @@ static struct usb_driver mwifiex_usb_driver = { ...@@ -571,7 +564,6 @@ static struct usb_driver mwifiex_usb_driver = {
.id_table = mwifiex_usb_table, .id_table = mwifiex_usb_table,
.suspend = mwifiex_usb_suspend, .suspend = mwifiex_usb_suspend,
.resume = mwifiex_usb_resume, .resume = mwifiex_usb_resume,
.supports_autosuspend = 1,
}; };
static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter) static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
......
...@@ -222,6 +222,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -222,6 +222,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
switch (vht_oper->chan_width) { switch (vht_oper->chan_width) {
case IEEE80211_VHT_CHANWIDTH_USE_HT: case IEEE80211_VHT_CHANWIDTH_USE_HT:
vht_chandef.width = chandef->width; vht_chandef.width = chandef->width;
vht_chandef.center_freq1 = chandef->center_freq1;
break; break;
case IEEE80211_VHT_CHANWIDTH_80MHZ: case IEEE80211_VHT_CHANWIDTH_80MHZ:
vht_chandef.width = NL80211_CHAN_WIDTH_80; vht_chandef.width = NL80211_CHAN_WIDTH_80;
...@@ -271,6 +272,28 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -271,6 +272,28 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
ret = 0; ret = 0;
out: out:
/*
* When tracking the current AP, don't do any further checks if the
* new chandef is identical to the one we're currently using for the
* connection. This keeps us from playing ping-pong with regulatory,
* without it the following can happen (for example):
* - connect to an AP with 80 MHz, world regdom allows 80 MHz
* - AP advertises regdom US
* - CRDA loads regdom US with 80 MHz prohibited (old database)
* - the code below detects an unsupported channel, downgrades, and
* we disconnect from the AP in the caller
* - disconnect causes CRDA to reload world regdomain and the game
* starts anew.
* (see https://bugzilla.kernel.org/show_bug.cgi?id=70881)
*
* It seems possible that there are still scenarios with CSA or real
* bandwidth changes where a this could happen, but those cases are
* less common and wouldn't completely prevent using the AP.
*/
if (tracking &&
cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef))
return ret;
/* don't print the message below for VHT mismatch if VHT is disabled */ /* don't print the message below for VHT mismatch if VHT is disabled */
if (ret & IEEE80211_STA_DISABLE_VHT) if (ret & IEEE80211_STA_DISABLE_VHT)
vht_chandef = *chandef; vht_chandef = *chandef;
......
...@@ -2373,6 +2373,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, ...@@ -2373,6 +2373,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
int set_regdom(const struct ieee80211_regdomain *rd) int set_regdom(const struct ieee80211_regdomain *rd)
{ {
struct regulatory_request *lr; struct regulatory_request *lr;
bool user_reset = false;
int r; int r;
if (!reg_is_valid_request(rd->alpha2)) { if (!reg_is_valid_request(rd->alpha2)) {
...@@ -2389,6 +2390,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) ...@@ -2389,6 +2390,7 @@ int set_regdom(const struct ieee80211_regdomain *rd)
break; break;
case NL80211_REGDOM_SET_BY_USER: case NL80211_REGDOM_SET_BY_USER:
r = reg_set_rd_user(rd, lr); r = reg_set_rd_user(rd, lr);
user_reset = true;
break; break;
case NL80211_REGDOM_SET_BY_DRIVER: case NL80211_REGDOM_SET_BY_DRIVER:
r = reg_set_rd_driver(rd, lr); r = reg_set_rd_driver(rd, lr);
...@@ -2402,8 +2404,14 @@ int set_regdom(const struct ieee80211_regdomain *rd) ...@@ -2402,8 +2404,14 @@ int set_regdom(const struct ieee80211_regdomain *rd)
} }
if (r) { if (r) {
if (r == -EALREADY) switch (r) {
case -EALREADY:
reg_set_request_processed(); reg_set_request_processed();
break;
default:
/* Back to world regulatory in case of errors */
restore_regulatory_settings(user_reset);
}
kfree(rd); kfree(rd);
return r; return r;
......
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