From eef35c2d41ddcc653c20d26b977acaa45c811e1f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 6 Aug 2010 21:11:15 +0200 Subject: Fix spelling fuction -> function in comments To avoid more patches, I also fixed other spelling and grammar bugs when they were in the same or following line: successfull -> successful parse -> parses controler -> controller controlers -> controllers Cc: Jiri Kosina Cc: linux-kernel@vger.kernel.org Signed-off-by: Stefan Weil Signed-off-by: Jiri Kosina --- drivers/net/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index df5dcd23e4fc..f0f82dc7c5db 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3527,7 +3527,7 @@ enum latency_range { * Stores a new ITR value based on strictly on packet size. This * algorithm is less sophisticated than that used in igb_update_itr, * due to the difficulty of synchronizing statistics across multiple - * receive rings. The divisors and thresholds used by this fuction + * receive rings. The divisors and thresholds used by this function * were determined based on theoretical maximum wire speed and testing * data, in order to minimize response time while increasing bulk * throughput. -- cgit v1.2.2 From 2244d07bfa2097cb00600da91c715a8aa547917e Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 17 Aug 2010 08:59:14 +0000 Subject: net: simplify flags for tx timestamping This patch removes the abstraction introduced by the union skb_shared_tx in the shared skb data. The access of the different union elements at several places led to some confusion about accessing the shared tx_flags e.g. in skb_orphan_try(). http://marc.info/?l=linux-netdev&m=128084897415886&w=2 Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 2 +- drivers/net/igb/igb_main.c | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 6e63d9a7fc75..44e0ff1494e0 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -143,7 +143,7 @@ struct igb_buffer { u16 next_to_watch; unsigned int bytecount; u16 gso_segs; - union skb_shared_tx shtx; + u8 tx_flags; u8 mapped_as_page; }; /* RX */ diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 9b4e5895f5f9..985e37cf17b6 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3954,7 +3954,7 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb, } tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].shtx = skb_shinfo(skb)->tx_flags; + tx_ring->buffer_info[i].tx_flags = skb_shinfo(skb)->tx_flags; /* multiply data chunks by size of headers */ tx_ring->buffer_info[i].bytecount = ((gso_segs - 1) * hlen) + skb->len; tx_ring->buffer_info[i].gso_segs = gso_segs; @@ -4088,7 +4088,6 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, u32 tx_flags = 0; u16 first; u8 hdr_len = 0; - union skb_shared_tx *shtx = skb_tx(skb); /* need: 1 descriptor per page, * + 2 desc gap to keep tail from touching head, @@ -4100,8 +4099,8 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (unlikely(shtx->hardware)) { - shtx->in_progress = 1; + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; tx_flags |= IGB_TX_FLAGS_TSTAMP; } @@ -5319,7 +5318,7 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct igb_buffer *bu u64 regval; /* if skb does not support hw timestamp or TX stamp not valid exit */ - if (likely(!buffer_info->shtx.hardware) || + if (likely(!(buffer_info->tx_flags & SKBTX_HW_TSTAMP)) || !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID)) return; @@ -5500,7 +5499,7 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr, * values must belong to this one here and therefore we don't need to * compare any of the additional attributes stored for it. * - * If nothing went wrong, then it should have a skb_shared_tx that we + * If nothing went wrong, then it should have a shared tx_flags that we * can turn into a skb_shared_hwtstamps. */ if (staterr & E1000_RXDADV_STAT_TSIP) { -- cgit v1.2.2 From c061b18df0f1fe3f50fe451dbbdc9ede3c19701a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Aug 2010 18:20:03 +0000 Subject: drivers/net: Remove address use from assignments of function pointers "foo = &function" is more commonly written "foo = function" Done with coccinelle script: // @r@ identifier f; @@ f(...) { ... } @@ identifier r.f; @@ - &f + f // drivers/net/tehuti.c used a function and struct with the same name, the function was renamed. Compile tested x86 only. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 985e37cf17b6..d35cc38bf8b2 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1888,9 +1888,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, goto err_eeprom; } - setup_timer(&adapter->watchdog_timer, &igb_watchdog, + setup_timer(&adapter->watchdog_timer, igb_watchdog, (unsigned long) adapter); - setup_timer(&adapter->phy_info_timer, &igb_update_phy_info, + setup_timer(&adapter->phy_info_timer, igb_update_phy_info, (unsigned long) adapter); INIT_WORK(&adapter->reset_task, igb_reset_task); -- cgit v1.2.2 From bc8acf2c8c3e43fcc192762a9f964b3e9a17748b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 2 Sep 2010 13:07:41 -0700 Subject: drivers/net: avoid some skb->ip_summed initializations fresh skbs have ip_summed set to CHECKSUM_NONE (0) We can avoid setting again skb->ip_summed to CHECKSUM_NONE in drivers. Introduce skb_checksum_none_assert() helper so that we keep this assertion documented in driver sources. Change most occurrences of : skb->ip_summed = CHECKSUM_NONE; by : skb_checksum_none_assert(skb); Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index d35cc38bf8b2..c4d861b557ca 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -5455,7 +5455,7 @@ static void igb_receive_skb(struct igb_q_vector *q_vector, static inline void igb_rx_checksum_adv(struct igb_ring *ring, u32 status_err, struct sk_buff *skb) { - skb->ip_summed = CHECKSUM_NONE; + skb_checksum_none_assert(skb); /* Ignore Checksum bit is set or checksum is disabled through ethtool */ if (!(ring->flags & IGB_RING_FLAG_RX_CSUM) || -- cgit v1.2.2 From d85b9004bc2047d79248b167cc151ff9a4b509c3 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 22 Sep 2010 17:56:20 +0000 Subject: igb: clear VF_PROMISC bits instead of setting all other bits This change corrects an issue in which we were setting all flag bits except for promisc instead of clearing the promisc bits due to the incorrect use of an |= instead of an &=. Signed-off-by: Alexander Duyck Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index c4d861b557ca..fd922e7db1d5 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4659,12 +4659,13 @@ static int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) u32 vmolr = rd32(E1000_VMOLR(vf)); struct vf_data_storage *vf_data = &adapter->vf_data[vf]; - vf_data->flags |= ~(IGB_VF_FLAG_UNI_PROMISC | + vf_data->flags &= ~(IGB_VF_FLAG_UNI_PROMISC | IGB_VF_FLAG_MULTI_PROMISC); vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) { vmolr |= E1000_VMOLR_MPME; + vf_data->flags |= IGB_VF_FLAG_MULTI_PROMISC; *msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST; } else { /* -- cgit v1.2.2 From 308fb39a860c816be8741fe783ae7c64e9c1af5d Mon Sep 17 00:00:00 2001 From: Joseph Gasparakis Date: Wed, 22 Sep 2010 17:56:44 +0000 Subject: igb: Add support for DH89xxCC This patch adds support for the Intel(r) DH89xxCC series. The new device will be using Intel(r) i347-AT4 and Marvell(r) M88E1322 and M88E1112 PHYs. Support for these devices has also been added here. Signed-off-by: Joseph Gasparakis Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 18 +++- drivers/net/igb/e1000_defines.h | 31 ++++++ drivers/net/igb/e1000_hw.h | 2 + drivers/net/igb/e1000_phy.c | 206 +++++++++++++++++++++++++++++++++++++--- drivers/net/igb/e1000_phy.h | 2 + drivers/net/igb/igb_main.c | 2 + 6 files changed, 247 insertions(+), 14 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 187622f1c816..bc183f5487cb 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -132,6 +132,8 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) case E1000_DEV_ID_82580_SERDES: case E1000_DEV_ID_82580_SGMII: case E1000_DEV_ID_82580_COPPER_DUAL: + case E1000_DEV_ID_DH89XXCC_SGMII: + case E1000_DEV_ID_DH89XXCC_SERDES: mac->type = e1000_82580; break; case E1000_DEV_ID_I350_COPPER: @@ -282,10 +284,18 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) /* Verify phy id and set remaining function pointers */ switch (phy->id) { + case I347AT4_E_PHY_ID: + case M88E1112_E_PHY_ID: case M88E1111_I_PHY_ID: phy->type = e1000_phy_m88; phy->ops.get_phy_info = igb_get_phy_info_m88; - phy->ops.get_cable_length = igb_get_cable_length_m88; + + if (phy->id == I347AT4_E_PHY_ID || + phy->id == M88E1112_E_PHY_ID) + phy->ops.get_cable_length = igb_get_cable_length_m88_gen2; + else + phy->ops.get_cable_length = igb_get_cable_length_m88; + phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; break; case IGP03E1000_E_PHY_ID: @@ -1058,7 +1068,11 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) } switch (hw->phy.type) { case e1000_phy_m88: - ret_val = igb_copper_link_setup_m88(hw); + if (hw->phy.id == I347AT4_E_PHY_ID || + hw->phy.id == M88E1112_E_PHY_ID) + ret_val = igb_copper_link_setup_m88_gen2(hw); + else + ret_val = igb_copper_link_setup_m88(hw); break; case e1000_phy_igp_3: ret_val = igb_copper_link_setup_igp(hw); diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index bbd2ec308eb0..62222796a8b3 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -634,6 +634,8 @@ * E = External */ #define M88E1111_I_PHY_ID 0x01410CC0 +#define M88E1112_E_PHY_ID 0x01410C90 +#define I347AT4_E_PHY_ID 0x01410DC0 #define IGP03E1000_E_PHY_ID 0x02A80390 #define I82580_I_PHY_ID 0x015403A0 #define I350_I_PHY_ID 0x015403B0 @@ -702,6 +704,35 @@ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ +/* Intel i347-AT4 Registers */ + +#define I347AT4_PCDL 0x10 /* PHY Cable Diagnostics Length */ +#define I347AT4_PCDC 0x15 /* PHY Cable Diagnostics Control */ +#define I347AT4_PAGE_SELECT 0x16 + +/* i347-AT4 Extended PHY Specific Control Register */ + +/* + * Number of times we will attempt to autonegotiate before downshifting if we + * are the master + */ +#define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800 +#define I347AT4_PSCR_DOWNSHIFT_MASK 0x7000 +#define I347AT4_PSCR_DOWNSHIFT_1X 0x0000 +#define I347AT4_PSCR_DOWNSHIFT_2X 0x1000 +#define I347AT4_PSCR_DOWNSHIFT_3X 0x2000 +#define I347AT4_PSCR_DOWNSHIFT_4X 0x3000 +#define I347AT4_PSCR_DOWNSHIFT_5X 0x4000 +#define I347AT4_PSCR_DOWNSHIFT_6X 0x5000 +#define I347AT4_PSCR_DOWNSHIFT_7X 0x6000 +#define I347AT4_PSCR_DOWNSHIFT_8X 0x7000 + +/* i347-AT4 PHY Cable Diagnostics Control */ +#define I347AT4_PCDC_CABLE_LENGTH_UNIT 0x0400 /* 0=cm 1=meters */ + +/* Marvell 1112 only registers */ +#define M88E1112_VCT_DSP_DISTANCE 0x001A + /* M88EC018 Rev 2 specific DownShift settings */ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index cb8db78b1a05..c0b017f8d782 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -54,6 +54,8 @@ struct e1000_hw; #define E1000_DEV_ID_82580_SERDES 0x1510 #define E1000_DEV_ID_82580_SGMII 0x1511 #define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 +#define E1000_DEV_ID_DH89XXCC_SGMII 0x0436 +#define E1000_DEV_ID_DH89XXCC_SERDES 0x0438 #define E1000_DEV_ID_I350_COPPER 0x1521 #define E1000_DEV_ID_I350_FIBER 0x1522 #define E1000_DEV_ID_I350_SERDES 0x1523 diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index cf1f32300923..ddd036a78999 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -569,6 +569,89 @@ out: return ret_val; } +/** + * igb_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link + * @hw: pointer to the HW structure + * + * Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's. + * Also enables and sets the downshift parameters. + **/ +s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + + if (phy->reset_disable) { + ret_val = 0; + goto out; + } + + /* Enable CRS on Tx. This must be set for half-duplex operation. */ + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + /* + * Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + + switch (phy->mdix) { + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + /* M88E1112 does not support this mode) */ + if (phy->id != M88E1112_E_PHY_ID) { + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + } + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; + } + + /* + * Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; + if (phy->disable_polarity_correction == 1) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + + /* Enable downshift and setting it to X6 */ + phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK; + phy_data |= I347AT4_PSCR_DOWNSHIFT_6X; + phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE; + + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + + /* Commit the changes. */ + ret_val = igb_phy_sw_reset(hw); + if (ret_val) { + hw_dbg("Error committing the PHY changes\n"); + goto out; + } + +out: + return ret_val; +} + /** * igb_copper_link_setup_igp - Setup igp PHY's for copper link * @hw: pointer to the HW structure @@ -1124,18 +1207,25 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) goto out; if (!link) { - /* - * We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = phy->ops.write_reg(hw, - M88E1000_PHY_PAGE_SELECT, - 0x001d); - if (ret_val) - goto out; - ret_val = igb_phy_reset_dsp(hw); - if (ret_val) - goto out; + if (hw->phy.type != e1000_phy_m88 || + hw->phy.id == I347AT4_E_PHY_ID || + hw->phy.id == M88E1112_E_PHY_ID) { + hw_dbg("Link taking longer than expected.\n"); + } else { + + /* + * We didn't get link. + * Reset the DSP and cross our fingers. + */ + ret_val = phy->ops.write_reg(hw, + M88E1000_PHY_PAGE_SELECT, + 0x001d); + if (ret_val) + goto out; + ret_val = igb_phy_reset_dsp(hw); + if (ret_val) + goto out; + } } /* Try once more */ @@ -1145,6 +1235,11 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) goto out; } + if (hw->phy.type != e1000_phy_m88 || + hw->phy.id == I347AT4_E_PHY_ID || + hw->phy.id == M88E1112_E_PHY_ID) + goto out; + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -1557,6 +1652,93 @@ out: return ret_val; } +s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data, phy_data2, index, default_page, is_cm; + + switch (hw->phy.id) { + case I347AT4_E_PHY_ID: + /* Remember the original page select and set it to 7 */ + ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, + &default_page); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07); + if (ret_val) + goto out; + + /* Get cable length from PHY Cable Diagnostics Control Reg */ + ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr), + &phy_data); + if (ret_val) + goto out; + + /* Check if the unit of cable length is meters or cm */ + ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2); + if (ret_val) + goto out; + + is_cm = !(phy_data & I347AT4_PCDC_CABLE_LENGTH_UNIT); + + /* Populate the phy structure with cable length in meters */ + phy->min_cable_length = phy_data / (is_cm ? 100 : 1); + phy->max_cable_length = phy_data / (is_cm ? 100 : 1); + phy->cable_length = phy_data / (is_cm ? 100 : 1); + + /* Reset the page selec to its original value */ + ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, + default_page); + if (ret_val) + goto out; + break; + case M88E1112_E_PHY_ID: + /* Remember the original page select and set it to 5 */ + ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, + &default_page); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE, + &phy_data); + if (ret_val) + goto out; + + index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT; + if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) { + ret_val = -E1000_ERR_PHY; + goto out; + } + + phy->min_cable_length = e1000_m88_cable_length_table[index]; + phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; + + phy->cable_length = (phy->min_cable_length + + phy->max_cable_length) / 2; + + /* Reset the page select to its original value */ + ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, + default_page); + if (ret_val) + goto out; + + break; + default: + ret_val = -E1000_ERR_PHY; + goto out; + } + +out: + return ret_val; +} + /** * igb_get_cable_length_igp_2 - Determine cable length for igp2 PHY * @hw: pointer to the HW structure diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h index 565a6dbb3714..2cc117705a31 100644 --- a/drivers/net/igb/e1000_phy.h +++ b/drivers/net/igb/e1000_phy.h @@ -45,9 +45,11 @@ s32 igb_check_downshift(struct e1000_hw *hw); s32 igb_check_reset_block(struct e1000_hw *hw); s32 igb_copper_link_setup_igp(struct e1000_hw *hw); s32 igb_copper_link_setup_m88(struct e1000_hw *hw); +s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw); s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw); s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw); s32 igb_get_cable_length_m88(struct e1000_hw *hw); +s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw); s32 igb_get_cable_length_igp_2(struct e1000_hw *hw); s32 igb_get_phy_id(struct e1000_hw *hw); s32 igb_get_phy_info_igp(struct e1000_hw *hw); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index fd922e7db1d5..61892b80d7ad 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -71,6 +71,8 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 }, -- cgit v1.2.2 From 7b872a55c40b7e6f5e257c252f96dde911bd7b2f Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 22 Sep 2010 17:57:58 +0000 Subject: e1000/e1000e/igb/ixgb/ixgbe: set NETIF_F_HIGHDMA for VLAN feature flags If the netdev->features is set with NETIF_F_HIGHDMA, we should set the corresponding netdev->vlan_features as well to allow VLAN netdev created on top of the real netdev to be able to also benefit from HIGHDMA on 32bit system, reducing the performance hit that is caused by __skb_linearize(), particularly for large send. This is fixed in this patch for all Intel e1000, e1000e, igb, ixgbe, and ixgbe drivers since this should be beneficial to all devices supported by these drivers. Signed-off-by: Yi Zou Tested-by: Emil Tantilov Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 61892b80d7ad..f915e9cb302e 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1858,8 +1858,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, netdev->vlan_features |= NETIF_F_IPV6_CSUM; netdev->vlan_features |= NETIF_F_SG; - if (pci_using_dac) + if (pci_using_dac) { netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= NETIF_F_HIGHDMA; + } if (hw->mac.type >= e1000_82576) netdev->features |= NETIF_F_SCTP_CSUM; -- cgit v1.2.2 From 807540baae406c84dcb9c1c8ef07a56d2d2ae84a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 23 Sep 2010 05:40:09 +0000 Subject: drivers/net: return operator cleanup Change "return (EXPR);" to "return EXPR;" return is not a function, parentheses are not required. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index f915e9cb302e..0394ca95f3ba 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -5435,7 +5435,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) tx_ring->total_packets += total_packets; tx_ring->tx_stats.bytes += total_bytes; tx_ring->tx_stats.packets += total_packets; - return (count < tx_ring->count); + return count < tx_ring->count; } /** -- cgit v1.2.2 From 21adef3e2959160df31f8516883431e5595f9e50 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 27 Sep 2010 08:28:39 +0000 Subject: igb: Use netif_set_real_num_{rx,tx}_queues() Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 0394ca95f3ba..55edcb74abf4 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -988,7 +988,7 @@ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter) * Attempt to configure interrupts using the best available * capabilities of the hardware and kernel. **/ -static void igb_set_interrupt_capability(struct igb_adapter *adapter) +static int igb_set_interrupt_capability(struct igb_adapter *adapter) { int err; int numvecs, i; @@ -1054,8 +1054,10 @@ msi_only: if (!pci_enable_msi(adapter->pdev)) adapter->flags |= IGB_FLAG_HAS_MSI; out: - /* Notify the stack of the (possibly) reduced Tx Queue count. */ - adapter->netdev->real_num_tx_queues = adapter->num_tx_queues; + /* Notify the stack of the (possibly) reduced queue counts. */ + netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues); + return netif_set_real_num_rx_queues(adapter->netdev, + adapter->num_rx_queues); } /** @@ -1154,7 +1156,9 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter) struct pci_dev *pdev = adapter->pdev; int err; - igb_set_interrupt_capability(adapter); + err = igb_set_interrupt_capability(adapter); + if (err) + return err; err = igb_alloc_q_vectors(adapter); if (err) { -- cgit v1.2.2 From cd2638a86c7b90e77ce623c09de2a26177f2a5c1 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Tue, 12 Oct 2010 22:27:02 +0000 Subject: igb: add check for fiber/serdes devices to igb_set_spd_dplx; Signed-off-by: Carolyn Wyborny Tested-by: Emil Tantilov Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 55edcb74abf4..5b04eff2fd23 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -6115,6 +6115,13 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) mac->autoneg = 0; + /* Fiber NIC's only allow 1000 Gbps Full duplex */ + if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes) && + spddplx != (SPEED_1000 + DUPLEX_FULL)) { + dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; + } + switch (spddplx) { case SPEED_10 + DUPLEX_HALF: mac->forced_speed_duplex = ADVERTISE_10_HALF; -- cgit v1.2.2 From 12dcd86b75d571772512676ab301279952efc0b0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 15 Oct 2010 17:27:10 +0000 Subject: igb: fix stats handling There are currently some problems with igb. - On 32bit arches, maintaining 64bit counters without proper synchronization between writers and readers. - Stats updated every two seconds, as reported by Jesper. (Jesper provided a patch for this) - Potential problem between worker thread and ethtool -S This patch uses u64_stats_sync, and convert everything to be 64bit safe, SMP safe, even on 32bit arches. It integrates Jesper idea of providing accurate stats at the time user reads them. Signed-off-by: Eric Dumazet Tested-by: Emil Tantilov Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 9 +++- drivers/net/igb/igb_ethtool.c | 52 +++++++++++++------ drivers/net/igb/igb_main.c | 113 +++++++++++++++++++++++++++++++----------- 3 files changed, 129 insertions(+), 45 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 44e0ff1494e0..edab9c442399 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -159,6 +159,7 @@ struct igb_tx_queue_stats { u64 packets; u64 bytes; u64 restart_queue; + u64 restart_queue2; }; struct igb_rx_queue_stats { @@ -210,11 +211,14 @@ struct igb_ring { /* TX */ struct { struct igb_tx_queue_stats tx_stats; + struct u64_stats_sync tx_syncp; + struct u64_stats_sync tx_syncp2; bool detect_tx_hung; }; /* RX */ struct { struct igb_rx_queue_stats rx_stats; + struct u64_stats_sync rx_syncp; u32 rx_buffer_len; }; }; @@ -288,6 +292,9 @@ struct igb_adapter { struct timecompare compare; struct hwtstamp_config hwtstamp_config; + spinlock_t stats64_lock; + struct rtnl_link_stats64 stats64; + /* structs defined in e1000_hw.h */ struct e1000_hw hw; struct e1000_hw_stats stats; @@ -357,7 +364,7 @@ extern netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *, struct igb_ring *); extern void igb_unmap_and_free_tx_resource(struct igb_ring *, struct igb_buffer *); extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int); -extern void igb_update_stats(struct igb_adapter *); +extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *); extern bool igb_has_link(struct igb_adapter *adapter); extern void igb_set_ethtool_ops(struct net_device *); extern void igb_power_up_link(struct igb_adapter *); diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 26bf6a13d1c1..a70e16bcfa7e 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -90,8 +90,8 @@ static const struct igb_stats igb_gstrings_stats[] = { #define IGB_NETDEV_STAT(_net_stat) { \ .stat_string = __stringify(_net_stat), \ - .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \ - .stat_offset = offsetof(struct net_device_stats, _net_stat) \ + .sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \ + .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \ } static const struct igb_stats igb_gstrings_net_stats[] = { IGB_NETDEV_STAT(rx_errors), @@ -111,8 +111,9 @@ static const struct igb_stats igb_gstrings_net_stats[] = { (sizeof(igb_gstrings_net_stats) / sizeof(struct igb_stats)) #define IGB_RX_QUEUE_STATS_LEN \ (sizeof(struct igb_rx_queue_stats) / sizeof(u64)) -#define IGB_TX_QUEUE_STATS_LEN \ - (sizeof(struct igb_tx_queue_stats) / sizeof(u64)) + +#define IGB_TX_QUEUE_STATS_LEN 3 /* packets, bytes, restart_queue */ + #define IGB_QUEUE_STATS_LEN \ ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \ IGB_RX_QUEUE_STATS_LEN) + \ @@ -2070,12 +2071,14 @@ static void igb_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct igb_adapter *adapter = netdev_priv(netdev); - struct net_device_stats *net_stats = &netdev->stats; - u64 *queue_stat; - int i, j, k; + struct rtnl_link_stats64 *net_stats = &adapter->stats64; + unsigned int start; + struct igb_ring *ring; + int i, j; char *p; - igb_update_stats(adapter); + spin_lock(&adapter->stats64_lock); + igb_update_stats(adapter, net_stats); for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { p = (char *)adapter + igb_gstrings_stats[i].stat_offset; @@ -2088,15 +2091,36 @@ static void igb_get_ethtool_stats(struct net_device *netdev, sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } for (j = 0; j < adapter->num_tx_queues; j++) { - queue_stat = (u64 *)&adapter->tx_ring[j]->tx_stats; - for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++) - data[i] = queue_stat[k]; + u64 restart2; + + ring = adapter->tx_ring[j]; + do { + start = u64_stats_fetch_begin_bh(&ring->tx_syncp); + data[i] = ring->tx_stats.packets; + data[i+1] = ring->tx_stats.bytes; + data[i+2] = ring->tx_stats.restart_queue; + } while (u64_stats_fetch_retry_bh(&ring->tx_syncp, start)); + do { + start = u64_stats_fetch_begin_bh(&ring->tx_syncp2); + restart2 = ring->tx_stats.restart_queue2; + } while (u64_stats_fetch_retry_bh(&ring->tx_syncp2, start)); + data[i+2] += restart2; + + i += IGB_TX_QUEUE_STATS_LEN; } for (j = 0; j < adapter->num_rx_queues; j++) { - queue_stat = (u64 *)&adapter->rx_ring[j]->rx_stats; - for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++) - data[i] = queue_stat[k]; + ring = adapter->rx_ring[j]; + do { + start = u64_stats_fetch_begin_bh(&ring->rx_syncp); + data[i] = ring->rx_stats.packets; + data[i+1] = ring->rx_stats.bytes; + data[i+2] = ring->rx_stats.drops; + data[i+3] = ring->rx_stats.csum_err; + data[i+4] = ring->rx_stats.alloc_failed; + } while (u64_stats_fetch_retry_bh(&ring->rx_syncp, start)); + i += IGB_RX_QUEUE_STATS_LEN; } + spin_unlock(&adapter->stats64_lock); } static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 5b04eff2fd23..b8dccc0ac089 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -96,7 +96,6 @@ static int igb_setup_all_rx_resources(struct igb_adapter *); static void igb_free_all_tx_resources(struct igb_adapter *); static void igb_free_all_rx_resources(struct igb_adapter *); static void igb_setup_mrqc(struct igb_adapter *); -void igb_update_stats(struct igb_adapter *); static int igb_probe(struct pci_dev *, const struct pci_device_id *); static void __devexit igb_remove(struct pci_dev *pdev); static int igb_sw_init(struct igb_adapter *); @@ -113,7 +112,8 @@ static void igb_update_phy_info(unsigned long); static void igb_watchdog(unsigned long); static void igb_watchdog_task(struct work_struct *); static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *); -static struct net_device_stats *igb_get_stats(struct net_device *); +static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats); static int igb_change_mtu(struct net_device *, int); static int igb_set_mac(struct net_device *, void *); static void igb_set_uta(struct igb_adapter *adapter); @@ -1536,7 +1536,9 @@ void igb_down(struct igb_adapter *adapter) netif_carrier_off(netdev); /* record the stats before reset*/ - igb_update_stats(adapter); + spin_lock(&adapter->stats64_lock); + igb_update_stats(adapter, &adapter->stats64); + spin_unlock(&adapter->stats64_lock); adapter->link_speed = 0; adapter->link_duplex = 0; @@ -1689,7 +1691,7 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_open = igb_open, .ndo_stop = igb_close, .ndo_start_xmit = igb_xmit_frame_adv, - .ndo_get_stats = igb_get_stats, + .ndo_get_stats64 = igb_get_stats64, .ndo_set_rx_mode = igb_set_rx_mode, .ndo_set_multicast_list = igb_set_rx_mode, .ndo_set_mac_address = igb_set_mac, @@ -2276,6 +2278,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + spin_lock_init(&adapter->stats64_lock); #ifdef CONFIG_PCI_IOV if (hw->mac.type == e1000_82576) adapter->vfs_allocated_count = (max_vfs > 7) ? 7 : max_vfs; @@ -3483,7 +3486,9 @@ static void igb_watchdog_task(struct work_struct *work) } } - igb_update_stats(adapter); + spin_lock(&adapter->stats64_lock); + igb_update_stats(adapter, &adapter->stats64); + spin_unlock(&adapter->stats64_lock); for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *tx_ring = adapter->tx_ring[i]; @@ -3550,6 +3555,8 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector) int new_val = q_vector->itr_val; int avg_wire_size = 0; struct igb_adapter *adapter = q_vector->adapter; + struct igb_ring *ring; + unsigned int packets; /* For non-gigabit speeds, just fix the interrupt rate at 4000 * ints/sec - ITR timer value of 120 ticks. @@ -3559,16 +3566,21 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector) goto set_itr_val; } - if (q_vector->rx_ring && q_vector->rx_ring->total_packets) { - struct igb_ring *ring = q_vector->rx_ring; - avg_wire_size = ring->total_bytes / ring->total_packets; + ring = q_vector->rx_ring; + if (ring) { + packets = ACCESS_ONCE(ring->total_packets); + + if (packets) + avg_wire_size = ring->total_bytes / packets; } - if (q_vector->tx_ring && q_vector->tx_ring->total_packets) { - struct igb_ring *ring = q_vector->tx_ring; - avg_wire_size = max_t(u32, avg_wire_size, - (ring->total_bytes / - ring->total_packets)); + ring = q_vector->tx_ring; + if (ring) { + packets = ACCESS_ONCE(ring->total_packets); + + if (packets) + avg_wire_size = max_t(u32, avg_wire_size, + ring->total_bytes / packets); } /* if avg_wire_size isn't set no work was done */ @@ -4077,7 +4089,11 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, int size) /* A reprieve! */ netif_wake_subqueue(netdev, tx_ring->queue_index); - tx_ring->tx_stats.restart_queue++; + + u64_stats_update_begin(&tx_ring->tx_syncp2); + tx_ring->tx_stats.restart_queue2++; + u64_stats_update_end(&tx_ring->tx_syncp2); + return 0; } @@ -4214,16 +4230,22 @@ static void igb_reset_task(struct work_struct *work) } /** - * igb_get_stats - Get System Network Statistics + * igb_get_stats64 - Get System Network Statistics * @netdev: network interface device structure + * @stats: rtnl_link_stats64 pointer * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. **/ -static struct net_device_stats *igb_get_stats(struct net_device *netdev) +static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) { - /* only return the current stats */ - return &netdev->stats; + struct igb_adapter *adapter = netdev_priv(netdev); + + spin_lock(&adapter->stats64_lock); + igb_update_stats(adapter, &adapter->stats64); + memcpy(stats, &adapter->stats64, sizeof(*stats)); + spin_unlock(&adapter->stats64_lock); + + return stats; } /** @@ -4305,15 +4327,17 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) * @adapter: board private structure **/ -void igb_update_stats(struct igb_adapter *adapter) +void igb_update_stats(struct igb_adapter *adapter, + struct rtnl_link_stats64 *net_stats) { - struct net_device_stats *net_stats = igb_get_stats(adapter->netdev); struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; u32 reg, mpc; u16 phy_tmp; int i; u64 bytes, packets; + unsigned int start; + u64 _bytes, _packets; #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF @@ -4331,10 +4355,17 @@ void igb_update_stats(struct igb_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) { u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF; struct igb_ring *ring = adapter->rx_ring[i]; + ring->rx_stats.drops += rqdpc_tmp; net_stats->rx_fifo_errors += rqdpc_tmp; - bytes += ring->rx_stats.bytes; - packets += ring->rx_stats.packets; + + do { + start = u64_stats_fetch_begin_bh(&ring->rx_syncp); + _bytes = ring->rx_stats.bytes; + _packets = ring->rx_stats.packets; + } while (u64_stats_fetch_retry_bh(&ring->rx_syncp, start)); + bytes += _bytes; + packets += _packets; } net_stats->rx_bytes = bytes; @@ -4344,8 +4375,13 @@ void igb_update_stats(struct igb_adapter *adapter) packets = 0; for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *ring = adapter->tx_ring[i]; - bytes += ring->tx_stats.bytes; - packets += ring->tx_stats.packets; + do { + start = u64_stats_fetch_begin_bh(&ring->tx_syncp); + _bytes = ring->tx_stats.bytes; + _packets = ring->tx_stats.packets; + } while (u64_stats_fetch_retry_bh(&ring->tx_syncp, start)); + bytes += _bytes; + packets += _packets; } net_stats->tx_bytes = bytes; net_stats->tx_packets = packets; @@ -5397,7 +5433,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) && !(test_bit(__IGB_DOWN, &adapter->state))) { netif_wake_subqueue(netdev, tx_ring->queue_index); + + u64_stats_update_begin(&tx_ring->tx_syncp); tx_ring->tx_stats.restart_queue++; + u64_stats_update_end(&tx_ring->tx_syncp); } } @@ -5437,8 +5476,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) } tx_ring->total_bytes += total_bytes; tx_ring->total_packets += total_packets; + u64_stats_update_begin(&tx_ring->tx_syncp); tx_ring->tx_stats.bytes += total_bytes; tx_ring->tx_stats.packets += total_packets; + u64_stats_update_end(&tx_ring->tx_syncp); return count < tx_ring->count; } @@ -5480,9 +5521,11 @@ static inline void igb_rx_checksum_adv(struct igb_ring *ring, * packets, (aka let the stack check the crc32c) */ if ((skb->len == 60) && - (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM)) + (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM)) { + u64_stats_update_begin(&ring->rx_syncp); ring->rx_stats.csum_err++; - + u64_stats_update_end(&ring->rx_syncp); + } /* let the stack verify checksum errors */ return; } @@ -5669,8 +5712,10 @@ next_desc: rx_ring->total_packets += total_packets; rx_ring->total_bytes += total_bytes; + u64_stats_update_begin(&rx_ring->rx_syncp); rx_ring->rx_stats.packets += total_packets; rx_ring->rx_stats.bytes += total_bytes; + u64_stats_update_end(&rx_ring->rx_syncp); return cleaned; } @@ -5698,8 +5743,10 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) if ((bufsz < IGB_RXBUFFER_1024) && !buffer_info->page_dma) { if (!buffer_info->page) { buffer_info->page = netdev_alloc_page(netdev); - if (!buffer_info->page) { + if (unlikely(!buffer_info->page)) { + u64_stats_update_begin(&rx_ring->rx_syncp); rx_ring->rx_stats.alloc_failed++; + u64_stats_update_end(&rx_ring->rx_syncp); goto no_buffers; } buffer_info->page_offset = 0; @@ -5714,7 +5761,9 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) if (dma_mapping_error(rx_ring->dev, buffer_info->page_dma)) { buffer_info->page_dma = 0; + u64_stats_update_begin(&rx_ring->rx_syncp); rx_ring->rx_stats.alloc_failed++; + u64_stats_update_end(&rx_ring->rx_syncp); goto no_buffers; } } @@ -5722,8 +5771,10 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) skb = buffer_info->skb; if (!skb) { skb = netdev_alloc_skb_ip_align(netdev, bufsz); - if (!skb) { + if (unlikely(!skb)) { + u64_stats_update_begin(&rx_ring->rx_syncp); rx_ring->rx_stats.alloc_failed++; + u64_stats_update_end(&rx_ring->rx_syncp); goto no_buffers; } @@ -5737,7 +5788,9 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) if (dma_mapping_error(rx_ring->dev, buffer_info->dma)) { buffer_info->dma = 0; + u64_stats_update_begin(&rx_ring->rx_syncp); rx_ring->rx_stats.alloc_failed++; + u64_stats_update_end(&rx_ring->rx_syncp); goto no_buffers; } } -- cgit v1.2.2 From b738127dfb469bb9f595cdace30e7f881e8146b2 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Wed, 20 Oct 2010 13:56:02 +0000 Subject: vlan: Rename VLAN_GROUP_ARRAY_LEN to VLAN_N_VID. VLAN_GROUP_ARRAY_LEN is simply the number of possible vlan VIDs. Since vlan groups will soon be more of an implementation detail for vlan devices, rename the constant to be descriptive of its actual purpose. Signed-off-by: Jesse Gross Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index b8dccc0ac089..0f0939caf091 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -6153,7 +6153,7 @@ static void igb_restore_vlan(struct igb_adapter *adapter) if (adapter->vlgrp) { u16 vid; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; igb_vlan_rx_add_vid(adapter->netdev, vid); -- cgit v1.2.2 From eab6d18d20fc5b5ba04a7e7fcd6f357197870e51 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Wed, 20 Oct 2010 13:56:03 +0000 Subject: vlan: Don't check for vlan group before vlan_tx_tag_present. Many (but not all) drivers check to see whether there is a vlan group configured before using a tag stored in the skb. There's not much point in this check since it just throws away data that should only be present in the expected circumstances. However, it will soon be legal and expected to get a vlan tag when no vlan group is configured, so remove this check from all drivers to avoid dropping the tags. Signed-off-by: Jesse Gross Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 0f0939caf091..75155a27fdde 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4128,7 +4128,7 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, tx_flags |= IGB_TX_FLAGS_TSTAMP; } - if (vlan_tx_tag_present(skb) && adapter->vlgrp) { + if (vlan_tx_tag_present(skb)) { tx_flags |= IGB_TX_FLAGS_VLAN; tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT); } -- cgit v1.2.2 From c1758012971e0410790b2bc96a77e26d7b286593 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Tue, 26 Oct 2010 14:56:03 +0000 Subject: igb: Fix unused variable warning. Commit eab6d18d "vlan: Don't check for vlan group before vlan_tx_tag_present" removed the need for the adapter variable in igb_xmit_frame_ring_adv(). This removes the variable as well to avoid the compiler warning. Reported-by: Stephen Rothwell Signed-off-by: Jesse Gross Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 14db09e2fa8b..892d196f17ac 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4107,7 +4107,6 @@ static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, int size) netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, struct igb_ring *tx_ring) { - struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); int tso = 0, count; u32 tx_flags = 0; u16 first; -- cgit v1.2.2 From 89bf67f1f080c947c92f8773482d9e57767ca292 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 22 Nov 2010 00:15:06 +0000 Subject: drivers/net: use vzalloc() Use vzalloc() and vzalloc_node() in net drivers Signed-off-by: Eric Dumazet Acked-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 892d196f17ac..67ea262e482a 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2436,10 +2436,9 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring) int size; size = sizeof(struct igb_buffer) * tx_ring->count; - tx_ring->buffer_info = vmalloc(size); + tx_ring->buffer_info = vzalloc(size); if (!tx_ring->buffer_info) goto err; - memset(tx_ring->buffer_info, 0, size); /* round up to nearest 4K */ tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); @@ -2587,10 +2586,9 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring) int size, desc_len; size = sizeof(struct igb_buffer) * rx_ring->count; - rx_ring->buffer_info = vmalloc(size); + rx_ring->buffer_info = vzalloc(size); if (!rx_ring->buffer_info) goto err; - memset(rx_ring->buffer_info, 0, size); desc_len = sizeof(union e1000_adv_rx_desc); -- cgit v1.2.2 From 667445008db3f45a760c235d771be0c9671e59e5 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Wed, 1 Dec 2010 19:59:50 +0000 Subject: Intel Wired LAN drivers: Use static const Based on work by Joe Perches Using static const to decrease data and overall object size. CC: Joe Perches Signed-off-by: Jeff Kirsher Tested-by: Emil Tantilov --- drivers/net/igb/e1000_phy.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index ddd036a78999..6694bf3e5ad9 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -1757,11 +1757,12 @@ s32 igb_get_cable_length_igp_2(struct e1000_hw *hw) u16 phy_data, i, agc_value = 0; u16 cur_agc_index, max_agc_index = 0; u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; - u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = - {IGP02E1000_PHY_AGC_A, - IGP02E1000_PHY_AGC_B, - IGP02E1000_PHY_AGC_C, - IGP02E1000_PHY_AGC_D}; + static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = { + IGP02E1000_PHY_AGC_A, + IGP02E1000_PHY_AGC_B, + IGP02E1000_PHY_AGC_C, + IGP02E1000_PHY_AGC_D + }; /* Read the AGC registers for all channels */ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { -- cgit v1.2.2 From 9835fd7321a67feba6432e63bf2cba43f5a56bd9 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Mon, 22 Nov 2010 17:17:21 +0000 Subject: igb: Add new function to read part number from EEPROM in string format New adapters will have part numbers stored in string format rather than simple hex format. This function will read part number formats in either hex or string. Signed-off-by: Carolyn Wyborny Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_defines.h | 7 ++++ drivers/net/igb/e1000_nvm.c | 93 ++++++++++++++++++++++++++++++++++++++--- drivers/net/igb/e1000_nvm.h | 2 + drivers/net/igb/igb_main.c | 11 ++--- 4 files changed, 102 insertions(+), 11 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 62222796a8b3..6319ed902bc0 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -419,6 +419,9 @@ #define E1000_ERR_SWFW_SYNC 13 #define E1000_NOT_IMPLEMENTED 14 #define E1000_ERR_MBX 15 +#define E1000_ERR_INVALID_ARGUMENT 16 +#define E1000_ERR_NO_SPACE 17 +#define E1000_ERR_NVM_PBA_SECTION 18 /* Loop limit on how long we wait for auto-negotiation to complete */ #define COPPER_LINK_UP_LIMIT 10 @@ -580,11 +583,15 @@ /* Mask bits for fields in Word 0x1a of the NVM */ +/* length of string needed to store part num */ +#define E1000_PBANUM_LENGTH 11 + /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ #define NVM_SUM 0xBABA #define NVM_PBA_OFFSET_0 8 #define NVM_PBA_OFFSET_1 9 +#define NVM_PBA_PTR_GUARD 0xFAFA #define NVM_WORD_SIZE_BASE_SHIFT 6 /* NVM Commands - Microwire */ diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c index d83b77fa4038..6b5cc2cc453d 100644 --- a/drivers/net/igb/e1000_nvm.c +++ b/drivers/net/igb/e1000_nvm.c @@ -445,31 +445,112 @@ out: } /** - * igb_read_part_num - Read device part number + * igb_read_part_string - Read device part number * @hw: pointer to the HW structure * @part_num: pointer to device part number + * @part_num_size: size of part number buffer * * Reads the product board assembly (PBA) number from the EEPROM and stores * the value in part_num. **/ -s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num) +s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size) { - s32 ret_val; + s32 ret_val; u16 nvm_data; + u16 pointer; + u16 offset; + u16 length; + + if (part_num == NULL) { + hw_dbg("PBA string buffer was null\n"); + ret_val = E1000_ERR_INVALID_ARGUMENT; + goto out; + } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { hw_dbg("NVM Read Error\n"); goto out; } - *part_num = (u32)(nvm_data << 16); - ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pointer); + if (ret_val) { + hw_dbg("NVM Read Error\n"); + goto out; + } + + /* + * if nvm_data is not ptr guard the PBA must be in legacy format which + * means pointer is actually our second data word for the PBA number + * and we can decode it into an ascii string + */ + if (nvm_data != NVM_PBA_PTR_GUARD) { + hw_dbg("NVM PBA number is not stored as string\n"); + + /* we will need 11 characters to store the PBA */ + if (part_num_size < 11) { + hw_dbg("PBA string buffer too small\n"); + return E1000_ERR_NO_SPACE; + } + + /* extract hex string from data and pointer */ + part_num[0] = (nvm_data >> 12) & 0xF; + part_num[1] = (nvm_data >> 8) & 0xF; + part_num[2] = (nvm_data >> 4) & 0xF; + part_num[3] = nvm_data & 0xF; + part_num[4] = (pointer >> 12) & 0xF; + part_num[5] = (pointer >> 8) & 0xF; + part_num[6] = '-'; + part_num[7] = 0; + part_num[8] = (pointer >> 4) & 0xF; + part_num[9] = pointer & 0xF; + + /* put a null character on the end of our string */ + part_num[10] = '\0'; + + /* switch all the data but the '-' to hex char */ + for (offset = 0; offset < 10; offset++) { + if (part_num[offset] < 0xA) + part_num[offset] += '0'; + else if (part_num[offset] < 0x10) + part_num[offset] += 'A' - 0xA; + } + + goto out; + } + + ret_val = hw->nvm.ops.read(hw, pointer, 1, &length); if (ret_val) { hw_dbg("NVM Read Error\n"); goto out; } - *part_num |= nvm_data; + + if (length == 0xFFFF || length == 0) { + hw_dbg("NVM PBA number section invalid length\n"); + ret_val = E1000_ERR_NVM_PBA_SECTION; + goto out; + } + /* check if part_num buffer is big enough */ + if (part_num_size < (((u32)length * 2) - 1)) { + hw_dbg("PBA string buffer too small\n"); + ret_val = E1000_ERR_NO_SPACE; + goto out; + } + + /* trim pba length from start of string */ + pointer++; + length--; + + for (offset = 0; offset < length; offset++) { + ret_val = hw->nvm.ops.read(hw, pointer + offset, 1, &nvm_data); + if (ret_val) { + hw_dbg("NVM Read Error\n"); + goto out; + } + part_num[offset * 2] = (u8)(nvm_data >> 8); + part_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); + } + part_num[offset * 2] = '\0'; out: return ret_val; diff --git a/drivers/net/igb/e1000_nvm.h b/drivers/net/igb/e1000_nvm.h index 1041c34dcbe1..29c956a84bd0 100644 --- a/drivers/net/igb/e1000_nvm.h +++ b/drivers/net/igb/e1000_nvm.h @@ -32,6 +32,8 @@ s32 igb_acquire_nvm(struct e1000_hw *hw); void igb_release_nvm(struct e1000_hw *hw); s32 igb_read_mac_addr(struct e1000_hw *hw); s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num); +s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, + u32 part_num_size); s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 igb_validate_nvm_checksum(struct e1000_hw *hw); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 67ea262e482a..041f8e6f74f4 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1729,12 +1729,13 @@ static int __devinit igb_probe(struct pci_dev *pdev, struct igb_adapter *adapter; struct e1000_hw *hw; u16 eeprom_data = 0; + s32 ret_val; static int global_quad_port_a; /* global quad port a indication */ const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; unsigned long mmio_start, mmio_len; int err, pci_using_dac; u16 eeprom_apme_mask = IGB_EEPROM_APME; - u32 part_num; + u8 part_str[E1000_PBANUM_LENGTH]; /* Catch broken hardware that put the wrong VF device ID in * the PCIe SR-IOV capability. @@ -2000,10 +2001,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, "unknown"), netdev->dev_addr); - igb_read_part_num(hw, &part_num); - dev_info(&pdev->dev, "%s: PBA No: %06x-%03x\n", netdev->name, - (part_num >> 8), (part_num & 0xff)); - + ret_val = igb_read_part_string(hw, part_str, E1000_PBANUM_LENGTH); + if (ret_val) + strcpy(part_str, "Unknown"); + dev_info(&pdev->dev, "%s: PBA No: %s\n", netdev->name, part_str); dev_info(&pdev->dev, "Using %s interrupts. %d rx queue(s), %d tx queue(s)\n", adapter->msix_entries ? "MSI-X" : -- cgit v1.2.2 From 760141a53e5d72d4cc1d8c6e2a0232a24bedb36b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Dec 2010 16:45:14 +0100 Subject: igb[v],ixgbe: don't use flush_scheduled_work() All three drivers use flush_scheduled_work() similarly during driver detach. Replace it with explicit cancels. Signed-off-by: Tejun Heo Cc: "David S. Miller" Cc: e1000-devel@lists.sourceforge.net Cc: netdev@vger.kernel.org --- drivers/net/igb/igb_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 041f8e6f74f4..62348fc60e53 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2050,13 +2050,16 @@ static void __devexit igb_remove(struct pci_dev *pdev) struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - /* flush_scheduled work may reschedule our watchdog task, so - * explicitly disable watchdog tasks from being rescheduled */ + /* + * The watchdog timer may be rescheduled, so explicitly + * disable watchdog from being rescheduled. + */ set_bit(__IGB_DOWN, &adapter->state); del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer); - flush_scheduled_work(); + cancel_work_sync(&adapter->reset_task); + cancel_work_sync(&adapter->watchdog_task); #ifdef CONFIG_IGB_DCA if (adapter->flags & IGB_FLAG_DCA_ENABLED) { -- cgit v1.2.2 From 8fa7e0f739b70db14e788efba4960bfc1873d550 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 6 Nov 2010 05:43:21 +0000 Subject: igb: Fix overwrite of the VF's flags The vf flags were being overwritten causing the flag that indicates that the PF has set the VF MAC address to get cleared. This would allow the VF to override the MAC address assigned by the Host VMM using the ip link set command. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 62348fc60e53..be426a4a7240 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1654,7 +1654,7 @@ void igb_reset(struct igb_adapter *adapter) if (adapter->vfs_allocated_count) { int i; for (i = 0 ; i < adapter->vfs_allocated_count; i++) - adapter->vf_data[i].flags = 0; + adapter->vf_data[i].flags &= IGB_VF_FLAG_PF_SET_MAC; /* ping all the active vfs to let them know we are going down */ igb_ping_all_vfs(adapter); @@ -4971,8 +4971,8 @@ static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) { - /* clear flags */ - adapter->vf_data[vf].flags &= ~(IGB_VF_FLAG_PF_SET_MAC); + /* clear flags - except flag that indicates PF has set the MAC */ + adapter->vf_data[vf].flags &= IGB_VF_FLAG_PF_SET_MAC; adapter->vf_data[vf].last_nack = jiffies; /* reset offloads to defaults */ @@ -5026,7 +5026,7 @@ static void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) reg = rd32(E1000_VFRE); wr32(E1000_VFRE, reg | (1 << vf)); - adapter->vf_data[vf].flags = IGB_VF_FLAG_CTS; + adapter->vf_data[vf].flags |= IGB_VF_FLAG_CTS; /* reply to reset with ack and vf mac address */ msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; -- cgit v1.2.2 From a6b5ea353845b3f3d9ac4317c0b3be9cc37c259b Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 6 Nov 2010 05:42:59 +0000 Subject: igb: Warn on attempt to override administratively set MAC/VLAN Print a warning message to the system log when the VF attempts to override administratively set MAC/VLAN configuration. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index be426a4a7240..c9aac7f15cd2 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -5105,7 +5105,14 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) switch ((msgbuf[0] & 0xFFFF)) { case E1000_VF_SET_MAC_ADDR: - retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); + retval = -EINVAL; + if (!(vf_data->flags & IGB_VF_FLAG_PF_SET_MAC)) + retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); + else + dev_warn(&pdev->dev, + "VF %d attempted to override administratively " + "set MAC address\nReload the VF driver to " + "resume operations\n", vf); break; case E1000_VF_SET_PROMISC: retval = igb_set_vf_promisc(adapter, msgbuf, vf); @@ -5117,8 +5124,12 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); break; case E1000_VF_SET_VLAN: - if (adapter->vf_data[vf].pf_vlan) - retval = -1; + retval = -1; + if (vf_data->pf_vlan) + dev_warn(&pdev->dev, + "VF %d attempted to override administratively " + "set VLAN tag\nReload the VF driver to " + "resume operations\n", vf); else retval = igb_set_vf_vlan(adapter, msgbuf, vf); break; -- cgit v1.2.2 From 1b5dda331ff8646a70d247cace45a60035937a9b Mon Sep 17 00:00:00 2001 From: "Gasparakis, Joseph" Date: Thu, 9 Dec 2010 01:41:01 +0000 Subject: igb: Some fine tuning This patch does the following: 1. Changes the existing supported device id's so now DH89xxCC is not supported when EEPROM is not read. 2. Adds two more device ids for DH89xxCC in backplane mode and SFP. 3. Driver now initializes previously possibly uninitialized value in igb_reset_mdicnfg_82580(). Signed-off-by: Joseph Gasparakis Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 4 +++- drivers/net/igb/e1000_hw.h | 6 ++++-- drivers/net/igb/igb_main.c | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index bc183f5487cb..50f6e9649845 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -134,6 +134,8 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) case E1000_DEV_ID_82580_COPPER_DUAL: case E1000_DEV_ID_DH89XXCC_SGMII: case E1000_DEV_ID_DH89XXCC_SERDES: + case E1000_DEV_ID_DH89XXCC_BACKPLANE: + case E1000_DEV_ID_DH89XXCC_SFP: mac->type = e1000_82580; break; case E1000_DEV_ID_I350_COPPER: @@ -1578,7 +1580,7 @@ static s32 igb_reset_mdicnfg_82580(struct e1000_hw *hw) { s32 ret_val = 0; u32 mdicnfg; - u16 nvm_data; + u16 nvm_data = 0; if (hw->mac.type != e1000_82580) goto out; diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index c0b017f8d782..e2638afb8cdc 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -54,8 +54,10 @@ struct e1000_hw; #define E1000_DEV_ID_82580_SERDES 0x1510 #define E1000_DEV_ID_82580_SGMII 0x1511 #define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 -#define E1000_DEV_ID_DH89XXCC_SGMII 0x0436 -#define E1000_DEV_ID_DH89XXCC_SERDES 0x0438 +#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438 +#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A +#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C +#define E1000_DEV_ID_DH89XXCC_SFP 0x0440 #define E1000_DEV_ID_I350_COPPER 0x1521 #define E1000_DEV_ID_I350_FIBER 0x1522 #define E1000_DEV_ID_I350_SERDES 0x1523 diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index c9aac7f15cd2..a364ae69ab37 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -73,6 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 }, -- cgit v1.2.2 From 13800469d40bf4dc9fbed17f4692b2ebe94d4526 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 6 Nov 2010 02:08:26 +0000 Subject: igb: Add Anti-spoofing feature support Add support for the anti-spoofing feature in the HW. Packets from VF devices with spoofed MAC addresses or VLAN tags will be blocked and an event generated. When the watchdog task runs it will call a function to check if any spoof events occurred. If an event was detected then a warning message is dumped to the system log. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 33 ++++++++++++++++++++++++++++++ drivers/net/igb/e1000_82575.h | 5 +++++ drivers/net/igb/e1000_regs.h | 1 + drivers/net/igb/igb.h | 1 + drivers/net/igb/igb_main.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 50f6e9649845..0a2368fa6bc6 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1479,6 +1479,39 @@ out: return ret_val; } +/** + * igb_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing + * @hw: pointer to the hardware struct + * @enable: state to enter, either enabled or disabled + * @pf: Physical Function pool - do not set anti-spoofing for the PF + * + * enables/disables L2 switch anti-spoofing functionality. + **/ +void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) +{ + u32 dtxswc; + + switch (hw->mac.type) { + case e1000_82576: + case e1000_i350: + dtxswc = rd32(E1000_DTXSWC); + if (enable) { + dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK | + E1000_DTXSWC_VLAN_SPOOF_MASK); + /* The PF can spoof - it has to in order to + * support emulation mode NICs */ + dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); + } else { + dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | + E1000_DTXSWC_VLAN_SPOOF_MASK); + } + wr32(E1000_DTXSWC, dtxswc); + break; + default: + break; + } +} + /** * igb_vmdq_set_loopback_pf - enable or disable vmdq loopback * @hw: pointer to the hardware struct diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index cbd1e1259e4d..1d01af2472e7 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -194,6 +194,10 @@ struct e1000_adv_tx_context_desc { #define E1000_NVM_APME_82575 0x0400 #define MAX_NUM_VFS 8 +#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */ +#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */ +#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ +#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8 #define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ /* Easy defines for setting default pool, would normally be left a zero */ @@ -243,6 +247,7 @@ struct e1000_adv_tx_context_desc { /* RX packet buffer size defines */ #define E1000_RXPBS_SIZE_MASK_82576 0x0000007F +void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int); void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool); void igb_vmdq_set_replication_pf(struct e1000_hw *, bool); u16 igb_rxpbs_adjust_82580(u32 data); diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index abb7333a1fbf..8ac83c5190d5 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -301,6 +301,7 @@ #define E1000_VFTE 0x00C90 /* VF Transmit Enables */ #define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ #define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */ +#define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */ #define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */ #define E1000_UTA 0x0A000 /* Unicast Table Array - RW */ #define E1000_IOVTCL 0x05BBC /* IOV Control Register */ diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index edab9c442399..92a4ef09e55c 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -324,6 +324,7 @@ struct igb_adapter { unsigned int vfs_allocated_count; struct vf_data_storage *vf_data; u32 rss_queues; + u32 wvbr; }; #define IGB_FLAG_HAS_MSI (1 << 0) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index a364ae69ab37..58c665b7513d 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3366,6 +3366,45 @@ static void igb_set_rx_mode(struct net_device *netdev) igb_restore_vf_multicasts(adapter); } +static void igb_check_wvbr(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 wvbr = 0; + + switch (hw->mac.type) { + case e1000_82576: + case e1000_i350: + if (!(wvbr = rd32(E1000_WVBR))) + return; + break; + default: + break; + } + + adapter->wvbr |= wvbr; +} + +#define IGB_STAGGERED_QUEUE_OFFSET 8 + +static void igb_spoof_check(struct igb_adapter *adapter) +{ + int j; + + if (!adapter->wvbr) + return; + + for(j = 0; j < adapter->vfs_allocated_count; j++) { + if (adapter->wvbr & (1 << j) || + adapter->wvbr & (1 << (j + IGB_STAGGERED_QUEUE_OFFSET))) { + dev_warn(&adapter->pdev->dev, + "Spoof event(s) detected on VF %d\n", j); + adapter->wvbr &= + ~((1 << j) | + (1 << (j + IGB_STAGGERED_QUEUE_OFFSET))); + } + } +} + /* Need to wait a few seconds after link up to get diagnostic information from * the phy */ static void igb_update_phy_info(unsigned long data) @@ -3525,6 +3564,8 @@ static void igb_watchdog_task(struct work_struct *work) wr32(E1000_ICS, E1000_ICS_RXDMT0); } + igb_spoof_check(adapter); + /* Reset the timer */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, @@ -4521,6 +4562,10 @@ static irqreturn_t igb_msix_other(int irq, void *data) if (icr & E1000_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */ adapter->stats.doosync++; + /* The DMA Out of Sync is also indication of a spoof event + * in IOV mode. Check the Wrong VM Behavior register to + * see if it is really a spoof event. */ + igb_check_wvbr(adapter); } /* Check for a mailbox event */ @@ -6595,6 +6640,8 @@ static void igb_vmm_control(struct igb_adapter *adapter) if (adapter->vfs_allocated_count) { igb_vmdq_set_loopback_pf(hw, true); igb_vmdq_set_replication_pf(hw, true); + igb_vmdq_set_anti_spoofing_pf(hw, true, + adapter->vfs_allocated_count); } else { igb_vmdq_set_loopback_pf(hw, false); igb_vmdq_set_replication_pf(hw, false); -- cgit v1.2.2 From 6493d24f77d8e4fe94913eb504ed9ffebb433402 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Fri, 14 Jan 2011 05:33:46 +0000 Subject: igb: Add support for i340 Quad Port Fiber Adapter This patch enables support for Intel i340 Quad Port Fiber Adapter. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 1 + drivers/net/igb/e1000_hw.h | 1 + drivers/net/igb/igb_main.c | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 0a2368fa6bc6..c1552b6f4a68 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -129,6 +129,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) break; case E1000_DEV_ID_82580_COPPER: case E1000_DEV_ID_82580_FIBER: + case E1000_DEV_ID_82580_QUAD_FIBER: case E1000_DEV_ID_82580_SERDES: case E1000_DEV_ID_82580_SGMII: case E1000_DEV_ID_82580_COPPER_DUAL: diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index e2638afb8cdc..281324e85980 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -54,6 +54,7 @@ struct e1000_hw; #define E1000_DEV_ID_82580_SERDES 0x1510 #define E1000_DEV_ID_82580_SGMII 0x1511 #define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 +#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527 #define E1000_DEV_ID_DH89XXCC_SGMII 0x0438 #define E1000_DEV_ID_DH89XXCC_SERDES 0x043A #define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 58c665b7513d..200cc3209672 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -68,6 +68,7 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_QUAD_FIBER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 }, -- cgit v1.2.2 From 6b78bb1d46cfae6502826ec31a6e9f7222ab3cb4 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Thu, 20 Jan 2011 06:40:45 +0000 Subject: igb: Enable PF side of SR-IOV support for i350 devices This patch adds full support for SR-IOV by enabling the PF side. VF side has already been committed. Signed-off-by: Carolyn Wyborny Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 10 ++++++++-- drivers/net/igb/e1000_mbx.c | 38 ++++++++++++++++++-------------------- drivers/net/igb/igb_main.c | 9 +++++++-- 3 files changed, 33 insertions(+), 24 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index c1552b6f4a68..65c1833244f7 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -238,9 +238,15 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) size = 14; nvm->word_size = 1 << size; - /* if 82576 then initialize mailbox parameters */ - if (mac->type == e1000_82576) + /* if part supports SR-IOV then initialize mailbox parameters */ + switch (mac->type) { + case e1000_82576: + case e1000_i350: igb_init_mbx_params_pf(hw); + break; + default: + break; + } /* setup PHY parameters */ if (phy->media_type != e1000_media_type_copper) { diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c index c474cdb70047..78d48c7fa859 100644 --- a/drivers/net/igb/e1000_mbx.c +++ b/drivers/net/igb/e1000_mbx.c @@ -422,26 +422,24 @@ s32 igb_init_mbx_params_pf(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; - if (hw->mac.type == e1000_82576) { - mbx->timeout = 0; - mbx->usec_delay = 0; - - mbx->size = E1000_VFMAILBOX_SIZE; - - mbx->ops.read = igb_read_mbx_pf; - mbx->ops.write = igb_write_mbx_pf; - mbx->ops.read_posted = igb_read_posted_mbx; - mbx->ops.write_posted = igb_write_posted_mbx; - mbx->ops.check_for_msg = igb_check_for_msg_pf; - mbx->ops.check_for_ack = igb_check_for_ack_pf; - mbx->ops.check_for_rst = igb_check_for_rst_pf; - - mbx->stats.msgs_tx = 0; - mbx->stats.msgs_rx = 0; - mbx->stats.reqs = 0; - mbx->stats.acks = 0; - mbx->stats.rsts = 0; - } + mbx->timeout = 0; + mbx->usec_delay = 0; + + mbx->size = E1000_VFMAILBOX_SIZE; + + mbx->ops.read = igb_read_mbx_pf; + mbx->ops.write = igb_write_mbx_pf; + mbx->ops.read_posted = igb_read_posted_mbx; + mbx->ops.write_posted = igb_write_posted_mbx; + mbx->ops.check_for_msg = igb_check_for_msg_pf; + mbx->ops.check_for_ack = igb_check_for_ack_pf; + mbx->ops.check_for_rst = igb_check_for_rst_pf; + + mbx->stats.msgs_tx = 0; + mbx->stats.msgs_rx = 0; + mbx->stats.reqs = 0; + mbx->stats.acks = 0; + mbx->stats.rsts = 0; return 0; } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 200cc3209672..cb6bf7b815ae 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2287,9 +2287,14 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) spin_lock_init(&adapter->stats64_lock); #ifdef CONFIG_PCI_IOV - if (hw->mac.type == e1000_82576) + switch (hw->mac.type) { + case e1000_82576: + case e1000_i350: adapter->vfs_allocated_count = (max_vfs > 7) ? 7 : max_vfs; - + break; + default: + break; + } #endif /* CONFIG_PCI_IOV */ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); -- cgit v1.2.2 From 17dc566c5ee46e14021e6b8dd89098d3cb237208 Mon Sep 17 00:00:00 2001 From: Lior Levy Date: Tue, 8 Feb 2011 02:28:46 +0000 Subject: igb: add support for VF Transmit rate limit using iproute2 Implemented igb_ndo_set_vf_bw function which is being used by iproute2 tool. In addition, updated igb_ndo_get_vf_config function to show the actual rate limit to the user. The rate limitation can be configured only when the link is up. The rate limit value can be ranged between 0 and actual link speed measured in Mbps. A value of '0' disables the rate limit for this specific VF. iproute2 usage will be 'ip link set ethX vf Y rate Z'. After the command is made, the rate will be changed instantly. To view the current rate limit, use 'ip link show ethX'. The rates will be zeroed only upon driver reload or a link speed change. This feature is being supported only by 82576 device. Signed-off-by: Lior Levy Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_defines.h | 7 ++++ drivers/net/igb/e1000_regs.h | 4 ++ drivers/net/igb/igb.h | 2 + drivers/net/igb/igb_main.c | 88 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 2 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 6319ed902bc0..ff46c91520af 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -770,4 +770,11 @@ #define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision based on DMA coal */ +/* Tx Rate-Scheduler Config fields */ +#define E1000_RTTBCNRC_RS_ENA 0x80000000 +#define E1000_RTTBCNRC_RF_DEC_MASK 0x00003FFF +#define E1000_RTTBCNRC_RF_INT_SHIFT 14 +#define E1000_RTTBCNRC_RF_INT_MASK \ + (E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT) + #endif diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 8ac83c5190d5..3a6f8471aea2 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -106,6 +106,10 @@ #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) +/* TX Rate Limit Registers */ +#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select - WO */ +#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config - WO */ + /* Split and Replication RX Control - RW */ #define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ /* diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 92a4ef09e55c..bbc5ebfe254a 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -77,6 +77,7 @@ struct vf_data_storage { unsigned long last_nack; u16 pf_vlan; /* When set, guest VLAN config not allowed. */ u16 pf_qos; + u16 tx_rate; }; #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ @@ -323,6 +324,7 @@ struct igb_adapter { u16 rx_ring_count; unsigned int vfs_allocated_count; struct vf_data_storage *vf_data; + int vf_rate_link_speed; u32 rss_queues; u32 wvbr; }; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index cb6bf7b815ae..88f8925b2d85 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -150,6 +150,7 @@ static int igb_ndo_set_vf_vlan(struct net_device *netdev, static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi); +static void igb_check_vf_rate_limit(struct igb_adapter *); #ifdef CONFIG_PM static int igb_suspend(struct pci_dev *, pm_message_t); @@ -3511,6 +3512,7 @@ static void igb_watchdog_task(struct work_struct *work) netif_carrier_on(netdev); igb_ping_all_vfs(adapter); + igb_check_vf_rate_limit(adapter); /* link state has changed, schedule phy info update */ if (!test_bit(__IGB_DOWN, &adapter->state)) @@ -6599,9 +6601,91 @@ static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) return igb_set_vf_mac(adapter, vf, mac); } +static int igb_link_mbps(int internal_link_speed) +{ + switch (internal_link_speed) { + case SPEED_100: + return 100; + case SPEED_1000: + return 1000; + default: + return 0; + } +} + +static void igb_set_vf_rate_limit(struct e1000_hw *hw, int vf, int tx_rate, + int link_speed) +{ + int rf_dec, rf_int; + u32 bcnrc_val; + + if (tx_rate != 0) { + /* Calculate the rate factor values to set */ + rf_int = link_speed / tx_rate; + rf_dec = (link_speed - (rf_int * tx_rate)); + rf_dec = (rf_dec * (1<vf_rate_link_speed == 0) || + (adapter->hw.mac.type != e1000_82576)) + return; + + actual_link_speed = igb_link_mbps(adapter->link_speed); + if (actual_link_speed != adapter->vf_rate_link_speed) { + reset_rate = true; + adapter->vf_rate_link_speed = 0; + dev_info(&adapter->pdev->dev, + "Link speed has been changed. VF Transmit " + "rate is disabled\n"); + } + + for (i = 0; i < adapter->vfs_allocated_count; i++) { + if (reset_rate) + adapter->vf_data[i].tx_rate = 0; + + igb_set_vf_rate_limit(&adapter->hw, i, + adapter->vf_data[i].tx_rate, + actual_link_speed); + } +} + static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) { - return -EOPNOTSUPP; + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + int actual_link_speed; + + if (hw->mac.type != e1000_82576) + return -EOPNOTSUPP; + + actual_link_speed = igb_link_mbps(adapter->link_speed); + if ((vf >= adapter->vfs_allocated_count) || + (!(rd32(E1000_STATUS) & E1000_STATUS_LU)) || + (tx_rate < 0) || (tx_rate > actual_link_speed)) + return -EINVAL; + + adapter->vf_rate_link_speed = actual_link_speed; + adapter->vf_data[vf].tx_rate = (u16)tx_rate; + igb_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed); + + return 0; } static int igb_ndo_get_vf_config(struct net_device *netdev, @@ -6612,7 +6696,7 @@ static int igb_ndo_get_vf_config(struct net_device *netdev, return -EINVAL; ivi->vf = vf; memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN); - ivi->tx_rate = 0; + ivi->tx_rate = adapter->vf_data[vf].tx_rate; ivi->vlan = adapter->vf_data[vf].pf_vlan; ivi->qos = adapter->vf_data[vf].pf_qos; return 0; -- cgit v1.2.2 From 4c4b42cb2f7b8273f8e458a23f08b62d89c337f3 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Thu, 17 Feb 2011 09:02:30 +0000 Subject: igb: Update Intel copyright notice for driver source. This fix updates copyright information to include current year 2011. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 88f8925b2d85..a55fa1708baa 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -55,7 +55,7 @@ char igb_driver_name[] = "igb"; char igb_driver_version[] = DRV_VERSION; static const char igb_driver_string[] = "Intel(R) Gigabit Ethernet Network Driver"; -static const char igb_copyright[] = "Copyright (c) 2007-2009 Intel Corporation."; +static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation."; static const struct e1000_info *igb_info_tbl[] = { [board_82575] = &e1000_82575_info, -- cgit v1.2.2 From c2b6a059cf4d527e1e71f384e9e45326bcc8b41f Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Wed, 16 Feb 2011 05:09:46 +0000 Subject: igb: update version string This will synchronize the version with the out of tree driver which shares its functionality. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index a55fa1708baa..579dbba5f9e4 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -50,7 +50,7 @@ #endif #include "igb.h" -#define DRV_VERSION "2.1.0-k2" +#define DRV_VERSION "2.4.13-k2" char igb_driver_name[] = "igb"; char igb_driver_version[] = DRV_VERSION; static const char igb_driver_string[] = -- cgit v1.2.2 From 9b082d734a938b951ed4b9b5a850ae3513d4a7e3 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Thu, 24 Feb 2011 20:03:31 +0000 Subject: igb: warn if max_vfs limit is exceeded Currently there's no warning printed when max_vfs > 7 is specified with igb and the maximum of 7 is silently enforced. This patch prints a warning and informs the user of the actions taken. Signed-off-by: Stefan Assmann Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 579dbba5f9e4..eef380af0537 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2291,7 +2291,12 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) switch (hw->mac.type) { case e1000_82576: case e1000_i350: - adapter->vfs_allocated_count = (max_vfs > 7) ? 7 : max_vfs; + if (max_vfs > 7) { + dev_warn(&pdev->dev, + "Maximum of 7 VFs per PF, using max\n"); + adapter->vfs_allocated_count = 7; + } else + adapter->vfs_allocated_count = max_vfs; break; default: break; -- cgit v1.2.2 From 93ed835928f3100c95e0408df0543f35d03f7c23 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Thu, 24 Feb 2011 03:12:15 +0000 Subject: igb: Fix reg pattern test in ethtool for i350 devices This fixes the reg_pattern_test so that the test does not fail on i350 parts. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index a70e16bcfa7e..16bbd4922bc3 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1070,7 +1070,7 @@ static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { wr32(reg, (_test[pat] & write)); - val = rd32(reg); + val = rd32(reg) & mask; if (val != (_test[pat] & write & mask)) { dev_err(&adapter->pdev->dev, "pattern test reg %04X " "failed: got 0x%08X expected 0x%08X\n", -- cgit v1.2.2 From 3b668a77bad7f03c3df28971760a3883a395ce55 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Wed, 2 Mar 2011 01:11:26 +0000 Subject: igb: Fix strncpy calls to be safe per source code review tools This fix changes the remaining calls to strncpy that have not yet been changed to use the "sizeof(buf) - 1" syntax rather than just a number for buffer size. Signed-off-by: Carolyn Wyborny Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_ethtool.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 16bbd4922bc3..61f7849cb5a7 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -727,8 +727,9 @@ static void igb_get_drvinfo(struct net_device *netdev, char firmware_version[32]; u16 eeprom_data; - strncpy(drvinfo->driver, igb_driver_name, 32); - strncpy(drvinfo->version, igb_driver_version, 32); + strncpy(drvinfo->driver, igb_driver_name, sizeof(drvinfo->driver) - 1); + strncpy(drvinfo->version, igb_driver_version, + sizeof(drvinfo->version) - 1); /* EEPROM image version # is reported as firmware version # for * 82575 controllers */ @@ -738,8 +739,10 @@ static void igb_get_drvinfo(struct net_device *netdev, (eeprom_data & 0x0FF0) >> 4, eeprom_data & 0x000F); - strncpy(drvinfo->fw_version, firmware_version, 32); - strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); + strncpy(drvinfo->fw_version, firmware_version, + sizeof(drvinfo->fw_version) - 1); + strncpy(drvinfo->bus_info, pci_name(adapter->pdev), + sizeof(drvinfo->bus_info) - 1); drvinfo->n_stats = IGB_STATS_LEN; drvinfo->testinfo_len = IGB_TEST_LEN; drvinfo->regdump_len = igb_get_regs_len(netdev); -- cgit v1.2.2 From 0a915b95d67f3bf63121c04aeb4eaebb183feb58 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Sat, 26 Feb 2011 07:42:37 +0000 Subject: igb: Add stats output for OS2BMC feature on i350 devices This patch adds statistics output for OS2BMC feature which is configured by eeprom on capable devices. Signed-off-by: Carolyn Wyborny Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_defines.h | 1 + drivers/net/igb/e1000_hw.h | 4 ++++ drivers/net/igb/e1000_regs.h | 7 +++++++ drivers/net/igb/igb_ethtool.c | 9 ++++++++- drivers/net/igb/igb_main.c | 9 +++++++++ 5 files changed, 29 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index ff46c91520af..92e11da25749 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -110,6 +110,7 @@ /* Management Control */ #define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ #define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ +#define E1000_MANC_EN_BMC2OS 0x10000000 /* OSBMC is Enabled or not */ /* Enable Neighbor Discovery Filtering */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ #define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 281324e85980..eec9ed735588 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -248,6 +248,10 @@ struct e1000_hw_stats { u64 scvpc; u64 hrmpc; u64 doosync; + u64 o2bgptc; + u64 o2bspc; + u64 b2ospc; + u64 b2ogprc; }; struct e1000_phy_stats { diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 3a6f8471aea2..61713548c027 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -328,4 +328,11 @@ /* DMA Coalescing registers */ #define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ + +/* OS2BMC Registers */ +#define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */ +#define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */ +#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */ +#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */ + #endif diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 61f7849cb5a7..78d420b4b2db 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -86,6 +86,10 @@ static const struct igb_stats igb_gstrings_stats[] = { IGB_STAT("tx_smbus", stats.mgptc), IGB_STAT("rx_smbus", stats.mgprc), IGB_STAT("dropped_smbus", stats.mgpdc), + IGB_STAT("os2bmc_rx_by_bmc", stats.o2bgptc), + IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc), + IGB_STAT("os2bmc_tx_by_host", stats.o2bspc), + IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc), }; #define IGB_NETDEV_STAT(_net_stat) { \ @@ -603,7 +607,10 @@ static void igb_get_regs(struct net_device *netdev, regs_buff[548] = rd32(E1000_TDFT); regs_buff[549] = rd32(E1000_TDFHS); regs_buff[550] = rd32(E1000_TDFPC); - + regs_buff[551] = adapter->stats.o2bgptc; + regs_buff[552] = adapter->stats.b2ospc; + regs_buff[553] = adapter->stats.o2bspc; + regs_buff[554] = adapter->stats.b2ogprc; } static int igb_get_eeprom_len(struct net_device *netdev) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index eef380af0537..3666b967846a 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4560,6 +4560,15 @@ void igb_update_stats(struct igb_adapter *adapter, adapter->stats.mgptc += rd32(E1000_MGTPTC); adapter->stats.mgprc += rd32(E1000_MGTPRC); adapter->stats.mgpdc += rd32(E1000_MGTPDC); + + /* OS2BMC Stats */ + reg = rd32(E1000_MANC); + if (reg & E1000_MANC_EN_BMC2OS) { + adapter->stats.o2bgptc += rd32(E1000_O2BGPTC); + adapter->stats.o2bspc += rd32(E1000_O2BSPC); + adapter->stats.b2ospc += rd32(E1000_B2OSPC); + adapter->stats.b2ogprc += rd32(E1000_B2OGPRC); + } } static irqreturn_t igb_msix_other(int irq, void *data) -- cgit v1.2.2 From 09b068d45737abb49320ab25cb4ed2916017ace7 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Fri, 11 Mar 2011 20:42:13 -0800 Subject: igb: Add Energy Efficient Ethernet (EEE) for i350 devices. This patch adds the EEE feature for i350 devices, enabled by default. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 46 ++++++++++++++++++++++++++++++++++++++++- drivers/net/igb/e1000_82575.h | 1 + drivers/net/igb/e1000_defines.h | 7 +++++++ drivers/net/igb/e1000_hw.h | 1 + drivers/net/igb/e1000_regs.h | 4 ++++ drivers/net/igb/igb_main.c | 8 ++++++- 6 files changed, 65 insertions(+), 2 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 65c1833244f7..20d172aeb1c0 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -195,7 +195,11 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) mac->arc_subsystem_valid = (rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK) ? true : false; - + /* enable EEE on i350 parts */ + if (mac->type == e1000_i350) + dev_spec->eee_disable = false; + else + dev_spec->eee_disable = true; /* physical interface link setup */ mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) @@ -1754,6 +1758,46 @@ u16 igb_rxpbs_adjust_82580(u32 data) return ret_val; } +/** + * igb_set_eee_i350 - Enable/disable EEE support + * @hw: pointer to the HW structure + * + * Enable/disable EEE based on setting in dev_spec structure. + * + **/ +s32 igb_set_eee_i350(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u32 ipcnfg, eeer, ctrl_ext; + + ctrl_ext = rd32(E1000_CTRL_EXT); + if ((hw->mac.type != e1000_i350) || + (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK)) + goto out; + ipcnfg = rd32(E1000_IPCNFG); + eeer = rd32(E1000_EEER); + + /* enable or disable per user setting */ + if (!(hw->dev_spec._82575.eee_disable)) { + ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | + E1000_IPCNFG_EEE_100M_AN); + eeer |= (E1000_EEER_TX_LPI_EN | + E1000_EEER_RX_LPI_EN | + E1000_EEER_LPI_FC); + + } else { + ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | + E1000_IPCNFG_EEE_100M_AN); + eeer &= ~(E1000_EEER_TX_LPI_EN | + E1000_EEER_RX_LPI_EN | + E1000_EEER_LPI_FC); + } + wr32(E1000_IPCNFG, ipcnfg); + wr32(E1000_EEER, eeer); +out: + + return ret_val; +} static struct e1000_mac_operations e1000_mac_ops_82575 = { .init_hw = igb_init_hw_82575, .check_for_link = igb_check_for_link_82575, diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index 1d01af2472e7..dd6df3498998 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -251,5 +251,6 @@ void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int); void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool); void igb_vmdq_set_replication_pf(struct e1000_hw *, bool); u16 igb_rxpbs_adjust_82580(u32 data); +s32 igb_set_eee_i350(struct e1000_hw *); #endif diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 92e11da25749..79267813982a 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -758,6 +758,13 @@ #define E1000_MDIC_ERROR 0x40000000 #define E1000_MDIC_DEST 0x80000000 +/* Energy Efficient Ethernet */ +#define E1000_IPCNFG_EEE_1G_AN 0x00000008 /* EEE Enable 1G AN */ +#define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* EEE Enable 100M AN */ +#define E1000_EEER_TX_LPI_EN 0x00010000 /* EEE Tx LPI Enable */ +#define E1000_EEER_RX_LPI_EN 0x00020000 /* EEE Rx LPI Enable */ +#define E1000_EEER_LPI_FC 0x00040000 /* EEE Enable on FC */ + /* SerDes Control */ #define E1000_GEN_CTL_READY 0x80000000 #define E1000_GEN_CTL_ADDRESS_SHIFT 8 diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index eec9ed735588..17569bfe3f2e 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -488,6 +488,7 @@ struct e1000_mbx_info { struct e1000_dev_spec_82575 { bool sgmii_active; bool global_device_reset; + bool eee_disable; }; struct e1000_hw { diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 61713548c027..b2f8e593da87 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -329,6 +329,10 @@ /* DMA Coalescing registers */ #define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ +/* Energy Efficient Ethernet "EEE" register */ +#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */ +#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet */ + /* OS2BMC Registers */ #define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */ #define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */ diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3666b967846a..8643f8c29199 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2014,7 +2014,13 @@ static int __devinit igb_probe(struct pci_dev *pdev, adapter->msix_entries ? "MSI-X" : (adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy", adapter->num_rx_queues, adapter->num_tx_queues); - + switch (hw->mac.type) { + case e1000_i350: + igb_set_eee_i350(hw); + break; + default: + break; + } return 0; err_register: -- cgit v1.2.2 From 4322e561a93ec7ee034b603a6c610e7be90d4e8a Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Fri, 11 Mar 2011 20:43:18 -0800 Subject: igb: Update NVM functions to work with i350 devices This patch adds functions and functions pointers to accommodate differences between NVM interfaces and options for i350 devices, 82580 devices and the rest. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 239 +++++++++++++++++++++++++++++++++++++++- drivers/net/igb/e1000_defines.h | 3 + drivers/net/igb/e1000_hw.h | 3 +- drivers/net/igb/e1000_nvm.c | 64 ++++++++++- drivers/net/igb/e1000_nvm.h | 1 + drivers/net/igb/igb_ethtool.c | 2 +- drivers/net/igb/igb_main.c | 2 +- 7 files changed, 306 insertions(+), 8 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 20d172aeb1c0..6b256c275e10 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -64,7 +64,14 @@ static s32 igb_reset_init_script_82575(struct e1000_hw *); static s32 igb_read_mac_addr_82575(struct e1000_hw *); static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw); static s32 igb_reset_mdicnfg_82580(struct e1000_hw *hw); - +static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw); +static s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw); +static s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, + u16 offset); +static s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw, + u16 offset); +static s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw); +static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw); static const u16 e1000_82580_rxpbs_table[] = { 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 }; @@ -237,10 +244,32 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) */ size += NVM_WORD_SIZE_BASE_SHIFT; - /* EEPROM access above 16k is unsupported */ - if (size > 14) - size = 14; nvm->word_size = 1 << size; + if (nvm->word_size == (1 << 15)) + nvm->page_size = 128; + + /* NVM Function Pointers */ + nvm->ops.acquire = igb_acquire_nvm_82575; + if (nvm->word_size < (1 << 15)) + nvm->ops.read = igb_read_nvm_eerd; + else + nvm->ops.read = igb_read_nvm_spi; + + nvm->ops.release = igb_release_nvm_82575; + switch (hw->mac.type) { + case e1000_82580: + nvm->ops.validate = igb_validate_nvm_checksum_82580; + nvm->ops.update = igb_update_nvm_checksum_82580; + break; + case e1000_i350: + nvm->ops.validate = igb_validate_nvm_checksum_i350; + nvm->ops.update = igb_update_nvm_checksum_i350; + break; + default: + nvm->ops.validate = igb_validate_nvm_checksum; + nvm->ops.update = igb_update_nvm_checksum; + } + nvm->ops.write = igb_write_nvm_spi; /* if part supports SR-IOV then initialize mailbox parameters */ switch (mac->type) { @@ -1758,6 +1787,207 @@ u16 igb_rxpbs_adjust_82580(u32 data) return ret_val; } +/** + * igb_validate_nvm_checksum_with_offset - Validate EEPROM + * checksum + * @hw: pointer to the HW structure + * @offset: offset in words of the checksum protected region + * + * Calculates the EEPROM checksum by reading/adding each word of the EEPROM + * and then verifies that the sum of the EEPROM is equal to 0xBABA. + **/ +s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) +{ + s32 ret_val = 0; + u16 checksum = 0; + u16 i, nvm_data; + + for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) { + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); + if (ret_val) { + hw_dbg("NVM Read Error\n"); + goto out; + } + checksum += nvm_data; + } + + if (checksum != (u16) NVM_SUM) { + hw_dbg("NVM Checksum Invalid\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + +out: + return ret_val; +} + +/** + * igb_update_nvm_checksum_with_offset - Update EEPROM + * checksum + * @hw: pointer to the HW structure + * @offset: offset in words of the checksum protected region + * + * Updates the EEPROM checksum by reading/adding each word of the EEPROM + * up to the checksum. Then calculates the EEPROM checksum and writes the + * value to the EEPROM. + **/ +s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) +{ + s32 ret_val; + u16 checksum = 0; + u16 i, nvm_data; + + for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) { + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); + if (ret_val) { + hw_dbg("NVM Read Error while updating checksum.\n"); + goto out; + } + checksum += nvm_data; + } + checksum = (u16) NVM_SUM - checksum; + ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1, + &checksum); + if (ret_val) + hw_dbg("NVM Write Error while updating checksum.\n"); + +out: + return ret_val; +} + +/** + * igb_validate_nvm_checksum_82580 - Validate EEPROM checksum + * @hw: pointer to the HW structure + * + * Calculates the EEPROM section checksum by reading/adding each word of + * the EEPROM and then verifies that the sum of the EEPROM is + * equal to 0xBABA. + **/ +static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u16 eeprom_regions_count = 1; + u16 j, nvm_data; + u16 nvm_offset; + + ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); + if (ret_val) { + hw_dbg("NVM Read Error\n"); + goto out; + } + + if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { + /* if chekcsums compatibility bit is set validate checksums + * for all 4 ports. */ + eeprom_regions_count = 4; + } + + for (j = 0; j < eeprom_regions_count; j++) { + nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); + ret_val = igb_validate_nvm_checksum_with_offset(hw, + nvm_offset); + if (ret_val != 0) + goto out; + } + +out: + return ret_val; +} + +/** + * igb_update_nvm_checksum_82580 - Update EEPROM checksum + * @hw: pointer to the HW structure + * + * Updates the EEPROM section checksums for all 4 ports by reading/adding + * each word of the EEPROM up to the checksum. Then calculates the EEPROM + * checksum and writes the value to the EEPROM. + **/ +static s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw) +{ + s32 ret_val; + u16 j, nvm_data; + u16 nvm_offset; + + ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); + if (ret_val) { + hw_dbg("NVM Read Error while updating checksum" + " compatibility bit.\n"); + goto out; + } + + if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) { + /* set compatibility bit to validate checksums appropriately */ + nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; + ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, + &nvm_data); + if (ret_val) { + hw_dbg("NVM Write Error while updating checksum" + " compatibility bit.\n"); + goto out; + } + } + + for (j = 0; j < 4; j++) { + nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); + ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset); + if (ret_val) + goto out; + } + +out: + return ret_val; +} + +/** + * igb_validate_nvm_checksum_i350 - Validate EEPROM checksum + * @hw: pointer to the HW structure + * + * Calculates the EEPROM section checksum by reading/adding each word of + * the EEPROM and then verifies that the sum of the EEPROM is + * equal to 0xBABA. + **/ +static s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u16 j; + u16 nvm_offset; + + for (j = 0; j < 4; j++) { + nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); + ret_val = igb_validate_nvm_checksum_with_offset(hw, + nvm_offset); + if (ret_val != 0) + goto out; + } + +out: + return ret_val; +} + +/** + * igb_update_nvm_checksum_i350 - Update EEPROM checksum + * @hw: pointer to the HW structure + * + * Updates the EEPROM section checksums for all 4 ports by reading/adding + * each word of the EEPROM up to the checksum. Then calculates the EEPROM + * checksum and writes the value to the EEPROM. + **/ +static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u16 j; + u16 nvm_offset; + + for (j = 0; j < 4; j++) { + nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); + ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset); + if (ret_val != 0) + goto out; + } + +out: + return ret_val; +} /** * igb_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure @@ -1798,6 +2028,7 @@ out: return ret_val; } + static struct e1000_mac_operations e1000_mac_ops_82575 = { .init_hw = igb_init_hw_82575, .check_for_link = igb_check_for_link_82575, diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 79267813982a..97969ad8afef 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -566,6 +566,8 @@ #define NVM_INIT_CONTROL3_PORT_A 0x0024 #define NVM_ALT_MAC_ADDR_PTR 0x0037 #define NVM_CHECKSUM_REG 0x003F +#define NVM_COMPATIBILITY_REG_3 0x0003 +#define NVM_COMPATIBILITY_BIT_MASK 0x8000 #define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ #define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ @@ -600,6 +602,7 @@ /* NVM Commands - SPI */ #define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ #define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */ +#define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */ #define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ #define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */ #define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */ diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 17569bfe3f2e..27153e8d7b16 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -336,6 +336,8 @@ struct e1000_nvm_operations { s32 (*read)(struct e1000_hw *, u16, u16, u16 *); void (*release)(struct e1000_hw *); s32 (*write)(struct e1000_hw *, u16, u16, u16 *); + s32 (*update)(struct e1000_hw *); + s32 (*validate)(struct e1000_hw *); }; struct e1000_info { @@ -422,7 +424,6 @@ struct e1000_phy_info { struct e1000_nvm_info { struct e1000_nvm_operations ops; - enum e1000_nvm_type type; enum e1000_nvm_override override; diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c index 6b5cc2cc453d..75bf36a4baee 100644 --- a/drivers/net/igb/e1000_nvm.c +++ b/drivers/net/igb/e1000_nvm.c @@ -317,6 +317,68 @@ out: return ret_val; } +/** + * igb_read_nvm_spi - Read EEPROM's using SPI + * @hw: pointer to the HW structure + * @offset: offset of word in the EEPROM to read + * @words: number of words to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM. + **/ +s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 i = 0; + s32 ret_val; + u16 word_in; + u8 read_opcode = NVM_READ_OPCODE_SPI; + + /* + * A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + hw_dbg("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + + ret_val = igb_ready_nvm_eeprom(hw); + if (ret_val) + goto release; + + igb_standby_nvm(hw); + + if ((nvm->address_bits == 8) && (offset >= 128)) + read_opcode |= NVM_A8_OPCODE_SPI; + + /* Send the READ command (opcode + addr) */ + igb_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); + igb_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); + + /* + * Read the data. SPI NVMs increment the address with each byte + * read and will roll over if reading beyond the end. This allows + * us to read the whole NVM from any offset + */ + for (i = 0; i < words; i++) { + word_in = igb_shift_in_eec_bits(hw, 16); + data[i] = (word_in >> 8) | (word_in << 8); + } + +release: + nvm->ops.release(hw); + +out: + return ret_val; +} + /** * igb_read_nvm_eerd - Reads EEPROM using EERD register * @hw: pointer to the HW structure @@ -353,7 +415,7 @@ s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) break; data[i] = (rd32(E1000_EERD) >> - E1000_NVM_RW_REG_DATA); + E1000_NVM_RW_REG_DATA); } out: diff --git a/drivers/net/igb/e1000_nvm.h b/drivers/net/igb/e1000_nvm.h index 29c956a84bd0..7f43564c4bcc 100644 --- a/drivers/net/igb/e1000_nvm.h +++ b/drivers/net/igb/e1000_nvm.h @@ -35,6 +35,7 @@ s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num); s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size); s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 igb_validate_nvm_checksum(struct e1000_hw *hw); s32 igb_update_nvm_checksum(struct e1000_hw *hw); diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 78d420b4b2db..df15a915bbea 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -721,7 +721,7 @@ static int igb_set_eeprom(struct net_device *netdev, /* Update the checksum over the first part of the EEPROM if needed * and flush shadow RAM for 82573 controllers */ if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG))) - igb_update_nvm_checksum(hw); + hw->nvm.ops.update(hw); kfree(eeprom_buff); return ret_val; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 8643f8c29199..8c6af11d93a6 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1884,7 +1884,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, hw->mac.ops.reset_hw(hw); /* make sure the NVM is good */ - if (igb_validate_nvm_checksum(hw) < 0) { + if (hw->nvm.ops.validate(hw) < 0) { dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); err = -EIO; goto err_eeprom; -- cgit v1.2.2 From 831ec0b4226cec7ea34f5c4c9810e78aeb2069bf Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Fri, 11 Mar 2011 20:43:54 -0800 Subject: igb: Add DMA Coalescing feature to driver This patch add DMA Coalescing which is a power-saving feature that coalesces DMA writes in order to stay in a low-power state as much as possible. Feature is disabled by default. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_defines.h | 29 ++++++++++++++++++++- drivers/net/igb/e1000_regs.h | 9 +++++++ drivers/net/igb/igb.h | 6 +++++ drivers/net/igb/igb_ethtool.c | 6 +++++ drivers/net/igb/igb_main.c | 57 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 97969ad8afef..9bb192825893 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -287,7 +287,34 @@ #define E1000_TCTL_COLD 0x003ff000 /* collision distance */ #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ -/* Transmit Arbitration Count */ +/* DMA Coalescing register fields */ +#define E1000_DMACR_DMACWT_MASK 0x00003FFF /* DMA Coalescing + * Watchdog Timer */ +#define E1000_DMACR_DMACTHR_MASK 0x00FF0000 /* DMA Coalescing Receive + * Threshold */ +#define E1000_DMACR_DMACTHR_SHIFT 16 +#define E1000_DMACR_DMAC_LX_MASK 0x30000000 /* Lx when no PCIe + * transactions */ +#define E1000_DMACR_DMAC_LX_SHIFT 28 +#define E1000_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */ + +#define E1000_DMCTXTH_DMCTTHR_MASK 0x00000FFF /* DMA Coalescing Transmit + * Threshold */ + +#define E1000_DMCTLX_TTLX_MASK 0x00000FFF /* Time to LX request */ + +#define E1000_DMCRTRH_UTRESH_MASK 0x0007FFFF /* Receive Traffic Rate + * Threshold */ +#define E1000_DMCRTRH_LRPRCW 0x80000000 /* Rcv packet rate in + * current window */ + +#define E1000_DMCCNT_CCOUNT_MASK 0x01FFFFFF /* DMA Coal Rcv Traffic + * Current Cnt */ + +#define E1000_FCRTC_RTH_COAL_MASK 0x0003FFF0 /* Flow ctrl Rcv Threshold + * High val */ +#define E1000_FCRTC_RTH_COAL_SHIFT 4 +#define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision */ /* SerDes Control */ #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index b2f8e593da87..ad77ed510d7c 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -106,6 +106,15 @@ #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) +/* DMA Coalescing registers */ +#define E1000_DMACR 0x02508 /* Control Register */ +#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */ +#define E1000_DMCTLX 0x02514 /* Time to Lx Request */ +#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */ +#define E1000_DMCCNT 0x05DD4 /* Current Rx Count */ +#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */ +#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ + /* TX Rate Limit Registers */ #define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select - WO */ #define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config - WO */ diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index bbc5ebfe254a..1c687e298d5e 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -333,6 +333,12 @@ struct igb_adapter { #define IGB_FLAG_DCA_ENABLED (1 << 1) #define IGB_FLAG_QUAD_PORT_A (1 << 2) #define IGB_FLAG_QUEUE_PAIRS (1 << 3) +#define IGB_FLAG_DMAC (1 << 4) + +/* DMA Coalescing defines */ +#define IGB_MIN_TXPBSIZE 20408 +#define IGB_TX_BUF_4096 4096 +#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */ #define IGB_82576_TSYNC_SHIFT 19 #define IGB_82580_TSYNC_SHIFT 24 diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index df15a915bbea..d976733bbcc2 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -2009,6 +2009,12 @@ static int igb_set_coalesce(struct net_device *netdev, if ((adapter->flags & IGB_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs) return -EINVAL; + /* If ITR is disabled, disable DMAC */ + if (ec->rx_coalesce_usecs == 0) { + if (adapter->flags & IGB_FLAG_DMAC) + adapter->flags &= ~IGB_FLAG_DMAC; + } + /* convert to rate of irq's per second */ if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) adapter->rx_itr_setting = ec->rx_coalesce_usecs; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 8c6af11d93a6..49476f773825 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1674,7 +1674,58 @@ void igb_reset(struct igb_adapter *adapter) if (hw->mac.ops.init_hw(hw)) dev_err(&pdev->dev, "Hardware Error\n"); + if (hw->mac.type > e1000_82580) { + if (adapter->flags & IGB_FLAG_DMAC) { + u32 reg; + /* + * DMA Coalescing high water mark needs to be higher + * than * the * Rx threshold. The Rx threshold is + * currently * pba - 6, so we * should use a high water + * mark of pba * - 4. */ + hwm = (pba - 4) << 10; + + reg = (((pba-6) << E1000_DMACR_DMACTHR_SHIFT) + & E1000_DMACR_DMACTHR_MASK); + + /* transition to L0x or L1 if available..*/ + reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK); + + /* watchdog timer= +-1000 usec in 32usec intervals */ + reg |= (1000 >> 5); + wr32(E1000_DMACR, reg); + + /* no lower threshold to disable coalescing(smart fifb) + * -UTRESH=0*/ + wr32(E1000_DMCRTRH, 0); + + /* set hwm to PBA - 2 * max frame size */ + wr32(E1000_FCRTC, hwm); + + /* + * This sets the time to wait before requesting tran- + * sition to * low power state to number of usecs needed + * to receive 1 512 * byte frame at gigabit line rate + */ + reg = rd32(E1000_DMCTLX); + reg |= IGB_DMCTLX_DCFLUSH_DIS; + + /* Delay 255 usec before entering Lx state. */ + reg |= 0xFF; + wr32(E1000_DMCTLX, reg); + + /* free space in Tx packet buffer to wake from DMAC */ + wr32(E1000_DMCTXTH, + (IGB_MIN_TXPBSIZE - + (IGB_TX_BUF_4096 + adapter->max_frame_size)) + >> 6); + + /* make low power state decision controlled by DMAC */ + reg = rd32(E1000_PCIEMISC); + reg |= E1000_PCIEMISC_LX_DECISION; + wr32(E1000_PCIEMISC, reg); + } /* end if IGB_FLAG_DMAC set */ + } if (hw->mac.type == e1000_82580) { u32 reg = rd32(E1000_PCIEMISC); wr32(E1000_PCIEMISC, @@ -2157,6 +2208,9 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) random_ether_addr(mac_addr); igb_set_vf_mac(adapter, i, mac_addr); } + /* DMA Coalescing is not supported in IOV mode. */ + if (adapter->flags & IGB_FLAG_DMAC) + adapter->flags &= ~IGB_FLAG_DMAC; } #endif /* CONFIG_PCI_IOV */ } @@ -2331,6 +2385,9 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) /* Explicitly disable IRQ since the NIC can be in any state. */ igb_irq_disable(adapter); + if (hw->mac.type == e1000_i350) + adapter->flags &= ~IGB_FLAG_DMAC; + set_bit(__IGB_DOWN, &adapter->state); return 0; } -- cgit v1.2.2 From 0d1fe82deacdcc90458558b5d6a4a5af5db9a6c6 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Fri, 11 Mar 2011 20:58:19 -0800 Subject: igb: Bump version to 3.0.6 This patch updates igb version to 3.0.6. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 49476f773825..b4f92b06f2ac 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -50,7 +50,12 @@ #endif #include "igb.h" -#define DRV_VERSION "2.4.13-k2" +#define MAJ 3 +#define MIN 0 +#define BUILD 6 +#define KFIX 2 +#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ +__stringify(BUILD) "-k" __stringify(KFIX) char igb_driver_name[] = "igb"; char igb_driver_version[] = DRV_VERSION; static const char igb_driver_string[] = -- cgit v1.2.2 From 673b8b70cfae2cd0428a8ab5647571521348549a Mon Sep 17 00:00:00 2001 From: Anders Berggren Date: Fri, 4 Feb 2011 07:32:32 +0000 Subject: igb: fix hw timestamping Hardware timestamping for Intel 82580 didn't work in either 2.6.36 or 2.6.37. Comparing it to Intel's igb-2.4.12 I found that the timecounter_init clock/counter initialization was done too early. Signed-off-by: Anders Berggren Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index b4f92b06f2ac..5366f2ab65f0 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -106,6 +106,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *); static void igb_setup_mrqc(struct igb_adapter *); static int igb_probe(struct pci_dev *, const struct pci_device_id *); static void __devexit igb_remove(struct pci_dev *pdev); +static void igb_init_hw_timer(struct igb_adapter *adapter); static int igb_sw_init(struct igb_adapter *); static int igb_open(struct net_device *); static int igb_close(struct net_device *); @@ -2048,6 +2049,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, } #endif + /* do hw tstamp init after resetting */ + igb_init_hw_timer(adapter); + dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); /* print bus type/speed/width info */ dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", @@ -2384,7 +2388,6 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) return -ENOMEM; } - igb_init_hw_timer(adapter); igb_probe_vfs(adapter); /* Explicitly disable IRQ since the NIC can be in any state. */ -- cgit v1.2.2 From 7ef5ed1ce96c3f9a95b7327279f94b0700c689ef Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Sat, 12 Mar 2011 08:59:47 +0000 Subject: igb: Add messaging for thermal sensor events on i350 devices This feature adds messaging to the link status change to notify the user if the device returned from a downshift or power off event due to the Thermal Sensor feature in i350 parts. Feature is only available on internal copper ports. Signed-off-by: Carolyn Wyborny Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_defines.h | 5 +++++ drivers/net/igb/e1000_regs.h | 3 +++ drivers/net/igb/igb_main.c | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 9bb192825893..6b80d40110ca 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -51,6 +51,7 @@ #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX 0x00400000 #define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 +#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 #define E1000_CTRL_EXT_EIAME 0x01000000 #define E1000_CTRL_EXT_IRCA 0x00000001 /* Interrupt delay cancellation */ @@ -788,6 +789,10 @@ #define E1000_MDIC_ERROR 0x40000000 #define E1000_MDIC_DEST 0x80000000 +/* Thermal Sensor */ +#define E1000_THSTAT_PWR_DOWN 0x00000001 /* Power Down Event */ +#define E1000_THSTAT_LINK_THROTTLE 0x00000002 /* Link Speed Throttle Event */ + /* Energy Efficient Ethernet */ #define E1000_IPCNFG_EEE_1G_AN 0x00000008 /* EEE Enable 1G AN */ #define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* EEE Enable 100M AN */ diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index ad77ed510d7c..958ca3bda482 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -342,6 +342,9 @@ #define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */ #define E1000_EEER 0x0E30 /* Energy Efficient Ethernet */ +/* Thermal Sensor Register */ +#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */ + /* OS2BMC Registers */ #define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */ #define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */ diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 5366f2ab65f0..3d850af0cdda 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3550,7 +3550,7 @@ static void igb_watchdog_task(struct work_struct *work) watchdog_task); struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - u32 link; + u32 link, ctrl_ext, thstat; int i; link = igb_has_link(adapter); @@ -3574,6 +3574,25 @@ static void igb_watchdog_task(struct work_struct *work) ((ctrl & E1000_CTRL_RFCE) ? "RX" : ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None"))); + /* check for thermal sensor event on i350, + * copper only */ + if (hw->mac.type == e1000_i350) { + thstat = rd32(E1000_THSTAT); + ctrl_ext = rd32(E1000_CTRL_EXT); + if ((hw->phy.media_type == + e1000_media_type_copper) && !(ctrl_ext & + E1000_CTRL_EXT_LINK_MODE_SGMII)) { + if (thstat & + E1000_THSTAT_LINK_THROTTLE) { + printk(KERN_INFO "igb: %s The " + "network adapter link " + "speed was downshifted " + "because it " + "overheated.\n", + netdev->name); + } + } + } /* adjust timeout factor according to speed/duplex */ adapter->tx_timeout_factor = 1; switch (adapter->link_speed) { @@ -3599,6 +3618,22 @@ static void igb_watchdog_task(struct work_struct *work) if (netif_carrier_ok(netdev)) { adapter->link_speed = 0; adapter->link_duplex = 0; + /* check for thermal sensor event on i350 + * copper only*/ + if (hw->mac.type == e1000_i350) { + thstat = rd32(E1000_THSTAT); + ctrl_ext = rd32(E1000_CTRL_EXT); + if ((hw->phy.media_type == + e1000_media_type_copper) && !(ctrl_ext & + E1000_CTRL_EXT_LINK_MODE_SGMII)) { + if (thstat & E1000_THSTAT_PWR_DOWN) { + printk(KERN_ERR "igb: %s The " + "network adapter was stopped " + "because it overheated.\n", + netdev->name); + } + } + } /* Links status message must follow this format */ printk(KERN_INFO "igb: %s NIC Link is Down\n", netdev->name); -- cgit v1.2.2 From 25985edcedea6396277003854657b5f3cb31a628 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 30 Mar 2011 22:57:33 -0300 Subject: Fix common misspellings Fixes generated by 'codespell' and manually reviewed. Signed-off-by: Lucas De Marchi --- drivers/net/igb/e1000_mac.c | 4 ++-- drivers/net/igb/e1000_phy.c | 2 +- drivers/net/igb/igb_main.c | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 90c5e01e9235..ce8255fc3c52 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -181,7 +181,7 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) * address and must override the actual permanent MAC address. If an * alternate MAC address is fopund it is saved in the hw struct and * prgrammed into RAR0 and the cuntion returns success, otherwise the - * fucntion returns an error. + * function returns an error. **/ s32 igb_check_alt_mac_addr(struct e1000_hw *hw) { @@ -982,7 +982,7 @@ out: } /** - * igb_get_speed_and_duplex_copper - Retreive current speed/duplex + * igb_get_speed_and_duplex_copper - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index 6694bf3e5ad9..d639706eb3f6 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -1421,7 +1421,7 @@ out: } /** - * igb_check_downshift - Checks whether a downshift in speed occured + * igb_check_downshift - Checks whether a downshift in speed occurred * @hw: pointer to the HW structure * * Success returns 0, Failure returns 1 diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3d850af0cdda..0dfd1b93829e 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -200,7 +200,7 @@ static struct pci_driver igb_driver = { .probe = igb_probe, .remove = __devexit_p(igb_remove), #ifdef CONFIG_PM - /* Power Managment Hooks */ + /* Power Management Hooks */ .suspend = igb_suspend, .resume = igb_resume, #endif @@ -2292,7 +2292,7 @@ static void igb_init_hw_timer(struct igb_adapter *adapter) /** * Scale the NIC clock cycle by a large factor so that * relatively small clock corrections can be added or - * substracted at each clock tick. The drawbacks of a large + * subtracted at each clock tick. The drawbacks of a large * factor are a) that the clock register overflows more quickly * (not such a big deal) and b) that the increment per tick has * to fit into 24 bits. As a result we need to use a shift of @@ -3409,7 +3409,7 @@ static void igb_set_rx_mode(struct net_device *netdev) } else { /* * Write addresses to the MTA, if the attempt fails - * then we should just turn on promiscous mode so + * then we should just turn on promiscuous mode so * that we can at least receive multicast traffic */ count = igb_write_mc_addr_list(netdev); @@ -3423,7 +3423,7 @@ static void igb_set_rx_mode(struct net_device *netdev) /* * Write addresses to available RAR registers, if there is not * sufficient space to store all the addresses then enable - * unicast promiscous mode + * unicast promiscuous mode */ count = igb_write_uc_addr_list(netdev); if (count < 0) { @@ -4317,7 +4317,7 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, /* * count reflects descriptors mapped, if 0 or less then mapping error - * has occured and we need to rewind the descriptor queue + * has occurred and we need to rewind the descriptor queue */ count = igb_tx_map_adv(tx_ring, skb, first); if (!count) { @@ -5352,8 +5352,8 @@ static void igb_msg_task(struct igb_adapter *adapter) * The unicast table address is a register array of 32-bit registers. * The table is meant to be used in a way similar to how the MTA is used * however due to certain limitations in the hardware it is necessary to - * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscous - * enable bit to allow vlan tag stripping when promiscous mode is enabled + * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous + * enable bit to allow vlan tag stripping when promiscuous mode is enabled **/ static void igb_set_uta(struct igb_adapter *adapter) { -- cgit v1.2.2 From 34a0326e3aaf1d67fe3de55e77e92961c6a9a847 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Tue, 5 Apr 2011 04:27:05 +0000 Subject: igb: fix typo in igb_validate_nvm_checksum_82580 Comment spelling fix. Signed-off-by: Stefan Assmann Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 6b256c275e10..0cd41c49bc17 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1877,7 +1877,7 @@ static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw) } if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { - /* if chekcsums compatibility bit is set validate checksums + /* if checksums compatibility bit is set validate checksums * for all 4 ports. */ eeprom_regions_count = 4; } @@ -1988,6 +1988,7 @@ static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw) out: return ret_val; } + /** * igb_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure -- cgit v1.2.2 From 563988dcfe706457ec7049d59e18d6147179bb0a Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Tue, 5 Apr 2011 04:27:15 +0000 Subject: igb: introduce igb_thermal_sensor_event for sensor checking The code for thermal sensor checking should be wrapped into a function. Signed-off-by: Stefan Assmann Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 67 +++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 33 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 0dfd1b93829e..cdfd57271051 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3532,6 +3532,25 @@ bool igb_has_link(struct igb_adapter *adapter) return link_active; } +static bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event) +{ + bool ret = false; + u32 ctrl_ext, thstat; + + /* check for thermal sensor event on i350, copper only */ + if (hw->mac.type == e1000_i350) { + thstat = rd32(E1000_THSTAT); + ctrl_ext = rd32(E1000_CTRL_EXT); + + if ((hw->phy.media_type == e1000_media_type_copper) && + !(ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII)) { + ret = !!(thstat & event); + } + } + + return ret; +} + /** * igb_watchdog - Timer Call-back * @data: pointer to adapter cast into an unsigned long @@ -3550,7 +3569,7 @@ static void igb_watchdog_task(struct work_struct *work) watchdog_task); struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - u32 link, ctrl_ext, thstat; + u32 link; int i; link = igb_has_link(adapter); @@ -3574,25 +3593,14 @@ static void igb_watchdog_task(struct work_struct *work) ((ctrl & E1000_CTRL_RFCE) ? "RX" : ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None"))); - /* check for thermal sensor event on i350, - * copper only */ - if (hw->mac.type == e1000_i350) { - thstat = rd32(E1000_THSTAT); - ctrl_ext = rd32(E1000_CTRL_EXT); - if ((hw->phy.media_type == - e1000_media_type_copper) && !(ctrl_ext & - E1000_CTRL_EXT_LINK_MODE_SGMII)) { - if (thstat & - E1000_THSTAT_LINK_THROTTLE) { - printk(KERN_INFO "igb: %s The " - "network adapter link " - "speed was downshifted " - "because it " - "overheated.\n", - netdev->name); - } - } + /* check for thermal sensor event */ + if (igb_thermal_sensor_event(hw, E1000_THSTAT_LINK_THROTTLE)) { + printk(KERN_INFO "igb: %s The network adapter " + "link speed was downshifted " + "because it overheated.\n", + netdev->name); } + /* adjust timeout factor according to speed/duplex */ adapter->tx_timeout_factor = 1; switch (adapter->link_speed) { @@ -3618,22 +3626,15 @@ static void igb_watchdog_task(struct work_struct *work) if (netif_carrier_ok(netdev)) { adapter->link_speed = 0; adapter->link_duplex = 0; - /* check for thermal sensor event on i350 - * copper only*/ - if (hw->mac.type == e1000_i350) { - thstat = rd32(E1000_THSTAT); - ctrl_ext = rd32(E1000_CTRL_EXT); - if ((hw->phy.media_type == - e1000_media_type_copper) && !(ctrl_ext & - E1000_CTRL_EXT_LINK_MODE_SGMII)) { - if (thstat & E1000_THSTAT_PWR_DOWN) { - printk(KERN_ERR "igb: %s The " - "network adapter was stopped " - "because it overheated.\n", + + /* check for thermal sensor event */ + if (igb_thermal_sensor_event(hw, E1000_THSTAT_PWR_DOWN)) { + printk(KERN_ERR "igb: %s The network adapter " + "was stopped because it " + "overheated.\n", netdev->name); - } - } } + /* Links status message must follow this format */ printk(KERN_INFO "igb: %s NIC Link is Down\n", netdev->name); -- cgit v1.2.2 From 25db0338813a8915457636b1f6abe6a28fa73f8d Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:39 +0000 Subject: ethtool: Use full 32 bit speed range in ethtool's set_settings This makes sure the ethtool's set_settings() callback of network drivers don't ignore the 16 most significant bits when ethtool calls their set_settings(). All drivers compiled with make allyesconfig on x86_64 have been updated. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/igb/igb_ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index d976733bbcc2..2cc221b65cd4 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -223,7 +223,8 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if (adapter->fc_autoneg) hw->fc.requested_mode = e1000_fc_default; } else { - if (igb_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { + u32 speed = ethtool_cmd_speed(ecmd); + if (igb_set_spd_dplx(adapter, speed + ecmd->duplex)) { clear_bit(__IGB_RESETTING, &adapter->state); return -EINVAL; } -- cgit v1.2.2 From 707394972093e2056e1e8cc39be19cf9bcb3e7b3 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:40 +0000 Subject: ethtool: cosmetic: Use ethtool ethtool_cmd_speed API This updates the network drivers so that they don't access the ethtool_cmd::speed field directly, but use ethtool_cmd_speed() instead. For most of the drivers, these changes are purely cosmetic and don't fix any problem, such as for those 1GbE/10GbE drivers that indirectly call their own ethtool get_settings()/mii_ethtool_gset(). The changes are meant to enforce code consistency and provide robustness with future larger throughputs, at the expense of a few CPU cycles for each ethtool operation. All drivers compiled with make allyesconfig ion x86_64 have been updated. Tested: make allyesconfig on x86_64 + e1000e/bnx2x work Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/igb/igb_ethtool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 2cc221b65cd4..023aa9b10654 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -178,11 +178,11 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if ((status & E1000_STATUS_SPEED_1000) || hw->phy.media_type != e1000_media_type_copper) - ecmd->speed = SPEED_1000; + ethtool_cmd_speed_set(ecmd, SPEED_1000); else if (status & E1000_STATUS_SPEED_100) - ecmd->speed = SPEED_100; + ethtool_cmd_speed_set(ecmd, SPEED_100); else - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); if ((status & E1000_STATUS_FD) || hw->phy.media_type != e1000_media_type_copper) @@ -190,7 +190,7 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) else ecmd->duplex = DUPLEX_HALF; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } -- cgit v1.2.2 From 14ad2513ed5b709e566a853f4b515d91c5d83311 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:43 +0000 Subject: net/igb/e1000/e1000e: more robust ethtool duplex/speed configuration This makes sure that one cannot request a 99Mbps full-duplex and get a 100Mbps half-duplex configuration in return due to the way the speed/duplex parameters are handled internally. Tested: e1000 works Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 2 +- drivers/net/igb/igb_ethtool.c | 2 +- drivers/net/igb/igb_main.c | 23 +++++++++++++++-------- 3 files changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 1c687e298d5e..f4fa4b1751cf 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -360,7 +360,7 @@ extern int igb_up(struct igb_adapter *); extern void igb_down(struct igb_adapter *); extern void igb_reinit_locked(struct igb_adapter *); extern void igb_reset(struct igb_adapter *); -extern int igb_set_spd_dplx(struct igb_adapter *, u16); +extern int igb_set_spd_dplx(struct igb_adapter *, u32, u8); extern int igb_setup_tx_resources(struct igb_ring *); extern int igb_setup_rx_resources(struct igb_ring *); extern void igb_free_tx_resources(struct igb_ring *); diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 023aa9b10654..6e29634b1fb5 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -224,7 +224,7 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) hw->fc.requested_mode = e1000_fc_default; } else { u32 speed = ethtool_cmd_speed(ecmd); - if (igb_set_spd_dplx(adapter, speed + ecmd->duplex)) { + if (igb_set_spd_dplx(adapter, speed, ecmd->duplex)) { clear_bit(__IGB_RESETTING, &adapter->state); return -EINVAL; } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index cdfd57271051..ce7838e55827 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -6349,21 +6349,25 @@ static void igb_restore_vlan(struct igb_adapter *adapter) } } -int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) +int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx) { struct pci_dev *pdev = adapter->pdev; struct e1000_mac_info *mac = &adapter->hw.mac; mac->autoneg = 0; + /* Make sure dplx is at most 1 bit and lsb of speed is not set + * for the switch() below to work */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + /* Fiber NIC's only allow 1000 Gbps Full duplex */ if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes) && - spddplx != (SPEED_1000 + DUPLEX_FULL)) { - dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; - } + spd != SPEED_1000 && + dplx != DUPLEX_FULL) + goto err_inval; - switch (spddplx) { + switch (spd + dplx) { case SPEED_10 + DUPLEX_HALF: mac->forced_speed_duplex = ADVERTISE_10_HALF; break; @@ -6382,10 +6386,13 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: - dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; + goto err_inval; } return 0; + +err_inval: + dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; } static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) -- cgit v1.2.2 From f6b1bfd17d42f9dc1d799b7e0eed817ed75005ec Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Wed, 4 May 2011 04:29:51 +0000 Subject: igb: Add check for invalid size to igb_get_invariants_82575() Recent commits have changed how EEPROM size is checked and if the size word is misconfigured, the driver will fail to load. This patch adds a check for invalid size word in the EEPROM and uses default size instead for 82576 parts. Reported-by: Stefan Assmann Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 0cd41c49bc17..0f563c8c5ffc 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -244,6 +244,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) */ size += NVM_WORD_SIZE_BASE_SHIFT; + /* + * Check for invalid size + */ + if ((hw->mac.type == e1000_82576) && (size > 15)) { + printk("igb: The NVM size is not valid, " + "defaulting to 32K.\n"); + size = 15; + } nvm->word_size = 1 << size; if (nvm->word_size == (1 << 15)) nvm->page_size = 128; -- cgit v1.2.2 From 936db3559fc4f6d2892234cadcbd88b8a7d34898 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Sat, 7 May 2011 06:37:14 +0000 Subject: igb: convert to ethtool set_phys_id Based on patch from Stephen Hemminger. Convert igb driver to use new set_phys_id ethtool interface. CC: Stephen Hemminger Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_ethtool.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 6e29634b1fb5..fdc895e5a3f8 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1964,27 +1964,28 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) /* bit defines for adapter->led_status */ #define IGB_LED_ON 0 -static int igb_phys_id(struct net_device *netdev, u32 data) +static int igb_set_phys_id(struct net_device *netdev, + enum ethtool_phys_id_state state) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - unsigned long timeout; - timeout = data * 1000; - - /* - * msleep_interruptable only accepts unsigned int so we are limited - * in how long a duration we can wait - */ - if (!timeout || timeout > UINT_MAX) - timeout = UINT_MAX; - - igb_blink_led(hw); - msleep_interruptible(timeout); - - igb_led_off(hw); - clear_bit(IGB_LED_ON, &adapter->led_status); - igb_cleanup_led(hw); + switch (state) { + case ETHTOOL_ID_ACTIVE: + igb_blink_led(hw); + return 2; + case ETHTOOL_ID_ON: + igb_blink_led(hw); + break; + case ETHTOOL_ID_OFF: + igb_led_off(hw); + break; + case ETHTOOL_ID_INACTIVE: + igb_led_off(hw); + clear_bit(IGB_LED_ON, &adapter->led_status); + igb_cleanup_led(hw); + break; + } return 0; } @@ -2216,7 +2217,7 @@ static const struct ethtool_ops igb_ethtool_ops = { .set_tso = igb_set_tso, .self_test = igb_diag_test, .get_strings = igb_get_strings, - .phys_id = igb_phys_id, + .set_phys_id = igb_set_phys_id, .get_sset_count = igb_get_sset_count, .get_ethtool_stats = igb_get_ethtool_stats, .get_coalesce = igb_get_coalesce, -- cgit v1.2.2 From 70c71606190e9115e5f8363bfcd164c582eb314a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 22 May 2011 16:47:17 -0400 Subject: Add appropriate include for prefetch users After discovering that wide use of prefetch on modern CPUs could be a net loss instead of a win, net drivers which were relying on the implicit inclusion of prefetch.h via the list headers showed up in the resulting cleanup fallout. Give them an explicit include via the following $0.02 script. ========================================= #!/bin/bash MANUAL="" for i in `git grep -l 'prefetch(.*)' .` ; do grep -q '' $i if [ $? = 0 ] ; then continue fi ( echo '?^#include ' echo . echo w echo q ) | ed -s $i > /dev/null 2>&1 if [ $? != 0 ]; then echo $i needs manual fixup MANUAL="$i $MANUAL" fi done echo ------------------- 8\<---------------------- echo vi $MANUAL ========================================= Signed-off-by: Paul [ Fixed up some incorrect #include placements, and added some non-network drivers and the fib_trie.c case - Linus ] Signed-off-by: Linus Torvalds --- drivers/net/igb/igb_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ce7838e55827..18fccf913635 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -45,6 +45,7 @@ #include #include #include +#include #ifdef CONFIG_IGB_DCA #include #endif -- cgit v1.2.2 From 665c8c8ee405738375b679246b49342ce38ba056 Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Tue, 7 Jun 2011 14:22:57 -0700 Subject: igb: fix i350 SR-IOV failture When SR-IOV is enabled, i350 devices fail to pass traffic. This is due to the driver attempting to enable RSS on the PF device, which is not supported by the i350. When max_vfs is specified on an i350 adapter, set the number of RSS queues to 1. This issue affects 2.6.39 as well. CC: stable@kernel.org Signed-off-by: Mitch Williams Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/igb') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 18fccf913635..2c28621eb30b 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2373,6 +2373,9 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) } #endif /* CONFIG_PCI_IOV */ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); + /* i350 cannot do RSS and SR-IOV at the same time */ + if (hw->mac.type == e1000_i350 && adapter->vfs_allocated_count) + adapter->rss_queues = 1; /* * if rss_queues > 4 or vfs are going to be allocated with rss_queues -- cgit v1.2.2