From a0ec570f4f69c4cb700d743a915096c2c8f56a99 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Tue, 25 Jun 2013 09:17:17 +0200 Subject: [PATCH 01/23] nl80211: fix mgmt tx status and testmode reporting for netns These two events were sent to the default network namespace. This caused AP mode in a non-default netns to not work correctly. Mgmt tx status was multicasted to a different (default) netns instead of the one the AP was in. Cc: stable@vger.kernel.org Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1cc47aca7f05..9fb8820b75c5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6613,12 +6613,14 @@ EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb); void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) { + struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0]; void *hdr = ((void **)skb->cb)[1]; struct nlattr *data = ((void **)skb->cb)[2]; nla_nest_end(skb, data); genlmsg_end(skb, hdr); - genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp); + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0, + nl80211_testmode_mcgrp.id, gfp); } EXPORT_SYMBOL(cfg80211_testmode_event); #endif @@ -10064,7 +10066,8 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, genlmsg_end(msg, hdr); - genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, gfp); return; nla_put_failure: From 923a0e7dee8c436108279568cf34444749ac796f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 28 Jun 2013 11:38:54 +0200 Subject: [PATCH 02/23] cfg80211: fix bugs in new SME implementation When splitting the SME implementation from the MLME code, I introduced a few bugs: * association failures no longer sent a connect-failure event * getting disassociated from the AP caused deauth to be sent but state wasn't cleaned up, leading to warnings * authentication failures weren't cleaned up properly, causing new connection attempts to warn and fail Fix these bugs. Signed-off-by: Johannes Berg --- net/wireless/sme.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 1d3cfb1a3f28..81c8a10d743c 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -34,8 +34,10 @@ struct cfg80211_conn { CFG80211_CONN_SCAN_AGAIN, CFG80211_CONN_AUTHENTICATE_NEXT, CFG80211_CONN_AUTHENTICATING, + CFG80211_CONN_AUTH_FAILED, CFG80211_CONN_ASSOCIATE_NEXT, CFG80211_CONN_ASSOCIATING, + CFG80211_CONN_ASSOC_FAILED, CFG80211_CONN_DEAUTH, CFG80211_CONN_CONNECTED, } state; @@ -164,6 +166,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) NULL, 0, params->key, params->key_len, params->key_idx, NULL, 0); + case CFG80211_CONN_AUTH_FAILED: + return -ENOTCONN; case CFG80211_CONN_ASSOCIATE_NEXT: BUG_ON(!rdev->ops->assoc); wdev->conn->state = CFG80211_CONN_ASSOCIATING; @@ -188,10 +192,17 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) WLAN_REASON_DEAUTH_LEAVING, false); return err; + case CFG80211_CONN_ASSOC_FAILED: + cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, + NULL, 0, + WLAN_REASON_DEAUTH_LEAVING, false); + return -ENOTCONN; case CFG80211_CONN_DEAUTH: cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, WLAN_REASON_DEAUTH_LEAVING, false); + /* free directly, disconnected event already sent */ + cfg80211_sme_free(wdev); return 0; default: return 0; @@ -371,7 +382,7 @@ bool cfg80211_sme_rx_assoc_resp(struct wireless_dev *wdev, u16 status) return true; } - wdev->conn->state = CFG80211_CONN_DEAUTH; + wdev->conn->state = CFG80211_CONN_ASSOC_FAILED; schedule_work(&rdev->conn_work); return false; } @@ -383,7 +394,13 @@ void cfg80211_sme_deauth(struct wireless_dev *wdev) void cfg80211_sme_auth_timeout(struct wireless_dev *wdev) { - cfg80211_sme_free(wdev); + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + + if (!wdev->conn) + return; + + wdev->conn->state = CFG80211_CONN_AUTH_FAILED; + schedule_work(&rdev->conn_work); } void cfg80211_sme_disassoc(struct wireless_dev *wdev) @@ -399,7 +416,13 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev) void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) { - cfg80211_sme_disassoc(wdev); + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + + if (!wdev->conn) + return; + + wdev->conn->state = CFG80211_CONN_ASSOC_FAILED; + schedule_work(&rdev->conn_work); } static int cfg80211_sme_connect(struct wireless_dev *wdev, From f77b86d7d3acf9dfcb5ee834628d12207584b2cb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 24 Jun 2013 15:43:38 +0200 Subject: [PATCH 03/23] regulatory: add missing rtnl locking restore_regulatory_settings() requires the RTNL to be held, add the missing locking in reg_timeout_work(). Signed-off-by: Johannes Berg --- net/wireless/reg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5a24c986f34b..5a950f36bae4 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2279,7 +2279,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy) static void reg_timeout_work(struct work_struct *work) { REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); + rtnl_lock(); restore_regulatory_settings(true); + rtnl_unlock(); } int __init regulatory_init(void) From 1cd158573951f737fbc878a35cb5eb47bf9af3d5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 28 Jun 2013 21:04:35 +0200 Subject: [PATCH 04/23] mac80211/minstrel_ht: fix cck rate sampling The CCK group needs special treatment to set the right flags and rate index. Add this missing check to prevent setting broken rates for tx packets. Cc: stable@vger.kernel.org # 3.10 Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 5b2d3012b983..f5aed963b22e 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -804,10 +804,18 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES]; info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; + rate->count = 1; + + if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) { + int idx = sample_idx % ARRAY_SIZE(mp->cck_rates); + rate->idx = mp->cck_rates[idx]; + rate->flags = 0; + return; + } + rate->idx = sample_idx % MCS_GROUP_RATES + (sample_group->streams - 1) * MCS_GROUP_RATES; rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags; - rate->count = 1; } static void From e13bae4f807401729b3f27c7e882a96b8b292809 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Jul 2013 10:43:31 +0200 Subject: [PATCH 05/23] mac80211: fix ethtool stats for non-station interfaces As reported in https://bugzilla.kernel.org/show_bug.cgi?id=60514, the station loop never initialises 'sinfo' and therefore adds up a stack values, leaking stack information (the number of times it adds values is easily obtained another way.) Fix this by initialising the sinfo for each station to add. Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8184d121ff09..43dd7525bfcb 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -666,6 +666,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, if (sta->sdata->dev != dev) continue; + sinfo.filled = 0; + sta_set_sinfo(sta, &sinfo); i = 0; ADD_STA_STATS(sta); } From 83374fe9de455e37c2a039603d2538eb77e8ec4d Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Thu, 11 Jul 2013 18:24:03 +0800 Subject: [PATCH 06/23] nl80211: fix the setting of RSSI threshold value for mesh RSSI threshold value used for mesh peering should be in negative value. After range checks to mesh parameters is introduced, this is not allowed. Fix this. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9fb8820b75c5..25d217d90807 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4770,9 +4770,9 @@ do { \ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1, mask, NL80211_MESHCONF_FORWARDING, nla_get_u8); - FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, 1, 255, + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0, mask, NL80211_MESHCONF_RSSI_THRESHOLD, - nla_get_u32); + nla_get_s32); FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16, mask, NL80211_MESHCONF_HT_OPMODE, nla_get_u16); From 6b0f32745dcfba01d7be33acd1b40306c7a914c6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Jul 2013 22:33:26 +0200 Subject: [PATCH 07/23] mac80211: fix duplicate retransmission detection The duplicate retransmission detection code in mac80211 erroneously attempts to do the check for every frame, even frames that don't have a sequence control field or that don't use it (QoS-Null frames.) This is problematic because it causes the code to access data beyond the end of the SKB and depending on the data there will drop packets erroneously. Correct the code to not do duplicate detection for such frames. I found this error while testing AP powersave, it lead to retransmitted PS-Poll frames being dropped entirely as the data beyond the end of the SKB was always zero. Cc: stable@vger.kernel.org [all versions] Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 23dbcfc69b3b..2c5a79bd3777 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -936,8 +936,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); - /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ - if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { + /* + * Drop duplicate 802.11 retransmissions + * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery") + */ + if (rx->skb->len >= 24 && rx->sta && + !ieee80211_is_ctl(hdr->frame_control) && + !ieee80211_is_qos_nullfunc(hdr->frame_control) && + !is_multicast_ether_addr(hdr->addr1)) { if (unlikely(ieee80211_has_retry(hdr->frame_control) && rx->sta->last_seq_ctrl[rx->seqno_idx] == hdr->seq_ctrl)) { From b7327d89ae694a89f9934d428bde520b77b3131c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 24 Jun 2013 15:44:03 +0300 Subject: [PATCH 08/23] iwlwifi: mvm: unregister leds when registration failed This was missing and prevented any further attempts to load the module. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index e08683b20531..cab2f0c61ec7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -257,7 +257,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) if (ret) return ret; - return ieee80211_register_hw(mvm->hw); + ret = ieee80211_register_hw(mvm->hw); + if (ret) + iwl_mvm_leds_exit(mvm); + + return ret; } static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, From 707aee401d2467baa785a697f40a6e2d9ee79ad5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 3 May 2013 18:58:16 +0200 Subject: [PATCH 09/23] iwlwifi: dvm: don't send BT_CONFIG on devices w/o Bluetooth The BT_CONFIG command that is sent to the device during startup will enable BT coex unless the module parameter turns it off, but on devices without Bluetooth this may cause problems, as reported in Redhat BZ 885407. Fix this by sending the BT_CONFIG command only when the device has Bluetooth. Cc: stable@vger.kernel.org Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 3952ddf2ddb2..1531a4fc0960 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -758,7 +758,7 @@ int iwl_alive_start(struct iwl_priv *priv) BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; - } else { + } else if (priv->lib->bt_params) { /* * default is 2-wire BT coexexistence support */ From 0ecb376375d662987eba2f6e3bfd4bd532bb3907 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Sun, 23 Jun 2013 20:31:07 +0300 Subject: [PATCH 10/23] iwlwifi: mvm: Fix VIF specific debugfs directory creation Avoid creating VIF specific debugfs directory if already exist. This may happen when, for example, resetting hw, suspend-resume. Signed-off-by: Alexander Bondar Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index e56ed2a84888..c24a744910ac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -988,7 +988,11 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); char buf[100]; - if (!dbgfs_dir) + /* + * Check if debugfs directory already exist before creating it. + * This may happen when, for example, resetting hw or suspend-resume + */ + if (!dbgfs_dir || mvmvif->dbgfs_dir) return; mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir); From 93a426673fbfeae7fa6b27008828e2ac4c08dbee Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 2 Jul 2013 13:35:35 +0300 Subject: [PATCH 11/23] iwlwifi: mvm: fix L2P BA ressources leak We didn't release the Rx AMPDU ressources properly. This bug led to firmware assert after 16 BA sessions. Cc: [3.9+] Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/sta.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 62fe5209093b..b6ab0766ea99 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -621,8 +621,12 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); cmd.sta_id = mvm_sta->sta_id; cmd.add_modify = STA_MODE_MODIFY; - cmd.add_immediate_ba_tid = (u8) tid; - cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); + if (start) { + cmd.add_immediate_ba_tid = (u8) tid; + cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); + } else { + cmd.remove_immediate_ba_tid = (u8) tid; + } cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID : STA_MODIFY_REMOVE_BA_TID; From 113a04470d9178170a5d1aa165809515884f39a8 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 2 Jul 2013 14:16:38 +0300 Subject: [PATCH 12/23] iwlwifi: mvm: track the number of Rx BA sessions The firmware / HW can't support more than 16 Rx BA sessions. Deny any attemps to open more sessions than that. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 1 + drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/iwlwifi/mvm/sta.c | 15 +++++++++++++++ 3 files changed, 17 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index cab2f0c61ec7..1a4a032cecb2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -389,6 +389,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) ieee80211_wake_queues(mvm->hw); mvm->vif_count = 0; + mvm->rx_ba_sessions = 0; } static int iwl_mvm_mac_start(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index d40d7db185d6..420e82d379d9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -419,6 +419,7 @@ struct iwl_mvm { struct work_struct sta_drained_wk; unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; atomic_t pending_frames[IWL_MVM_STATION_COUNT]; + u8 rx_ba_sessions; /* configured by mac80211 */ u32 rts_threshold; diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index b6ab0766ea99..85d4bbe52157 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -608,6 +608,8 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta) return ret; } +#define IWL_MAX_RX_BA_SESSIONS 16 + int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, int tid, u16 ssn, bool start) { @@ -618,6 +620,11 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lockdep_assert_held(&mvm->mutex); + if (start && mvm->rx_ba_sessions >= IWL_MAX_RX_BA_SESSIONS) { + IWL_WARN(mvm, "Not enough RX BA SESSIONS\n"); + return -ENOSPC; + } + cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); cmd.sta_id = mvm_sta->sta_id; cmd.add_modify = STA_MODE_MODIFY; @@ -652,6 +659,14 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, break; } + if (!ret) { + if (start) + mvm->rx_ba_sessions++; + else if (mvm->rx_ba_sessions > 0) + /* check that restart flow didn't zero the counter */ + mvm->rx_ba_sessions--; + } + return ret; } From 48bc13072109ea58465542aa1ee31b4e1065468a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 4 Jul 2013 15:55:29 +0200 Subject: [PATCH 13/23] iwlwifi: mvm: refuse connection to APs with BI < 16 Due to a firmware bug, it crashes when the beacon interval is smaller than 16. Avoid this by refusing the station state change creating the AP station, causing mac80211 to abandon the attempt to connect to the AP, and eventually wpa_s to blacklist it. Cc: stable@vger.kernel.org Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 1a4a032cecb2..1eedc424051c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1011,6 +1011,21 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { + /* + * Firmware bug - it'll crash if the beacon interval is less + * than 16. We can't avoid connecting at all, so refuse the + * station state change, this will cause mac80211 to abandon + * attempts to connect to this AP, and eventually wpa_s will + * blacklist the AP... + */ + if (vif->type == NL80211_IFTYPE_STATION && + vif->bss_conf.beacon_int < 16) { + IWL_ERR(mvm, + "AP %pM beacon interval is %d, refusing due to firmware bug!\n", + sta->addr, vif->bss_conf.beacon_int); + ret = -EINVAL; + goto out_unlock; + } ret = iwl_mvm_add_sta(mvm, vif, sta); } else if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_AUTH) { @@ -1043,6 +1058,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, } else { ret = -EIO; } + out_unlock: mutex_unlock(&mvm->mutex); return ret; From fe04e83706037802c502ea41c0d1799ec35fc0d7 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Thu, 4 Jul 2013 15:17:48 +0300 Subject: [PATCH 14/23] iwlwifi: mvm: fix bug in scan ssid Increment index in each iteration. Without this increment we are overriding the added SSIDs and we will send only the last SSId and (n_ssids - 1) broadcast probes. Cc: [3.9+] Signed-off-by: David Spinadel Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 2157b0f8ced5..8023deec20cb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -137,8 +137,8 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, { int fw_idx, req_idx; - fw_idx = 0; - for (req_idx = req->n_ssids - 1; req_idx > 0; req_idx--) { + for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx > 0; + req_idx--, fw_idx++) { cmd->direct_scan[fw_idx].id = WLAN_EID_SSID; cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len; memcpy(cmd->direct_scan[fw_idx].ssid, From a590ad411891de551e6de1b51ea635c0484148d6 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Thu, 4 Jul 2013 15:22:26 +0300 Subject: [PATCH 15/23] iwlwifi: mvm: remove extra SSID from probe request Bits 1-21 in this channel type attributes are indication for which SSID is going to be sent on this channel. Since the first SSID is sent implicitly in the probe request, we don't need to toggle its bit here. Signed-off-by: David Spinadel Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/scan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 8023deec20cb..268f027b45b0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -153,7 +153,9 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, * just to notify that this scan is active and not passive. * In order to notify the FW of the number of SSIDs we wish to scan (including * the zero-length one), we need to set the corresponding bits in chan->type, - * one for each SSID, and set the active bit (first). + * one for each SSID, and set the active bit (first). The first SSID is already + * included in the probe template, so we need to set only req->n_ssids - 1 bits + * in addition to the first bit. */ static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) { @@ -179,7 +181,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, __le32 chan_type_value; if (req->n_ssids > 0) - chan_type_value = cpu_to_le32(BIT(req->n_ssids + 1) - 1); + chan_type_value = cpu_to_le32(BIT(req->n_ssids) - 1); else chan_type_value = SCAN_CHANNEL_TYPE_PASSIVE; From 5c9fc93bc9bc417418fc1b6366833ae6a07b804d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 15 Jul 2013 14:35:06 +0200 Subject: [PATCH 16/23] mac80211/minstrel: fix NULL pointer dereference issue When priv_sta == NULL, mi->prev_sample is dereferenced too early. Move the assignment further down, after the rate_control_send_low call. Reported-by: Krzysztof Mazur Cc: stable@vger.kernel.org # 3.10 Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index ac7ef5414bde..e6512e2ffd20 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -290,7 +290,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, struct minstrel_rate *msr, *mr; unsigned int ndx; bool mrr_capable; - bool prev_sample = mi->prev_sample; + bool prev_sample; int delta; int sampling_ratio; @@ -314,6 +314,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, (mi->sample_count + mi->sample_deferred / 2); /* delta < 0: no sampling required */ + prev_sample = mi->prev_sample; mi->prev_sample = false; if (delta < 0 || (!mrr_capable && prev_sample)) return; From 232fde062e0a2cc52e8e18a50cda361b4ba88f34 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sat, 13 Jul 2013 10:57:10 -0400 Subject: [PATCH 17/23] mwifiex: fix IRQ enable/disable During tear down (e.g. mwifiex_sdio_remove during system suspend), mwifiex left IRQs enabled for a significant period of time when it was unable to handle them correctly. This caused interrupt storms and interfered with the bluetooth interface on the same SDIO card. Solve this by disabling interrupts at the point when they can no longer be handled correctly, which is at the start of mwifiex_remove_card(). For cleanliness, we now enable interrupts in the mwifiex_add_card() path, to be symmetrical with the disabling of interrupts. We also couple the registration of the sdio IRQ handler with the actual enable/disable of interrupts at the hardware level. I also removed a write to this register in mwifiex_init_sdio which seemed pointless and won't cause any ill effects now that we only register the SDIO IRQ handler when we are ready to accept interrupts. Includes some corrections from Amitkumar Karwar. Signed-off-by: Daniel Drake Acked-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 10 +--- drivers/net/wireless/mwifiex/main.c | 13 ++++- drivers/net/wireless/mwifiex/main.h | 1 + drivers/net/wireless/mwifiex/sdio.c | 91 +++++++++++++---------------- drivers/net/wireless/mwifiex/sdio.h | 3 - 5 files changed, 57 insertions(+), 61 deletions(-) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index caaf4bd56b30..2cf8b964e966 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -693,7 +693,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, if (!ret) { dev_notice(adapter->dev, "WLAN FW already running! Skip FW dnld\n"); - goto done; + return 0; } poll_num = MAX_FIRMWARE_POLL_TRIES; @@ -719,14 +719,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, poll_fw: /* Check if the firmware is downloaded successfully or not */ ret = adapter->if_ops.check_fw_status(adapter, poll_num); - if (ret) { + if (ret) dev_err(adapter->dev, "FW failed to be active in time\n"); - return -1; - } -done: - /* re-enable host interrupt for mwifiex after fw dnld is successful */ - if (adapter->if_ops.enable_int) - adapter->if_ops.enable_int(adapter); return ret; } diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index e15ab72fb03d..1753431de361 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -427,6 +427,10 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) "Cal data request_firmware() failed\n"); } + /* enable host interrupt after fw dnld is successful */ + if (adapter->if_ops.enable_int) + adapter->if_ops.enable_int(adapter); + adapter->init_wait_q_woken = false; ret = mwifiex_init_fw(adapter); if (ret == -1) { @@ -478,6 +482,8 @@ err_add_intf: mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev); rtnl_unlock(); err_init_fw: + if (adapter->if_ops.disable_int) + adapter->if_ops.disable_int(adapter); pr_debug("info: %s: unregister device\n", __func__); adapter->if_ops.unregister_dev(adapter); done: @@ -855,7 +861,7 @@ mwifiex_add_card(void *card, struct semaphore *sem, INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); /* Register the device. Fill up the private data structure with relevant - information from the card and request for the required IRQ. */ + information from the card. */ if (adapter->if_ops.register_dev(adapter)) { pr_err("%s: failed to register mwifiex device\n", __func__); goto err_registerdev; @@ -919,6 +925,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) if (!adapter) goto exit_remove; + /* We can no longer handle interrupts once we start doing the teardown + * below. */ + if (adapter->if_ops.disable_int) + adapter->if_ops.disable_int(adapter); + adapter->surprise_removed = true; /* Stop data */ diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 3da73d36acdf..253e0bd38e25 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -601,6 +601,7 @@ struct mwifiex_if_ops { int (*register_dev) (struct mwifiex_adapter *); void (*unregister_dev) (struct mwifiex_adapter *); int (*enable_int) (struct mwifiex_adapter *); + void (*disable_int) (struct mwifiex_adapter *); int (*process_int_status) (struct mwifiex_adapter *); int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *, struct mwifiex_tx_param *); diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 5ee5ed02eccd..5ef49f2e375a 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -51,6 +51,7 @@ static struct mwifiex_if_ops sdio_ops; static struct semaphore add_remove_card_sem; static int mwifiex_sdio_resume(struct device *dev); +static void mwifiex_sdio_interrupt(struct sdio_func *func); /* * SDIO probe. @@ -296,6 +297,15 @@ static struct sdio_driver mwifiex_sdio = { } }; +/* Write data into SDIO card register. Caller claims SDIO device. */ +static int +mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data) +{ + int ret = -1; + sdio_writeb(func, data, reg, &ret); + return ret; +} + /* * This function writes data into SDIO card register. */ @@ -303,10 +313,10 @@ static int mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) { struct sdio_mmc_card *card = adapter->card; - int ret = -1; + int ret; sdio_claim_host(card->func); - sdio_writeb(card->func, data, reg, &ret); + ret = mwifiex_write_reg_locked(card->func, reg, data); sdio_release_host(card->func); return ret; @@ -685,23 +695,15 @@ mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) * The host interrupt mask is read, the disable bit is reset and * written back to the card host interrupt mask register. */ -static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) +static void mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) { - u8 host_int_mask, host_int_disable = HOST_INT_DISABLE; + struct sdio_mmc_card *card = adapter->card; + struct sdio_func *func = card->func; - /* Read back the host_int_mask register */ - if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) - return -1; - - /* Update with the mask and write back to the register */ - host_int_mask &= ~host_int_disable; - - if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, host_int_mask)) { - dev_err(adapter->dev, "disable host interrupt failed\n"); - return -1; - } - - return 0; + sdio_claim_host(func); + mwifiex_write_reg_locked(func, HOST_INT_MASK_REG, 0); + sdio_release_irq(func); + sdio_release_host(func); } /* @@ -713,14 +715,29 @@ static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) { struct sdio_mmc_card *card = adapter->card; + struct sdio_func *func = card->func; + int ret; + + sdio_claim_host(func); + + /* Request the SDIO IRQ */ + ret = sdio_claim_irq(func, mwifiex_sdio_interrupt); + if (ret) { + dev_err(adapter->dev, "claim irq failed: ret=%d\n", ret); + goto out; + } /* Simply write the mask to the register */ - if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, - card->reg->host_int_enable)) { + ret = mwifiex_write_reg_locked(func, HOST_INT_MASK_REG, + card->reg->host_int_enable); + if (ret) { dev_err(adapter->dev, "enable host interrupt failed\n"); - return -1; + sdio_release_irq(func); } - return 0; + +out: + sdio_release_host(func); + return ret; } /* @@ -997,9 +1014,6 @@ mwifiex_sdio_interrupt(struct sdio_func *func) } adapter = card->adapter; - if (adapter->surprise_removed) - return; - if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP) adapter->ps_state = PS_STATE_AWAKE; @@ -1728,9 +1742,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter) struct sdio_mmc_card *card = adapter->card; if (adapter->card) { - /* Release the SDIO IRQ */ sdio_claim_host(card->func); - sdio_release_irq(card->func); sdio_disable_func(card->func); sdio_release_host(card->func); sdio_set_drvdata(card->func, NULL); @@ -1744,7 +1756,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter) */ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) { - int ret = 0; + int ret; struct sdio_mmc_card *card = adapter->card; struct sdio_func *func = card->func; @@ -1753,22 +1765,14 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) sdio_claim_host(func); - /* Request the SDIO IRQ */ - ret = sdio_claim_irq(func, mwifiex_sdio_interrupt); - if (ret) { - pr_err("claim irq failed: ret=%d\n", ret); - goto disable_func; - } - /* Set block size */ ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE); + sdio_release_host(func); if (ret) { pr_err("cannot set SDIO block size\n"); - ret = -1; - goto release_irq; + return ret; } - sdio_release_host(func); sdio_set_drvdata(func, card); adapter->dev = &func->dev; @@ -1776,15 +1780,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) strcpy(adapter->fw_name, card->firmware); return 0; - -release_irq: - sdio_release_irq(func); -disable_func: - sdio_disable_func(func); - sdio_release_host(func); - adapter->card = NULL; - - return -1; } /* @@ -1813,9 +1808,6 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) */ mwifiex_read_reg(adapter, HOST_INTSTATUS_REG, &sdio_ireg); - /* Disable host interrupt mask register for SDIO */ - mwifiex_sdio_disable_host_int(adapter); - /* Get SDIO ioport */ mwifiex_init_sdio_ioport(adapter); @@ -1957,6 +1949,7 @@ static struct mwifiex_if_ops sdio_ops = { .register_dev = mwifiex_register_dev, .unregister_dev = mwifiex_unregister_dev, .enable_int = mwifiex_sdio_enable_host_int, + .disable_int = mwifiex_sdio_disable_host_int, .process_int_status = mwifiex_process_int_status, .host_to_card = mwifiex_sdio_host_to_card, .wakeup = mwifiex_pm_wakeup_card, diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 6d51dfdd8251..532ae0ac4dfb 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -92,9 +92,6 @@ /* Host Control Registers : Download host interrupt mask */ #define DN_LD_HOST_INT_MASK (0x2U) -/* Disable Host interrupt mask */ -#define HOST_INT_DISABLE 0xff - /* Host Control Registers : Host interrupt status */ #define HOST_INTSTATUS_REG 0x03 /* Host Control Registers : Upload host interrupt status */ From dc2a87f519a4d8cb376ab54f22b6b98a943b51ce Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 19 Jul 2013 20:16:17 +0200 Subject: [PATCH 18/23] ath9k_htc: do some initial hardware configuration Currently we configure harwdare and clock, only after interface start. In this case, if we reload module or reboot PC without configuring adapter, firmware will freeze. There is no software way to reset adpter. This patch add initial configuration and set it in disabled state, to avoid this freeze. Behaviour of this patch should be similar to: ifconfig wlan0 up; ifconfig wlan0 down. Bug: https://github.com/qca/open-ath9k-htc-firmware/issues/1 Tested-by: Bo Shi Signed-off-by: Oleksij Rempel Cc: Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 71a183ffc77f..c3676bf1d6c4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -861,6 +861,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, if (error != 0) goto err_rx; + ath9k_hw_disable(priv->ah); #ifdef CONFIG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, From 4928bd2ef8ece262f4f314630219999a91eaa440 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 19 Jul 2013 20:16:18 +0200 Subject: [PATCH 19/23] ath9k_htc: reboot firmware if it was loaded Currently ath9k_htc will reboot firmware only if interface was ever started. Which lead to the problem in case where interface was never started but module need to be reloaded. This patch will partially fix bug "ath9k_htc: Target is unresponsive" https://github.com/qca/open-ath9k-htc-firmware/issues/1 Reproduction case: - plug adapter - make sure nothing will touch it. Stop Networkmanager or blacklist mac address of this adapter. - rmmod ath9k_htc; sleep 1; modprobe ath9k_htc Signed-off-by: Oleksij Rempel Cc: Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 2469db5a5bb1..5205a3625e84 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1295,7 +1295,9 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); - if (!unplugged && (hif_dev->flags & HIF_USB_START)) + /* If firmware was loaded we should drop it + * go back to first stage bootloader. */ + if (!unplugged && (hif_dev->flags & HIF_USB_READY)) ath9k_hif_usb_reboot(udev); kfree(hif_dev); From 16ec75b5de6479637993ad0f7c11a49aae069f68 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 19 Jul 2013 23:31:27 -0400 Subject: [PATCH 20/23] cw1200: Fix OOPS in monitor mode In monitor mode, priv->vif is NULL, but at one point in the receive path we blindly attempt to dereference it. Add a test to prevent this. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/cw1200/txrx.c b/drivers/net/wireless/cw1200/txrx.c index 5862c373d714..e824d4d4a18d 100644 --- a/drivers/net/wireless/cw1200/txrx.c +++ b/drivers/net/wireless/cw1200/txrx.c @@ -1165,7 +1165,7 @@ void cw1200_rx_cb(struct cw1200_common *priv, if (cw1200_handle_action_rx(priv, skb)) return; } else if (ieee80211_is_beacon(frame->frame_control) && - !arg->status && + !arg->status && priv->vif && !memcmp(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid, ETH_ALEN)) { const u8 *tim_ie; From 5d21608a592a9afcac8d82c6478a564e911ce70b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 20 Jul 2013 21:46:48 -0500 Subject: [PATCH 21/23] ath: wil6210: Fix build error Building driver wil6210 in 3.10 and 3.11 kernels yields the following errors: CC [M] drivers/net/wireless/ath/wil6210/debugfs.o drivers/net/wireless/ath/wil6210/debugfs.c: In function 'wil_print_ring': drivers/net/wireless/ath/wil6210/debugfs.c:163:11: error: pointer targets in passing argument 5 of 'hex_dump_to_buffer' differ in signedness [-Werror=pointer-sign] false); ^ In file included from include/linux/kernel.h:13:0, from include/linux/cache.h:4, from include/linux/time.h:4, from include/linux/stat.h:18, from include/linux/module.h:10, from drivers/net/wireless/ath/wil6210/debugfs.c:17: include/linux/printk.h:361:13: note: expected 'char *' but argument is of type 'unsigned char *' extern void hex_dump_to_buffer(const void *buf, size_t len, ^ drivers/net/wireless/ath/wil6210/debugfs.c: In function 'wil_txdesc_debugfs_show': drivers/net/wireless/ath/wil6210/debugfs.c:429:10: error: pointer targets in passing argument 5 of 'hex_dump_to_buffer' differ in signedness [-Werror=pointer-sign] sizeof(printbuf), false); ^ In file included from include/linux/kernel.h:13:0, from include/linux/cache.h:4, from include/linux/time.h:4, from include/linux/stat.h:18, from include/linux/module.h:10, from drivers/net/wireless/ath/wil6210/debugfs.c:17: include/linux/printk.h:361:13: note: expected 'char *' but argument is of type 'unsigned char *' extern void hex_dump_to_buffer(const void *buf, size_t len, ^ cc1: all warnings being treated as errors make[5]: *** [drivers/net/wireless/ath/wil6210/debugfs.o] Error 1 make[4]: *** [drivers/net/wireless/ath/wil6210] Error 2 make[3]: *** [drivers/net/wireless/ath] Error 2 make[2]: *** [drivers/net/wireless] Error 2 make[1]: *** [drivers/net] Error 2 make: *** [drivers] Error 2 These errors are fixed by changing the type of the buffer from "unsigned char *" to "char *". Reported-by: Thomas Fjellstrom Tested-by: Thomas Fjellstrom Signed-off-by: Larry Finger Cc: Stable [3.10] Cc: Thomas Fjellstrom Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index e8308ec30970..ab636767fbde 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -145,7 +145,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, le16_to_cpu(hdr.type), hdr.flags); if (len <= MAX_MBOXITEM_SIZE) { int n = 0; - unsigned char printbuf[16 * 3 + 2]; + char printbuf[16 * 3 + 2]; unsigned char databuf[MAX_MBOXITEM_SIZE]; void __iomem *src = wmi_buffer(wil, d.addr) + sizeof(struct wil6210_mbox_hdr); @@ -416,7 +416,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) seq_printf(s, " SKB = %p\n", skb); if (skb) { - unsigned char printbuf[16 * 3 + 2]; + char printbuf[16 * 3 + 2]; int i = 0; int len = le16_to_cpu(d->dma.length); void *p = skb->data; From 28a905b51c2b3fabbb0eb53af229fc365200e398 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 22 Jul 2013 20:31:22 +0200 Subject: [PATCH 22/23] brcmfmac: decrement pending 8021x count upon tx failure If the transmit fails because there are no hanger slots or any other reason and the packet was an EAPOL packet the pending counter should be decreased although it was not transmitted so the driver does not end up in a dead-lock. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index f0d9f7f6c83d..29b1f24c2d0f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1744,13 +1744,14 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) ulong flags; int fifo = BRCMF_FWS_FIFO_BCMC; bool multicast = is_multicast_ether_addr(eh->h_dest); + bool pae = eh->h_proto == htons(ETH_P_PAE); /* determine the priority */ if (!skb->priority) skb->priority = cfg80211_classify8021d(skb); drvr->tx_multicast += !!multicast; - if (ntohs(eh->h_proto) == ETH_P_PAE) + if (pae) atomic_inc(&ifp->pend_8021x_cnt); if (!brcmf_fws_fc_active(fws)) { @@ -1781,6 +1782,11 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) brcmf_fws_schedule_deq(fws); } else { brcmf_err("drop skb: no hanger slot\n"); + if (pae) { + atomic_dec(&ifp->pend_8021x_cnt); + if (waitqueue_active(&ifp->pend_8021x_wait)) + wake_up(&ifp->pend_8021x_wait); + } brcmu_pkt_buf_free_skb(skb); } brcmf_fws_unlock(drvr, flags); From 23d412a2e94f55b84dbf9d5e64f381677bc90575 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 22 Jul 2013 12:46:24 +0200 Subject: [PATCH 23/23] brcmfmac: bail out of brcmf_txflowblock_if() for non-netdev interface To avoid ending up in a NULL-pointer access, the function brcmf_txflowblock_if() should only be called for interfaces that have a netdev associated with it. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 8e8975562ec3..80099016d21f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -242,7 +242,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, { unsigned long flags; - if (!ifp) + if (!ifp || !ifp->ndev) return; brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",