From 5c0999b72b34541a3734a9138c43d5c024a42d47 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 19 Jan 2009 15:20:57 -0800 Subject: igb: Replace LRO with GRO This patch makes igb invoke the GRO hooks instead of LRO. As GRO has a compatible external interface to LRO this is a very straightforward replacement. Three things of note: 1) I've kept the LRO Kconfig option until we decide to enable GRO across the board at which point it can also be killed. 2) The poll_controller stuff is broken in igb as it tries to do the same work as the normal poll routine. Since poll_controller can be called in the middle of a poll, this can't be good. I noticed this because poll_controller can invoke the GRO hooks without flushing held GRO packets. However, this should be harmless (assuming the poll_controller bug above doesn't kill you first :) since the next ->poll will clear the backlog. The only time when we'll have a problem is if we're already executing the GRO code on the same ring, but that's no worse than what happens now. 3) I kept the ip_summed check before calling GRO so that we're on par with previous behaviour. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 5a27825cc48a..7d8c88739154 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -36,12 +36,6 @@ struct igb_adapter; -#ifdef CONFIG_IGB_LRO -#include -#define MAX_LRO_AGGR 32 -#define MAX_LRO_DESCRIPTORS 8 -#endif - /* Interrupt defines */ #define IGB_MIN_DYN_ITR 3000 #define IGB_MAX_DYN_ITR 96000 @@ -176,10 +170,6 @@ struct igb_ring { struct napi_struct napi; int set_itr; struct igb_ring *buddy; -#ifdef CONFIG_IGB_LRO - struct net_lro_mgr lro_mgr; - bool lro_used; -#endif }; }; @@ -288,12 +278,6 @@ struct igb_adapter { int need_ioport; struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES]; -#ifdef CONFIG_IGB_LRO - unsigned int lro_max_aggr; - unsigned int lro_aggregated; - unsigned int lro_flushed; - unsigned int lro_no_desc; -#endif unsigned int tx_ring_count; unsigned int rx_ring_count; }; -- cgit v1.2.3-59-g8ed1b From aed5dec370e294233d647251ce1e5f74d70b09c9 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:16:04 +0000 Subject: igb: remove check for needing an io port Since igb supports only pci-e nics and there is no plan to support any legacy pci parts in the driver there isn't really much need for checking to see if an io port is needed. In the unlikely event that we do begin supporting legacy pci parts then we can see about adding this code back to the driver. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 4 ---- drivers/net/igb/igb_main.c | 50 ++++++++++------------------------------------ 2 files changed, 10 insertions(+), 44 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 30657ddf4842..530d7aa4cb86 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -273,10 +273,6 @@ struct igb_adapter { unsigned int flags; u32 eeprom_wol; - /* for ioport free */ - int bars; - int need_ioport; - struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES]; unsigned int tx_ring_count; unsigned int rx_ring_count; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 6ef0adb7a06d..13b10ba8a3c4 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -974,21 +974,6 @@ void igb_reset(struct igb_adapter *adapter) igb_get_phy_info(&adapter->hw); } -/** - * igb_is_need_ioport - determine if an adapter needs ioport resources or not - * @pdev: PCI device information struct - * - * Returns true if an adapter needs ioport resources - **/ -static int igb_is_need_ioport(struct pci_dev *pdev) -{ - switch (pdev->device) { - /* Currently there are no adapters that need ioport resources */ - default: - return false; - } -} - static const struct net_device_ops igb_netdev_ops = { .ndo_open = igb_open, .ndo_stop = igb_close, @@ -1032,17 +1017,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, u16 eeprom_data = 0, state = 0; u16 eeprom_apme_mask = IGB_EEPROM_APME; u32 part_num; - int bars, need_ioport; - /* do not allocate ioport bars when not needed */ - need_ioport = igb_is_need_ioport(pdev); - if (need_ioport) { - bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); - err = pci_enable_device(pdev); - } else { - bars = pci_select_bars(pdev, IORESOURCE_MEM); - err = pci_enable_device_mem(pdev); - } + err = pci_enable_device_mem(pdev); if (err) return err; @@ -1085,7 +1061,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, break; } - err = pci_request_selected_regions(pdev, bars, igb_driver_name); + err = pci_request_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM), + igb_driver_name); if (err) goto err_pci_reg; @@ -1113,8 +1091,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, hw = &adapter->hw; hw->back = adapter; adapter->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE; - adapter->bars = bars; - adapter->need_ioport = need_ioport; mmio_start = pci_resource_start(pdev, 0); mmio_len = pci_resource_len(pdev, 0); @@ -1361,7 +1337,8 @@ err_hw_init: err_ioremap: free_netdev(netdev); err_alloc_etherdev: - pci_release_selected_regions(pdev, bars); + pci_release_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM)); err_pci_reg: err_dma: pci_disable_device(pdev); @@ -1420,7 +1397,8 @@ static void __devexit igb_remove(struct pci_dev *pdev) iounmap(adapter->hw.hw_addr); if (adapter->hw.flash_address) iounmap(adapter->hw.flash_address); - pci_release_selected_regions(pdev, adapter->bars); + pci_release_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM)); free_netdev(netdev); @@ -4309,10 +4287,7 @@ static int igb_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - if (adapter->need_ioport) - err = pci_enable_device(pdev); - else - err = pci_enable_device_mem(pdev); + err = pci_enable_device_mem(pdev); if (err) { dev_err(&pdev->dev, "igb: Cannot enable PCI device from suspend\n"); @@ -4423,12 +4398,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) pci_ers_result_t result; int err; - if (adapter->need_ioport) - err = pci_enable_device(pdev); - else - err = pci_enable_device_mem(pdev); - - if (err) { + if (pci_enable_device_mem(pdev)) { dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n"); result = PCI_ERS_RESULT_DISCONNECT; -- cgit v1.2.3-59-g8ed1b From a8d2a0c27f84bdbf54b7e1c1a52ef7b8b7196dbc Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:17:26 +0000 Subject: igb: rename phy ops This patch renames write_phy_reg to write_reg and read_phy_reg to read_reg. It seems redundant to call out phy in an operation that is part of the phy_ops struct. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 38 ++--- drivers/net/igb/e1000_hw.h | 10 +- drivers/net/igb/e1000_mac.c | 8 +- drivers/net/igb/e1000_phy.c | 347 ++++++++++++++++-------------------------- drivers/net/igb/e1000_phy.h | 1 - drivers/net/igb/igb.h | 12 +- 6 files changed, 162 insertions(+), 254 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index ed9e8c0333a3..9a66e345729e 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -179,13 +179,13 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) /* PHY function pointers */ if (igb_sgmii_active_82575(hw)) { - phy->ops.reset_phy = igb_phy_hw_reset_sgmii_82575; - phy->ops.read_phy_reg = igb_read_phy_reg_sgmii_82575; - phy->ops.write_phy_reg = igb_write_phy_reg_sgmii_82575; + phy->ops.reset = igb_phy_hw_reset_sgmii_82575; + phy->ops.read_reg = igb_read_phy_reg_sgmii_82575; + phy->ops.write_reg = igb_write_phy_reg_sgmii_82575; } else { - phy->ops.reset_phy = igb_phy_hw_reset; - phy->ops.read_phy_reg = igb_read_phy_reg_igp; - phy->ops.write_phy_reg = igb_write_phy_reg_igp; + phy->ops.reset = igb_phy_hw_reset; + phy->ops.read_reg = igb_read_phy_reg_igp; + phy->ops.write_reg = igb_write_phy_reg_igp; } /* Set phy->phy_addr and phy->id. */ @@ -435,7 +435,7 @@ static s32 igb_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) * SFP documentation requires the following to configure the SPF module * to work on SGMII. No further documentation is given. */ - ret_val = hw->phy.ops.write_phy_reg(hw, 0x1B, 0x8084); + ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); if (ret_val) goto out; @@ -464,28 +464,28 @@ static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) s32 ret_val; u16 data; - ret_val = phy->ops.read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); + ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) goto out; if (active) { data |= IGP02E1000_PM_D0_LPLU; - ret_val = phy->ops.write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = phy->ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else { data &= ~IGP02E1000_PM_D0_LPLU; - ret_val = phy->ops.write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used @@ -494,24 +494,24 @@ static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = phy->ops.read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = phy->ops.read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; @@ -1035,7 +1035,7 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) * depending on user settings. */ hw_dbg("Forcing Speed and Duplex\n"); - ret_val = igb_phy_force_speed_duplex(hw); + ret_val = hw->phy.ops.force_speed_duplex(hw); if (ret_val) { hw_dbg("Error Forcing Speed and Duplex\n"); goto out; @@ -1423,9 +1423,9 @@ static struct e1000_mac_operations e1000_mac_ops_82575 = { }; static struct e1000_phy_operations e1000_phy_ops_82575 = { - .acquire_phy = igb_acquire_phy_82575, + .acquire = igb_acquire_phy_82575, .get_cfg_done = igb_get_cfg_done_82575, - .release_phy = igb_release_phy_82575, + .release = igb_release_phy_82575, }; static struct e1000_nvm_operations e1000_nvm_ops_82575 = { diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 06f72ae6a2c2..5acb8497cd64 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -422,18 +422,18 @@ struct e1000_mac_operations { }; struct e1000_phy_operations { - s32 (*acquire_phy)(struct e1000_hw *); + s32 (*acquire)(struct e1000_hw *); s32 (*check_reset_block)(struct e1000_hw *); s32 (*force_speed_duplex)(struct e1000_hw *); s32 (*get_cfg_done)(struct e1000_hw *hw); s32 (*get_cable_length)(struct e1000_hw *); s32 (*get_phy_info)(struct e1000_hw *); - s32 (*read_phy_reg)(struct e1000_hw *, u32, u16 *); - void (*release_phy)(struct e1000_hw *); - s32 (*reset_phy)(struct e1000_hw *); + s32 (*read_reg)(struct e1000_hw *, u32, u16 *); + void (*release)(struct e1000_hw *); + s32 (*reset)(struct e1000_hw *); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); - s32 (*write_phy_reg)(struct e1000_hw *, u32, u16); + s32 (*write_reg)(struct e1000_hw *, u32, u16); }; struct e1000_nvm_operations { diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 16fa0833368c..d0b695cf956c 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -707,11 +707,11 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; @@ -729,11 +729,11 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) * Page Ability Register (Address 5) to determine how * flow control was negotiated. */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_AUTONEG_ADV, + ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_LP_ABILITY, + ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); if (ret_val) goto out; diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index 17fddb91c9f5..d73ea71d741f 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -31,10 +31,6 @@ #include "e1000_mac.h" #include "e1000_phy.h" -static s32 igb_get_phy_cfg_done(struct e1000_hw *hw); -static void igb_release_phy(struct e1000_hw *hw); -static s32 igb_acquire_phy(struct e1000_hw *hw); -static s32 igb_phy_reset_dsp(struct e1000_hw *hw); static s32 igb_phy_setup_autoneg(struct e1000_hw *hw); static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); @@ -91,13 +87,13 @@ s32 igb_get_phy_id(struct e1000_hw *hw) s32 ret_val = 0; u16 phy_id; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_ID1, &phy_id); + ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); if (ret_val) goto out; phy->id = (u32)(phy_id << 16); udelay(20); - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_ID2, &phy_id); + ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); if (ret_val) goto out; @@ -118,11 +114,11 @@ static s32 igb_phy_reset_dsp(struct e1000_hw *hw) { s32 ret_val; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); + ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); if (ret_val) goto out; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); + ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); out: return ret_val; @@ -257,9 +253,12 @@ out: **/ s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) { - s32 ret_val; + s32 ret_val = 0; + + if (!(hw->phy.ops.acquire)) + goto out; - ret_val = igb_acquire_phy(hw); + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; @@ -268,16 +267,15 @@ s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (ret_val) { - igb_release_phy(hw); + hw->phy.ops.release(hw); goto out; } } - ret_val = igb_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); + ret_val = igb_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); - igb_release_phy(hw); + hw->phy.ops.release(hw); out: return ret_val; @@ -294,9 +292,12 @@ out: **/ s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) { - s32 ret_val; + s32 ret_val = 0; - ret_val = igb_acquire_phy(hw); + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; @@ -305,16 +306,15 @@ s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (ret_val) { - igb_release_phy(hw); + hw->phy.ops.release(hw); goto out; } } - ret_val = igb_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, + ret_val = igb_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); - igb_release_phy(hw); + hw->phy.ops.release(hw); out: return ret_val; @@ -339,8 +339,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) } /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -383,8 +382,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) if (phy->disable_polarity_correction == 1) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; @@ -393,8 +391,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) * Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ - ret_val = hw->phy.ops.read_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -413,8 +410,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); } - ret_val = hw->phy.ops.write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, + ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; @@ -449,7 +445,7 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.reset_phy(hw); + ret_val = phy->ops.reset(hw); if (ret_val) { hw_dbg("Error resetting the PHY.\n"); goto out; @@ -464,8 +460,8 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) */ if (phy->type == e1000_phy_igp) { /* disable lplu d3 during driver init */ - if (hw->phy.ops.set_d3_lplu_state) - ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); + if (phy->ops.set_d3_lplu_state) + ret_val = phy->ops.set_d3_lplu_state(hw, false); if (ret_val) { hw_dbg("Error Disabling LPLU D3\n"); goto out; @@ -473,13 +469,13 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) } /* disable lplu d0 during driver init */ - ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); + ret_val = phy->ops.set_d0_lplu_state(hw, false); if (ret_val) { hw_dbg("Error Disabling LPLU D0\n"); goto out; } /* Configure mdi-mdix settings */ - ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); if (ret_val) goto out; @@ -497,7 +493,7 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) data |= IGP01E1000_PSCR_AUTO_MDIX; break; } - ret_val = hw->phy.ops.write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); if (ret_val) goto out; @@ -510,33 +506,31 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) */ if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { /* Disable SmartSpeed */ - ret_val = hw->phy.ops.read_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = hw->phy.ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; /* Set auto Master/Slave resolution process */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_1000T_CTRL, - &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); if (ret_val) goto out; data &= ~CR_1000T_MS_ENABLE; - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_1000T_CTRL, - data); + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); if (ret_val) goto out; } - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_1000T_CTRL, &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); if (ret_val) goto out; @@ -560,7 +554,7 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) default: break; } - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_1000T_CTRL, data); + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); if (ret_val) goto out; } @@ -609,12 +603,12 @@ s32 igb_copper_link_autoneg(struct e1000_hw *hw) * Restart auto-negotiation by setting the Auto Neg Enable bit and * the Auto Neg Restart bit in the PHY control register. */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_ctrl); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) goto out; phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_ctrl); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) goto out; @@ -656,15 +650,13 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) phy->autoneg_advertised &= phy->autoneg_mask; /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_AUTONEG_ADV, - &mii_autoneg_adv_reg); + ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); if (ret_val) goto out; if (phy->autoneg_mask & ADVERTISE_1000_FULL) { /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = hw->phy.ops.read_phy_reg(hw, - PHY_1000T_CTRL, + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); if (ret_val) goto out; @@ -785,17 +777,16 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_AUTONEG_ADV, - mii_autoneg_adv_reg); + ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); if (ret_val) goto out; hw_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - ret_val = hw->phy.ops.write_phy_reg(hw, - PHY_1000T_CTRL, - mii_1000t_ctrl_reg); + ret_val = phy->ops.write_reg(hw, + PHY_1000T_CTRL, + mii_1000t_ctrl_reg); if (ret_val) goto out; } @@ -819,13 +810,13 @@ s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw) u16 phy_data; bool link; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) goto out; igb_phy_force_speed_duplex_setup(hw, &phy_data); - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_data); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) goto out; @@ -833,16 +824,14 @@ s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw) * Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed and duplex are forced. */ - ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); if (ret_val) goto out; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - ret_val = hw->phy.ops.write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); if (ret_val) goto out; @@ -897,20 +886,18 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed and duplex are forced. */ - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; hw_dbg("M88E1000 PSCR: %X\n", phy_data); - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) goto out; @@ -919,7 +906,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) /* Reset the phy to commit changes. */ phy_data |= MII_CR_RESET; - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_data); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) goto out; @@ -940,7 +927,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) * We didn't get link. * Reset the DSP and cross our fingers. */ - ret_val = hw->phy.ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x001d); if (ret_val) @@ -957,8 +944,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -968,8 +954,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) * the reset value of 2.5MHz. */ phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; @@ -977,14 +962,12 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) * In addition, we must re-enable CRS on Tx for both half and full * duplex. */ - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); out: return ret_val; @@ -1071,15 +1054,13 @@ s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) s32 ret_val; u16 data; - ret_val = hw->phy.ops.read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, - &data); + ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) goto out; if (!active) { data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = hw->phy.ops.write_phy_reg(hw, - IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; @@ -1090,27 +1071,27 @@ s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = hw->phy.ops.read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = hw->phy.ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = hw->phy.ops.read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = hw->phy.ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) @@ -1120,22 +1101,19 @@ s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { data |= IGP02E1000_PM_D3_LPLU; - ret_val = hw->phy.ops.write_phy_reg(hw, - IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = hw->phy.ops.read_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = hw->phy.ops.write_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); } @@ -1176,7 +1154,7 @@ s32 igb_check_downshift(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.read_phy_reg(hw, offset, &phy_data); + ret_val = phy->ops.read_reg(hw, offset, &phy_data); if (!ret_val) phy->speed_downgraded = (phy_data & mask) ? true : false; @@ -1199,7 +1177,7 @@ static s32 igb_check_polarity_m88(struct e1000_hw *hw) s32 ret_val; u16 data; - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); if (!ret_val) phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) @@ -1228,8 +1206,7 @@ static s32 igb_check_polarity_igp(struct e1000_hw *hw) * Polarity is determined based on the speed of * our connection. */ - ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) goto out; @@ -1246,7 +1223,7 @@ static s32 igb_check_polarity_igp(struct e1000_hw *hw) mask = IGP01E1000_PSSR_POLARITY_REVERSED; } - ret_val = hw->phy.ops.read_phy_reg(hw, offset, &data); + ret_val = phy->ops.read_reg(hw, offset, &data); if (!ret_val) phy->cable_polarity = (data & mask) @@ -1271,10 +1248,10 @@ static s32 igb_wait_autoneg(struct e1000_hw *hw) /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_AUTONEG_COMPLETE) @@ -1310,10 +1287,10 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, * twice due to the link bit being sticky. No harm doing * it across the board. */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_LINK_STATUS) @@ -1350,8 +1327,7 @@ s32 igb_get_cable_length_m88(struct e1000_hw *hw) s32 ret_val; u16 phy_data, index; - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) goto out; @@ -1372,8 +1348,8 @@ out: * * The automatic gain control (agc) normalizes the amplitude of the * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which reperesent the - * cobination of course and fine gain value, the value can be put + * cable. By reading the AGC registers, which represent the + * combination of coarse and fine gain value, the value can be put * into a lookup table to obtain the approximate cable length * for each channel. **/ @@ -1392,14 +1368,13 @@ s32 igb_get_cable_length_igp_2(struct e1000_hw *hw) /* Read the AGC registers for all channels */ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = hw->phy.ops.read_phy_reg(hw, agc_reg_array[i], - &phy_data); + ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); if (ret_val) goto out; /* * Getting bits 15:9, which represent the combination of - * course and fine gain values. The result is a number + * coarse and fine gain values. The result is a number * that can be put into the lookup table to obtain the * approximate cable length. */ @@ -1456,7 +1431,7 @@ s32 igb_get_phy_info_m88(struct e1000_hw *hw) u16 phy_data; bool link; - if (hw->phy.media_type != e1000_media_type_copper) { + if (phy->media_type != e1000_media_type_copper) { hw_dbg("Phy info is only valid for copper media\n"); ret_val = -E1000_ERR_CONFIG; goto out; @@ -1472,33 +1447,29 @@ s32 igb_get_phy_info_m88(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) - ? true - : false; + ? true : false; ret_val = igb_check_polarity_m88(hw); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) goto out; phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { - ret_val = hw->phy.ops.get_cable_length(hw); + ret_val = phy->ops.get_cable_length(hw); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_1000T_STATUS, - &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); if (ret_val) goto out; @@ -1552,8 +1523,7 @@ s32 igb_get_phy_info_igp(struct e1000_hw *hw) if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) goto out; @@ -1561,12 +1531,11 @@ s32 igb_get_phy_info_igp(struct e1000_hw *hw) if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { - ret_val = hw->phy.ops.get_cable_length(hw); + ret_val = phy->ops.get_cable_length(hw); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_1000T_STATUS, - &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); if (ret_val) goto out; @@ -1599,12 +1568,12 @@ s32 igb_phy_sw_reset(struct e1000_hw *hw) s32 ret_val; u16 phy_ctrl; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_ctrl); + ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) goto out; phy_ctrl |= MII_CR_RESET; - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_ctrl); + ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) goto out; @@ -1635,7 +1604,7 @@ s32 igb_phy_hw_reset(struct e1000_hw *hw) goto out; } - ret_val = igb_acquire_phy(hw); + ret_val = phy->ops.acquire(hw); if (ret_val) goto out; @@ -1650,74 +1619,14 @@ s32 igb_phy_hw_reset(struct e1000_hw *hw) udelay(150); - igb_release_phy(hw); + phy->ops.release(hw); - ret_val = igb_get_phy_cfg_done(hw); + ret_val = phy->ops.get_cfg_done(hw); out: return ret_val; } -/* Internal function pointers */ - -/** - * igb_get_phy_cfg_done - Generic PHY configuration done - * @hw: pointer to the HW structure - * - * Return success if silicon family did not implement a family specific - * get_cfg_done function. - **/ -static s32 igb_get_phy_cfg_done(struct e1000_hw *hw) -{ - if (hw->phy.ops.get_cfg_done) - return hw->phy.ops.get_cfg_done(hw); - - return 0; -} - -/** - * igb_release_phy - Generic release PHY - * @hw: pointer to the HW structure - * - * Return if silicon family does not require a semaphore when accessing the - * PHY. - **/ -static void igb_release_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.release_phy) - hw->phy.ops.release_phy(hw); -} - -/** - * igb_acquire_phy - Generic acquire PHY - * @hw: pointer to the HW structure - * - * Return success if silicon family does not require a semaphore when - * accessing the PHY. - **/ -static s32 igb_acquire_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.acquire_phy) - return hw->phy.ops.acquire_phy(hw); - - return 0; -} - -/** - * igb_phy_force_speed_duplex - Generic force PHY speed/duplex - * @hw: pointer to the HW structure - * - * When the silicon family has not implemented a forced speed/duplex - * function for the PHY, simply return 0. - **/ -s32 igb_phy_force_speed_duplex(struct e1000_hw *hw) -{ - if (hw->phy.ops.force_speed_duplex) - return hw->phy.ops.force_speed_duplex(hw); - - return 0; -} - /** * igb_phy_init_script_igp3 - Inits the IGP3 PHY * @hw: pointer to the HW structure @@ -1730,75 +1639,75 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw) /* PHY init IGP 3 */ /* Enable rise/fall, 10-mode work in class-A */ - hw->phy.ops.write_phy_reg(hw, 0x2F5B, 0x9018); + hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); /* Remove all caps from Replica path filter */ - hw->phy.ops.write_phy_reg(hw, 0x2F52, 0x0000); + hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); /* Bias trimming for ADC, AFE and Driver (Default) */ - hw->phy.ops.write_phy_reg(hw, 0x2FB1, 0x8B24); + hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); /* Increase Hybrid poly bias */ - hw->phy.ops.write_phy_reg(hw, 0x2FB2, 0xF8F0); + hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); /* Add 4% to TX amplitude in Giga mode */ - hw->phy.ops.write_phy_reg(hw, 0x2010, 0x10B0); + hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); /* Disable trimming (TTT) */ - hw->phy.ops.write_phy_reg(hw, 0x2011, 0x0000); + hw->phy.ops.write_reg(hw, 0x2011, 0x0000); /* Poly DC correction to 94.6% + 2% for all channels */ - hw->phy.ops.write_phy_reg(hw, 0x20DD, 0x249A); + hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); /* ABS DC correction to 95.9% */ - hw->phy.ops.write_phy_reg(hw, 0x20DE, 0x00D3); + hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); /* BG temp curve trim */ - hw->phy.ops.write_phy_reg(hw, 0x28B4, 0x04CE); + hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); /* Increasing ADC OPAMP stage 1 currents to max */ - hw->phy.ops.write_phy_reg(hw, 0x2F70, 0x29E4); + hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); /* Force 1000 ( required for enabling PHY regs configuration) */ - hw->phy.ops.write_phy_reg(hw, 0x0000, 0x0140); + hw->phy.ops.write_reg(hw, 0x0000, 0x0140); /* Set upd_freq to 6 */ - hw->phy.ops.write_phy_reg(hw, 0x1F30, 0x1606); + hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); /* Disable NPDFE */ - hw->phy.ops.write_phy_reg(hw, 0x1F31, 0xB814); + hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); /* Disable adaptive fixed FFE (Default) */ - hw->phy.ops.write_phy_reg(hw, 0x1F35, 0x002A); + hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); /* Enable FFE hysteresis */ - hw->phy.ops.write_phy_reg(hw, 0x1F3E, 0x0067); + hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); /* Fixed FFE for short cable lengths */ - hw->phy.ops.write_phy_reg(hw, 0x1F54, 0x0065); + hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); /* Fixed FFE for medium cable lengths */ - hw->phy.ops.write_phy_reg(hw, 0x1F55, 0x002A); + hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); /* Fixed FFE for long cable lengths */ - hw->phy.ops.write_phy_reg(hw, 0x1F56, 0x002A); + hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); /* Enable Adaptive Clip Threshold */ - hw->phy.ops.write_phy_reg(hw, 0x1F72, 0x3FB0); + hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); /* AHT reset limit to 1 */ - hw->phy.ops.write_phy_reg(hw, 0x1F76, 0xC0FF); + hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); /* Set AHT master delay to 127 msec */ - hw->phy.ops.write_phy_reg(hw, 0x1F77, 0x1DEC); + hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); /* Set scan bits for AHT */ - hw->phy.ops.write_phy_reg(hw, 0x1F78, 0xF9EF); + hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); /* Set AHT Preset bits */ - hw->phy.ops.write_phy_reg(hw, 0x1F79, 0x0210); + hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); /* Change integ_factor of channel A to 3 */ - hw->phy.ops.write_phy_reg(hw, 0x1895, 0x0003); + hw->phy.ops.write_reg(hw, 0x1895, 0x0003); /* Change prop_factor of channels BCD to 8 */ - hw->phy.ops.write_phy_reg(hw, 0x1796, 0x0008); + hw->phy.ops.write_reg(hw, 0x1796, 0x0008); /* Change cg_icount + enable integbp for channels BCD */ - hw->phy.ops.write_phy_reg(hw, 0x1798, 0xD008); + hw->phy.ops.write_reg(hw, 0x1798, 0xD008); /* * Change cg_icount + enable integbp + change prop_factor_master * to 8 for channel A */ - hw->phy.ops.write_phy_reg(hw, 0x1898, 0xD918); + hw->phy.ops.write_reg(hw, 0x1898, 0xD918); /* Disable AHT in Slave mode on channel A */ - hw->phy.ops.write_phy_reg(hw, 0x187A, 0x0800); + hw->phy.ops.write_reg(hw, 0x187A, 0x0800); /* * Enable LPLU and disable AN to 1000 in non-D0a states, * Enable SPD+B2B */ - hw->phy.ops.write_phy_reg(hw, 0x0019, 0x008D); + hw->phy.ops.write_reg(hw, 0x0019, 0x008D); /* Enable restart AN on an1000_dis change */ - hw->phy.ops.write_phy_reg(hw, 0x001B, 0x2080); + hw->phy.ops.write_reg(hw, 0x001B, 0x2080); /* Enable wh_fifo read clock in 10/100 modes */ - hw->phy.ops.write_phy_reg(hw, 0x0014, 0x0045); + hw->phy.ops.write_reg(hw, 0x0014, 0x0045); /* Restart AN, Speed selection is 1000 */ - hw->phy.ops.write_phy_reg(hw, 0x0000, 0x1340); + hw->phy.ops.write_reg(hw, 0x0000, 0x1340); return 0; } diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h index 8f8fe0a780d1..7499e5deec48 100644 --- a/drivers/net/igb/e1000_phy.h +++ b/drivers/net/igb/e1000_phy.h @@ -44,7 +44,6 @@ enum e1000_smart_speed { s32 igb_check_downshift(struct e1000_hw *hw); s32 igb_check_reset_block(struct e1000_hw *hw); s32 igb_copper_link_autoneg(struct e1000_hw *hw); -s32 igb_phy_force_speed_duplex(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_phy_force_speed_duplex_igp(struct e1000_hw *hw); diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 530d7aa4cb86..a2a812deb6b8 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -313,24 +313,24 @@ extern void igb_set_ethtool_ops(struct net_device *); static inline s32 igb_reset_phy(struct e1000_hw *hw) { - if (hw->phy.ops.reset_phy) - return hw->phy.ops.reset_phy(hw); + if (hw->phy.ops.reset) + return hw->phy.ops.reset(hw); return 0; } static inline s32 igb_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data) { - if (hw->phy.ops.read_phy_reg) - return hw->phy.ops.read_phy_reg(hw, offset, data); + if (hw->phy.ops.read_reg) + return hw->phy.ops.read_reg(hw, offset, data); return 0; } static inline s32 igb_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data) { - if (hw->phy.ops.write_phy_reg) - return hw->phy.ops.write_phy_reg(hw, offset, data); + if (hw->phy.ops.write_reg) + return hw->phy.ops.write_reg(hw, offset, data); return 0; } -- cgit v1.2.3-59-g8ed1b From 0fbe67af3ee1928f7eae273133b7112d1665d4d3 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:18:06 +0000 Subject: igb: remove unused rx_hdr_split statistic This statistic is not used and so it is safe to remove Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 1 - drivers/net/igb/igb_ethtool.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index a2a812deb6b8..88fdfe4961d8 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -238,7 +238,6 @@ struct igb_adapter { u64 hw_csum_err; u64 hw_csum_good; - u64 rx_hdr_split; u32 alloc_rx_buff_failed; bool rx_csum; u32 gorc; diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index a5bf8ef2848a..84be46c2a0f9 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -88,7 +88,6 @@ static const struct igb_stats igb_gstrings_stats[] = { { "rx_long_byte_count", IGB_STAT(stats.gorc) }, { "rx_csum_offload_good", IGB_STAT(hw_csum_good) }, { "rx_csum_offload_errors", IGB_STAT(hw_csum_err) }, - { "rx_header_split", IGB_STAT(rx_hdr_split) }, { "alloc_rx_buff_failed", IGB_STAT(alloc_rx_buff_failed) }, { "tx_smbus", IGB_STAT(stats.mgptc) }, { "rx_smbus", IGB_STAT(stats.mgprc) }, -- cgit v1.2.3-59-g8ed1b From eebbbdba5eb44406061e4dff130257b654773d3f Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:19:29 +0000 Subject: igb: cleanup igb_netpoll to be more friendly with napi & GRO This patch cleans up igb_netpoll so that it is more friendly with both the current napi and newly introduced GRO features. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 5 ++--- drivers/net/igb/igb_main.c | 37 +++++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 19 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 88fdfe4961d8..0519ae408af9 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -280,9 +280,8 @@ struct igb_adapter { #define IGB_FLAG_HAS_MSI (1 << 0) #define IGB_FLAG_MSI_ENABLE (1 << 1) #define IGB_FLAG_DCA_ENABLED (1 << 2) -#define IGB_FLAG_IN_NETPOLL (1 << 3) -#define IGB_FLAG_QUAD_PORT_A (1 << 4) -#define IGB_FLAG_NEED_CTX_IDX (1 << 5) +#define IGB_FLAG_QUAD_PORT_A (1 << 3) +#define IGB_FLAG_NEED_CTX_IDX (1 << 4) enum e1000_state_t { __IGB_TESTING, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index c05ca3461f60..3bf560f0fde9 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -404,7 +404,7 @@ static void igb_configure_msix(struct igb_adapter *adapter) /* Turn on MSI-X capability first, or our settings * won't stick. And it will take days to debug. */ wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE | - E1000_GPIE_PBA | E1000_GPIE_EIAME | + E1000_GPIE_PBA | E1000_GPIE_EIAME | E1000_GPIE_NSICR); for (i = 0; i < adapter->num_tx_queues; i++) { @@ -1629,7 +1629,7 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter) for (i = 0; i < IGB_MAX_TX_QUEUES; i++) { r_idx = i % adapter->num_tx_queues; adapter->multi_tx_table[i] = &adapter->tx_ring[r_idx]; - } + } return err; } @@ -3298,7 +3298,7 @@ static irqreturn_t igb_msix_other(int irq, void *data) /* guard against interrupt when we're going down */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, jiffies + 1); - + no_link_interrupt: wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); wr32(E1000_EIMS, adapter->eims_other); @@ -3751,7 +3751,7 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring) /** * igb_receive_skb - helper function to handle rx indications - * @ring: pointer to receive ring receving this packet + * @ring: pointer to receive ring receving this packet * @status: descriptor status field as written by hardware * @vlan: descriptor vlan field as written by hardware (no le/be conversion) * @skb: pointer to sk_buff to be indicated to stack @@ -4378,22 +4378,27 @@ static void igb_shutdown(struct pci_dev *pdev) static void igb_netpoll(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; int i; - int work_done = 0; - igb_irq_disable(adapter); - adapter->flags |= IGB_FLAG_IN_NETPOLL; - - for (i = 0; i < adapter->num_tx_queues; i++) - igb_clean_tx_irq(&adapter->tx_ring[i]); + if (!adapter->msix_entries) { + igb_irq_disable(adapter); + napi_schedule(&adapter->rx_ring[0].napi); + return; + } - for (i = 0; i < adapter->num_rx_queues; i++) - igb_clean_rx_irq_adv(&adapter->rx_ring[i], - &work_done, - adapter->rx_ring[i].napi.weight); + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igb_ring *tx_ring = &adapter->tx_ring[i]; + wr32(E1000_EIMC, tx_ring->eims_value); + igb_clean_tx_irq(tx_ring); + wr32(E1000_EIMS, tx_ring->eims_value); + } - adapter->flags &= ~IGB_FLAG_IN_NETPOLL; - igb_irq_enable(adapter); + for (i = 0; i < adapter->num_rx_queues; i++) { + struct igb_ring *rx_ring = &adapter->rx_ring[i]; + wr32(E1000_EIMC, rx_ring->eims_value); + napi_schedule(&rx_ring->napi); + } } #endif /* CONFIG_NET_POLL_CONTROLLER */ -- cgit v1.2.3-59-g8ed1b From 86d5d38fa1afe2c96f184482d6c6d1a59ee7e2dc Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:23:12 +0000 Subject: igb: update version number and copyright dates Update the version number to 1.3.16 and update copyright dates for 2009. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/Makefile | 2 +- drivers/net/igb/e1000_82575.c | 2 +- drivers/net/igb/e1000_82575.h | 2 +- drivers/net/igb/e1000_defines.h | 2 +- drivers/net/igb/e1000_hw.h | 2 +- drivers/net/igb/e1000_mac.c | 2 +- drivers/net/igb/e1000_mac.h | 2 +- drivers/net/igb/e1000_nvm.c | 2 +- drivers/net/igb/e1000_phy.c | 2 +- drivers/net/igb/e1000_phy.h | 2 +- drivers/net/igb/e1000_regs.h | 2 +- drivers/net/igb/igb.h | 2 +- drivers/net/igb/igb_ethtool.c | 2 +- drivers/net/igb/igb_main.c | 6 +++--- 14 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/Makefile b/drivers/net/igb/Makefile index 1927b3fd6f05..cda3ad51bafa 100644 --- a/drivers/net/igb/Makefile +++ b/drivers/net/igb/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel 82575 PCI-Express Ethernet Linux driver -# Copyright(c) 1999 - 2007 Intel Corporation. +# Copyright(c) 1999 - 2009 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 68a9822f4059..7f43e253c566 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 - 2008 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index e0a376fa28a1..dd50237c8cb0 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 - 2008 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index bff62dd84312..5342e231c1d5 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 - 2008 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 6d1564f43833..bd86cebed37c 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index e5d23e08650a..5c249e2ce93b 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index 4ef40d5629d5..91461de083f5 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c index 337986422086..a88bfe2f1e8f 100644 --- a/drivers/net/igb/e1000_nvm.c +++ b/drivers/net/igb/e1000_nvm.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index d73ea71d741f..ff0050e5d0b5 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h index 7499e5deec48..3228a862031f 100644 --- a/drivers/net/igb/e1000_phy.h +++ b/drivers/net/igb/e1000_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index bdf5d839c4bf..5038b73c78e9 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 0519ae408af9..e507449b3cc2 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index de09430ce7f5..bd050b1dab7f 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 67138400af8b..8bc1ffa04ec2 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -48,12 +48,12 @@ #endif #include "igb.h" -#define DRV_VERSION "1.2.45-k2" +#define DRV_VERSION "1.3.16-k2" 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) 2008 Intel Corporation."; +static const char igb_copyright[] = "Copyright (c) 2007-2009 Intel Corporation."; static const struct e1000_info *igb_info_tbl[] = { [board_82575] = &e1000_82575_info, -- cgit v1.2.3-59-g8ed1b From 38c845c7648ee354fd1d2fb8a7fbc352f2d3dcc3 Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Thu, 12 Feb 2009 05:03:41 +0000 Subject: igb: access to NIC time Adds the register definitions and code to read the time register. Signed-off-by: John Ronciak Signed-off-by: Patrick Ohly Signed-off-by: David S. Miller --- drivers/net/igb/e1000_regs.h | 28 +++++++++++ drivers/net/igb/igb.h | 4 ++ drivers/net/igb/igb_main.c | 111 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 5038b73c78e9..64d95cd71f2e 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -75,6 +75,34 @@ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ #define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ + +/* IEEE 1588 TIMESYNCH */ +#define E1000_TSYNCTXCTL 0x0B614 +#define E1000_TSYNCRXCTL 0x0B620 +#define E1000_TSYNCRXCFG 0x05F50 + +#define E1000_SYSTIML 0x0B600 +#define E1000_SYSTIMH 0x0B604 +#define E1000_TIMINCA 0x0B608 + +#define E1000_RXMTRL 0x0B634 +#define E1000_RXSTMPL 0x0B624 +#define E1000_RXSTMPH 0x0B628 +#define E1000_RXSATRL 0x0B62C +#define E1000_RXSATRH 0x0B630 + +#define E1000_TXSTMPL 0x0B618 +#define E1000_TXSTMPH 0x0B61C + +#define E1000_ETQF0 0x05CB0 +#define E1000_ETQF1 0x05CB4 +#define E1000_ETQF2 0x05CB8 +#define E1000_ETQF3 0x05CBC +#define E1000_ETQF4 0x05CC0 +#define E1000_ETQF5 0x05CC4 +#define E1000_ETQF6 0x05CC8 +#define E1000_ETQF7 0x05CCC + /* Split and Replication RX Control - RW */ /* * Convenience macros diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index e507449b3cc2..797a9fe107ad 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -34,6 +34,8 @@ #include "e1000_mac.h" #include "e1000_82575.h" +#include + struct igb_adapter; /* Interrupt defines */ @@ -251,6 +253,8 @@ struct igb_adapter { struct napi_struct napi; struct pci_dev *pdev; struct net_device_stats net_stats; + struct cyclecounter cycles; + struct timecounter clock; /* structs defined in e1000_hw.h */ struct e1000_hw hw; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index f8c2919bcec0..8b2ba4245090 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -175,6 +175,54 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +/** + * 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 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. + * + * Note that + * TIMINCA = IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS * + * IGB_TSYNC_SCALE + * TIMINCA += TIMINCA * adjustment [ppm] / 1e9 + * + * The base scale factor is intentionally a power of two + * so that the division in %struct timecounter can be done with + * a shift. + */ +#define IGB_TSYNC_SHIFT (19) +#define IGB_TSYNC_SCALE (1<= (1<<24) +# error IGB_TSYNC_SCALE and/or IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS are too large to fit into TIMINCA +#endif + +/** + * igb_read_clock - read raw cycle counter (to be used by time counter) + */ +static cycle_t igb_read_clock(const struct cyclecounter *tc) +{ + struct igb_adapter *adapter = + container_of(tc, struct igb_adapter, cycles); + struct e1000_hw *hw = &adapter->hw; + u64 stamp; + + stamp = rd32(E1000_SYSTIML); + stamp |= (u64)rd32(E1000_SYSTIMH) << 32ULL; + + return stamp; +} + #ifdef DEBUG /** * igb_get_hw_dev_name - return device name string @@ -185,6 +233,29 @@ char *igb_get_hw_dev_name(struct e1000_hw *hw) struct igb_adapter *adapter = hw->back; return adapter->netdev->name; } + +/** + * igb_get_time_str - format current NIC and system time as string + */ +static char *igb_get_time_str(struct igb_adapter *adapter, + char buffer[160]) +{ + cycle_t hw = adapter->cycles.read(&adapter->cycles); + struct timespec nic = ns_to_timespec(timecounter_read(&adapter->clock)); + struct timespec sys; + struct timespec delta; + getnstimeofday(&sys); + + delta = timespec_sub(nic, sys); + + sprintf(buffer, + "NIC %ld.%09lus, SYS %ld.%09lus, NIC-SYS %lds + %09luns", + (long)nic.tv_sec, nic.tv_nsec, + (long)sys.tv_sec, sys.tv_nsec, + (long)delta.tv_sec, delta.tv_nsec); + + return buffer; +} #endif /** @@ -1298,6 +1369,46 @@ static int __devinit igb_probe(struct pci_dev *pdev, } #endif + /* + * Initialize hardware timer: we keep it running just in case + * that some program needs it later on. + */ + memset(&adapter->cycles, 0, sizeof(adapter->cycles)); + adapter->cycles.read = igb_read_clock; + adapter->cycles.mask = CLOCKSOURCE_MASK(64); + adapter->cycles.mult = 1; + adapter->cycles.shift = IGB_TSYNC_SHIFT; + wr32(E1000_TIMINCA, + (1<<24) | + IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS * IGB_TSYNC_SCALE); +#if 0 + /* + * Avoid rollover while we initialize by resetting the time counter. + */ + wr32(E1000_SYSTIML, 0x00000000); + wr32(E1000_SYSTIMH, 0x00000000); +#else + /* + * Set registers so that rollover occurs soon to test this. + */ + wr32(E1000_SYSTIML, 0x00000000); + wr32(E1000_SYSTIMH, 0xFF800000); +#endif + wrfl(); + timecounter_init(&adapter->clock, + &adapter->cycles, + ktime_to_ns(ktime_get_real())); + +#ifdef DEBUG + { + char buffer[160]; + printk(KERN_DEBUG + "igb: %s: hw %p initialized timer\n", + igb_get_time_str(adapter, buffer), + &adapter->hw); + } +#endif + 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", -- cgit v1.2.3-59-g8ed1b From 33af6bcc005a826726b48e8775df5d58112bc10b Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Thu, 12 Feb 2009 05:03:43 +0000 Subject: igb: use timecompare to implement hardware time stamping Both TX and RX hardware time stamping are implemented. Due to hardware limitations it is not possible to verify reliably which packet was time stamped when multiple were pending for sending; this could be solved by only allowing one packet marked for hardware time stamping into the queue (not implemented yet). RX time stamping relies on the flag in the packet descriptor which marks packets that were time stamped. In "all packet" mode this flag is not set. TODO: also support that mode (even though it'll suffer from race conditions). Signed-off-by: John Ronciak Signed-off-by: Patrick Ohly Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.h | 1 + drivers/net/igb/e1000_defines.h | 1 + drivers/net/igb/e1000_regs.h | 40 ++++++ drivers/net/igb/igb.h | 4 + drivers/net/igb/igb_main.c | 266 ++++++++++++++++++++++++++++++++++++++-- 5 files changed, 304 insertions(+), 8 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index dd50237c8cb0..e613d5a606d8 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -116,6 +116,7 @@ union e1000_adv_tx_desc { }; /* Adv Transmit Descriptor Config Masks */ +#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */ #define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ #define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ #define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 5342e231c1d5..79168eeaaa09 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -104,6 +104,7 @@ #define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ #define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ +#define E1000_RXD_STAT_TS 0x10000 /* Pkt was time stamped */ #define E1000_RXD_ERR_CE 0x01 /* CRC Error */ #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 64d95cd71f2e..1fb19ca081c6 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -78,9 +78,37 @@ /* IEEE 1588 TIMESYNCH */ #define E1000_TSYNCTXCTL 0x0B614 +#define E1000_TSYNCTXCTL_VALID (1<<0) +#define E1000_TSYNCTXCTL_ENABLED (1<<4) #define E1000_TSYNCRXCTL 0x0B620 +#define E1000_TSYNCRXCTL_VALID (1<<0) +#define E1000_TSYNCRXCTL_ENABLED (1<<4) +enum { + E1000_TSYNCRXCTL_TYPE_L2_V2 = 0, + E1000_TSYNCRXCTL_TYPE_L4_V1 = (1<<1), + E1000_TSYNCRXCTL_TYPE_L2_L4_V2 = (1<<2), + E1000_TSYNCRXCTL_TYPE_ALL = (1<<3), + E1000_TSYNCRXCTL_TYPE_EVENT_V2 = (1<<3) | (1<<1), +}; #define E1000_TSYNCRXCFG 0x05F50 +enum { + E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE = 0<<0, + E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE = 1<<0, + E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE = 2<<0, + E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE = 3<<0, + E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE = 4<<0, + E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE = 0<<8, + E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE = 1<<8, + E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE = 2<<8, + E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE = 3<<8, + E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE = 8<<8, + E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE = 9<<8, + E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE = 0xA<<8, + E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE = 0xB<<8, + E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE = 0xC<<8, + E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE = 0xD<<8, +}; #define E1000_SYSTIML 0x0B600 #define E1000_SYSTIMH 0x0B604 #define E1000_TIMINCA 0x0B608 @@ -103,6 +131,18 @@ #define E1000_ETQF6 0x05CC8 #define E1000_ETQF7 0x05CCC +/* Filtering Registers */ +#define E1000_SAQF(_n) (0x5980 + 4 * (_n)) +#define E1000_DAQF(_n) (0x59A0 + 4 * (_n)) +#define E1000_SPQF(_n) (0x59C0 + 4 * (_n)) +#define E1000_FTQF(_n) (0x59E0 + 4 * (_n)) +#define E1000_SAQF0 E1000_SAQF(0) +#define E1000_DAQF0 E1000_DAQF(0) +#define E1000_SPQF0 E1000_SPQF(0) +#define E1000_FTQF0 E1000_FTQF(0) +#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ +#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ + /* Split and Replication RX Control - RW */ /* * Convenience macros diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 797a9fe107ad..bb8c35cec1ab 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -35,6 +35,8 @@ #include "e1000_82575.h" #include +#include +#include struct igb_adapter; @@ -255,6 +257,8 @@ struct igb_adapter { struct net_device_stats net_stats; struct cyclecounter cycles; struct timecounter clock; + struct timecompare compare; + struct hwtstamp_config hwtstamp_config; /* structs defined in e1000_hw.h */ struct e1000_hw hw; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 90090bb26044..f9d576bfef90 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -250,7 +250,8 @@ static char *igb_get_time_str(struct igb_adapter *adapter, delta = timespec_sub(nic, sys); sprintf(buffer, - "NIC %ld.%09lus, SYS %ld.%09lus, NIC-SYS %lds + %09luns", + "HW %llu, NIC %ld.%09lus, SYS %ld.%09lus, NIC-SYS %lds + %09luns", + hw, (long)nic.tv_sec, nic.tv_nsec, (long)sys.tv_sec, sys.tv_nsec, (long)delta.tv_sec, delta.tv_nsec); @@ -1400,6 +1401,18 @@ static int __devinit igb_probe(struct pci_dev *pdev, &adapter->cycles, ktime_to_ns(ktime_get_real())); + /* + * Synchronize our NIC clock against system wall clock. NIC + * time stamp reading requires ~3us per sample, each sample + * was pretty stable even under load => only require 10 + * samples for each offset comparison. + */ + memset(&adapter->compare, 0, sizeof(adapter->compare)); + adapter->compare.source = &adapter->clock; + adapter->compare.target = ktime_get_real; + adapter->compare.num_samples = 10; + timecompare_update(&adapter->compare, 0); + #ifdef DEBUG { char buffer[160]; @@ -2748,6 +2761,7 @@ set_itr_now: #define IGB_TX_FLAGS_VLAN 0x00000002 #define IGB_TX_FLAGS_TSO 0x00000004 #define IGB_TX_FLAGS_IPV4 0x00000008 +#define IGB_TX_FLAGS_TSTAMP 0x00000010 #define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 #define IGB_TX_FLAGS_VLAN_SHIFT 16 @@ -2975,6 +2989,9 @@ static inline void igb_tx_queue_adv(struct igb_adapter *adapter, if (tx_flags & IGB_TX_FLAGS_VLAN) cmd_type_len |= E1000_ADVTXD_DCMD_VLE; + if (tx_flags & IGB_TX_FLAGS_TSTAMP) + cmd_type_len |= E1000_ADVTXD_MAC_TSTAMP; + if (tx_flags & IGB_TX_FLAGS_TSO) { cmd_type_len |= E1000_ADVTXD_DCMD_TSE; @@ -3065,6 +3082,7 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb, unsigned int tx_flags = 0; u8 hdr_len = 0; int tso = 0; + union skb_shared_tx *shtx; if (test_bit(__IGB_DOWN, &adapter->state)) { dev_kfree_skb_any(skb); @@ -3085,7 +3103,29 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb, /* this is a hard error */ return NETDEV_TX_BUSY; } - skb_orphan(skb); + + /* + * TODO: check that there currently is no other packet with + * time stamping in the queue + * + * When doing time stamping, keep the connection to the socket + * a while longer: it is still needed by skb_hwtstamp_tx(), + * called either in igb_tx_hwtstamp() or by our caller when + * doing software time stamping. + */ + shtx = skb_tx(skb); + if (unlikely(shtx->hardware)) { + shtx->in_progress = 1; + tx_flags |= IGB_TX_FLAGS_TSTAMP; + } else if (likely(!shtx->software)) { + /* + * TODO: can this be solved in dev.c:dev_hard_start_xmit()? + * There are probably unmodified driver which do something + * like this and thus don't work in combination with + * SOF_TIMESTAMPING_TX_SOFTWARE. + */ + skb_orphan(skb); + } if (adapter->vlgrp && vlan_tx_tag_present(skb)) { tx_flags |= IGB_TX_FLAGS_VLAN; @@ -3743,6 +3783,43 @@ static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget) return 1; } +/** + * igb_hwtstamp - utility function which checks for TX time stamp + * @adapter: board private structure + * @skb: packet that was just sent + * + * If we were asked to do hardware stamping and such a time stamp is + * available, then it must have been for this skb here because we only + * allow only one such packet into the queue. + */ +static void igb_tx_hwtstamp(struct igb_adapter *adapter, struct sk_buff *skb) +{ + union skb_shared_tx *shtx = skb_tx(skb); + struct e1000_hw *hw = &adapter->hw; + + if (unlikely(shtx->hardware)) { + u32 valid = rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID; + if (valid) { + u64 regval = rd32(E1000_TXSTMPL); + u64 ns; + struct skb_shared_hwtstamps shhwtstamps; + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + regval |= (u64)rd32(E1000_TXSTMPH) << 32; + ns = timecounter_cyc2time(&adapter->clock, + regval); + timecompare_update(&adapter->compare, ns); + shhwtstamps.hwtstamp = ns_to_ktime(ns); + shhwtstamps.syststamp = + timecompare_transform(&adapter->compare, ns); + skb_tstamp_tx(skb, &shhwtstamps); + } + + /* delayed orphaning: skb_tstamp_tx() needs the socket */ + skb_orphan(skb); + } +} + /** * igb_clean_tx_irq - Reclaim resources after transmit completes * @adapter: board private structure @@ -3781,6 +3858,8 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring) skb->len; total_packets += segs; total_bytes += bytecount; + + igb_tx_hwtstamp(adapter, skb); } igb_unmap_and_free_tx_resource(adapter, buffer_info); @@ -3914,6 +3993,7 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, { struct igb_adapter *adapter = rx_ring->adapter; struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; union e1000_adv_rx_desc *rx_desc , *next_rxd; struct igb_buffer *buffer_info , *next_buffer; @@ -4006,6 +4086,47 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, goto next_desc; } send_up: + /* + * If this bit is set, then the RX registers contain + * the time stamp. No other packet will be time + * stamped until we read these registers, so read the + * registers to make them available again. Because + * only one packet can be time stamped at a time, we + * know that the register 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 can turn into a + * skb_shared_hwtstamps. + * + * TODO: can time stamping be triggered (thus locking + * the registers) without the packet reaching this point + * here? In that case RX time stamping would get stuck. + * + * TODO: in "time stamp all packets" mode this bit is + * not set. Need a global flag for this mode and then + * always read the registers. Cannot be done without + * a race condition. + */ + if (unlikely(staterr & E1000_RXD_STAT_TS)) { + u64 regval; + u64 ns; + struct skb_shared_hwtstamps *shhwtstamps = + skb_hwtstamps(skb); + + WARN(!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID), + "igb: no RX time stamp available for time stamped packet"); + regval = rd32(E1000_RXSTMPL); + regval |= (u64)rd32(E1000_RXSTMPH) << 32; + ns = timecounter_cyc2time(&adapter->clock, regval); + timecompare_update(&adapter->compare, ns); + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + shhwtstamps->hwtstamp = ns_to_ktime(ns); + shhwtstamps->syststamp = + timecompare_transform(&adapter->compare, ns); + } + if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { dev_kfree_skb_irq(skb); goto next_desc; @@ -4188,13 +4309,33 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) * @ifreq: * @cmd: * - * Currently cannot enable any kind of hardware time stamping, but - * supports SIOCSHWTSTAMP in general. + * Outgoing time stamping can be enabled and disabled. Play nice and + * disable it when requested, although it shouldn't case any overhead + * when no packet needs it. At most one packet in the queue may be + * marked for time stamping, otherwise it would be impossible to tell + * for sure to which packet the hardware time stamp belongs. + * + * Incoming time stamping has to be configured via the hardware + * filters. Not all combinations are supported, in particular event + * type has to be specified. Matching the kind of event packet is + * not supported, with the exception of "all V2 events regardless of + * level 2 or 4". + * **/ static int igb_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; struct hwtstamp_config config; + u32 tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED; + u32 tsync_rx_ctl_bit = E1000_TSYNCRXCTL_ENABLED; + u32 tsync_rx_ctl_type = 0; + u32 tsync_rx_cfg = 0; + int is_l4 = 0; + int is_l2 = 0; + short port = 319; /* PTP */ + u32 regval; if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; @@ -4203,11 +4344,120 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev, if (config.flags) return -EINVAL; - if (config.tx_type == HWTSTAMP_TX_OFF && - config.rx_filter == HWTSTAMP_FILTER_NONE) - return 0; + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + tsync_tx_ctl_bit = 0; + break; + case HWTSTAMP_TX_ON: + tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED; + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + tsync_rx_ctl_bit = 0; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_ALL: + /* + * register TSYNCRXCFG must be set, therefore it is not + * possible to time stamp both Sync and Delay_Req messages + * => fall back to time stamping all packets + */ + tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_ALL; + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1; + tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; + is_l4 = 1; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1; + tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; + is_l4 = 1; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2; + tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE; + is_l2 = 1; + is_l4 = 1; + config.rx_filter = HWTSTAMP_FILTER_SOME; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2; + tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE; + is_l2 = 1; + is_l4 = 1; + config.rx_filter = HWTSTAMP_FILTER_SOME; + break; + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_EVENT_V2; + config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + is_l2 = 1; + break; + default: + return -ERANGE; + } + + /* enable/disable TX */ + regval = rd32(E1000_TSYNCTXCTL); + regval = (regval & ~E1000_TSYNCTXCTL_ENABLED) | tsync_tx_ctl_bit; + wr32(E1000_TSYNCTXCTL, regval); + + /* enable/disable RX, define which PTP packets are time stamped */ + regval = rd32(E1000_TSYNCRXCTL); + regval = (regval & ~E1000_TSYNCRXCTL_ENABLED) | tsync_rx_ctl_bit; + regval = (regval & ~0xE) | tsync_rx_ctl_type; + wr32(E1000_TSYNCRXCTL, regval); + wr32(E1000_TSYNCRXCFG, tsync_rx_cfg); + + /* + * Ethertype Filter Queue Filter[0][15:0] = 0x88F7 + * (Ethertype to filter on) + * Ethertype Filter Queue Filter[0][26] = 0x1 (Enable filter) + * Ethertype Filter Queue Filter[0][30] = 0x1 (Enable Timestamping) + */ + wr32(E1000_ETQF0, is_l2 ? 0x440088f7 : 0); + + /* L4 Queue Filter[0]: only filter by source and destination port */ + wr32(E1000_SPQF0, htons(port)); + wr32(E1000_IMIREXT(0), is_l4 ? + ((1<<12) | (1<<19) /* bypass size and control flags */) : 0); + wr32(E1000_IMIR(0), is_l4 ? + (htons(port) + | (0<<16) /* immediate interrupt disabled */ + | 0 /* (1<<17) bit cleared: do not bypass + destination port check */) + : 0); + wr32(E1000_FTQF0, is_l4 ? + (0x11 /* UDP */ + | (1<<15) /* VF not compared */ + | (1<<27) /* Enable Timestamping */ + | (7<<28) /* only source port filter enabled, + source/target address and protocol + masked */) + : ((1<<15) | (15<<28) /* all mask bits set = filter not + enabled */)); + + wrfl(); + + adapter->hwtstamp_config = config; + + /* clear TX/RX time stamp registers, just to be sure */ + regval = rd32(E1000_TXSTMPH); + regval = rd32(E1000_RXSTMPH); - return -ERANGE; + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; } /** -- cgit v1.2.3-59-g8ed1b From cbd347adfee2ba52a8ef85f92a46933d5840cc39 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sun, 15 Feb 2009 23:59:44 -0800 Subject: igb: remove unused defines This patch removes all of the unused defines from the .h files contained in igb. For some defines there was a use and so I plugged them into the correct locations. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.h | 16 +----- drivers/net/igb/e1000_defines.h | 113 ---------------------------------------- drivers/net/igb/e1000_mac.h | 5 -- drivers/net/igb/e1000_phy.c | 3 -- drivers/net/igb/e1000_regs.h | 14 ----- drivers/net/igb/igb.h | 17 ++---- drivers/net/igb/igb_ethtool.c | 6 +-- drivers/net/igb/igb_main.c | 12 ++--- 8 files changed, 11 insertions(+), 175 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index e613d5a606d8..49b41c92a8c8 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -58,9 +58,6 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); E1000_EICR_RX_QUEUE2 | \ E1000_EICR_RX_QUEUE3) -#define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE -#define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE - /* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */ /* Receive Descriptor - Advanced */ @@ -95,12 +92,6 @@ union e1000_adv_rx_desc { #define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0 #define E1000_RXDADV_HDRBUFLEN_SHIFT 5 -/* RSS Hash results */ - -/* RSS Packet Types as indicated in the receive descriptor */ -#define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */ -#define E1000_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */ - /* Transmit Descriptor - Advanced */ union e1000_adv_tx_desc { struct { @@ -150,11 +141,8 @@ struct e1000_adv_tx_context_desc { #define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */ /* Direct Cache Access (DCA) definitions */ -#define E1000_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */ -#define E1000_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */ - -#define E1000_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */ -#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */ +#define E1000_DCA_CTRL_DCA_MODE_DISABLE 0x01 /* DCA Disable */ +#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */ #define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */ #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 79168eeaaa09..5a32a7004e0a 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -42,33 +42,9 @@ #define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ #define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ #define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ -#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ -#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ -#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ -#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ -#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Wake Up Status */ - -/* Wake Up Packet Length */ - -/* Four Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 - -/* Each Flexible Filter is at most 128 (0x80) bytes in length */ -#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 - /* Extended Device Control */ -#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ -#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */ -#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */ #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ -#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ -#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 @@ -103,14 +79,7 @@ #define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ #define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ -#define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ #define E1000_RXD_STAT_TS 0x10000 /* Pkt was time stamped */ -#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ -#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ -#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ -#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ -#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ -#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ #define E1000_RXDEXT_STATERR_CE 0x01000000 #define E1000_RXDEXT_STATERR_SE 0x02000000 @@ -120,14 +89,6 @@ #define E1000_RXDEXT_STATERR_IPE 0x40000000 #define E1000_RXDEXT_STATERR_RXE 0x80000000 -/* mask to determine if packets should be dropped due to frame errors */ -#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ - E1000_RXD_ERR_CE | \ - E1000_RXD_ERR_SE | \ - E1000_RXD_ERR_SEQ | \ - E1000_RXD_ERR_CXE | \ - E1000_RXD_ERR_RXE) - /* Same mask, but for extended and packet split descriptors */ #define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ E1000_RXDEXT_STATERR_CE | \ @@ -146,16 +107,11 @@ /* Management Control */ #define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ #define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ -#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ /* 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 */ /* Enable MAC address filtering */ #define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 -/* Enable MNG packets to host memory */ -#define E1000_MANC_EN_MNG2HOST 0x00200000 -/* Enable IP address filtering */ - /* Receive Control */ #define E1000_RCTL_EN 0x00000002 /* enable */ @@ -163,14 +119,11 @@ #define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ #define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ #define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ #define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ #define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ #define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ -#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ #define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ #define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ #define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ @@ -227,11 +180,7 @@ /* enable link status from external LINK_0 and LINK_1 pins */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ -#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ -#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ #define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ -#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ -#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ #define E1000_CTRL_RST 0x04000000 /* Global reset */ #define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ #define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ @@ -309,9 +258,7 @@ #define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX /* LED Control */ -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 #define E1000_LEDCTL_LED0_BLINK 0x00000080 #define E1000_LEDCTL_MODE_LED_ON 0xE @@ -358,12 +305,7 @@ #define MAX_JUMBO_FRAME_SIZE 0x3F00 -/* Extended Configuration Control and Size */ -#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 - /* PBA constants */ -#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ -#define E1000_PBA_24K 0x0018 #define E1000_PBA_34K 0x0022 #define E1000_PBA_64K 0x0040 /* 64KB */ @@ -379,41 +321,13 @@ /* Interrupt Cause Read */ #define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ #define E1000_ICR_LSC 0x00000004 /* Link Status Change */ #define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ #define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ -#define E1000_ICR_RXO 0x00000040 /* rx overrun */ #define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ -#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ -#define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */ -#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ -#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ -#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ -#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ -#define E1000_ICR_TXD_LOW 0x00008000 -#define E1000_ICR_SRPD 0x00010000 -#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ -#define E1000_ICR_MNG 0x00040000 /* Manageability event */ -#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 -/* queue 0 Rx descriptor FIFO parity error */ -#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 -/* queue 0 Tx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 -/* host arb read buffer parity error */ -#define E1000_ICR_HOST_ARB_PAR 0x00400000 -#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ -/* queue 1 Rx descriptor FIFO parity error */ -#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 -/* queue 1 Tx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 -/* FW changed the status of DISSW bit in the FWSM */ -#define E1000_ICR_DSW 0x00000020 /* LAN connected device generates an interrupt */ -#define E1000_ICR_PHYINT 0x00001000 -#define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */ #define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ /* Extended Interrupt Cause Read */ @@ -425,7 +339,6 @@ #define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */ #define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */ #define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */ -#define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ #define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ /* TCP Timer */ @@ -455,13 +368,11 @@ #define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ /* Extended Interrupt Mask Set */ -#define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ #define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ /* Interrupt Cause Set */ #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_ICS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ /* Extended Interrupt Cause Set */ @@ -497,7 +408,6 @@ #define E1000_ERR_MAC_INIT 5 #define E1000_ERR_RESET 9 #define E1000_ERR_MASTER_REQUESTS_PENDING 10 -#define E1000_ERR_HOST_INTERFACE_COMMAND 11 #define E1000_BLK_PHY_RESET 12 #define E1000_ERR_SWFW_SYNC 13 #define E1000_NOT_IMPLEMENTED 14 @@ -517,30 +427,9 @@ /* Flow Control */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ -/* Transmit Configuration Word */ -#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ - -/* Receive Configuration Word */ - -/* PCI Express Control */ -#define E1000_GCR_RXD_NO_SNOOP 0x00000001 -#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 -#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 -#define E1000_GCR_TXD_NO_SNOOP 0x00000008 -#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 -#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 - -#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ - E1000_GCR_RXDSCW_NO_SNOOP | \ - E1000_GCR_RXDSCR_NO_SNOOP | \ - E1000_GCR_TXD_NO_SNOOP | \ - E1000_GCR_TXDSCW_NO_SNOOP | \ - E1000_GCR_TXDSCR_NO_SNOOP) - /* PHY Control Register */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ -#define MII_CR_POWER_DOWN 0x0800 /* Power down */ #define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ #define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ #define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ @@ -670,10 +559,8 @@ #define IGP_LED3_MODE 0x07000000 /* PCI/PCI-X/PCI-EX Config space */ -#define PCI_HEADER_TYPE_REGISTER 0x0E #define PCIE_LINK_STATUS 0x12 -#define PCI_HEADER_TYPE_MULTIFUNC 0x80 #define PCIE_LINK_WIDTH_MASK 0x3F0 #define PCIE_LINK_WIDTH_SHIFT 4 diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index 91461de083f5..e5200def582f 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h @@ -82,13 +82,8 @@ enum e1000_mng_mode { #define E1000_FWSM_MODE_MASK 0xE #define E1000_FWSM_MODE_SHIFT 1 -#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 -#define E1000_HICR_EN 0x01 /* Enable bit - RO */ -/* Driver sets this bit when done to put command in RAM */ -#define E1000_HICR_C 0x02 - extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); extern u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr); diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index ff0050e5d0b5..de2d48624683 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -39,9 +39,6 @@ static s32 igb_wait_autoneg(struct e1000_hw *hw); /* Cable length tables */ static const u16 e1000_m88_cable_length_table[] = { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; -#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ - (sizeof(e1000_m88_cable_length_table) / \ - sizeof(e1000_m88_cable_length_table[0])) static const u16 e1000_igp_2_cable_length_table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 1fb19ca081c6..95ed8ec15770 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -73,7 +73,6 @@ #define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ -#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ /* IEEE 1588 TIMESYNCH */ @@ -178,7 +177,6 @@ enum { : (0x0E018 + ((_n) * 0x40))) #define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) \ : (0x0E028 + ((_n) * 0x40))) -#define E1000_TARC(_n) (0x03840 + (_n << 8)) #define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) #define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) #define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) \ @@ -301,9 +299,7 @@ enum { #define E1000_MANC 0x05820 /* Management Control - RW */ #define E1000_IPAV 0x05838 /* IP Address Valid - RW */ #define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ -#define E1000_HOST_IF 0x08800 /* Host Interface */ -#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ #define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ #define E1000_CCMCTL 0x05B48 /* CCM Control Register */ #define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */ @@ -311,9 +307,7 @@ enum { #define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ #define E1000_SWSM 0x05B50 /* SW Semaphore */ #define E1000_FWSM 0x05B54 /* FW Semaphore */ -#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */ #define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */ -#define E1000_HICR 0x08F00 /* Host Inteface Control */ /* RSS registers */ #define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ @@ -322,14 +316,6 @@ enum { #define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt RX VLAN Priority - RW */ /* MSI-X Allocation Register (_i) - RW */ #define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) -/* MSI-X Table entry addr low reg 0 - RW */ -#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) -/* MSI-X Table entry addr upper reg 0 - RW */ -#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) -/* MSI-X Table entry message reg 0 - RW */ -#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) -/* MSI-X Table entry vector ctrl reg 0 - RW */ -#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* Redirection Table - RW Array */ #define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */ diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index bb8c35cec1ab..1f09e042a5f2 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -40,17 +40,9 @@ struct igb_adapter; -/* Interrupt defines */ -#define IGB_MIN_DYN_ITR 3000 -#define IGB_MAX_DYN_ITR 96000 - /* ((1000000000ns / (6000ints/s * 1024ns)) << 2 = 648 */ #define IGB_START_ITR 648 -#define IGB_DYN_ITR_PACKET_THRESHOLD 2 -#define IGB_DYN_ITR_LENGTH_LOW 200 -#define IGB_DYN_ITR_LENGTH_HIGH 1000 - /* TX/RX descriptor defines */ #define IGB_DEFAULT_TXD 256 #define IGB_MIN_TXD 80 @@ -92,8 +84,6 @@ struct igb_adapter; #define IGB_RXBUFFER_512 512 #define IGB_RXBUFFER_1024 1024 #define IGB_RXBUFFER_2048 2048 -#define IGB_RXBUFFER_4096 4096 -#define IGB_RXBUFFER_8192 8192 #define IGB_RXBUFFER_16384 16384 /* Packet Buffer allocations */ @@ -286,10 +276,9 @@ struct igb_adapter { }; #define IGB_FLAG_HAS_MSI (1 << 0) -#define IGB_FLAG_MSI_ENABLE (1 << 1) -#define IGB_FLAG_DCA_ENABLED (1 << 2) -#define IGB_FLAG_QUAD_PORT_A (1 << 3) -#define IGB_FLAG_NEED_CTX_IDX (1 << 4) +#define IGB_FLAG_DCA_ENABLED (1 << 1) +#define IGB_FLAG_QUAD_PORT_A (1 << 2) +#define IGB_FLAG_NEED_CTX_IDX (1 << 3) enum e1000_state_t { __IGB_TESTING, diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index bd050b1dab7f..30b7bc008d9d 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1366,8 +1366,7 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter) wr32(E1000_RDH(0), 0); wr32(E1000_RDT(0), 0); rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); - rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_RDMTS_HALF | + rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF | (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); wr32(E1000_RCTL, rctl); wr32(E1000_SRRCTL(0), 0); @@ -1855,9 +1854,6 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) return 0; } -/* toggle LED 4 times per second = 2 "blinks" per second */ -#define IGB_ID_INTERVAL (HZ/4) - /* bit defines for adapter->led_status */ #define IGB_LED_ON 0 diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 18bc5700faf5..23209bd4f401 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1305,7 +1305,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, hw->fc.original_type = e1000_fc_default; hw->fc.type = e1000_fc_default; - adapter->itr_setting = 3; + adapter->itr_setting = IGB_DEFAULT_ITR; adapter->itr = IGB_START_ITR; igb_validate_mdi_setting(hw); @@ -1366,7 +1366,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "DCA enabled\n"); /* Always use CB2 mode, difference is masked * in the CB driver. */ - wr32(E1000_DCA_CTRL, 2); + wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); igb_setup_dca(adapter); } #endif @@ -1498,7 +1498,7 @@ static void __devexit igb_remove(struct pci_dev *pdev) dev_info(&pdev->dev, "DCA disabled\n"); dca_remove_requester(&pdev->dev); adapter->flags &= ~IGB_FLAG_DCA_ENABLED; - wr32(E1000_DCA_CTRL, 1); + wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE); } #endif @@ -3058,8 +3058,6 @@ static int igb_maybe_stop_tx(struct net_device *netdev, return __igb_maybe_stop_tx(netdev, tx_ring, size); } -#define TXD_USE_COUNT(S) (((S) >> (IGB_MAX_TXD_PWR)) + 1) - static int igb_xmit_frame_ring_adv(struct sk_buff *skb, struct net_device *netdev, struct igb_ring *tx_ring) @@ -3586,7 +3584,7 @@ static int __igb_notify_dca(struct device *dev, void *data) break; /* Always use CB2 mode, difference is masked * in the CB driver. */ - wr32(E1000_DCA_CTRL, 2); + wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); if (dca_add_requester(dev) == 0) { adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(&adapter->pdev->dev, "DCA enabled\n"); @@ -3601,7 +3599,7 @@ static int __igb_notify_dca(struct device *dev, void *data) dca_remove_requester(dev); dev_info(&adapter->pdev->dev, "DCA disabled\n"); adapter->flags &= ~IGB_FLAG_DCA_ENABLED; - wr32(E1000_DCA_CTRL, 1); + wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE); } break; } -- cgit v1.2.3-59-g8ed1b From 85e8d004ecbc51ead6ae926e15973b42cf07b36e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 16 Feb 2009 00:00:20 -0800 Subject: igb: transition driver to only using advanced descriptors Currently the driver uses advanced descriptors for its main functionality, but then uses legacy when testing. This patch changes this so that advanced descriptors are used throughout and all mentions of legacy descriptors are removed. Signed-off-by: Alexander Duyck Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_hw.h | 138 ------------------------------------------ drivers/net/igb/igb.h | 3 - drivers/net/igb/igb_ethtool.c | 51 +++++++++------- drivers/net/igb/igb_main.c | 6 +- 4 files changed, 32 insertions(+), 166 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index bd86cebed37c..10b872d3c9f4 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -144,144 +144,6 @@ enum e1000_fc_type { e1000_fc_default = 0xFF }; - -/* Receive Descriptor */ -struct e1000_rx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - __le16 length; /* Length of data DMAed into data buffer */ - __le16 csum; /* Packet checksum */ - u8 status; /* Descriptor status */ - u8 errors; /* Descriptor Errors */ - __le16 special; -}; - -/* Receive Descriptor - Extended */ -union e1000_rx_desc_extended { - struct { - __le64 buffer_addr; - __le64 reserved; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define MAX_PS_BUFFERS 4 -/* Receive Descriptor - Packet Split */ -union e1000_rx_desc_packet_split { - struct { - /* one buffer for protocol header(s), three data buffers */ - __le64 buffer_addr[MAX_PS_BUFFERS]; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length0; /* length of buffer 0 */ - __le16 vlan; /* VLAN tag */ - } middle; - struct { - __le16 header_status; - __le16 length[3]; /* length of buffers 1-3 */ - } upper; - __le64 reserved; - } wb; /* writeback */ -}; - -/* Transmit Descriptor */ -struct e1000_tx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - __le16 special; - } fields; - } upper; -}; - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - __le32 ip_config; - struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - __le16 ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - __le32 tcp_config; - struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - __le16 tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - __le32 cmd_and_length; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - __le16 mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - __le64 buffer_addr; /* Address of the descriptor's buffer address */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 typ_len_ext; - u8 cmd; - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - __le16 special; - } fields; - } upper; -}; - /* Statistics counters collected by the MAC */ struct e1000_hw_stats { u64 crcerrs; diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 1f09e042a5f2..49fc0daf45af 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -180,9 +180,6 @@ struct igb_ring { (&(((union e1000_adv_tx_desc *)((R).desc))[i])) #define E1000_TX_CTXTDESC_ADV(R, i) \ (&(((struct e1000_adv_tx_context_desc *)((R).desc))[i])) -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) /* board specific private data structure */ diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 30b7bc008d9d..31f9a64773ff 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1272,6 +1272,7 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter) struct igb_ring *tx_ring = &adapter->test_tx_ring; struct igb_ring *rx_ring = &adapter->test_rx_ring; struct pci_dev *pdev = adapter->pdev; + struct igb_buffer *buffer_info; u32 rctl; int i, ret_val; @@ -1288,7 +1289,7 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter) goto err_nomem; } - tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); + tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size, &tx_ring->dma); @@ -1302,7 +1303,7 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter) ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); wr32(E1000_TDBAH(0), ((u64) tx_ring->dma >> 32)); wr32(E1000_TDLEN(0), - tx_ring->count * sizeof(struct e1000_tx_desc)); + tx_ring->count * sizeof(union e1000_adv_tx_desc)); wr32(E1000_TDH(0), 0); wr32(E1000_TDT(0), 0); wr32(E1000_TCTL, @@ -1311,27 +1312,31 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter) E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); for (i = 0; i < tx_ring->count; i++) { - struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); + union e1000_adv_tx_desc *tx_desc; struct sk_buff *skb; unsigned int size = 1024; + tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); skb = alloc_skb(size, GFP_KERNEL); if (!skb) { ret_val = 3; goto err_nomem; } skb_put(skb, size); - tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].length = skb->len; - tx_ring->buffer_info[i].dma = - pci_map_single(pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); - tx_desc->lower.data = cpu_to_le32(skb->len); - tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS | - E1000_TXD_CMD_RS); - tx_desc->upper.data = 0; + buffer_info = &tx_ring->buffer_info[i]; + buffer_info->skb = skb; + buffer_info->length = skb->len; + buffer_info->dma = pci_map_single(pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + tx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); + tx_desc->read.olinfo_status = cpu_to_le32(skb->len) << + E1000_ADVTXD_PAYLEN_SHIFT; + tx_desc->read.cmd_type_len = cpu_to_le32(skb->len); + tx_desc->read.cmd_type_len |= cpu_to_le32(E1000_TXD_CMD_EOP | + E1000_TXD_CMD_IFCS | + E1000_TXD_CMD_RS | + E1000_ADVTXD_DTYP_DATA | + E1000_ADVTXD_DCMD_DEXT); } /* Setup Rx descriptor ring and Rx buffers */ @@ -1347,7 +1352,7 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter) goto err_nomem; } - rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc); + rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc); rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size, &rx_ring->dma); if (!rx_ring->desc) { @@ -1369,12 +1374,14 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter) rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF | (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); wr32(E1000_RCTL, rctl); - wr32(E1000_SRRCTL(0), 0); + wr32(E1000_SRRCTL(0), E1000_SRRCTL_DESCTYPE_ADV_ONEBUF); for (i = 0; i < rx_ring->count; i++) { - struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i); + union e1000_adv_rx_desc *rx_desc; struct sk_buff *skb; + buffer_info = &rx_ring->buffer_info[i]; + rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); skb = alloc_skb(IGB_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL); if (!skb) { @@ -1382,11 +1389,11 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter) goto err_nomem; } skb_reserve(skb, NET_IP_ALIGN); - rx_ring->buffer_info[i].skb = skb; - rx_ring->buffer_info[i].dma = - pci_map_single(pdev, skb->data, IGB_RXBUFFER_2048, - PCI_DMA_FROMDEVICE); - rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma); + buffer_info->skb = skb; + buffer_info->dma = pci_map_single(pdev, skb->data, + IGB_RXBUFFER_2048, + PCI_DMA_FROMDEVICE); + rx_desc->read.pkt_addr = cpu_to_le64(buffer_info->dma); memset(skb->data, 0x00, skb->len); } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 23209bd4f401..43f489aba191 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -994,7 +994,7 @@ void igb_reset(struct igb_adapter *adapter) /* the tx fifo also stores 16 bytes of information about the tx * but don't include ethernet FCS because hardware appends it */ min_tx_space = (adapter->max_frame_size + - sizeof(struct e1000_tx_desc) - + sizeof(union e1000_adv_tx_desc) - ETH_FCS_LEN) * 2; min_tx_space = ALIGN(min_tx_space, 1024); min_tx_space >>= 10; @@ -1704,7 +1704,7 @@ int igb_setup_tx_resources(struct igb_adapter *adapter, memset(tx_ring->buffer_info, 0, size); /* round up to nearest 4K */ - tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); + tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size, @@ -1773,7 +1773,7 @@ static void igb_configure_tx(struct igb_adapter *adapter) struct igb_ring *ring = &adapter->tx_ring[i]; j = ring->reg_idx; wr32(E1000_TDLEN(j), - ring->count * sizeof(struct e1000_tx_desc)); + ring->count * sizeof(union e1000_adv_tx_desc)); tdba = ring->dma; wr32(E1000_TDBAL(j), tdba & 0x00000000ffffffffULL); -- cgit v1.2.3-59-g8ed1b From 1bfaf07bb1d7201d3c6cb984bccd9c2416e19b6c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Feb 2009 20:39:23 -0800 Subject: igb: add vfs_allocated_count as placeholder for number of vfs This is the first step in supporting sr-iov. The vf_allocated_count value will be 0 until we actually have vfs present. In the meantime it represents an offset value for the start of the queues. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 9 ++++++--- drivers/net/igb/igb_main.c | 17 +++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 49fc0daf45af..3d3e5f6cd313 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -57,8 +57,10 @@ struct igb_adapter; #define IGB_MIN_ITR_USECS 10 /* Transmit and receive queues */ -#define IGB_MAX_RX_QUEUES 4 -#define IGB_MAX_TX_QUEUES 4 +#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? \ + (adapter->vfs_allocated_count > 6 ? 1 : 2) : 4) +#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES +#define IGB_ABS_MAX_TX_QUEUES 4 /* RX descriptor control thresholds. * PTHRESH - MAC will consider prefetch if it has fewer than this number of @@ -267,9 +269,10 @@ struct igb_adapter { unsigned int flags; u32 eeprom_wol; - struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES]; + struct igb_ring *multi_tx_table[IGB_ABS_MAX_TX_QUEUES]; unsigned int tx_ring_count; unsigned int rx_ring_count; + unsigned int vfs_allocated_count; }; #define IGB_FLAG_HAS_MSI (1 << 0) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 5a6fff622e4f..0dcc0c109b9d 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -312,6 +312,7 @@ module_exit(igb_exit_module); static void igb_cache_ring_register(struct igb_adapter *adapter) { int i; + unsigned int rbase_offset = adapter->vfs_allocated_count; switch (adapter->hw.mac.type) { case e1000_82576: @@ -321,9 +322,11 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) * and continue consuming queues in the same sequence */ for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].reg_idx = Q_IDX_82576(i); + adapter->rx_ring[i].reg_idx = rbase_offset + + Q_IDX_82576(i); for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].reg_idx = Q_IDX_82576(i); + adapter->tx_ring[i].reg_idx = rbase_offset + + Q_IDX_82576(i); break; case e1000_82575: default: @@ -423,7 +426,7 @@ static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue, a vector number along with a "valid" bit. Sadly, the layout of the table is somewhat counterintuitive. */ if (rx_queue > IGB_N0_QUEUE) { - index = (rx_queue >> 1); + index = (rx_queue >> 1) + adapter->vfs_allocated_count; ivar = array_rd32(E1000_IVAR0, index); if (rx_queue & 0x1) { /* vector goes into third byte of register */ @@ -438,7 +441,7 @@ static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue, array_wr32(E1000_IVAR0, index, ivar); } if (tx_queue > IGB_N0_QUEUE) { - index = (tx_queue >> 1); + index = (tx_queue >> 1) + adapter->vfs_allocated_count; ivar = array_rd32(E1000_IVAR0, index); if (tx_queue & 0x1) { /* vector goes into high byte of register */ @@ -1157,7 +1160,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, pci_save_state(pdev); err = -ENOMEM; - netdev = alloc_etherdev_mq(sizeof(struct igb_adapter), IGB_MAX_TX_QUEUES); + netdev = alloc_etherdev_mq(sizeof(struct igb_adapter), + IGB_ABS_MAX_TX_QUEUES); if (!netdev) goto err_alloc_etherdev; @@ -2029,6 +2033,7 @@ static void igb_configure_rx(struct igb_adapter *adapter) writel(reta.dword, hw->hw_addr + E1000_RETA(0) + (j & ~3)); } + mrqc = E1000_MRQC_ENABLE_RSS_4Q; /* Fill out hash function seeds */ @@ -3150,7 +3155,7 @@ static int igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *netdev) struct igb_ring *tx_ring; int r_idx = 0; - r_idx = skb->queue_mapping & (IGB_MAX_TX_QUEUES - 1); + r_idx = skb->queue_mapping & (IGB_ABS_MAX_TX_QUEUES - 1); tx_ring = adapter->multi_tx_table[r_idx]; /* This goes back to the question of how to logically map a tx queue -- cgit v1.2.3-59-g8ed1b From e173952257d7a3d3c64de3039d9fc02d1fbf49c3 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Feb 2009 20:39:44 -0800 Subject: igb: add pf side of VMDq support Add the pf portion of vmdq support. This provides enough support so that VMDq is enabled, and the pf is functional without enabling vfs. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.h | 26 ++++++ drivers/net/igb/e1000_defines.h | 2 + drivers/net/igb/e1000_regs.h | 7 +- drivers/net/igb/igb.h | 3 +- drivers/net/igb/igb_ethtool.c | 2 +- drivers/net/igb/igb_main.c | 174 ++++++++++++++++++++++++++++++++++++---- 6 files changed, 195 insertions(+), 19 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index 49b41c92a8c8..116714f346bb 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -40,8 +40,11 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); #define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */ #define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 #define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 +#define E1000_SRRCTL_DROP_EN 0x80000000 #define E1000_MRQC_ENABLE_RSS_4Q 0x00000002 +#define E1000_MRQC_ENABLE_VMDQ 0x00000003 +#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005 #define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 @@ -159,4 +162,27 @@ struct e1000_adv_tx_context_desc { #define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */ #define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */ +/* Easy defines for setting default pool, would normally be left a zero */ +#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7 +#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT) + +/* Other useful VMD_CTL register defines */ +#define E1000_VT_CTL_IGNORE_MAC (1 << 28) +#define E1000_VT_CTL_DISABLE_DEF_POOL (1 << 29) +#define E1000_VT_CTL_VM_REPL_EN (1 << 30) + +/* Per VM Offload register setup */ +#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */ +#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */ +#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */ +#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */ +#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */ +#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */ +#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */ +#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */ +#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ + +#define ALL_QUEUES 0xFFFF + + #endif diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 5a32a7004e0a..d7613db78000 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -399,6 +399,8 @@ #define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ #define E1000_RAL_MAC_ADDR_LEN 4 #define E1000_RAH_MAC_ADDR_LEN 2 +#define E1000_RAH_POOL_MASK 0x03FC0000 +#define E1000_RAH_POOL_1 0x00040000 /* Error Codes */ #define E1000_ERR_NVM 1 diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 95ed8ec15770..5d00c864d106 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -292,7 +292,7 @@ enum { #define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ (0x054E4 + ((_i - 16) * 8))) #define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -#define E1000_VMD_CTL 0x0581C /* VMDq Control - RW */ +#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */ #define E1000_WUC 0x05800 /* Wakeup Control - RW */ #define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ #define E1000_WUS 0x05810 /* Wakeup Status - RO */ @@ -320,6 +320,11 @@ enum { #define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */ +/* VT Registers */ +#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ +/* These act per VF so an array friendly macro is used */ +#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) + #define wr32(reg, value) (writel(value, hw->hw_addr + reg)) #define rd32(reg) (readl(hw->hw_addr + reg)) #define wrfl() ((void)rd32(E1000_STATUS)) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 3d3e5f6cd313..d925f7dd7fb2 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -88,8 +88,7 @@ struct igb_adapter; #define IGB_RXBUFFER_2048 2048 #define IGB_RXBUFFER_16384 16384 -/* Packet Buffer allocations */ - +#define MAX_STD_JUMBO_FRAME_SIZE 9234 /* How many Tx Descriptors do we need to call netif_wake_queue ? */ #define IGB_TX_QUEUE_WAKE 16 diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 31f9a64773ff..34a8a0fadf2d 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -398,7 +398,7 @@ static void igb_get_regs(struct net_device *netdev, regs_buff[34] = rd32(E1000_RLPML); regs_buff[35] = rd32(E1000_RFCTL); regs_buff[36] = rd32(E1000_MRQC); - regs_buff[37] = rd32(E1000_VMD_CTL); + regs_buff[37] = rd32(E1000_VT_CTL); /* Transmit */ regs_buff[38] = rd32(E1000_TCTL); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 0dcc0c109b9d..c7c7eeba3366 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -122,6 +122,10 @@ static void igb_vlan_rx_register(struct net_device *, struct vlan_group *); static void igb_vlan_rx_add_vid(struct net_device *, u16); static void igb_vlan_rx_kill_vid(struct net_device *, u16); static void igb_restore_vlan(struct igb_adapter *); +static inline void igb_set_rah_pool(struct e1000_hw *, int , int); +static void igb_set_mc_list_pools(struct igb_adapter *, int, u16); +static inline void igb_set_vmolr(struct e1000_hw *, int); +static inline void igb_set_vf_rlpml(struct igb_adapter *, int, int); static int igb_suspend(struct pci_dev *, pm_message_t); #ifdef CONFIG_PM @@ -888,6 +892,9 @@ int igb_up(struct igb_adapter *adapter) if (adapter->msix_entries) igb_configure_msix(adapter); + igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); + igb_set_vmolr(hw, adapter->vfs_allocated_count); + /* Clear any pending interrupts. */ rd32(E1000_ICR); igb_irq_enable(adapter); @@ -1617,6 +1624,9 @@ static int igb_open(struct net_device *netdev) * clean_rx handler before we do so. */ igb_configure(adapter); + igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); + igb_set_vmolr(hw, adapter->vfs_allocated_count); + err = igb_request_irq(adapter); if (err) goto err_req_irq; @@ -1797,10 +1807,11 @@ static void igb_configure_tx(struct igb_adapter *adapter) wr32(E1000_DCA_TXCTRL(j), txctrl); } - /* Use the default values for the Tx Inter Packet Gap (IPG) timer */ + /* disable queue 0 to prevent tail bump w/o re-configuration */ + if (adapter->vfs_allocated_count) + wr32(E1000_TXDCTL(0), 0); /* Program the Transmit Control Register */ - tctl = rd32(E1000_TCTL); tctl &= ~E1000_TCTL_CT; tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | @@ -1954,6 +1965,30 @@ static void igb_setup_rctl(struct igb_adapter *adapter) srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; } + /* Attention!!! For SR-IOV PF driver operations you must enable + * queue drop for all VF and PF queues to prevent head of line blocking + * if an un-trusted VF does not provide descriptors to hardware. + */ + if (adapter->vfs_allocated_count) { + u32 vmolr; + + j = adapter->rx_ring[0].reg_idx; + + /* set all queue drop enable bits */ + wr32(E1000_QDE, ALL_QUEUES); + srrctl |= E1000_SRRCTL_DROP_EN; + + /* disable queue 0 to prevent tail write w/o re-config */ + wr32(E1000_RXDCTL(0), 0); + + vmolr = rd32(E1000_VMOLR(j)); + if (rctl & E1000_RCTL_LPE) + vmolr |= E1000_VMOLR_LPE; + if (adapter->num_rx_queues > 0) + vmolr |= E1000_VMOLR_RSSE; + wr32(E1000_VMOLR(j), vmolr); + } + for (i = 0; i < adapter->num_rx_queues; i++) { j = adapter->rx_ring[i].reg_idx; wr32(E1000_SRRCTL(j), srrctl); @@ -1962,6 +1997,54 @@ static void igb_setup_rctl(struct igb_adapter *adapter) wr32(E1000_RCTL, rctl); } +/** + * igb_rlpml_set - set maximum receive packet size + * @adapter: board private structure + * + * Configure maximum receivable packet size. + **/ +static void igb_rlpml_set(struct igb_adapter *adapter) +{ + u32 max_frame_size = adapter->max_frame_size; + struct e1000_hw *hw = &adapter->hw; + u16 pf_id = adapter->vfs_allocated_count; + + if (adapter->vlgrp) + max_frame_size += VLAN_TAG_SIZE; + + /* if vfs are enabled we set RLPML to the largest possible request + * size and set the VMOLR RLPML to the size we need */ + if (pf_id) { + igb_set_vf_rlpml(adapter, max_frame_size, pf_id); + max_frame_size = MAX_STD_JUMBO_FRAME_SIZE + VLAN_TAG_SIZE; + } + + wr32(E1000_RLPML, max_frame_size); +} + +/** + * igb_configure_vt_default_pool - Configure VT default pool + * @adapter: board private structure + * + * Configure the default pool + **/ +static void igb_configure_vt_default_pool(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u16 pf_id = adapter->vfs_allocated_count; + u32 vtctl; + + /* not in sr-iov mode - do nothing */ + if (!pf_id) + return; + + vtctl = rd32(E1000_VT_CTL); + vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK | + E1000_VT_CTL_DISABLE_DEF_POOL); + vtctl |= pf_id << E1000_VT_CTL_DEFAULT_POOL_SHIFT; + wr32(E1000_VT_CTL, vtctl); +} + /** * igb_configure_rx - Configure receive Unit after Reset * @adapter: board private structure @@ -2033,8 +2116,10 @@ static void igb_configure_rx(struct igb_adapter *adapter) writel(reta.dword, hw->hw_addr + E1000_RETA(0) + (j & ~3)); } - - mrqc = E1000_MRQC_ENABLE_RSS_4Q; + if (adapter->vfs_allocated_count) + mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q; + else + mrqc = E1000_MRQC_ENABLE_RSS_4Q; /* Fill out hash function seeds */ for (j = 0; j < 10; j++) @@ -2059,6 +2144,9 @@ static void igb_configure_rx(struct igb_adapter *adapter) rxcsum |= E1000_RXCSUM_PCSD; wr32(E1000_RXCSUM, rxcsum); } else { + /* Enable multi-queue for sr-iov */ + if (adapter->vfs_allocated_count) + wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ); /* Enable Receive Checksum Offload for TCP and UDP */ rxcsum = rd32(E1000_RXCSUM); if (adapter->rx_csum) @@ -2069,11 +2157,10 @@ static void igb_configure_rx(struct igb_adapter *adapter) wr32(E1000_RXCSUM, rxcsum); } - if (adapter->vlgrp) - wr32(E1000_RLPML, - adapter->max_frame_size + VLAN_TAG_SIZE); - else - wr32(E1000_RLPML, adapter->max_frame_size); + /* Set the default pool for the PF's first queue */ + igb_configure_vt_default_pool(adapter); + + igb_rlpml_set(adapter); /* Enable Receives */ wr32(E1000_RCTL, rctl); @@ -2303,6 +2390,8 @@ static int igb_set_mac(struct net_device *netdev, void *p) hw->mac.ops.rar_set(hw, hw->mac.addr, 0); + igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); + return 0; } @@ -2362,7 +2451,11 @@ static void igb_set_multi(struct net_device *netdev) memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); mc_ptr = mc_ptr->next; } - igb_update_mc_addr_list(hw, mta_list, i, 1, mac->rar_entry_count); + igb_update_mc_addr_list(hw, mta_list, i, + adapter->vfs_allocated_count + 1, + mac->rar_entry_count); + + igb_set_mc_list_pools(adapter, i, mac->rar_entry_count); kfree(mta_list); } @@ -3222,7 +3315,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } -#define MAX_STD_JUMBO_FRAME_SIZE 9234 if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n"); return -EINVAL; @@ -3256,6 +3348,12 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) #else adapter->rx_buffer_len = PAGE_SIZE / 2; #endif + + /* if sr-iov is enabled we need to force buffer size to 1K or larger */ + if (adapter->vfs_allocated_count && + (adapter->rx_buffer_len < IGB_RXBUFFER_1024)) + adapter->rx_buffer_len = IGB_RXBUFFER_1024; + /* adjust allocation if LPE protects us, and we aren't using SBP */ if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) || (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)) @@ -4462,8 +4560,6 @@ static void igb_vlan_rx_register(struct net_device *netdev, rctl &= ~E1000_RCTL_CFIEN; wr32(E1000_RCTL, rctl); igb_update_mng_vlan(adapter); - wr32(E1000_RLPML, - adapter->max_frame_size + VLAN_TAG_SIZE); } else { /* disable VLAN tag insert/strip */ ctrl = rd32(E1000_CTRL); @@ -4474,10 +4570,10 @@ static void igb_vlan_rx_register(struct net_device *netdev, igb_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); adapter->mng_vlan_id = IGB_MNG_VLAN_NONE; } - wr32(E1000_RLPML, - adapter->max_frame_size); } + igb_rlpml_set(adapter); + if (!test_bit(__IGB_DOWN, &adapter->state)) igb_irq_enable(adapter); } @@ -4841,4 +4937,52 @@ static void igb_io_resume(struct pci_dev *pdev) igb_get_hw_control(adapter); } +static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn) +{ + u32 reg_data; + + reg_data = rd32(E1000_VMOLR(vfn)); + reg_data |= E1000_VMOLR_BAM | /* Accept broadcast */ + E1000_VMOLR_ROPE | /* Accept packets matched in UTA */ + E1000_VMOLR_ROMPE | /* Accept packets matched in MTA */ + E1000_VMOLR_AUPE | /* Accept untagged packets */ + E1000_VMOLR_STRVLAN; /* Strip vlan tags */ + wr32(E1000_VMOLR(vfn), reg_data); +} + +static inline void igb_set_vf_rlpml(struct igb_adapter *adapter, int size, + int vfn) +{ + struct e1000_hw *hw = &adapter->hw; + u32 vmolr; + + vmolr = rd32(E1000_VMOLR(vfn)); + vmolr &= ~E1000_VMOLR_RLPML_MASK; + vmolr |= size | E1000_VMOLR_LPE; + wr32(E1000_VMOLR(vfn), vmolr); +} + +static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry) +{ + u32 reg_data; + + reg_data = rd32(E1000_RAH(entry)); + reg_data &= ~E1000_RAH_POOL_MASK; + reg_data |= E1000_RAH_POOL_1 << pool;; + wr32(E1000_RAH(entry), reg_data); +} + +static void igb_set_mc_list_pools(struct igb_adapter *adapter, + int entry_count, u16 total_rar_filters) +{ + struct e1000_hw *hw = &adapter->hw; + int i = adapter->vfs_allocated_count + 1; + + if ((i + entry_count) < total_rar_filters) + total_rar_filters = i + entry_count; + + for (; i < total_rar_filters; i++) + igb_set_rah_pool(hw, adapter->vfs_allocated_count, i); +} + /* igb_main.c */ -- cgit v1.2.3-59-g8ed1b From 4ae196dfd61d06b061c069edcdd7c73121e60a21 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Feb 2009 20:40:07 -0800 Subject: igb: Add support for enabling VFs to PF driver. This patch adds the support to handle requests from the VF to perform operations such as completing resets, setting/reading mac address, adding vlans, adding multicast addresses, setting rlpml, and general communications between the PF and all VFs. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/Makefile | 2 +- drivers/net/igb/e1000_82575.c | 42 ++++ drivers/net/igb/e1000_82575.h | 17 ++ drivers/net/igb/e1000_defines.h | 9 + drivers/net/igb/e1000_hw.h | 31 ++- drivers/net/igb/e1000_mac.c | 24 +++ drivers/net/igb/e1000_mac.h | 1 + drivers/net/igb/e1000_mbx.c | 447 ++++++++++++++++++++++++++++++++++++++++ drivers/net/igb/e1000_mbx.h | 77 +++++++ drivers/net/igb/e1000_regs.h | 12 ++ drivers/net/igb/igb.h | 12 ++ drivers/net/igb/igb_main.c | 429 +++++++++++++++++++++++++++++++++++--- 12 files changed, 1077 insertions(+), 26 deletions(-) create mode 100644 drivers/net/igb/e1000_mbx.c create mode 100644 drivers/net/igb/e1000_mbx.h (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/Makefile b/drivers/net/igb/Makefile index cda3ad51bafa..8372cb9a8c1a 100644 --- a/drivers/net/igb/Makefile +++ b/drivers/net/igb/Makefile @@ -33,5 +33,5 @@ obj-$(CONFIG_IGB) += igb.o igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \ - e1000_mac.o e1000_nvm.o e1000_phy.o + e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 7f43e253c566..ea63a215c909 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -213,6 +213,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) return -E1000_ERR_PHY; } + /* if 82576 then initialize mailbox parameters */ + if (mac->type == e1000_82576) + igb_init_mbx_params_pf(hw); + return 0; } @@ -1413,6 +1417,44 @@ void igb_rx_fifo_flush_82575(struct e1000_hw *hw) rd32(E1000_MPC); } +/** + * igb_vmdq_set_loopback_pf - enable or disable vmdq loopback + * @hw: pointer to the hardware struct + * @enable: state to enter, either enabled or disabled + * + * enables/disables L2 switch loopback functionality. + **/ +void igb_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) +{ + u32 dtxswc = rd32(E1000_DTXSWC); + + if (enable) + dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; + else + dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; + + wr32(E1000_DTXSWC, dtxswc); +} + +/** + * igb_vmdq_set_replication_pf - enable or disable vmdq replication + * @hw: pointer to the hardware struct + * @enable: state to enter, either enabled or disabled + * + * enables/disables replication of packets across multiple pools. + **/ +void igb_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) +{ + u32 vt_ctl = rd32(E1000_VT_CTL); + + if (enable) + vt_ctl |= E1000_VT_CTL_VM_REPL_EN; + else + vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; + + wr32(E1000_VT_CTL, vt_ctl); +} + static struct e1000_mac_operations e1000_mac_ops_82575 = { .reset_hw = igb_reset_hw_82575, .init_hw = igb_init_hw_82575, diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index 116714f346bb..eaf977050368 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -162,6 +162,10 @@ struct e1000_adv_tx_context_desc { #define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */ #define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */ +#define MAX_NUM_VFS 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 */ #define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7 #define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT) @@ -181,8 +185,21 @@ struct e1000_adv_tx_context_desc { #define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */ #define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */ #define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ +#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */ + +#define E1000_VLVF_ARRAY_SIZE 32 +#define E1000_VLVF_VLANID_MASK 0x00000FFF +#define E1000_VLVF_POOLSEL_SHIFT 12 +#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT) +#define E1000_VLVF_LVLAN 0x00100000 +#define E1000_VLVF_VLANID_ENABLE 0x80000000 + +#define E1000_IOVCTL 0x05BBC +#define E1000_IOVCTL_REUSE_VFQ 0x00000001 #define ALL_QUEUES 0xFFFF +void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool); +void igb_vmdq_set_replication_pf(struct e1000_hw *, bool); #endif diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index d7613db78000..62e378b64611 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -45,6 +45,8 @@ /* Extended Device Control */ #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ +/* Physical Func Reset Done Indication */ +#define E1000_CTRL_EXT_PFRSTD 0x00004000 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 @@ -325,6 +327,7 @@ #define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ #define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ #define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ +#define E1000_ICR_VMMB 0x00000100 /* VM MB event */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 /* LAN connected device generates an interrupt */ @@ -362,6 +365,7 @@ /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ #define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */ #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ @@ -413,6 +417,7 @@ #define E1000_BLK_PHY_RESET 12 #define E1000_ERR_SWFW_SYNC 13 #define E1000_NOT_IMPLEMENTED 14 +#define E1000_ERR_MBX 15 /* Loop limit on how long we wait for auto-negotiation to complete */ #define COPPER_LINK_UP_LIMIT 10 @@ -659,4 +664,8 @@ #define E1000_GEN_CTL_ADDRESS_SHIFT 8 #define E1000_GEN_POLL_TIMEOUT 640 +#define E1000_VFTA_ENTRY_SHIFT 5 +#define E1000_VFTA_ENTRY_MASK 0x7F +#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F + #endif diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 10b872d3c9f4..d793dca1eef6 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -32,7 +32,6 @@ #include #include -#include "e1000_mac.h" #include "e1000_regs.h" #include "e1000_defines.h" @@ -272,6 +271,7 @@ struct e1000_host_mng_command_info { #include "e1000_mac.h" #include "e1000_phy.h" #include "e1000_nvm.h" +#include "e1000_mbx.h" struct e1000_mac_operations { s32 (*check_for_link)(struct e1000_hw *); @@ -427,6 +427,34 @@ struct e1000_fc_info { enum e1000_fc_type original_type; }; +struct e1000_mbx_operations { + s32 (*init_params)(struct e1000_hw *hw); + s32 (*read)(struct e1000_hw *, u32 *, u16, u16); + s32 (*write)(struct e1000_hw *, u32 *, u16, u16); + s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16); + s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16); + s32 (*check_for_msg)(struct e1000_hw *, u16); + s32 (*check_for_ack)(struct e1000_hw *, u16); + s32 (*check_for_rst)(struct e1000_hw *, u16); +}; + +struct e1000_mbx_stats { + u32 msgs_tx; + u32 msgs_rx; + + u32 acks; + u32 reqs; + u32 rsts; +}; + +struct e1000_mbx_info { + struct e1000_mbx_operations ops; + struct e1000_mbx_stats stats; + u32 timeout; + u32 usec_delay; + u16 size; +}; + struct e1000_dev_spec_82575 { bool sgmii_active; }; @@ -443,6 +471,7 @@ struct e1000_hw { struct e1000_phy_info phy; struct e1000_nvm_info nvm; struct e1000_bus_info bus; + struct e1000_mbx_info mbx; struct e1000_host_mng_dhcp_cookie mng_cookie; union { diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 5c249e2ce93b..2804db03e9d9 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -117,6 +117,30 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) wrfl(); } +/** + * igb_vfta_set - enable or disable vlan in VLAN filter table + * @hw: pointer to the HW structure + * @vid: VLAN id to add or remove + * @add: if true add filter, if false remove + * + * Sets or clears a bit in the VLAN filter table array based on VLAN id + * and if we are adding or removing the filter + **/ +void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) +{ + u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; + u32 mask = 1 < (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); + u32 vfta; + + vfta = array_rd32(E1000_VFTA, index); + if (add) + vfta |= mask; + else + vfta &= ~mask; + + igb_write_vfta(hw, index, vfta); +} + /** * igb_check_alt_mac_addr - Check for alternate MAC addr * @hw: pointer to the HW structure diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index e5200def582f..eccc3536a568 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h @@ -58,6 +58,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, void igb_clear_hw_cntrs_base(struct e1000_hw *hw); void igb_clear_vfta(struct e1000_hw *hw); +void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); void igb_config_collision_dist(struct e1000_hw *hw); void igb_mta_set(struct e1000_hw *hw, u32 hash_value); void igb_put_hw_semaphore(struct e1000_hw *hw); diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c new file mode 100644 index 000000000000..fe71c7ddaa05 --- /dev/null +++ b/drivers/net/igb/e1000_mbx.c @@ -0,0 +1,447 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver + Copyright(c) 2007-2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "e1000_mbx.h" + +/** + * igb_read_mbx - Reads a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to read + * + * returns SUCCESS if it successfuly read message from buffer + **/ +s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + /* limit read to size of mailbox */ + if (size > mbx->size) + size = mbx->size; + + if (mbx->ops.read) + ret_val = mbx->ops.read(hw, msg, size, mbx_id); + + return ret_val; +} + +/** + * igb_write_mbx - Write a message to the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer + **/ +s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = 0; + + if (size > mbx->size) + ret_val = -E1000_ERR_MBX; + + else if (mbx->ops.write) + ret_val = mbx->ops.write(hw, msg, size, mbx_id); + + return ret_val; +} + +/** + * igb_check_for_msg - checks to see if someone sent us mail + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ +s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (mbx->ops.check_for_msg) + ret_val = mbx->ops.check_for_msg(hw, mbx_id); + + return ret_val; +} + +/** + * igb_check_for_ack - checks to see if someone sent us ACK + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ +s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (mbx->ops.check_for_ack) + ret_val = mbx->ops.check_for_ack(hw, mbx_id); + + return ret_val; +} + +/** + * igb_check_for_rst - checks to see if other side has reset + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ +s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (mbx->ops.check_for_rst) + ret_val = mbx->ops.check_for_rst(hw, mbx_id); + + return ret_val; +} + +/** + * igb_poll_for_msg - Wait for message notification + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message notification + **/ +static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!mbx->ops.check_for_msg) + goto out; + + while (mbx->ops.check_for_msg(hw, mbx_id)) { + if (!countdown) + break; + countdown--; + udelay(mbx->usec_delay); + } +out: + return countdown ? 0 : -E1000_ERR_MBX; +} + +/** + * igb_poll_for_ack - Wait for message acknowledgement + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message acknowledgement + **/ +static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!mbx->ops.check_for_ack) + goto out; + + while (mbx->ops.check_for_ack(hw, mbx_id)) { + if (!countdown) + break; + countdown--; + udelay(mbx->usec_delay); + } +out: + return countdown ? 0 : -E1000_ERR_MBX; +} + +/** + * igb_read_posted_mbx - Wait for message notification and receive message + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message notification and + * copied it into the receive buffer. + **/ +s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; + + if (!mbx->ops.read) + goto out; + + ret_val = igb_poll_for_msg(hw, mbx_id); + + if (!ret_val) + ret_val = mbx->ops.read(hw, msg, size, mbx_id); +out: + return ret_val; +} + +/** + * igb_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ +s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = 0; + + if (!mbx->ops.write) + goto out; + + /* send msg*/ + ret_val = mbx->ops.write(hw, msg, size, mbx_id); + + /* if msg sent wait until we receive an ack */ + if (!ret_val) + ret_val = igb_poll_for_ack(hw, mbx_id); +out: + return ret_val; +} + +/** + * e1000_init_mbx_ops_generic - Initialize NVM function pointers + * @hw: pointer to the HW structure + * + * Setups up the function pointers to no-op functions + **/ +void e1000_init_mbx_ops_generic(struct e1000_hw *hw) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + mbx->ops.read_posted = igb_read_posted_mbx; + mbx->ops.write_posted = igb_write_posted_mbx; +} + +static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask) +{ + u32 mbvficr = rd32(E1000_MBVFICR); + s32 ret_val = -E1000_ERR_MBX; + + if (mbvficr & mask) { + ret_val = 0; + wr32(E1000_MBVFICR, mask); + } + + return ret_val; +} + +/** + * igb_check_for_msg_pf - checks to see if the VF has sent mail + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ +static s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number) +{ + s32 ret_val = -E1000_ERR_MBX; + + if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) { + ret_val = 0; + hw->mbx.stats.reqs++; + } + + return ret_val; +} + +/** + * igb_check_for_ack_pf - checks to see if the VF has ACKed + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ +static s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number) +{ + s32 ret_val = -E1000_ERR_MBX; + + if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) { + ret_val = 0; + hw->mbx.stats.acks++; + } + + return ret_val; +} + +/** + * igb_check_for_rst_pf - checks to see if the VF has reset + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ +static s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number) +{ + u32 vflre = rd32(E1000_VFLRE); + s32 ret_val = -E1000_ERR_MBX; + + if (vflre & (1 << vf_number)) { + ret_val = 0; + wr32(E1000_VFLRE, (1 << vf_number)); + hw->mbx.stats.rsts++; + } + + return ret_val; +} + +/** + * igb_write_mbx_pf - Places a message in the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_number: the VF index + * + * returns SUCCESS if it successfully copied message into the buffer + **/ +static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, + u16 vf_number) +{ + u32 p2v_mailbox; + s32 ret_val = 0; + u16 i; + + /* Take ownership of the buffer */ + wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); + + /* Make sure we have ownership now... */ + p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); + if (!(p2v_mailbox & E1000_P2VMAILBOX_PFU)) { + /* failed to grab ownership */ + ret_val = -E1000_ERR_MBX; + goto out_no_write; + } + + /* + * flush any ack or msg which may already be in the queue + * as they are likely the result of an error + */ + igb_check_for_ack_pf(hw, vf_number); + igb_check_for_msg_pf(hw, vf_number); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + array_wr32(E1000_VMBMEM(vf_number), i, msg[i]); + + /* Interrupt VF to tell it a message has been sent and release buffer*/ + wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS); + + /* update stats */ + hw->mbx.stats.msgs_tx++; + +out_no_write: + return ret_val; + +} + +/** + * igb_read_mbx_pf - Read a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_number: the VF index + * + * This function copies a message from the mailbox buffer to the caller's + * memory buffer. The presumption is that the caller knows that there was + * a message due to a VF request so no polling for message is needed. + **/ +static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, + u16 vf_number) +{ + u32 p2v_mailbox; + s32 ret_val = 0; + u16 i; + + /* Take ownership of the buffer */ + wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); + + /* Make sure we have ownership now... */ + p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); + if (!(p2v_mailbox & E1000_P2VMAILBOX_PFU)) { + /* failed to grab ownership */ + ret_val = -E1000_ERR_MBX; + goto out_no_read; + } + + /* copy the message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = array_rd32(E1000_VMBMEM(vf_number), i); + + /* Acknowledge the message and release buffer */ + wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); + + /* update stats */ + hw->mbx.stats.msgs_rx++; + + ret_val = 0; + +out_no_read: + return ret_val; +} + +/** + * e1000_init_mbx_params_pf - set initial values for pf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for pf mailbox + */ +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; + } + + return 0; +} + diff --git a/drivers/net/igb/e1000_mbx.h b/drivers/net/igb/e1000_mbx.h new file mode 100644 index 000000000000..6ec9890a8f7a --- /dev/null +++ b/drivers/net/igb/e1000_mbx.h @@ -0,0 +1,77 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver + Copyright(c) 2007-2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _E1000_MBX_H_ +#define _E1000_MBX_H_ + +#include "e1000_hw.h" + +#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */ +#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ +#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ +#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ +#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ + +#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */ +#define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ +#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */ +#define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ + +#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ + +/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the + * PF. The reverse is true if it is E1000_PF_*. + * Message ACK's are the value or'd with 0xF0000000 + */ +#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with + * this are the ACK */ +#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with + * this are the NACK */ +#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still + clear to send requests */ +#define E1000_VT_MSGINFO_SHIFT 16 +/* bits 23:16 are used for exra info for certain messages */ +#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT) + +#define E1000_VF_RESET 0x01 /* VF requests reset */ +#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */ +#define E1000_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ +#define E1000_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ +#define E1000_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ + +#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */ + +s32 igb_read_mbx(struct e1000_hw *, u32 *, u16, u16); +s32 igb_write_mbx(struct e1000_hw *, u32 *, u16, u16); +s32 igb_read_posted_mbx(struct e1000_hw *, u32 *, u16, u16); +s32 igb_write_posted_mbx(struct e1000_hw *, u32 *, u16, u16); +s32 igb_check_for_msg(struct e1000_hw *, u16); +s32 igb_check_for_ack(struct e1000_hw *, u16); +s32 igb_check_for_rst(struct e1000_hw *, u16); +s32 igb_init_mbx_params_pf(struct e1000_hw *); + +#endif /* _E1000_MBX_H_ */ diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 5d00c864d106..0bd7728fe469 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -321,9 +321,21 @@ enum { #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */ /* VT Registers */ +#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */ +#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */ +#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */ +#define E1000_VFRE 0x00C8C /* VF Receive Enables */ +#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_RPLOLR 0x05AF0 /* Replication Offload - RW */ +#define E1000_IOVTCL 0x05BBC /* IOV Control Register */ /* These act per VF so an array friendly macro is used */ +#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n))) +#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n))) #define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) +#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine + * Filter - RW */ #define wr32(reg, value) (writel(value, hw->hw_addr + reg)) #define rd32(reg) (readl(hw->hw_addr + reg)) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index d925f7dd7fb2..e18ac1bf45ff 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -62,6 +62,17 @@ struct igb_adapter; #define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES #define IGB_ABS_MAX_TX_QUEUES 4 +#define IGB_MAX_VF_MC_ENTRIES 30 +#define IGB_MAX_VF_FUNCTIONS 8 +#define IGB_MAX_VFTA_ENTRIES 128 + +struct vf_data_storage { + unsigned char vf_mac_addresses[ETH_ALEN]; + u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES]; + u16 num_vf_mc_hashes; + bool clear_to_send; +}; + /* RX descriptor control thresholds. * PTHRESH - MAC will consider prefetch if it has fewer than this number of * descriptors available in its onboard memory. @@ -272,6 +283,7 @@ struct igb_adapter { unsigned int tx_ring_count; unsigned int rx_ring_count; unsigned int vfs_allocated_count; + struct vf_data_storage *vf_data; }; #define IGB_FLAG_HAS_MSI (1 << 0) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index c7c7eeba3366..b9e7980e3f47 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -122,10 +122,16 @@ static void igb_vlan_rx_register(struct net_device *, struct vlan_group *); static void igb_vlan_rx_add_vid(struct net_device *, u16); static void igb_vlan_rx_kill_vid(struct net_device *, u16); static void igb_restore_vlan(struct igb_adapter *); +static void igb_ping_all_vfs(struct igb_adapter *); +static void igb_msg_task(struct igb_adapter *); +static int igb_rcv_msg_from_vf(struct igb_adapter *, u32); static inline void igb_set_rah_pool(struct e1000_hw *, int , int); static void igb_set_mc_list_pools(struct igb_adapter *, int, u16); +static void igb_vmm_control(struct igb_adapter *); static inline void igb_set_vmolr(struct e1000_hw *, int); -static inline void igb_set_vf_rlpml(struct igb_adapter *, int, int); +static inline int igb_set_vf_rlpml(struct igb_adapter *, int, int); +static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *); +static void igb_restore_vf_multicasts(struct igb_adapter *adapter); static int igb_suspend(struct pci_dev *, pm_message_t); #ifdef CONFIG_PM @@ -768,7 +774,10 @@ static void igb_irq_enable(struct igb_adapter *adapter) wr32(E1000_EIAC, adapter->eims_enable_mask); wr32(E1000_EIAM, adapter->eims_enable_mask); wr32(E1000_EIMS, adapter->eims_enable_mask); - wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); + if (adapter->vfs_allocated_count) + wr32(E1000_MBVFIMR, 0xFF); + wr32(E1000_IMS, (E1000_IMS_LSC | E1000_IMS_VMMB | + E1000_IMS_DOUTSYNC)); } else { wr32(E1000_IMS, IMS_ENABLE_MASK); wr32(E1000_IAM, IMS_ENABLE_MASK); @@ -892,6 +901,7 @@ int igb_up(struct igb_adapter *adapter) if (adapter->msix_entries) igb_configure_msix(adapter); + igb_vmm_control(adapter); igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); igb_set_vmolr(hw, adapter->vfs_allocated_count); @@ -1047,6 +1057,20 @@ void igb_reset(struct igb_adapter *adapter) fc->send_xon = 1; fc->type = fc->original_type; + /* disable receive for all VFs and wait one second */ + if (adapter->vfs_allocated_count) { + int i; + for (i = 0 ; i < adapter->vfs_allocated_count; i++) + adapter->vf_data[i].clear_to_send = false; + + /* ping all the active vfs to let them know we are going down */ + igb_ping_all_vfs(adapter); + + /* disable transmits and receives */ + wr32(E1000_VFRE, 0); + wr32(E1000_VFTE, 0); + } + /* Allow time for pending master requests to run */ adapter->hw.mac.ops.reset_hw(&adapter->hw); wr32(E1000_WUC, 0); @@ -1624,6 +1648,7 @@ static int igb_open(struct net_device *netdev) * clean_rx handler before we do so. */ igb_configure(adapter); + igb_vmm_control(adapter); igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); igb_set_vmolr(hw, adapter->vfs_allocated_count); @@ -2456,6 +2481,8 @@ static void igb_set_multi(struct net_device *netdev) mac->rar_entry_count); igb_set_mc_list_pools(adapter, i, mac->rar_entry_count); + igb_restore_vf_multicasts(adapter); + kfree(mta_list); } @@ -2571,6 +2598,8 @@ static void igb_watchdog_task(struct work_struct *work) netif_carrier_on(netdev); netif_tx_wake_all_queues(netdev); + igb_ping_all_vfs(adapter); + /* link state has changed, schedule phy info update */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, @@ -2586,6 +2615,8 @@ static void igb_watchdog_task(struct work_struct *work) netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); + igb_ping_all_vfs(adapter); + /* link state has changed, schedule phy info update */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, @@ -3523,15 +3554,19 @@ static irqreturn_t igb_msix_other(int irq, void *data) /* HW is reporting DMA is out of sync */ adapter->stats.doosync++; } - if (!(icr & E1000_ICR_LSC)) - goto no_link_interrupt; - hw->mac.get_link_status = 1; - /* guard against interrupt when we're going down */ - if (!test_bit(__IGB_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies + 1); -no_link_interrupt: - wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); + /* Check for a mailbox event */ + if (icr & E1000_ICR_VMMB) + igb_msg_task(adapter); + + if (icr & E1000_ICR_LSC) { + hw->mac.get_link_status = 1; + /* guard against interrupt when we're going down */ + if (!test_bit(__IGB_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + + wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC | E1000_IMS_VMMB); wr32(E1000_EIMS, adapter->eims_other); return IRQ_HANDLED; @@ -3719,6 +3754,317 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event, } #endif /* CONFIG_IGB_DCA */ +static void igb_ping_all_vfs(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ping; + int i; + + for (i = 0 ; i < adapter->vfs_allocated_count; i++) { + ping = E1000_PF_CONTROL_MSG; + if (adapter->vf_data[i].clear_to_send) + ping |= E1000_VT_MSGTYPE_CTS; + igb_write_mbx(hw, &ping, 1, i); + } +} + +static int igb_set_vf_multicasts(struct igb_adapter *adapter, + u32 *msgbuf, u32 vf) +{ + int n = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; + u16 *hash_list = (u16 *)&msgbuf[1]; + struct vf_data_storage *vf_data = &adapter->vf_data[vf]; + int i; + + /* only up to 30 hash values supported */ + if (n > 30) + n = 30; + + /* salt away the number of multi cast addresses assigned + * to this VF for later use to restore when the PF multi cast + * list changes + */ + vf_data->num_vf_mc_hashes = n; + + /* VFs are limited to using the MTA hash table for their multicast + * addresses */ + for (i = 0; i < n; i++) + vf_data->vf_mc_hashes[i] = hash_list[i];; + + /* Flush and reset the mta with the new values */ + igb_set_multi(adapter->netdev); + + return 0; +} + +static void igb_restore_vf_multicasts(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct vf_data_storage *vf_data; + int i, j; + + for (i = 0; i < adapter->vfs_allocated_count; i++) { + vf_data = &adapter->vf_data[i]; + for (j = 0; j < vf_data[i].num_vf_mc_hashes; j++) + igb_mta_set(hw, vf_data->vf_mc_hashes[j]); + } +} + +static void igb_clear_vf_vfta(struct igb_adapter *adapter, u32 vf) +{ + struct e1000_hw *hw = &adapter->hw; + u32 pool_mask, reg, vid; + int i; + + pool_mask = 1 << (E1000_VLVF_POOLSEL_SHIFT + vf); + + /* Find the vlan filter for this id */ + for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { + reg = rd32(E1000_VLVF(i)); + + /* remove the vf from the pool */ + reg &= ~pool_mask; + + /* if pool is empty then remove entry from vfta */ + if (!(reg & E1000_VLVF_POOLSEL_MASK) && + (reg & E1000_VLVF_VLANID_ENABLE)) { + reg = 0; + vid = reg & E1000_VLVF_VLANID_MASK; + igb_vfta_set(hw, vid, false); + } + + wr32(E1000_VLVF(i), reg); + } +} + +static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) +{ + struct e1000_hw *hw = &adapter->hw; + u32 reg, i; + + /* It is an error to call this function when VFs are not enabled */ + if (!adapter->vfs_allocated_count) + return -1; + + /* Find the vlan filter for this id */ + for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { + reg = rd32(E1000_VLVF(i)); + if ((reg & E1000_VLVF_VLANID_ENABLE) && + vid == (reg & E1000_VLVF_VLANID_MASK)) + break; + } + + if (add) { + if (i == E1000_VLVF_ARRAY_SIZE) { + /* Did not find a matching VLAN ID entry that was + * enabled. Search for a free filter entry, i.e. + * one without the enable bit set + */ + for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { + reg = rd32(E1000_VLVF(i)); + if (!(reg & E1000_VLVF_VLANID_ENABLE)) + break; + } + } + if (i < E1000_VLVF_ARRAY_SIZE) { + /* Found an enabled/available entry */ + reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT + vf); + + /* if !enabled we need to set this up in vfta */ + if (!(reg & E1000_VLVF_VLANID_ENABLE)) { + /* add VID to filter table */ + igb_vfta_set(hw, vid, true); + reg |= E1000_VLVF_VLANID_ENABLE; + } + + wr32(E1000_VLVF(i), reg); + return 0; + } + } else { + if (i < E1000_VLVF_ARRAY_SIZE) { + /* remove vf from the pool */ + reg &= ~(1 << (E1000_VLVF_POOLSEL_SHIFT + vf)); + /* if pool is empty then remove entry from vfta */ + if (!(reg & E1000_VLVF_POOLSEL_MASK)) { + reg = 0; + igb_vfta_set(hw, vid, false); + } + wr32(E1000_VLVF(i), reg); + return 0; + } + } + return -1; +} + +static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) +{ + int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; + int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); + + return igb_vlvf_set(adapter, vid, add, vf); +} + +static inline void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) +{ + struct e1000_hw *hw = &adapter->hw; + + /* disable mailbox functionality for vf */ + adapter->vf_data[vf].clear_to_send = false; + + /* reset offloads to defaults */ + igb_set_vmolr(hw, vf); + + /* reset vlans for device */ + igb_clear_vf_vfta(adapter, vf); + + /* reset multicast table array for vf */ + adapter->vf_data[vf].num_vf_mc_hashes = 0; + + /* Flush and reset the mta with the new values */ + igb_set_multi(adapter->netdev); +} + +static inline void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) +{ + struct e1000_hw *hw = &adapter->hw; + unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; + u32 reg, msgbuf[3]; + u8 *addr = (u8 *)(&msgbuf[1]); + + /* process all the same items cleared in a function level reset */ + igb_vf_reset_event(adapter, vf); + + /* set vf mac address */ + igb_rar_set(hw, vf_mac, vf + 1); + igb_set_rah_pool(hw, vf, vf + 1); + + /* enable transmit and receive for vf */ + reg = rd32(E1000_VFTE); + wr32(E1000_VFTE, reg | (1 << vf)); + reg = rd32(E1000_VFRE); + wr32(E1000_VFRE, reg | (1 << vf)); + + /* enable mailbox functionality for vf */ + adapter->vf_data[vf].clear_to_send = true; + + /* reply to reset with ack and vf mac address */ + msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; + memcpy(addr, vf_mac, 6); + igb_write_mbx(hw, msgbuf, 3, vf); +} + +static int igb_set_vf_mac_addr(struct igb_adapter *adapter, u32 *msg, int vf) +{ + unsigned char *addr = (char *)&msg[1]; + int err = -1; + + if (is_valid_ether_addr(addr)) + err = igb_set_vf_mac(adapter, vf, addr); + + return err; + +} + +static void igb_rcv_ack_from_vf(struct igb_adapter *adapter, u32 vf) +{ + struct e1000_hw *hw = &adapter->hw; + u32 msg = E1000_VT_MSGTYPE_NACK; + + /* if device isn't clear to send it shouldn't be reading either */ + if (!adapter->vf_data[vf].clear_to_send) + igb_write_mbx(hw, &msg, 1, vf); +} + + +static void igb_msg_task(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 vf; + + for (vf = 0; vf < adapter->vfs_allocated_count; vf++) { + /* process any reset requests */ + if (!igb_check_for_rst(hw, vf)) { + adapter->vf_data[vf].clear_to_send = false; + igb_vf_reset_event(adapter, vf); + } + + /* process any messages pending */ + if (!igb_check_for_msg(hw, vf)) + igb_rcv_msg_from_vf(adapter, vf); + + /* process any acks */ + if (!igb_check_for_ack(hw, vf)) + igb_rcv_ack_from_vf(adapter, vf); + + } +} + +static int igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) +{ + u32 mbx_size = E1000_VFMAILBOX_SIZE; + u32 msgbuf[mbx_size]; + struct e1000_hw *hw = &adapter->hw; + s32 retval; + + retval = igb_read_mbx(hw, msgbuf, mbx_size, vf); + + if (retval) + dev_err(&adapter->pdev->dev, + "Error receiving message from VF\n"); + + /* this is a message we already processed, do nothing */ + if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) + return retval; + + /* + * until the vf completes a reset it should not be + * allowed to start any configuration. + */ + + if (msgbuf[0] == E1000_VF_RESET) { + igb_vf_reset_msg(adapter, vf); + + return retval; + } + + if (!adapter->vf_data[vf].clear_to_send) { + msgbuf[0] |= E1000_VT_MSGTYPE_NACK; + igb_write_mbx(hw, msgbuf, 1, vf); + return retval; + } + + switch ((msgbuf[0] & 0xFFFF)) { + case E1000_VF_SET_MAC_ADDR: + retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); + break; + case E1000_VF_SET_MULTICAST: + retval = igb_set_vf_multicasts(adapter, msgbuf, vf); + break; + case E1000_VF_SET_LPE: + retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); + break; + case E1000_VF_SET_VLAN: + retval = igb_set_vf_vlan(adapter, msgbuf, vf); + break; + default: + dev_err(&adapter->pdev->dev, "Unhandled Msg %08x\n", msgbuf[0]); + retval = -1; + break; + } + + /* notify the VF of the results of what it sent us */ + if (retval) + msgbuf[0] |= E1000_VT_MSGTYPE_NACK; + else + msgbuf[0] |= E1000_VT_MSGTYPE_ACK; + + msgbuf[0] |= E1000_VT_MSGTYPE_CTS; + + igb_write_mbx(hw, msgbuf, 1, vf); + + return retval; +} + /** * igb_intr_msi - Interrupt Handler * @irq: interrupt number @@ -4582,24 +4928,25 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; + int pf_id = adapter->vfs_allocated_count; if ((hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && (vid == adapter->mng_vlan_id)) return; - /* add VID to filter table */ - index = (vid >> 5) & 0x7F; - vfta = array_rd32(E1000_VFTA, index); - vfta |= (1 << (vid & 0x1F)); - igb_write_vfta(&adapter->hw, index, vfta); + + /* add vid to vlvf if sr-iov is enabled, + * if that fails add directly to filter table */ + if (igb_vlvf_set(adapter, vid, true, pf_id)) + igb_vfta_set(hw, vid, true); + } static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; + int pf_id = adapter->vfs_allocated_count; igb_irq_disable(adapter); vlan_group_set_device(adapter->vlgrp, vid, NULL); @@ -4615,11 +4962,10 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) return; } - /* remove VID from filter table */ - index = (vid >> 5) & 0x7F; - vfta = array_rd32(E1000_VFTA, index); - vfta &= ~(1 << (vid & 0x1F)); - igb_write_vfta(&adapter->hw, index, vfta); + /* remove vid from vlvf if sr-iov is enabled, + * if not in vlvf remove from vfta */ + if (igb_vlvf_set(adapter, vid, false, pf_id)) + igb_vfta_set(hw, vid, false); } static void igb_restore_vlan(struct igb_adapter *adapter) @@ -4950,8 +5296,8 @@ static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn) wr32(E1000_VMOLR(vfn), reg_data); } -static inline void igb_set_vf_rlpml(struct igb_adapter *adapter, int size, - int vfn) +static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, + int vfn) { struct e1000_hw *hw = &adapter->hw; u32 vmolr; @@ -4960,6 +5306,8 @@ static inline void igb_set_vf_rlpml(struct igb_adapter *adapter, int size, vmolr &= ~E1000_VMOLR_RLPML_MASK; vmolr |= size | E1000_VMOLR_LPE; wr32(E1000_VMOLR(vfn), vmolr); + + return 0; } static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry) @@ -4985,4 +5333,37 @@ static void igb_set_mc_list_pools(struct igb_adapter *adapter, igb_set_rah_pool(hw, adapter->vfs_allocated_count, i); } +static int igb_set_vf_mac(struct igb_adapter *adapter, + int vf, unsigned char *mac_addr) +{ + struct e1000_hw *hw = &adapter->hw; + int rar_entry = vf + 1; /* VF MAC addresses start at entry 1 */ + + igb_rar_set(hw, mac_addr, rar_entry); + + memcpy(adapter->vf_data[vf].vf_mac_addresses, mac_addr, 6); + + igb_set_rah_pool(hw, vf, rar_entry); + + return 0; +} + +static void igb_vmm_control(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 reg_data; + + if (!adapter->vfs_allocated_count) + return; + + /* VF's need PF reset indication before they + * can send/receive mail */ + reg_data = rd32(E1000_CTRL_EXT); + reg_data |= E1000_CTRL_EXT_PFRSTD; + wr32(E1000_CTRL_EXT, reg_data); + + igb_vmdq_set_loopback_pf(hw, true); + igb_vmdq_set_replication_pf(hw, true); +} + /* igb_main.c */ -- cgit v1.2.3-59-g8ed1b From c493ea45a4251869fe7b820e0486b73b57df7c12 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 20 Mar 2009 00:16:50 +0000 Subject: igb: remove IGB_DESC_UNUSED since it is better handled by a function call This patch removes IGB_DESC_UNUSED and replaces it with a function call instead in order to cleanup some of the ugliness introduced by the macro. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 4 ---- drivers/net/igb/igb_main.c | 25 ++++++++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers/net/igb/igb.h') diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index e18ac1bf45ff..4e8464b9df2e 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -182,10 +182,6 @@ struct igb_ring { char name[IFNAMSIZ + 5]; }; -#define IGB_DESC_UNUSED(R) \ - ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ - (R)->next_to_clean - (R)->next_to_use - 1) - #define E1000_RX_DESC_ADV(R, i) \ (&(((union e1000_adv_rx_desc *)((R).desc))[i])) #define E1000_TX_DESC_ADV(R, i) \ diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 39ac375487d6..3fd2efa91cb2 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -277,6 +277,17 @@ static char *igb_get_time_str(struct igb_adapter *adapter, } #endif +/** + * igb_desc_unused - calculate if we have unused descriptors + **/ +static int igb_desc_unused(struct igb_ring *ring) +{ + if (ring->next_to_clean > ring->next_to_use) + return ring->next_to_clean - ring->next_to_use - 1; + + return ring->count + ring->next_to_clean - ring->next_to_use - 1; +} + /** * igb_init_module - Driver Registration Routine * @@ -873,12 +884,12 @@ static void igb_configure(struct igb_adapter *adapter) igb_rx_fifo_flush_82575(&adapter->hw); - /* call IGB_DESC_UNUSED which always leaves + /* call igb_desc_unused which always leaves * at least 1 descriptor unused to make sure * next_to_use != next_to_clean */ for (i = 0; i < adapter->num_rx_queues; i++) { struct igb_ring *ring = &adapter->rx_ring[i]; - igb_alloc_rx_buffers_adv(ring, IGB_DESC_UNUSED(ring)); + igb_alloc_rx_buffers_adv(ring, igb_desc_unused(ring)); } @@ -2661,7 +2672,7 @@ link_up: igb_update_adaptive(&adapter->hw); if (!netif_carrier_ok(netdev)) { - if (IGB_DESC_UNUSED(tx_ring) + 1 < tx_ring->count) { + if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { /* We've lost link, so the controller stops DMA, * but we've got queued Tx work that's never going * to get done, so reset controller to flush Tx. @@ -3199,7 +3210,7 @@ static int __igb_maybe_stop_tx(struct net_device *netdev, /* We need to check again in a case another CPU has just * made room available. */ - if (IGB_DESC_UNUSED(tx_ring) < size) + if (igb_desc_unused(tx_ring) < size) return -EBUSY; /* A reprieve! */ @@ -3211,7 +3222,7 @@ static int __igb_maybe_stop_tx(struct net_device *netdev, static int igb_maybe_stop_tx(struct net_device *netdev, struct igb_ring *tx_ring, int size) { - if (IGB_DESC_UNUSED(tx_ring) >= size) + if (igb_desc_unused(tx_ring) >= size) return 0; return __igb_maybe_stop_tx(netdev, tx_ring, size); } @@ -4310,7 +4321,7 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring) if (unlikely(count && netif_carrier_ok(netdev) && - IGB_DESC_UNUSED(tx_ring) >= IGB_TX_QUEUE_WAKE)) { + igb_desc_unused(tx_ring) >= IGB_TX_QUEUE_WAKE)) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean. */ @@ -4587,7 +4598,7 @@ next_desc: } rx_ring->next_to_clean = i; - cleaned_count = IGB_DESC_UNUSED(rx_ring); + cleaned_count = igb_desc_unused(rx_ring); if (cleaned_count) igb_alloc_rx_buffers_adv(rx_ring, cleaned_count); -- cgit v1.2.3-59-g8ed1b