From ef15aa490f2e447ce04fe643500b814ef40f6ea9 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 9 Jan 2009 21:06:30 +0100 Subject: [PATCH 01/92] p54: fix oops caused by bad eeproms This patch fixes a bug that could occur, if it the eeprom is incomplete or partly corrupted. BUG: unable to handle kernel NULL pointer dereference at 00000008 IP: p54_assign_address+0x108/0x15d [p54common] Oops: 0002 [#1] SMP Pid: 12988, comm: phy1 Tainted: P W 2.6.28-rc6-wl #3 RIP: 0010: p54_assign_address+0x108/0x15d [p54common] [...] Call Trace: p54_alloc_skb+0xa3/0xc0 [p54common] p54_scan+0x37/0x204 [p54common] [...] Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index c6a370fa9bcb..3b44e8e76030 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1610,7 +1610,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) err: printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy)); - kfree_skb(skb); + p54_free_skb(dev, skb); return -EINVAL; } From b6b50a21625bbf59a89b807dd0fc1eb5412aeff3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 9 Jan 2009 15:25:09 -0800 Subject: [PATCH 02/92] mac80211: more kernel-doc fixes Fix (delete) more mac80211 kernel-doc: Warning(linux-2.6.28-git13//include/net/mac80211.h:375): Excess struct/union/enum/typedef member 'retry_count' description in 'ieee80211_tx_info' Warning(linux-2.6.28-git13//net/mac80211/sta_info.h:308): Excess struct/union/enum/typedef member 'last_txrate' description in 'sta_info' Signed-off-by: Randy Dunlap Signed-off-by: John W. Linville --- include/net/mac80211.h | 1 - net/mac80211/sta_info.h | 1 - 2 files changed, 2 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b3bd00a9d992..559422fc0943 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -322,7 +322,6 @@ struct ieee80211_tx_rate { * @control: union for control data * @status: union for status data * @driver_data: array of driver_data pointers - * @retry_count: number of retries * @ampdu_ack_len: number of aggregated frames. * relevant only if IEEE80211_TX_STATUS_AMPDU was set. * @ampdu_ack_map: block ack bit map for the aggregation. diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index dc2606d0ae77..e49a5b99cf10 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -195,7 +195,6 @@ struct sta_ampdu_mlme { * @tx_packets: number of RX/TX MSDUs * @tx_bytes: number of bytes transmitted to this STA * @tx_fragments: number of transmitted MPDUs - * @last_txrate: description of the last used transmit rate * @tid_seq: per-TID sequence numbers for sending to this STA * @ampdu_mlme: A-MPDU state machine state * @timer_to_tid: identity mapping to ID timers From d71038c05970ad0c9d7da6f797803f69e4f91837 Mon Sep 17 00:00:00 2001 From: Andrey Yurovsky Date: Mon, 12 Jan 2009 13:14:27 -0800 Subject: [PATCH 03/92] libertas: Fix alignment issues in libertas core Data structures that come over the wire from the WLAN firmware must be packed. This fixes alignment problems on the blackfin architecture and, reportedly, on the AVR32. This is a replacement for the previous version of this patch which had also explicitly used get_unaligned_ macros. As Johannes Berg pointed out, these macros were unnecessary. Signed-off-by: Andrey Yurovsky Signed-off-by: Colin McCabe Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/hostcmd.h | 91 ++++++++++++------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index e173b1b46c23..f6a79a653b7b 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -32,7 +32,7 @@ struct txpd { u8 pktdelay_2ms; /* reserved */ u8 reserved1; -}; +} __attribute__ ((packed)); /* RxPD Descriptor */ struct rxpd { @@ -63,7 +63,7 @@ struct rxpd { /* Pkt Priority */ u8 priority; u8 reserved[3]; -}; +} __attribute__ ((packed)); struct cmd_header { __le16 command; @@ -97,7 +97,7 @@ struct enc_key { struct lbs_offset_value { u32 offset; u32 value; -}; +} __attribute__ ((packed)); /* Define general data structure */ /* cmd_DS_GEN */ @@ -107,7 +107,7 @@ struct cmd_ds_gen { __le16 seqnum; __le16 result; void *cmdresp[0]; -}; +} __attribute__ ((packed)); #define S_DS_GEN sizeof(struct cmd_ds_gen) @@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event { * bump this up a bit. */ uint8_t tlv[128]; -}; +} __attribute__ ((packed)); /* * This scan handle Country Information IE(802.11d compliant) @@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan { mrvlietypes_chanlistparamset_t ChanListParamSet; mrvlietypes_ratesparamset_t OpRateSet; #endif -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_scan_rsp { struct cmd_header hdr; @@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp { __le16 bssdescriptsize; uint8_t nr_sets; uint8_t bssdesc_and_tlvbuffer[0]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_get_log { struct cmd_header hdr; @@ -206,33 +206,33 @@ struct cmd_ds_802_11_get_log { __le32 fcserror; __le32 txframe; __le32 wepundecryptable; -}; +} __attribute__ ((packed)); struct cmd_ds_mac_control { struct cmd_header hdr; __le16 action; u16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_mac_multicast_adr { struct cmd_header hdr; __le16 action; __le16 nr_of_adrs; u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_authenticate { u8 macaddr[ETH_ALEN]; u8 authtype; u8 reserved[10]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_deauthenticate { struct cmd_header hdr; u8 macaddr[ETH_ALEN]; __le16 reasoncode; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_associate { u8 peerstaaddr[6]; @@ -251,7 +251,7 @@ struct cmd_ds_802_11_associate { struct cmd_ds_802_11_associate_rsp { struct ieeetypes_assocrsp assocRsp; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_set_wep { struct cmd_header hdr; @@ -265,7 +265,7 @@ struct cmd_ds_802_11_set_wep { /* 40, 128bit or TXWEP */ uint8_t keytype[4]; uint8_t keymaterial[4][16]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_3_get_stat { __le32 xmitok; @@ -274,7 +274,7 @@ struct cmd_ds_802_3_get_stat { __le32 rcverror; __le32 rcvnobuffer; __le32 rcvcrcerror; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_get_stat { __le32 txfragmentcnt; @@ -294,7 +294,7 @@ struct cmd_ds_802_11_get_stat { __le32 txbeacon; __le32 rxbeacon; __le32 wepundecryptable; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_snmp_mib { struct cmd_header hdr; @@ -303,58 +303,58 @@ struct cmd_ds_802_11_snmp_mib { __le16 oid; __le16 bufsize; u8 value[128]; -}; +} __attribute__ ((packed)); struct cmd_ds_mac_reg_map { __le16 buffersize; u8 regmap[128]; __le16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_bbp_reg_map { __le16 buffersize; u8 regmap[128]; __le16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_rf_reg_map { __le16 buffersize; u8 regmap[64]; __le16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_mac_reg_access { __le16 action; __le16 offset; __le32 value; -}; +} __attribute__ ((packed)); struct cmd_ds_bbp_reg_access { __le16 action; __le16 offset; u8 value; u8 reserved[3]; -}; +} __attribute__ ((packed)); struct cmd_ds_rf_reg_access { __le16 action; __le16 offset; u8 value; u8 reserved[3]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_radio_control { struct cmd_header hdr; __le16 action; __le16 control; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_beacon_control { __le16 action; __le16 beacon_enable; __le16 beacon_period; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_sleep_params { struct cmd_header hdr; @@ -379,7 +379,7 @@ struct cmd_ds_802_11_sleep_params { /* reserved field, should be set to zero */ __le16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_inactivity_timeout { struct cmd_header hdr; @@ -389,7 +389,7 @@ struct cmd_ds_802_11_inactivity_timeout { /* Inactivity timeout in msec */ __le16 timeout; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rf_channel { struct cmd_header hdr; @@ -399,7 +399,7 @@ struct cmd_ds_802_11_rf_channel { __le16 rftype; /* unused */ __le16 reserved; /* unused */ u8 channellist[32]; /* unused */ -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rssi { /* weighting factor */ @@ -408,21 +408,21 @@ struct cmd_ds_802_11_rssi { __le16 reserved_0; __le16 reserved_1; __le16 reserved_2; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rssi_rsp { __le16 SNR; __le16 noisefloor; __le16 avgSNR; __le16 avgnoisefloor; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_mac_address { struct cmd_header hdr; __le16 action; u8 macadd[ETH_ALEN]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rf_tx_power { struct cmd_header hdr; @@ -431,7 +431,7 @@ struct cmd_ds_802_11_rf_tx_power { __le16 curlevel; s8 maxlevel; s8 minlevel; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rf_antenna { __le16 action; @@ -439,33 +439,33 @@ struct cmd_ds_802_11_rf_antenna { /* Number of antennas or 0xffff(diversity) */ __le16 antennamode; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_monitor_mode { __le16 action; __le16 mode; -}; +} __attribute__ ((packed)); struct cmd_ds_set_boot2_ver { struct cmd_header hdr; __le16 action; __le16 version; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_fw_wake_method { struct cmd_header hdr; __le16 action; __le16 method; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_sleep_period { struct cmd_header hdr; __le16 action; __le16 period; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_ps_mode { __le16 action; @@ -473,7 +473,7 @@ struct cmd_ds_802_11_ps_mode { __le16 multipledtim; __le16 reserved; __le16 locallisteninterval; -}; +} __attribute__ ((packed)); struct cmd_confirm_sleep { struct cmd_header hdr; @@ -483,7 +483,7 @@ struct cmd_confirm_sleep { __le16 multipledtim; __le16 reserved; __le16 locallisteninterval; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_data_rate { struct cmd_header hdr; @@ -491,14 +491,14 @@ struct cmd_ds_802_11_data_rate { __le16 action; __le16 reserved; u8 rates[MAX_RATES]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rate_adapt_rateset { struct cmd_header hdr; __le16 action; __le16 enablehwauto; __le16 bitmap; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_ad_hoc_start { struct cmd_header hdr; @@ -520,7 +520,7 @@ struct cmd_ds_802_11_ad_hoc_result { u8 pad[3]; u8 bssid[ETH_ALEN]; -}; +} __attribute__ ((packed)); struct adhoc_bssdesc { u8 bssid[ETH_ALEN]; @@ -578,7 +578,7 @@ struct MrvlIEtype_keyParamSet { /* key material of size keylen */ u8 key[32]; -}; +} __attribute__ ((packed)); #define MAX_WOL_RULES 16 @@ -590,7 +590,7 @@ struct host_wol_rule { __le16 reserve; __be32 sig_mask; __be32 signature; -}; +} __attribute__ ((packed)); struct wol_config { uint8_t action; @@ -598,8 +598,7 @@ struct wol_config { uint8_t no_rules_in_cmd; uint8_t result; struct host_wol_rule rule[MAX_WOL_RULES]; -}; - +} __attribute__ ((packed)); struct cmd_ds_host_sleep { struct cmd_header hdr; From b657eade2f98b5c689e405bd6e4e445471066380 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Jan 2009 14:33:49 +0200 Subject: [PATCH 04/92] ath9k: Fix an operator typo in phy rate validation This was not supposed to be a bitwise AND operation, but a check of two separate conditions. Anyway, the old code happened to result in the same behavior, so this is just changing the code to be easier to understand and also to keep sparse from warning about dubious operators. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 04ab457a8faa..1b71b934bb5e 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -490,7 +490,7 @@ static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table, static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) { - if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG)) + if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG)) return 0; if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) return 0; From 9d97f2e55e3df44e3b6b4cc58b091501ba7ee0ac Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Jan 2009 14:35:08 +0200 Subject: [PATCH 05/92] ath9k: Fix an operator typo in REG_DOMAIN_2GHZ_MASK Incorrect operator causes the REG_DOMAIN_2GHZ_MASK to be zero which surely was not the goal of this definition. Mask out the 11a flags correctly. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/regd_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath9k/regd_common.h index 9112c030b1e8..6df1b3b77c25 100644 --- a/drivers/net/wireless/ath9k/regd_common.h +++ b/drivers/net/wireless/ath9k/regd_common.h @@ -228,7 +228,7 @@ enum { }; #define REG_DOMAIN_2GHZ_MASK (REQ_MASK & \ - (!(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB))) + (~(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB))) #define REG_DOMAIN_5GHZ_MASK REQ_MASK static struct reg_dmn_pair_mapping regDomainPairs[] = { From 73e1a65d3c4a013f6fa56e47133be95143a75fe3 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 8 Jan 2009 10:19:58 -0800 Subject: [PATCH 06/92] iwlwifi: remove CMD_WANT_SKB flag if send_cmd_sync failure In function iwl_send_cmd_sync(), if the flag CMD_WANT_SKB is set but we are not provided with a valid SKB (cmd->meta.u.skb == NULL), we need to remove the CMD_WANT_SKB flag from the TX cmd queue. Otherwise in case the cmd comes in later, it will possibly set an invalid address. Thus it causes an invalid memory access. This fixed the bug http://bugzilla.kernel.org/show_bug.cgi?id=11326. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8c71ad4f88c5..4b35b30e493e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -224,7 +224,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) IWL_ERROR("Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; - goto out; + goto cancel; } ret = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d64580805d6e..15f5655c636e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -745,7 +745,7 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_ IWL_ERROR("Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; - goto out; + goto cancel; } ret = 0; From a92a3ce72483d7f0902dff8a3be8cdcee215a37c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 7 Jan 2009 17:43:33 -0800 Subject: [PATCH 07/92] cfg80211: make handle_band() and handle_channel() wiphy specific This allows us to make more wiphy specific judgements when handling the channels later on. Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4f877535e666..af805b0e1579 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -778,13 +778,22 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth, return !max_bandwidth; } -static void handle_channel(struct ieee80211_channel *chan) +static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, + unsigned int chan_idx) { int r; - u32 flags = chan->orig_flags; + u32 flags; u32 max_bandwidth = 0; const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + + sband = wiphy->bands[band]; + BUG_ON(chan_idx >= sband->n_channels); + chan = &sband->channels[chan_idx]; + + flags = chan->orig_flags; r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq), &max_bandwidth, ®_rule); @@ -808,12 +817,16 @@ static void handle_channel(struct ieee80211_channel *chan) chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); } -static void handle_band(struct ieee80211_supported_band *sband) +static void handle_band(struct wiphy *wiphy, enum ieee80211_band band) { - int i; + unsigned int i; + struct ieee80211_supported_band *sband; + + BUG_ON(!wiphy->bands[band]); + sband = wiphy->bands[band]; for (i = 0; i < sband->n_channels; i++) - handle_channel(&sband->channels[i]); + handle_channel(wiphy, band, i); } static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) @@ -840,7 +853,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) enum ieee80211_band band; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (wiphy->bands[band]) - handle_band(wiphy->bands[band]); + handle_band(wiphy, band); if (wiphy->reg_notifier) wiphy->reg_notifier(wiphy, setby); } From 0c7dc45d21de6ae212b5ccb7cdff5beff795ccf0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 7 Jan 2009 17:43:36 -0800 Subject: [PATCH 08/92] cfg80211: Fix regression with 11d on bands This fixes a regression on disallowing bands introduced with the new 802.11d support. The issue is that IEEE-802.11 allows APs to send a subset of what a country regulatory domain defines. This was clarified in this document: http://tinyurl.com/11d-clarification As such it is possible, and this is what is done in practice, that a single band 2.4 GHz AP will only send 2.4 GHz band regulatory information through the 802.11 country information element and then the current intersection with what CRDA provided yields a regulatory domain with no 5 GHz information -- even though that country may actually allow 5 GHz operation. We correct this by only applying the intersection rules on a channel if the the intersection yields a regulatory rule on the same band the channel is on. Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 82 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index af805b0e1579..5f6d20d98eeb 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -421,6 +421,31 @@ static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, return 0; } +/** + * freq_in_rule_band - tells us if a frequency is in a frequency band + * @freq_range: frequency rule we want to query + * @freq_khz: frequency we are inquiring about + * + * This lets us know if a specific frequency rule is or is not relevant to + * a specific frequency's band. Bands are device specific and artificial + * definitions (the "2.4 GHz band" and the "5 GHz band"), however it is + * safe for now to assume that a frequency rule should not be part of a + * frequency's band if the start freq or end freq are off by more than 2 GHz. + * This resolution can be lowered and should be considered as we add + * regulatory rule support for other "bands". + **/ +static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, + u32 freq_khz) +{ +#define ONE_GHZ_IN_KHZ 1000000 + if (abs(freq_khz - freq_range->start_freq_khz) <= (2 * ONE_GHZ_IN_KHZ)) + return true; + if (abs(freq_khz - freq_range->end_freq_khz) <= (2 * ONE_GHZ_IN_KHZ)) + return true; + return false; +#undef ONE_GHZ_IN_KHZ +} + /* Converts a country IE to a regulatory domain. A regulatory domain * structure has a lot of information which the IE doesn't yet have, * so for the other values we use upper max values as we will intersect @@ -748,12 +773,23 @@ static u32 map_regdom_flags(u32 rd_flags) * this value to the maximum allowed bandwidth. * @reg_rule: the regulatory rule which we have for this frequency * - * Use this function to get the regulatory rule for a specific frequency. + * Use this function to get the regulatory rule for a specific frequency on + * a given wireless device. If the device has a specific regulatory domain + * it wants to follow we respect that unless a country IE has been received + * and processed already. + * + * Returns 0 if it was able to find a valid regulatory rule which does + * apply to the given center_freq otherwise it returns non-zero. It will + * also return -ERANGE if we determine the given center_freq does not even have + * a regulatory rule for a frequency range in the center_freq's band. See + * freq_in_rule_band() for our current definition of a band -- this is purely + * subjective and right now its 802.11 specific. */ static int freq_reg_info(u32 center_freq, u32 *bandwidth, const struct ieee80211_reg_rule **reg_rule) { int i; + bool band_rule_found = false; u32 max_bandwidth = 0; if (!cfg80211_regdomain) @@ -767,7 +803,15 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth, rr = &cfg80211_regdomain->reg_rules[i]; fr = &rr->freq_range; pr = &rr->power_rule; + + /* We only need to know if one frequency rule was + * was in center_freq's band, that's enough, so lets + * not overwrite it once found */ + if (!band_rule_found) + band_rule_found = freq_in_rule_band(fr, center_freq); + max_bandwidth = freq_max_bandwidth(fr, center_freq); + if (max_bandwidth && *bandwidth <= max_bandwidth) { *reg_rule = rr; *bandwidth = max_bandwidth; @@ -775,6 +819,9 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth, } } + if (!band_rule_found) + return -ERANGE; + return !max_bandwidth; } @@ -799,8 +846,37 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, &max_bandwidth, ®_rule); if (r) { - flags |= IEEE80211_CHAN_DISABLED; - chan->flags = flags; + /* This means no regulatory rule was found in the country IE + * with a frequency range on the center_freq's band, since + * IEEE-802.11 allows for a country IE to have a subset of the + * regulatory information provided in a country we ignore + * disabling the channel unless at least one reg rule was + * found on the center_freq's band. For details see this + * clarification: + * + * http://tinyurl.com/11d-clarification + */ + if (r == -ERANGE && + last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { +#ifdef CONFIG_CFG80211_REG_DEBUG + printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz " + "intact on %s - no rule found in band on " + "Country IE\n", + chan->center_freq, wiphy_name(wiphy)); +#endif + } else { + /* In this case we know the country IE has at least one reg rule + * for the band so we respect its band definitions */ +#ifdef CONFIG_CFG80211_REG_DEBUG + if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) + printk(KERN_DEBUG "cfg80211: Disabling " + "channel %d MHz on %s due to " + "Country IE\n", + chan->center_freq, wiphy_name(wiphy)); +#endif + flags |= IEEE80211_CHAN_DISABLED; + chan->flags = flags; + } return; } From 02e68a3da0fbdb178cdec54b7db48edeefd1691d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 7 Jan 2009 17:43:37 -0800 Subject: [PATCH 09/92] cfg80211: Fix parsed country IE info for 5 GHz The country IE number of channels on 5 GHz specifies the number of 5 GHz channels, not the number of sequential channel numbers. For example, if in a country IEs if the first channel given is 36 and the number of channels passed is 4 then the individual channel numbers defined for the 5 GHz PHY by these parameters are: 36, 40, 44, 48 not: 36, 37, 38, 39 See: http://tinyurl.com/11d-clarification Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5f6d20d98eeb..bc494cef2102 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -563,6 +563,7 @@ static struct ieee80211_regdomain *country_ie_2_rd( /* This time around we fill in the rd */ while (country_ie_len >= 3) { + int end_channel = 0; struct ieee80211_country_ie_triplet *triplet = (struct ieee80211_country_ie_triplet *) country_ie; struct ieee80211_reg_rule *reg_rule = NULL; @@ -584,6 +585,23 @@ static struct ieee80211_regdomain *country_ie_2_rd( reg_rule->flags = flags; + /* 2 GHz */ + if (triplet->chans.first_channel <= 14) + end_channel = triplet->chans.first_channel + + triplet->chans.num_channels; + else + /* + * 5 GHz -- For example in country IEs if the first + * channel given is 36 and the number of channels is 4 + * then the individual channel numbers defined for the + * 5 GHz PHY by these parameters are: 36, 40, 44, and 48 + * and not 36, 37, 38, 39. + * + * See: http://tinyurl.com/11d-clarification + */ + end_channel = triplet->chans.first_channel + + (4 * (triplet->chans.num_channels - 1)); + /* The +10 is since the regulatory domain expects * the actual band edge, not the center of freq for * its start and end freqs, assuming 20 MHz bandwidth on @@ -593,8 +611,7 @@ static struct ieee80211_regdomain *country_ie_2_rd( triplet->chans.first_channel) - 10); freq_range->end_freq_khz = MHZ_TO_KHZ(ieee80211_channel_to_frequency( - triplet->chans.first_channel + - triplet->chans.num_channels) + 10); + end_channel) + 10); /* Large arbitrary values, we intersect later */ /* Increment this if we ever support >= 40 MHz channels From e223b6dc051ad030a70d5c6ed6226b95bdfc3af7 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Wed, 14 Jan 2009 00:00:13 +0200 Subject: [PATCH 10/92] rt2x00: fix a wrong parameter for __test_and_clear_bit() in rt2x00rfkill_free(). When running modprobe rt73usb, and then rmmod rt73usb, and then iwconfig, the wlan0 device does not disappear. When repeating this process again, we get a kernel Oops errors and "BUG: unable to handle kernel paging request..." message in the kernel log. The reason for this is that there is an error in rt2x00rfkill_free(), which is called in the process of removing the device (rt2x00lib_remove_dev() in rt2x00dev.c). rt2x00rfkill_free() clears the RFKILL_STATE_ALLOCATED bit , which is bit number 1 () in rt2x00dev->flags instead of in rt2x00dev->rfkill_state. As a result, when checking the DEVICE_STATE_REGISTERED_HW bit (bit number 1 in rt2x00dev->flags) in rt2x00lib_remove_hw() it is **unset**, and we wrongly **don't** call ieee80211_unregister_hw(). This patch corrects this: the parameter for __test_and_clear_bit() in rt2x00rfkill_free() should be &rt2x00dev->rfkill_state and not &rt2x00dev->flags. Signed-off-by: Rami Rosen Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index c3f53a92180a..3298cae1e12d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -162,7 +162,7 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) { - if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->flags)) + if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) return; cancel_delayed_work_sync(&rt2x00dev->rfkill_work); From 275719089bfe7dbf446b72c3e520966e7fa42b6a Mon Sep 17 00:00:00 2001 From: Artur Skawina Date: Thu, 15 Jan 2009 21:07:03 +0100 Subject: [PATCH 11/92] p54: set_tim must be atomic. Fix for: BUG: scheduling while atomic: named/2004/0x10000200 Pid: 2004, comm: named Not tainted 2.6.29-rc1-00271-ge9fa6b0 #45 Call Trace: [] schedule+0x2a7/0x320 [] __alloc_skb+0x34/0x110 [] __cond_resched+0x13/0x30 [] _cond_resched+0x2d/0x40 [] kmem_cache_alloc+0x95/0xc0 [] check_object+0xc4/0x230 [] __alloc_skb+0x34/0x110 [] p54_alloc_skb+0x71/0xf0 [] p54_set_tim+0x3f/0xa0 [] sta_info_set_tim_bit+0x64/0x80 [] invoke_tx_handlers+0xd57/0xd80 [] free_debug_processing+0x197/0x210 [] pskb_expand_head+0xf5/0x170 [] __ieee80211_tx_prepare+0x164/0x2f0 [] ieee80211_skb_resize+0x6d/0xe0 [] ieee80211_master_start_xmit+0x23f/0x550 [] __slab_alloc+0x2b8/0x4f0 [] getnstimeofday+0x51/0x120 [] dev_hard_start_xmit+0x1db/0x240 [] __qdisc_run+0x1ab/0x200 [] __run_hrtimer+0x31/0xf0 [] dev_queue_xmit+0x247/0x500 [] ieee80211_subif_start_xmit+0x356/0x7d0 [] packet_rcv_spkt+0x37/0x150 [] packet_rcv_spkt+0x37/0x150 [] dev_hard_start_xmit+0x1db/0x240 [] __qdisc_run+0x1ab/0x200 [] dev_queue_xmit+0x247/0x500 [] neigh_resolve_output+0xe2/0x200 [] ip_finish_output+0x0/0x290 [] ip_finish_output+0x1e7/0x290 [] ip_local_out+0x15/0x20 [] ip_push_pending_frames+0x272/0x380 [] udp_push_pending_frames+0x146/0x3a0 [] udp_sendmsg+0x2fa/0x6b0 [] inet_sendmsg+0x37/0x70 [] sock_sendmsg+0xbe/0x100 [] autoremove_wake_function+0x0/0x50 [] __wake_up_common+0x43/0x70 [] copy_from_user+0x32/0x130 [] copy_from_user+0x32/0x130 [] verify_iovec+0x2e/0xb0 [] sys_sendmsg+0x17f/0x290 [] pipe_write+0x29a/0x570 [] update_wall_time+0x492/0x8e0 [] getnstimeofday+0x51/0x120 [] sched_slice+0x3d/0x80 [] getnstimeofday+0x51/0x120 [] hrtimer_forward+0x147/0x1a0 [] lapic_next_event+0x10/0x20 [] clockevents_program_event+0xa3/0x170 [] sys_socketcall+0xa4/0x290 [] smp_apic_timer_interrupt+0x40/0x70 [] sysenter_do_call+0x12/0x25 Signed-off-by: Artur Skawina Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 3b44e8e76030..ae31e3775e0c 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1147,7 +1147,7 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(struct p54_hdr) + sizeof(*tim), - P54_CONTROL_TYPE_TIM, GFP_KERNEL); + P54_CONTROL_TYPE_TIM, GFP_ATOMIC); if (!skb) return -ENOMEM; From 674743033c1ae9f7cc94e1e0037f6f719e6d1d67 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 16 Jan 2009 19:46:28 +0100 Subject: [PATCH 12/92] p54: fix p54_set_key's return code p54 doesn't support AES-128-CMAC offload. This patch will fix the noisy mac80211 warnings, when 802.11w is enabled: mac80211-phy189: failed to set key (4, ff:ff:ff:ff:ff:ff) to hardware (-22) mac80211-phy189: failed to set key (5, ff:ff:ff:ff:ff:ff) to hardware (-22) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index ae31e3775e0c..12d0717c3992 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2077,7 +2077,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, algo = P54_CRYPTO_AESCCMP; break; default: - return -EINVAL; + return -EOPNOTSUPP; } } From 70b9986ca4baaf6deb6f0e01d50f72457579adea Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:48 +0000 Subject: [PATCH 13/92] bnx2x: Free IRQ Error check could result with not freeing the IRQ Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7c533797c064..ce98ecf8cb1c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6684,6 +6684,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); bnx2x_stats_handle(bp, STATS_EVENT_STOP); + /* Release IRQs */ + bnx2x_free_irq(bp); + /* Wait until tx fast path tasks complete */ for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; @@ -6711,9 +6714,6 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) /* Give HW time to discard old tx messages */ msleep(1); - /* Release IRQs */ - bnx2x_free_irq(bp); - if (CHIP_IS_E1(bp)) { struct mac_configuration_cmd *config = bnx2x_sp(bp, mcast_config); From 693fc0d14334859430733ab902adac182fdd8153 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:52 +0000 Subject: [PATCH 14/92] bnx2x: Handling probe failures Failures in the probe not handled correctly - separate the flow to handle different failures Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ce98ecf8cb1c..911067586a4a 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -10269,17 +10269,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return rc; } - rc = register_netdev(dev); - if (rc) { - dev_err(&pdev->dev, "Cannot register net device\n"); - goto init_one_exit; - } - pci_set_drvdata(pdev, dev); rc = bnx2x_init_bp(bp); + if (rc) + goto init_one_exit; + + rc = register_netdev(dev); if (rc) { - unregister_netdev(dev); + dev_err(&pdev->dev, "Cannot register net device\n"); goto init_one_exit; } From b4661739c67acd15a02f8e112f8cc52d24b609ed Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:56 +0000 Subject: [PATCH 15/92] bnx2x: Potential race after iSCSI boot The lock was release too soon. Make sure the HW is marked as locked until the boot driver was unloaded from FW perspective Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 911067586a4a..70fc61033ddf 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6874,10 +6874,6 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) */ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); val = REG_RD(bp, DORQ_REG_NORM_CID_OFST); - if (val == 0x7) - REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); - if (val == 0x7) { u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; /* save our func */ @@ -6885,6 +6881,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) u32 swap_en; u32 swap_val; + /* clear the UNDI indication */ + REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); + BNX2X_DEV_INFO("UNDI is active! reset device\n"); /* try unload UNDI on port 0 */ @@ -6910,6 +6909,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bnx2x_fw_command(bp, reset_code); } + /* now it's safe to release the lock */ + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); + REG_WR(bp, (BP_PORT(bp) ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0), 0x1000); @@ -6954,7 +6956,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bp->fw_seq = (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); - } + + } else + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); } } From af2464011f0954785687071b298f066f6cbb1c84 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:59 +0000 Subject: [PATCH 16/92] bnx2x: Wrong HDR offset in CAM Has a negative side effect when sending MAC update with no content (as done in the self-test) Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 70fc61033ddf..8f8271d76db6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6144,7 +6144,7 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set) * multicast 64-127:port0 128-191:port1 */ config->hdr.length_6b = 2; - config->hdr.offset = port ? 31 : 0; + config->hdr.offset = port ? 32 : 0; config->hdr.client_id = BP_CL_ID(bp); config->hdr.reserved1 = 0; @@ -8910,7 +8910,10 @@ static int bnx2x_test_intr(struct bnx2x *bp) return -ENODEV; config->hdr.length_6b = 0; - config->hdr.offset = 0; + if (CHIP_IS_E1(bp)) + config->hdr.offset = (BP_PORT(bp) ? 32 : 0); + else + config->hdr.offset = BP_FUNC(bp); config->hdr.client_id = BP_CL_ID(bp); config->hdr.reserved1 = 0; @@ -9863,7 +9866,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev) for (; i < old; i++) { if (CAM_IS_INVALID(config-> config_table[i])) { - i--; /* already invalidated */ + /* already invalidated */ break; } /* invalidate */ From 5a40e08e666e8caa1227333de41fd1e2cd84d4f5 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:04 +0000 Subject: [PATCH 17/92] bnx2x: Read chip ID Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 8f8271d76db6..7ee6a211f9ba 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6975,7 +6975,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) id |= ((val & 0xf) << 12); val = REG_RD(bp, MISC_REG_CHIP_METAL); id |= ((val & 0xff) << 4); - REG_RD(bp, MISC_REG_BOND_ID); + val = REG_RD(bp, MISC_REG_BOND_ID); id |= (val & 0xf); bp->common.chip_id = id; bp->link_params.chip_id = bp->common.chip_id; From 2add3acb11a26cc14b54669433ae6ace6406cbf2 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:07 +0000 Subject: [PATCH 18/92] bnx2x: Block nvram access when the device is inactive Don't dump eeprom when bnx2x adapter is down. Running ethtool -e causes an eeh without it when the device is down Signed-off-by: Paul Larson Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7ee6a211f9ba..ca5090c3341e 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -8107,6 +8107,9 @@ static int bnx2x_get_eeprom(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); int rc; + if (!netif_running(dev)) + return -EAGAIN; + DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n" DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n", eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset, From 632da4d66324b5baf947a048dd1f1e9093b6dd90 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:10 +0000 Subject: [PATCH 19/92] bnx2x: Overstepping array bounds If the page size is > 8KB this violation happens Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ca5090c3341e..2e00da6ab172 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9427,6 +9427,7 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) return rc; } +#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) /* check if packet requires linearization (packet is too fragmented) */ static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb, u32 xmit_type) @@ -9504,6 +9505,7 @@ exit_lbl: return to_copy; } +#endif /* called with netif_tx_lock * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call @@ -9544,6 +9546,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr, ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type); +#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) /* First, check if we need to linearize the skb (due to FW restrictions) */ if (bnx2x_pkt_req_lin(bp, skb, xmit_type)) { @@ -9556,6 +9559,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } } +#endif /* Please read carefully. First we use one BD which we mark as start, From 6c55c3cdc86881383075a933594748b30dd0054b Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:13 +0000 Subject: [PATCH 20/92] bnx2x: 1G-10G toggling race The HW should be configured so fast toggling between 1G and 10G will not be missed. Make sure that the HW is re-configured in full Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 43 ++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index fefa6ab13064..d9e1cfcd06dd 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -317,6 +317,9 @@ static u8 bnx2x_emac_enable(struct link_params *params, val &= ~0x810; EMAC_WR(bp, EMAC_REG_EMAC_MODE, val); + /* enable emac */ + REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1); + /* enable emac for jumbo packets */ EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE, (EMAC_RX_MTU_SIZE_JUMBO_ENA | @@ -1609,7 +1612,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, u32 gp_status) { struct bnx2x *bp = params->bp; - + u16 new_line_speed; u8 rc = 0; vars->link_status = 0; @@ -1629,7 +1632,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, switch (gp_status & GP_STATUS_SPEED_MASK) { case GP_STATUS_10M: - vars->line_speed = SPEED_10; + new_line_speed = SPEED_10; if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_10TFD; else @@ -1637,7 +1640,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, break; case GP_STATUS_100M: - vars->line_speed = SPEED_100; + new_line_speed = SPEED_100; if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_100TXFD; else @@ -1646,7 +1649,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, case GP_STATUS_1G: case GP_STATUS_1G_KX: - vars->line_speed = SPEED_1000; + new_line_speed = SPEED_1000; if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_1000TFD; else @@ -1654,7 +1657,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, break; case GP_STATUS_2_5G: - vars->line_speed = SPEED_2500; + new_line_speed = SPEED_2500; if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_2500TFD; else @@ -1671,32 +1674,32 @@ static u8 bnx2x_link_settings_status(struct link_params *params, case GP_STATUS_10G_KX4: case GP_STATUS_10G_HIG: case GP_STATUS_10G_CX4: - vars->line_speed = SPEED_10000; + new_line_speed = SPEED_10000; vars->link_status |= LINK_10GTFD; break; case GP_STATUS_12G_HIG: - vars->line_speed = SPEED_12000; + new_line_speed = SPEED_12000; vars->link_status |= LINK_12GTFD; break; case GP_STATUS_12_5G: - vars->line_speed = SPEED_12500; + new_line_speed = SPEED_12500; vars->link_status |= LINK_12_5GTFD; break; case GP_STATUS_13G: - vars->line_speed = SPEED_13000; + new_line_speed = SPEED_13000; vars->link_status |= LINK_13GTFD; break; case GP_STATUS_15G: - vars->line_speed = SPEED_15000; + new_line_speed = SPEED_15000; vars->link_status |= LINK_15GTFD; break; case GP_STATUS_16G: - vars->line_speed = SPEED_16000; + new_line_speed = SPEED_16000; vars->link_status |= LINK_16GTFD; break; @@ -1708,6 +1711,15 @@ static u8 bnx2x_link_settings_status(struct link_params *params, break; } + /* Upon link speed change set the NIG into drain mode. + Comes to deals with possible FIFO glitch due to clk change + when speed is decreased without link down indicator */ + if (new_line_speed != vars->line_speed) { + REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + + params->port*4, 0); + msleep(1); + } + vars->line_speed = new_line_speed; vars->link_status |= LINK_STATUS_SERDES_LINK; if ((params->req_line_speed == SPEED_AUTO_NEG) && @@ -4194,6 +4206,11 @@ static u8 bnx2x_update_link_down(struct link_params *params, /* activate nig drain */ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); + /* disable emac */ + REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); + + msleep(10); + /* reset BigMac */ bnx2x_bmac_rx_disable(bp, params->port); REG_WR(bp, GRCBASE_MISC + @@ -4238,6 +4255,7 @@ static u8 bnx2x_update_link_up(struct link_params *params, /* update shared memory */ bnx2x_update_mng(params, vars->link_status); + msleep(20); return rc; } /* This function should called upon link interrupt */ @@ -4276,6 +4294,9 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); + /* disable emac */ + REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); + ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); /* Check external link change only for non-direct */ From 3858276b7198074bf3570470463808627f0c9e31 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:16 +0000 Subject: [PATCH 21/92] bnx2x: Prevent self test loopback failures Setting loopback requires time to take effect Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index d9e1cfcd06dd..4ce107c125d1 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -3583,7 +3583,7 @@ static void bnx2x_set_xgxs_loopback(struct link_params *params, (MDIO_REG_BANK_CL73_IEEEB0 + (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)), 0x6041); - + msleep(200); /* set aer mmd back */ bnx2x_set_aer_mmd(params, vars); From 44722d1d216c9dd4536de5f88fe8320b07e68a96 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:21 +0000 Subject: [PATCH 22/92] bnx2x: Legacy speeds autoneg failures 10M/100M autoneg was not establishing link. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 4ce107c125d1..2fd6be0cca13 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -3882,9 +3882,15 @@ static u8 bnx2x_link_initialize(struct link_params *params, } if (vars->phy_flags & PHY_XGXS_FLAG) { - if (params->req_line_speed && + if ((params->req_line_speed && ((params->req_line_speed == SPEED_100) || - (params->req_line_speed == SPEED_10))) { + (params->req_line_speed == SPEED_10))) || + (!params->req_line_speed && + (params->speed_cap_mask >= + PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) && + (params->speed_cap_mask < + PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) + )) { vars->phy_flags |= PHY_SGMII_FLAG; } else { vars->phy_flags &= ~PHY_SGMII_FLAG; From 16b311cc29806bb968746c1a752a087b32841af9 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:24 +0000 Subject: [PATCH 23/92] bnx2x: Handling PHY FW load failure If the default PHY version (0x4321) is read - the PHY FW load failed Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 2fd6be0cca13..b4527a4a60e3 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -4404,10 +4404,11 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) ext_phy_addr[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &fw_ver1); - if (fw_ver1 == 0) { + if (fw_ver1 == 0 || fw_ver1 == 0x4321) { DP(NETIF_MSG_LINK, - "bnx2x_8073_common_init_phy port %x " - "fw Download failed\n", port); + "bnx2x_8073_common_init_phy port %x:" + "Download failed. fw version = 0x%x\n", + port, fw_ver1); return -EINVAL; } From e47d7e6eb841c1850f0e69b95ae6cf3c86881f53 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:28 +0000 Subject: [PATCH 24/92] bnx2x: Driver description update The Driver supports the 57711 and 57711E as well but the description was out of date Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 2e00da6ab172..dc05e37c581d 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -69,7 +69,7 @@ static char version[] __devinitdata = DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Eliezer Tamir"); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver"); +MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); From 237907c1ded8a1a447cea7c4f97ab853e8b46052 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:42:44 +0000 Subject: [PATCH 25/92] bnx2x: Barriers for the compiler To make sure no swapping are made by the compiler, changed HAS_WORK to inline functions and added all the necessary barriers Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 9 +-------- drivers/net/bnx2x_main.c | 37 ++++++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 6fcccef4cf3d..18f60aa3efdd 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -271,14 +271,7 @@ struct bnx2x_fastpath { #define bnx2x_fp(bp, nr, var) (bp->fp[nr].var) -#define BNX2X_HAS_TX_WORK(fp) \ - ((fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) || \ - (fp->tx_pkt_prod != fp->tx_pkt_cons)) - -#define BNX2X_HAS_RX_WORK(fp) \ - (fp->rx_comp_cons != rx_cons_sb) - -#define BNX2X_HAS_WORK(fp) (BNX2X_HAS_RX_WORK(fp) || BNX2X_HAS_TX_WORK(fp)) +#define BNX2X_HAS_WORK(fp) (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp)) /* MC hsi */ diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index dc05e37c581d..3236527477a3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -733,6 +733,17 @@ static u16 bnx2x_ack_int(struct bnx2x *bp) * fast path service functions */ +static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) +{ + u16 tx_cons_sb; + + /* Tell compiler that status block fields can change */ + barrier(); + tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb); + return ((fp->tx_pkt_prod != tx_cons_sb) || + (fp->tx_pkt_prod != fp->tx_pkt_cons)); +} + /* free skb in the packet ring at pos idx * return idx of last bd freed */ @@ -6693,7 +6704,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) cnt = 1000; smp_rmb(); - while (BNX2X_HAS_TX_WORK(fp)) { + while (bnx2x_has_tx_work(fp)) { bnx2x_tx_int(fp, 1000); if (!cnt) { @@ -9281,6 +9292,18 @@ static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) return 0; } +static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) +{ + u16 rx_cons_sb; + + /* Tell compiler that status block fields can change */ + barrier(); + rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); + if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) + rx_cons_sb++; + return (fp->rx_comp_cons != rx_cons_sb); +} + /* * net_device service functions */ @@ -9291,7 +9314,6 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) napi); struct bnx2x *bp = fp->bp; int work_done = 0; - u16 rx_cons_sb; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) @@ -9304,19 +9326,12 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) bnx2x_update_fpsb_idx(fp); - if (BNX2X_HAS_TX_WORK(fp)) + if (bnx2x_has_tx_work(fp)) bnx2x_tx_int(fp, budget); - rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); - if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - rx_cons_sb++; - if (BNX2X_HAS_RX_WORK(fp)) + if (bnx2x_has_rx_work(fp)) work_done = bnx2x_rx_int(fp, budget); - rmb(); /* BNX2X_HAS_WORK() reads the status block */ - rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); - if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - rx_cons_sb++; /* must not complete if we consumed full budget */ if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) { From d05c26ce690e867aabfc7d708d481e0f86f23496 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Sat, 17 Jan 2009 23:26:13 -0800 Subject: [PATCH 26/92] bnx2x: Version update Updating the version and the year of updated files Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- drivers/net/bnx2x_link.c | 2 +- drivers/net/bnx2x_main.c | 6 +++--- drivers/net/bnx2x_reg.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 18f60aa3efdd..15a5cf0f676b 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -1,6 +1,6 @@ /* bnx2x.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index b4527a4a60e3..aea26b4dc453 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -1,4 +1,4 @@ -/* Copyright 2008 Broadcom Corporation +/* Copyright 2008-2009 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 3236527477a3..074374ff93f3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1,6 +1,6 @@ /* bnx2x_main.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.23" -#define DRV_MODULE_RELDATE "2008/11/03" +#define DRV_MODULE_VERSION "1.45.24" +#define DRV_MODULE_RELDATE "2009/01/14" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index a67b0c358ae4..d084e5fc4b51 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h @@ -1,6 +1,6 @@ /* bnx2x_reg.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 24e94de41e76134fad05552588fe01af2cab1494 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sun, 18 Jan 2009 21:32:11 -0800 Subject: [PATCH 27/92] net/9p: fid->fid is used uninitialized Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- net/9p/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/9p/client.c b/net/9p/client.c index 821f1ec0b2c3..1eb580c38fbb 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -618,7 +618,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt) return ERR_PTR(-ENOMEM); ret = p9_idpool_get(clnt->fidpool); - if (fid->fid < 0) { + if (ret < 0) { ret = -ENOSPC; goto error; } From 39eddb4c3970e9aadbc87b8a7cab7b4fefff077f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sun, 18 Jan 2009 21:57:35 -0800 Subject: [PATCH 28/92] macb: avoid lockup when TGO during underrun MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In rare cases when an underrun occur, all macb buffers where consumed and the netif_queue was stopped infinitely. This happens then the TGO (transfer ongoing) bit in the TSR is set (and UND). It seems like clening up after the underrun makes the driver and the macb hardware end up in an inconsistent state. The result of this is that in the following calls to macb_tx no TX buffers are released -> the netif_queue was stopped, and never woken up again. The solution is to disable the transmitter, if TGO is set, before clening up after the underrun, and re-enable the transmitter when the cleaning up is done. Signed-off-by: Richard Röjfors Signed-off-by: David S. Miller --- drivers/net/macb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index a04da4ecaa88..f6c4936e2fa8 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -321,6 +321,10 @@ static void macb_tx(struct macb *bp) printk(KERN_ERR "%s: TX underrun, resetting buffers\n", bp->dev->name); + /* Transfer ongoing, disable transmitter, to avoid confusion */ + if (status & MACB_BIT(TGO)) + macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE)); + head = bp->tx_head; /*Mark all the buffer as used to avoid sending a lost buffer*/ @@ -343,6 +347,10 @@ static void macb_tx(struct macb *bp) } bp->tx_head = bp->tx_tail = 0; + + /* Enable the transmitter again */ + if (status & MACB_BIT(TGO)) + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE)); } if (!(status & MACB_BIT(COMP))) From eed087e367591fc08490d7c6c2779b4b72c8f20c Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 18 Jan 2009 22:01:32 -0800 Subject: [PATCH 29/92] cxgb3: Fix LRO misalignment The lro manager's frag_align_pad setting was missing, leading to misaligned access to the skb passed up to the stack. Tested-by: Rick Jones Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 14f9fb3e8795..379a1324db4e 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2104,6 +2104,7 @@ static void init_lro_mgr(struct sge_qset *qs, struct net_lro_mgr *lro_mgr) { lro_mgr->dev = qs->netdev; lro_mgr->features = LRO_F_NAPI; + lro_mgr->frag_align_pad = NET_IP_ALIGN; lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; lro_mgr->max_desc = T3_MAX_LRO_SES; From 6a2fe9834e578590f4a2fbe18a574465ab0e127c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 15 Jan 2009 12:29:55 +0000 Subject: [PATCH 30/92] korina: fix loop back of receive descriptors After the last loop iteration, i has the value RC32434_NUM_RDS and therefore leads to an index overflow when used afterwards to address the last element. This is yet another another bug introduced when rewriting parts of the driver for upstream preparation, as the original driver used 'RC32434_NUM_RDS - 1' instead. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 1d6e48e13366..67fbdf40aceb 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -769,11 +769,12 @@ static void korina_alloc_ring(struct net_device *dev) lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]); } - /* loop back */ - lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[0]); - lp->rx_next_done = 0; + /* loop back receive descriptors, so the last + * descriptor points to the first one */ + lp->rd_ring[i - 1].link = CPHYSADDR(&lp->rd_ring[0]); + lp->rd_ring[i - 1].control |= DMA_DESC_COD; - lp->rd_ring[i].control |= DMA_DESC_COD; + lp->rx_next_done = 0; lp->rx_chain_head = 0; lp->rx_chain_tail = 0; lp->rx_chain_status = desc_empty; From 63a66c6c0debcae70183849121734fd4809e1dde Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 15 Jan 2009 12:29:56 +0000 Subject: [PATCH 31/92] korina: adjust headroom for new skb's also This is copy and paste from the original driver. As skb_reserve() is also called within korina_alloc_ring() when initially allocating the receive descriptors, the same should be done when allocating new space after passing an skb to upper layers. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 67fbdf40aceb..60ae7bfb1d9b 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -416,6 +416,9 @@ static int korina_rx(struct net_device *dev, int limit) if (devcs & ETH_RX_MP) dev->stats.multicast++; + /* 16 bit align */ + skb_reserve(skb_new, 2); + lp->rx_skb[lp->rx_next_done] = skb_new; } From e85bf47e6ded66ea138f692fe149c00a4998afe8 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 15 Jan 2009 12:29:57 +0000 Subject: [PATCH 32/92] korina: drop leftover assignment As the assigned value is being overwritten shortly after, it can be dropped and so the whole variable definition moved to the start of the function. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 60ae7bfb1d9b..75010cac76ac 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -743,6 +743,7 @@ static struct ethtool_ops netdev_ethtool_ops = { static void korina_alloc_ring(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); + struct sk_buff *skb; int i; /* Initialize the transmit descriptors */ @@ -758,8 +759,6 @@ static void korina_alloc_ring(struct net_device *dev) /* Initialize the receive descriptors */ for (i = 0; i < KORINA_NUM_RDS; i++) { - struct sk_buff *skb = lp->rx_skb[i]; - skb = dev_alloc_skb(KORINA_RBSIZE + 2); if (!skb) break; From 67fd1a731ff1a990d4da7689909317756e50cb4d Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 19 Jan 2009 16:26:44 -0800 Subject: [PATCH 33/92] net: Add debug info to track down GSO checksum bug I'm trying to track down why people're hitting the checksum warning in skb_gso_segment. As the problem seems to be hitting lots of people and I can't reproduce it or locate the bug, here is a patch to print out more details which hopefully should help us to track this down. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 8d675975d85b..6e44c3277101 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1534,7 +1534,19 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) skb->mac_len = skb->network_header - skb->mac_header; __skb_pull(skb, skb->mac_len); - if (WARN_ON(skb->ip_summed != CHECKSUM_PARTIAL)) { + if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { + struct net_device *dev = skb->dev; + struct ethtool_drvinfo info = {}; + + if (dev && dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) + dev->ethtool_ops->get_drvinfo(dev, &info); + + WARN(1, "%s: caps=(0x%lx, 0x%lx) len=%d data_len=%d " + "ip_summed=%d", + info.driver, dev ? dev->features : 0L, + skb->sk ? skb->sk->sk_route_caps : 0L, + skb->len, skb->data_len, skb->ip_summed); + if (skb_header_cloned(skb) && (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) return ERR_PTR(err); From 15005a320473b8d3676b878deb29bbe738ef9027 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Mon, 19 Jan 2009 16:54:13 -0800 Subject: [PATCH 34/92] ixgbe: fix dca issue with relaxed ordering turned on The is an issue where setting Relaxed Ordering (RO) bit (in a PCI-E write transaction) on 82598 causing the chipset to drop DCA hints. This patch forces RO not to be set for descriptors as well as payload. This will only be in effect while DCA is enabled and no performance difference was noticed in testing. Signed-off-by: Don Skidmore Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 3 +++ drivers/net/ixgbe/ixgbe_type.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index acef3c65cd2c..92d9b17a081a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -318,6 +318,9 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN; rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN; + rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN); + rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl); rx_ring->cpu = cpu; } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 83a11ff9ffd1..f011c57c9205 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -404,6 +404,9 @@ #define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ #define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */ #define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */ +#define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */ +#define IXGBE_DCA_RXCTRL_DESC_WRO_EN (1 << 13) /* DCA Rx wr Desc Relax Order */ +#define IXGBE_DCA_RXCTRL_DESC_HSRO_EN (1 << 15) /* DCA Rx Split Header RO */ #define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ From 068c89b014ebd27b1c09c3c772e9d982988e7786 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Mon, 19 Jan 2009 16:54:36 -0800 Subject: [PATCH 35/92] ixgbe: fix tag stripping for VLAN ID 0 Register VLAN ID 0 so that frames with VLAN ID 0 are received and get their tag stripped when ixgbe is not in DCB mode. VLAN ID 0 means that the frame is 'priority tagged' only - it is not a VLAN, but the priority value is the tag in valid. The functions ixgbe_vlan_rx_register() and ixgbe_vlan_rx_kill_vid() were moved up a couple functions to correct compiling issues with this change. Signed-off-by: Don Skidmore Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Eric W Multanen Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 65 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 92d9b17a081a..bf36737e2ec7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1744,38 +1744,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); } -static void ixgbe_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - u32 ctrl; - - if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_disable(adapter); - adapter->vlgrp = grp; - - /* - * For a DCB driver, always enable VLAN tag stripping so we can - * still receive traffic from a DCB-enabled host even if we're - * not in DCB mode. - */ - ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); - ctrl |= IXGBE_VLNCTRL_VME; - ctrl &= ~IXGBE_VLNCTRL_CFIEN; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); - - if (grp) { - /* enable VLAN tag insert/strip */ - ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); - ctrl |= IXGBE_VLNCTRL_VME; - ctrl &= ~IXGBE_VLNCTRL_CFIEN; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); - } - - if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_enable(adapter); -} - static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -1802,6 +1770,39 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) hw->mac.ops.set_vfta(&adapter->hw, vid, 0, false); } +static void ixgbe_vlan_rx_register(struct net_device *netdev, + struct vlan_group *grp) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + u32 ctrl; + + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + ixgbe_irq_disable(adapter); + adapter->vlgrp = grp; + + /* + * For a DCB driver, always enable VLAN tag stripping so we can + * still receive traffic from a DCB-enabled host even if we're + * not in DCB mode. + */ + ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); + ctrl |= IXGBE_VLNCTRL_VME; + ctrl &= ~IXGBE_VLNCTRL_CFIEN; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); + ixgbe_vlan_rx_add_vid(netdev, 0); + + if (grp) { + /* enable VLAN tag insert/strip */ + ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); + ctrl |= IXGBE_VLNCTRL_VME; + ctrl &= ~IXGBE_VLNCTRL_CFIEN; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); + } + + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + ixgbe_irq_enable(adapter); +} + static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter) { ixgbe_vlan_rx_register(adapter->netdev, adapter->vlgrp); From 1da100bb47ef32cb43bb6a365f64183898f830b5 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Mon, 19 Jan 2009 16:55:03 -0800 Subject: [PATCH 36/92] ixgbe: Fix usage of netif_*_all_queues() with netif_carrier_{off|on}() netif_carrier_off() is sufficient to stop Tx into the driver. Stopping the Tx queues is redundant and unnecessary. By the same token, netif_carrier_on() will be sufficient to re-enable Tx, so waking the queues is unnecessary. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index bf36737e2ec7..d2f4d5f508b7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2078,6 +2078,9 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) ixgbe_irq_enable(adapter); + /* enable transmits */ + netif_tx_start_all_queues(netdev); + /* bring the link up in the watchdog, this could race with our first * link up interrupt but shouldn't be a problem */ adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; @@ -3479,7 +3482,6 @@ static void ixgbe_watchdog_task(struct work_struct *work) (FLOW_TX ? "TX" : "None")))); netif_carrier_on(netdev); - netif_tx_wake_all_queues(netdev); } else { /* Force detection of hung controller */ adapter->detect_tx_hung = true; @@ -3491,7 +3493,6 @@ static void ixgbe_watchdog_task(struct work_struct *work) printk(KERN_INFO "ixgbe: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); } } @@ -4222,7 +4223,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, } netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); From 9e9fd12dc0679643c191fc9795a3021807e77de4 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 19 Jan 2009 16:57:45 -0800 Subject: [PATCH 37/92] tg3: Fix firmware loading This patch modifies how the tg3 driver handles device firmware. The patch starts by consolidating David Woodhouse's earlier patch under the same name. Specifically, the patch moves the request_firmware call into a separate tg3_request_firmware() function and calls that function from tg3_open() rather than tg3_init_one(). The patch then goes on to limit the number of devices that will make request_firmware calls. The original firmware patch unnecessarily requested TSO firmware for devices that did not need it. This patch reduces the set of devices making TSO firmware patches to approximately the following device set : 5703, 5704, and 5705. Finally, the patch reduces the effects of a request_firmware() failure. For those devices that are requesting TSO firmware, the driver will turn off the TSO capability. If TSO firmware becomes available at a later time, the device can be closed and then opened again to reacquire the TSO capability. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 81 +++++++++++++++++++++++++++++------------------ drivers/net/tg3.h | 1 + 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5e2dbaee125b..8b3f84685387 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7535,11 +7535,58 @@ static int tg3_test_msi(struct tg3 *tp) return err; } +static int tg3_request_firmware(struct tg3 *tp) +{ + const __be32 *fw_data; + + if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) { + printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", + tp->dev->name, tp->fw_needed); + return -ENOENT; + } + + fw_data = (void *)tp->fw->data; + + /* Firmware blob starts with version numbers, followed by + * start address and _full_ length including BSS sections + * (which must be longer than the actual data, of course + */ + + tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ + if (tp->fw_len < (tp->fw->size - 12)) { + printk(KERN_ERR "%s: bogus length %d in \"%s\"\n", + tp->dev->name, tp->fw_len, tp->fw_needed); + release_firmware(tp->fw); + tp->fw = NULL; + return -EINVAL; + } + + /* We no longer need firmware; we have it. */ + tp->fw_needed = NULL; + return 0; +} + static int tg3_open(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); int err; + if (tp->fw_needed) { + err = tg3_request_firmware(tp); + if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { + if (err) + return err; + } else if (err) { + printk(KERN_WARNING "%s: TSO capability disabled.\n", + tp->dev->name); + tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; + } else if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { + printk(KERN_NOTICE "%s: TSO capability restored.\n", + tp->dev->name); + tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + } + } + netif_carrier_off(tp->dev); err = tg3_set_power_state(tp, PCI_D0); @@ -12934,7 +12981,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, struct net_device *dev; struct tg3 *tp; int err, pm_cap; - const char *fw_name = NULL; char str[40]; u64 dma_mask, persist_dma_mask; @@ -13091,7 +13137,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_bufmgr_config(tp); if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) - fw_name = FIRMWARE_TG3; + tp->fw_needed = FIRMWARE_TG3; if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; @@ -13104,37 +13150,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; } else { tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG; - } - if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - fw_name = FIRMWARE_TG3TSO5; + tp->fw_needed = FIRMWARE_TG3TSO5; else - fw_name = FIRMWARE_TG3TSO; - } - - if (fw_name) { - const __be32 *fw_data; - - err = request_firmware(&tp->fw, fw_name, &tp->pdev->dev); - if (err) { - printk(KERN_ERR "tg3: Failed to load firmware \"%s\"\n", - fw_name); - goto err_out_iounmap; - } - - fw_data = (void *)tp->fw->data; - - /* Firmware blob starts with version numbers, followed by - start address and _full_ length including BSS sections - (which must be longer than the actual data, of course */ - - tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ - if (tp->fw_len < (tp->fw->size - 12)) { - printk(KERN_ERR "tg3: bogus length %d in \"%s\"\n", - tp->fw_len, fw_name); - err = -EINVAL; - goto err_out_fw; - } + tp->fw_needed = FIRMWARE_TG3TSO; } /* TSO is on by default on chips that support hardware TSO. diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ae5da603c6af..508def3e077f 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2764,6 +2764,7 @@ struct tg3 { struct ethtool_coalesce coal; /* firmware info */ + const char *fw_needed; const struct firmware *fw; u32 fw_len; /* includes BSS */ }; From 8b9d3728977760f6bd1317c4420890f73695354e Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 19 Jan 2009 17:03:56 -0800 Subject: [PATCH 38/92] net: Fix data corruption when splicing from sockets. The trick in socket splicing where we try to convert the skb->data into a page based reference using virt_to_page() does not work so well. The idea is to pass the virt_to_page() reference via the pipe buffer, and refcount the buffer using a SKB reference. But if we are splicing from a socket to a socket (via sendpage) this doesn't work. The from side processing will grab the page (and SKB) references. The sendpage() calls will grab page references only, return, and then the from side processing completes and drops the SKB ref. The page based reference to skb->data is not enough to keep the kmalloc() buffer backing it from being reused. Yet, that is all that the socket send side has at this point. This leads to data corruption if the skb->data buffer is reused by SLAB before the send side socket actually gets the TX packet out to the device. The fix employed here is to simply allocate a page and copy the skb->data bytes into that page. This will hurt performance, but there is no clear way to fix this properly without a copy at the present time, and it is important to get rid of the data corruption. With fixes from Herbert Xu. Tested-by: Willy Tarreau Foreseen-by: Changli Gao Diagnosed-by: Willy Tarreau Reported-by: Willy Tarreau Fixed-by: Jens Axboe Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/core/skbuff.c | 61 ++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 65eac7739033..56272ac6dfd8 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -73,17 +73,13 @@ static struct kmem_cache *skbuff_fclone_cache __read_mostly; static void sock_pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { - struct sk_buff *skb = (struct sk_buff *) buf->private; - - kfree_skb(skb); + put_page(buf->page); } static void sock_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { - struct sk_buff *skb = (struct sk_buff *) buf->private; - - skb_get(skb); + get_page(buf->page); } static int sock_pipe_buf_steal(struct pipe_inode_info *pipe, @@ -1334,9 +1330,19 @@ fault: */ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) { - struct sk_buff *skb = (struct sk_buff *) spd->partial[i].private; + put_page(spd->pages[i]); +} - kfree_skb(skb); +static inline struct page *linear_to_page(struct page *page, unsigned int len, + unsigned int offset) +{ + struct page *p = alloc_pages(GFP_KERNEL, 0); + + if (!p) + return NULL; + memcpy(page_address(p) + offset, page_address(page) + offset, len); + + return p; } /* @@ -1344,16 +1350,23 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) */ static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, unsigned int len, unsigned int offset, - struct sk_buff *skb) + struct sk_buff *skb, int linear) { if (unlikely(spd->nr_pages == PIPE_BUFFERS)) return 1; + if (linear) { + page = linear_to_page(page, len, offset); + if (!page) + return 1; + } else + get_page(page); + spd->pages[spd->nr_pages] = page; spd->partial[spd->nr_pages].len = len; spd->partial[spd->nr_pages].offset = offset; - spd->partial[spd->nr_pages].private = (unsigned long) skb_get(skb); spd->nr_pages++; + return 0; } @@ -1369,7 +1382,7 @@ static inline void __segment_seek(struct page **page, unsigned int *poff, static inline int __splice_segment(struct page *page, unsigned int poff, unsigned int plen, unsigned int *off, unsigned int *len, struct sk_buff *skb, - struct splice_pipe_desc *spd) + struct splice_pipe_desc *spd, int linear) { if (!*len) return 1; @@ -1392,7 +1405,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff, /* the linear region may spread across several pages */ flen = min_t(unsigned int, flen, PAGE_SIZE - poff); - if (spd_fill_page(spd, page, flen, poff, skb)) + if (spd_fill_page(spd, page, flen, poff, skb, linear)) return 1; __segment_seek(&page, &poff, &plen, flen); @@ -1419,7 +1432,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, if (__splice_segment(virt_to_page(skb->data), (unsigned long) skb->data & (PAGE_SIZE - 1), skb_headlen(skb), - offset, len, skb, spd)) + offset, len, skb, spd, 1)) return 1; /* @@ -1429,7 +1442,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, const skb_frag_t *f = &skb_shinfo(skb)->frags[seg]; if (__splice_segment(f->page, f->page_offset, f->size, - offset, len, skb, spd)) + offset, len, skb, spd, 0)) return 1; } @@ -1442,7 +1455,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, * the frag list, if such a thing exists. We'd probably need to recurse to * handle that cleanly. */ -int skb_splice_bits(struct sk_buff *__skb, unsigned int offset, +int skb_splice_bits(struct sk_buff *skb, unsigned int offset, struct pipe_inode_info *pipe, unsigned int tlen, unsigned int flags) { @@ -1455,16 +1468,6 @@ int skb_splice_bits(struct sk_buff *__skb, unsigned int offset, .ops = &sock_pipe_buf_ops, .spd_release = sock_spd_release, }; - struct sk_buff *skb; - - /* - * I'd love to avoid the clone here, but tcp_read_sock() - * ignores reference counts and unconditonally kills the sk_buff - * on return from the actor. - */ - skb = skb_clone(__skb, GFP_KERNEL); - if (unlikely(!skb)) - return -ENOMEM; /* * __skb_splice_bits() only fails if the output has no room left, @@ -1488,15 +1491,9 @@ int skb_splice_bits(struct sk_buff *__skb, unsigned int offset, } done: - /* - * drop our reference to the clone, the pipe consumption will - * drop the rest. - */ - kfree_skb(skb); - if (spd.nr_pages) { + struct sock *sk = skb->sk; int ret; - struct sock *sk = __skb->sk; /* * Drop the socket lock, otherwise we have reverse From e0c6ef9388b58f297937fc9651331941d1579b25 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 19 Jan 2009 17:16:00 -0800 Subject: [PATCH 39/92] Revert "mv643xx_eth: use longer DMA bursts". This reverts commit cd4ccf76bfd2c36d351e68be7e6a597268f98a1a. On the Pegasos board, we can't do DMA burst that are longer than one cache line. For now, go back to using 32 byte DMA bursts for all mv643xx_eth platforms -- we can switch the ARM-based platforms back to doing long 128 byte bursts in the next development cycle. Signed-off-by: Lennert Buytenhek Reported-by: Alan Curry Reported-by: Gabriel Paubert Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 7253a499d9c8..e2aa468d40f1 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -136,21 +136,23 @@ static char mv643xx_eth_driver_version[] = "1.4"; /* * SDMA configuration register. */ +#define RX_BURST_SIZE_4_64BIT (2 << 1) #define RX_BURST_SIZE_16_64BIT (4 << 1) #define BLM_RX_NO_SWAP (1 << 4) #define BLM_TX_NO_SWAP (1 << 5) +#define TX_BURST_SIZE_4_64BIT (2 << 22) #define TX_BURST_SIZE_16_64BIT (4 << 22) #if defined(__BIG_ENDIAN) #define PORT_SDMA_CONFIG_DEFAULT_VALUE \ - (RX_BURST_SIZE_16_64BIT | \ - TX_BURST_SIZE_16_64BIT) + (RX_BURST_SIZE_4_64BIT | \ + TX_BURST_SIZE_4_64BIT) #elif defined(__LITTLE_ENDIAN) #define PORT_SDMA_CONFIG_DEFAULT_VALUE \ - (RX_BURST_SIZE_16_64BIT | \ - BLM_RX_NO_SWAP | \ - BLM_TX_NO_SWAP | \ - TX_BURST_SIZE_16_64BIT) + (RX_BURST_SIZE_4_64BIT | \ + BLM_RX_NO_SWAP | \ + BLM_TX_NO_SWAP | \ + TX_BURST_SIZE_4_64BIT) #else #error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined #endif From 2b448334a255d34401562229f467ffd95d8ed6ef Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 19 Jan 2009 17:17:18 -0800 Subject: [PATCH 40/92] mv643xx_eth: fix multicast filter programming Commit 66e63ffbc04706568d8789cbb00eaa8ddbcae648 ("mv643xx_eth: implement ->set_rx_mode()") cleaned up mv643xx_eth's multicast filter programming, but broke it as well. The non-special multicast filter table (for multicast addresses that are not of the form 01:00:5e:00:00:xx) consists of 256 hash table buckets organised as 64 32-bit words, where the 'accept' bits are in the LSB of each byte, so in bits 24 16 8 0 of each 32-bit word. The old code got this right, but the referenced commit broke this by using bits 3 2 1 0 instead. This commit fixes this up. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index e2aa468d40f1..8c6979a26d61 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1596,7 +1596,7 @@ oom: entry = addr_crc(a); } - table[entry >> 2] |= 1 << (entry & 3); + table[entry >> 2] |= 1 << (8 * (entry & 3)); } for (i = 0; i < 0x100; i += 4) { From fe65e704534de5d0661ebc3466a2b9018945f694 Mon Sep 17 00:00:00 2001 From: Gabriel Paubert Date: Mon, 19 Jan 2009 17:18:09 -0800 Subject: [PATCH 41/92] mv643xx_eth: prevent interrupt storm on ifconfig down Contrary to what the docs say, the 'extended interrupt cause' bit in the interrupt cause register (bit 1) appears to not be maskable on at least some of the mv643xx_eth platforms, making writing zeroes to the interrupt mask register but not the extended interrupt mask register insufficient to stop interrupts from occuring. Therefore, also write zeroes to the extended interrupt mask register when shutting down the port. This fixes the interrupt storm seen on the Pegasos board when shutting down the interface. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 8c6979a26d61..5f31bbb614af 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2212,6 +2212,7 @@ static int mv643xx_eth_stop(struct net_device *dev) struct mv643xx_eth_private *mp = netdev_priv(dev); int i; + wrlp(mp, INT_MASK_EXT, 0x00000000); wrlp(mp, INT_MASK, 0x00000000); rdlp(mp, INT_MASK); From f4895b8bc83a22a36446c4aee277e1750fcc6a18 Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Mon, 19 Jan 2009 13:19:30 +0000 Subject: [PATCH 42/92] wimax/i2400m: error paths that need to free an skb should use kfree_skb() Roel Kluin reported a bug in two error paths where skbs were wrongly being freed using kfree(). He provided a fix where it was replaced to kfree_skb(), as it should be. However, in i2400mu_rx(), the error path was missing returning an indication of the failure. Changed to reset rx_skb to NULL and return it to the caller, i2400mu_rxd(). It will be treated as a transient error and just ignore the packet. Depending on the buffering conditions inside the device, the data packet might be dropped or the device will signal the host again for data-ready-to-read and the host will retry. Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/control.c | 2 +- drivers/net/wimax/i2400m/usb-rx.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index d3d37fed6893..15d9f51b292c 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -609,7 +609,7 @@ void i2400m_msg_to_dev_cancel_wait(struct i2400m *i2400m, int code) spin_lock_irqsave(&i2400m->rx_lock, flags); ack_skb = i2400m->ack_skb; if (ack_skb && !IS_ERR(ack_skb)) - kfree(ack_skb); + kfree_skb(ack_skb); i2400m->ack_skb = ERR_PTR(code); spin_unlock_irqrestore(&i2400m->rx_lock, flags); } diff --git a/drivers/net/wimax/i2400m/usb-rx.c b/drivers/net/wimax/i2400m/usb-rx.c index 074cc1f89853..a314799967cf 100644 --- a/drivers/net/wimax/i2400m/usb-rx.c +++ b/drivers/net/wimax/i2400m/usb-rx.c @@ -184,6 +184,8 @@ void i2400mu_rx_size_maybe_shrink(struct i2400mu *i2400mu) * NOTE: this function might realloc the skb (if it is too small), * so always update with the one returned. * ERR_PTR() is < 0 on error. + * Will return NULL if it cannot reallocate -- this can be + * considered a transient retryable error. */ static struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) @@ -243,8 +245,8 @@ retry: if (printk_ratelimit()) dev_err(dev, "RX: Can't reallocate skb to %d; " "RX dropped\n", rx_size); - kfree(rx_skb); - result = 0; + kfree_skb(rx_skb); + rx_skb = NULL; goto out; /* drop it...*/ } kfree_skb(rx_skb); @@ -344,7 +346,8 @@ int i2400mu_rxd(void *_i2400mu) if (IS_ERR(rx_skb)) goto out; atomic_dec(&i2400mu->rx_pending_count); - if (rx_skb->len == 0) { /* some ignorable condition */ + if (rx_skb == NULL || rx_skb->len == 0) { + /* some "ignorable" condition */ kfree_skb(rx_skb); continue; } From 66f9a2590aa87dc77cddaeaf46177de76edd2339 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Jan 2009 09:49:51 -0800 Subject: [PATCH 43/92] Revert "xfrm: For 32/64 compatability wrt. xfrm_usersa_info" This reverts commit fc8c7dc1b29560c016a67a34ccff32a712b5aa86. As indicated by Jiri Klimes, this won't work. These numbers are not only used the size validation, they are also used to locate attributes sitting after the message. Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7877e7975dae..b95a2d64eb59 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1914,17 +1914,10 @@ static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, } #endif -/* For the xfrm_usersa_info cases we have to work around some 32-bit vs. - * 64-bit compatability issues. On 32-bit the structure is 220 bytes, but - * for 64-bit it gets padded out to 224 bytes. Those bytes are just - * padding and don't have any content we care about. Therefore as long - * as we have enough bytes for the content we can make both cases work. - */ - #define XMSGSIZE(type) sizeof(struct type) static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { - [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = 220, /* see above */ + [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), [XFRM_MSG_DELSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id), [XFRM_MSG_GETSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id), [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), @@ -1934,7 +1927,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), - [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = 220, /* see above */ + [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = 0, From 357f5b0b91054ae23385ea4b0634bb8b43736e83 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 17 Jan 2009 06:47:12 +0000 Subject: [PATCH 44/92] NET: net_namespace, fix lock imbalance register_pernet_gen_subsys omits mutex_unlock in one fail path. Fix it. Signed-off-by: Jiri Slaby Signed-off-by: David S. Miller --- net/core/net_namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 55cffad2f328..55151faaf90c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -341,8 +341,8 @@ again: rv = register_pernet_operations(first_device, ops); if (rv < 0) ida_remove(&net_generic_ids, *id); - mutex_unlock(&net_mutex); out: + mutex_unlock(&net_mutex); return rv; } EXPORT_SYMBOL_GPL(register_pernet_gen_subsys); From e3fd553468738e0342cbd82a63ede00c983a0eb4 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Sat, 17 Jan 2009 08:27:19 +0000 Subject: [PATCH 45/92] myri10ge: don't forget pci_disable_device() Don't forget to call pci_disable_device() in myri10ge_remove() and when myri10ge_probe() fails. By the way, update the copyright years. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 6bb71b687f7b..e9c1296b267e 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1,7 +1,7 @@ /************************************************************************* * myri10ge.c: Myricom Myri-10G Ethernet driver. * - * Copyright (C) 2005 - 2007 Myricom, Inc. + * Copyright (C) 2005 - 2009 Myricom, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.4.4-1.398" +#define MYRI10GE_VERSION_STR "1.4.4-1.401" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -3786,7 +3786,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (status != 0) { dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n", status); - goto abort_with_netdev; + goto abort_with_enabled; } pci_set_master(pdev); @@ -3801,13 +3801,13 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } if (status != 0) { dev_err(&pdev->dev, "Error %d setting DMA mask\n", status); - goto abort_with_netdev; + goto abort_with_enabled; } (void)pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd), &mgp->cmd_bus, GFP_KERNEL); if (mgp->cmd == NULL) - goto abort_with_netdev; + goto abort_with_enabled; mgp->board_span = pci_resource_len(pdev, 0); mgp->iomem_base = pci_resource_start(pdev, 0); @@ -3943,8 +3943,10 @@ abort_with_mtrr: dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), mgp->cmd, mgp->cmd_bus); -abort_with_netdev: +abort_with_enabled: + pci_disable_device(pdev); +abort_with_netdev: free_netdev(netdev); return status; } @@ -3990,6 +3992,7 @@ static void myri10ge_remove(struct pci_dev *pdev) mgp->cmd, mgp->cmd_bus); free_netdev(netdev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } From 0d1cfd20cc5f785d5345d249d4b6a6f84b29e6a6 Mon Sep 17 00:00:00 2001 From: roel kluin Date: Sat, 17 Jan 2009 11:14:31 +0000 Subject: [PATCH 46/92] via-velocity: fix hot spin while(--j >= 0) keeps spinning when j is unsigned: Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index a75f91dc3153..c5691fdb7079 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1302,7 +1302,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr) static int velocity_init_td_ring(struct velocity_info *vptr) { dma_addr_t curr; - unsigned int j; + int j; /* Init the TD ring entries */ for (j = 0; j < vptr->tx.numq; j++) { From ebad18e93fbc6bc63ee734edbc0eb38ac6b919c0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 17 Jan 2009 19:46:16 +0000 Subject: [PATCH 47/92] gro: Fix handling of complete checksums in IPv6 We need to perform skb_postpull_rcsum after pulling the IPv6 header in order to maintain the correctness of the complete checksum. This patch also adds a missing iph reload after pulling. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 94f74f5b0cbf..c802bc1658a8 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -797,6 +797,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, unsigned int nlen; int flush = 1; int proto; + __wsum csum; if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) goto out; @@ -808,6 +809,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, rcu_read_lock(); proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr); + iph = ipv6_hdr(skb); IPV6_GRO_CB(skb)->proto = proto; ops = rcu_dereference(inet6_protos[proto]); if (!ops || !ops->gro_receive) @@ -839,8 +841,13 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, NAPI_GRO_CB(skb)->flush |= flush; + csum = skb->csum; + skb_postpull_rcsum(skb, iph, skb_network_header_len(skb)); + pp = ops->gro_receive(head, skb); + skb->csum = csum; + out_unlock: rcu_read_unlock(); From 9a8e47ffd95608f0768e1a8a0225c822aa53aa9b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 17 Jan 2009 19:47:18 +0000 Subject: [PATCH 48/92] gro: Fix error handling on extremely short frags When a frag is shorter than an Ethernet header, we'd return a zeroed packet instead of aborting. This patch fixes that. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/dev.c b/net/core/dev.c index 6e44c3277101..5379b0c1190a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2536,6 +2536,7 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, if (!pskb_may_pull(skb, ETH_HLEN)) { napi_reuse_skb(napi, skb); + skb = NULL; goto out; } From 37fe4732b978eb02e5433387a40f2b61706cebe3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 17 Jan 2009 19:48:13 +0000 Subject: [PATCH 49/92] gro: Fix merging of paged packets The previous fix to paged packets broke the merging because it reset the skb->len before we added it to the merged packet. This wasn't detected because it simply resulted in the truncation of the packet while the missing bit is subsequently retransmitted. The fix is to store skb->len before we clobber it. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/skbuff.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 56272ac6dfd8..2e5f2ca3bdcd 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2585,8 +2585,9 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) struct sk_buff *nskb; unsigned int headroom; unsigned int hlen = p->data - skb_mac_header(p); + unsigned int len = skb->len; - if (hlen + p->len + skb->len >= 65536) + if (hlen + p->len + len >= 65536) return -E2BIG; if (skb_shinfo(p)->frag_list) @@ -2648,9 +2649,9 @@ merge: done: NAPI_GRO_CB(p)->count++; - p->data_len += skb->len; - p->truesize += skb->len; - p->len += skb->len; + p->data_len += len; + p->truesize += len; + p->len += len; NAPI_GRO_CB(skb)->same_flow = 1; return 0; From 748085fcbedbf7b0f38d95e178265d7b13360b44 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 21 Jan 2009 12:19:49 -0800 Subject: [PATCH 50/92] netfilter: ctnetlink: fix scheduling while atomic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caused by call to request_module() while holding nf_conntrack_lock. Reported-and-tested-by: Kövesdi György Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_netlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 3dddec6d2f7e..c32a7e8e3a1b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -831,13 +831,16 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct, if (!parse_nat_setup) { #ifdef CONFIG_MODULES rcu_read_unlock(); + spin_unlock_bh(&nf_conntrack_lock); nfnl_unlock(); if (request_module("nf-nat-ipv4") < 0) { nfnl_lock(); + spin_lock_bh(&nf_conntrack_lock); rcu_read_lock(); return -EOPNOTSUPP; } nfnl_lock(); + spin_lock_bh(&nf_conntrack_lock); rcu_read_lock(); if (nfnetlink_parse_nat_setup_hook) return -EAGAIN; From 0b491eee46012772cbf029450d123e933c2e7940 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Wed, 21 Jan 2009 12:35:43 -0800 Subject: [PATCH 51/92] usbnet: allow type check of devdbg arguments in non-debug build Improve usbnet's devdbg to always type-check diagnostic arguments, like dev_dbg (device.h). This makes no change to the resulting size of usbnet modules. This patch also removes an #ifdef DEBUG directive from rndis_wlan so it's devdbg statements are always type-checked at compile time. Signed-off-by: Steve Glendinning Signed-off-by: David Brownell Signed-off-by: David S. Miller --- drivers/net/wireless/rndis_wlan.c | 2 -- include/linux/usb/usbnet.h | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 607ce9f61b54..ed93ac41297f 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1649,9 +1649,7 @@ static char *rndis_translate_scan(struct net_device *dev, char *end_buf, struct ndis_80211_bssid_ex *bssid) { -#ifdef DEBUG struct usbnet *usbdev = netdev_priv(dev); -#endif u8 *ie; char *current_val; int bssid_len, ie_len, i; diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index ba09fe88adda..7d3822243074 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -197,7 +197,9 @@ extern int usbnet_nway_reset(struct net_device *net); #define devdbg(usbnet, fmt, arg...) \ printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , ## arg) #else -#define devdbg(usbnet, fmt, arg...) do {} while(0) +#define devdbg(usbnet, fmt, arg...) \ + ({ if (0) printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , \ + ## arg); 0; }) #endif #define deverr(usbnet, fmt, arg...) \ From 6d317482944250228255bcbe97a95b7e7ad9a538 Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Wed, 21 Jan 2009 12:56:24 -0800 Subject: [PATCH 52/92] usb/mcs7830: Don't use buffers from stack for USB transfers mcs7830_set_reg() and mcs7830_get_reg() are called with buffers from stack which must not be used directly for USB transfers. This causes corruption of the stack particulary on non x86 architectures because DMA may be used for these transfers. Signed-off-by: Christian Eggers Acked-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/usb/mcs7830.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 5385d66b306e..ced8f36ebd01 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -94,10 +94,18 @@ static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data) { struct usb_device *xdev = dev->udev; int ret; + void *buffer; + + buffer = kmalloc(size, GFP_NOIO); + if (buffer == NULL) + return -ENOMEM; ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ, - MCS7830_RD_BMREQ, 0x0000, index, data, + MCS7830_RD_BMREQ, 0x0000, index, buffer, size, MCS7830_CTRL_TIMEOUT); + memcpy(data, buffer, size); + kfree(buffer); + return ret; } @@ -105,10 +113,18 @@ static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, void *data) { struct usb_device *xdev = dev->udev; int ret; + void *buffer; + + buffer = kmalloc(size, GFP_NOIO); + if (buffer == NULL) + return -ENOMEM; + + memcpy(buffer, data, size); ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ, - MCS7830_WR_BMREQ, 0x0000, index, data, + MCS7830_WR_BMREQ, 0x0000, index, buffer, size, MCS7830_CTRL_TIMEOUT); + kfree(buffer); return ret; } From 5dc306f3bd1d4cfdf79df39221b3036eab1ddcf3 Mon Sep 17 00:00:00 2001 From: Brian Cavagnolo Date: Fri, 16 Jan 2009 19:04:49 -0800 Subject: [PATCH 53/92] mac80211: decrement ref count to netdev after launching mesh discovery After launching mesh discovery in tx path, reference count was not being decremented. This was preventing module unload. Signed-off-by: Brian Cavagnolo Signed-off-by: Andrey Yurovsky Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a4af3a124cce..4278e545638f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1307,8 +1307,10 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) if (is_multicast_ether_addr(hdr->addr3)) memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); else - if (mesh_nexthop_lookup(skb, osdata)) - return 0; + if (mesh_nexthop_lookup(skb, osdata)) { + dev_put(odev); + return 0; + } if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, fwded_frames); From 7fe99c4e28ab54eada8aa456b417114e6ef21587 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Tue, 20 Jan 2009 20:26:46 +0300 Subject: [PATCH 54/92] orinoco: move kmalloc(..., GFP_KERNEL) outside spinlock in orinoco_ioctl_set_genie [ 56.923623] BUG: sleeping function called from invalid context at /home/bor/src/linux-git/mm/slub.c:1599 [ 56.923644] in_atomic(): 0, irqs_disabled(): 1, pid: 3031, name: wpa_supplicant [ 56.923656] 2 locks held by wpa_supplicant/3031: [ 56.923662] #0: (rtnl_mutex){--..}, at: [] rtnl_lock+0xf/0x20 [ 56.923703] #1: (&priv->lock){++..}, at: [] orinoco_ioctl_set_genie+0x52/0x130 [orinoco] [ 56.923782] irq event stamp: 910 [ 56.923788] hardirqs last enabled at (909): [] __kmalloc+0x7b/0x140 [ 56.923820] hardirqs last disabled at (910): [] _spin_lock_irqsave+0x19/0x80 [ 56.923847] softirqs last enabled at (880): [] __do_softirq+0xc4/0x110 [ 56.923865] softirqs last disabled at (871): [] do_softirq+0x8e/0xe0 [ 56.923895] Pid: 3031, comm: wpa_supplicant Not tainted 2.6.29-rc2-1avb #1 [ 56.923905] Call Trace: [ 56.923919] [] ? do_softirq+0x8e/0xe0 [ 56.923941] [] __might_sleep+0xd2/0x100 [ 56.923952] [] __kmalloc+0xd7/0x140 [ 56.923963] [] ? _spin_lock_irqsave+0x6a/0x80 [ 56.923981] [] ? orinoco_ioctl_set_genie+0x79/0x130 [orinoco] [ 56.923999] [] ? orinoco_ioctl_set_genie+0x52/0x130 [orinoco] [ 56.924017] [] orinoco_ioctl_set_genie+0x79/0x130 [orinoco] [ 56.924036] [] ? copy_from_user+0x35/0x130 [ 56.924061] [] ioctl_standard_call+0x196/0x380 [ 56.924085] [] ? __dev_get_by_name+0x85/0xb0 [ 56.924096] [] wext_handle_ioctl+0x14f/0x230 [ 56.924113] [] ? orinoco_ioctl_set_genie+0x0/0x130 [orinoco] [ 56.924132] [] dev_ioctl+0x495/0x570 [ 56.924155] [] ? sys_sendto+0xa5/0xd0 [ 56.924171] [] ? mark_held_locks+0x48/0x90 [ 56.924183] [] ? sock_ioctl+0x0/0x280 [ 56.924193] [] sock_ioctl+0xfd/0x280 [ 56.924203] [] ? sock_ioctl+0x0/0x280 [ 56.924235] [] vfs_ioctl+0x20/0x80 [ 56.924246] [] do_vfs_ioctl+0x72/0x570 [ 56.924257] [] ? sys_send+0x32/0x40 [ 56.924268] [] ? sys_socketcall+0x1d0/0x2a0 [ 56.924280] [] ? sysenter_exit+0xf/0x16 [ 56.924292] [] sys_ioctl+0x39/0x70 [ 56.924302] [] sysenter_do_call+0x12/0x31 Signed-off-by: Andrey Borzenkov Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco.c | 30 +++++++++++--------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index c3bb85e0251e..39eab39b065f 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -5068,33 +5068,30 @@ static int orinoco_ioctl_set_genie(struct net_device *dev, struct orinoco_private *priv = netdev_priv(dev); u8 *buf; unsigned long flags; - int err = 0; /* cut off at IEEE80211_MAX_DATA_LEN */ if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) || (wrqu->data.length && (extra == NULL))) return -EINVAL; - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - if (wrqu->data.length) { buf = kmalloc(wrqu->data.length, GFP_KERNEL); - if (buf == NULL) { - err = -ENOMEM; - goto out; - } + if (buf == NULL) + return -ENOMEM; memcpy(buf, extra, wrqu->data.length); - kfree(priv->wpa_ie); - priv->wpa_ie = buf; - priv->wpa_ie_len = wrqu->data.length; - } else { - kfree(priv->wpa_ie); - priv->wpa_ie = NULL; - priv->wpa_ie_len = 0; + } else + buf = NULL; + + if (orinoco_lock(priv, &flags) != 0) { + kfree(buf); + return -EBUSY; } + kfree(priv->wpa_ie); + priv->wpa_ie = buf; + priv->wpa_ie_len = wrqu->data.length; + if (priv->wpa_ie) { /* Looks like wl_lkm wants to check the auth alg, and * somehow pass it to the firmware. @@ -5103,9 +5100,8 @@ static int orinoco_ioctl_set_genie(struct net_device *dev, */ } -out: orinoco_unlock(priv, &flags); - return err; + return 0; } static int orinoco_ioctl_get_genie(struct net_device *dev, From 391429c18f58ae37cc2e254e408bff847f4beb21 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 18 Jan 2009 02:24:15 +0100 Subject: [PATCH 55/92] mac80211: fix slot time debug message wlan0: switched to short barker preamble (BSSID=00:01:aa:bb:cc:dd) wlan0: switched to short slot (BSSID=) should be: wlan0: switched to short barker preamble (BSSID=00:01:aa:bb:cc:dd) wlan0: switched to short slot (BSSID=00:01:aa:bb:cc:dd) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5ba721b6a399..2b890af01ba4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -620,8 +620,8 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, if (use_short_slot != bss_conf->use_short_slot) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (net_ratelimit()) { - printk(KERN_DEBUG "%s: switched to %s slot" - " (BSSID=%s)\n", + printk(KERN_DEBUG "%s: switched to %s slot time" + " (BSSID=%pM)\n", sdata->dev->name, use_short_slot ? "short" : "long", ifsta->bssid); From 7490889c105764d80af58dee5983d91a84e4aec8 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 18 Jan 2009 20:15:24 +0100 Subject: [PATCH 56/92] rt2x00: Fix TX rate short preamble detection Mac80211 provides 2 structures to handle bitrates, namely ieee80211_rate and ieee80211_tx_rate. To determine the short preamble mode for an outgoing frame, the flag IEEE80211_TX_RC_USE_SHORT_PREAMBLE must be checked on ieee80211_tx_rate and not ieee80211_rate (which rt2x00 did). This fixes a regression which was triggered in 2.6.29-rcX as reported by Chris Clayton. Signed-off-by: Ivo van Doorn Tested-By: Chris Clayton Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 746a8f36b931..0709decec9c2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -154,6 +154,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; + struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; struct ieee80211_rate *rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); const struct rt2x00_rate *hwrate; @@ -313,7 +314,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * When preamble is enabled we should set the * preamble bit for the signal. */ - if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) txdesc->signal |= 0x08; } } From 11eaea416716deebcb18383b201ba8033cbf33dc Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sun, 18 Jan 2009 23:20:58 -0500 Subject: [PATCH 57/92] orinoco: use KERN_DEBUG for link status messages KERN_INFO is too "loud" for messages that are generated by the ordinary events, such as accociation. Use of KERN_DEBUG is consistent with mac80211. Suggested by Michael Gilbert Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 39eab39b065f..45a04faa7818 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -1673,7 +1673,7 @@ static void print_linkstatus(struct net_device *dev, u16 status) s = "UNKNOWN"; } - printk(KERN_INFO "%s: New link status: %s (%04x)\n", + printk(KERN_DEBUG "%s: New link status: %s (%04x)\n", dev->name, s, status); } From 40ab73cc6c38ce93253fe8c2d7e502c948adfd13 Mon Sep 17 00:00:00 2001 From: Chr Date: Mon, 19 Jan 2009 14:30:26 +0100 Subject: [PATCH 58/92] p54: add missing break in eeprom parser This patch fixes a obvious memory leak in the eeprom parser. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 12d0717c3992..61b01930d9aa 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -451,8 +451,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) } if (err) goto err; - - } + } + break; case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); if (!priv->iq_autocal) { From 12da401e0d616f738c8b8a368d1f63f365cc78e4 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 19 Jan 2009 16:08:48 +0100 Subject: [PATCH 59/92] p54: more cryptographic accelerator fixes If we let the firmware do the data encryption, we have to remove the ICV and (M)MIC at the end of the frame before we can give it back to mac80211. Or, these data frames have a few trailing bytes on cooked monitor interfaces. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 61b01930d9aa..34561e6e816b 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -745,7 +745,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); struct p54_hdr *entry_hdr; struct p54_tx_data *entry_data; - int pad = 0; + unsigned int pad = 0, frame_len; range = (void *)info->rate_driver_data; if (range->start_addr != addr) { @@ -768,6 +768,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) __skb_unlink(entry, &priv->tx_queue); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); + frame_len = entry->len; entry_hdr = (struct p54_hdr *) entry->data; entry_data = (struct p54_tx_data *) entry_hdr->data; priv->tx_stats[entry_data->hw_queue].len--; @@ -814,15 +815,28 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) info->status.ack_signal = p54_rssi_to_dbm(dev, (int)payload->ack_rssi); - if (entry_data->key_type == P54_CRYPTO_TKIPMICHAEL) { + /* Undo all changes to the frame. */ + switch (entry_data->key_type) { + case P54_CRYPTO_TKIPMICHAEL: { u8 *iv = (u8 *)(entry_data->align + pad + - entry_data->crypt_offset); + entry_data->crypt_offset); /* Restore the original TKIP IV. */ iv[2] = iv[0]; iv[0] = iv[1]; iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */ + + frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */ + break; + } + case P54_CRYPTO_AESCCMP: + frame_len -= 8; /* remove CCMP_MIC */ + break; + case P54_CRYPTO_WEP: + frame_len -= 4; /* remove WEP_ICV */ + break; } + skb_trim(entry, frame_len); skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); ieee80211_tx_status_irqsafe(dev, entry); goto out; From e2fe154e918276e900067a9d1d3a6a963faee041 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 20 Jan 2009 00:27:57 +0100 Subject: [PATCH 60/92] p54usb: fix nasty use after free In theory, the firmware acks the received a data frame, before signaling the driver to free it again. However Artur Skawina has shown that it can happen in reverse order as well. This is very bad and could lead to memory corruptions, oopses and panics. Thanks to Artur Skawina for reporting and debugging this issue. Signed-off-by: Christian Lamparter Tested-by: Artur Skawina Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 34 ++++++++++++------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 6a6a72f6f82c..4487cc5c928b 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -144,11 +144,8 @@ static void p54u_tx_cb(struct urb *urb) struct sk_buff *skb = urb->context; struct ieee80211_hw *dev = (struct ieee80211_hw *) usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - struct p54u_priv *priv = dev->priv; - skb_pull(skb, priv->common.tx_hdr_len); - if (FREE_AFTER_TX(skb)) - p54_free_skb(dev, skb); + p54_free_skb(dev, skb); } static void p54u_tx_dummy_cb(struct urb *urb) { } @@ -230,7 +227,8 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) p54u_tx_dummy_cb, dev); usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - skb->data, skb->len, p54u_tx_cb, skb); + skb->data, skb->len, FREE_AFTER_TX(skb) ? + p54u_tx_cb : p54u_tx_dummy_cb, skb); usb_anchor_urb(addr_urb, &priv->submitted); err = usb_submit_urb(addr_urb, GFP_ATOMIC); @@ -269,28 +267,24 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb) { struct p54u_priv *priv = dev->priv; struct urb *data_urb; - struct lm87_tx_hdr *hdr; - __le32 checksum; - __le32 addr = ((struct p54_hdr *)skb->data)->req_id; + struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); data_urb = usb_alloc_urb(0, GFP_ATOMIC); if (!data_urb) return; - checksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len); - hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr)); - hdr->chksum = checksum; - hdr->device_addr = addr; + hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len); + hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id; usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - skb->data, skb->len, p54u_tx_cb, skb); + hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ? + p54u_tx_cb : p54u_tx_dummy_cb, skb); data_urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(data_urb, &priv->submitted); if (usb_submit_urb(data_urb, GFP_ATOMIC)) { usb_unanchor_urb(data_urb); - skb_pull(skb, sizeof(*hdr)); p54_free_skb(dev, skb); } usb_free_urb(data_urb); @@ -300,11 +294,9 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) { struct p54u_priv *priv = dev->priv; struct urb *int_urb, *data_urb; - struct net2280_tx_hdr *hdr; + struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); struct net2280_reg_write *reg; int err = 0; - __le32 addr = ((struct p54_hdr *) skb->data)->req_id; - __le16 len = cpu_to_le16(skb->len); reg = kmalloc(sizeof(*reg), GFP_ATOMIC); if (!reg) @@ -327,10 +319,9 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) reg->addr = cpu_to_le32(P54U_DEV_BASE); reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA); - hdr = (void *)skb_push(skb, sizeof(*hdr)); memset(hdr, 0, sizeof(*hdr)); - hdr->len = len; - hdr->device_addr = addr; + hdr->len = cpu_to_le16(skb->len); + hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id; usb_fill_bulk_urb(int_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), @@ -345,7 +336,8 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - skb->data, skb->len, p54u_tx_cb, skb); + hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ? + p54u_tx_cb : p54u_tx_dummy_cb, skb); usb_anchor_urb(int_urb, &priv->submitted); err = usb_submit_urb(int_urb, GFP_ATOMIC); From de2624966f9bc6ffafc4fd6555336fabc2854420 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Mon, 19 Jan 2009 23:39:09 +0000 Subject: [PATCH 61/92] zd1211rw: adding Sitecom WL-603 (0df6:0036) to the USB id list Giuseppe Cala (The second "a" in "Cala" should be a grave, U+00E0) reported success on zd1211-devs@lists.sourceforge.net. The chip info is: zd1211b chip 0df6:0036 v4810 high 00-0c-f6 AL2230_RF pa0 g--N- The Sitecom WL-603 is detected as a zd1211b with a AL2230 RF transceiver chip. Signed-off-by: Giuseppe Cala Signed-off-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index b5db57d2fcf5..17527f765b39 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -84,6 +84,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, From 637f883739b32746889a191f282c9ea2590ecf4f Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 19 Jan 2009 15:30:32 -0800 Subject: [PATCH 62/92] iwlwifi: return NETDEV_TX_OK from _tx ops be consistent with mac80211 drivers and return correct return code. NETDEV_TX_OK is 0, but we need to be consistent wrt formatting amongst implementations re: http://marc.info/?l=linux-wireless&m=123119327419865&w=2 Signed-off-by: Reinette Chatre Reviewed-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5da6b35cd26d..0dc8eed16404 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2482,7 +2482,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); IWL_DEBUG_MACDUMP("leave\n"); - return 0; + return NETDEV_TX_OK; } static int iwl_mac_add_interface(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 15f5655c636e..95d01984c80e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6538,7 +6538,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); IWL_DEBUG_MAC80211("leave\n"); - return 0; + return NETDEV_TX_OK; } static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, From 81f75bbf67c7a26ea1266ac93b9319bb985d588d Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:31 +0000 Subject: [PATCH 63/92] bnx2x: Reset HW before use To avoid complications, make sure that the HW is in reset (as it should be) before trying to take it out of reset. In normal flows, the HW is indeed in rest so this should have no effect Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 074374ff93f3..ed8b34665931 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -5148,12 +5148,21 @@ static void enable_blocks_attention(struct bnx2x *bp) } +static void bnx2x_reset_common(struct bnx2x *bp) +{ + /* reset_common */ + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, + 0xd3ffff7f); + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403); +} + static int bnx2x_init_common(struct bnx2x *bp) { u32 val, i; DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_FUNC(bp)); + bnx2x_reset_common(bp); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc); @@ -6640,14 +6649,6 @@ static void bnx2x_reset_port(struct bnx2x *bp) /* TODO: Close Doorbell port? */ } -static void bnx2x_reset_common(struct bnx2x *bp) -{ - /* reset_common */ - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, - 0xd3ffff7f); - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403); -} - static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code) { DP(BNX2X_MSG_MCP, "function %d reset_code %x\n", From e94d8af3da79f4bfbd22819d28ecf0602456f06f Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:36 +0000 Subject: [PATCH 64/92] bnx2x: Disable napi Calling napi disabled unconditionally at netif stop Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ed8b34665931..860b9f8ddd30 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6143,8 +6143,8 @@ static void bnx2x_netif_start(struct bnx2x *bp) static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) { bnx2x_int_disable_sync(bp, disable_hw); + bnx2x_napi_disable(bp); if (netif_running(bp->dev)) { - bnx2x_napi_disable(bp); netif_tx_disable(bp->dev); bp->dev->trans_start = jiffies; /* prevent tx timeout */ } @@ -6689,8 +6689,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bnx2x_set_storm_rx_mode(bp); bnx2x_netif_stop(bp, 1); - if (!netif_running(bp->dev)) - bnx2x_napi_disable(bp); + del_timer_sync(&bp->timer); SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb, (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); From 2dfe0e1fecb582b4aae7f2490904864c05472f3a Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:44 +0000 Subject: [PATCH 65/92] bnx2x: Handling load failures Failures on load were not handled correctly - separate the flow to handle different failures Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 168 ++++++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 73 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 860b9f8ddd30..707c4bbe46a4 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6328,7 +6328,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev); static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) { u32 load_code; - int i, rc; + int i, rc = 0; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) return -EPERM; @@ -6336,6 +6336,77 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; + if (use_inta) { + bp->num_queues = 1; + + } else { + if ((use_multi > 1) && (use_multi <= BP_MAX_QUEUES(bp))) + /* user requested number */ + bp->num_queues = use_multi; + + else if (use_multi) + bp->num_queues = min_t(u32, num_online_cpus(), + BP_MAX_QUEUES(bp)); + else + bp->num_queues = 1; + + DP(NETIF_MSG_IFUP, + "set number of queues to %d\n", bp->num_queues); + + /* if we can't use MSI-X we only need one fp, + * so try to enable MSI-X with the requested number of fp's + * and fallback to MSI or legacy INTx with one fp + */ + rc = bnx2x_enable_msix(bp); + if (rc) { + /* failed to enable MSI-X */ + bp->num_queues = 1; + if (use_multi) + BNX2X_ERR("Multi requested but failed" + " to enable MSI-X\n"); + } + } + + if (bnx2x_alloc_mem(bp)) + return -ENOMEM; + + for_each_queue(bp, i) + bnx2x_fp(bp, i, disable_tpa) = + ((bp->flags & TPA_ENABLE_FLAG) == 0); + + for_each_queue(bp, i) + netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), + bnx2x_poll, 128); + +#ifdef BNX2X_STOP_ON_ERROR + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + + fp->poll_no_work = 0; + fp->poll_calls = 0; + fp->poll_max_calls = 0; + fp->poll_complete = 0; + fp->poll_exit = 0; + } +#endif + bnx2x_napi_enable(bp); + + if (bp->flags & USING_MSIX_FLAG) { + rc = bnx2x_req_msix_irqs(bp); + if (rc) { + pci_disable_msix(bp->pdev); + goto load_error1; + } + printk(KERN_INFO PFX "%s: using MSI-X\n", bp->dev->name); + } else { + bnx2x_ack_int(bp); + rc = bnx2x_req_irq(bp); + if (rc) { + BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc); + goto load_error1; + } + } + /* Send LOAD_REQUEST command to MCP Returns the type of LOAD command: if it is the first port to be initialized @@ -6345,10 +6416,13 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); - return -EBUSY; + rc = -EBUSY; + goto load_error2; + } + if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) { + rc = -EBUSY; /* other port in diagnostic mode */ + goto load_error2; } - if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) - return -EBUSY; /* other port in diagnostic mode */ } else { int port = BP_PORT(bp); @@ -6374,66 +6448,11 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->port.pmf = 0; DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); - /* if we can't use MSI-X we only need one fp, - * so try to enable MSI-X with the requested number of fp's - * and fallback to inta with one fp - */ - if (use_inta) { - bp->num_queues = 1; - - } else { - if ((use_multi > 1) && (use_multi <= BP_MAX_QUEUES(bp))) - /* user requested number */ - bp->num_queues = use_multi; - - else if (use_multi) - bp->num_queues = min_t(u32, num_online_cpus(), - BP_MAX_QUEUES(bp)); - else - bp->num_queues = 1; - - if (bnx2x_enable_msix(bp)) { - /* failed to enable MSI-X */ - bp->num_queues = 1; - if (use_multi) - BNX2X_ERR("Multi requested but failed" - " to enable MSI-X\n"); - } - } - DP(NETIF_MSG_IFUP, - "set number of queues to %d\n", bp->num_queues); - - if (bnx2x_alloc_mem(bp)) - return -ENOMEM; - - for_each_queue(bp, i) - bnx2x_fp(bp, i, disable_tpa) = - ((bp->flags & TPA_ENABLE_FLAG) == 0); - - if (bp->flags & USING_MSIX_FLAG) { - rc = bnx2x_req_msix_irqs(bp); - if (rc) { - pci_disable_msix(bp->pdev); - goto load_error; - } - } else { - bnx2x_ack_int(bp); - rc = bnx2x_req_irq(bp); - if (rc) { - BNX2X_ERR("IRQ request failed, aborting\n"); - goto load_error; - } - } - - for_each_queue(bp, i) - netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), - bnx2x_poll, 128); - /* Initialize HW */ rc = bnx2x_init_hw(bp, load_code); if (rc) { BNX2X_ERR("HW init failed, aborting\n"); - goto load_int_disable; + goto load_error2; } /* Setup NIC internals and enable interrupts */ @@ -6445,7 +6464,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); rc = -EBUSY; - goto load_rings_free; + goto load_error3; } } @@ -6454,7 +6473,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_setup_leading(bp); if (rc) { BNX2X_ERR("Setup leading failed!\n"); - goto load_netif_stop; + goto load_error3; } if (CHIP_IS_E1H(bp)) @@ -6467,7 +6486,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) for_each_nondefault_queue(bp, i) { rc = bnx2x_setup_multi(bp, i); if (rc) - goto load_netif_stop; + goto load_error3; } if (CHIP_IS_E1(bp)) @@ -6483,18 +6502,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) case LOAD_NORMAL: /* Tx queue should be only reenabled */ netif_wake_queue(bp->dev); + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); break; case LOAD_OPEN: netif_start_queue(bp->dev); + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); - if (bp->flags & USING_MSIX_FLAG) - printk(KERN_INFO PFX "%s: using MSI-X\n", - bp->dev->name); break; case LOAD_DIAG: + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); bp->state = BNX2X_STATE_DIAG; break; @@ -6512,20 +6531,23 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) return 0; -load_netif_stop: - bnx2x_napi_disable(bp); -load_rings_free: +load_error3: + bnx2x_int_disable_sync(bp, 1); + if (!BP_NOMCP(bp)) { + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); + } + bp->port.pmf = 0; /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); -load_int_disable: - bnx2x_int_disable_sync(bp, 1); +load_error2: /* Release IRQs */ bnx2x_free_irq(bp); -load_error: +load_error1: + bnx2x_napi_disable(bp); bnx2x_free_mem(bp); - bp->port.pmf = 0; /* TBD we really need to reset the chip if we want to recover from this */ From 6eccabb301d442e6106ecc84b07a976c2816d9fb Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:48 +0000 Subject: [PATCH 66/92] bnx2x: Carrier off first call Call carrier off should not be called after register_netdev since after register netdev open can be called at any time followed by an interrupt that will set it to carrier_on and the probe will resume control and set it to off Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 707c4bbe46a4..fbd71659cca6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9827,6 +9827,8 @@ static int bnx2x_open(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); + netif_carrier_off(dev); + bnx2x_set_power_state(bp, PCI_D0); return bnx2x_nic_load(bp, LOAD_OPEN); @@ -10332,8 +10334,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, goto init_one_exit; } - netif_carrier_off(dev); - bp->common.name = board_info[ent->driver_data].name; printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx," " IRQ %d, ", dev->name, bp->common.name, From 7cde1c8b79f913a0158bae4f4c612de2cb98e7e4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:25 +0000 Subject: [PATCH 67/92] bnx2x: Calling napi_del rmmod might hang without this patch since the reference counter is not going down Signed-off-by: Yitchak Gertner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index fbd71659cca6..71fbf2dbda3b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6547,6 +6547,8 @@ load_error2: bnx2x_free_irq(bp); load_error1: bnx2x_napi_disable(bp); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); /* TBD we really need to reset the chip @@ -6855,6 +6857,8 @@ unload_error: bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; @@ -10481,6 +10485,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; From 5650d9d4cbf3898d3f9725ccad5dfca6bc086324 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:29 +0000 Subject: [PATCH 68/92] bnx2x: Missing rmb when waiting for FW response Waiting for the FW to response requires a memory barrier Signed-off-by: Michal Kalderon Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 71fbf2dbda3b..f71b8a5872b3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6622,6 +6622,7 @@ static int bnx2x_stop_leading(struct bnx2x *bp) } cnt--; msleep(1); + rmb(); /* Refresh the dsb_sp_prod */ } bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD; bp->fp[0].state = BNX2X_FP_STATE_CLOSED; From 3910c8ae44c59cebed721e33aa496f0a385b4e03 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:32 +0000 Subject: [PATCH 69/92] bnx2x: loopback test failure A link change interrupt might be queued and activated after the loopback was set and it will cause the loopback to fail. The PHY lock should be kept until the loopback test is over. That implies that the bnx2x_test_link should used within the loopback function and not bnx2x_wait_for_link since that function also takes the PHY link Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index f71b8a5872b3..d95714f780f3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -8750,18 +8750,17 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) if (loopback_mode == BNX2X_MAC_LOOPBACK) { bp->link_params.loopback_mode = LOOPBACK_BMAC; - bnx2x_acquire_phy_lock(bp); bnx2x_phy_init(&bp->link_params, &bp->link_vars); - bnx2x_release_phy_lock(bp); } else if (loopback_mode == BNX2X_PHY_LOOPBACK) { + u16 cnt = 1000; bp->link_params.loopback_mode = LOOPBACK_XGXS_10; - bnx2x_acquire_phy_lock(bp); bnx2x_phy_init(&bp->link_params, &bp->link_vars); - bnx2x_release_phy_lock(bp); /* wait until link state is restored */ - bnx2x_wait_for_link(bp, link_up); - + if (link_up) + while (cnt-- && bnx2x_test_link(&bp->link_params, + &bp->link_vars)) + msleep(10); } else return -EINVAL; @@ -8867,6 +8866,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) return BNX2X_LOOPBACK_FAILED; bnx2x_netif_stop(bp, 1); + bnx2x_acquire_phy_lock(bp); if (bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up)) { DP(NETIF_MSG_PROBE, "MAC loopback failed\n"); @@ -8878,6 +8878,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) rc |= BNX2X_PHY_LOOPBACK_FAILED; } + bnx2x_release_phy_lock(bp); bnx2x_netif_start(bp); return rc; From 5422a2257350d984094e655b2361abed51a9ddc1 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:37 +0000 Subject: [PATCH 70/92] bnx2x: Version Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d95714f780f3..4b84f6ce5ed2 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.24" -#define DRV_MODULE_RELDATE "2009/01/14" +#define DRV_MODULE_VERSION "1.45.25" +#define DRV_MODULE_RELDATE "2009/01/22" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ From 6f051069d8a2045666055e3020ae8a7dec9762e0 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 22 Jan 2009 13:51:24 -0800 Subject: [PATCH 71/92] phylib: Fix oops in suspend/resume paths Suspend/resume routines check for phydrv != NULL, but that is wrong because "phydrv" comes from container_of(drv). If drv is NULL, then container_of(drv) will return non-NULL result, and the checks won't work. The Freescale TBI PHYs are driver-less, so "drv" is NULL, and that leads to the following oops: Unable to handle kernel paging request for data at address 0xffffffe4 Faulting instruction address: 0xc0215554 Oops: Kernel access of bad area, sig: 11 [#1] [...] NIP [c0215554] mdio_bus_suspend+0x34/0x70 LR [c01cc508] suspend_device+0x258/0x2bc Call Trace: [cfad3da0] [cfad3db8] 0xcfad3db8 (unreliable) [cfad3db0] [c01cc508] suspend_device+0x258/0x2bc [cfad3dd0] [c01cc62c] dpm_suspend+0xc0/0x140 [cfad3e20] [c01cc6f4] device_suspend+0x48/0x5c [cfad3e40] [c0068dd8] suspend_devices_and_enter+0x8c/0x148 [cfad3e60] [c00690f8] enter_state+0x100/0x118 [cfad3e80] [c00691c0] state_store+0xb0/0xe4 [cfad3ea0] [c018c938] kobj_attr_store+0x24/0x3c [cfad3eb0] [c00ea9a8] flush_write_buffer+0x58/0x7c [cfad3ed0] [c00eadf0] sysfs_write_file+0x58/0xa0 [cfad3ef0] [c009e810] vfs_write+0xb4/0x16c [cfad3f10] [c009ed40] sys_write+0x4c/0x90 [cfad3f40] [c0014954] ret_from_syscall+0x0/0x38 [...] This patch fixes the issue, plus removes unneeded parentheses and fixes indentation level in mdio_bus_suspend(). Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 11adf6ed4628..811a637695ca 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -296,9 +296,8 @@ static int mdio_bus_suspend(struct device * dev, pm_message_t state) struct phy_driver *phydrv = to_phy_driver(drv); struct phy_device *phydev = to_phy_device(dev); - if ((!device_may_wakeup(phydev->dev.parent)) && - (phydrv && phydrv->suspend)) - ret = phydrv->suspend(phydev); + if (drv && phydrv->suspend && !device_may_wakeup(phydev->dev.parent)) + ret = phydrv->suspend(phydev); return ret; } @@ -310,8 +309,7 @@ static int mdio_bus_resume(struct device * dev) struct phy_driver *phydrv = to_phy_driver(drv); struct phy_device *phydev = to_phy_device(dev); - if ((!device_may_wakeup(phydev->dev.parent)) && - (phydrv && phydrv->resume)) + if (drv && phydrv->resume && !device_may_wakeup(phydev->dev.parent)) ret = phydrv->resume(phydev); return ret; From c64d2a9afbccd0aecb122d108770a407fe7b7e3f Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 22 Jan 2009 14:07:43 -0800 Subject: [PATCH 72/92] phy: Add suspend/resume support to SMSC PHYs All supported SMSC PHYs implement the standard "power down" bit 11 of BMCR, so this patch adds support using the generic genphy_{suspend,resume} functions. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index c05d38d46350..1387187543e4 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -81,6 +81,9 @@ static struct phy_driver lan83c185_driver = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE, } }; @@ -102,6 +105,9 @@ static struct phy_driver lan8187_driver = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE, } }; @@ -123,6 +129,9 @@ static struct phy_driver lan8700_driver = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE, } }; @@ -144,6 +153,9 @@ static struct phy_driver lan911x_int_driver = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE, } }; From 9c5ff5f75d0d0a1c7928ecfae3f38418b51a88e3 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 22 Jan 2009 14:52:23 -0800 Subject: [PATCH 73/92] sctp: Fix crc32c calculations on big-endian arhes. crc32c algorithm provides a byteswaped result. On little-endian arches, the result ends up in big-endian/network byte order. On big-endinan arches, the result ends up in little-endian order and needs to be byte swapped again. Thus calling cpu_to_le32 gives the right output. Tested-by: Jukka Taimisto Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/checksum.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/sctp/checksum.h b/include/net/sctp/checksum.h index b799fb21519a..2fec3c366e81 100644 --- a/include/net/sctp/checksum.h +++ b/include/net/sctp/checksum.h @@ -79,5 +79,5 @@ static inline __be32 sctp_update_cksum(__u8 *buffer, __u16 length, __be32 crc32) static inline __be32 sctp_end_cksum(__be32 crc32) { - return ~crc32; + return (__force __be32)~cpu_to_le32((__force u32)crc32); } From 6574df9a89f9f7da3a4e5cee7633d430319d3350 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 22 Jan 2009 14:52:43 -0800 Subject: [PATCH 74/92] sctp: Correctly start rtx timer on new packet transmissions. Commit 62aeaff5ccd96462b7077046357a6d7886175a57 (sctp: Start T3-RTX timer when fast retransmitting lowest TSN) introduced a regression where it was possible to forcibly restart the sctp retransmit timer at the transmission of any new chunk. This resulted in much longer timeout times and sometimes hung sctp connections. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/outqueue.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 247ebc95c1e5..bc411c896216 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -929,7 +929,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) } /* Finally, transmit new packets. */ - start_timer = 0; while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { /* RFC 2960 6.5 Every DATA chunk MUST carry a valid * stream identifier. @@ -1028,7 +1027,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) list_add_tail(&chunk->transmitted_list, &transport->transmitted); - sctp_transport_reset_timers(transport, start_timer-1); + sctp_transport_reset_timers(transport, 0); q->empty = 0; From 759af00ebef858015eb68876ac1f383bcb6a1774 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 22 Jan 2009 14:53:01 -0800 Subject: [PATCH 75/92] sctp: Properly timestamp outgoing data chunks for rtx purposes Recent changes to the retransmit code exposed a long standing bug where it was possible for a chunk to be time stamped after the retransmit timer was reset. This caused a rare situation where the retrnamist timer has expired, but nothing was marked for retrnasmission because all of timesamps on data were less then 1 rto ago. As result, the timer was never restarted since nothing was retransmitted, and this resulted in a hung association that did couldn't complete the data transfer. The solution is to timestamp the chunk when it's added to the packet for transmission purposes. After the packet is trsnmitted the rtx timer is restarted. This guarantees that when the timer expires, there will be data to retransmit. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/output.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index c3f417f7ec6e..73639355157e 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -324,14 +324,16 @@ append: switch (chunk->chunk_hdr->type) { case SCTP_CID_DATA: retval = sctp_packet_append_data(packet, chunk); + if (SCTP_XMIT_OK != retval) + goto finish; /* Disallow SACK bundling after DATA. */ packet->has_sack = 1; /* Disallow AUTH bundling after DATA */ packet->has_auth = 1; /* Let it be knows that packet has DATA in it */ packet->has_data = 1; - if (SCTP_XMIT_OK != retval) - goto finish; + /* timestamp the chunk for rtx purposes */ + chunk->sent_at = jiffies; break; case SCTP_CID_COOKIE_ECHO: packet->has_cookie_echo = 1; @@ -470,7 +472,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) } else chunk->resent = 1; - chunk->sent_at = jiffies; has_data = 1; } From ae53b5bd77719fed58086c5be60ce4f22bffe1c6 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 22 Jan 2009 14:53:23 -0800 Subject: [PATCH 76/92] sctp: Fix another socket race during accept/peeloff There is a race between sctp_rcv() and sctp_accept() where we have moved the association from the listening socket to the accepted socket, but sctp_rcv() processing cached the old socket and continues to use it. The easy solution is to check for the socket mismatch once we've grabed the socket lock. If we hit a mis-match, that means that were are currently holding the lock on the listening socket, but the association is refrencing a newly accepted socket. We need to drop the lock on the old socket and grab the lock on the new one. A more proper solution might be to create accepted sockets when the new association is established, similar to TCP. That would eliminate the race for 1-to-1 style sockets, but it would still existing for 1-to-many sockets where a user wished to peeloff an association. For now, we'll live with this easy solution as it addresses the problem. Reported-by: Michal Hocko Reported-by: Karsten Keil Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/input.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/net/sctp/input.c b/net/sctp/input.c index bf612d954d41..2e4a8646dbc3 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -249,6 +249,19 @@ int sctp_rcv(struct sk_buff *skb) */ sctp_bh_lock_sock(sk); + if (sk != rcvr->sk) { + /* Our cached sk is different from the rcvr->sk. This is + * because migrate()/accept() may have moved the association + * to a new socket and released all the sockets. So now we + * are holding a lock on the old socket while the user may + * be doing something with the new socket. Switch our veiw + * of the current sk. + */ + sctp_bh_unlock_sock(sk); + sk = rcvr->sk; + sctp_bh_lock_sock(sk); + } + if (sock_owned_by_user(sk)) { SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); sctp_add_backlog(sk, skb); From b4068a80492022848c11123bf485aff5c902c583 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 20 Jan 2009 23:11:21 +0100 Subject: [PATCH 77/92] p54usb: fix packet loss with first generation devices Artur Skawina confirmed that the first generation devices needs the same URB_ZERO_PACKET flag, in oder to finish the pending transfer properly. The second generation has been successfully fixed by "p54usb: fix random traffic stalls (LM87)" (43af18f06d5) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 4487cc5c928b..5de2ebfb28c7 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -229,6 +229,8 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), skb->data, skb->len, FREE_AFTER_TX(skb) ? p54u_tx_cb : p54u_tx_dummy_cb, skb); + addr_urb->transfer_flags |= URB_ZERO_PACKET; + data_urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(addr_urb, &priv->submitted); err = usb_submit_urb(addr_urb, GFP_ATOMIC); @@ -237,7 +239,7 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) goto out; } - usb_anchor_urb(addr_urb, &priv->submitted); + usb_anchor_urb(data_urb, &priv->submitted); err = usb_submit_urb(data_urb, GFP_ATOMIC); if (err) usb_unanchor_urb(data_urb); @@ -332,12 +334,13 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) * free what's inside the transfer_buffer after the callback routine * has completed. */ - int_urb->transfer_flags |= URB_FREE_BUFFER; + int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET; usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ? p54u_tx_cb : p54u_tx_dummy_cb, skb); + data_urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(int_urb, &priv->submitted); err = usb_submit_urb(int_urb, GFP_ATOMIC); From c338ba3ca5bef2df2082d9e8d336ff7b2880c326 Mon Sep 17 00:00:00 2001 From: "Abbas, Mohamed" Date: Wed, 21 Jan 2009 10:58:02 -0800 Subject: [PATCH 78/92] iwlwifi: fix rs_get_rate WARN_ON() In ieee80211_sta structure there is u64 supp_rates[IEEE80211_NUM_BANDS] this is filled with all support rate from assoc_resp. If we associate with G-band AP only supp_rates of G-band will be set the other band supp_rates will be set to 0. If the user type this command this will cause mac80211 to set to new channel, mac80211 does not disassociate in setting new channel, so the active band is now A-band. then in handling the new essid mac80211 will kick in the assoc steps which involve sending disassociation frame. in this mac80211 will WARN_ON sta->supp_rates[A_BAND] == 0. This fixes: http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1822 http://www.kerneloops.org/searchweek.php?search=rs_get_rate Signed-off-by: mohamed abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 14 +++++++++++--- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 9b60a0c5de5f..21c841847d88 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -638,12 +638,16 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, s8 scale_action = 0; unsigned long flags; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc, rate_mask; + u16 fc; + u16 rate_mask = 0; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); + if (sta) + rate_mask = sta->supp_rates[sband->band]; + /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); @@ -651,11 +655,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - info->control.rates[0].idx = rate_lowest_index(sband, sta); + if (!rate_mask) + info->control.rates[0].idx = + rate_lowest_index(sband, NULL); + else + info->control.rates[0].idx = + rate_lowest_index(sband, sta); return; } - rate_mask = sta->supp_rates[sband->band]; index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); if (sband->band == IEEE80211_BAND_5GHZ) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index f3f17929ca0b..27f50471aed8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -944,7 +944,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, } /* See if there's a better rate or modulation mode to try. */ - rs_rate_scale_perform(priv, hdr, sta, lq_sta); + if (sta && sta->supp_rates[sband->band]) + rs_rate_scale_perform(priv, hdr, sta, lq_sta); out: return; } @@ -2101,14 +2102,23 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = priv_sta; int rate_idx; + u64 mask_bit = 0; IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); + if (sta) + mask_bit = sta->supp_rates[sband->band]; + /* Send management frames and broadcast/multicast data using lowest * rate. */ if (!ieee80211_is_data(hdr->frame_control) || is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) { - info->control.rates[0].idx = rate_lowest_index(sband, sta); + if (!mask_bit) + info->control.rates[0].idx = + rate_lowest_index(sband, NULL); + else + info->control.rates[0].idx = + rate_lowest_index(sband, sta); return; } From 2fcbab044a3faf4d4a6e269148dd1f188303b206 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 23 Jan 2009 11:46:32 -0600 Subject: [PATCH 79/92] rtl8187: Add termination packet to prevent stall The RTL8187 and RTL8187B devices can stall unless an explicit termination packet is sent. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 6ad6bac37706..22bc07ef2f37 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -273,6 +273,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), buf, skb->len, rtl8187_tx_cb, skb); + urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(urb, &priv->anchored); rc = usb_submit_urb(urb, GFP_ATOMIC); if (rc < 0) { From 801599b0cd4c026a18fb9fce436eae4459f799a6 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 20 Jan 2009 06:14:32 +0000 Subject: [PATCH 80/92] lcs: fix compilation for !CONFIG_IP_MULTICAST drivers/s390/net/lcs.c: In function 'lcs_new_device': drivers/s390/net/lcs.c:2179: error: implicit declaration of function 'lcs_set_multicast_list' Reported-by: Kamalesh Babulal Signed-off-by: Heiko Carstens Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/lcs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index acca6678cb2b..49c3bfa1afd7 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -70,7 +70,9 @@ static char debug_buffer[255]; static void lcs_tasklet(unsigned long); static void lcs_start_kernel_thread(struct work_struct *); static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *); +#ifdef CONFIG_IP_MULTICAST static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *); +#endif /* CONFIG_IP_MULTICAST */ static int lcs_recovery(void *ptr); /** @@ -1285,6 +1287,8 @@ out: lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD); return 0; } +#endif /* CONFIG_IP_MULTICAST */ + /** * function called by net device to * handle multicast address relevant things @@ -1292,6 +1296,7 @@ out: static void lcs_set_multicast_list(struct net_device *dev) { +#ifdef CONFIG_IP_MULTICAST struct lcs_card *card; LCS_DBF_TEXT(4, trace, "setmulti"); @@ -1299,9 +1304,8 @@ lcs_set_multicast_list(struct net_device *dev) if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) schedule_work(&card->kernel_thread_starter); -} - #endif /* CONFIG_IP_MULTICAST */ +} static long lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb) From e918085aaff34086e265f825dd469926b1aec4a4 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Sun, 25 Jan 2009 18:06:26 -0800 Subject: [PATCH 81/92] virtio_net: Fix MAX_PACKET_LEN to support 802.1Q VLANs 802.1Q expanded the maximum ethernet frame size by 4 bytes for the VLAN tag. We're not taking this into account in virtio_net, which means the buffers we provide to the backend in the virtqueue RX ring aren't big enough to hold a full MTU VLAN packet. For QEMU/KVM, this results in the backend exiting with a packet truncation error. Signed-off-by: Alex Williamson Acked-by: Mark McLoughlin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 43f6523c40be..63ef2a8905fb 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -24,6 +24,7 @@ #include #include #include +#include static int napi_weight = 128; module_param(napi_weight, int, 0444); @@ -33,7 +34,7 @@ module_param(csum, bool, 0444); module_param(gso, bool, 0444); /* FIXME: MTU in config. */ -#define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN) +#define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) #define GOOD_COPY_LEN 128 struct virtnet_info From a8d694c651356ec89452e15b0189c061fb7e1cf1 Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Sun, 25 Jan 2009 20:49:14 -0800 Subject: [PATCH 82/92] af_key: initialize xfrm encap_oa Currently encap_oa is left uninitialized, so it contains garbage data which is visible to userland via Netlink. Initialize it by zeroing it out. Signed-off-by: Timo Teras Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/key/af_key.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/key/af_key.c b/net/key/af_key.c index f8bd8df5e257..7dcbde3ea7d9 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1285,6 +1285,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1]; natt->encap_dport = n_port->sadb_x_nat_t_port_port; } + memset(&natt->encap_oa, 0, sizeof(natt->encap_oa)); } err = xfrm_init_state(x); From 78272bbab895cc8f63bab5181dee55b72208e3b7 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 26 Jan 2009 12:16:26 -0800 Subject: [PATCH 83/92] e1000e: workaround hw errata There is a hardware errata in some revisions of the 82574 that needs to be worked around in the driver by setting a register bit at init. If this bit is not set A0 versions of the 82574 can generate tx hangs. Signed-off-by: Jesse Brandeburg Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 6 +++++- drivers/net/e1000e/hw.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index cf43ee743b3c..0890162953e9 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -981,11 +981,15 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) ew32(PBA_ECC, reg); } - /* PCI-Ex Control Register */ + /* PCI-Ex Control Registers */ if (hw->mac.type == e1000_82574) { reg = er32(GCR); reg |= (1 << 22); ew32(GCR, reg); + + reg = er32(GCR2); + reg |= 1; + ew32(GCR2, reg); } return; diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index f25e961c6b3b..2d4ce0492df0 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -206,6 +206,7 @@ enum e1e_registers { E1000_MANC2H = 0x05860, /* Management Control To Host - RW */ E1000_SW_FW_SYNC = 0x05B5C, /* Software-Firmware Synchronization - RW */ E1000_GCR = 0x05B00, /* PCI-Ex Control */ + E1000_GCR2 = 0x05B64, /* PCI-Ex Control #2 */ E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */ E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */ From e955281cd6afef7ad7ea11cae0ca71d78a7b2b2b Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 26 Jan 2009 12:19:23 -0800 Subject: [PATCH 84/92] networking: document "nc" in addition to "netcat" in netconsole.txt It always annoyed me that the netconsole documentation didn't give me the correct command for my distro. Update it with a command line that actually works on my Fedora install. Signed-off-by: Jesse Barnes Signed-off-by: Randy Dunlap Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- Documentation/networking/netconsole.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt index 3c2f2b328638..8d022073e3ef 100644 --- a/Documentation/networking/netconsole.txt +++ b/Documentation/networking/netconsole.txt @@ -51,7 +51,8 @@ Built-in netconsole starts immediately after the TCP stack is initialized and attempts to bring up the supplied dev at the supplied address. -The remote host can run either 'netcat -u -l -p ' or syslogd. +The remote host can run either 'netcat -u -l -p ', +'nc -l -u ' or syslogd. Dynamic reconfiguration: ======================== From 26285ba35813063ade9abd2c2eaaddba9354f587 Mon Sep 17 00:00:00 2001 From: Daniele Venzano Date: Mon, 26 Jan 2009 12:24:38 -0800 Subject: [PATCH 85/92] isdn: Fix missing ifdef in isdn_ppp The following patch fixes a warning caused by a missing ifdef in isdn_ppp.c. A function was defined, but never used if CONFIG_IPPP_FILTER was not defined. The warning was: 'get_filter' defined but not used Patch is against 2.6.28.1 Signed-off-by: Daniele Venzano Acked-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_ppp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index a3551dd0324d..aa30b5cb3513 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -431,6 +431,7 @@ set_arg(void __user *b, void *val,int len) return 0; } +#ifdef CONFIG_IPPP_FILTER static int get_filter(void __user *arg, struct sock_filter **p) { struct sock_fprog uprog; @@ -465,6 +466,7 @@ static int get_filter(void __user *arg, struct sock_filter **p) *p = code; return uprog.len; } +#endif /* CONFIG_IPPP_FILTER */ /* * ippp device ioctl From d6eb633fe680c18119346a364acff7723245e278 Mon Sep 17 00:00:00 2001 From: Matt Helsley Date: Mon, 26 Jan 2009 12:25:55 -0800 Subject: [PATCH 86/92] net: Move config NET_NS to from net/Kconfig to init/Kconfig Make NET_NS available underneath the generic Namespaces config option since all of the other namespace options are there. Signed-off-by: Matt Helsley Acked-by: Serge Hallyn Signed-off-by: David S. Miller --- init/Kconfig | 8 ++++++++ net/Kconfig | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 2af83825634e..1e948825974c 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -541,6 +541,14 @@ config PID_NS Unless you want to work with an experimental feature say N here. +config NET_NS + bool "Network namespace" + default n + depends on NAMESPACES && EXPERIMENTAL && NET + help + Allow user space to create what appear to be multiple instances + of the network stack. + config BLK_DEV_INITRD bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" depends on BROKEN || !FRV diff --git a/net/Kconfig b/net/Kconfig index bf2776018f71..cdb8fdef6c4a 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -24,14 +24,6 @@ if NET menu "Networking options" -config NET_NS - bool "Network namespace support" - default n - depends on EXPERIMENTAL && NAMESPACES - help - Allow user space to create what appear to be multiple instances - of the network stack. - config COMPAT_NET_DEV_OPS def_bool y From 3121a48d87a580f369eeb26aa0a075142274a353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Mon, 26 Jan 2009 12:30:12 -0800 Subject: [PATCH 87/92] net: Fix linux/if_frad.h's suitability for userspace. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The userspace interfaces are protected by CONFIG_* ifdefs and that of course can't work. Reported by Jaswinder Singh Rajput. Signed-off-by: Krzysztof Hałasa Signed-off-by: David S. Miller --- include/linux/if_frad.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/include/linux/if_frad.h b/include/linux/if_frad.h index 5c34240de746..60e16a551dd6 100644 --- a/include/linux/if_frad.h +++ b/include/linux/if_frad.h @@ -26,8 +26,6 @@ #include -#if defined(CONFIG_DLCI) || defined(CONFIG_DLCI_MODULE) - /* Structures and constants associated with the DLCI device driver */ struct dlci_add @@ -127,6 +125,8 @@ struct frad_conf #ifdef __KERNEL__ +#if defined(CONFIG_DLCI) || defined(CONFIG_DLCI_MODULE) + /* these are the fields of an RFC 1490 header */ struct frhdr { @@ -190,12 +190,10 @@ struct frad_local int buffer; /* current buffer for S508 firmware */ }; -#endif /* __KERNEL__ */ - #endif /* CONFIG_DLCI || CONFIG_DLCI_MODULE */ -#ifdef __KERNEL__ extern void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)); -#endif + +#endif /* __KERNEL__ */ #endif From cdff1036492ac97b4213aeab2546914a633a7de7 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 26 Jan 2009 12:34:57 -0800 Subject: [PATCH 88/92] netxen: fix vlan tso/checksum offload o set netdev->vlan_features appropriately. o fix tso descriptor initialization for vlan case. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 31 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index d854f07ef4d3..645d384fe87e 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -735,17 +735,18 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); - /* ScatterGather support */ - netdev->features = NETIF_F_SG; - netdev->features |= NETIF_F_IP_CSUM; - netdev->features |= NETIF_F_TSO; + netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + if (NX_IS_REVISION_P3(revision_id)) { - netdev->features |= NETIF_F_IPV6_CSUM; - netdev->features |= NETIF_F_TSO6; + netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); } - if (adapter->pci_using_dac) + if (adapter->pci_using_dac) { netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= NETIF_F_HIGHDMA; + } /* * Set the CRB window to invalid. If any register in window 0 is @@ -1166,6 +1167,14 @@ static bool netxen_tso_check(struct net_device *netdev, { bool tso = false; u8 opcode = TX_ETHER_PKT; + __be16 protocol = skb->protocol; + u16 flags = 0; + + if (protocol == __constant_htons(ETH_P_8021Q)) { + struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; + protocol = vh->h_vlan_encapsulated_proto; + flags = FLAGS_VLAN_TAGGED; + } if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && skb_shinfo(skb)->gso_size > 0) { @@ -1174,21 +1183,21 @@ static bool netxen_tso_check(struct net_device *netdev, desc->total_hdr_length = skb_transport_offset(skb) + tcp_hdrlen(skb); - opcode = (skb->protocol == htons(ETH_P_IPV6)) ? + opcode = (protocol == __constant_htons(ETH_P_IPV6)) ? TX_TCP_LSO6 : TX_TCP_LSO; tso = true; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 l4proto; - if (skb->protocol == htons(ETH_P_IP)) { + if (protocol == __constant_htons(ETH_P_IP)) { l4proto = ip_hdr(skb)->protocol; if (l4proto == IPPROTO_TCP) opcode = TX_TCP_PKT; else if(l4proto == IPPROTO_UDP) opcode = TX_UDP_PKT; - } else if (skb->protocol == htons(ETH_P_IPV6)) { + } else if (protocol == __constant_htons(ETH_P_IPV6)) { l4proto = ipv6_hdr(skb)->nexthdr; if (l4proto == IPPROTO_TCP) @@ -1199,7 +1208,7 @@ static bool netxen_tso_check(struct net_device *netdev, } desc->tcp_hdr_offset = skb_transport_offset(skb); desc->ip_hdr_offset = skb_network_offset(skb); - netxen_set_tx_flags_opcode(desc, 0, opcode); + netxen_set_tx_flags_opcode(desc, flags, opcode); return tso; } From 32ec803348b4d5f1353e1d7feae30880b8b3e342 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 26 Jan 2009 12:35:19 -0800 Subject: [PATCH 89/92] netxen: reduce memory footprint o reduce rx ring size from 8192 to 4096. o cut down old huge lro buffers. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 12 ++++++------ drivers/net/netxen/netxen_nic_ethtool.c | 5 ++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index c11c568fd7db..a75a31005fd3 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -146,7 +146,7 @@ #define MAX_RX_BUFFER_LENGTH 1760 #define MAX_RX_JUMBO_BUFFER_LENGTH 8062 -#define MAX_RX_LRO_BUFFER_LENGTH ((48*1024)-512) +#define MAX_RX_LRO_BUFFER_LENGTH (8062) #define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - 2) #define RX_JUMBO_DMA_MAP_LEN \ (MAX_RX_JUMBO_BUFFER_LENGTH - 2) @@ -207,11 +207,11 @@ #define MAX_CMD_DESCRIPTORS 4096 #define MAX_RCV_DESCRIPTORS 16384 -#define MAX_CMD_DESCRIPTORS_HOST (MAX_CMD_DESCRIPTORS / 4) -#define MAX_RCV_DESCRIPTORS_1G (MAX_RCV_DESCRIPTORS / 4) -#define MAX_RCV_DESCRIPTORS_10G 8192 -#define MAX_JUMBO_RCV_DESCRIPTORS 1024 -#define MAX_LRO_RCV_DESCRIPTORS 64 +#define MAX_CMD_DESCRIPTORS_HOST 1024 +#define MAX_RCV_DESCRIPTORS_1G 2048 +#define MAX_RCV_DESCRIPTORS_10G 4096 +#define MAX_JUMBO_RCV_DESCRIPTORS 512 +#define MAX_LRO_RCV_DESCRIPTORS 8 #define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS #define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS #define MAX_RCV_DESC MAX_RCV_DESCRIPTORS diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index c0bd40fcf708..0894a7be0225 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -561,7 +561,10 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) } ring->tx_pending = adapter->max_tx_desc_count; - ring->rx_max_pending = MAX_RCV_DESCRIPTORS; + if (adapter->ahw.board_type == NETXEN_NIC_GBE) + ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; + else + ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G; ring->tx_max_pending = MAX_CMD_DESCRIPTORS_HOST; ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS; ring->rx_mini_max_pending = 0; From e8b5fc514d1c7637cb4b8f77e7d8ac33ef66130c Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Mon, 26 Jan 2009 12:36:42 -0800 Subject: [PATCH 90/92] bnx2x: tx_has_work should not wait for FW The current tx_has_work waited until all packets sent by the driver are marked as completed by the FW. This is too greedy and it causes the bnx2x_poll to spin in vain. The driver should only check that all packets FW already completed are freed - only in unload flow the driver should make sure that transmit queue is empty Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 4b84f6ce5ed2..d3e7775a9ccf 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.25" -#define DRV_MODULE_RELDATE "2009/01/22" +#define DRV_MODULE_VERSION "1.45.26" +#define DRV_MODULE_RELDATE "2009/01/26" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ @@ -740,8 +740,15 @@ static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) /* Tell compiler that status block fields can change */ barrier(); tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb); - return ((fp->tx_pkt_prod != tx_cons_sb) || - (fp->tx_pkt_prod != fp->tx_pkt_cons)); + return (fp->tx_pkt_cons != tx_cons_sb); +} + +static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp) +{ + /* Tell compiler that consumer and producer can change */ + barrier(); + return (fp->tx_pkt_prod != fp->tx_pkt_cons); + } /* free skb in the packet ring at pos idx @@ -6729,7 +6736,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) cnt = 1000; smp_rmb(); - while (bnx2x_has_tx_work(fp)) { + while (bnx2x_has_tx_work_unload(fp)) { bnx2x_tx_int(fp, 1000); if (!cnt) { From 116cb42855fbd052fc8cd2ca3e06050bff762673 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 26 Jan 2009 12:37:53 -0800 Subject: [PATCH 91/92] vlan: Export symbols as non GPL symbols. In previous kernels, any kernel module could get access to the 'real-device' and the VLAN-ID for a particular VLAN. In more recent kernels, the code was restructured such that this is hard to do without accessing private .h files for any module that cannot use GPL-only symbols. Attached is a patch to once again allow non-GPL modules the ability to access the real-device and VLAN id for VLANs. Signed-off-by: Ben Greear Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- net/8021q/vlan_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 6c1323940263..e9db889d6222 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -62,13 +62,13 @@ struct net_device *vlan_dev_real_dev(const struct net_device *dev) { return vlan_dev_info(dev)->real_dev; } -EXPORT_SYMBOL_GPL(vlan_dev_real_dev); +EXPORT_SYMBOL(vlan_dev_real_dev); u16 vlan_dev_vlan_id(const struct net_device *dev) { return vlan_dev_info(dev)->vlan_id; } -EXPORT_SYMBOL_GPL(vlan_dev_vlan_id); +EXPORT_SYMBOL(vlan_dev_vlan_id); static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb) From cd1f55a5b49b74e13ed9e7bc74d005803aaa0da8 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 26 Jan 2009 14:33:23 -0800 Subject: [PATCH 92/92] gianfar: Revive VLAN support commit 77ecaf2d5a8bfd548eed3f05c1c2e6573d5de4ba ("gianfar: Fix VLAN HW feature related frame/buffer size calculation") wrongly removed priv->vlgrp assignment, and now priv->vlgrp is always NULL. This patch fixes the issue, plus fixes following sparse warning introduced by the same commit: gianfar.c:1406:13: warning: context imbalance in 'gfar_vlan_rx_register' - wrong count at exit gfar_vlan_rx_register() checks for "if (old_grp == grp)" and tries to return w/o dropping the lock. According to net/8021q/vlan.c VLAN core issues rx_register() callback: 1. In register_vlan_dev() only on a newly created group; 2. In unregister_vlan_dev() only if the group becomes empty. Thus the check in the gianfar driver isn't needed. Signed-off-by: Anton Vorontsov Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ea530673236e..3f7eab42aef1 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1423,15 +1423,11 @@ static void gfar_vlan_rx_register(struct net_device *dev, { struct gfar_private *priv = netdev_priv(dev); unsigned long flags; - struct vlan_group *old_grp; u32 tempval; spin_lock_irqsave(&priv->rxlock, flags); - old_grp = priv->vlgrp; - - if (old_grp == grp) - return; + priv->vlgrp = grp; if (grp) { /* Enable VLAN tag insertion */