From 0174b0c30a9de25dcb0d3049defcfad0c2947a36 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2011 10:03:20 +0200 Subject: [PATCH 01/47] vhost: fix signed/unsigned comparison To detect that a sequence number is done, we are doing math on unsigned integers so the result is unsigned too. Not what was intended for the <= comparison. The result is user stuck forever in flush call. Convert to int to fix this. Further, get rid of ({}) to make code clearer. Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 38244f59cdd9..ade0568c07a4 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -97,22 +97,26 @@ void vhost_poll_stop(struct vhost_poll *poll) remove_wait_queue(poll->wqh, &poll->wait); } +static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, + unsigned seq) +{ + int left; + spin_lock_irq(&dev->work_lock); + left = seq - work->done_seq; + spin_unlock_irq(&dev->work_lock); + return left <= 0; +} + static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) { unsigned seq; - int left; int flushing; spin_lock_irq(&dev->work_lock); seq = work->queue_seq; work->flushing++; spin_unlock_irq(&dev->work_lock); - wait_event(work->done, ({ - spin_lock_irq(&dev->work_lock); - left = seq - work->done_seq <= 0; - spin_unlock_irq(&dev->work_lock); - left; - })); + wait_event(work->done, vhost_work_seq_done(dev, work, seq)); spin_lock_irq(&dev->work_lock); flushing = --work->flushing; spin_unlock_irq(&dev->work_lock); From 6cae913d6c06557fee81aa8a181eafcc9a76516a Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jan 2011 13:16:37 +0530 Subject: [PATCH 02/47] ath9k_hw: Fix chip test USB devices do not require the chip test routine. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index fde978665e07..4a44f711045e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -436,9 +436,10 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) static int ath9k_hw_post_init(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); int ecode; - if (!AR_SREV_9271(ah)) { + if (common->bus_ops->ath_bus_type != ATH_USB) { if (!ath9k_hw_chip_test(ah)) return -ENODEV; } From 07422063d43612762d53fac8b6df213c96f4b1f6 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jan 2011 13:16:54 +0530 Subject: [PATCH 03/47] ath9k_hw: Fix calibration for AR9287 devices AR9287 based devices have issues with ADC gain calibration which would cause uplink throughput drops in HT40 mode. Remove ADC gain from the supported calibration algorithms. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 01880aa13e36..ea2e7d714bda 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -954,6 +954,9 @@ static void ar9002_hw_init_cal_settings(struct ath_hw *ah) &adc_dc_cal_multi_sample; } ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + + if (AR_SREV_9287(ah)) + ah->supp_cals &= ~ADC_GAIN_CAL; } } From 69bdacc8fbac32e4dc804ab13cafe3c1bbdcba9d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jan 2011 13:17:05 +0530 Subject: [PATCH 04/47] ath9k_hw: Fix thermal issue with UB94 Hardcode the output voltage of x-PA bias LDO to the lowest value for UB94. The card doesn't get too hot now. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom_def.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 088f141f2006..749a93608664 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -226,6 +226,10 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) eep->baseEepHeader.pwdclkind == 0) ah->need_an_top2_fixup = 1; + if ((common->bus_ops->ath_bus_type == ATH_USB) && + (AR_SREV_9280(ah))) + eep->modalHeader[0].xpaBiasLvl = 0; + return 0; } From 6d50192c17d4481c0e34c1ed2ae24fd7bc16e121 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jan 2011 13:43:39 +0530 Subject: [PATCH 05/47] ath9k_hw: Fix RX handling for USB devices Commit "ath9k_hw: Abort rx if hw is not coming out of full sleep in reset" uncondionally added aborting RX DMA in a HW reset, though it is a bit unclear as to why this is needed. Anyway, RX DMA is handled in the target for USB devices, and this would interfere with normal operations (scanning etc.), so fix this. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4a44f711045e..1afb8bb85756 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1214,7 +1214,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ah->txchainmask = common->tx_chainmask; ah->rxchainmask = common->rx_chainmask; - if (!ah->chip_fullsleep) { + if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) { ath9k_hw_abortpcurecv(ah); if (!ath9k_hw_stopdmarecv(ah)) { ath_dbg(common, ATH_DBG_XMIT, From 4976b4eb9d083f035aa97afec560c7e1c16c6afd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 4 Jan 2011 13:02:32 +0100 Subject: [PATCH 06/47] mac80211: add remain-on-channel docs Add documentation for the new callbacks that I forgot in the patch adding the callbacks. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5b3fd5add7a4..3ce8e1f70c06 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1753,6 +1753,16 @@ enum ieee80211_ampdu_mlme_action { * (also see nl80211.h @NL80211_ATTR_WIPHY_ANTENNA_TX). * * @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant). + * + * @remain_on_channel: Starts an off-channel period on the given channel, must + * call back to ieee80211_ready_on_channel() when on that channel. Note + * that normal channel traffic is not stopped as this is intended for hw + * offload. Frames to transmit on the off-channel channel are transmitted + * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the + * duration (which will always be non-zero) expires, the driver must call + * ieee80211_remain_on_channel_expired(). This callback may sleep. + * @cancel_remain_on_channel: Requests that an ongoing off-channel period is + * aborted before it expires. This callback may sleep. */ struct ieee80211_ops { int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); From 55de80d64545e5c4cca7f574fdf04b1f02a5f8fd Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 5 Jan 2011 01:06:21 +0530 Subject: [PATCH 07/47] ath9k_htc: Really fix packet injection The chainmask value along with other configuration has to be set on the target for packet injection. Fix this and also move the monitor interface addition before the channel set segment to ensure that the opmode is updated properly. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 37 +++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index a099b3e87ed3..1ce506f23110 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -433,6 +433,7 @@ void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, bool txok); +int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv); void ath9k_htc_station_work(struct work_struct *work); void ath9k_htc_aggr_work(struct work_struct *work); void ath9k_ani_work(struct work_struct *work);; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 845b4c938d16..f4d576bc3ccd 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -301,6 +301,16 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) priv->nstations++; + /* + * Set chainmask etc. on the target. + */ + ret = ath9k_htc_update_cap_target(priv); + if (ret) + ath_dbg(common, ATH_DBG_CONFIG, + "Failed to update capability in target\n"); + + priv->ah->is_monitoring = true; + return 0; err_vif: @@ -328,6 +338,7 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) } priv->nstations--; + priv->ah->is_monitoring = false; return 0; } @@ -419,7 +430,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, return 0; } -static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) +int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) { struct ath9k_htc_cap_target tcap; int ret; @@ -1186,6 +1197,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) } } + /* + * Monitor interface should be added before + * IEEE80211_CONF_CHANGE_CHANNEL is handled. + */ + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + if (conf->flags & IEEE80211_CONF_MONITOR) { + if (ath9k_htc_add_monitor_interface(priv)) + ath_err(common, "Failed to set monitor mode\n"); + else + ath_dbg(common, ATH_DBG_CONFIG, + "HW opmode set to Monitor mode\n"); + } + } + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; @@ -1221,16 +1246,6 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) ath_update_txpow(priv); } - if (changed & IEEE80211_CONF_CHANGE_MONITOR) { - if (conf->flags & IEEE80211_CONF_MONITOR) { - if (ath9k_htc_add_monitor_interface(priv)) - ath_err(common, "Failed to set monitor mode\n"); - else - ath_dbg(common, ATH_DBG_CONFIG, - "HW opmode set to Monitor mode\n"); - } - } - if (changed & IEEE80211_CONF_CHANGE_IDLE) { mutex_lock(&priv->htc_pm_lock); if (!priv->ps_idle) { From 610dbc980f7ad886313278ce946287f24b44cf55 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Jan 2011 22:36:44 +0100 Subject: [PATCH 08/47] mac80211: add missing docs for off-chan TX flag The flag is IEEE80211_TX_CTL_TX_OFFCHAN and I had added that in a previous patch but forgotten docs. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3ce8e1f70c06..62c0ce2d1dc8 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -337,6 +337,10 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this * frame and selects the maximum number of streams that it can use. + * @IEEE80211_TX_CTL_TX_OFFCHAN: Marks this packet to be transmitted on + * the off-channel channel when a remain-on-channel offload is done + * in hardware -- normal packets still flow and are expected to be + * handled properly by the device. * * Note: If you have to add new flags to the enumeration, then don't * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. From f52555a4b2d229079155e6642ec09afa63d10cab Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Jan 2011 22:36:45 +0100 Subject: [PATCH 09/47] cfg80211: add mesh join/leave callback docs When I made the patch to add mesh join/leave I didn't pay attention to docs because it was a proof of concept, and then when we actually did merge it I forgot -- add docs now. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index bcc9f448ec4e..1322695beb52 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1103,6 +1103,8 @@ struct cfg80211_pmksa { * @change_mpath: change a given mesh path * @get_mpath: get a mesh path for the given parameters * @dump_mpath: dump mesh path callback -- resume dump at index @idx + * @join_mesh: join the mesh network with the specified parameters + * @leave_mesh: leave the current mesh network * * @get_mesh_config: Get the current mesh configuration * From 45007fd590c6b099cec5d36ea7056b00f8b4916a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Jan 2011 22:36:46 +0100 Subject: [PATCH 10/47] nl80211: add/fix mesh docs Some mesh attribute/command docs are missing or have errors in the name so they don't match, fix all of them. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2b89b712565b..821ffb954f14 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -148,6 +148,10 @@ * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to * destination %NL80211_ATTR_MAC on the interface identified by * %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_NEW_MPATH: Create a new mesh path for the destination given by + * %NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP. + * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by + * %NL80211_ATTR_MAC. * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the * the interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC @@ -612,7 +616,7 @@ enum nl80211_commands { * consisting of a nested array. * * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). - * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link. + * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link. * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path * info given for %NL80211_CMD_GET_MPATH, nested attribute described at @@ -879,7 +883,9 @@ enum nl80211_commands { * See &enum nl80211_key_default_types. * * @NL80211_ATTR_MESH_SETUP: Optional mesh setup parameters. These cannot be - * changed once the mesh is active. + * changed once the mesh is active. + * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute + * containing attributes from &enum nl80211_meshconf_params. * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -1225,8 +1231,6 @@ enum nl80211_rate_info { * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) - * @__NL80211_STA_INFO_AFTER_LAST: internal - * @NL80211_STA_INFO_MAX: highest possible station info attribute * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute * containing info as possible, see &enum nl80211_sta_info_txrate. @@ -1236,6 +1240,11 @@ enum nl80211_rate_info { * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station) * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station) * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm) + * @NL80211_STA_INFO_LLID: the station's mesh LLID + * @NL80211_STA_INFO_PLID: the station's mesh PLID + * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station + * @__NL80211_STA_INFO_AFTER_LAST: internal + * @NL80211_STA_INFO_MAX: highest possible station info attribute */ enum nl80211_sta_info { __NL80211_STA_INFO_INVALID, @@ -1626,7 +1635,7 @@ enum nl80211_mntr_flags { * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) * that it takes for an HWMP information element to propagate across the mesh * - * @NL80211_MESHCONF_ROOTMODE: whether root mode is enabled or not + * @NL80211_MESHCONF_HWMP_ROOTMODE: whether root mode is enabled or not * * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a * source mesh point for path selection elements. @@ -1678,6 +1687,7 @@ enum nl80211_meshconf_params { * element that vendors will use to identify the path selection methods and * metrics in use. * + * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use */ enum nl80211_mesh_setup_params { From 016134eee334d51262f10ce3261976ea40a57878 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Jan 2011 22:36:47 +0100 Subject: [PATCH 11/47] mac80211: add doc short section on LED triggers Just create a section to collect the LED trigger functions and add a very short description as to what drivers should do. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/80211.tmpl | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 03641a08e275..8906648f962b 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -268,10 +268,6 @@ !Finclude/net/mac80211.h ieee80211_ops !Finclude/net/mac80211.h ieee80211_alloc_hw !Finclude/net/mac80211.h ieee80211_register_hw -!Finclude/net/mac80211.h ieee80211_get_tx_led_name -!Finclude/net/mac80211.h ieee80211_get_rx_led_name -!Finclude/net/mac80211.h ieee80211_get_assoc_led_name -!Finclude/net/mac80211.h ieee80211_get_radio_led_name !Finclude/net/mac80211.h ieee80211_unregister_hw !Finclude/net/mac80211.h ieee80211_free_hw @@ -382,6 +378,23 @@ + + LED support + + Mac80211 supports various ways of blinking LEDs. Wherever possible, + device LEDs should be exposed as LED class devices and hooked up to + the appropriate trigger, which will then be triggered appropriately + by mac80211. + +!Finclude/net/mac80211.h ieee80211_get_tx_led_name +!Finclude/net/mac80211.h ieee80211_get_rx_led_name +!Finclude/net/mac80211.h ieee80211_get_assoc_led_name +!Finclude/net/mac80211.h ieee80211_get_radio_led_name +!Finclude/net/mac80211.h ieee80211_tpt_blink +!Finclude/net/mac80211.h ieee80211_tpt_led_trigger_flags +!Finclude/net/mac80211.h ieee80211_create_tpt_led_trigger + + Hardware crypto acceleration !Pinclude/net/mac80211.h Hardware crypto acceleration From 3b5c5827d1f80ad8ae844a8b1183f59ddb90fe25 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 6 Jan 2011 23:47:52 +0100 Subject: [PATCH 12/47] p54: fix sequence no. accounting off-by-one error P54_HDR_FLAG_DATA_OUT_SEQNR is meant to tell the firmware that "the frame's sequence number has already been set by the application." Whereas IEEE80211_TX_CTL_ASSIGN_SEQ is set for frames which lack a valid sequence number and either the driver or firmware has to assign one. Yup, it's the exact opposite! Cc: Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 76b2318a7dc7..f618b9623e5a 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -618,7 +618,7 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, else *burst_possible = false; - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) + if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) *flags |= P54_HDR_FLAG_DATA_OUT_SEQNR; if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE) From ed70c6e60ee51b0fb46752ab4fd372a071da59d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=BCsch?= Date: Fri, 7 Jan 2011 19:48:05 +0100 Subject: [PATCH 13/47] ssb: Ignore dangling ethernet cores on wireless devices Some Broadcom based wireless devices contain dangling ethernet cores. This triggers the ssb probing mechanism and tries to load the b44 driver on this core. Ignore the dangling core in the ssb core scanning code to avoid access to the core and failure of b44 probing. Signed-off-by: Michael Buesch Tested-by: Larry Finger Signed-off-by: John W. Linville --- drivers/ssb/scan.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 5a0985d4ce15..29884c00c4d5 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -420,6 +420,16 @@ int ssb_bus_scan(struct ssb_bus *bus, bus->pcicore.dev = dev; #endif /* CONFIG_SSB_DRIVER_PCICORE */ break; + case SSB_DEV_ETHERNET: + if (bus->bustype == SSB_BUSTYPE_PCI) { + if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && + (bus->host_pci->device & 0xFF00) == 0x4300) { + /* This is a dangling ethernet core on a + * wireless device. Ignore it. */ + continue; + } + } + break; default: break; } From 3c4a8cc46e8cc17910020964689f3faf6bffb8ad Mon Sep 17 00:00:00 2001 From: Indan Zupancic Date: Sat, 8 Jan 2011 12:17:27 +0100 Subject: [PATCH 14/47] ipw2200: Check for -1 INTA in tasklet too. This is an attempt to fix a long standing open bug: http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=1334 The interrupt handler checks for INTA being -1, apparently that means that the hardware is gone. But the interrupt handler defers actual interrupt processing to a tasklet. By the time the tasklet is run and checks INTA again, the hardware might be gone and INTA be -1, which confuses the driver because all event bits are set. The patch applies to 2.6.37. Signed-off-by: Indan Zupancic Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 8d6ed5f6f46f..ae438ed80c2f 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -1973,6 +1973,13 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) inta = ipw_read32(priv, IPW_INTA_RW); inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); + + if (inta == 0xFFFFFFFF) { + /* Hardware disappeared */ + IPW_WARNING("TASKLET INTA == 0xFFFFFFFF\n"); + /* Only handle the cached INTA values */ + inta = 0; + } inta &= (IPW_INTA_MASK_ALL & inta_mask); /* Add any cached INTA values that need to be handled */ From 4e5518ca53be29c1ec3c00089c97bef36bfed515 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Jan 2011 12:56:05 +0100 Subject: [PATCH 15/47] hostap_cs: fix sleeping function called from invalid context pcmcia_request_irq() and pcmcia_enable_device() are intended to be called from process context (first function allocate memory with GFP_KERNEL, second take a mutex). We can not take spin lock and call them. It's safe to move spin lock after pcmcia_enable_device() as we still hold off IRQ until dev->base_addr is 0 and driver will not proceed with interrupts when is not ready. Patch resolves: https://bugzilla.redhat.com/show_bug.cgi?id=643758 Reported-and-tested-by: rbugz@biobind.com Cc: stable@kernel.org # 2.6.34+ Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_cs.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index bd8a4134edeb..2176edede39b 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -518,22 +518,21 @@ static int prism2_config(struct pcmcia_device *link) hw_priv->link = link; /* - * Make sure the IRQ handler cannot proceed until at least - * dev->base_addr is initialized. + * We enable IRQ here, but IRQ handler will not proceed + * until dev->base_addr is set below. This protect us from + * receive interrupts when driver is not initialized. */ - spin_lock_irqsave(&local->irq_init_lock, flags); - ret = pcmcia_request_irq(link, prism2_interrupt); if (ret) - goto failed_unlock; + goto failed; ret = pcmcia_enable_device(link); if (ret) - goto failed_unlock; + goto failed; + spin_lock_irqsave(&local->irq_init_lock, flags); dev->irq = link->irq; dev->base_addr = link->resource[0]->start; - spin_unlock_irqrestore(&local->irq_init_lock, flags); local->shutdown = 0; @@ -546,8 +545,6 @@ static int prism2_config(struct pcmcia_device *link) return ret; - failed_unlock: - spin_unlock_irqrestore(&local->irq_init_lock, flags); failed: kfree(hw_priv); prism2_release((u_long)link); From 5b919f833d9d60588d026ad82d17f17e8872c7a9 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 12 Jan 2011 00:34:49 -0800 Subject: [PATCH 16/47] net: ax25: fix information leak to userland harder Commit fe10ae53384e48c51996941b7720ee16995cbcb7 adds a memset() to clear the structure being sent back to userspace, but accidentally used the wrong size. Reported-by: Brad Spengler Signed-off-by: Kees Cook Cc: stable@kernel.org Signed-off-by: David S. Miller --- net/ax25/af_ax25.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index bb86d2932394..6da5daeebab7 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1392,7 +1392,7 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, ax25_cb *ax25; int err = 0; - memset(fsa, 0, sizeof(fsa)); + memset(fsa, 0, sizeof(*fsa)); lock_sock(sk); ax25 = ax25_sk(sk); From 2fc72c7b84002ffb3c66918e2a7b0ee607d8b5aa Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Wed, 12 Jan 2011 20:25:08 +0100 Subject: [PATCH 17/47] netfilter: fix compilation when conntrack is disabled but tproxy is enabled The IPv6 tproxy patches split IPv6 defragmentation off of conntrack, but failed to update the #ifdef stanzas guarding the defragmentation related fields and code in skbuff and conntrack related code in nf_defrag_ipv6.c. This patch adds the required #ifdefs so that IPv6 tproxy can truly be used without connection tracking. Original report: http://marc.info/?l=linux-netdev&m=129010118516341&w=2 Reported-by: Randy Dunlap Acked-by: Randy Dunlap Signed-off-by: KOVACS Krisztian Signed-off-by: Pablo Neira Ayuso --- include/linux/skbuff.h | 15 +++++++++++++++ include/net/netfilter/ipv6/nf_conntrack_ipv6.h | 10 ---------- include/net/netfilter/ipv6/nf_defrag_ipv6.h | 10 ++++++++++ net/core/skbuff.c | 2 ++ net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 8 +++++++- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 20ec0a64cb9f..bf221d65d9ad 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -255,6 +255,11 @@ typedef unsigned int sk_buff_data_t; typedef unsigned char *sk_buff_data_t; #endif +#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \ + defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE) +#define NET_SKBUFF_NF_DEFRAG_NEEDED 1 +#endif + /** * struct sk_buff - socket buffer * @next: Next buffer in list @@ -362,6 +367,8 @@ struct sk_buff { void (*destructor)(struct sk_buff *skb); #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct nf_conntrack *nfct; +#endif +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED struct sk_buff *nfct_reasm; #endif #ifdef CONFIG_BRIDGE_NETFILTER @@ -2057,6 +2064,8 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct) if (nfct) atomic_inc(&nfct->use); } +#endif +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED static inline void nf_conntrack_get_reasm(struct sk_buff *skb) { if (skb) @@ -2085,6 +2094,8 @@ static inline void nf_reset(struct sk_buff *skb) #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) nf_conntrack_put(skb->nfct); skb->nfct = NULL; +#endif +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED nf_conntrack_put_reasm(skb->nfct_reasm); skb->nfct_reasm = NULL; #endif @@ -2101,6 +2112,8 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src) dst->nfct = src->nfct; nf_conntrack_get(src->nfct); dst->nfctinfo = src->nfctinfo; +#endif +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED dst->nfct_reasm = src->nfct_reasm; nf_conntrack_get_reasm(src->nfct_reasm); #endif @@ -2114,6 +2127,8 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src) { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) nf_conntrack_put(dst->nfct); +#endif +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED nf_conntrack_put_reasm(dst->nfct_reasm); #endif #ifdef CONFIG_BRIDGE_NETFILTER diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h index 1ee717eb5b09..a4c993685795 100644 --- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h +++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h @@ -7,16 +7,6 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; -extern int nf_ct_frag6_init(void); -extern void nf_ct_frag6_cleanup(void); -extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); -extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, - struct net_device *in, - struct net_device *out, - int (*okfn)(struct sk_buff *)); - -struct inet_frags_ctl; - #include extern struct ctl_table nf_ct_ipv6_sysctl_table[]; diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h index 94dd54d76b48..fd79c9a1779d 100644 --- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h +++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h @@ -3,4 +3,14 @@ extern void nf_defrag_ipv6_enable(void); +extern int nf_ct_frag6_init(void); +extern void nf_ct_frag6_cleanup(void); +extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); +extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, + struct net_device *in, + struct net_device *out, + int (*okfn)(struct sk_buff *)); + +struct inet_frags_ctl; + #endif /* _NF_DEFRAG_IPV6_H */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 19d6c21220fd..d31bb36ae0dc 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -380,6 +380,8 @@ static void skb_release_head_state(struct sk_buff *skb) } #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) nf_conntrack_put(skb->nfct); +#endif +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED nf_conntrack_put_reasm(skb->nfct_reasm); #endif #ifdef CONFIG_BRIDGE_NETFILTER diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index 99abfb53bab9..97c5b21b9674 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c @@ -19,13 +19,15 @@ #include #include +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) #include #include #include #include #include -#include #include +#endif +#include #include static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, @@ -33,8 +35,10 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, { u16 zone = NF_CT_DEFAULT_ZONE; +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) if (skb->nfct) zone = nf_ct_zone((struct nf_conn *)skb->nfct); +#endif #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge && @@ -56,9 +60,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum, { struct sk_buff *reasm; +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) /* Previously seen (loopback)? */ if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) return NF_ACCEPT; +#endif reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); /* queued */ From 6c64b0c696d7a650f52d75ea59375983ec0d5e33 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 11 Jan 2011 23:31:01 +0000 Subject: [PATCH 18/47] netdev: ucc_geth: Use is_multicast_ether_addr helper Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index acbdab3d66ca..dc6cb974f25d 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2031,7 +2031,7 @@ static void ucc_geth_set_multi(struct net_device *dev) netdev_for_each_mc_addr(ha, dev) { /* Only support group multicast for now. */ - if (!(ha->addr[0] & 1)) + if (!is_multicast_ether_addr(ha->addr)) continue; /* Ask CPM to run CRC and set bit in From 12252771691aaf4935206367e0917a8f697acfcb Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 11 Jan 2011 23:30:11 +0000 Subject: [PATCH 19/47] netdev: bfin_mac: Use is_multicast_ether_addr helper Signed-off-by: Tobias Klauser Acked-by: Mike Frysinger Signed-off-by: David S. Miller --- drivers/net/bfin_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 0b9fc5173aef..fe75e7a9742e 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -1293,7 +1293,7 @@ static void bfin_mac_multicast_hash(struct net_device *dev) addrs = ha->addr; /* skip non-multicast addresses */ - if (!(*addrs & 1)) + if (!is_multicast_ether_addr(addrs)) continue; crc = ether_crc(ETH_ALEN, addrs); From 72b43d0898e97f588293b4a24b33c58c46633d81 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 12 Jan 2011 08:34:08 +0000 Subject: [PATCH 20/47] inet6: prevent network storms caused by linux IPv6 routers Linux IPv6 forwards unicast packets, which are link layer multicasts... The hole was present since day one. I was 100% this check is there, but it is not. The problem shows itself, f.e. when Microsoft Network Load Balancer runs on a network. This software resolves IPv6 unicast addresses to multicast MAC addresses. Signed-off-by: Alexey Kuznetsov Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 94b5bf132b2e..5f8d242be3f3 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -401,6 +401,9 @@ int ip6_forward(struct sk_buff *skb) goto drop; } + if (skb->pkt_type != PACKET_HOST) + goto drop; + skb_forward_csum(skb); /* From 35ab7b798a2dc4a9b19bd85833f83a19736bcfd8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 12 Jan 2011 11:21:18 +0000 Subject: [PATCH 21/47] bna: Remove unnecessary memset(,0,) kzalloc'd memory doesn't need a memset to 0. Signed-off-by: Joe Perches Acked-by: Rasesh Mody Signed-off-by: David S. Miller --- drivers/net/bna/bnad_ethtool.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c index 99be5ae91991..142d6047da27 100644 --- a/drivers/net/bna/bnad_ethtool.c +++ b/drivers/net/bna/bnad_ethtool.c @@ -275,7 +275,6 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL); if (ioc_attr) { - memset(ioc_attr, 0, sizeof(*ioc_attr)); spin_lock_irqsave(&bnad->bna_lock, flags); bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr); spin_unlock_irqrestore(&bnad->bna_lock, flags); From 838b4dc6d8a6bd83a93077ebc6873712c65bf85e Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 12 Jan 2011 15:42:32 +0000 Subject: [PATCH 22/47] sched: remove unused backlog in RED stats The RED statistics structure includes backlog field which is not set or used by any code. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/red.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/red.h b/include/net/red.h index 995108e54d9f..3319f16b3beb 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -97,7 +97,6 @@ struct red_stats { u32 forced_mark; /* Forced marks, qavg > max_thresh */ u32 pdrop; /* Drops due to queue limits */ u32 other; /* Drops due to drop() calls */ - u32 backlog; }; struct red_parms { From 3806b4f3b6115ce324b7125844f9e6acc80d34ec Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 12 Jan 2011 14:50:51 +0000 Subject: [PATCH 23/47] eth: fix new kernel-doc warning Fix new kernel-doc warning (copy-paste typo): Warning(net/ethernet/eth.c:366): No description found for parameter 'rxqs' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- net/ethernet/eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index f9d7ac924f15..44d2b42fda56 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -351,7 +351,7 @@ EXPORT_SYMBOL(ether_setup); * @sizeof_priv: Size of additional driver-private structure to be allocated * for this Ethernet device * @txqs: The number of TX queues this device has. - * @txqs: The number of RX queues this device has. + * @rxqs: The number of RX queues this device has. * * Fill in the fields of the device structure with Ethernet-generic * values. Basically does everything except registering the device. From f31e8d4982653b39fe312f9938be0f49dd9ab5fa Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 13 Jan 2011 14:19:55 +0100 Subject: [PATCH 24/47] netfilter: ctnetlink: fix loop in ctnetlink_get_conntrack() This patch fixes a loop in ctnetlink_get_conntrack() that can be triggered if you use the same socket to receive events and to perform a GET operation. Under heavy load, netlink_unicast() may return -EAGAIN, this error code is reserved in nfnetlink for the module load-on-demand. Instead, we return -ENOBUFS which is the appropriate error code that has to be propagated to user-space. Reported-by: Holger Eitzenberger Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_netlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 5cb8d3027b18..2b7eef37875c 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -972,7 +972,8 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, free: kfree_skb(skb2); out: - return err; + /* this avoids a loop in nfnetlink. */ + return err == -EAGAIN ? -ENOBUFS : err; } #ifdef CONFIG_NF_NAT_NEEDED From 976534319b0823aae29237d02e29a32ebcd5f910 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 12 Jan 2011 18:26:56 +0000 Subject: [PATCH 25/47] sfc: Make efx_get_tx_queue() an inline function Signed-off-by: Ben Hutchings --- drivers/net/sfc/efx.c | 15 +++------------ drivers/net/sfc/net_driver.h | 10 ++++++++-- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 711449c6e675..c2dc9a525dea 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1266,27 +1266,18 @@ static void efx_remove_interrupts(struct efx_nic *efx) efx->legacy_irq = 0; } -struct efx_tx_queue * -efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type) -{ - unsigned tx_channel_offset = - separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; - EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels || - type >= EFX_TXQ_TYPES); - return &efx->channel[tx_channel_offset + index]->tx_queue[type]; -} - static void efx_set_channels(struct efx_nic *efx) { struct efx_channel *channel; struct efx_tx_queue *tx_queue; - unsigned tx_channel_offset = + + efx->tx_channel_offset = separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; /* Channel pointers were set in efx_init_struct() but we now * need to clear them for TX queues in any RX-only channels. */ efx_for_each_channel(channel, efx) { - if (channel->channel - tx_channel_offset >= + if (channel->channel - efx->tx_channel_offset >= efx->n_tx_channels) { efx_for_each_channel_tx_queue(tx_queue, channel) tx_queue->channel = NULL; diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index bdce66ddf93a..28df8665256a 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -735,6 +735,7 @@ struct efx_nic { unsigned next_buffer_table; unsigned n_channels; unsigned n_rx_channels; + unsigned tx_channel_offset; unsigned n_tx_channels; unsigned int rx_buffer_len; unsigned int rx_buffer_order; @@ -929,8 +930,13 @@ efx_get_channel(struct efx_nic *efx, unsigned index) _channel = (_channel->channel + 1 < (_efx)->n_channels) ? \ (_efx)->channel[_channel->channel + 1] : NULL) -extern struct efx_tx_queue * -efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type); +static inline struct efx_tx_queue * +efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type) +{ + EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels || + type >= EFX_TXQ_TYPES); + return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type]; +} static inline struct efx_tx_queue * efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type) From 5b874e25c5c84bc45fc205407286fbe4744f4776 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 12 Jan 2011 19:11:05 +0000 Subject: [PATCH 26/47] sfc: Restore the effect of the rss_cpus module parameter Commit a4900ac ("sfc: Create multiple TX queues") accidentally disabled the rss_cpus module parameter. Signed-off-by: Ben Hutchings --- drivers/net/sfc/efx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index c2dc9a525dea..002bac743843 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1153,6 +1153,9 @@ static int efx_wanted_channels(void) int count; int cpu; + if (rss_cpus) + return rss_cpus; + if (unlikely(!zalloc_cpumask_var(&core_mask, GFP_KERNEL))) { printk(KERN_WARNING "sfc: RSS disabled due to allocation failure\n"); From 1ac9ad1394fa542ac7ae0dc943ee3cda678799fa Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 12 Jan 2011 12:13:14 +0000 Subject: [PATCH 27/47] net: remove dev_txq_stats_fold() After recent changes, (percpu stats on vlan/tunnels...), we dont need anymore per struct netdev_queue tx_bytes/tx_packets/tx_dropped counters. Only remaining users are ixgbe, sch_teql, gianfar & macvlan : 1) ixgbe can be converted to use existing tx_ring counters. 2) macvlan incremented txq->tx_dropped, it can use the dev->stats.tx_dropped counter. 3) sch_teql : almost revert ab35cd4b8f42 (Use net_device internal stats) Now we have ndo_get_stats64(), use it, even for "unsigned long" fields (No need to bring back a struct net_device_stats) 4) gianfar adds a stats structure per tx queue to hold tx_bytes/tx_packets This removes a lockdep warning (and possible lockup) in rndis gadget, calling dev_get_stats() from hard IRQ context. Ref: http://www.spinics.net/lists/netdev/msg149202.html Reported-by: Neil Jones Signed-off-by: Eric Dumazet CC: Jarek Poplawski CC: Alexander Duyck CC: Jeff Kirsher CC: Sandeep Gopalpet CC: Michal Nazarewicz Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 10 ++++------ drivers/net/gianfar.h | 10 ++++++++++ drivers/net/ixgbe/ixgbe_main.c | 23 ++++++++++++++++------- drivers/net/macvtap.c | 2 +- include/linux/netdevice.h | 5 ----- net/core/dev.c | 29 ----------------------------- net/sched/sch_teql.c | 26 +++++++++++++++++++++----- 7 files changed, 52 insertions(+), 53 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 45c4b7bfcf39..f1d4b450e797 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -433,7 +433,6 @@ static void gfar_init_mac(struct net_device *ndev) static struct net_device_stats *gfar_get_stats(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct netdev_queue *txq; unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0; unsigned long tx_packets = 0, tx_bytes = 0; int i = 0; @@ -449,9 +448,8 @@ static struct net_device_stats *gfar_get_stats(struct net_device *dev) dev->stats.rx_dropped = rx_dropped; for (i = 0; i < priv->num_tx_queues; i++) { - txq = netdev_get_tx_queue(dev, i); - tx_bytes += txq->tx_bytes; - tx_packets += txq->tx_packets; + tx_bytes += priv->tx_queue[i]->stats.tx_bytes; + tx_packets += priv->tx_queue[i]->stats.tx_packets; } dev->stats.tx_bytes = tx_bytes; @@ -2108,8 +2106,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* Update transmit stats */ - txq->tx_bytes += skb->len; - txq->tx_packets ++; + tx_queue->stats.tx_bytes += skb->len; + tx_queue->stats.tx_packets++; txbdp = txbdp_start = tx_queue->cur_tx; lstatus = txbdp->lstatus; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 68984eb88ae0..54de4135e932 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -907,12 +907,21 @@ enum { MQ_MG_MODE }; +/* + * Per TX queue stats + */ +struct tx_q_stats { + unsigned long tx_packets; + unsigned long tx_bytes; +}; + /** * struct gfar_priv_tx_q - per tx queue structure * @txlock: per queue tx spin lock * @tx_skbuff:skb pointers * @skb_curtx: to be used skb pointer * @skb_dirtytx:the last used skb pointer + * @stats: bytes/packets stats * @qindex: index of this queue * @dev: back pointer to the dev structure * @grp: back pointer to the group to which this queue belongs @@ -934,6 +943,7 @@ struct gfar_priv_tx_q { struct txbd8 *tx_bd_base; struct txbd8 *cur_tx; struct txbd8 *dirty_tx; + struct tx_q_stats stats; struct net_device *dev; struct gfar_priv_grp *grp; u16 skb_curtx; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a060610a42db..602078b84892 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -6667,8 +6667,6 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring) { - struct net_device *netdev = tx_ring->netdev; - struct netdev_queue *txq; unsigned int first; unsigned int tx_flags = 0; u8 hdr_len = 0; @@ -6765,9 +6763,6 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, /* add the ATR filter if ATR is on */ if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state)) ixgbe_atr(tx_ring, skb, tx_flags, protocol); - txq = netdev_get_tx_queue(netdev, tx_ring->queue_index); - txq->tx_bytes += skb->len; - txq->tx_packets++; ixgbe_tx_queue(tx_ring, tx_flags, count, skb->len, hdr_len); ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED); @@ -6925,8 +6920,6 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev, struct ixgbe_adapter *adapter = netdev_priv(netdev); int i; - /* accurate rx/tx bytes/packets stats */ - dev_txq_stats_fold(netdev, stats); rcu_read_lock(); for (i = 0; i < adapter->num_rx_queues; i++) { struct ixgbe_ring *ring = ACCESS_ONCE(adapter->rx_ring[i]); @@ -6943,6 +6936,22 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev, stats->rx_bytes += bytes; } } + + for (i = 0; i < adapter->num_tx_queues; i++) { + struct ixgbe_ring *ring = ACCESS_ONCE(adapter->tx_ring[i]); + u64 bytes, packets; + unsigned int start; + + if (ring) { + do { + start = u64_stats_fetch_begin_bh(&ring->syncp); + packets = ring->stats.packets; + bytes = ring->stats.bytes; + } while (u64_stats_fetch_retry_bh(&ring->syncp, start)); + stats->tx_packets += packets; + stats->tx_bytes += bytes; + } + } rcu_read_unlock(); /* following stats updated by ixgbe_watchdog_task() */ stats->multicast = netdev->stats.multicast; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 21845affea13..5933621ac3ff 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -585,7 +585,7 @@ err: rcu_read_lock_bh(); vlan = rcu_dereference(q->vlan); if (vlan) - netdev_get_tx_queue(vlan->dev, 0)->tx_dropped++; + vlan->dev->stats.tx_dropped++; rcu_read_unlock_bh(); return err; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index be4957cf6511..d971346b0340 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -520,9 +520,6 @@ struct netdev_queue { * please use this field instead of dev->trans_start */ unsigned long trans_start; - u64 tx_bytes; - u64 tx_packets; - u64 tx_dropped; } ____cacheline_aligned_in_smp; static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) @@ -2265,8 +2262,6 @@ extern void dev_load(struct net *net, const char *name); extern void dev_mcast_init(void); extern struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, struct rtnl_link_stats64 *storage); -extern void dev_txq_stats_fold(const struct net_device *dev, - struct rtnl_link_stats64 *stats); extern int netdev_max_backlog; extern int netdev_tstamp_prequeue; diff --git a/net/core/dev.c b/net/core/dev.c index a3ef808b5e36..83507c265e48 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5523,34 +5523,6 @@ void netdev_run_todo(void) } } -/** - * dev_txq_stats_fold - fold tx_queues stats - * @dev: device to get statistics from - * @stats: struct rtnl_link_stats64 to hold results - */ -void dev_txq_stats_fold(const struct net_device *dev, - struct rtnl_link_stats64 *stats) -{ - u64 tx_bytes = 0, tx_packets = 0, tx_dropped = 0; - unsigned int i; - struct netdev_queue *txq; - - for (i = 0; i < dev->num_tx_queues; i++) { - txq = netdev_get_tx_queue(dev, i); - spin_lock_bh(&txq->_xmit_lock); - tx_bytes += txq->tx_bytes; - tx_packets += txq->tx_packets; - tx_dropped += txq->tx_dropped; - spin_unlock_bh(&txq->_xmit_lock); - } - if (tx_bytes || tx_packets || tx_dropped) { - stats->tx_bytes = tx_bytes; - stats->tx_packets = tx_packets; - stats->tx_dropped = tx_dropped; - } -} -EXPORT_SYMBOL(dev_txq_stats_fold); - /* Convert net_device_stats to rtnl_link_stats64. They have the same * fields in the same order, with only the type differing. */ @@ -5594,7 +5566,6 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev)); } else { netdev_stats_to_stats64(storage, &dev->stats); - dev_txq_stats_fold(dev, storage); } storage->rx_dropped += atomic_long_read(&dev->rx_dropped); return storage; diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index af9360d1f6eb..84ce48eadff4 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -59,6 +59,10 @@ struct teql_master struct net_device *dev; struct Qdisc *slaves; struct list_head master_list; + unsigned long tx_bytes; + unsigned long tx_packets; + unsigned long tx_errors; + unsigned long tx_dropped; }; struct teql_sched_data @@ -274,7 +278,6 @@ static inline int teql_resolve(struct sk_buff *skb, static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) { struct teql_master *master = netdev_priv(dev); - struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); struct Qdisc *start, *q; int busy; int nores; @@ -314,8 +317,8 @@ restart: __netif_tx_unlock(slave_txq); master->slaves = NEXT_SLAVE(q); netif_wake_queue(dev); - txq->tx_packets++; - txq->tx_bytes += length; + master->tx_packets++; + master->tx_bytes += length; return NETDEV_TX_OK; } __netif_tx_unlock(slave_txq); @@ -342,10 +345,10 @@ restart: netif_stop_queue(dev); return NETDEV_TX_BUSY; } - dev->stats.tx_errors++; + master->tx_errors++; drop: - txq->tx_dropped++; + master->tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -398,6 +401,18 @@ static int teql_master_close(struct net_device *dev) return 0; } +static struct rtnl_link_stats64 *teql_master_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct teql_master *m = netdev_priv(dev); + + stats->tx_packets = m->tx_packets; + stats->tx_bytes = m->tx_bytes; + stats->tx_errors = m->tx_errors; + stats->tx_dropped = m->tx_dropped; + return stats; +} + static int teql_master_mtu(struct net_device *dev, int new_mtu) { struct teql_master *m = netdev_priv(dev); @@ -422,6 +437,7 @@ static const struct net_device_ops teql_netdev_ops = { .ndo_open = teql_master_open, .ndo_stop = teql_master_close, .ndo_start_xmit = teql_master_xmit, + .ndo_get_stats64 = teql_master_stats64, .ndo_change_mtu = teql_master_mtu, }; From 78d07369462e9feeaa5db301b0aa70e9dcb40b48 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 13 Jan 2011 11:51:03 +0000 Subject: [PATCH 28/47] ipsec: update MAX_AH_AUTH_LEN to support sha512 icv_truncbits is set to 256 for sha512, so update MAX_AH_AUTH_LEN to 64. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/ah.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/ah.h b/include/net/ah.h index be7798dea6f4..ca95b98969dd 100644 --- a/include/net/ah.h +++ b/include/net/ah.h @@ -4,7 +4,7 @@ #include /* This is the maximum truncated ICV length that we know of. */ -#define MAX_AH_AUTH_LEN 16 +#define MAX_AH_AUTH_LEN 64 struct crypto_ahash; From f767b6df8a796f901b2bd595ae22234636be4124 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 12 Jan 2011 18:08:04 +0000 Subject: [PATCH 29/47] netdev: bfin_mac: Remove is_multicast_ether_addr use in netdev_for_each_mc_addr Remove code that has no effect. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/bfin_mac.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index fe75e7a9742e..22abfb39d813 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -1284,19 +1284,12 @@ static void bfin_mac_multicast_hash(struct net_device *dev) { u32 emac_hashhi, emac_hashlo; struct netdev_hw_addr *ha; - char *addrs; u32 crc; emac_hashhi = emac_hashlo = 0; netdev_for_each_mc_addr(ha, dev) { - addrs = ha->addr; - - /* skip non-multicast addresses */ - if (!is_multicast_ether_addr(addrs)) - continue; - - crc = ether_crc(ETH_ALEN, addrs); + crc = ether_crc(ETH_ALEN, ha->addr); crc >>= 26; if (crc & 0x20) From e84f885ebfb43b1ebb1481ee8bb2018743f947e9 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 13 Jan 2011 10:25:20 +0000 Subject: [PATCH 30/47] vxge: Remember to release firmware after upgrading firmware Regardless of whether the firmware update being performed by vxge_fw_upgrade() is a success or not we must still remember to always release_firmware() before returning. Signed-off-by: Jesper Juhl Acked-by: Ram Vepa Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index 1ac9b568f1b0..c81a6512c683 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -4120,6 +4120,7 @@ int vxge_fw_upgrade(struct vxgedev *vdev, char *fw_name, int override) "hotplug event.\n"); out: + release_firmware(fw); return ret; } From 9e56790ad31d72a5a44142af462d047c0c897b29 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 13 Jan 2011 11:40:11 +0000 Subject: [PATCH 31/47] USB CDC NCM: Don't deref NULL in cdc_ncm_rx_fixup() and don't use uninitialized variable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skb_clone() dynamically allocates memory and may fail. If it does it returns NULL. This means we'll dereference a NULL pointer in drivers/net/usb/cdc_ncm.c::cdc_ncm_rx_fixup(). As far as I can tell, the proper way to deal with this is simply to goto the error label. Furthermore gcc complains that 'skb' may be used uninitialized: drivers/net/usb/cdc_ncm.c: In function ‘cdc_ncm_rx_fixup’: drivers/net/usb/cdc_ncm.c:922:18: warning: ‘skb’ may be used uninitialized in this function and I believe it is right. On the line where we pr_debug("invalid frame detected (ignored)" ... we are using the local variable 'skb' but nothing has ever been assigned to that variable yet. I believe the correct fix for that is to use 'skb_in' instead. Signed-off-by: Jesper Juhl Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ncm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 593c104ab199..d776c4a8d3c1 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1021,13 +1021,15 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) (temp > CDC_NCM_MAX_DATAGRAM_SIZE) || (temp < ETH_HLEN)) { pr_debug("invalid frame detected (ignored)" "offset[%u]=%u, length=%u, skb=%p\n", - x, offset, temp, skb); + x, offset, temp, skb_in); if (!x) goto error; break; } else { skb = skb_clone(skb_in, GFP_ATOMIC); + if (!skb) + goto error; skb->len = temp; skb->data = ((u8 *)skb_in->data) + offset; skb_set_tail_pointer(skb, temp); From c3d2a7309c95021f143c94a16ea9becc0c9b9d23 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 13 Jan 2011 07:50:14 +0000 Subject: [PATCH 32/47] ks8695net: Disable non-working ethtool operations Some ethtool operations can only be implemented for the WAN port, and not all such operations are allowed to return an error code such as -EOPNOTSUPP. Therefore, define two separate ethtool_ops structures for WAN and non-WAN ports; simplify and rename the WAN-only functions. This is completely untested as I don't have an ARM build environment. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/arm/ks8695net.c | 274 +++++++++++++----------------------- 1 file changed, 95 insertions(+), 179 deletions(-) diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 54c6d849cf25..8820fcdca10b 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -854,12 +854,12 @@ ks8695_set_msglevel(struct net_device *ndev, u32 value) } /** - * ks8695_get_settings - Get device-specific settings. + * ks8695_wan_get_settings - Get device-specific settings. * @ndev: The network device to read settings from * @cmd: The ethtool structure to read into */ static int -ks8695_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) +ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; @@ -870,69 +870,50 @@ ks8695_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) SUPPORTED_TP | SUPPORTED_MII); cmd->transceiver = XCVR_INTERNAL; - /* Port specific extras */ - switch (ksp->dtype) { - case KS8695_DTYPE_HPNA: - cmd->phy_address = 0; - /* not supported for HPNA */ + cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; + cmd->port = PORT_MII; + cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause); + cmd->phy_address = 0; + + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + if ((ctrl & WMC_WAND) == 0) { + /* auto-negotiation is enabled */ + cmd->advertising |= ADVERTISED_Autoneg; + if (ctrl & WMC_WANA100F) + cmd->advertising |= ADVERTISED_100baseT_Full; + if (ctrl & WMC_WANA100H) + cmd->advertising |= ADVERTISED_100baseT_Half; + if (ctrl & WMC_WANA10F) + cmd->advertising |= ADVERTISED_10baseT_Full; + if (ctrl & WMC_WANA10H) + cmd->advertising |= ADVERTISED_10baseT_Half; + if (ctrl & WMC_WANAP) + cmd->advertising |= ADVERTISED_Pause; + cmd->autoneg = AUTONEG_ENABLE; + + cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10; + cmd->duplex = (ctrl & WMC_WDS) ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + /* auto-negotiation is disabled */ cmd->autoneg = AUTONEG_DISABLE; - /* BUG: Erm, dtype hpna implies no phy regs */ - /* - ctrl = readl(KS8695_MISC_VA + KS8695_HMC); - cmd->speed = (ctrl & HMC_HSS) ? SPEED_100 : SPEED_10; - cmd->duplex = (ctrl & HMC_HDS) ? DUPLEX_FULL : DUPLEX_HALF; - */ - return -EOPNOTSUPP; - case KS8695_DTYPE_WAN: - cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; - cmd->port = PORT_MII; - cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause); - cmd->phy_address = 0; - - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - if ((ctrl & WMC_WAND) == 0) { - /* auto-negotiation is enabled */ - cmd->advertising |= ADVERTISED_Autoneg; - if (ctrl & WMC_WANA100F) - cmd->advertising |= ADVERTISED_100baseT_Full; - if (ctrl & WMC_WANA100H) - cmd->advertising |= ADVERTISED_100baseT_Half; - if (ctrl & WMC_WANA10F) - cmd->advertising |= ADVERTISED_10baseT_Full; - if (ctrl & WMC_WANA10H) - cmd->advertising |= ADVERTISED_10baseT_Half; - if (ctrl & WMC_WANAP) - cmd->advertising |= ADVERTISED_Pause; - cmd->autoneg = AUTONEG_ENABLE; - - cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10; - cmd->duplex = (ctrl & WMC_WDS) ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - /* auto-negotiation is disabled */ - cmd->autoneg = AUTONEG_DISABLE; - - cmd->speed = (ctrl & WMC_WANF100) ? - SPEED_100 : SPEED_10; - cmd->duplex = (ctrl & WMC_WANFF) ? - DUPLEX_FULL : DUPLEX_HALF; - } - break; - case KS8695_DTYPE_LAN: - return -EOPNOTSUPP; + cmd->speed = (ctrl & WMC_WANF100) ? + SPEED_100 : SPEED_10; + cmd->duplex = (ctrl & WMC_WANFF) ? + DUPLEX_FULL : DUPLEX_HALF; } return 0; } /** - * ks8695_set_settings - Set device-specific settings. + * ks8695_wan_set_settings - Set device-specific settings. * @ndev: The network device to configure * @cmd: The settings to configure */ static int -ks8695_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) +ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; @@ -956,171 +937,99 @@ ks8695_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) ADVERTISED_100baseT_Full)) == 0) return -EINVAL; - switch (ksp->dtype) { - case KS8695_DTYPE_HPNA: - /* HPNA does not support auto-negotiation. */ - return -EINVAL; - case KS8695_DTYPE_WAN: - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H | - WMC_WANA10F | WMC_WANA10H); - if (cmd->advertising & ADVERTISED_100baseT_Full) - ctrl |= WMC_WANA100F; - if (cmd->advertising & ADVERTISED_100baseT_Half) - ctrl |= WMC_WANA100H; - if (cmd->advertising & ADVERTISED_10baseT_Full) - ctrl |= WMC_WANA10F; - if (cmd->advertising & ADVERTISED_10baseT_Half) - ctrl |= WMC_WANA10H; - - /* force a re-negotiation */ - ctrl |= WMC_WANR; - writel(ctrl, ksp->phyiface_regs + KS8695_WMC); - break; - case KS8695_DTYPE_LAN: - return -EOPNOTSUPP; - } + ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H | + WMC_WANA10F | WMC_WANA10H); + if (cmd->advertising & ADVERTISED_100baseT_Full) + ctrl |= WMC_WANA100F; + if (cmd->advertising & ADVERTISED_100baseT_Half) + ctrl |= WMC_WANA100H; + if (cmd->advertising & ADVERTISED_10baseT_Full) + ctrl |= WMC_WANA10F; + if (cmd->advertising & ADVERTISED_10baseT_Half) + ctrl |= WMC_WANA10H; + /* force a re-negotiation */ + ctrl |= WMC_WANR; + writel(ctrl, ksp->phyiface_regs + KS8695_WMC); } else { - switch (ksp->dtype) { - case KS8695_DTYPE_HPNA: - /* BUG: dtype_hpna implies no phy registers */ - /* - ctrl = __raw_readl(KS8695_MISC_VA + KS8695_HMC); + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - ctrl &= ~(HMC_HSS | HMC_HDS); - if (cmd->speed == SPEED_100) - ctrl |= HMC_HSS; - if (cmd->duplex == DUPLEX_FULL) - ctrl |= HMC_HDS; + /* disable auto-negotiation */ + ctrl |= WMC_WAND; + ctrl &= ~(WMC_WANF100 | WMC_WANFF); - __raw_writel(ctrl, KS8695_MISC_VA + KS8695_HMC); - */ - return -EOPNOTSUPP; - case KS8695_DTYPE_WAN: - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + if (cmd->speed == SPEED_100) + ctrl |= WMC_WANF100; + if (cmd->duplex == DUPLEX_FULL) + ctrl |= WMC_WANFF; - /* disable auto-negotiation */ - ctrl |= WMC_WAND; - ctrl &= ~(WMC_WANF100 | WMC_WANFF); - - if (cmd->speed == SPEED_100) - ctrl |= WMC_WANF100; - if (cmd->duplex == DUPLEX_FULL) - ctrl |= WMC_WANFF; - - writel(ctrl, ksp->phyiface_regs + KS8695_WMC); - break; - case KS8695_DTYPE_LAN: - return -EOPNOTSUPP; - } + writel(ctrl, ksp->phyiface_regs + KS8695_WMC); } return 0; } /** - * ks8695_nwayreset - Restart the autonegotiation on the port. + * ks8695_wan_nwayreset - Restart the autonegotiation on the port. * @ndev: The network device to restart autoneotiation on */ static int -ks8695_nwayreset(struct net_device *ndev) +ks8695_wan_nwayreset(struct net_device *ndev) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; - switch (ksp->dtype) { - case KS8695_DTYPE_HPNA: - /* No phy means no autonegotiation on hpna */ - return -EINVAL; - case KS8695_DTYPE_WAN: - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - if ((ctrl & WMC_WAND) == 0) - writel(ctrl | WMC_WANR, - ksp->phyiface_regs + KS8695_WMC); - else - /* auto-negotiation not enabled */ - return -EINVAL; - break; - case KS8695_DTYPE_LAN: - return -EOPNOTSUPP; - } + if ((ctrl & WMC_WAND) == 0) + writel(ctrl | WMC_WANR, + ksp->phyiface_regs + KS8695_WMC); + else + /* auto-negotiation not enabled */ + return -EINVAL; return 0; } /** - * ks8695_get_link - Retrieve link status of network interface + * ks8695_wan_get_link - Retrieve link status of network interface * @ndev: The network interface to retrive the link status of. */ static u32 -ks8695_get_link(struct net_device *ndev) +ks8695_wan_get_link(struct net_device *ndev) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; - switch (ksp->dtype) { - case KS8695_DTYPE_HPNA: - /* HPNA always has link */ - return 1; - case KS8695_DTYPE_WAN: - /* WAN we can read the PHY for */ - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - return ctrl & WMC_WLS; - case KS8695_DTYPE_LAN: - return -EOPNOTSUPP; - } - return 0; + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + return ctrl & WMC_WLS; } /** - * ks8695_get_pause - Retrieve network pause/flow-control advertising + * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising * @ndev: The device to retrieve settings from * @param: The structure to fill out with the information */ static void -ks8695_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param) +ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param) { struct ks8695_priv *ksp = netdev_priv(ndev); u32 ctrl; - switch (ksp->dtype) { - case KS8695_DTYPE_HPNA: - /* No phy link on hpna to configure */ - return; - case KS8695_DTYPE_WAN: - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); + ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - /* advertise Pause */ - param->autoneg = (ctrl & WMC_WANAP); + /* advertise Pause */ + param->autoneg = (ctrl & WMC_WANAP); - /* current Rx Flow-control */ - ctrl = ks8695_readreg(ksp, KS8695_DRXC); - param->rx_pause = (ctrl & DRXC_RFCE); + /* current Rx Flow-control */ + ctrl = ks8695_readreg(ksp, KS8695_DRXC); + param->rx_pause = (ctrl & DRXC_RFCE); - /* current Tx Flow-control */ - ctrl = ks8695_readreg(ksp, KS8695_DTXC); - param->tx_pause = (ctrl & DTXC_TFCE); - break; - case KS8695_DTYPE_LAN: - /* The LAN's "phy" is a direct-attached switch */ - return; - } -} - -/** - * ks8695_set_pause - Configure pause/flow-control - * @ndev: The device to configure - * @param: The pause parameters to set - * - * TODO: Implement this - */ -static int -ks8695_set_pause(struct net_device *ndev, struct ethtool_pauseparam *param) -{ - return -EOPNOTSUPP; + /* current Tx Flow-control */ + ctrl = ks8695_readreg(ksp, KS8695_DTXC); + param->tx_pause = (ctrl & DTXC_TFCE); } /** @@ -1140,12 +1049,17 @@ ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) static const struct ethtool_ops ks8695_ethtool_ops = { .get_msglevel = ks8695_get_msglevel, .set_msglevel = ks8695_set_msglevel, - .get_settings = ks8695_get_settings, - .set_settings = ks8695_set_settings, - .nway_reset = ks8695_nwayreset, - .get_link = ks8695_get_link, - .get_pauseparam = ks8695_get_pause, - .set_pauseparam = ks8695_set_pause, + .get_drvinfo = ks8695_get_drvinfo, +}; + +static const struct ethtool_ops ks8695_wan_ethtool_ops = { + .get_msglevel = ks8695_get_msglevel, + .set_msglevel = ks8695_set_msglevel, + .get_settings = ks8695_wan_get_settings, + .set_settings = ks8695_wan_set_settings, + .nway_reset = ks8695_wan_nwayreset, + .get_link = ks8695_wan_get_link, + .get_pauseparam = ks8695_wan_get_pause, .get_drvinfo = ks8695_get_drvinfo, }; @@ -1541,7 +1455,6 @@ ks8695_probe(struct platform_device *pdev) /* driver system setup */ ndev->netdev_ops = &ks8695_netdev_ops; - SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); ndev->watchdog_timeo = msecs_to_jiffies(watchdog); netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT); @@ -1608,12 +1521,15 @@ ks8695_probe(struct platform_device *pdev) if (ksp->phyiface_regs && ksp->link_irq == -1) { ks8695_init_switch(ksp); ksp->dtype = KS8695_DTYPE_LAN; + SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); } else if (ksp->phyiface_regs && ksp->link_irq != -1) { ks8695_init_wan_phy(ksp); ksp->dtype = KS8695_DTYPE_WAN; + SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops); } else { /* No initialisation since HPNA does not have a PHY */ ksp->dtype = KS8695_DTYPE_HPNA; + SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); } /* And bring up the net_device with the net core */ From 5cd8a77df3e9916069787365a32918caa371fc16 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 13 Jan 2011 07:52:51 +0000 Subject: [PATCH 33/47] ks8695net: Use default implementation of ethtool_ops::get_link This is completely untested as I don't have an ARM build environment. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/arm/ks8695net.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 8820fcdca10b..62d6f88cbab5 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -993,20 +993,6 @@ ks8695_wan_nwayreset(struct net_device *ndev) return 0; } -/** - * ks8695_wan_get_link - Retrieve link status of network interface - * @ndev: The network interface to retrive the link status of. - */ -static u32 -ks8695_wan_get_link(struct net_device *ndev) -{ - struct ks8695_priv *ksp = netdev_priv(ndev); - u32 ctrl; - - ctrl = readl(ksp->phyiface_regs + KS8695_WMC); - return ctrl & WMC_WLS; -} - /** * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising * @ndev: The device to retrieve settings from @@ -1058,7 +1044,7 @@ static const struct ethtool_ops ks8695_wan_ethtool_ops = { .get_settings = ks8695_wan_get_settings, .set_settings = ks8695_wan_set_settings, .nway_reset = ks8695_wan_nwayreset, - .get_link = ks8695_wan_get_link, + .get_link = ethtool_op_get_link, .get_pauseparam = ks8695_wan_get_pause, .get_drvinfo = ks8695_get_drvinfo, }; From 51e7eed79c41180919ff94942895ba38467d9ad4 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 12 Jan 2011 22:14:56 +0000 Subject: [PATCH 34/47] etherdevice.h: Add is_unicast_ether_addr function From a check for !is_multicast_ether_addr it is not always obvious that we're checking for a unicast address. So add this helper function to make those code paths easier to read. Signed-off-by: Tobias Klauser Acked-by: Chris Metcalf Signed-off-by: David S. Miller --- include/linux/etherdevice.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index bec8b82889bf..ab68f785fd19 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -98,6 +98,17 @@ static inline int is_broadcast_ether_addr(const u8 *addr) return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; } +/** + * is_unicast_ether_addr - Determine if the Ethernet address is unicast + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is a unicast address. + */ +static inline int is_unicast_ether_addr(const u8 *addr) +{ + return !is_multicast_ether_addr(addr); +} + /** * is_valid_ether_addr - Determine if the given Ethernet address is valid * @addr: Pointer to a six-byte array containing the Ethernet address From d0f49157d1ce02671a450b566a12ff19baed6c19 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 12 Jan 2011 22:15:08 +0000 Subject: [PATCH 35/47] netdev: tilepro: Use is_unicast_ether_addr helper Use is_unicast_ether_addr from linux/etherdevice.h instead of custom macros. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/tile/tilepro.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/net/tile/tilepro.c b/drivers/net/tile/tilepro.c index 0e6bac5ec65b..7cb301da7474 100644 --- a/drivers/net/tile/tilepro.c +++ b/drivers/net/tile/tilepro.c @@ -142,14 +142,6 @@ MODULE_AUTHOR("Tilera"); MODULE_LICENSE("GPL"); - -#define IS_MULTICAST(mac_addr) \ - (((u8 *)(mac_addr))[0] & 0x01) - -#define IS_BROADCAST(mac_addr) \ - (((u16 *)(mac_addr))[0] == 0xffff) - - /* * Queue of incoming packets for a specific cpu and device. * @@ -795,7 +787,7 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index) /* * FIXME: Implement HW multicast filter. */ - if (!IS_MULTICAST(buf) && !IS_BROADCAST(buf)) { + if (is_unicast_ether_addr(buf)) { /* Filter packets not for our address. */ const u8 *mine = dev->dev_addr; filter = compare_ether_addr(mine, buf); From f1e02ed109df5f99abf942b8ccc99960cb09dd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fran=C3=A7ois=20romieu?= Date: Thu, 13 Jan 2011 13:07:53 +0000 Subject: [PATCH 36/47] r8169: keep firmware in memory. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The firmware agent is not available during resume. Loading the firmware during open() (see eee3a96c6368f47df8df5bd4ed1843600652b337) is not enough. close() is run during resume through rtl8169_reset_task(), whence the mildly natural release of firmware in the driver removal method instead. It will help with http://bugs.debian.org/609538. It will not avoid the 60 seconds delay when: - there is no firmware - the driver is loaded and the device is not up before a suspend/resume Signed-off-by: Francois Romieu Tested-by: Jarek Kamiński Cc: Hayes Cc: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/r8169.c | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index bb8645ab247c..bde7d61f1930 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -554,6 +554,8 @@ struct rtl8169_private { struct mii_if_info mii; struct rtl8169_counters counters; u32 saved_wolopts; + + const struct firmware *fw; }; MODULE_AUTHOR("Realtek and the Linux r8169 crew "); @@ -1766,6 +1768,29 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw) } } +static void rtl_release_firmware(struct rtl8169_private *tp) +{ + release_firmware(tp->fw); + tp->fw = NULL; +} + +static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name) +{ + const struct firmware **fw = &tp->fw; + int rc = !*fw; + + if (rc) { + rc = request_firmware(fw, fw_name, &tp->pci_dev->dev); + if (rc < 0) + goto out; + } + + /* TODO: release firmware once rtl_phy_write_fw signals failures. */ + rtl_phy_write_fw(tp, *fw); +out: + return rc; +} + static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@ -2139,7 +2164,6 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) { 0x0d, 0xf880 } }; void __iomem *ioaddr = tp->mmio_addr; - const struct firmware *fw; rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); @@ -2203,11 +2227,8 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x001b); - if (rtl_readphy(tp, 0x06) == 0xbf00 && - request_firmware(&fw, FIRMWARE_8168D_1, &tp->pci_dev->dev) == 0) { - rtl_phy_write_fw(tp, fw); - release_firmware(fw); - } else { + if ((rtl_readphy(tp, 0x06) != 0xbf00) || + (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) { netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); } @@ -2257,7 +2278,6 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) { 0x0d, 0xf880 } }; void __iomem *ioaddr = tp->mmio_addr; - const struct firmware *fw; rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); @@ -2312,11 +2332,8 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x001b); - if (rtl_readphy(tp, 0x06) == 0xb300 && - request_firmware(&fw, FIRMWARE_8168D_2, &tp->pci_dev->dev) == 0) { - rtl_phy_write_fw(tp, fw); - release_firmware(fw); - } else { + if ((rtl_readphy(tp, 0x06) != 0xb300) || + (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) { netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); } @@ -3200,6 +3217,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) cancel_delayed_work_sync(&tp->task); + rtl_release_firmware(tp); + unregister_netdev(dev); if (pci_dev_run_wake(pdev)) From 4c11b8adbc48bd21885fbc671df2f8ac04a75473 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 13 Jan 2011 07:48:13 +0000 Subject: [PATCH 37/47] e1000: Avoid unhandled IRQ If hardware asserted an interrupt and driver is down, then there is nothing to do so return IRQ_HANDLED instead of IRQ_NONE. Returning IRQ_NONE in above situation causes screaming IRQ on virtual machines. CC: Andy Gospodarek Signed-off-by: Tushar Dave Signed-off-by: Jesse Brandeburg Tested-by: Signed-off-by: Jeff Kirsher --- drivers/net/e1000/e1000_main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4ff88a683f61..e332aee386f6 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3478,9 +3478,17 @@ static irqreturn_t e1000_intr(int irq, void *data) struct e1000_hw *hw = &adapter->hw; u32 icr = er32(ICR); - if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags))) + if (unlikely((!icr))) return IRQ_NONE; /* Not our interrupt */ + /* + * we might have caused the interrupt, but the above + * read cleared it, and just in case the driver is + * down there is nothing to do so return handled + */ + if (unlikely(test_bit(__E1000_DOWN, &adapter->flags))) + return IRQ_HANDLED; + if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { hw->get_link_status = 1; /* guard against interrupt when we're going down */ From 0d6057e48b9d2004024e97252da83dce0661b131 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 4 Jan 2011 01:16:44 +0000 Subject: [PATCH 38/47] e1000e: update Copyright for 2011 Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/e1000e/82571.c | 2 +- drivers/net/e1000e/Makefile | 2 +- drivers/net/e1000e/defines.h | 2 +- drivers/net/e1000e/e1000.h | 2 +- drivers/net/e1000e/es2lan.c | 2 +- drivers/net/e1000e/ethtool.c | 2 +- drivers/net/e1000e/hw.h | 2 +- drivers/net/e1000e/ich8lan.c | 2 +- drivers/net/e1000e/lib.c | 2 +- drivers/net/e1000e/netdev.c | 4 ++-- drivers/net/e1000e/param.c | 2 +- drivers/net/e1000e/phy.c | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index cb6c7b1c1fb8..003a717041c7 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/Makefile b/drivers/net/e1000e/Makefile index 360c91369f35..28519acacd2d 100644 --- a/drivers/net/e1000e/Makefile +++ b/drivers/net/e1000e/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel PRO/1000 Linux driver -# Copyright(c) 1999 - 2008 Intel Corporation. +# Copyright(c) 1999 - 2011 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 7245dc2e0b7c..13149983d07e 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 5255be753746..e610e1369053 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index e45a61c8930a..2fefa820302b 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index f8ed03dab9b1..fa08b6336cfb 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index e774380c7cec..efdbb28c92de 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 5328a2927731..b43fc7fb1ee4 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index ff2872153b21..1c98dfa7b461 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index fa5b60452547..04df74537a20 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -6193,7 +6193,7 @@ static int __init e1000_init_module(void) int ret; pr_info("Intel(R) PRO/1000 Network Driver - %s\n", e1000e_driver_version); - pr_info("Copyright (c) 1999 - 2010 Intel Corporation.\n"); + pr_info("Copyright(c) 1999 - 2011 Intel Corporation.\n"); ret = pci_register_driver(&e1000_driver); return ret; diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index a9612b0e4bca..d6f618d3359a 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index a640f1c369ae..eb6cbad598b8 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2010 Intel Corporation. + Copyright(c) 1999 - 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, From af667a29dd3dfc0464f83bac30cc3c63fe5d0206 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 31 Dec 2010 06:10:01 +0000 Subject: [PATCH 39/47] e1000e: consistent use of Rx/Tx vs. RX/TX/rx/tx in comments/logs Some minor comment errors and whitespace issues discovered while looking into this are also addressed. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/e1000e/82571.c | 2 +- drivers/net/e1000e/hw.h | 2 +- drivers/net/e1000e/lib.c | 18 +-- drivers/net/e1000e/netdev.c | 219 ++++++++++++++++++------------------ drivers/net/e1000e/param.c | 4 +- drivers/net/e1000e/phy.c | 2 +- 6 files changed, 125 insertions(+), 122 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 003a717041c7..7bdec0b0c562 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1310,7 +1310,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) * apply workaround for hardware errata documented in errata * docs Fixes issue where some error prone or unreliable PCIe * completions are occurring, particularly with ASPM enabled. - * Without fix, issue can cause tx timeouts. + * Without fix, issue can cause Tx timeouts. */ reg = er32(GCR2); reg |= 1; diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index efdbb28c92de..bc0860a598c9 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -102,7 +102,7 @@ enum e1e_registers { E1000_RDTR = 0x02820, /* Rx Delay Timer - RW */ E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */ #define E1000_RXDCTL(_n) (E1000_RXDCTL_BASE + (_n << 8)) - E1000_RADV = 0x0282C, /* RX Interrupt Absolute Delay Timer - RW */ + E1000_RADV = 0x0282C, /* Rx Interrupt Absolute Delay Timer - RW */ /* Convenience macros * diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 1c98dfa7b461..68aa1749bf66 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -533,7 +533,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) mac->autoneg_failed = 1; return 0; } - e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); + e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); @@ -556,7 +556,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. */ - e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); + e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); @@ -598,7 +598,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) mac->autoneg_failed = 1; return 0; } - e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); + e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); @@ -621,7 +621,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. */ - e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); + e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); @@ -800,9 +800,9 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, - * but not send pause frames). + * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but we - * do not support receiving pause frames). + * do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. */ switch (hw->fc.current_mode) { @@ -1031,9 +1031,9 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw) * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). + * frames but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). + * frames but we do not receive pause frames). * 3: Both Rx and Tx flow control (symmetric) is enabled. * other: No other values should be possible at this point. */ @@ -1189,7 +1189,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) } else { hw->fc.current_mode = e1000_fc_rx_pause; e_dbg("Flow Control = " - "RX PAUSE frames only.\r\n"); + "Rx PAUSE frames only.\r\n"); } } /* diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 04df74537a20..1c18f26b0812 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -77,17 +77,17 @@ struct e1000_reg_info { char *name; }; -#define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ -#define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ -#define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ -#define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ -#define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ +#define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ +#define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ +#define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ +#define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ +#define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ -#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ -#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ -#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ -#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ -#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ +#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ +#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ +#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ +#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ +#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ static const struct e1000_reg_info e1000_reg_info_tbl[] = { @@ -99,7 +99,7 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = { /* Interrupt Registers */ {E1000_ICR, "ICR"}, - /* RX Registers */ + /* Rx Registers */ {E1000_RCTL, "RCTL"}, {E1000_RDLEN, "RDLEN"}, {E1000_RDH, "RDH"}, @@ -115,7 +115,7 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = { {E1000_RDFTS, "RDFTS"}, {E1000_RDFPC, "RDFPC"}, - /* TX Registers */ + /* Tx Registers */ {E1000_TCTL, "TCTL"}, {E1000_TDBAL, "TDBAL"}, {E1000_TDBAH, "TDBAH"}, @@ -160,7 +160,7 @@ static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) break; default: printk(KERN_INFO "%-15s %08x\n", - reginfo->name, __er32(hw, reginfo->ofs)); + reginfo->name, __er32(hw, reginfo->ofs)); return; } @@ -171,9 +171,8 @@ static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) printk(KERN_CONT "\n"); } - /* - * e1000e_dump - Print registers, tx-ring and rx-ring + * e1000e_dump - Print registers, Tx-ring and Rx-ring */ static void e1000e_dump(struct e1000_adapter *adapter) { @@ -182,12 +181,20 @@ static void e1000e_dump(struct e1000_adapter *adapter) struct e1000_reg_info *reginfo; struct e1000_ring *tx_ring = adapter->tx_ring; struct e1000_tx_desc *tx_desc; - struct my_u0 { u64 a; u64 b; } *u0; + struct my_u0 { + u64 a; + u64 b; + } *u0; struct e1000_buffer *buffer_info; struct e1000_ring *rx_ring = adapter->rx_ring; union e1000_rx_desc_packet_split *rx_desc_ps; struct e1000_rx_desc *rx_desc; - struct my_u1 { u64 a; u64 b; u64 c; u64 d; } *u1; + struct my_u1 { + u64 a; + u64 b; + u64 c; + u64 d; + } *u1; u32 staterr; int i = 0; @@ -198,12 +205,10 @@ static void e1000e_dump(struct e1000_adapter *adapter) if (netdev) { dev_info(&adapter->pdev->dev, "Net device Info\n"); printk(KERN_INFO "Device Name state " - "trans_start last_rx\n"); + "trans_start last_rx\n"); printk(KERN_INFO "%-15s %016lX %016lX %016lX\n", - netdev->name, - netdev->state, - netdev->trans_start, - netdev->last_rx); + netdev->name, netdev->state, netdev->trans_start, + netdev->last_rx); } /* Print Registers */ @@ -214,26 +219,26 @@ static void e1000e_dump(struct e1000_adapter *adapter) e1000_regdump(hw, reginfo); } - /* Print TX Ring Summary */ + /* Print Tx Ring Summary */ if (!netdev || !netif_running(netdev)) goto exit; - dev_info(&adapter->pdev->dev, "TX Rings Summary\n"); + dev_info(&adapter->pdev->dev, "Tx Ring Summary\n"); printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma ]" - " leng ntw timestamp\n"); + " leng ntw timestamp\n"); buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean]; printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n", - 0, tx_ring->next_to_use, tx_ring->next_to_clean, - (unsigned long long)buffer_info->dma, - buffer_info->length, - buffer_info->next_to_watch, - (unsigned long long)buffer_info->time_stamp); + 0, tx_ring->next_to_use, tx_ring->next_to_clean, + (unsigned long long)buffer_info->dma, + buffer_info->length, + buffer_info->next_to_watch, + (unsigned long long)buffer_info->time_stamp); - /* Print TX Rings */ + /* Print Tx Ring */ if (!netif_msg_tx_done(adapter)) goto rx_ring_summary; - dev_info(&adapter->pdev->dev, "TX Rings Dump\n"); + dev_info(&adapter->pdev->dev, "Tx Ring Dump\n"); /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended) * @@ -263,22 +268,22 @@ static void e1000e_dump(struct e1000_adapter *adapter) * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 */ printk(KERN_INFO "Tl[desc] [address 63:0 ] [SpeCssSCmCsLen]" - " [bi->dma ] leng ntw timestamp bi->skb " - "<-- Legacy format\n"); + " [bi->dma ] leng ntw timestamp bi->skb " + "<-- Legacy format\n"); printk(KERN_INFO "Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen]" - " [bi->dma ] leng ntw timestamp bi->skb " - "<-- Ext Context format\n"); + " [bi->dma ] leng ntw timestamp bi->skb " + "<-- Ext Context format\n"); printk(KERN_INFO "Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen]" - " [bi->dma ] leng ntw timestamp bi->skb " - "<-- Ext Data format\n"); + " [bi->dma ] leng ntw timestamp bi->skb " + "<-- Ext Data format\n"); for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; u0 = (struct my_u0 *)tx_desc; printk(KERN_INFO "T%c[0x%03X] %016llX %016llX %016llX " - "%04X %3X %016llX %p", - (!(le64_to_cpu(u0->b) & (1<<29)) ? 'l' : - ((le64_to_cpu(u0->b) & (1<<20)) ? 'd' : 'c')), i, + "%04X %3X %016llX %p", + (!(le64_to_cpu(u0->b) & (1 << 29)) ? 'l' : + ((le64_to_cpu(u0->b) & (1 << 20)) ? 'd' : 'c')), i, (unsigned long long)le64_to_cpu(u0->a), (unsigned long long)le64_to_cpu(u0->b), (unsigned long long)buffer_info->dma, @@ -296,22 +301,22 @@ static void e1000e_dump(struct e1000_adapter *adapter) if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, phys_to_virt(buffer_info->dma), - buffer_info->length, true); + 16, 1, phys_to_virt(buffer_info->dma), + buffer_info->length, true); } - /* Print RX Rings Summary */ + /* Print Rx Ring Summary */ rx_ring_summary: - dev_info(&adapter->pdev->dev, "RX Rings Summary\n"); + dev_info(&adapter->pdev->dev, "Rx Ring Summary\n"); printk(KERN_INFO "Queue [NTU] [NTC]\n"); printk(KERN_INFO " %5d %5X %5X\n", 0, - rx_ring->next_to_use, rx_ring->next_to_clean); + rx_ring->next_to_use, rx_ring->next_to_clean); - /* Print RX Rings */ + /* Print Rx Ring */ if (!netif_msg_rx_status(adapter)) goto exit; - dev_info(&adapter->pdev->dev, "RX Rings Dump\n"); + dev_info(&adapter->pdev->dev, "Rx Ring Dump\n"); switch (adapter->rx_ps_pages) { case 1: case 2: @@ -329,7 +334,7 @@ rx_ring_summary: * +-----------------------------------------------------+ */ printk(KERN_INFO "R [desc] [buffer 0 63:0 ] " - "[buffer 1 63:0 ] " + "[buffer 1 63:0 ] " "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma ] " "[bi->skb] <-- Ext Pkt Split format\n"); /* [Extended] Receive Descriptor (Write-Back) Format @@ -344,7 +349,7 @@ rx_ring_summary: * 63 48 47 32 31 20 19 0 */ printk(KERN_INFO "RWB[desc] [ck ipid mrqhsh] " - "[vl l0 ee es] " + "[vl l0 ee es] " "[ l3 l2 l1 hs] [reserved ] ---------------- " "[bi->skb] <-- Ext Rx Write-Back format\n"); for (i = 0; i < rx_ring->count; i++) { @@ -352,26 +357,26 @@ rx_ring_summary: rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i); u1 = (struct my_u1 *)rx_desc_ps; staterr = - le32_to_cpu(rx_desc_ps->wb.middle.status_error); + le32_to_cpu(rx_desc_ps->wb.middle.status_error); if (staterr & E1000_RXD_STAT_DD) { /* Descriptor Done */ printk(KERN_INFO "RWB[0x%03X] %016llX " - "%016llX %016llX %016llX " - "---------------- %p", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - (unsigned long long)le64_to_cpu(u1->c), - (unsigned long long)le64_to_cpu(u1->d), - buffer_info->skb); + "%016llX %016llX %016llX " + "---------------- %p", i, + (unsigned long long)le64_to_cpu(u1->a), + (unsigned long long)le64_to_cpu(u1->b), + (unsigned long long)le64_to_cpu(u1->c), + (unsigned long long)le64_to_cpu(u1->d), + buffer_info->skb); } else { printk(KERN_INFO "R [0x%03X] %016llX " - "%016llX %016llX %016llX %016llX %p", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - (unsigned long long)le64_to_cpu(u1->c), - (unsigned long long)le64_to_cpu(u1->d), - (unsigned long long)buffer_info->dma, - buffer_info->skb); + "%016llX %016llX %016llX %016llX %p", i, + (unsigned long long)le64_to_cpu(u1->a), + (unsigned long long)le64_to_cpu(u1->b), + (unsigned long long)le64_to_cpu(u1->c), + (unsigned long long)le64_to_cpu(u1->d), + (unsigned long long)buffer_info->dma, + buffer_info->skb); if (netif_msg_pktdata(adapter)) print_hex_dump(KERN_INFO, "", @@ -400,18 +405,18 @@ rx_ring_summary: * 63 48 47 40 39 32 31 16 15 0 */ printk(KERN_INFO "Rl[desc] [address 63:0 ] " - "[vl er S cks ln] [bi->dma ] [bi->skb] " - "<-- Legacy format\n"); + "[vl er S cks ln] [bi->dma ] [bi->skb] " + "<-- Legacy format\n"); for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) { rx_desc = E1000_RX_DESC(*rx_ring, i); buffer_info = &rx_ring->buffer_info[i]; u0 = (struct my_u0 *)rx_desc; printk(KERN_INFO "Rl[0x%03X] %016llX %016llX " - "%016llX %p", i, - (unsigned long long)le64_to_cpu(u0->a), - (unsigned long long)le64_to_cpu(u0->b), - (unsigned long long)buffer_info->dma, - buffer_info->skb); + "%016llX %p", i, + (unsigned long long)le64_to_cpu(u0->a), + (unsigned long long)le64_to_cpu(u0->b), + (unsigned long long)buffer_info->dma, + buffer_info->skb); if (i == rx_ring->next_to_use) printk(KERN_CONT " NTU\n"); else if (i == rx_ring->next_to_clean) @@ -421,9 +426,10 @@ rx_ring_summary: if (netif_msg_pktdata(adapter)) print_hex_dump(KERN_INFO, "", - DUMP_PREFIX_ADDRESS, - 16, 1, phys_to_virt(buffer_info->dma), - adapter->rx_buffer_len, true); + DUMP_PREFIX_ADDRESS, + 16, 1, + phys_to_virt(buffer_info->dma), + adapter->rx_buffer_len, true); } } @@ -450,8 +456,7 @@ static int e1000_desc_unused(struct e1000_ring *ring) * @skb: pointer to sk_buff to be indicated to stack **/ static void e1000_receive_skb(struct e1000_adapter *adapter, - struct net_device *netdev, - struct sk_buff *skb, + struct net_device *netdev, struct sk_buff *skb, u8 status, __le16 vlan) { skb->protocol = eth_type_trans(skb, netdev); @@ -464,7 +469,7 @@ static void e1000_receive_skb(struct e1000_adapter *adapter, } /** - * e1000_rx_checksum - Receive Checksum Offload for 82543 + * e1000_rx_checksum - Receive Checksum Offload * @adapter: board private structure * @status_err: receive descriptor status and error fields * @csum: receive descriptor csum field @@ -548,7 +553,7 @@ map_skb: adapter->rx_buffer_len, DMA_FROM_DEVICE); if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - dev_err(&pdev->dev, "RX DMA map failed\n"); + dev_err(&pdev->dev, "Rx DMA map failed\n"); adapter->rx_dma_failed++; break; } @@ -601,7 +606,8 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, ps_page = &buffer_info->ps_pages[j]; if (j >= adapter->rx_ps_pages) { /* all unused desc entries get hw null ptr */ - rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0); + rx_desc->read.buffer_addr[j + 1] = + ~cpu_to_le64(0); continue; } if (!ps_page->page) { @@ -617,7 +623,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, if (dma_mapping_error(&pdev->dev, ps_page->dma)) { dev_err(&adapter->pdev->dev, - "RX DMA page map failed\n"); + "Rx DMA page map failed\n"); adapter->rx_dma_failed++; goto no_buffers; } @@ -627,8 +633,8 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, * didn't change because each write-back * erases this info. */ - rx_desc->read.buffer_addr[j+1] = - cpu_to_le64(ps_page->dma); + rx_desc->read.buffer_addr[j + 1] = + cpu_to_le64(ps_page->dma); } skb = netdev_alloc_skb_ip_align(netdev, @@ -644,7 +650,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, adapter->rx_ps_bsize0, DMA_FROM_DEVICE); if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - dev_err(&pdev->dev, "RX DMA map failed\n"); + dev_err(&pdev->dev, "Rx DMA map failed\n"); adapter->rx_dma_failed++; /* cleanup skb */ dev_kfree_skb_any(skb); @@ -662,7 +668,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, * such as IA-64). */ wmb(); - writel(i<<1, adapter->hw.hw_addr + rx_ring->tail); + writel(i << 1, adapter->hw.hw_addr + rx_ring->tail); } i++; @@ -1106,11 +1112,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, cleaned = 1; cleaned_count++; dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_ps_bsize0, - DMA_FROM_DEVICE); + adapter->rx_ps_bsize0, DMA_FROM_DEVICE); buffer_info->dma = 0; - /* see !EOP comment in other rx routine */ + /* see !EOP comment in other Rx routine */ if (!(staterr & E1000_RXD_STAT_EOP)) adapter->flags2 |= FLAG2_IS_DISCARDING; @@ -2610,7 +2615,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter) } /** - * e1000_configure_tx - Configure 8254x Transmit Unit after Reset + * e1000_configure_tx - Configure Transmit Unit after Reset * @adapter: board private structure * * Configure the Tx unit of the MAC after a reset. @@ -2663,7 +2668,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) * hthresh = 1 ==> prefetch when one or more available * pthresh = 0x1f ==> prefetch if internal cache 31 or less * BEWARE: this seems to work but should be considered first if - * there are tx hangs or other tx related bugs + * there are Tx hangs or other Tx related bugs */ txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE; ew32(TXDCTL(0), txdctl); @@ -2877,7 +2882,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) if (adapter->rx_ps_pages) { /* this is a 32 byte descriptor */ rdlen = rx_ring->count * - sizeof(union e1000_rx_desc_packet_split); + sizeof(union e1000_rx_desc_packet_split); adapter->clean_rx = e1000_clean_rx_irq_ps; adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps; } else if (adapter->netdev->mtu > ETH_FRAME_LEN + ETH_FCS_LEN) { @@ -2900,7 +2905,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) /* * set the writeback threshold (only takes effect if the RDTR * is set). set GRAN=1 and write back up to 0x4 worth, and - * enable prefetching of 0x20 rx descriptors + * enable prefetching of 0x20 Rx descriptors * granularity = 01 * wthresh = 04, * hthresh = 04, @@ -2981,12 +2986,10 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) * excessive C-state transition latencies result in * dropped transactions. */ - pm_qos_update_request( - &adapter->netdev->pm_qos_req, 55); + pm_qos_update_request(&adapter->netdev->pm_qos_req, 55); } else { - pm_qos_update_request( - &adapter->netdev->pm_qos_req, - PM_QOS_DEFAULT_VALUE); + pm_qos_update_request(&adapter->netdev->pm_qos_req, + PM_QOS_DEFAULT_VALUE); } } @@ -3152,7 +3155,7 @@ void e1000e_reset(struct e1000_adapter *adapter) /* lower 16 bits has Rx packet buffer allocation size in KB */ pba &= 0xffff; /* - * the Tx fifo also stores 16 bytes of information about the tx + * the Tx fifo also stores 16 bytes of information about the Tx * but don't include ethernet FCS because hardware appends it */ min_tx_space = (adapter->max_frame_size + @@ -3175,7 +3178,7 @@ void e1000e_reset(struct e1000_adapter *adapter) pba -= min_tx_space - tx_space; /* - * if short on Rx space, Rx wins and must trump tx + * if short on Rx space, Rx wins and must trump Tx * adjustment or use Early Receive if available */ if ((pba < min_rx_space) && @@ -4039,11 +4042,11 @@ static void e1000_print_link_info(struct e1000_adapter *adapter) adapter->netdev->name, adapter->link_speed, (adapter->link_duplex == FULL_DUPLEX) ? - "Full Duplex" : "Half Duplex", + "Full Duplex" : "Half Duplex", ((ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE)) ? - "RX/TX" : - ((ctrl & E1000_CTRL_RFCE) ? "RX" : - ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" ))); + "Rx/Tx" : + ((ctrl & E1000_CTRL_RFCE) ? "Rx" : + ((ctrl & E1000_CTRL_TFCE) ? "Tx" : "None"))); } static bool e1000e_has_link(struct e1000_adapter *adapter) @@ -4338,7 +4341,7 @@ link_up: /* Force detection of hung controller every watchdog period */ adapter->detect_tx_hung = 1; - /* flush partial descriptors to memory before detecting tx hang */ + /* flush partial descriptors to memory before detecting Tx hang */ if (adapter->flags2 & FLAG2_DMA_BURST) { ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD); @@ -4529,7 +4532,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, buffer_info->next_to_watch = i; buffer_info->dma = dma_map_single(&pdev->dev, skb->data + offset, - size, DMA_TO_DEVICE); + size, DMA_TO_DEVICE); buffer_info->mapped_as_page = false; if (dma_mapping_error(&pdev->dev, buffer_info->dma)) goto dma_error; @@ -4576,7 +4579,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, } } - segs = skb_shinfo(skb)->gso_segs ?: 1; + segs = skb_shinfo(skb)->gso_segs ? : 1; /* multiply data chunks by size of headers */ bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len; @@ -4588,13 +4591,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, return count; dma_error: - dev_err(&pdev->dev, "TX DMA map failed\n"); + dev_err(&pdev->dev, "Tx DMA map failed\n"); buffer_info->dma = 0; if (count) count--; while (count--) { - if (i==0) + if (i == 0) i += tx_ring->count; i--; buffer_info = &tx_ring->buffer_info[i]; diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index d6f618d3359a..4dd9b63273f6 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -62,10 +62,9 @@ MODULE_PARM_DESC(copybreak, module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); - /* * Transmit Interrupt Delay in units of 1.024 microseconds - * Tx interrupt delay needs to typically be set to something non zero + * Tx interrupt delay needs to typically be set to something non-zero * * Valid Range: 0-65535 */ @@ -112,6 +111,7 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); #define DEFAULT_ITR 3 #define MAX_ITR 100000 #define MIN_ITR 100 + /* IntMode (Interrupt Mode) * * Valid Range: 0 - 2 diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index eb6cbad598b8..326788eab2f7 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -640,7 +640,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) s32 ret_val; u16 phy_data; - /* Enable CRS on TX. This must be set for half-duplex operation. */ + /* Enable CRS on Tx. This must be set for half-duplex operation. */ ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data); if (ret_val) goto out; From 92d76e81b9df5f33b0c9e2091e892560a437a15f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 14 Jan 2011 12:39:59 -0800 Subject: [PATCH 40/47] cassini: Fix build bustage on x86. Unfortunately, not all CONFIG_OF platforms provide pci_device_to_OF_node(). Change the test to CONFIG_SPARC for now to deal with the build regressions. Signed-off-by: David S. Miller --- drivers/net/cassini.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 7206ab2cbbf8..3437613f0454 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -3203,7 +3203,7 @@ static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr, int phy_type = CAS_PHY_MII_MDIO0; /* default phy type */ int mac_off = 0; -#if defined(CONFIG_OF) +#if defined(CONFIG_SPARC) const unsigned char *addr; #endif @@ -3354,7 +3354,7 @@ use_random_mac_addr: if (found & VPD_FOUND_MAC) goto done; -#if defined(CONFIG_OF) +#if defined(CONFIG_SPARC) addr = of_get_property(cp->of_node, "local-mac-address", NULL); if (addr != NULL) { memcpy(dev_addr, addr, 6); @@ -5031,7 +5031,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, cp->msg_enable = (cassini_debug < 0) ? CAS_DEF_MSG_ENABLE : cassini_debug; -#if defined(CONFIG_OF) +#if defined(CONFIG_SPARC) cp->of_node = pci_device_to_OF_node(pdev); #endif From ad4650a89ac47bd153cbb76c3fd6eb1fa6f315b7 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 14 Jan 2011 03:02:37 +0000 Subject: [PATCH 41/47] GRETH: added raw AMBA vendor/device number to match against. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 27d6960ce09e..1c2dbdb43631 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -1600,6 +1600,9 @@ static struct of_device_id greth_of_match[] = { { .name = "GAISLER_ETHMAC", }, + { + .name = "01_01d", + }, {}, }; From bbe9e637330abe55442aebe799425e224086959f Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 14 Jan 2011 03:02:38 +0000 Subject: [PATCH 42/47] GRETH: fix opening/closing When NAPI is disabled there is no point in having IRQs enabled, TX/RX should be off before clearing the TX/RX descriptor rings. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 1c2dbdb43631..b307696e0f63 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -356,6 +356,8 @@ static int greth_open(struct net_device *dev) dev_dbg(&dev->dev, " starting queue\n"); netif_start_queue(dev); + GRETH_REGSAVE(greth->regs->status, 0xFF); + napi_enable(&greth->napi); greth_enable_irqs(greth); @@ -371,7 +373,9 @@ static int greth_close(struct net_device *dev) napi_disable(&greth->napi); + greth_disable_irqs(greth); greth_disable_tx(greth); + greth_disable_rx(greth); netif_stop_queue(dev); From 2a2bc012b98729ce9a39386faed28d11ee021683 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 14 Jan 2011 03:02:39 +0000 Subject: [PATCH 43/47] GRETH: GBit transmit descriptor handling optimization It is safe to enable all fragments before enabling the first descriptor, this way all descriptors don't have to be processed twice, added extra memory barrier. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index b307696e0f63..869e38d6f41b 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -503,7 +503,7 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) greth->tx_skbuff[curr_tx] = NULL; bdp = greth->tx_bd_base + curr_tx; - status = GRETH_TXBD_CSALL; + status = GRETH_TXBD_CSALL | GRETH_BD_EN; status |= frag->size & GRETH_BD_LEN; /* Wrap around descriptor ring */ @@ -540,26 +540,27 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) wmb(); - /* Enable the descriptors that we configured ... */ - for (i = 0; i < nr_frags + 1; i++) { - bdp = greth->tx_bd_base + greth->tx_next; - greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); - greth->tx_next = NEXT_TX(greth->tx_next); - greth->tx_free--; - } + /* Enable the descriptor chain by enabling the first descriptor */ + bdp = greth->tx_bd_base + greth->tx_next; + greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); + greth->tx_next = curr_tx; + greth->tx_free -= nr_frags + 1; + + wmb(); greth_enable_tx(greth); return NETDEV_TX_OK; frag_map_error: - /* Unmap SKB mappings that succeeded */ + /* Unmap SKB mappings that succeeded and disable descriptor */ for (i = 0; greth->tx_next + i != curr_tx; i++) { bdp = greth->tx_bd_base + greth->tx_next + i; dma_unmap_single(greth->dev, greth_read_bd(&bdp->addr), greth_read_bd(&bdp->stat) & GRETH_BD_LEN, DMA_TO_DEVICE); + greth_write_bd(&bdp->stat, 0); } map_error: if (net_ratelimit()) From b669e7f0580f3c0058f1b32c276ef6da8f05c138 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 14 Jan 2011 03:02:40 +0000 Subject: [PATCH 44/47] GRETH: fixed skb buffer memory leak on frame errors A new SKB buffer should not be allocated when the old SKB is reused. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 869e38d6f41b..9386bce9dea5 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -870,10 +870,9 @@ static int greth_rx_gbit(struct net_device *dev, int limit) } } - /* Allocate new skb to replace current */ - newskb = netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN); - - if (!bad && newskb) { + /* Allocate new skb to replace current, not needed if the + * current skb can be reused */ + if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) { skb_reserve(newskb, NET_IP_ALIGN); dma_addr = dma_map_single(greth->dev, @@ -910,11 +909,22 @@ static int greth_rx_gbit(struct net_device *dev, int limit) if (net_ratelimit()) dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n"); dev_kfree_skb(newskb); + /* reusing current skb, so it is a drop */ dev->stats.rx_dropped++; } + } else if (bad) { + /* Bad Frame transfer, the skb is reused */ + dev->stats.rx_dropped++; } else { + /* Failed Allocating a new skb. This is rather stupid + * but the current "filled" skb is reused, as if + * transfer failure. One could argue that RX descriptor + * table handling should be divided into cleaning and + * filling as the TX part of the driver + */ if (net_ratelimit()) dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n"); + /* reusing current skb, so it is a drop */ dev->stats.rx_dropped++; } From 2436af8ca7a6c4679cf7da7e3867f1d5cd8528b7 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 14 Jan 2011 03:02:41 +0000 Subject: [PATCH 45/47] GRETH: avoid writing bad speed/duplex when setting transfer mode Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 9386bce9dea5..e48d18216cbe 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -1232,29 +1232,26 @@ static void greth_link_change(struct net_device *dev) struct greth_private *greth = netdev_priv(dev); struct phy_device *phydev = greth->phy; unsigned long flags; - int status_change = 0; + u32 ctrl; spin_lock_irqsave(&greth->devlock, flags); if (phydev->link) { if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) { - - GRETH_REGANDIN(greth->regs->control, - ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB)); + ctrl = GRETH_REGLOAD(greth->regs->control) & + ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB); if (phydev->duplex) - GRETH_REGORIN(greth->regs->control, GRETH_CTRL_FD); - - if (phydev->speed == SPEED_100) { - - GRETH_REGORIN(greth->regs->control, GRETH_CTRL_SP); - } + ctrl |= GRETH_CTRL_FD; + if (phydev->speed == SPEED_100) + ctrl |= GRETH_CTRL_SP; else if (phydev->speed == SPEED_1000) - GRETH_REGORIN(greth->regs->control, GRETH_CTRL_GB); + ctrl |= GRETH_CTRL_GB; + GRETH_REGSAVE(greth->regs->control, ctrl); greth->speed = phydev->speed; greth->duplex = phydev->duplex; status_change = 1; From 1ca23434dd0001bd2bfff31b8251436b34aa9066 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 14 Jan 2011 03:02:42 +0000 Subject: [PATCH 46/47] GRETH: handle frame error interrupts Frame error interrupts must also be handled since the RX flag only indicates successful reception, it is unlikely but the old code may lead to dead lock if 128 error frames are recieved in a row. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 9 +++++---- drivers/net/greth.h | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index e48d18216cbe..b888abe6cd21 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -586,12 +586,13 @@ static irqreturn_t greth_interrupt(int irq, void *dev_id) status = GRETH_REGLOAD(greth->regs->status); /* Handle rx and tx interrupts through poll */ - if (status & (GRETH_INT_RX | GRETH_INT_TX)) { + if (status & (GRETH_INT_RE | GRETH_INT_RX | + GRETH_INT_TE | GRETH_INT_TX)) { /* Clear interrupt status */ - GRETH_REGORIN(greth->regs->status, - status & (GRETH_INT_RX | GRETH_INT_TX)); - + GRETH_REGSAVE(greth->regs->status, + status & (GRETH_INT_RE | GRETH_INT_RX | + GRETH_INT_TE | GRETH_INT_TX)); retval = IRQ_HANDLED; /* Disable interrupts and schedule poll() */ diff --git a/drivers/net/greth.h b/drivers/net/greth.h index 03ad903cd676..be0f2062bd14 100644 --- a/drivers/net/greth.h +++ b/drivers/net/greth.h @@ -23,6 +23,7 @@ #define GRETH_BD_LEN 0x7FF #define GRETH_TXEN 0x1 +#define GRETH_INT_TE 0x2 #define GRETH_INT_TX 0x8 #define GRETH_TXI 0x4 #define GRETH_TXBD_STATUS 0x0001C000 @@ -35,6 +36,7 @@ #define GRETH_TXBD_ERR_UE 0x4000 #define GRETH_TXBD_ERR_AL 0x8000 +#define GRETH_INT_RE 0x1 #define GRETH_INT_RX 0x4 #define GRETH_RXEN 0x2 #define GRETH_RXI 0x8 From 0f73f2c5a3ebb957ee66718c903c17ed71a4fc2e Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 14 Jan 2011 03:02:43 +0000 Subject: [PATCH 47/47] GRETH: resolve SMP issues and other problems Fixes the following: 1. POLL should not enable IRQ when work is not completed 2. No locking between TX descriptor cleaning and XMIT descriptor handling 3. No locking between RX POLL and XMIT modifying control register 4. Since TX cleaning (called from POLL) is running in parallel with XMIT unnecessary locking is needed. 5. IRQ handler looks at RX frame status solely, this is wrong when IRQ is temporarily disabled (in POLL), and when IRQ is shared. 6. IRQ handler clears IRQ status, which is unnecessary 7. TX queue was stopped in preventing cause when not MAX_SKB_FRAGS+1 descriptors were available after a SKB been scheduled by XMIT. Instead the TX queue is stopped first when not enough descriptors are available upon entering XMIT. It was hard to split up this patch in smaller pieces since all are tied together somehow. Note the RX flag used in the interrupt handler does not signal that interrupt was asserted, but that a frame was received. Same goes for TX. Also, IRQ is not asserted when the RX flag is set before enabling IRQ enable until a new frame is received. So extra care must be taken to avoid enabling IRQ and all descriptors are already used, hence dead lock will upon us. See new POLL implementation that enableds IRQ then look at the RX flag to determine if one or more IRQs may have been missed. TX/RX flags are cleared before handling previously enabled descriptors, this ensures that the RX/TX flags are valid when determining if IRQ should be turned on again. By moving TX cleaning from POLL to XMIT in the standard case, removes some locking trouble. Enabling TX cleaning from poll only when not enough TX descriptors are available is safe because the TX queue is at the same time stopped, thus XMIT will not be called. The TX queue is woken up again when enough descriptrs are available. TX Frames are always enabled with IRQ, however the TX IRQ Enable flag will not be enabled until XMIT must wait for free descriptors. Locking RX and XMIT parts of the driver from each other is needed because the RX/TX enable bits share the same register. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 159 +++++++++++++++++++++++++------------------- 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index b888abe6cd21..fdb0333f5cb6 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -1,7 +1,7 @@ /* * Aeroflex Gaisler GRETH 10/100/1G Ethernet MAC. * - * 2005-2009 (c) Aeroflex Gaisler AB + * 2005-2010 (c) Aeroflex Gaisler AB * * This driver supports GRETH 10/100 and GRETH 10/100/1G Ethernet MACs * available in the GRLIB VHDL IP core library. @@ -392,12 +392,20 @@ greth_start_xmit(struct sk_buff *skb, struct net_device *dev) struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; int err = NETDEV_TX_OK; - u32 status, dma_addr; + u32 status, dma_addr, ctrl; + unsigned long flags; - bdp = greth->tx_bd_base + greth->tx_next; + /* Clean TX Ring */ + greth_clean_tx(greth->netdev); if (unlikely(greth->tx_free <= 0)) { + spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/ + ctrl = GRETH_REGLOAD(greth->regs->control); + /* Enable TX IRQ only if not already in poll() routine */ + if (ctrl & GRETH_RXI) + GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI); netif_stop_queue(dev); + spin_unlock_irqrestore(&greth->devlock, flags); return NETDEV_TX_BUSY; } @@ -410,13 +418,14 @@ greth_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out; } + bdp = greth->tx_bd_base + greth->tx_next; dma_addr = greth_read_bd(&bdp->addr); memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len); dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE); - status = GRETH_BD_EN | (skb->len & GRETH_BD_LEN); + status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN); /* Wrap around descriptor ring */ if (greth->tx_next == GRETH_TXBD_NUM_MASK) { @@ -426,22 +435,11 @@ greth_start_xmit(struct sk_buff *skb, struct net_device *dev) greth->tx_next = NEXT_TX(greth->tx_next); greth->tx_free--; - /* No more descriptors */ - if (unlikely(greth->tx_free == 0)) { - - /* Free transmitted descriptors */ - greth_clean_tx(dev); - - /* If nothing was cleaned, stop queue & wait for irq */ - if (unlikely(greth->tx_free == 0)) { - status |= GRETH_BD_IE; - netif_stop_queue(dev); - } - } - /* Write descriptor control word and enable transmission */ greth_write_bd(&bdp->stat, status); + spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ greth_enable_tx(greth); + spin_unlock_irqrestore(&greth->devlock, flags); out: dev_kfree_skb(skb); @@ -454,13 +452,23 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; - u32 status = 0, dma_addr; + u32 status = 0, dma_addr, ctrl; int curr_tx, nr_frags, i, err = NETDEV_TX_OK; + unsigned long flags; nr_frags = skb_shinfo(skb)->nr_frags; + /* Clean TX Ring */ + greth_clean_tx_gbit(dev); + if (greth->tx_free < nr_frags + 1) { + spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/ + ctrl = GRETH_REGLOAD(greth->regs->control); + /* Enable TX IRQ only if not already in poll() routine */ + if (ctrl & GRETH_RXI) + GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI); netif_stop_queue(dev); + spin_unlock_irqrestore(&greth->devlock, flags); err = NETDEV_TX_BUSY; goto out; } @@ -513,14 +521,8 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) /* More fragments left */ if (i < nr_frags - 1) status |= GRETH_TXBD_MORE; - - /* ... last fragment, check if out of descriptors */ - else if (greth->tx_free - nr_frags - 1 < (MAX_SKB_FRAGS + 1)) { - - /* Enable interrupts and stop queue */ - status |= GRETH_BD_IE; - netif_stop_queue(dev); - } + else + status |= GRETH_BD_IE; /* enable IRQ on last fragment */ greth_write_bd(&bdp->stat, status); @@ -548,7 +550,9 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) wmb(); + spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ greth_enable_tx(greth); + spin_unlock_irqrestore(&greth->devlock, flags); return NETDEV_TX_OK; @@ -570,12 +574,11 @@ out: return err; } - static irqreturn_t greth_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct greth_private *greth; - u32 status; + u32 status, ctrl; irqreturn_t retval = IRQ_NONE; greth = netdev_priv(dev); @@ -585,14 +588,15 @@ static irqreturn_t greth_interrupt(int irq, void *dev_id) /* Get the interrupt events that caused us to be here. */ status = GRETH_REGLOAD(greth->regs->status); - /* Handle rx and tx interrupts through poll */ - if (status & (GRETH_INT_RE | GRETH_INT_RX | - GRETH_INT_TE | GRETH_INT_TX)) { + /* Must see if interrupts are enabled also, INT_TX|INT_RX flags may be + * set regardless of whether IRQ is enabled or not. Especially + * important when shared IRQ. + */ + ctrl = GRETH_REGLOAD(greth->regs->control); - /* Clear interrupt status */ - GRETH_REGSAVE(greth->regs->status, - status & (GRETH_INT_RE | GRETH_INT_RX | - GRETH_INT_TE | GRETH_INT_TX)); + /* Handle rx and tx interrupts through poll */ + if (((status & (GRETH_INT_RE | GRETH_INT_RX)) && (ctrl & GRETH_RXI)) || + ((status & (GRETH_INT_TE | GRETH_INT_TX)) && (ctrl & GRETH_TXI))) { retval = IRQ_HANDLED; /* Disable interrupts and schedule poll() */ @@ -616,6 +620,8 @@ static void greth_clean_tx(struct net_device *dev) while (1) { bdp = greth->tx_bd_base + greth->tx_last; + GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); + mb(); stat = greth_read_bd(&bdp->stat); if (unlikely(stat & GRETH_BD_EN)) @@ -676,7 +682,10 @@ static void greth_clean_tx_gbit(struct net_device *dev) /* We only clean fully completed SKBs */ bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags); - stat = bdp_last_frag->stat; + + GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); + mb(); + stat = greth_read_bd(&bdp_last_frag->stat); if (stat & GRETH_BD_EN) break; @@ -708,21 +717,9 @@ static void greth_clean_tx_gbit(struct net_device *dev) greth->tx_free += nr_frags+1; dev_kfree_skb(skb); } - if (greth->tx_free > (MAX_SKB_FRAGS + 1)) { - netif_wake_queue(dev); - } -} -static int greth_pending_packets(struct greth_private *greth) -{ - struct greth_bd *bdp; - u32 status; - bdp = greth->rx_bd_base + greth->rx_cur; - status = greth_read_bd(&bdp->stat); - if (status & GRETH_BD_EN) - return 0; - else - return 1; + if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1))) + netif_wake_queue(dev); } static int greth_rx(struct net_device *dev, int limit) @@ -733,20 +730,24 @@ static int greth_rx(struct net_device *dev, int limit) int pkt_len; int bad, count; u32 status, dma_addr; + unsigned long flags; greth = netdev_priv(dev); for (count = 0; count < limit; ++count) { bdp = greth->rx_bd_base + greth->rx_cur; + GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX); + mb(); status = greth_read_bd(&bdp->stat); - dma_addr = greth_read_bd(&bdp->addr); - bad = 0; if (unlikely(status & GRETH_BD_EN)) { break; } + dma_addr = greth_read_bd(&bdp->addr); + bad = 0; + /* Check status for errors. */ if (unlikely(status & GRETH_RXBD_STATUS)) { if (status & GRETH_RXBD_ERR_FT) { @@ -808,7 +809,9 @@ static int greth_rx(struct net_device *dev, int limit) dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE); + spin_lock_irqsave(&greth->devlock, flags); /* save from XMIT */ greth_enable_rx(greth); + spin_unlock_irqrestore(&greth->devlock, flags); greth->rx_cur = NEXT_RX(greth->rx_cur); } @@ -842,6 +845,7 @@ static int greth_rx_gbit(struct net_device *dev, int limit) int pkt_len; int bad, count = 0; u32 status, dma_addr; + unsigned long flags; greth = netdev_priv(dev); @@ -849,6 +853,8 @@ static int greth_rx_gbit(struct net_device *dev, int limit) bdp = greth->rx_bd_base + greth->rx_cur; skb = greth->rx_skbuff[greth->rx_cur]; + GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX); + mb(); status = greth_read_bd(&bdp->stat); bad = 0; @@ -936,7 +942,9 @@ static int greth_rx_gbit(struct net_device *dev, int limit) wmb(); greth_write_bd(&bdp->stat, status); + spin_lock_irqsave(&greth->devlock, flags); greth_enable_rx(greth); + spin_unlock_irqrestore(&greth->devlock, flags); greth->rx_cur = NEXT_RX(greth->rx_cur); } @@ -948,15 +956,18 @@ static int greth_poll(struct napi_struct *napi, int budget) { struct greth_private *greth; int work_done = 0; + unsigned long flags; + u32 mask, ctrl; greth = container_of(napi, struct greth_private, napi); - if (greth->gbit_mac) { - greth_clean_tx_gbit(greth->netdev); - } else { - greth_clean_tx(greth->netdev); +restart_txrx_poll: + if (netif_queue_stopped(greth->netdev)) { + if (greth->gbit_mac) + greth_clean_tx_gbit(greth->netdev); + else + greth_clean_tx(greth->netdev); } -restart_poll: if (greth->gbit_mac) { work_done += greth_rx_gbit(greth->netdev, budget - work_done); } else { @@ -965,15 +976,29 @@ restart_poll: if (work_done < budget) { - napi_complete(napi); + spin_lock_irqsave(&greth->devlock, flags); - if (greth_pending_packets(greth)) { - napi_reschedule(napi); - goto restart_poll; + ctrl = GRETH_REGLOAD(greth->regs->control); + if (netif_queue_stopped(greth->netdev)) { + GRETH_REGSAVE(greth->regs->control, + ctrl | GRETH_TXI | GRETH_RXI); + mask = GRETH_INT_RX | GRETH_INT_RE | + GRETH_INT_TX | GRETH_INT_TE; + } else { + GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_RXI); + mask = GRETH_INT_RX | GRETH_INT_RE; + } + + if (GRETH_REGLOAD(greth->regs->status) & mask) { + GRETH_REGSAVE(greth->regs->control, ctrl); + spin_unlock_irqrestore(&greth->devlock, flags); + goto restart_txrx_poll; + } else { + __napi_complete(napi); + spin_unlock_irqrestore(&greth->devlock, flags); } } - greth_enable_irqs(greth); return work_done; } @@ -1168,11 +1193,11 @@ static const struct ethtool_ops greth_ethtool_ops = { }; static struct net_device_ops greth_netdev_ops = { - .ndo_open = greth_open, - .ndo_stop = greth_close, - .ndo_start_xmit = greth_start_xmit, - .ndo_set_mac_address = greth_set_mac_add, - .ndo_validate_addr = eth_validate_addr, + .ndo_open = greth_open, + .ndo_stop = greth_close, + .ndo_start_xmit = greth_start_xmit, + .ndo_set_mac_address = greth_set_mac_add, + .ndo_validate_addr = eth_validate_addr, }; static inline int wait_for_mdio(struct greth_private *greth)