From f09eca8db0184aeb6b9718a987cfb3653ad7c4ae Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 9 Jul 2013 20:16:39 +0200 Subject: netfilter: ctnetlink: fix incorrect NAT expectation dumping nf_ct_expect_alloc leaves unset the expectation NAT fields. However, ctnetlink_exp_dump_expect expects them to be zeroed in case they are not used, which may not be the case. This results in dumping the NAT tuple of the expectation when it should not. Fix it by zeroing the NAT fields of the expectation. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_expect.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index c63b618cd619..4fd1ca94fd4a 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -293,6 +293,11 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class, sizeof(exp->tuple.dst.u3) - len); exp->tuple.dst.u.all = *dst; + +#ifdef CONFIG_NF_NAT_NEEDED + memset(&exp->saved_addr, 0, sizeof(exp->saved_addr)); + memset(&exp->saved_proto, 0, sizeof(exp->saved_proto)); +#endif } EXPORT_SYMBOL_GPL(nf_ct_expect_init); -- cgit v1.2.3-59-g8ed1b From baf60efa585c78b269f0097288868a51ccc61f55 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 11 Jul 2013 19:22:19 -0700 Subject: netfilter: xt_socket: fix broken v0 support commit 681f130f39e10 ("netfilter: xt_socket: add XT_SOCKET_NOWILDCARD flag") added a potential NULL dereference if an old iptables package uses v0 of the match. Fix this by removing the test on @info in fast path. IPv6 can remove the test as well, as it uses v1 or v2. Reported-by: Neal Cardwell Signed-off-by: Eric Dumazet Cc: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_socket.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index f8b71911037a..20b15916f403 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -172,7 +172,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, /* Ignore non-transparent sockets, if XT_SOCKET_TRANSPARENT is used */ - if (info && info->flags & XT_SOCKET_TRANSPARENT) + if (info->flags & XT_SOCKET_TRANSPARENT) transparent = ((sk->sk_state != TCP_TIME_WAIT && inet_sk(sk)->transparent) || (sk->sk_state == TCP_TIME_WAIT && @@ -196,7 +196,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, static bool socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par) { - return socket_match(skb, par, NULL); + static struct xt_socket_mtinfo1 xt_info_v0 = { + .flags = 0, + }; + + return socket_match(skb, par, &xt_info_v0); } static bool @@ -314,7 +318,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) /* Ignore non-transparent sockets, if XT_SOCKET_TRANSPARENT is used */ - if (info && info->flags & XT_SOCKET_TRANSPARENT) + if (info->flags & XT_SOCKET_TRANSPARENT) transparent = ((sk->sk_state != TCP_TIME_WAIT && inet_sk(sk)->transparent) || (sk->sk_state == TCP_TIME_WAIT && -- cgit v1.2.3-59-g8ed1b From a0ec570f4f69c4cb700d743a915096c2c8f56a99 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Tue, 25 Jun 2013 09:17:17 +0200 Subject: 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: -- cgit v1.2.3-59-g8ed1b From 923a0e7dee8c436108279568cf34444749ac796f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 28 Jun 2013 11:38:54 +0200 Subject: 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, -- cgit v1.2.3-59-g8ed1b From f77b86d7d3acf9dfcb5ee834628d12207584b2cb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 24 Jun 2013 15:43:38 +0200 Subject: 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) -- cgit v1.2.3-59-g8ed1b From 1cd158573951f737fbc878a35cb5eb47bf9af3d5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 28 Jun 2013 21:04:35 +0200 Subject: 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 -- cgit v1.2.3-59-g8ed1b From e13bae4f807401729b3f27c7e882a96b8b292809 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Jul 2013 10:43:31 +0200 Subject: 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); } -- cgit v1.2.3-59-g8ed1b From 83374fe9de455e37c2a039603d2538eb77e8ec4d Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Thu, 11 Jul 2013 18:24:03 +0800 Subject: 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); -- cgit v1.2.3-59-g8ed1b From 6b0f32745dcfba01d7be33acd1b40306c7a914c6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Jul 2013 22:33:26 +0200 Subject: 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)) { -- cgit v1.2.3-59-g8ed1b From b7327d89ae694a89f9934d428bde520b77b3131c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 24 Jun 2013 15:44:03 +0300 Subject: 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, -- cgit v1.2.3-59-g8ed1b From 707aee401d2467baa785a697f40a6e2d9ee79ad5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 3 May 2013 18:58:16 +0200 Subject: 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 */ -- cgit v1.2.3-59-g8ed1b From 0ecb376375d662987eba2f6e3bfd4bd532bb3907 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Sun, 23 Jun 2013 20:31:07 +0300 Subject: 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); -- cgit v1.2.3-59-g8ed1b From 93a426673fbfeae7fa6b27008828e2ac4c08dbee Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 2 Jul 2013 13:35:35 +0300 Subject: 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; -- cgit v1.2.3-59-g8ed1b From 113a04470d9178170a5d1aa165809515884f39a8 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 2 Jul 2013 14:16:38 +0300 Subject: 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; } -- cgit v1.2.3-59-g8ed1b From 48bc13072109ea58465542aa1ee31b4e1065468a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 4 Jul 2013 15:55:29 +0200 Subject: 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; -- cgit v1.2.3-59-g8ed1b From fe04e83706037802c502ea41c0d1799ec35fc0d7 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Thu, 4 Jul 2013 15:17:48 +0300 Subject: 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, -- cgit v1.2.3-59-g8ed1b From a590ad411891de551e6de1b51ea635c0484148d6 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Thu, 4 Jul 2013 15:22:26 +0300 Subject: 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; -- cgit v1.2.3-59-g8ed1b From 5c9fc93bc9bc417418fc1b6366833ae6a07b804d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 15 Jul 2013 14:35:06 +0200 Subject: 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; -- cgit v1.2.3-59-g8ed1b From bcfb879432094c267c35a7ff75d953d3a66c193a Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 28 Jun 2013 09:12:53 -0500 Subject: rtlwifi: Initialize power-setting callback for USB devices Commit a269913c5 entitled "rtlwifi: Rework rtl_lps_leave() and rtl_lps_enter() to use work queue" has two bugs for USB drivers. Firstly, the work queue in question was not initialized. Secondly, the callback routine used by this queue is contained within the file used for PCI devices. As a result, it is not available for architectures without PCI hardware. Signed-off-by: Larry Finger Reported-by: Richard Genoud Tested-by: Richard Genoud Cc: Richard Genoud Cc: Stable [3.10] Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 13 ------------- drivers/net/wireless/rtlwifi/ps.c | 12 ++++++++++++ drivers/net/wireless/rtlwifi/ps.h | 1 + drivers/net/wireless/rtlwifi/usb.c | 2 ++ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index c97e9d327331..e70b4ffaf97f 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1008,19 +1008,6 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) return; } -static void rtl_lps_change_work_callback(struct work_struct *work) -{ - struct rtl_works *rtlworks = - container_of(work, struct rtl_works, lps_change_work); - struct ieee80211_hw *hw = rtlworks->hw; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->enter_ps) - rtl_lps_enter(hw); - else - rtl_lps_leave(hw); -} - static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 884bceae38a9..71e917db8338 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -611,6 +611,18 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); } +void rtl_lps_change_work_callback(struct work_struct *work) +{ + struct rtl_works *rtlworks = + container_of(work, struct rtl_works, lps_change_work); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->enter_ps) + rtl_lps_enter(hw); + else + rtl_lps_leave(hw); +} void rtl_swlps_wq_callback(void *data) { diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h index 4d682b753f50..88bd76ea88f7 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/rtlwifi/ps.h @@ -49,5 +49,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw); void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len); +void rtl_lps_change_work_callback(struct work_struct *work); #endif diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index a3532e077871..1feebdc92f41 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -1070,6 +1070,8 @@ int rtl_usb_probe(struct usb_interface *intf, spin_lock_init(&rtlpriv->locks.usb_lock); INIT_WORK(&rtlpriv->works.fill_h2c_cmd, rtl_fill_h2c_cmd_work_callback); + INIT_WORK(&rtlpriv->works.lps_change_work, + rtl_lps_change_work_callback); rtlpriv->usb_data_index = 0; init_completion(&rtlpriv->firmware_loading_complete); -- cgit v1.2.3-59-g8ed1b From a4943ccbc316fd74d3612d7a5984a91ab7e5dc8c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 30 Jun 2013 12:02:13 +0200 Subject: ath9k: fix tx pending frames accounting for dropped packets When dropping packets that have gone far enough into the tx path, the pending frame counter needs to be decreased. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 44 ++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index c59ae43b9b35..927992732620 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -146,6 +146,28 @@ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta, ARRAY_SIZE(bf->rates)); } +static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, + struct sk_buff *skb) +{ + int q; + + q = skb_get_queue_mapping(skb); + if (txq == sc->tx.uapsdq) + txq = sc->tx.txq_map[q]; + + if (txq != sc->tx.txq_map[q]) + return; + + if (WARN_ON(--txq->pending_frames < 0)) + txq->pending_frames = 0; + + if (txq->stopped && + txq->pending_frames < sc->tx.txq_max_pending[q]) { + ieee80211_wake_queue(sc->hw, q); + txq->stopped = false; + } +} + static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { struct ath_txq *txq = tid->ac->txq; @@ -167,6 +189,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) if (!bf) { bf = ath_tx_setup_buffer(sc, txq, tid, skb); if (!bf) { + ath_txq_skb_done(sc, txq, skb); ieee80211_free_txskb(sc->hw, skb); continue; } @@ -811,6 +834,7 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, if (!bf) { __skb_unlink(skb, &tid->buf_q); + ath_txq_skb_done(sc, txq, skb); ieee80211_free_txskb(sc->hw, skb); continue; } @@ -1824,6 +1848,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_txq *txq, bf = ath_tx_setup_buffer(sc, txq, tid, skb); if (!bf) { + ath_txq_skb_done(sc, txq, skb); ieee80211_free_txskb(sc->hw, skb); return; } @@ -2090,6 +2115,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, bf = ath_tx_setup_buffer(sc, txq, tid, skb); if (!bf) { + ath_txq_skb_done(sc, txq, skb); if (txctl->paprd) dev_kfree_skb_any(skb); else @@ -2189,7 +2215,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; - int q, padpos, padsize; + int padpos, padsize; unsigned long flags; ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); @@ -2225,21 +2251,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, spin_unlock_irqrestore(&sc->sc_pm_lock, flags); __skb_queue_tail(&txq->complete_q, skb); - - q = skb_get_queue_mapping(skb); - if (txq == sc->tx.uapsdq) - txq = sc->tx.txq_map[q]; - - if (txq == sc->tx.txq_map[q]) { - if (WARN_ON(--txq->pending_frames < 0)) - txq->pending_frames = 0; - - if (txq->stopped && - txq->pending_frames < sc->tx.txq_max_pending[q]) { - ieee80211_wake_queue(sc->hw, q); - txq->stopped = false; - } - } + ath_txq_skb_done(sc, txq, skb); } static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, -- cgit v1.2.3-59-g8ed1b From 9494849e53e74048ee14d512feade01db402eef7 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Tue, 2 Jul 2013 00:43:42 +0400 Subject: ath9k_htc: fix data race between request_firmware_nowait() callback and suspend() ath9k_hif_usb_probe() requests firmware asynchronically and there is some initialization postponed till firmware is ready. In particular, ath9k_hif_usb_firmware_cb() callback initializes hif_dev->tx.tx_buf and hif_dev->tx.tx_pending lists. At the same time, ath9k_hif_usb_suspend() iterates that lists through ath9k_hif_usb_dealloc_urbs(). If suspend happens before request_firmware_nowait() callback is called, it can lead to oops. Similar issue could be in ath9k_hif_usb_disconnect(), but it is prevented using hif_dev->fw_done completion and HIF_USB_READY flag. The patch extends this approach to suspend() as well. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 9e582e14da74..2469db5a5bb1 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1082,7 +1082,7 @@ static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev) struct device *dev = &hif_dev->udev->dev; struct device *parent = dev->parent; - complete(&hif_dev->fw_done); + complete_all(&hif_dev->fw_done); if (parent) device_lock(parent); @@ -1131,7 +1131,7 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context) release_firmware(fw); hif_dev->flags |= HIF_USB_READY; - complete(&hif_dev->fw_done); + complete_all(&hif_dev->fw_done); return; @@ -1316,7 +1316,10 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface, if (!(hif_dev->flags & HIF_USB_START)) ath9k_htc_suspend(hif_dev->htc_handle); - ath9k_hif_usb_dealloc_urbs(hif_dev); + wait_for_completion(&hif_dev->fw_done); + + if (hif_dev->flags & HIF_USB_READY) + ath9k_hif_usb_dealloc_urbs(hif_dev); return 0; } -- cgit v1.2.3-59-g8ed1b From b01a60be7a4a161ac0a11df30569d21a20795aef Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 5 Jul 2013 17:43:56 +0200 Subject: ssb: fix alignment of struct bcma_device_id The ARM OABI and EABI disagree on the alignment of structures with small members, so module init tools may interpret the ssb device table incorrectly, as shown by this warning when building the b43 device driver in an OABI kernel: FATAL: drivers/net/wireless/b43/b43: sizeof(struct ssb_device_id)=6 is not a modulo of the size of section __mod_ssb_device_table=88. Forcing the default (EABI) alignment on the structure makes this problem go away. Since the ssb_device_id may have the same problem, better fix both structures. Signed-off-by: Arnd Bergmann Cc: Russell King Cc: John W. Linville Cc: Michael Buesch Cc: Larry Finger Signed-off-by: John W. Linville --- include/linux/mod_devicetable.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index b62d4af6c667..45e921401b06 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -361,7 +361,8 @@ struct ssb_device_id { __u16 vendor; __u16 coreid; __u8 revision; -}; + __u8 __pad; +} __attribute__((packed, aligned(2))); #define SSB_DEVICE(_vendor, _coreid, _revision) \ { .vendor = _vendor, .coreid = _coreid, .revision = _revision, } #define SSB_DEVTABLE_END \ @@ -377,7 +378,7 @@ struct bcma_device_id { __u16 id; __u8 rev; __u8 class; -}; +} __attribute__((packed,aligned(2))); #define BCMA_CORE(_manuf, _id, _rev, _class) \ { .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, } #define BCMA_CORETABLE_END \ -- cgit v1.2.3-59-g8ed1b From 6a08483926bf26d9e5274b4dd5086d583971f1ea Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 10 Jul 2013 23:03:35 +0200 Subject: rt2x00: RT2X00 should depend on HAS_DMA If NO_DMA=y: drivers/built-in.o: In function `rt2x00queue_unmap_skb': drivers/net/wireless/rt2x00/rt2x00queue.c:129: undefined reference to `dma_unmap_single' drivers/net/wireless/rt2x00/rt2x00queue.c:133: undefined reference to `dma_unmap_single' drivers/built-in.o: In function `rt2x00queue_map_txskb': drivers/net/wireless/rt2x00/rt2x00queue.c:112: undefined reference to `dma_map_single' drivers/net/wireless/rt2x00/rt2x00queue.c:115: undefined reference to `dma_mapping_error' drivers/built-in.o: In function `rt2x00queue_alloc_rxskb': drivers/net/wireless/rt2x00/rt2x00queue.c:93: undefined reference to `dma_map_single' drivers/net/wireless/rt2x00/rt2x00queue.c:95: undefined reference to `dma_mapping_error' Signed-off-by: Geert Uytterhoeven Cc: linux-wireless@vger.kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 9b915d3a44be..3e60a31582f8 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -1,6 +1,6 @@ menuconfig RT2X00 tristate "Ralink driver support" - depends on MAC80211 + depends on MAC80211 && HAS_DMA ---help--- This will enable the support for the Ralink drivers, developed in the rt2x00 project . -- cgit v1.2.3-59-g8ed1b From f287cbd01f2e8e1b325b96233c373619c2d25ee2 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 11 Jul 2013 09:19:13 -0400 Subject: ath5k: fix extra set bit in multicast mask Bit 32 was always set which looks to have been accidental, according to git history. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 81b686c6a376..40825d43322e 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -325,7 +325,7 @@ ath5k_prepare_multicast(struct ieee80211_hw *hw, struct netdev_hw_addr *ha; mfilt[0] = 0; - mfilt[1] = 1; + mfilt[1] = 0; netdev_hw_addr_list_for_each(ha, mc_list) { /* calculate XOR of eight 6-bit values */ -- cgit v1.2.3-59-g8ed1b From 6f334c2b3966f10cbd089bb124ec0e114d8d8c77 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 12 Jul 2013 15:32:15 -0500 Subject: rtlwifi: Fix build errors for unusual cases The present build configuration for the rtlwifi family of drivers will fail under two known conditions: (1) If rtlwifi is selected without selecting any of the dependent drivers, there are errors in the build. (2) If the PCI drivers are built into the kernel and the USB drivers are modules, or vice versa, there are missing globals. The first condition is fixed by never building rtlwifi unless at least one of the device drivers is selected. The second failure is fixed by splitting the PCI and USB codes out of rtlwifi, and creating their own mini drivers. If the drivers that use them are modules, they will also be modules. Although a number of files are touched by this patch, only Makefile and Kconfig have undergone significant changes. The only modifications to the other files were to export entry points needed by the new rtl_pci and rtl_usb units, or to rename two variables that had names that were likely to cause namespace collisions. Reported-by: Fengguang Wu [Condition 1] Reported-by: Ben Hutchings [Condition 2] Signed-off-by: Larry Finger Cc: Ben Hutchings Cc: Fengguang Wu Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/Kconfig | 72 +++++++++++++++++++++++------------ drivers/net/wireless/rtlwifi/Makefile | 10 ++--- drivers/net/wireless/rtlwifi/base.c | 19 +++++++-- drivers/net/wireless/rtlwifi/base.h | 2 +- drivers/net/wireless/rtlwifi/core.c | 1 + drivers/net/wireless/rtlwifi/debug.c | 1 + drivers/net/wireless/rtlwifi/efuse.c | 1 + drivers/net/wireless/rtlwifi/pci.c | 9 ++++- drivers/net/wireless/rtlwifi/ps.c | 4 ++ drivers/net/wireless/rtlwifi/usb.c | 7 ++++ 10 files changed, 91 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index 7253de3d8c66..c2ffce7a907c 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig @@ -1,27 +1,20 @@ -config RTLWIFI - tristate "Realtek wireless card support" - depends on MAC80211 - select FW_LOADER - ---help--- - This is common code for RTL8192CE/RTL8192CU/RTL8192SE/RTL8723AE - drivers. This module does nothing by itself - the various front-end - drivers need to be enabled to support any desired devices. - - If you choose to build as a module, it'll be called rtlwifi. - -config RTLWIFI_DEBUG - bool "Debugging output for rtlwifi driver family" - depends on RTLWIFI +menuconfig RTL_CARDS + tristate "Realtek rtlwifi family of devices" + depends on MAC80211 && (PCI || USB) default y ---help--- - To use the module option that sets the dynamic-debugging level for, - the front-end driver, this parameter must be "Y". For memory-limited - systems, choose "N". If in doubt, choose "Y". + This option will enable support for the Realtek mac80211-based + wireless drivers. Drivers rtl8192ce, rtl8192cu, rtl8192se, rtl8192de, + rtl8723eu, and rtl8188eu share some common code. + +if RTL_CARDS config RTL8192CE tristate "Realtek RTL8192CE/RTL8188CE Wireless Network Adapter" - depends on RTLWIFI && PCI + depends on PCI select RTL8192C_COMMON + select RTLWIFI + select RTLWIFI_PCI ---help--- This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe wireless network adapters. @@ -30,7 +23,9 @@ config RTL8192CE config RTL8192SE tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter" - depends on RTLWIFI && PCI + depends on PCI + select RTLWIFI + select RTLWIFI_PCI ---help--- This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe wireless network adapters. @@ -39,7 +34,9 @@ config RTL8192SE config RTL8192DE tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter" - depends on RTLWIFI && PCI + depends on PCI + select RTLWIFI + select RTLWIFI_PCI ---help--- This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe wireless network adapters. @@ -48,7 +45,9 @@ config RTL8192DE config RTL8723AE tristate "Realtek RTL8723AE PCIe Wireless Network Adapter" - depends on RTLWIFI && PCI + depends on PCI + select RTLWIFI + select RTLWIFI_PCI ---help--- This is the driver for Realtek RTL8723AE 802.11n PCIe wireless network adapters. @@ -57,7 +56,9 @@ config RTL8723AE config RTL8188EE tristate "Realtek RTL8188EE Wireless Network Adapter" - depends on RTLWIFI && PCI + depends on PCI + select RTLWIFI + select RTLWIFI_PCI ---help--- This is the driver for Realtek RTL8188EE 802.11n PCIe wireless network adapters. @@ -66,7 +67,9 @@ config RTL8188EE config RTL8192CU tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" - depends on RTLWIFI && USB + depends on USB + select RTLWIFI + select RTLWIFI_USB select RTL8192C_COMMON ---help--- This is the driver for Realtek RTL8192CU/RTL8188CU 802.11n USB @@ -74,7 +77,28 @@ config RTL8192CU If you choose to build it as a module, it will be called rtl8192cu +config RTLWIFI + tristate + select FW_LOADER + +config RTLWIFI_PCI + tristate + +config RTLWIFI_USB + tristate + +config RTLWIFI_DEBUG + bool "Debugging output for rtlwifi driver family" + depends on RTLWIFI + default y + ---help--- + To use the module option that sets the dynamic-debugging level for, + the front-end driver, this parameter must be "Y". For memory-limited + systems, choose "N". If in doubt, choose "Y". + config RTL8192C_COMMON tristate depends on RTL8192CE || RTL8192CU - default m + default y + +endif diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile index ff02b874f8d8..d56f023a4b90 100644 --- a/drivers/net/wireless/rtlwifi/Makefile +++ b/drivers/net/wireless/rtlwifi/Makefile @@ -12,13 +12,11 @@ rtlwifi-objs := \ rtl8192c_common-objs += \ -ifneq ($(CONFIG_PCI),) -rtlwifi-objs += pci.o -endif +obj-$(CONFIG_RTLWIFI_PCI) += rtl_pci.o +rtl_pci-objs := pci.o -ifneq ($(CONFIG_USB),) -rtlwifi-objs += usb.o -endif +obj-$(CONFIG_RTLWIFI_USB) += rtl_usb.o +rtl_usb-objs := usb.o obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/ obj-$(CONFIG_RTL8192CE) += rtl8192ce/ diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 9d558ac77b0c..7651f5acc14b 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -172,6 +172,7 @@ u8 rtl_tid_to_ac(u8 tid) { return tid_to_ac[tid]; } +EXPORT_SYMBOL_GPL(rtl_tid_to_ac); static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, struct ieee80211_sta_ht_cap *ht_cap) @@ -406,6 +407,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw) cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); cancel_delayed_work(&rtlpriv->works.fwevt_wq); } +EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work); void rtl_init_rfkill(struct ieee80211_hw *hw) { @@ -439,6 +441,7 @@ void rtl_deinit_rfkill(struct ieee80211_hw *hw) { wiphy_rfkill_stop_polling(hw->wiphy); } +EXPORT_SYMBOL_GPL(rtl_deinit_rfkill); int rtl_init_core(struct ieee80211_hw *hw) { @@ -489,10 +492,12 @@ int rtl_init_core(struct ieee80211_hw *hw) return 0; } +EXPORT_SYMBOL_GPL(rtl_init_core); void rtl_deinit_core(struct ieee80211_hw *hw) { } +EXPORT_SYMBOL_GPL(rtl_deinit_core); void rtl_init_rx_config(struct ieee80211_hw *hw) { @@ -501,6 +506,7 @@ void rtl_init_rx_config(struct ieee80211_hw *hw) rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); } +EXPORT_SYMBOL_GPL(rtl_init_rx_config); /********************************************************* * @@ -879,6 +885,7 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) return true; } +EXPORT_SYMBOL_GPL(rtl_tx_mgmt_proc); void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, @@ -1052,6 +1059,7 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) return true; } +EXPORT_SYMBOL_GPL(rtl_action_proc); /*should call before software enc*/ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) @@ -1125,6 +1133,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) return false; } +EXPORT_SYMBOL_GPL(rtl_is_special_data); /********************************************************* * @@ -1300,6 +1309,7 @@ void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) rtlpriv->link_info.bcn_rx_inperiod++; } +EXPORT_SYMBOL_GPL(rtl_beacon_statistic); void rtl_watchdog_wq_callback(void *data) { @@ -1793,6 +1803,7 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) mac->vendor = vendor; } +EXPORT_SYMBOL_GPL(rtl_recognize_peer); /********************************************************* * @@ -1849,6 +1860,7 @@ struct attribute_group rtl_attribute_group = { .name = "rtlsysfs", .attrs = rtl_sysfs_entries, }; +EXPORT_SYMBOL_GPL(rtl_attribute_group); MODULE_AUTHOR("lizhaoming "); MODULE_AUTHOR("Realtek WlanFAE "); @@ -1856,7 +1868,8 @@ MODULE_AUTHOR("Larry Finger "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); -struct rtl_global_var global_var = {}; +struct rtl_global_var rtl_global_var = {}; +EXPORT_SYMBOL_GPL(rtl_global_var); static int __init rtl_core_module_init(void) { @@ -1864,8 +1877,8 @@ static int __init rtl_core_module_init(void) pr_err("Unable to register rtl_rc, use default RC !!\n"); /* init some global vars */ - INIT_LIST_HEAD(&global_var.glb_priv_list); - spin_lock_init(&global_var.glb_list_lock); + INIT_LIST_HEAD(&rtl_global_var.glb_priv_list); + spin_lock_init(&rtl_global_var.glb_list_lock); return 0; } diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index 8576bc34b032..0e5fe0902daf 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h @@ -147,7 +147,7 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); u8 rtl_tid_to_ac(u8 tid); extern struct attribute_group rtl_attribute_group; void rtl_easy_concurrent_retrytimer_callback(unsigned long data); -extern struct rtl_global_var global_var; +extern struct rtl_global_var rtl_global_var; int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, u8 desc_rate, bool first_ampdu); bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index ee84844be008..733b7ce7f0e2 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -1330,3 +1330,4 @@ const struct ieee80211_ops rtl_ops = { .rfkill_poll = rtl_op_rfkill_poll, .flush = rtl_op_flush, }; +EXPORT_SYMBOL_GPL(rtl_ops); diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c index 7d52d3d7769f..76e2086e137e 100644 --- a/drivers/net/wireless/rtlwifi/debug.c +++ b/drivers/net/wireless/rtlwifi/debug.c @@ -51,3 +51,4 @@ void rtl_dbgp_flag_init(struct ieee80211_hw *hw) /*Init Debug flag enable condition */ } +EXPORT_SYMBOL_GPL(rtl_dbgp_flag_init); diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 9e3894178e77..838a1ed3f194 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -229,6 +229,7 @@ void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) *pbuf = (u8) (value32 & 0xff); } +EXPORT_SYMBOL_GPL(read_efuse_byte); void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) { diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index e70b4ffaf97f..703f839af6ca 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -35,6 +35,13 @@ #include "efuse.h" #include #include +#include + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PCI basic driver for rtlwifi"); static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { PCI_VENDOR_ID_INTEL, @@ -1886,7 +1893,7 @@ int rtl_pci_probe(struct pci_dev *pdev, rtlpriv->rtlhal.interface = INTF_PCI; rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); rtlpriv->intf_ops = &rtl_pci_ops; - rtlpriv->glb_var = &global_var; + rtlpriv->glb_var = &rtl_global_var; /* *init dbgp flags before all diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 71e917db8338..298b615964e8 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -269,6 +269,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw) spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags); } +EXPORT_SYMBOL_GPL(rtl_ips_nic_on); /*for FW LPS*/ @@ -518,6 +519,7 @@ void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed); } } +EXPORT_SYMBOL_GPL(rtl_swlps_beacon); void rtl_swlps_rf_awake(struct ieee80211_hw *hw) { @@ -623,6 +625,7 @@ void rtl_lps_change_work_callback(struct work_struct *work) else rtl_lps_leave(hw); } +EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback); void rtl_swlps_wq_callback(void *data) { @@ -934,3 +937,4 @@ void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len) else rtl_p2p_noa_ie(hw, data, len - FCS_LEN); } +EXPORT_SYMBOL_GPL(rtl_p2p_info); diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 1feebdc92f41..e56778cac9bf 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -32,6 +32,13 @@ #include "ps.h" #include "rtl8192c/fw_common.h" #include +#include + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("USB basic driver for rtlwifi"); #define REALTEK_USB_VENQT_READ 0xC0 #define REALTEK_USB_VENQT_WRITE 0x40 -- cgit v1.2.3-59-g8ed1b From 64b6f46f1141ad938e354f37af62e28da972e8eb Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 15 Jul 2013 11:03:57 +0530 Subject: ath9k_hw: Fix multicast search for AR9002 family The multicast search bit is disabled for the AR9003 family, but this is required for AR9002 too. Fix this in the INI override routine. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index d1acfe98918a..1576d58291d4 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -610,7 +610,15 @@ static void ar5008_hw_override_ini(struct ath_hw *ah, REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); if (AR_SREV_9280_20_OR_LATER(ah)) { - val = REG_READ(ah, AR_PCU_MISC_MODE2); + /* + * For AR9280 and above, there is a new feature that allows + * Multicast search based on both MAC Address and Key ID. + * By default, this feature is enabled. But since the driver + * is not using this feature, we switch it off; otherwise + * multicast search based on MAC addr only will fail. + */ + val = REG_READ(ah, AR_PCU_MISC_MODE2) & + (~AR_ADHOC_MCAST_KEYID_ENABLE); if (!AR_SREV_9271(ah)) val &= ~AR_PCU_MISC_MODE2_HWWAR1; -- cgit v1.2.3-59-g8ed1b From 233a26e85f9a72bcd0cdb7a95d1d5abcd052369f Mon Sep 17 00:00:00 2001 From: Maximilian Schneider Date: Tue, 2 Jul 2013 23:43:29 +0000 Subject: net: can: esd_usb2: check index of array before accessing The esd_usb2_read_bulk_callback() function is parsing the data that comes from the USB CAN adapter. One datum is used as an index to access the dev->nets[] array. This patch adds the missing bounds checking. Acked-by: Matthias Fuchs Signed-off-by: Maximilian Schneider Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/esd_usb2.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index 6aa7b3266c80..ac6177d3befc 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -412,10 +412,20 @@ static void esd_usb2_read_bulk_callback(struct urb *urb) switch (msg->msg.hdr.cmd) { case CMD_CAN_RX: + if (msg->msg.rx.net >= dev->net_count) { + dev_err(dev->udev->dev.parent, "format error\n"); + break; + } + esd_usb2_rx_can_msg(dev->nets[msg->msg.rx.net], msg); break; case CMD_CAN_TX: + if (msg->msg.txdone.net >= dev->net_count) { + dev_err(dev->udev->dev.parent, "format error\n"); + break; + } + esd_usb2_tx_done_msg(dev->nets[msg->msg.txdone.net], msg); break; -- cgit v1.2.3-59-g8ed1b From 7671986839f9207f8d76e8ef92b2d3f263a794cc Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Thu, 18 Jul 2013 01:20:33 +0400 Subject: can: usb_8dev: fix urb leak on failure path in usb_8dev_start() If usb_8dev_start() fails to submit urb, it unanchors the urb but forgets to free it. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/usb_8dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index cbd388eea682..8becd3d838b5 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -779,6 +779,7 @@ static int usb_8dev_start(struct usb_8dev_priv *priv) usb_unanchor_urb(urb); usb_free_coherent(priv->udev, RX_BUFFER_SIZE, buf, urb->transfer_dma); + usb_free_urb(urb); break; } -- cgit v1.2.3-59-g8ed1b From 372675a4a9ac0a0af962d44dadeea69926ce45e0 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 18 Jul 2013 08:38:26 -0700 Subject: vxlan: unregister on namespace exit Fix memory leaks and other badness from VXLAN network namespace teardown. When network namespace is removed, all the vxlan devices should be unregistered (not closed). Signed-off-by: Stephen Hemminger Reviewed-by: Pravin B Shelar Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a5ba8dd7e6be..f101034a297a 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1878,10 +1878,12 @@ static __net_exit void vxlan_exit_net(struct net *net) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_dev *vxlan; + LIST_HEAD(list); rtnl_lock(); list_for_each_entry(vxlan, &vn->vxlan_list, next) - dev_close(vxlan->dev); + unregister_netdevice_queue(vxlan->dev, &list); + unregister_netdevice_many(&list); rtnl_unlock(); } -- cgit v1.2.3-59-g8ed1b From 3fc2de2faba387218bdf9dbc6b13f513ac3b060a Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 18 Jul 2013 08:40:15 -0700 Subject: vxlan: fix igmp races There are two race conditions in existing code for doing IGMP management in workqueue in vxlan. First, the vxlan_group_used function checks the list of vxlan's without any protection, and it is possible for open followed by close to occur before the igmp work queue runs. To solve these move the check into vxlan_open/stop so it is protected by RTNL. And split into two work structures so that there is no racy reference to underlying device state. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 53 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f101034a297a..f4c6db419ddb 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -136,7 +136,8 @@ struct vxlan_dev { u32 flags; /* VXLAN_F_* below */ struct work_struct sock_work; - struct work_struct igmp_work; + struct work_struct igmp_join; + struct work_struct igmp_leave; unsigned long age_interval; struct timer_list age_timer; @@ -736,7 +737,6 @@ static bool vxlan_snoop(struct net_device *dev, return false; } - /* See if multicast group is already in use by other ID */ static bool vxlan_group_used(struct vxlan_net *vn, __be32 remote_ip) { @@ -770,12 +770,13 @@ static void vxlan_sock_release(struct vxlan_net *vn, struct vxlan_sock *vs) queue_work(vxlan_wq, &vs->del_work); } -/* Callback to update multicast group membership. - * Scheduled when vxlan goes up/down. +/* Callback to update multicast group membership when first VNI on + * multicast asddress is brought up + * Done as workqueue because ip_mc_join_group acquires RTNL. */ -static void vxlan_igmp_work(struct work_struct *work) +static void vxlan_igmp_join(struct work_struct *work) { - struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_work); + struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_join); struct vxlan_net *vn = net_generic(dev_net(vxlan->dev), vxlan_net_id); struct vxlan_sock *vs = vxlan->vn_sock; struct sock *sk = vs->sock->sk; @@ -785,10 +786,27 @@ static void vxlan_igmp_work(struct work_struct *work) }; lock_sock(sk); - if (vxlan_group_used(vn, vxlan->default_dst.remote_ip)) - ip_mc_join_group(sk, &mreq); - else - ip_mc_leave_group(sk, &mreq); + ip_mc_join_group(sk, &mreq); + release_sock(sk); + + vxlan_sock_release(vn, vs); + dev_put(vxlan->dev); +} + +/* Inverse of vxlan_igmp_join when last VNI is brought down */ +static void vxlan_igmp_leave(struct work_struct *work) +{ + struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_leave); + struct vxlan_net *vn = net_generic(dev_net(vxlan->dev), vxlan_net_id); + struct vxlan_sock *vs = vxlan->vn_sock; + struct sock *sk = vs->sock->sk; + struct ip_mreqn mreq = { + .imr_multiaddr.s_addr = vxlan->default_dst.remote_ip, + .imr_ifindex = vxlan->default_dst.remote_ifindex, + }; + + lock_sock(sk); + ip_mc_leave_group(sk, &mreq); release_sock(sk); vxlan_sock_release(vn, vs); @@ -1359,6 +1377,7 @@ static void vxlan_uninit(struct net_device *dev) /* Start ageing timer and join group when device is brought up */ static int vxlan_open(struct net_device *dev) { + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_sock *vs = vxlan->vn_sock; @@ -1366,10 +1385,11 @@ static int vxlan_open(struct net_device *dev) if (!vs) return -ENOTCONN; - if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { + if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip)) && + ! vxlan_group_used(vn, vxlan->default_dst.remote_ip)) { vxlan_sock_hold(vs); dev_hold(dev); - queue_work(vxlan_wq, &vxlan->igmp_work); + queue_work(vxlan_wq, &vxlan->igmp_join); } if (vxlan->age_interval) @@ -1400,13 +1420,15 @@ static void vxlan_flush(struct vxlan_dev *vxlan) /* Cleanup timer and forwarding table on shutdown */ static int vxlan_stop(struct net_device *dev) { + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_sock *vs = vxlan->vn_sock; - if (vs && IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { + if (vs && IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip)) && + ! vxlan_group_used(vn, vxlan->default_dst.remote_ip)) { vxlan_sock_hold(vs); dev_hold(dev); - queue_work(vxlan_wq, &vxlan->igmp_work); + queue_work(vxlan_wq, &vxlan->igmp_leave); } del_timer_sync(&vxlan->age_timer); @@ -1471,7 +1493,8 @@ static void vxlan_setup(struct net_device *dev) INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); - INIT_WORK(&vxlan->igmp_work, vxlan_igmp_work); + INIT_WORK(&vxlan->igmp_join, vxlan_igmp_join); + INIT_WORK(&vxlan->igmp_leave, vxlan_igmp_leave); INIT_WORK(&vxlan->sock_work, vxlan_sock_work); init_timer_deferrable(&vxlan->age_timer); -- cgit v1.2.3-59-g8ed1b From 2deb535af7c824f37d6bc8657fd09e3d10696ee8 Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Fri, 19 Jul 2013 16:56:26 -0400 Subject: qlcnic: Fix invalid register offset calculation 83xx adapter specific code was accessing 82xx register which resulted in invalid register offset. This patch uses proper register access method. Signed-off-by: Shahed Shaikh Signed-off-by: Jitendra Kalsaria Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 700a46324d09..05a847e599c6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -1540,7 +1540,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) return 0; case QLCNIC_SET_QUIESCENT: case QLCNIC_RESET_QUIESCENT: - state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); + state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) netdev_info(netdev, "Device in FAILED state\n"); return 0; -- cgit v1.2.3-59-g8ed1b From cfacb172fa699263a4f74a63d886e171fe3eafbe Mon Sep 17 00:00:00 2001 From: Pratik Pujar Date: Fri, 19 Jul 2013 16:56:27 -0400 Subject: qlcnic: Set __QLCNIC_DEV_UP in adapter state before enabling interrupts NAPI poll function does not re-enable the interrupt, if __QLCNIC_DEV_UP is not set in adapter state. This was preventing driver from receiving any packet. Signed-off-by: Pratik Pujar Signed-off-by: Jitendra Kalsaria Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 4528f8ec333b..41635f2b9399 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -1531,12 +1531,12 @@ int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) if (netdev->features & NETIF_F_LRO) qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED); + set_bit(__QLCNIC_DEV_UP, &adapter->state); qlcnic_napi_enable(adapter); qlcnic_linkevent_request(adapter, 1); adapter->ahw->reset_context = 0; - set_bit(__QLCNIC_DEV_UP, &adapter->state); return 0; } -- cgit v1.2.3-59-g8ed1b From e9a355a9b407da41b7cb22767f3898d4628411b2 Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Fri, 19 Jul 2013 16:56:28 -0400 Subject: qlcnic: Fix NULL pointer dereference in VF probe path. o Check for non-NULL set_mac_filter_count function pointer before calling it fixes the panic. This patch fixes regression introduced by patch "qlcnic: Secondary unicast MAC address support." with commit id 168e4fb54c11865668ad50eff81b5f2729e0e0f4. Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index b00cf5665eab..f4bb8f5d7453 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -1869,7 +1869,8 @@ static inline void qlcnic_free_mac_list(struct qlcnic_adapter *adapter) static inline void qlcnic_set_mac_filter_count(struct qlcnic_adapter *adapter) { - adapter->ahw->hw_ops->set_mac_filter_count(adapter); + if (adapter->ahw->hw_ops->set_mac_filter_count) + adapter->ahw->hw_ops->set_mac_filter_count(adapter); } static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, -- cgit v1.2.3-59-g8ed1b From 8dc394af2e6159d3799b1219625db47c42a1964f Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Fri, 19 Jul 2013 16:56:29 -0400 Subject: qlcnic: Fix multicast packet handling for PF and VF. o Multicast MAC was not getting programmed due to which multicast packets were being dropped by FW. This patch fixes commit 168e4fb54c11865668ad50eff81b5f2729e0e0f4 ("qlcnic: Secondary unicast MAC address support.") which introduced bug in handling multicast packets. Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 5b5d2edf125d..4ed7e73d88d3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -516,20 +516,18 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) if (netdev->flags & IFF_PROMISC) { if (!(adapter->flags & QLCNIC_PROMISC_DISABLED)) mode = VPORT_MISS_MODE_ACCEPT_ALL; - } else if (netdev->flags & IFF_ALLMULTI) { - if (netdev_mc_count(netdev) > ahw->max_mc_count) { - mode = VPORT_MISS_MODE_ACCEPT_MULTI; - } else if (!netdev_mc_empty(netdev) && - !qlcnic_sriov_vf_check(adapter)) { - netdev_for_each_mc_addr(ha, netdev) - qlcnic_nic_add_mac(adapter, ha->addr, - vlan); - } - if (mode != VPORT_MISS_MODE_ACCEPT_MULTI && - qlcnic_sriov_vf_check(adapter)) - qlcnic_vf_add_mc_list(netdev, vlan); + } else if ((netdev->flags & IFF_ALLMULTI) || + (netdev_mc_count(netdev) > ahw->max_mc_count)) { + mode = VPORT_MISS_MODE_ACCEPT_MULTI; + } else if (!netdev_mc_empty(netdev) && + !qlcnic_sriov_vf_check(adapter)) { + netdev_for_each_mc_addr(ha, netdev) + qlcnic_nic_add_mac(adapter, ha->addr, vlan); } + if (qlcnic_sriov_vf_check(adapter)) + qlcnic_vf_add_mc_list(netdev, vlan); + /* configure unicast MAC address, if there is not sufficient space * to store all the unicast addresses then enable promiscuous mode */ -- cgit v1.2.3-59-g8ed1b From cab150b5874babb0a3d558c10d28c936fdf6ac69 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 19 Jul 2013 16:56:30 -0400 Subject: qlcnic: Fix panic while setting VF's MAC address o "qlcnic_sriov" structure pointer should be accessed only when SR-IOV is enabled. Access this pointer after SR-IOV PF check. Signed-off-by: Manish Chopra Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index ee0c1d307966..b9b88f3a7b51 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -1621,13 +1621,15 @@ int qlcnic_sriov_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) { struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_sriov *sriov = adapter->ahw->sriov; - int i, num_vfs = sriov->num_vfs; + int i, num_vfs; struct qlcnic_vf_info *vf_info; u8 *curr_mac; if (!qlcnic_sriov_pf_check(adapter)) return -EOPNOTSUPP; + num_vfs = sriov->num_vfs; + if (!is_valid_ether_addr(mac) || vf >= num_vfs) return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 15d79747b57159fc1e063f1404e4f379cb5be026 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 19 Jul 2013 16:56:31 -0400 Subject: qlcnic: Fix ethtool display for 83xx adapter. o Commit b938662d88264c1a92611ca1b82fdff5a4e87121 ("qlcnic: Fix ethtool supported port status for 83xx") introduced regression for display of link status for 83xx adapter while refactoring port status display. This patch is to fix the link status display for 83xx adapter. Signed-off-by: Himanshu Madhani Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 0913c623a67e..bc483e1881a3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -3014,8 +3014,8 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter, } if (ahw->port_type == QLCNIC_XGBE) { - ecmd->supported = SUPPORTED_1000baseT_Full; - ecmd->advertising = ADVERTISED_1000baseT_Full; + ecmd->supported = SUPPORTED_10000baseT_Full; + ecmd->advertising = ADVERTISED_10000baseT_Full; } else { ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | -- cgit v1.2.3-59-g8ed1b From 744b66dde0dcdf3a0c31e1f6540d1f59d779ddd0 Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Fri, 19 Jul 2013 16:56:32 -0400 Subject: qlcnic: Fix dump template version mask Driver was using wrong mask for template version. Signed-off-by: Shahed Shaikh Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index ab8a6744d402..79e54efe07b9 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c @@ -1084,7 +1084,7 @@ flash_temp: tmpl_hdr = ahw->fw_dump.tmpl_hdr; tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; - if ((tmpl_hdr->version & 0xffffff) >= 0x20001) + if ((tmpl_hdr->version & 0xfffff) >= 0x20001) ahw->fw_dump.use_pex_dma = true; else ahw->fw_dump.use_pex_dma = false; -- cgit v1.2.3-59-g8ed1b From b662eca098184184a4d9df09835c3740401fb6a0 Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Fri, 19 Jul 2013 16:56:33 -0400 Subject: qlcnic: Fix releasing of Tx frag which was never mapped. o Driver was freeing Tx frag which was never mapped before which result into panic as kernel was unable to handle paging request. BUG: unable to handle kernel paging request at ffffc9002552a000 IP: [] qlcnic_release_tx_buffers+0x72/0x170 [qlcnic] PGD 87fc15067 PUD 47febf067 PMD 4758c5067 PTE 0 Oops: 0000 [#1] SMP crash> bt PID: 27343 TASK: ffff8802a5de8080 CPU: 27 COMMAND: "ifconfig" [ffff8802a34b3850] machine_kexec at ffffffff81035b7b [ffff8802a34b38b0] crash_kexec at ffffffff810c0db2 [ffff8802a34b3980] oops_end at ffffffff815111d0 [ffff8802a34b39b0] no_context at ffffffff81046bfb [ffff8802a34b3a00] __bad_area_nosemaphore at ffffffff81046e85 [ffff8802a34b3a50] bad_area_nosemaphore at ffffffff81046f53 [ffff8802a34b3a60] __do_page_fault at ffffffff810476b1 [ffff8802a34b3b80] do_page_fault at ffffffff8151311e [ffff8802a34b3bb0] page_fault at ffffffff815104d5 [exception RIP: qlcnic_release_tx_buffers+114] RIP: ffffffffa05ed762 RSP: ffff8802a34b3c68 RFLAGS: 00010246 RAX: ffff88087989c000 RBX: ffffc90025529ff8 RCX: 0000000000000001 RDX: 0000000000000013 RSI: 0000000000000013 RDI: 0000000000000000 RBP: ffff8802a34b3ca8 R8: 0000000000000000 R9: 0000000000000000 R10: 000000000000000c R11: 0000000000000000 R12: 0000000000000012 R13: ffffc90025529ec0 R14: ffff880761e876e0 R15: 00000000000003ff ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 [ffff8802a34b3cb0] __qlcnic_down at ffffffffa05e8b15 [qlcnic] [ffff8802a34b3d00] qlcnic_close at ffffffffa05e8b78 [qlcnic] [ffff8802a34b3d10] dev_close at ffffffff81449d81 [ffff8802a34b3d30] dev_change_flags at ffffffff814495c1 Signed-off-by: Jitendra Kalsaria Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index d28336fc65ab..a2023090e866 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c @@ -142,7 +142,7 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter) buffrag->length, PCI_DMA_TODEVICE); buffrag->dma = 0ULL; } - for (j = 0; j < cmd_buf->frag_count; j++) { + for (j = 1; j < cmd_buf->frag_count; j++) { buffrag++; if (buffrag->dma) { pci_unmap_page(adapter->pdev, buffrag->dma, -- cgit v1.2.3-59-g8ed1b From 2f0a9afaefcedfdb803e1347b0fe429cbd84d525 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 19 Jul 2013 16:56:34 -0400 Subject: qlcnic: Fix guest VLAN o Clear cached vport vlan variable(vp->vlan) in PF on PCI FLR and back-channel termination which will allow to configure guest VLAN on VF after force off/shut down the guest VM. Signed-off-by: Manish Chopra Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index b9b88f3a7b51..46aeb593fd52 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -635,10 +635,12 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans, struct qlcnic_cmd_args *cmd) { struct qlcnic_vf_info *vf = trans->vf; - struct qlcnic_adapter *adapter = vf->adapter; - int err; + struct qlcnic_vport *vp = vf->vp; + struct qlcnic_adapter *adapter; u16 func = vf->pci_func; + int err; + adapter = vf->adapter; cmd->rsp.arg[0] = trans->req_hdr->cmd_op; cmd->rsp.arg[0] |= (1 << 16); @@ -650,6 +652,8 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans, qlcnic_sriov_pf_config_vport(adapter, 0, func); } } else { + if (vp->vlan_mode == QLC_GUEST_VLAN_MODE) + vp->vlan = 0; err = qlcnic_sriov_pf_config_vport(adapter, 0, func); } @@ -1561,6 +1565,7 @@ void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov, struct qlcnic_vf_info *vf) { struct net_device *dev = vf->adapter->netdev; + struct qlcnic_vport *vp = vf->vp; if (!test_and_clear_bit(QLC_BC_VF_STATE, &vf->state)) { clear_bit(QLC_BC_VF_FLR, &vf->state); @@ -1573,6 +1578,9 @@ void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov, return; } + if (vp->vlan_mode == QLC_GUEST_VLAN_MODE) + vp->vlan = 0; + qlcnic_sriov_schedule_flr(sriov, vf, qlcnic_sriov_pf_process_flr); netdev_info(dev, "FLR received for PCI func %d\n", vf->pci_func); } -- cgit v1.2.3-59-g8ed1b From b69bbddfa136dc53ac319d58bc38b41f8aefffea Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Thu, 18 Jul 2013 16:15:11 -0300 Subject: veth: add vlan features The veth device doesn't provide the vlan features, so TSO for example is disabled and that causes performance issues when using tagged traffic. The test topology looks like this: br0 br1 / \ / \ vnet veth0.10 ----- veth1.10 vnet VM VM The netperf results with current veth driver: MIGRATED TCP STREAM TEST from 192.168.1.1 () port 0 AF_INET to 192.168.1.2 () port 0 AF_INET Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 87380 16384 16384 10.01 2210.22 Now after applying the proposed patch: MIGRATED TCP STREAM TEST from 192.168.1.1 () port 0 AF_INET to 192.168.1.2 () port 0 AF_INET Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 87380 16384 16384 10.00 13067.47 Signed-off-by: Flavio Leitner Signed-off-by: David S. Miller --- drivers/net/veth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index da866523cf20..eee1f19ef1e9 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -269,6 +269,7 @@ static void veth_setup(struct net_device *dev) dev->ethtool_ops = &veth_ethtool_ops; dev->features |= NETIF_F_LLTX; dev->features |= VETH_FEATURES; + dev->vlan_features = dev->features; dev->destructor = veth_dev_free; dev->hw_features = VETH_FEATURES; -- cgit v1.2.3-59-g8ed1b From 087d273caf4f7d3f2159256f255f1f432bc84a5b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 19 Jul 2013 08:48:05 +0300 Subject: arcnet: cleanup sizeof parameter This patch doesn't change the compiled code because ARC_HDR_SIZE is 4 and sizeof(int) is 4, but the intent was to use the header size and not the sizeof the header size. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/arcnet/arcnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index a746ba272f04..a956053608f9 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -1007,7 +1007,7 @@ static void arcnet_rx(struct net_device *dev, int bufnum) soft = &pkt.soft.rfc1201; - lp->hw.copy_from_card(dev, bufnum, 0, &pkt, sizeof(ARC_HDR_SIZE)); + lp->hw.copy_from_card(dev, bufnum, 0, &pkt, ARC_HDR_SIZE); if (pkt.hard.offset[0]) { ofs = pkt.hard.offset[0]; length = 256 - ofs; -- cgit v1.2.3-59-g8ed1b From 651e92716aaae60fc41b9652f54cb6803896e0da Mon Sep 17 00:00:00 2001 From: Michal Tesar Date: Fri, 19 Jul 2013 14:09:01 +0200 Subject: sysctl net: Keep tcp_syn_retries inside the boundary Limit the min/max value passed to the /proc/sys/net/ipv4/tcp_syn_retries. Signed-off-by: Michal Tesar Signed-off-by: David S. Miller --- net/ipv4/sysctl_net_ipv4.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index b2c123c44d69..610e324348d1 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -36,6 +36,8 @@ static int tcp_adv_win_scale_min = -31; static int tcp_adv_win_scale_max = 31; static int ip_ttl_min = 1; static int ip_ttl_max = 255; +static int tcp_syn_retries_min = 1; +static int tcp_syn_retries_max = MAX_TCP_SYNCNT; static int ip_ping_group_range_min[] = { 0, 0 }; static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; @@ -332,7 +334,9 @@ static struct ctl_table ipv4_table[] = { .data = &sysctl_tcp_syn_retries, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec + .proc_handler = proc_dointvec_minmax, + .extra1 = &tcp_syn_retries_min, + .extra2 = &tcp_syn_retries_max }, { .procname = "tcp_synack_retries", -- cgit v1.2.3-59-g8ed1b From 1faabf2aab1fdaa1ace4e8c829d1b9cf7bfec2f1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 19 Jul 2013 20:07:16 -0700 Subject: bridge: do not call setup_timer() multiple times commit 9f00b2e7cf24 ("bridge: only expire the mdb entry when query is received") added a nasty bug as an active timer can be reinitialized. setup_timer() must be done once, no matter how many time mod_timer() is called. br_multicast_new_group() is the right place to do this. Reported-by: Srivatsa S. Bhat Diagnosed-by: Thomas Gleixner Signed-off-by: Eric Dumazet Tested-by: Srivatsa S. Bhat Cc: Cong Wang Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 69af490cce44..4b99c9a27044 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -619,6 +619,9 @@ rehash: mp->br = br; mp->addr = *group; + setup_timer(&mp->timer, br_multicast_group_expired, + (unsigned long)mp); + hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); mdb->size++; @@ -1126,7 +1129,6 @@ static int br_ip4_multicast_query(struct net_bridge *br, if (!mp) goto out; - setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); mod_timer(&mp->timer, now + br->multicast_membership_interval); mp->timer_armed = true; @@ -1204,7 +1206,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, if (!mp) goto out; - setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); mod_timer(&mp->timer, now + br->multicast_membership_interval); mp->timer_armed = true; -- cgit v1.2.3-59-g8ed1b From 232fde062e0a2cc52e8e18a50cda361b4ba88f34 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sat, 13 Jul 2013 10:57:10 -0400 Subject: 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; - - /* 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; - } + struct sdio_mmc_card *card = adapter->card; + struct sdio_func *func = card->func; - 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 */ -- cgit v1.2.3-59-g8ed1b From dc2a87f519a4d8cb376ab54f22b6b98a943b51ce Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 19 Jul 2013 20:16:17 +0200 Subject: 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, -- cgit v1.2.3-59-g8ed1b From 4928bd2ef8ece262f4f314630219999a91eaa440 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 19 Jul 2013 20:16:18 +0200 Subject: 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); -- cgit v1.2.3-59-g8ed1b From 16ec75b5de6479637993ad0f7c11a49aae069f68 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 19 Jul 2013 23:31:27 -0400 Subject: 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; -- cgit v1.2.3-59-g8ed1b From 5d21608a592a9afcac8d82c6478a564e911ce70b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 20 Jul 2013 21:46:48 -0500 Subject: 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; -- cgit v1.2.3-59-g8ed1b From 28a905b51c2b3fabbb0eb53af229fc365200e398 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 22 Jul 2013 20:31:22 +0200 Subject: 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); -- cgit v1.2.3-59-g8ed1b From 23d412a2e94f55b84dbf9d5e64f381677bc90575 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 22 Jul 2013 12:46:24 +0200 Subject: 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", -- cgit v1.2.3-59-g8ed1b From f0e61604d747bf541808a1ebde6eeaef57e904e4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 19 Jul 2013 08:26:09 +0200 Subject: net: pch_gbe depends on x86 Since 4bb1667255a86360721291fe59991d033bbc2f2a (build some drivers only when compile-testing), PTP_1588_CLOCK_PCH depends on (X86 || COMPILE_TEST). But PCH_GBE selects PTP_1588_CLOCK_PCH without depending on x86. Fix this by adding the same dependency here. Signed-off-by: Jiri Slaby Reported-by: [intel's build test robot] Cc: "David S. Miller" Cc: Ben Hutchings Cc: netdev@vger.kernel.org Cc: Greg Kroah-Hartman Cc: kbuild-all@01.org Signed-off-by: David S. Miller --- drivers/net/ethernet/oki-semi/pch_gbe/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig index cb22341a14a8..a588ffde9700 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig +++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig @@ -4,7 +4,7 @@ config PCH_GBE tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE" - depends on PCI + depends on PCI && (X86 || COMPILE_TEST) select MII select PTP_1588_CLOCK_PCH ---help--- -- cgit v1.2.3-59-g8ed1b From 7aa0076c497d6f0d5d957b431d0d80e1e9780274 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 23 Jul 2013 00:17:25 +0100 Subject: sfc: Enable RX scatter for flows steered by RFS Received packets are only scattered if this is enabled in both the matching filter and the receiving queue. This was not being done for filters inserted for RFS, so any packet requiring more than a single descriptor was dropped. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/filter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c index b74a60ab9ac7..2a469b27a506 100644 --- a/drivers/net/ethernet/sfc/filter.c +++ b/drivers/net/ethernet/sfc/filter.c @@ -1209,7 +1209,9 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4); ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl); - efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index); + efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, + efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0, + rxq_index); rc = efx_filter_set_ipv4_full(&spec, ip->protocol, ip->daddr, ports[1], ip->saddr, ports[0]); if (rc) -- cgit v1.2.3-59-g8ed1b From f8c0aca9fda7856a8a8d61d523ba3187affbd714 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 20 Jul 2013 16:20:36 -0300 Subject: fec: Add MODULE_ALIAS Add MODULE_ALIAS, so that auto module loading can work. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index d3ad5ea711d3..f0f0e96453a0 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2279,4 +2279,5 @@ static struct platform_driver fec_driver = { module_platform_driver(fec_driver); +MODULE_ALIAS("platform:"DRIVER_NAME); MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 4ea72445bddd2ca09fc719065fc3c5a8bfc8ca10 Mon Sep 17 00:00:00 2001 From: Lekensteyn Date: Mon, 22 Jul 2013 09:53:30 +0200 Subject: r8169: fix lockdep warning when removing interface The work queue is initialised in rtl_open (when the interface goes up), but canceled in rtl_remove_one (when the PCI device gets removed). If the network interface is not brought up, then the work queue struct is not initialised. When the device is removed, the attempt to cancel the uninitialised work queue causes a lockdep warning. This patch fixes the issue by moving cancel_work_sync to rtl_close (to match rtl_open). (Note that rtl_close is also called via unregister_netdev in rtl_remove_one.) Signed-off-by: Peter Wu Acked-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 4106a743ca74..880015cae6a3 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -6468,6 +6468,8 @@ static int rtl8169_close(struct net_device *dev) rtl8169_down(dev); rtl_unlock_work(tp); + cancel_work_sync(&tp->wk.work); + free_irq(pdev->irq, dev); dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, @@ -6793,8 +6795,6 @@ static void rtl_remove_one(struct pci_dev *pdev) rtl8168_driver_stop(tp); } - cancel_work_sync(&tp->wk.work); - netif_napi_del(&tp->napi); unregister_netdev(dev); -- cgit v1.2.3-59-g8ed1b From 64d2c22a4cdd3ce752ca700964a6120049d78aed Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 22 Jul 2013 11:02:01 +0300 Subject: mlx5: use after free in mlx5_cmd_comp_handler() We can't dereference "ent" after passing it to free_cmd(). Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 205753a04cfc..40374063c01e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1113,7 +1113,13 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector) for (i = 0; i < (1 << cmd->log_sz); i++) { if (test_bit(i, &vector)) { + struct semaphore *sem; + ent = cmd->ent_arr[i]; + if (ent->page_queue) + sem = &cmd->pages_sem; + else + sem = &cmd->sem; ktime_get_ts(&ent->ts2); memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out)); dump_command(dev, ent, 0); @@ -1136,10 +1142,7 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector) } else { complete(&ent->done); } - if (ent->page_queue) - up(&cmd->pages_sem); - else - up(&cmd->sem); + up(sem); } } } -- cgit v1.2.3-59-g8ed1b From f585a991e1d1612265f0d4e812f77e40dd54975b Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Mon, 22 Jul 2013 12:01:58 -0700 Subject: fib_trie: potential out of bounds access in trie_show_stats() With the <= max condition in the for loop, it will be always go 1 element further than needed. If the condition for the while loop is never met, then max is MAX_STAT_DEPTH, and for loop will walk off the end of nodesizes[]. Signed-off-by: Jerry Snitselaar Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv4/fib_trie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 49616fed9340..108a1e9c9eac 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -2133,7 +2133,7 @@ static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat) max--; pointers = 0; - for (i = 1; i <= max; i++) + for (i = 1; i < max; i++) if (stat->nodesizes[i] != 0) { seq_printf(seq, " %u: %u", i, stat->nodesizes[i]); pointers += (1<nodesizes[i]; -- cgit v1.2.3-59-g8ed1b From 905a6f96a1b18e490a75f810d733ced93c39b0e5 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 22 Jul 2013 23:45:53 +0200 Subject: ipv6: take rtnl_lock and mark mrt6 table as freed on namespace cleanup Otherwise we end up dereferencing the already freed net->ipv6.mrt pointer which leads to a panic (from Srivatsa S. Bhat): BUG: unable to handle kernel paging request at ffff882018552020 IP: [] ip6mr_sk_done+0x32/0xb0 [ipv6] PGD 290a067 PUD 207ffe0067 PMD 207ff1d067 PTE 8000002018552060 Oops: 0000 [#1] SMP DEBUG_PAGEALLOC Modules linked in: ebtable_nat ebtables nfs fscache nf_conntrack_ipv4 nf_defrag_ipv4 ipt_REJECT xt_CHECKSUM iptable_mangle iptable_filter ip_tables nfsd lockd nfs_acl exportfs auth_rpcgss autofs4 sunrpc 8021q garp bridge stp llc ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter +ip6_tables ipv6 vfat fat vhost_net macvtap macvlan vhost tun kvm_intel kvm uinput iTCO_wdt iTCO_vendor_support cdc_ether usbnet mii microcode i2c_i801 i2c_core lpc_ich mfd_core shpchp ioatdma dca mlx4_core be2net wmi acpi_cpufreq mperf ext4 jbd2 mbcache dm_mirror dm_region_hash dm_log dm_mod CPU: 0 PID: 7 Comm: kworker/u33:0 Not tainted 3.11.0-rc1-ea45e-a #4 Hardware name: IBM -[8737R2A]-/00Y2738, BIOS -[B2E120RUS-1.20]- 11/30/2012 Workqueue: netns cleanup_net task: ffff8810393641c0 ti: ffff881039366000 task.ti: ffff881039366000 RIP: 0010:[] [] ip6mr_sk_done+0x32/0xb0 [ipv6] RSP: 0018:ffff881039367bd8 EFLAGS: 00010286 RAX: ffff881039367fd8 RBX: ffff882018552000 RCX: dead000000200200 RDX: 0000000000000000 RSI: ffff881039367b68 RDI: ffff881039367b68 RBP: ffff881039367bf8 R08: ffff881039367b68 R09: 2222222222222222 R10: 2222222222222222 R11: 2222222222222222 R12: ffff882015a7a040 R13: ffff882014eb89c0 R14: ffff8820289e2800 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff88103fc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffff882018552020 CR3: 0000000001c0b000 CR4: 00000000000407f0 Stack: ffff881039367c18 ffff882014eb89c0 ffff882015e28c00 0000000000000000 ffff881039367c18 ffffffffa034d9d1 ffff8820289e2800 ffff882014eb89c0 ffff881039367c58 ffffffff815bdecb ffffffff815bddf2 ffff882014eb89c0 Call Trace: [] rawv6_close+0x21/0x40 [ipv6] [] inet_release+0xfb/0x220 [] ? inet_release+0x22/0x220 [] inet6_release+0x3f/0x50 [ipv6] [] sock_release+0x29/0xa0 [] sk_release_kernel+0x30/0x70 [] icmpv6_sk_exit+0x3b/0x80 [ipv6] [] ops_exit_list+0x39/0x60 [] cleanup_net+0xfb/0x1a0 [] process_one_work+0x1da/0x610 [] ? process_one_work+0x169/0x610 [] worker_thread+0x120/0x3a0 [] ? process_one_work+0x610/0x610 [] kthread+0xee/0x100 [] ? __init_kthread_worker+0x70/0x70 [] ret_from_fork+0x7c/0xb0 [] ? __init_kthread_worker+0x70/0x70 Code: 20 48 89 5d e8 4c 89 65 f0 4c 89 6d f8 66 66 66 66 90 4c 8b 67 30 49 89 fd e8 db 3c 1e e1 49 8b 9c 24 90 08 00 00 48 85 db 74 06 <4c> 39 6b 20 74 20 bb f3 ff ff ff e8 8e 3c 1e e1 89 d8 4c 8b 65 RIP [] ip6mr_sk_done+0x32/0xb0 [ipv6] RSP CR2: ffff882018552020 Reported-by: Srivatsa S. Bhat Tested-by: Srivatsa S. Bhat Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/ip6mr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 583e8d435f9a..03986d31fa41 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -259,10 +259,12 @@ static void __net_exit ip6mr_rules_exit(struct net *net) { struct mr6_table *mrt, *next; + rtnl_lock(); list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) { list_del(&mrt->list); ip6mr_free_table(mrt); } + rtnl_unlock(); fib_rules_unregister(net->ipv6.mr6_rules_ops); } #else @@ -289,7 +291,10 @@ static int __net_init ip6mr_rules_init(struct net *net) static void __net_exit ip6mr_rules_exit(struct net *net) { + rtnl_lock(); ip6mr_free_table(net->ipv6.mrt6); + net->ipv6.mrt6 = NULL; + rtnl_unlock(); } #endif -- cgit v1.2.3-59-g8ed1b From 2bf420a7686e0fdd2fbf16d75e729b306744db0d Mon Sep 17 00:00:00 2001 From: Emilio López Date: Mon, 22 Jul 2013 22:09:18 -0300 Subject: net: sun4i: fix timeout check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current timeout check is comparing two constant values, so it won't ever detect a timeout. This patch reworks the affected code a bit so it has a chance at detecting timeouts correctly. Signed-off-by: Emilio López Acked-by: Maxime Ripard Signed-off-by: David S. Miller --- drivers/net/phy/mdio-sun4i.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c index 61d3f4ebf52e..7f25e49ae37f 100644 --- a/drivers/net/phy/mdio-sun4i.c +++ b/drivers/net/phy/mdio-sun4i.c @@ -40,7 +40,7 @@ struct sun4i_mdio_data { static int sun4i_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct sun4i_mdio_data *data = bus->priv; - unsigned long start_jiffies; + unsigned long timeout_jiffies; int value; /* issue the phy address and reg */ @@ -49,10 +49,9 @@ static int sun4i_mdio_read(struct mii_bus *bus, int mii_id, int regnum) writel(0x1, data->membase + EMAC_MAC_MCMD_REG); /* Wait read complete */ - start_jiffies = jiffies; + timeout_jiffies = jiffies + MDIO_TIMEOUT; while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) { - if (time_after(start_jiffies, - start_jiffies + MDIO_TIMEOUT)) + if (time_is_before_jiffies(timeout_jiffies)) return -ETIMEDOUT; msleep(1); } @@ -69,7 +68,7 @@ static int sun4i_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { struct sun4i_mdio_data *data = bus->priv; - unsigned long start_jiffies; + unsigned long timeout_jiffies; /* issue the phy address and reg */ writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG); @@ -77,10 +76,9 @@ static int sun4i_mdio_write(struct mii_bus *bus, int mii_id, int regnum, writel(0x1, data->membase + EMAC_MAC_MCMD_REG); /* Wait read complete */ - start_jiffies = jiffies; + timeout_jiffies = jiffies + MDIO_TIMEOUT; while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) { - if (time_after(start_jiffies, - start_jiffies + MDIO_TIMEOUT)) + if (time_is_before_jiffies(timeout_jiffies)) return -ETIMEDOUT; msleep(1); } -- cgit v1.2.3-59-g8ed1b From deceb4c062a8dd63fe554c3be2b4bf9151a5cedf Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 23 Jul 2013 20:22:39 +0100 Subject: net: fix comment above build_skb() build_skb() specifies that the data parameter must come from a kmalloc'd area, this is only true if frag_size equals 0, because then build_skb() will use kzsize(data) to figure out the actual data size. Update the comment to reflect that special condition. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- net/core/skbuff.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 20e02d2605ec..3df4d4ccf440 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -309,7 +309,8 @@ EXPORT_SYMBOL(__alloc_skb); * @frag_size: size of fragment, or 0 if head was kmalloced * * Allocate a new &sk_buff. Caller provides space holding head and - * skb_shared_info. @data must have been allocated by kmalloc() + * skb_shared_info. @data must have been allocated by kmalloc() only if + * @frag_size is 0, otherwise data should come from the page allocator. * The return is the new skb buffer. * On a failure the return is %NULL, and @data is not freed. * Notes : -- cgit v1.2.3-59-g8ed1b From 20f0170377264e8449b6987041f0bcc4d746d3ed Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 23 Jul 2013 17:15:54 -0700 Subject: usbnet: do not pretend to support SG/TSO usbnet doesn't support yet SG, so drivers should not advertise SG or TSO capabilities, as they allow TCP stack to build large TSO packets that need to be linearized and might use order-5 pages. This adds an extra copy overhead and possible allocation failures. Current code ignore skb_linearize() return code so crashes are even possible. Best is to not pretend SG/TSO is supported, and add this again when/if usbnet really supports SG for devices who could get a performance gain. Based on a prior patch from Freddy Xin Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/usb/ax88179_178a.c | 9 ++++----- drivers/net/usb/smsc75xx.c | 12 +++--------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 1e3c302d94fe..2bc87e3a8141 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1029,10 +1029,10 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.supports_gmii = 1; dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; + NETIF_F_RXCSUM; dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; + NETIF_F_RXCSUM; /* Enable checksum offload */ *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | @@ -1173,7 +1173,6 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) if (((skb->len + 8) % frame_size) == 0) tx_hdr2 |= 0x80008000; /* Enable padding */ - skb_linearize(skb); headroom = skb_headroom(skb); tailroom = skb_tailroom(skb); @@ -1317,10 +1316,10 @@ static int ax88179_reset(struct usbnet *dev) 1, 1, tmp); dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; + NETIF_F_RXCSUM; dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; + NETIF_F_RXCSUM; /* Enable checksum offload */ *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 75409748c774..66ebbacf066f 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -45,7 +45,6 @@ #define EEPROM_MAC_OFFSET (0x01) #define DEFAULT_TX_CSUM_ENABLE (true) #define DEFAULT_RX_CSUM_ENABLE (true) -#define DEFAULT_TSO_ENABLE (true) #define SMSC75XX_INTERNAL_PHY_ID (1) #define SMSC75XX_TX_OVERHEAD (8) #define MAX_RX_FIFO_SIZE (20 * 1024) @@ -1410,17 +1409,14 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write); - if (DEFAULT_TX_CSUM_ENABLE) { + if (DEFAULT_TX_CSUM_ENABLE) dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - if (DEFAULT_TSO_ENABLE) - dev->net->features |= NETIF_F_SG | - NETIF_F_TSO | NETIF_F_TSO6; - } + if (DEFAULT_RX_CSUM_ENABLE) dev->net->features |= NETIF_F_RXCSUM; dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXCSUM; + NETIF_F_RXCSUM; ret = smsc75xx_wait_ready(dev, 0); if (ret < 0) { @@ -2200,8 +2196,6 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev, { u32 tx_cmd_a, tx_cmd_b; - skb_linearize(skb); - if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) { struct sk_buff *skb2 = skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags); -- cgit v1.2.3-59-g8ed1b From 05bc250fe623e61e132dc1f771fca0a842ea60b6 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 24 Jul 2013 09:11:37 +0200 Subject: drivers: net: allwinner: Fix Kconfig indentation Signed-off-by: Maxime Ripard Signed-off-by: David S. Miller --- drivers/net/ethernet/allwinner/Kconfig | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/allwinner/Kconfig b/drivers/net/ethernet/allwinner/Kconfig index 53ad213e865b..cf7aa24d559c 100644 --- a/drivers/net/ethernet/allwinner/Kconfig +++ b/drivers/net/ethernet/allwinner/Kconfig @@ -3,19 +3,20 @@ # config NET_VENDOR_ALLWINNER - bool "Allwinner devices" - default y - depends on ARCH_SUNXI - ---help--- - If you have a network (Ethernet) card belonging to this - class, say Y and read the Ethernet-HOWTO, available from - . + bool "Allwinner devices" + default y - Note that the answer to this question doesn't directly - affect the kernel: saying N will just cause the configurator - to skip all the questions about Allwinner cards. If you say Y, - you will be asked for your specific card in the following - questions. + depends on ARCH_SUNXI + ---help--- + If you have a network (Ethernet) card belonging to this + class, say Y and read the Ethernet-HOWTO, available from + . + + Note that the answer to this question doesn't directly + affect the kernel: saying N will just cause the configurator + to skip all the questions about Allwinner cards. If you say Y, + you will be asked for your specific card in the following + questions. if NET_VENDOR_ALLWINNER -- cgit v1.2.3-59-g8ed1b From 111cc5da2a95568ca20a5f86f43ae328c069e455 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 24 Jul 2013 09:12:08 +0200 Subject: drivers: net: sun4i-emac: select MDIO_SUN4I The EMAC driver can't work without its associated PHY driver. Reflect this in the Kconfig options by selecting it. Signed-off-by: Maxime Ripard Signed-off-by: David S. Miller --- drivers/net/ethernet/allwinner/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/allwinner/Kconfig b/drivers/net/ethernet/allwinner/Kconfig index cf7aa24d559c..d8d95d4cd45a 100644 --- a/drivers/net/ethernet/allwinner/Kconfig +++ b/drivers/net/ethernet/allwinner/Kconfig @@ -27,6 +27,7 @@ config SUN4I_EMAC select CRC32 select MII select PHYLIB + select MDIO_SUN4I ---help--- Support for Allwinner A10 EMAC ethernet driver. -- cgit v1.2.3-59-g8ed1b From 555445cd11803c6bc93b2be31968f3949ef7708b Mon Sep 17 00:00:00 2001 From: Francesco Fusco Date: Wed, 24 Jul 2013 10:39:06 +0200 Subject: neigh: prevent overflowing params in /proc/sys/net/ipv4/neigh/ Without this patch, the fields app_solicit, gc_thresh1, gc_thresh2, gc_thresh3, proxy_qlen, ucast_solicit, mcast_solicit could have assumed negative values when setting large numbers. Signed-off-by: Francesco Fusco Signed-off-by: David S. Miller --- net/core/neighbour.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b7de821f98df..9232c68941ab 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2767,6 +2767,7 @@ EXPORT_SYMBOL(neigh_app_ns); #ifdef CONFIG_SYSCTL static int zero; +static int int_max = INT_MAX; static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN); static int proc_unres_qlen(struct ctl_table *ctl, int write, @@ -2819,19 +2820,25 @@ static struct neigh_sysctl_table { .procname = "mcast_solicit", .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .extra1 = &zero, + .extra2 = &int_max, + .proc_handler = proc_dointvec_minmax, }, [NEIGH_VAR_UCAST_PROBE] = { .procname = "ucast_solicit", .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .extra1 = &zero, + .extra2 = &int_max, + .proc_handler = proc_dointvec_minmax, }, [NEIGH_VAR_APP_PROBE] = { .procname = "app_solicit", .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .extra1 = &zero, + .extra2 = &int_max, + .proc_handler = proc_dointvec_minmax, }, [NEIGH_VAR_RETRANS_TIME] = { .procname = "retrans_time", @@ -2874,7 +2881,9 @@ static struct neigh_sysctl_table { .procname = "proxy_qlen", .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .extra1 = &zero, + .extra2 = &int_max, + .proc_handler = proc_dointvec_minmax, }, [NEIGH_VAR_ANYCAST_DELAY] = { .procname = "anycast_delay", @@ -2916,19 +2925,25 @@ static struct neigh_sysctl_table { .procname = "gc_thresh1", .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .extra1 = &zero, + .extra2 = &int_max, + .proc_handler = proc_dointvec_minmax, }, [NEIGH_VAR_GC_THRESH2] = { .procname = "gc_thresh2", .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .extra1 = &zero, + .extra2 = &int_max, + .proc_handler = proc_dointvec_minmax, }, [NEIGH_VAR_GC_THRESH3] = { .procname = "gc_thresh3", .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .extra1 = &zero, + .extra2 = &int_max, + .proc_handler = proc_dointvec_minmax, }, {}, }, -- cgit v1.2.3-59-g8ed1b From d738ce8fdc05ebf5b1475f8ae26d908c8c50970b Mon Sep 17 00:00:00 2001 From: Francesco Fusco Date: Wed, 24 Jul 2013 10:39:07 +0200 Subject: sysctl: range checking in do_proc_dointvec_ms_jiffies_conv When (integer) sysctl values are expressed in ms and have to be represented internally as jiffies. The msecs_to_jiffies function returns an unsigned long, which gets assigned to the integer. This patch prevents the value to be assigned if bigger than INT_MAX, done in a similar way as in cba9f3 ("Range checking in do_proc_dointvec_(userhz_)jiffies_conv"). Signed-off-by: Francesco Fusco CC: Andrew Morton CC: linux-kernel@vger.kernel.org Signed-off-by: David S. Miller --- kernel/sysctl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index ac09d98490aa..07f6fc468e17 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2346,7 +2346,11 @@ static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp, int write, void *data) { if (write) { - *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp); + unsigned long jif = msecs_to_jiffies(*negp ? -*lvalp : *lvalp); + + if (jif > INT_MAX) + return 1; + *valp = (int)jif; } else { int val = *valp; unsigned long lval; -- cgit v1.2.3-59-g8ed1b From d8af4dfd84329015e18ea3d83a84c46e92f21020 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 24 Jul 2013 17:25:08 +0800 Subject: net/tg3: Fix kernel crash While EEH error happens, we might not have network device instance (struct net_device) yet. So we can't access the instance safely and check its link state, which causes kernel crash. The patch fixes it. EEH: Frozen PE#2 on PHB#3 detected EEH: This PCI device has failed 1 times in the last hour EEH: Notify device drivers to shutdown (NULL net_device): PCI I/O error detected Unable to handle kernel paging request for data at address 0x00000048 Faulting instruction address: 0xd00000001c9387a8 Oops: Kernel access of bad area, sig: 11 [#1] SMP NR_CPUS=1024 NUMA PowerNV : NIP [d00000001c9387a8] .tg3_io_error_detected+0x78/0x2a0 [tg3] LR [d00000001c9387a4] .tg3_io_error_detected+0x74/0x2a0 [tg3] Call Trace: [c000003f93a0f960] [d00000001c9387a4] .tg3_io_error_detected+0x74/0x2a0 [tg3] [c000003f93a0fa30] [c00000000003844c] .eeh_report_error+0xac/0x120 [c000003f93a0fac0] [c0000000000371bc] .eeh_pe_dev_traverse+0x8c/0x150 [c000003f93a0fb60] [c000000000038858] .eeh_handle_normal_event+0x128/0x3d0 [c000003f93a0fbf0] [c000000000038db8] .eeh_handle_event+0x2b8/0x2c0 [c000003f93a0fc90] [c000000000038e80] .eeh_event_handler+0xc0/0x170 [c000003f93a0fd30] [c0000000000cc000] .kthread+0xf0/0x100 [c000003f93a0fe30] [c00000000000a0dc] .ret_from_kernel_thread+0x5c/0x80 Reported-by: Wei Yang Signed-off-by: Gavin Shan Acked-by: Nithin Nayak Sujir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index d964f302ac94..aee1b9a79b30 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -17773,7 +17773,8 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, rtnl_lock(); - if (!netif_running(netdev)) + /* We probably don't have netdev yet */ + if (!netdev || !netif_running(netdev)) goto done; tg3_phy_stop(tp); -- cgit v1.2.3-59-g8ed1b From c80dc13dda73db67e156b161d06c78f266b36ea6 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 24 Jul 2013 17:25:09 +0800 Subject: net/tg3: Fix warning from pci_disable_device() The patch fixes following warning. The PCI device might have been disabled somewhere else when we have EEH errors during early stage. Device tg3 disabling already-disabled device WARNING: at drivers/pci/pci.c:1403 : NIP [c00000000044fd5c] .pci_disable_device+0xcc/0xe0 LR [c00000000044fd58] .pci_disable_device+0xc8/0xe0 Call Trace: [c000003f80bc7370] [c00000000044fd58] .pci_disable_device+0xc8/0xe0 [c000003f80bc73f0] [d00000001cfe8fc0] .tg3_init_one+0x2f0/0x19f0 [tg3] [c000003f80bc74d0] [c0000000004534e8] .local_pci_probe+0x68/0xb0 [c000003f80bc7560] [c0000000004537c8] .pci_device_probe+0x198/0x1a0 [c000003f80bc7610] [c0000000004f9e98] .driver_probe_device+0xd8/0x450 [c000003f80bc76a0] [c0000000004fa3bc] .__driver_attach+0x10c/0x110 [c000003f80bc7730] [c0000000004f6e94] .bus_for_each_dev+0x94/0x100 [c000003f80bc77d0] [c0000000004f9634] .driver_attach+0x34/0x50 [c000003f80bc7850] [c0000000004f8f98] .bus_add_driver+0x288/0x380 [c000003f80bc78f0] [c0000000004fae2c] .driver_register+0x9c/0x200 [c000003f80bc7980] [c000000000453214] .__pci_register_driver+0x64/0x90 [c000003f80bc7a10] [d00000001cff7a60] .tg3_driver_init+0x2c/0x40 [tg3] [c000003f80bc7a80] [c00000000000b424] .do_one_initcall+0x144/0x1f0 [c000003f80bc7b70] [c0000000001244a0] .load_module+0x1f30/0x2700 [c000003f80bc7d40] [c000000000124e80] .SyS_finit_module+0xc0/0x110 [c000003f80bc7e30] [c000000000009dd4] syscall_exit+0x0/0x98 Reported-by: Wei Yang Signed-off-by: Gavin Shan Acked-by: Nithin Nayak Sujir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index aee1b9a79b30..ddebc7a5dda0 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -17625,7 +17625,8 @@ err_out_free_res: pci_release_regions(pdev); err_out_disable_pdev: - pci_disable_device(pdev); + if (pci_is_enabled(pdev)) + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); return err; } -- cgit v1.2.3-59-g8ed1b From ebe7fdbaf3e90ea22feade6c9f5e50f42b23b6d8 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 26 Jul 2013 12:47:14 -0400 Subject: atl1c: Fix misuse of netdev_alloc_skb in refilling rx ring atl1c uses netdev_alloc_skb to refill its rx dma ring, but that call makes no guarantees about the suitability of the memory for use in DMA. As a result we've gotten reports of atl1c drivers occasionally hanging and needing to be reset: https://bugzilla.kernel.org/show_bug.cgi?id=54021 Fix this by modifying the call to use the internal version __netdev_alloc_skb, where you can set the gfp_mask explicitly to include GFP_DMA. Tested by two reporters in the above bug, who have the hardware to validate it. Both report immediate cessation of the problem with this patch Signed-off-by: Neil Horman CC: Jay Cliburn CC: "David S. Miller" CC: stable@vger.kernel.org Tested-by: Luis Henriques Tested-by: Vincent Alquier Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 786a87483298..d5e38d1ea3a2 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1660,7 +1660,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) while (next_info->flags & ATL1C_BUFFER_FREE) { rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); - skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len); + skb = __netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len, GFP_ATOMIC|GFP_DMA); if (unlikely(!skb)) { if (netif_msg_rx_err(adapter)) dev_warn(&pdev->dev, "alloc rx buffer failed\n"); -- cgit v1.2.3-59-g8ed1b From fafb6ebe384e62e68519ae8f5ae9b2cb578d7dde Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 27 Jul 2013 20:00:44 -0700 Subject: Revert "atl1c: Fix misuse of netdev_alloc_skb in refilling rx ring" This reverts commit ebe7fdbaf3e90ea22feade6c9f5e50f42b23b6d8. This change is not correct. GFP_DMA is not necessary for this device. There is some other problem causing this bug. Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index d5e38d1ea3a2..786a87483298 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1660,7 +1660,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) while (next_info->flags & ATL1C_BUFFER_FREE) { rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); - skb = __netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len, GFP_ATOMIC|GFP_DMA); + skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len); if (unlikely(!skb)) { if (netif_msg_rx_err(adapter)) dev_warn(&pdev->dev, "alloc rx buffer failed\n"); -- cgit v1.2.3-59-g8ed1b From c70a31750679ca10a46dd0cc2d57ed7b54dbe7c2 Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Fri, 26 Jul 2013 16:24:00 -0400 Subject: qlcnic: Fix initialization of work function. Work function needs to be initialized before we participate in inter device communication (IDC). Signed-off-by: Jitendra Kalsaria Signed-off-by: Himanshu Madhani Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index f41dfab1e9a3..51ab4b56fc91 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -2123,6 +2123,8 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); qlcnic_83xx_clear_function_resources(adapter); + INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); + /* register for NIC IDC AEN Events */ qlcnic_83xx_register_nic_idc_func(adapter, 1); @@ -2140,8 +2142,6 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) if (adapter->nic_ops->init_driver(adapter)) return -EIO; - INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); - /* Periodically monitor device status */ qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work); -- cgit v1.2.3-59-g8ed1b From 6226204bcf20d2bb8e47e996c1688186355c1db4 Mon Sep 17 00:00:00 2001 From: Pratik Pujar Date: Fri, 26 Jul 2013 16:24:01 -0400 Subject: qlcnic: Fix operation type and command type. Operation type and command type is not set correct in back channel response. Signed-off-by: Pratik Pujar Signed-off-by: Himanshu Madhani Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 2 ++ drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 62380ce89905..56e85f98117f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -762,6 +762,7 @@ static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *mbx, u32 type) memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); mbx->req.arg[0] = (type | (mbx->req.num << 16) | (3 << 29)); + mbx->rsp.arg[0] = (type & 0xffff) | mbx->rsp.num << 16; return 0; } } @@ -813,6 +814,7 @@ static int qlcnic_sriov_prepare_bc_hdr(struct qlcnic_bc_trans *trans, cmd->req.num = trans->req_pay_size / 4; cmd->rsp.num = trans->rsp_pay_size / 4; hdr = trans->rsp_hdr; + cmd->op_type = trans->req_hdr->op_type; } trans->trans_id = seq; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index 46aeb593fd52..9bdd51e6b44c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -641,8 +641,6 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans, int err; adapter = vf->adapter; - cmd->rsp.arg[0] = trans->req_hdr->cmd_op; - cmd->rsp.arg[0] |= (1 << 16); if (trans->req_hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) { err = qlcnic_sriov_pf_config_vport(adapter, 1, func); @@ -1187,7 +1185,7 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans, u8 cmd_op, mode = vp->vlan_mode; cmd_op = trans->req_hdr->cmd_op; - cmd->rsp.arg[0] = (cmd_op & 0xffff) | 14 << 16 | 1 << 25; + cmd->rsp.arg[0] |= 1 << 25; switch (mode) { case QLC_GUEST_VLAN_MODE: -- cgit v1.2.3-59-g8ed1b From 7cfc1cebdaee367c30e8944dd5adf2f6bbae8123 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 26 Jul 2013 16:24:02 -0400 Subject: qlcnic: Fix setting Guest VLAN o When configuring guest VLAN after PVID configuration, VF was loading with previously configured PVID. Clear the PVID which was previously configured before configuring guest VLAN. o Display guest VLAN when it is configured Signed-off-by: Manish Chopra Signed-off-by: Himanshu Madhani Signed-off-by: David S. Miller --- .../net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index 9bdd51e6b44c..eb49cd65378c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -1749,6 +1749,7 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf, switch (vlan) { case 4095: + vp->vlan = 0; vp->vlan_mode = QLC_GUEST_VLAN_MODE; break; case 0: @@ -1767,6 +1768,29 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf, return 0; } +static inline __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, + struct qlcnic_vport *vp, int vf) +{ + __u32 vlan = 0; + + switch (vp->vlan_mode) { + case QLC_PVID_MODE: + vlan = vp->vlan; + break; + case QLC_GUEST_VLAN_MODE: + vlan = MAX_VLAN_ID; + break; + case QLC_NO_VLAN_MODE: + vlan = 0; + break; + default: + netdev_info(adapter->netdev, "Invalid VLAN mode = %d for VF %d\n", + vp->vlan_mode, vf); + } + + return vlan; +} + int qlcnic_sriov_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi) { @@ -1782,7 +1806,7 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev, vp = sriov->vf_info[vf].vp; memcpy(&ivi->mac, vp->mac, ETH_ALEN); - ivi->vlan = vp->vlan; + ivi->vlan = qlcnic_sriov_get_vf_vlan(adapter, vp, vf); ivi->qos = vp->qos; ivi->spoofchk = vp->spoofchk; if (vp->max_tx_bw == MAX_BW) -- cgit v1.2.3-59-g8ed1b From c2534384233647a8702eca291199b94ffedc12d3 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 26 Jul 2013 16:24:03 -0400 Subject: qlcnic: Fix diagnostic interrupt test for 83xx adapters. o Initialize proper interrupt handler for 83xx. Signed-off-by: Manish Chopra Signed-off-by: Himanshu Madhani Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 41635f2b9399..cc78d3924c6a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -1383,6 +1383,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { if (qlcnic_82xx_check(adapter)) handler = qlcnic_tmp_intr; + else + handler = qlcnic_83xx_tmp_intr; if (!QLCNIC_IS_MSI_FAMILY(adapter)) flags |= IRQF_SHARED; -- cgit v1.2.3-59-g8ed1b From 031916568a1aa2ef1809f86d26f0bcfa215ff5c0 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 25 Jul 2013 14:05:53 +0800 Subject: net: fec: workaround stop tx during errata ERR006358 If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously detected as not set during a prior frame transmission, then the ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in frames not being transmitted until there is a 0-to-1 transition on ENET_TDAR[TDAR]. Workarounds: code can use the transmit frame interrupt flag (ENET_EIR[TXF]) as a method to detect whether the ENET has completed transmission and the ENET_TDAR[TDAR] has been cleared. If ENET_TDAR[TDAR] is detected as cleared when packets are queued and waiting for transmit, then a write to the TDAR bit will restart TxBD processing. This case main happen when loading is light. A ethernet package may not send out utile next package put into tx queue. How to test: while [ true ] do ping -s 10000 -w 4 ping -s 6000 -w 2 ping -s 4000 -w 2 ping -s 10000 -w 2 done You will see below result in overnight test. 6008 bytes from 10.192.242.116: seq=1 ttl=128 time=0.722 ms 4008 bytes from 10.192.242.116: seq=0 ttl=128 time=1001.008 ms 4008 bytes from 10.192.242.116: seq=1 ttl=128 time=1.010 ms 10008 bytes from 10.192.242.116: seq=0 ttl=128 time=0.896 ms After apply this patch, >1000ms delay disappear. Signed-off-by: Frank Li Acked-by: Fugang Duan Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 1 + drivers/net/ethernet/freescale/fec_main.c | 32 +++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 2b0a0ea4f8e7..ae236009f1a8 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -259,6 +259,7 @@ struct bufdesc_ex { struct fec_enet_delayed_work { struct delayed_work delay_work; bool timeout; + bool trig_tx; }; /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index f0f0e96453a0..0dda45481d16 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -93,6 +93,20 @@ static void set_multicast_list(struct net_device *ndev); #define FEC_QUIRK_HAS_CSUM (1 << 5) /* Controller has hardware vlan support */ #define FEC_QUIRK_HAS_VLAN (1 << 6) +/* ENET IP errata ERR006358 + * + * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously + * detected as not set during a prior frame transmission, then the + * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs + * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in + * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously + * detected as not set during a prior frame transmission, then the + * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs + * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in + * frames not being transmitted until there is a 0-to-1 transition on + * ENET_TDAR[TDAR]. + */ +#define FEC_QUIRK_ERR006358 (1 << 7) static struct platform_device_id fec_devtype[] = { { @@ -112,7 +126,7 @@ static struct platform_device_id fec_devtype[] = { .name = "imx6q-fec", .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | - FEC_QUIRK_HAS_VLAN, + FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358, }, { .name = "mvf600-fec", .driver_data = FEC_QUIRK_ENET_MAC, @@ -275,7 +289,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); - struct bufdesc *bdp; + struct bufdesc *bdp, *bdp_pre; void *bufaddr; unsigned short status; unsigned int index; @@ -370,6 +384,15 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) ebdp->cbd_esc |= BD_ENET_TX_PINS; } } + + bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); + if ((id_entry->driver_data & FEC_QUIRK_ERR006358) && + !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) { + fep->delay_work.trig_tx = true; + schedule_delayed_work(&(fep->delay_work.delay_work), + msecs_to_jiffies(1)); + } + /* If this was the last BD in the ring, start at the beginning again. */ if (status & BD_ENET_TX_WRAP) bdp = fep->tx_bd_base; @@ -689,6 +712,11 @@ static void fec_enet_work(struct work_struct *work) fec_restart(fep->netdev, fep->full_duplex); netif_wake_queue(fep->netdev); } + + if (fep->delay_work.trig_tx) { + fep->delay_work.trig_tx = false; + writel(0, fep->hwp + FEC_X_DES_ACTIVE); + } } static void -- cgit v1.2.3-59-g8ed1b From c74f2b2678f40b80265dd53556f1f778c8e1823f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 26 Jul 2013 11:00:10 +0200 Subject: genetlink: release cb_lock before requesting additional module Requesting external module with cb_lock taken can result in the deadlock like showed below: [ 2458.111347] Showing all locks held in the system: [ 2458.111347] 1 lock held by NetworkManager/582: [ 2458.111347] #0: (cb_lock){++++++}, at: [] genl_rcv+0x19/0x40 [ 2458.111347] 1 lock held by modprobe/603: [ 2458.111347] #0: (cb_lock){++++++}, at: [] genl_lock_all+0x15/0x30 [ 2461.579457] SysRq : Show Blocked State [ 2461.580103] task PC stack pid father [ 2461.580103] NetworkManager D ffff880034b84500 4040 582 1 0x00000080 [ 2461.580103] ffff8800197ff720 0000000000000046 00000000001d5340 ffff8800197fffd8 [ 2461.580103] ffff8800197fffd8 00000000001d5340 ffff880019631700 7fffffffffffffff [ 2461.580103] ffff8800197ff880 ffff8800197ff878 ffff880019631700 ffff880019631700 [ 2461.580103] Call Trace: [ 2461.580103] [] schedule+0x29/0x70 [ 2461.580103] [] schedule_timeout+0x1c1/0x360 [ 2461.580103] [] ? mark_held_locks+0xbb/0x140 [ 2461.580103] [] ? _raw_spin_unlock_irq+0x2c/0x50 [ 2461.580103] [] ? trace_hardirqs_on_caller+0xfd/0x1c0 [ 2461.580103] [] wait_for_completion_killable+0xe8/0x170 [ 2461.580103] [] ? wake_up_state+0x20/0x20 [ 2461.580103] [] call_usermodehelper_exec+0x1a5/0x210 [ 2461.580103] [] ? wait_for_completion_killable+0x3d/0x170 [ 2461.580103] [] __request_module+0x1b3/0x370 [ 2461.580103] [] ? trace_hardirqs_on_caller+0xfd/0x1c0 [ 2461.580103] [] ctrl_getfamily+0x159/0x190 [ 2461.580103] [] genl_family_rcv_msg+0x1f4/0x2e0 [ 2461.580103] [] ? genl_family_rcv_msg+0x2e0/0x2e0 [ 2461.580103] [] genl_rcv_msg+0x8e/0xd0 [ 2461.580103] [] netlink_rcv_skb+0xa9/0xc0 [ 2461.580103] [] genl_rcv+0x28/0x40 [ 2461.580103] [] netlink_unicast+0xdd/0x190 [ 2461.580103] [] netlink_sendmsg+0x329/0x750 [ 2461.580103] [] sock_sendmsg+0x99/0xd0 [ 2461.580103] [] ? local_clock+0x5f/0x70 [ 2461.580103] [] ? lock_release_non_nested+0x308/0x350 [ 2461.580103] [] ___sys_sendmsg+0x39e/0x3b0 [ 2461.580103] [] ? kvm_clock_read+0x2f/0x50 [ 2461.580103] [] ? sched_clock+0x9/0x10 [ 2461.580103] [] ? sched_clock_local+0x1d/0x80 [ 2461.580103] [] ? sched_clock_cpu+0xa8/0x100 [ 2461.580103] [] ? trace_hardirqs_off+0xd/0x10 [ 2461.580103] [] ? local_clock+0x5f/0x70 [ 2461.580103] [] ? lock_release_holdtime.part.28+0xf/0x1a0 [ 2461.580103] [] ? fget_light+0xf9/0x510 [ 2461.580103] [] ? fget_light+0x3c/0x510 [ 2461.580103] [] __sys_sendmsg+0x42/0x80 [ 2461.580103] [] SyS_sendmsg+0x12/0x20 [ 2461.580103] [] system_call_fastpath+0x16/0x1b [ 2461.580103] modprobe D ffff88000f2c8000 4632 603 602 0x00000080 [ 2461.580103] ffff88000f04fba8 0000000000000046 00000000001d5340 ffff88000f04ffd8 [ 2461.580103] ffff88000f04ffd8 00000000001d5340 ffff8800377d4500 ffff8800377d4500 [ 2461.580103] ffffffff81d0b260 ffffffff81d0b268 ffffffff00000000 ffffffff81d0b2b0 [ 2461.580103] Call Trace: [ 2461.580103] [] schedule+0x29/0x70 [ 2461.580103] [] rwsem_down_write_failed+0xed/0x1a0 [ 2461.580103] [] ? update_cpu_load_active+0x10/0xb0 [ 2461.580103] [] call_rwsem_down_write_failed+0x13/0x20 [ 2461.580103] [] ? down_write+0x9d/0xb2 [ 2461.580103] [] ? genl_lock_all+0x15/0x30 [ 2461.580103] [] genl_lock_all+0x15/0x30 [ 2461.580103] [] genl_register_family+0x53/0x1f0 [ 2461.580103] [] ? 0xffffffffa01dbfff [ 2461.580103] [] genl_register_family_with_ops+0x20/0x80 [ 2461.580103] [] ? 0xffffffffa01dbfff [ 2461.580103] [] nl80211_init+0x24/0xf0 [cfg80211] [ 2461.580103] [] ? 0xffffffffa01dbfff [ 2461.580103] [] cfg80211_init+0x43/0xdb [cfg80211] [ 2461.580103] [] do_one_initcall+0xfa/0x1b0 [ 2461.580103] [] ? set_memory_nx+0x43/0x50 [ 2461.580103] [] load_module+0x1c6f/0x27f0 [ 2461.580103] [] ? store_uevent+0x40/0x40 [ 2461.580103] [] SyS_finit_module+0x86/0xb0 [ 2461.580103] [] system_call_fastpath+0x16/0x1b [ 2461.580103] Sched Debug Version: v0.10, 3.11.0-0.rc1.git4.1.fc20.x86_64 #1 Problem start to happen after adding net-pf-16-proto-16-family-nl80211 alias name to cfg80211 module by below commit (though that commit itself is perfectly fine): commit fb4e156886ce6e8309e912d8b370d192330d19d3 Author: Marcel Holtmann Date: Sun Apr 28 16:22:06 2013 -0700 nl80211: Add generic netlink module alias for cfg80211/nl80211 Reported-and-tested-by: Jeff Layton Reported-by: Richard W.M. Jones Signed-off-by: Stanislaw Gruszka Reviewed-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/netlink/genetlink.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 2fd6dbea327a..1076fe16b122 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -877,8 +877,10 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info) #ifdef CONFIG_MODULES if (res == NULL) { genl_unlock(); + up_read(&cb_lock); request_module("net-pf-%d-proto-%d-family-%s", PF_NETLINK, NETLINK_GENERIC, name); + down_read(&cb_lock); genl_lock(); res = genl_family_find_byname(name); } -- cgit v1.2.3-59-g8ed1b From 1eb9ac14c34a948bf1538bfb9034e8ab29099a64 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 26 Jul 2013 05:46:35 -0700 Subject: ixgbe: Fix Tx Hang issue with lldpad on 82598EB This patch fixes an issue with the 82598EB device, where lldpad is causing Tx Hangs on the card as soon as it attempts to configure DCB for the device. The adapter will continually Tx hang and reset in a loop. Signed-off-by: Jacob Keller Cc: Stable Tested-by: Phil Schmitt Tested-by: Jack Morgan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c index ac780770863d..7a77f37a7cbc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c @@ -108,9 +108,8 @@ s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, /* Enable arbiter */ reg &= ~IXGBE_DPMCS_ARBDIS; - /* Enable DFP and Recycle mode */ - reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM); reg |= IXGBE_DPMCS_TSOEF; + /* Configure Max TSO packet size 34KB including payload and headers */ reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT); -- cgit v1.2.3-59-g8ed1b From 7e44892c1b6bb499cb2f6d5c0f4afcc077a26074 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 26 Jul 2013 05:46:36 -0700 Subject: igb: fix vlan filtering in promisc mode when not in VT mode This patch fixes a VT mode check to make sure VLAN filters are disabled when in promisc mode and VT is not enabled. The problem with the previous check was that: E1000_MRQC_ENABLE_VMDQ is defined as 0x00000003 but when not in VT mode: mrqc |= E1000_MRQC_ENABLE_RSS_4Q (0x00000002) So the above check will trigger regardless if VT mode is being used or not. Signed-off-by: Emil Tantilov Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/igb/igb_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 6a0c1b66ce54..c1d72c03cb59 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -3739,9 +3739,8 @@ static void igb_set_rx_mode(struct net_device *netdev) rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_VFE); if (netdev->flags & IFF_PROMISC) { - u32 mrqc = rd32(E1000_MRQC); /* retain VLAN HW filtering if in VT mode */ - if (mrqc & E1000_MRQC_ENABLE_VMDQ) + if (adapter->vfs_allocated_count) rctl |= E1000_RCTL_VFE; rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME); -- cgit v1.2.3-59-g8ed1b From a0db856a95a29efb1c23db55c02d9f0ff4f0db48 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 30 Jul 2013 00:16:21 -0700 Subject: net_sched: Fix stack info leak in cbq_dump_wrr(). Make sure the reserved fields, and padding (if any), are fully initialized. Based upon a patch by Dan Carpenter and feedback from Joe Perches. Signed-off-by: David S. Miller --- net/sched/sch_cbq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 71a568862557..7a42c81a19eb 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -1465,6 +1465,7 @@ static int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl) unsigned char *b = skb_tail_pointer(skb); struct tc_cbq_wrropt opt; + memset(&opt, 0, sizeof(opt)); opt.flags = 0; opt.allot = cl->allot; opt.priority = cl->priority + 1; -- cgit v1.2.3-59-g8ed1b From a264b981f2c76e281ef27e7232774bf6c54ec865 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 30 Jul 2013 11:29:40 +0200 Subject: net/fec: Don't let ndo_start_xmit return NETDEV_TX_BUSY without link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't test for having link and let hardware deal with this situation. Without this patch I see a machine running an -rt patched Linux being stuck in sch_direct_xmit when it looses link while there is still a packet to be sent. In this case the fec_enet_start_xmit routine returned NETDEV_TX_BUSY which makes the network stack reschedule the packet and so sch_direct_xmit calls fec_enet_start_xmit again. I failed to reproduce a complete hang without -rt, but I think the problem exists there, too. Signed-off-by: Uwe Kleine-König Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 0dda45481d16..77ea0db0bbfc 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -294,11 +294,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) unsigned short status; unsigned int index; - if (!fep->link) { - /* Link is down or auto-negotiation is in progress. */ - return NETDEV_TX_BUSY; - } - /* Fill in a Tx ring entry */ bdp = fep->cur_tx; -- cgit v1.2.3-59-g8ed1b From ff862a4668dd6dba962b1d2d8bd344afa6375683 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 28 Jul 2013 23:04:45 +0300 Subject: af_key: more info leaks in pfkey messages This is inspired by a5cc68f3d6 "af_key: fix info leaks in notify messages". There are some struct members which don't get initialized and could disclose small amounts of private information. Acked-by: Mathias Krause Signed-off-by: Dan Carpenter Acked-by: Steffen Klassert Signed-off-by: David S. Miller --- net/key/af_key.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/key/af_key.c b/net/key/af_key.c index 9da862070dd8..ab8bd2cabfa0 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2081,6 +2081,7 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, const struct xfrm_policy * pol->sadb_x_policy_type = IPSEC_POLICY_NONE; } pol->sadb_x_policy_dir = dir+1; + pol->sadb_x_policy_reserved = 0; pol->sadb_x_policy_id = xp->index; pol->sadb_x_policy_priority = xp->priority; @@ -3137,7 +3138,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; pol->sadb_x_policy_dir = XFRM_POLICY_OUT + 1; + pol->sadb_x_policy_reserved = 0; pol->sadb_x_policy_id = xp->index; + pol->sadb_x_policy_priority = xp->priority; /* Set sadb_comb's. */ if (x->id.proto == IPPROTO_AH) @@ -3525,6 +3528,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; pol->sadb_x_policy_dir = dir + 1; + pol->sadb_x_policy_reserved = 0; pol->sadb_x_policy_id = 0; pol->sadb_x_policy_priority = 0; -- cgit v1.2.3-59-g8ed1b From e1ee3673a83cc02b6b5e43c9e647d8dd5e1c4e26 Mon Sep 17 00:00:00 2001 From: Pablo Neira Date: Mon, 29 Jul 2013 12:30:04 +0200 Subject: genetlink: fix usage of NLM_F_EXCL or NLM_F_REPLACE Currently, it is not possible to use neither NLM_F_EXCL nor NLM_F_REPLACE from genetlink. This is due to this checking in genl_family_rcv_msg: if (nlh->nlmsg_flags & NLM_F_DUMP) NLM_F_DUMP is NLM_F_MATCH|NLM_F_ROOT. Thus, if NLM_F_EXCL or NLM_F_REPLACE flag is set, genetlink believes that you're requesting a dump and it calls the .dumpit callback. The solution that I propose is to refine this checking to make it stricter: if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) And given the combination NLM_F_REPLACE and NLM_F_EXCL does not make sense to me, it removes the ambiguity. There was a patch that tried to fix this some time ago (0ab03c2 netlink: test for all flags of the NLM_F_DUMP composite) but it tried to resolve this ambiguity in *all* existing netlink subsystems, not only genetlink. That patch was reverted since it broke iproute2, which is using NLM_F_ROOT to request the dump of the routing cache. Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- net/netlink/genetlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 1076fe16b122..512718adb0d5 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -571,7 +571,7 @@ static int genl_family_rcv_msg(struct genl_family *family, !capable(CAP_NET_ADMIN)) return -EPERM; - if (nlh->nlmsg_flags & NLM_F_DUMP) { + if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) { struct netlink_dump_control c = { .dump = ops->dumpit, .done = ops->done, -- cgit v1.2.3-59-g8ed1b From 7b70176421993866e616f1cbc4d0dd4054f1bf78 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 29 Jul 2013 10:24:04 -0700 Subject: atl1c: Fix misuse of netdev_alloc_skb in refilling rx ring On Mon, 2013-07-29 at 08:30 -0700, Eric Dumazet wrote: > On Mon, 2013-07-29 at 13:09 +0100, Luis Henriques wrote: > > > > > I confirm that I can't reproduce the issue using this patch. > > > > Thanks, I'll send a polished patch, as this one had an error if > build_skb() returns NULL (in case sk_buff allocation fails) Please try the following patch : It should use 2K frags instead of 4K for normal 1500 mtu Thanks ! [PATCH] atl1c: use custom skb allocator We had reports ( https://bugzilla.kernel.org/show_bug.cgi?id=54021 ) that using high order pages for skb allocations is problematic for atl1c We do not know exactly what the problem is, but we suspect that crossing 4K pages is not well supported by this hardware. Use a custom allocator, using page allocator and 2K fragments for optimal stack behavior. We might make this allocator generic in future kernels. Signed-off-by: Eric Dumazet Cc: Luis Henriques Cc: Neil Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1c/atl1c.h | 3 ++ drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 40 ++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h index b2bf324631dc..0f0556526ba9 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c.h +++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h @@ -520,6 +520,9 @@ struct atl1c_adapter { struct net_device *netdev; struct pci_dev *pdev; struct napi_struct napi; + struct page *rx_page; + unsigned int rx_page_offset; + unsigned int rx_frag_size; struct atl1c_hw hw; struct atl1c_hw_stats hw_stats; struct mii_if_info mii; /* MII interface info */ diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 786a87483298..a36a760ada28 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -481,10 +481,15 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p) static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter, struct net_device *dev) { + unsigned int head_size; int mtu = dev->mtu; adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ? roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE; + + head_size = SKB_DATA_ALIGN(adapter->rx_buffer_len + NET_SKB_PAD) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + adapter->rx_frag_size = roundup_pow_of_two(head_size); } static netdev_features_t atl1c_fix_features(struct net_device *netdev, @@ -952,6 +957,10 @@ static void atl1c_free_ring_resources(struct atl1c_adapter *adapter) kfree(adapter->tpd_ring[0].buffer_info); adapter->tpd_ring[0].buffer_info = NULL; } + if (adapter->rx_page) { + put_page(adapter->rx_page); + adapter->rx_page = NULL; + } } /** @@ -1639,6 +1648,35 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, skb_checksum_none_assert(skb); } +static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter) +{ + struct sk_buff *skb; + struct page *page; + + if (adapter->rx_frag_size > PAGE_SIZE) + return netdev_alloc_skb(adapter->netdev, + adapter->rx_buffer_len); + + page = adapter->rx_page; + if (!page) { + adapter->rx_page = page = alloc_page(GFP_ATOMIC); + if (unlikely(!page)) + return NULL; + adapter->rx_page_offset = 0; + } + + skb = build_skb(page_address(page) + adapter->rx_page_offset, + adapter->rx_frag_size); + if (likely(skb)) { + adapter->rx_page_offset += adapter->rx_frag_size; + if (adapter->rx_page_offset >= PAGE_SIZE) + adapter->rx_page = NULL; + else + get_page(page); + } + return skb; +} + static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) { struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; @@ -1660,7 +1698,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) while (next_info->flags & ATL1C_BUFFER_FREE) { rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); - skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len); + skb = atl1c_alloc_skb(adapter); if (unlikely(!skb)) { if (netif_msg_rx_err(adapter)) dev_warn(&pdev->dev, "alloc rx buffer failed\n"); -- cgit v1.2.3-59-g8ed1b From aded09555b7a0748a692d0d644ac54c10c1c0757 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard \\(Rtp\\)" Date: Mon, 29 Jul 2013 21:56:47 +0200 Subject: mvneta: Fix hang when loading the mvneta driver When the mvneta driver is compiled, it'll be loaded with clocks disabled. This implies that the clocks should be enabled again before any register access or it'll hang. To fix it: - enable clock earlier - move timer callback after setting timer.data Signed-off-by: Arnaud Patard Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 712779fb12b7..3ac29c64bd6c 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2728,20 +2728,10 @@ static int mvneta_probe(struct platform_device *pdev) pp = netdev_priv(dev); - pp->tx_done_timer.function = mvneta_tx_done_timer_callback; - init_timer(&pp->tx_done_timer); - clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags); - pp->weight = MVNETA_RX_POLL_WEIGHT; pp->phy_node = phy_node; pp->phy_interface = phy_mode; - pp->base = of_iomap(dn, 0); - if (pp->base == NULL) { - err = -ENOMEM; - goto err_free_irq; - } - pp->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(pp->clk)) { err = PTR_ERR(pp->clk); @@ -2765,7 +2755,16 @@ static int mvneta_probe(struct platform_device *pdev) } } + pp->base = of_iomap(dn, 0); + if (pp->base == NULL) { + err = -ENOMEM; + goto err_free_irq; + } + pp->tx_done_timer.data = (unsigned long)dev; + pp->tx_done_timer.function = mvneta_tx_done_timer_callback; + init_timer(&pp->tx_done_timer); + clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; -- cgit v1.2.3-59-g8ed1b From 5445eaf309ff2868c77354016505fc7315947a35 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard \\(Rtp\\)" Date: Mon, 29 Jul 2013 21:56:48 +0200 Subject: mvneta: Try to fix mvneta when compiled as module When the mvneta driver is compiled as module, the clock is disabled before it's loading. This will reset the registers values and all configuration made by the bootloader. This patch sets the "sgmii serdes configuration" register to a magical value found in: https://github.com/yellowback/ubuntu-precise-armadaxp/blob/master/arch/arm/mach-armadaxp/armada_xp_family/ctrlEnv/mvCtrlEnvLib.c With this change, the interrupts are working/generated and ethernet is working. Signed-off-by: Arnaud Patard Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 3ac29c64bd6c..b017818bccae 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -88,6 +88,8 @@ #define MVNETA_TX_IN_PRGRS BIT(1) #define MVNETA_TX_FIFO_EMPTY BIT(8) #define MVNETA_RX_MIN_FRAME_SIZE 0x247c +#define MVNETA_SGMII_SERDES_CFG 0x24A0 +#define MVNETA_SGMII_SERDES_PROTO 0x0cc7 #define MVNETA_TYPE_PRIO 0x24bc #define MVNETA_FORCE_UNI BIT(21) #define MVNETA_TXQ_CMD_1 0x24e4 @@ -655,6 +657,8 @@ static void mvneta_port_sgmii_config(struct mvneta_port *pp) val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); val |= MVNETA_GMAC2_PSC_ENABLE; mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); + + mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); } /* Start the Ethernet port RX and TX activity */ @@ -2735,11 +2739,17 @@ static int mvneta_probe(struct platform_device *pdev) pp->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(pp->clk)) { err = PTR_ERR(pp->clk); - goto err_unmap; + goto err_free_irq; } clk_prepare_enable(pp->clk); + pp->base = of_iomap(dn, 0); + if (pp->base == NULL) { + err = -ENOMEM; + goto err_clk; + } + dt_mac_addr = of_get_mac_address(dn); if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) { mac_from = "device tree"; @@ -2755,12 +2765,6 @@ static int mvneta_probe(struct platform_device *pdev) } } - pp->base = of_iomap(dn, 0); - if (pp->base == NULL) { - err = -ENOMEM; - goto err_free_irq; - } - pp->tx_done_timer.data = (unsigned long)dev; pp->tx_done_timer.function = mvneta_tx_done_timer_callback; init_timer(&pp->tx_done_timer); @@ -2775,7 +2779,7 @@ static int mvneta_probe(struct platform_device *pdev) err = mvneta_init(pp, phy_addr); if (err < 0) { dev_err(&pdev->dev, "can't init eth hal\n"); - goto err_clk; + goto err_unmap; } mvneta_port_power_up(pp, phy_mode); @@ -2805,10 +2809,10 @@ static int mvneta_probe(struct platform_device *pdev) err_deinit: mvneta_deinit(pp); -err_clk: - clk_disable_unprepare(pp->clk); err_unmap: iounmap(pp->base); +err_clk: + clk_disable_unprepare(pp->clk); err_free_irq: irq_dispose_mapping(dev->irq); err_free_netdev: -- cgit v1.2.3-59-g8ed1b From a661b43fd047ef501da43a19975415f861c7c3db Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 30 Jul 2013 07:57:06 +0800 Subject: mlx5: fix error return code in mlx5_alloc_uuars() Fix to return -ENOMEM from the ioremap error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/uar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/uar.c b/drivers/net/ethernet/mellanox/mlx5/core/uar.c index 71d4a3937200..68f5d9c77c7b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/uar.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/uar.c @@ -164,6 +164,7 @@ int mlx5_alloc_uuars(struct mlx5_core_dev *dev, struct mlx5_uuar_info *uuari) uuari->uars[i].map = ioremap(addr, PAGE_SIZE); if (!uuari->uars[i].map) { mlx5_cmd_free_uar(dev, uuari->uars[i].index); + err = -ENOMEM; goto out_count; } mlx5_core_dbg(dev, "allocated uar index 0x%x, mmaped at %p\n", -- cgit v1.2.3-59-g8ed1b