From 96066c1d4cbbd7b5fd2ba16153ec529537bca244 Mon Sep 17 00:00:00 2001 From: intel-ethernet Date: Mon, 5 Nov 2012 16:34:41 -0800 Subject: [PATCH] Merge with version 4.0.17 of standard igb driver --- kmod/igb/Makefile | 13 +- kmod/igb/e1000_82575.c | 288 ++++++++--------------- kmod/igb/e1000_api.c | 95 +------- kmod/igb/e1000_api.h | 23 +- kmod/igb/e1000_defines.h | 33 ++- kmod/igb/e1000_hw.h | 42 +--- kmod/igb/e1000_i210.c | 161 ++++++++++++- kmod/igb/e1000_i210.h | 16 ++ kmod/igb/e1000_mac.c | 153 ++++++++++++- kmod/igb/e1000_mac.h | 2 +- kmod/igb/e1000_manage.c | 8 +- kmod/igb/e1000_nvm.c | 456 ++++++------------------------------- kmod/igb/e1000_nvm.h | 38 ++-- kmod/igb/e1000_osdep.h | 9 + kmod/igb/e1000_phy.c | 47 +++- kmod/igb/e1000_phy.h | 6 +- kmod/igb/e1000_regs.h | 29 ++- kmod/igb/igb.h | 81 +++---- kmod/igb/igb_ethtool.c | 290 ++++++++++++++---------- kmod/igb/igb_main.c | 577 +++++++++++++++++++---------------------------- kmod/igb/igb_param.c | 143 ++++++------ kmod/igb/igb_procfs.c | 17 +- kmod/igb/igb_ptp.c | 164 +++++++++----- kmod/igb/igb_regtest.h | 2 +- kmod/igb/igb_sysfs.c | 26 +-- kmod/igb/kcompat.c | 68 +++++- kmod/igb/kcompat.h | 228 +++++++++++++++++-- 27 files changed, 1532 insertions(+), 1483 deletions(-) diff --git a/kmod/igb/Makefile b/kmod/igb/Makefile index 1de8e48..3c6703f 100644 --- a/kmod/igb/Makefile +++ b/kmod/igb/Makefile @@ -27,17 +27,16 @@ ########################################################################### # Driver files -FAMILYC = e1000_82575.c -FAMILYH = e1000_82575.h +FAMILYC = e1000_82575.c e1000_i210.c +FAMILYH = e1000_82575.h e1000_i210.h # core driver files CFILES = igb_main.c $(FAMILYC) e1000_mac.c e1000_nvm.c e1000_phy.c \ e1000_manage.c igb_param.c igb_ethtool.c kcompat.c e1000_api.c \ - e1000_mbx.c igb_vmdq.c e1000_i210.c igb_sysfs.c igb_procfs.c \ - igb_ptp.c + e1000_mbx.c igb_vmdq.c igb_sysfs.c igb_procfs.c igb_ptp.c HFILES = igb.h e1000_hw.h e1000_osdep.h e1000_defines.h e1000_mac.h \ e1000_nvm.h e1000_manage.h $(FAMILYH) kcompat.h e1000_regs.h \ - e1000_api.h igb_regtest.h e1000_mbx.h igb_vmdq.h e1000_i210.h + e1000_api.h igb_regtest.h e1000_mbx.h igb_vmdq.h ifeq (,$(BUILD_KERNEL)) BUILD_KERNEL=$(shell uname -r) endif @@ -247,7 +246,7 @@ else endif endif -else # ifeq ($(K_VERSION),2.6) +else # ifeq (1,$(shell [ $(KVER_CODE) -ge 132352 ] && echo 1 || echo 0)) # Makefile for 2.4.x kernel TARGET = $(DRIVER_NAME).o @@ -284,7 +283,7 @@ $(CFILES:.c=.o): $(HFILES) Makefile default: $(MAKE) -endif # ifeq ($(K_VERSION),2.6) +endif # ifeq (1,$(shell [ $(KVER_CODE) -ge 132352 ] && echo 1 || echo 0)) ifeq (,$(MANDIR)) # find the best place to install the man page diff --git a/kmod/igb/e1000_82575.c b/kmod/igb/e1000_82575.c index e9cd462..cbb4bab 100644 --- a/kmod/igb/e1000_82575.c +++ b/kmod/igb/e1000_82575.c @@ -31,6 +31,8 @@ * 82575GB Gigabit Network Connection * 82576 Gigabit Network Connection * 82576 Quad Port Gigabit Mezzanine Adapter + * 82580 Gigabit Network Connection + * I350 Gigabit Network Connection */ #include "e1000_api.h" @@ -51,14 +53,6 @@ static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw); static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data); static s32 e1000_reset_hw_82575(struct e1000_hw *hw); -static s32 e1000_get_protected_blocks_82576(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 *blocks_size, u32 block_type_mask, - u16 *eeprom_buffer, u32 eeprom_size); -static s32 e1000_get_protected_blocks_82580(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 *blocks_size, u32 block_type_mask, - u16 *eeprom_buffer, u32 eeprom_size); static s32 e1000_reset_hw_82580(struct e1000_hw *hw); static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data); @@ -218,11 +212,11 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) } } + /* Set phy->phy_addr and phy->id. */ ret_val = e1000_get_phy_id_82575(hw); /* Verify phy id and set remaining function pointers */ switch (phy->id) { - case M88E1145_E_PHY_ID: case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: @@ -343,19 +337,6 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) nvm->ops.validate = e1000_validate_nvm_checksum_generic; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_82575; - switch (hw->mac.type) { - case e1000_82576: - nvm->ops.get_protected_blocks = - e1000_get_protected_blocks_82576; - break; - case e1000_82580: - case e1000_i350: - nvm->ops.get_protected_blocks = - e1000_get_protected_blocks_82580; - break; - default: - break; - } /* override generic family function pointers for specific descendants */ switch (hw->mac.type) { @@ -434,15 +415,13 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575; /* check for link */ mac->ops.check_for_link = e1000_check_for_link_82575; - /* receive address register setting */ - mac->ops.rar_set = e1000_rar_set_generic; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82575; /* configure collision distance */ mac->ops.config_collision_dist = e1000_config_collision_dist_82575; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; - if (hw->mac.type == e1000_i350) { + if (mac->type == e1000_i350) { /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_i350; /* clearing VFTA */ @@ -453,6 +432,9 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; } + if (hw->mac.type >= e1000_82580) + mac->ops.validate_mdi_setting = + e1000_validate_mdi_setting_crossover_generic; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* blink LED */ @@ -849,7 +831,7 @@ static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; - u16 data; + u32 data; DEBUGFUNC("e1000_set_d0_lplu_state_82580"); @@ -897,7 +879,7 @@ s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; - u16 data; + u32 data; DEBUGFUNC("e1000_set_d3_lplu_state_82580"); @@ -1105,7 +1087,7 @@ static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) DEBUGOUT("MNG configuration cycle has not completed.\n"); /* If EEPROM is not marked present, init the PHY manually */ - if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && (hw->phy.type == e1000_phy_igp_3)) e1000_phy_init_script_igp3(hw); @@ -1163,6 +1145,15 @@ static s32 e1000_check_for_link_82575(struct e1000_hw *hw) */ hw->mac.get_link_status = !hw->mac.serdes_has_link; + /* + * Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. + */ + ret_val = e1000_config_fc_after_link_up_generic(hw); + if (ret_val) + DEBUGOUT("Error configuring flow control\n"); } else { ret_val = e1000_check_for_copper_link_generic(hw); } @@ -1216,11 +1207,6 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); - /* Set up defaults for the return values of this function */ - mac->serdes_has_link = false; - *speed = 0; - *duplex = 0; - /* * Read the PCS Status register for link state. For non-copper mode, * the status register is not accurate. The PCS status register is @@ -1247,6 +1233,10 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, *duplex = FULL_DUPLEX; else *duplex = HALF_DUPLEX; + } else { + mac->serdes_has_link = false; + *speed = 0; + *duplex = 0; } return E1000_SUCCESS; @@ -1339,7 +1329,7 @@ static s32 e1000_reset_hw_82575(struct e1000_hw *hw) } /* If EEPROM is not present, run manual init scripts */ - if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) e1000_reset_init_script_82575(hw); /* Clear any pending interrupt events. */ @@ -1419,6 +1409,7 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; + u32 phpm_reg; DEBUGFUNC("e1000_setup_copper_link_82575"); @@ -1427,6 +1418,12 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + /* Clear Go Link Disconnect bit */ + if (hw->mac.type >= e1000_82580) { + phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); + phpm_reg &= ~E1000_82580_PM_GO_LINKD; + E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); + } ret_val = e1000_setup_serdes_link_82575(hw); if (ret_val) goto out; @@ -1481,7 +1478,7 @@ out: **/ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) { - u32 ctrl_ext, ctrl_reg, reg; + u32 ctrl_ext, ctrl_reg, reg, anadv_reg; bool pcs_autoneg; s32 ret_val = E1000_SUCCESS; u16 data; @@ -1565,26 +1562,43 @@ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - /* - * We force flow control to prevent the CTRL register values from being - * overwritten by the autonegotiated flow control values - */ - reg |= E1000_PCS_LCTL_FORCE_FCTRL; - if (pcs_autoneg) { /* Set PCS register for autoneg */ reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ + /* Disable force flow control for autoneg */ + reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; + + /* Configure flow control advertisement for autoneg */ + anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); + anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); + + switch (hw->fc.requested_mode) { + case e1000_fc_full: + case e1000_fc_rx_pause: + anadv_reg |= E1000_TXCW_ASM_DIR; + anadv_reg |= E1000_TXCW_PAUSE; + break; + case e1000_fc_tx_pause: + anadv_reg |= E1000_TXCW_ASM_DIR; + break; + default: + break; + } + + E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg); DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); } else { /* Set PCS register for forced link */ reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ + /* Force flow control for forced link */ + reg |= E1000_PCS_LCTL_FORCE_FCTRL; DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); } E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); - if (!e1000_sgmii_active_82575(hw)) + if (!pcs_autoneg && !e1000_sgmii_active_82575(hw)) e1000_force_mac_fc_generic(hw); return ret_val; @@ -1652,31 +1666,27 @@ static s32 e1000_get_media_type_82575(struct e1000_hw *hw) } /* Read Init Control Word #3*/ hw->nvm.ops.read(hw, init_ctrl_wd_3_offset, 1, &init_ctrl_wd_3); - current_link_mode = init_ctrl_wd_3; - /* - * Switch to CSR for all but internal PHY. - */ - if ((init_ctrl_wd_3 << (E1000_CTRL_EXT_LINK_MODE_OFFSET - - init_ctrl_wd_3_bit_offset)) != - E1000_CTRL_EXT_LINK_MODE_GMII) { - current_link_mode = ctrl_ext; - init_ctrl_wd_3_bit_offset = - E1000_CTRL_EXT_LINK_MODE_OFFSET; - } - } else { - /* Take link mode from CSR */ - current_link_mode = ctrl_ext; - init_ctrl_wd_3_bit_offset = E1000_CTRL_EXT_LINK_MODE_OFFSET; - } /* * Align link mode bits to * their CTRL_EXT location. */ + current_link_mode = init_ctrl_wd_3; current_link_mode <<= (E1000_CTRL_EXT_LINK_MODE_OFFSET - init_ctrl_wd_3_bit_offset); current_link_mode &= E1000_CTRL_EXT_LINK_MODE_MASK; + /* + * Switch to CSR for all but internal PHY. + */ + if (current_link_mode != E1000_CTRL_EXT_LINK_MODE_GMII) + /* Take link mode from CSR */ + current_link_mode = ctrl_ext & + E1000_CTRL_EXT_LINK_MODE_MASK; + } else { + /* Take link mode from CSR */ + current_link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; + } switch (current_link_mode) { case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: @@ -1700,8 +1710,11 @@ static s32 e1000_get_media_type_82575(struct e1000_hw *hw) goto out; if (hw->phy.media_type == e1000_media_type_internal_serdes) { + /* Keep Link Mode as SGMII for 100BaseFX */ + if (!dev_spec->eth_flags.e100_base_fx) { current_link_mode = E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; + } } else if (hw->phy.media_type == e1000_media_type_copper) { current_link_mode = @@ -1754,22 +1767,31 @@ static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) s32 ret_val = E1000_ERR_CONFIG; u32 ctrl_ext = 0; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; - struct sfp_e1000_flags eth_flags = {0}; + struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags; u8 tranceiver_type = 0; + s32 timeout = 3; - /* Turn I2C interface ON */ + /* Turn I2C interface ON and power on sfp cage */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); + E1000_WRITE_FLUSH(hw); /* Read SFP module data */ + while (timeout) { ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), &tranceiver_type); + if (ret_val == E1000_SUCCESS) + break; + msec_delay(100); + timeout--; + } if (ret_val != E1000_SUCCESS) goto out; ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), - (u8 *)ð_flags); + (u8 *)eth_flags); if (ret_val != E1000_SUCCESS) goto out; /* @@ -1779,9 +1801,12 @@ static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { dev_spec->module_plugged = true; - if (eth_flags.e1000_base_lx || eth_flags.e1000_base_sx) { + if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { + hw->phy.media_type = e1000_media_type_internal_serdes; + } else if (eth_flags->e100_base_fx) { + dev_spec->sgmii_active = true; hw->phy.media_type = e1000_media_type_internal_serdes; - } else if (eth_flags.e1000_base_t) { + } else if (eth_flags->e1000_base_t) { dev_spec->sgmii_active = true; hw->phy.media_type = e1000_media_type_copper; } else { @@ -2406,7 +2431,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) } /* If EEPROM is not present, run manual init scripts */ - if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) e1000_reset_init_script_82575(hw); /* clear global device reset status bit */ @@ -2585,7 +2610,7 @@ static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw) goto out; } - if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) { + if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) { /* set compatibility bit to validate checksums appropriately */ nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, @@ -2687,6 +2712,13 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw) ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); + /* keep the LPI clock running before EEE is enabled */ + if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) { + u32 eee_su; + eee_su = E1000_READ_REG(hw, E1000_EEE_SU); + eee_su &= ~E1000_EEE_SU_LPI_CLK_STP; + E1000_WRITE_REG(hw, E1000_EEE_SU, eee_su); + } } else { ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); @@ -2798,7 +2830,7 @@ s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u32 retry = 1; u16 swfw_mask = 0; - bool nack = 1; + bool nack = true; DEBUGFUNC("e1000_read_i2c_byte_generic"); @@ -3069,7 +3101,7 @@ static s32 e1000_get_i2c_ack(struct e1000_hw *hw) u32 i = 0; u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); u32 timeout = 10; - bool ack = 1; + bool ack = true; DEBUGFUNC("e1000_get_i2c_ack"); @@ -3089,7 +3121,7 @@ static s32 e1000_get_i2c_ack(struct e1000_hw *hw) return E1000_ERR_I2C; ack = e1000_get_i2c_data(&i2cctl); - if (ack == 1) { + if (ack) { DEBUGOUT("I2C ack was not received.\n"); status = E1000_ERR_I2C; } @@ -3437,123 +3469,3 @@ s32 e1000_init_thermal_sensor_thresh_generic(struct e1000_hw *hw) } return status; } - -/** - * e1000_get_protected_blocks_82576 - Get the list of protected EEPROM words - * @hw: pointer to hardware structure - * @blocks: buffer to contain the list of protected words - * @blocks_size: size of the blocks buffer - * @block_type_mask: any combination of ixgbe_eeprom_block_type types. - * - * This function reads masked list of protected EEPROM blocks from - * protected_blocks_82575 list. If words is set to NULL the function return - * the size of blocks buffer required to hold masked list of EEPROM blocks - **/ -static s32 e1000_get_protected_blocks_82576(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 *blocks_size, u32 block_type_mask, - u16 *eeprom_buffer, u32 eeprom_size) -{ - struct e1000_nvm_protected_block protected_blocks_82576[] = { - {0x0000, e1000_block_mac_address, false, 0x00, 0x03, 0xFFFF, - NULL}, - {0x0014, e1000_block_wol_config, false, 0x00, 0x01, 0x0480, - NULL}, - {0x0024, e1000_block_wol_config, false, 0x00, 0x01, 0x0480, - NULL}, - {0x0030, e1000_block_preboot_data, false, 0x00, 0x07, 0xFFFF, - NULL}, - {0x0038, e1000_block_preboot_data, false, 0x00, 0x04, 0xFFFF, - NULL}, - {0x0037, e1000_block_alt_mac_address, true, 0x00, 0x03, - 0xFFFF, NULL}, - {0x003D, e1000_block_iscsi_boot_config, true, 0x00, 0x00, - 0xFFFF, NULL}, - {0x0014, e1000_block_flash_config, false, 0x00, 0x01, 0x2000, - NULL}, - {0x0024, e1000_block_flash_config, false, 0x00, 0x01, 0x2000, - NULL}, - {0x000F, e1000_block_flash_config, false, 0x00, 0x01, 0x0700, - NULL}, - }; - s32 status; - u16 table_size; - - DEBUGFUNC("e1000_get_protected_blocks_82576"); - - status = -E1000_ERR_INVALID_ARGUMENT; - if (blocks_size) { - table_size = sizeof(protected_blocks_82576) / - sizeof(protected_blocks_82576[0]); - - status = e1000_get_protected_blocks_from_table(hw, - protected_blocks_82576, table_size, blocks, - blocks_size, block_type_mask, eeprom_buffer, - eeprom_size); - } - - return status; -} - -/** - * e1000_get_protected_blocks_82580 - Get the list of protected EEPROM words - * @hw: pointer to hardware structure - * @blocks: buffer to contain the list of protected words - * @blocks_size: size of the blocks buffer - * @block_type_mask: any combination of ixgbe_eeprom_block_type types. - * - * This function reads masked list of protected EEPROM blocks from - * protected_blocks_82575 list. If words is set to NULL the function return - * the size of blocks buffer required to hold masked list of EEPROM blocks - **/ -static s32 e1000_get_protected_blocks_82580(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 *blocks_size, u32 block_type_mask, - u16 *eeprom_buffer, u32 eeprom_size) -{ - struct e1000_nvm_protected_block protected_blocks_82580[] = { - {0x0000, e1000_block_mac_address, false, 0x00, 0x03, 0xFFFF, - NULL}, - {0x0080, e1000_block_mac_address, false, 0x00, 0x03, 0xFFFF, - NULL}, - {0x00C0, e1000_block_mac_address, false, 0x00, 0x03, 0xFFFF, - NULL}, - {0x0100, e1000_block_mac_address, false, 0x00, 0x03, 0xFFFF, - NULL}, - {0x0024, e1000_block_wol_config, false, 0x00, 0x01, 0x0480, - NULL}, - {0x00A4, e1000_block_wol_config, false, 0x00, 0x01, 0x0480, - NULL}, - {0x00E4, e1000_block_wol_config, false, 0x00, 0x01, 0x0480, - NULL}, - {0x0124, e1000_block_wol_config, false, 0x00, 0x01, 0x0480, - NULL}, - {0x0030, e1000_block_preboot_data, false, 0x00, 0x07, 0xFFFF, - NULL}, - {0x0038, e1000_block_preboot_data, false, 0x00, 0x04, 0xFFFF, - NULL}, - {0x0037, e1000_block_alt_mac_address, true, 0x00, 0x0B, 0xFFFF, - NULL}, - {0x003D, e1000_block_iscsi_boot_config, true, 0x00, 0x00, - 0xFFFF, NULL}, - {0x000F, e1000_block_flash_config, false, 0x00, 0x01, 0x0720, - NULL}, - }; - s32 status; - u16 table_size; - - DEBUGFUNC("e1000_get_protected_blocks_82580"); - - status = -E1000_ERR_INVALID_ARGUMENT; - if (blocks_size) { - table_size = sizeof(protected_blocks_82580) / - sizeof(protected_blocks_82580[0]); - - status = e1000_get_protected_blocks_from_table(hw, - protected_blocks_82580, table_size, blocks, - blocks_size, block_type_mask, eeprom_buffer, - eeprom_size); - } - - return status; -} diff --git a/kmod/igb/e1000_api.c b/kmod/igb/e1000_api.c index 82a2be1..1c0af57 100644 --- a/kmod/igb/e1000_api.c +++ b/kmod/igb/e1000_api.c @@ -182,6 +182,9 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_I350_DA4: mac->type = e1000_i350; break; +#if defined(QV_RELEASE) && defined(SPRINGVILLE_FLASHLESS_HW) + case E1000_DEV_ID_I210_NVMLESS: +#endif /* QV_RELEASE && SPRINGVILLE_FLASHLESS_HW */ case E1000_DEV_ID_I210_COPPER: case E1000_DEV_ID_I210_COPPER_OEM1: case E1000_DEV_ID_I210_COPPER_IT: @@ -1076,99 +1079,7 @@ s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) return hw->nvm.ops.write(hw, offset, words, data); return E1000_SUCCESS; -} - -/** - * e1000_get_protected_block_size - Get the size of protected EEPROM block - * @hw: pointer to hardware structure - * @block: pointer to the protected block structure describing our block - * @eeprom_buffer: pointer to eeprom image buffer - * @eeprom_buffer_size: size of eeprom_buffer - * - * This function reads the size of protected EEPROM block from the EEPROM - * content or the eeprom_buffer (if provided) - **/ -s32 e1000_get_protected_block_size(struct e1000_hw *hw, - struct e1000_nvm_protected_block *block, - u16 *eeprom_buffer, u32 eeprom_buffer_size) -{ - if (hw->nvm.ops.get_protected_block_size) - return hw->nvm.ops.get_protected_block_size(hw, block, - eeprom_buffer, eeprom_buffer_size); - return -E1000_ERR_CONFIG; -} - -/** - * e1000_get_protected_blocks - Get the list of protected EEPROM words - * @hw: pointer to hardware structure - * @blocks: buffer to contain the list of protected words - * @blocks_number: size of the words buffer - * @block_type_mask: any combination of e1000_nvm_block_type values - * @eeprom_buffer: pointer to eeprom image buffer - * @eeprom_buffer_size: size of eeprom_buffer - * - * This function reads masked list of protected EEPROM blocks from device - * specific e1000_nvm_protected_block list. If words is set to NULL the - * function returns the size of buffer required to hold masked list of EEPROM - * blocks. If eeprom_buffer is not specified the function will read data from - * onboard EEPROM. - **/ -s32 e1000_get_protected_blocks(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 *blocks_number, u32 block_type_mask, - u16 *eeprom_buffer, u32 eeprom_buffer_size) -{ - if (hw->nvm.ops.get_protected_blocks) - return hw->nvm.ops.get_protected_blocks(hw, blocks, - blocks_number, block_type_mask, - eeprom_buffer, eeprom_buffer_size); - return -E1000_ERR_CONFIG; -} -/** - * e1000_read_protected_blocks - Read EEPROM protected blocks - * @hw: pointer to hardware structure - * @blocks: pointer to the protected blocks to read - * @blocks_number: number of blocks to read - * @eeprom_buffer: pointer to eeprom image buffer - * @eeprom_buffer_size: size of eeprom_buffer - * - * This function reads the content of EEPROM protected blocks from - * eeprom_buffer (if provided) or onboard EEPROM. - **/ -s32 e1000_read_protected_blocks(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 blocks_number, u16 *eeprom_buffer, - u32 eeprom_buffer_size) -{ - if (hw->nvm.ops.read_protected_blocks) - return hw->nvm.ops.read_protected_blocks(hw, blocks, - blocks_number, eeprom_buffer, - eeprom_buffer_size); - return -E1000_ERR_CONFIG; -} - -/** - * e1000_write_protected_blocks - Read EEPROM protected blocks - * @hw: pointer to hardware structure - * @blocks: pointer to the protected blocks to write - * @blocks_number: number of blocks to write - * @eeprom_buffer: pointer to eeprom image buffer - * @eeprom_buffer_size: size of eeprom_buffer - * - * This function writes the content of EEPROM protected blocks from - * eeprom_buffer (if provided) or onboard EEPROM. - **/ -s32 e1000_write_protected_blocks(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 blocks_number, u16 *eeprom_buffer, - u32 eeprom_buffer_size) -{ - if (hw->nvm.ops.write_protected_blocks) - return hw->nvm.ops.write_protected_blocks(hw, blocks, - blocks_number, eeprom_buffer, - eeprom_buffer_size); - return -E1000_ERR_CONFIG; } /** diff --git a/kmod/igb/e1000_api.h b/kmod/igb/e1000_api.h index 8be89bb..ba9fea5 100644 --- a/kmod/igb/e1000_api.h +++ b/kmod/igb/e1000_api.h @@ -37,6 +37,7 @@ extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw); extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw); extern void e1000_init_function_pointers_i210(struct e1000_hw *hw); +s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr); s32 e1000_set_mac_type(struct e1000_hw *hw); s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device); s32 e1000_init_mac_params(struct e1000_hw *hw); @@ -105,22 +106,6 @@ s32 e1000_get_thermal_sensor_data(struct e1000_hw *hw); s32 e1000_init_thermal_sensor_thresh(struct e1000_hw *hw); -s32 e1000_get_protected_block_size(struct e1000_hw *hw, - struct e1000_nvm_protected_block *block, - u16 *eeprom_buffer, u32 eeprom_buffer_size); -s32 e1000_get_protected_blocks(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 *blocks_number, u32 block_type_mask, - u16 *eeprom_buffer, u32 eeprom_buffer_size); -s32 e1000_read_protected_blocks(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 blocks_number, u16 *eeprom_buffer, - u32 eeprom_buffer_size); -s32 e1000_write_protected_blocks(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 blocks_number, u16 *eeprom_buffer, - u32 eeprom_buffer_size); - /* * TBI_ACCEPT macro definition: * @@ -163,4 +148,10 @@ s32 e1000_write_protected_blocks(struct e1000_hw *hw, (((length) > min_frame_size) && \ ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1))))) +#ifndef E1000_MAX +#define E1000_MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef E1000_DIVIDE_ROUND_UP +#define E1000_DIVIDE_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) /* ceil(a/b) */ #endif +#endif /* _E1000_API_H_ */ diff --git a/kmod/igb/e1000_defines.h b/kmod/igb/e1000_defines.h index 15c7457..dec83a7 100644 --- a/kmod/igb/e1000_defines.h +++ b/kmod/igb/e1000_defines.h @@ -200,6 +200,7 @@ #define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ #define E1000_RXD_SPC_CFI_SHIFT 12 +#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */ #define E1000_RXDEXT_STATERR_LB 0x00040000 #define E1000_RXDEXT_STATERR_CE 0x01000000 #define E1000_RXDEXT_STATERR_SE 0x02000000 @@ -225,6 +226,9 @@ E1000_RXDEXT_STATERR_CXE | \ E1000_RXDEXT_STATERR_RXE) +/* Packet Types as indicated in the Adv/Ext receive descriptor. */ +#define E1000_RXD_PKTTYPE_MASK 0x000F0000 +#define E1000_RXD_PKTTYPE_PTP 0x000E0000 #define E1000_MRQC_ENABLE_MASK 0x00000007 #define E1000_MRQC_ENABLE_RSS_2Q 0x00000001 #define E1000_MRQC_ENABLE_RSS_INT 0x00000004 @@ -584,6 +588,7 @@ #define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ /* Extended desc bits for Linksec and timesync */ +#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ /* Transmit Control */ #define E1000_TCTL_RST 0x00000001 /* software reset */ @@ -698,7 +703,7 @@ #define E1000_PBA_48K 0x0030 /* 48KB */ #define E1000_PBA_64K 0x0040 /* 64KB */ -#define E1000_PBA_RXA_MASK 0xFFFF; +#define E1000_PBA_RXA_MASK 0xFFFF #define E1000_PBS_16K E1000_PBA_16K #define E1000_PBS_24K E1000_PBA_24K @@ -736,8 +741,8 @@ #define E1000_ICR_SRPD 0x00010000 #define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ #define E1000_ICR_MNG 0x00040000 /* Manageability event */ -#define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */ #define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ +#define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */ #define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 @@ -811,7 +816,6 @@ #define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ #define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */ -#define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */ #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ #define E1000_IMS_RXO E1000_ICR_RXO /* Rx overrun */ @@ -827,6 +831,7 @@ #define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */ #define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */ /* Q0 Rx desc FIFO parity error */ #define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 @@ -1023,6 +1028,7 @@ #define E1000_TSYNCRXCTL_TYPE_ALL 0x08 #define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A #define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ +#define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ #define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF #define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00 @@ -1044,6 +1050,8 @@ #define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE 0x0D00 #define E1000_TIMINCA_16NS_SHIFT 24 +#define E1000_TIMINCA_INCPERIOD_SHIFT 24 +#define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF #define E1000_TSICR_TXTS 0x00000002 #define E1000_TSIM_TXTS 0x00000002 @@ -1089,6 +1097,7 @@ #define E1000_EEER_RX_LPI_STATUS 0x40000000 /* Rx in LPI state */ #define E1000_EEER_TX_LPI_STATUS 0x80000000 /* Tx in LPI state */ +#define E1000_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */ /* PCI Express Control */ #define E1000_GCR_RXD_NO_SNOOP 0x00000001 #define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 @@ -1262,6 +1271,7 @@ #define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES) #define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ #define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/ +#define E1000_EECD_FLASH_DETECTED_I210 0x00080000 /* FLASH detected */ #define E1000_FLUDONE_ATTEMPTS 20000 #define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ #define E1000_I210_FIFO_SEL_RX 0x00 @@ -1286,6 +1296,18 @@ #define NVM_VERSION 0x0005 #define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */ #define NVM_PHY_CLASS_WORD 0x0007 +#define NVM_ETRACK_WORD 0x0042 +#define NVM_COMB_VER_OFF 0x0083 +#define NVM_COMB_VER_PTR 0x003d + +/* NVM version defines */ +#define NVM_MAJOR_MASK 0xF000 +#define NVM_MINOR_MASK 0x000F +#define NVM_COMB_VER_MASK 0x00FF +#define NVM_MAJOR_SHIFT 12 +#define NVM_COMB_VER_SHFT 8 +#define NVM_VER_INVALID 0xFFFF +#define NVM_ETRACK_SHIFT 16 #define NVM_MAC_ADDR 0x0000 #define NVM_SUB_DEV_ID 0x000B @@ -1439,7 +1461,6 @@ #define M88E1000_I_PHY_ID 0x01410C30 #define M88E1011_I_PHY_ID 0x01410C20 #define IGP01E1000_I_PHY_ID 0x02A80380 -#define M88E1145_E_PHY_ID 0x01410CD0 #define M88E1011_I_REV_4 0x04 #define M88E1111_I_PHY_ID 0x01410CC0 #define M88E1112_E_PHY_ID 0x01410C90 @@ -1731,12 +1752,10 @@ /* Lx power decision based on DMA coal */ #define E1000_PCIEMISC_LX_DECISION 0x00000080 +#define E1000_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */ #define E1000_RXPBS_SIZE_I210_MASK 0x0000003F /* Rx packet buffer size */ #define E1000_TXPB0S_SIZE_I210_MASK 0x0000003F /* Tx packet buffer 0 size */ -/* Timestamp in Rx buffer */ -#define E1000_RXPBS_CFG_TS_EN 0x80000000 - /* Proxy Filer Control */ #define E1000_PROXYFC_D0 0x00000001 /* Enable offload in D0 */ #define E1000_PROXYFC_EX 0x00000004 /* Directed exact proxy */ diff --git a/kmod/igb/e1000_hw.h b/kmod/igb/e1000_hw.h index 9e901a0..dba8088 100644 --- a/kmod/igb/e1000_hw.h +++ b/kmod/igb/e1000_hw.h @@ -56,6 +56,9 @@ struct e1000_hw; #define E1000_DEV_ID_I350_SERDES 0x1523 #define E1000_DEV_ID_I350_SGMII 0x1524 #define E1000_DEV_ID_I350_DA4 0x1546 +#if defined(QV_RELEASE) && defined(SPRINGVILLE_FLASHLESS_HW) +#define E1000_DEV_ID_I210_NVMLESS 0x1531 +#endif /* QV_RELEASE && SPRINGVILLE_FLASHLESS_HW */ #define E1000_DEV_ID_I210_COPPER 0x1533 #define E1000_DEV_ID_I210_COPPER_OEM1 0x1534 #define E1000_DEV_ID_I210_COPPER_IT 0x1535 @@ -477,35 +480,6 @@ struct e1000_host_mng_command_info { u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; }; -enum e1000_nvm_block_type { - e1000_block_undefined = 0x00000000, - e1000_block_mac_address = 0x00000001, - e1000_block_alt_mac_address = 0x00000002, - e1000_block_fcoe_config = 0x00000004, - e1000_block_wol_config = 0x00000008, - e1000_block_pointer = 0x00000010, - e1000_block_general_config = 0x00000020, - e1000_block_preboot_data = 0x00000040, - e1000_block_iscsi_boot_config = 0x00000080, - e1000_block_flash_config = 0x00000100, - e1000_type_lan_core_module = 0x00000200, - e1000_type_san_mac = 0x00000400, - e1000_type_alt_san_mac = 0x00000800, - e1000_block_user = 0x80000000, - e1000_block_all = 0xFFFFFFFF, -}; - -struct e1000_nvm_protected_block { - u32 word_address; - enum e1000_nvm_block_type block_type; - bool pointer; - u32 pointed_word_offset; - u32 block_size; - u16 word_mask; - u16 *buffer; -}; - -#define E1000_ISCSI_BLOCK_SIZE_WORD_OFFSET 0x01 #include "e1000_mac.h" #include "e1000_phy.h" @@ -604,14 +578,6 @@ struct e1000_nvm_operations { s32 (*valid_led_default)(struct e1000_hw *, u16 *); s32 (*validate)(struct e1000_hw *); s32 (*write)(struct e1000_hw *, u16, u16, u16 *); - s32 (*get_protected_block_size)(struct e1000_hw *, - struct e1000_nvm_protected_block *, u16 *, u32); - s32 (*get_protected_blocks)(struct e1000_hw *, - struct e1000_nvm_protected_block *, u16 *, u32, u16 *, u32); - s32 (*read_protected_blocks)(struct e1000_hw *, - struct e1000_nvm_protected_block *, u16, u16 *, u32); - s32 (*write_protected_blocks)(struct e1000_hw *, - struct e1000_nvm_protected_block *, u16, u16 *, u32); }; #define E1000_MAX_SENSORS 3 @@ -668,7 +634,6 @@ struct e1000_mac_info { enum e1000_serdes_link_state serdes_link_state; bool serdes_has_link; bool tx_pkt_filtering; - u32 max_frame_size; struct e1000_thermal_sensor_data thermal_sensor_data; }; @@ -775,6 +740,7 @@ struct e1000_dev_spec_82575 { bool eee_disable; bool module_plugged; u32 mtu; + struct sfp_e1000_flags eth_flags; }; struct e1000_dev_spec_vf { diff --git a/kmod/igb/e1000_i210.c b/kmod/igb/e1000_i210.c index 441bb1c..9fd3aca 100644 --- a/kmod/igb/e1000_i210.c +++ b/kmod/igb/e1000_i210.c @@ -373,15 +373,40 @@ static s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, if (ret_val != E1000_SUCCESS) DEBUGOUT("MAC Addr not found in iNVM\n"); break; - case NVM_ID_LED_SETTINGS: case NVM_INIT_CTRL_2: + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_INIT_CTRL_2_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; case NVM_INIT_CTRL_4: + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_INIT_CTRL_4_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; case NVM_LED_1_CFG: + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_LED_1_CFG_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; case NVM_LED_0_2_CFG: - e1000_read_invm_i211(hw, (u8)offset, data); + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_LED_0_2_CFG_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } break; - case NVM_COMPAT: - *data = ID_LED_DEFAULT_I210; + case NVM_ID_LED_SETTINGS: + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = ID_LED_RESERVED_FFFF; + ret_val = E1000_SUCCESS; + } break; case NVM_SUB_DEV_ID: *data = hw->subsystem_device_id; @@ -448,6 +473,105 @@ s32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data) } /** + * e1000_read_invm_version - Reads iNVM version and image type + * @hw: pointer to the HW structure + * @invm_ver: version structure for the version read + * + * Reads iNVM version and image type. + **/ +s32 e1000_read_invm_version(struct e1000_hw *hw, + struct e1000_fw_version *invm_ver) +{ + u32 *record = NULL; + u32 *next_record = NULL; + u32 i = 0; + u32 invm_dword = 0; + u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE / + E1000_INVM_RECORD_SIZE_IN_BYTES); + u32 buffer[E1000_INVM_SIZE]; + s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; + u16 version = 0; + + DEBUGFUNC("e1000_read_invm_version"); + + /* Read iNVM memory */ + for (i = 0; i < E1000_INVM_SIZE; i++) { + invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i)); + buffer[i] = invm_dword; + } + + /* Read version number */ + for (i = 1; i < invm_blocks; i++) { + record = &buffer[invm_blocks - i]; + next_record = &buffer[invm_blocks - i + 1]; + + /* Check if we have first version location used */ + if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) { + version = 0; + status = E1000_SUCCESS; + break; + } + /* Check if we have second version location used */ + else if ((i == 1) && + ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) { + version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; + status = E1000_SUCCESS; + break; + } + /* + * Check if we have odd version location + * used and it is the last one used + */ + else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) && + ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) && + (i != 1))) { + version = (*next_record & E1000_INVM_VER_FIELD_TWO) + >> 13; + status = E1000_SUCCESS; + break; + } + /* + * Check if we have even version location + * used and it is the last one used + */ + else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) && + ((*record & 0x3) == 0)) { + version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; + status = E1000_SUCCESS; + break; + } + } + + if (status == E1000_SUCCESS) { + invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK) + >> E1000_INVM_MAJOR_SHIFT; + invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK; + } + /* Read Image Type */ + for (i = 1; i < invm_blocks; i++) { + record = &buffer[invm_blocks - i]; + next_record = &buffer[invm_blocks - i + 1]; + + /* Check if we have image type in first location used */ + if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) { + invm_ver->invm_img_type = 0; + status = E1000_SUCCESS; + break; + } + /* Check if we have image type in first location used */ + else if ((((*record & 0x3) == 0) && + ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) || + ((((*record & 0x3) != 0) && (i != 1)))) { + invm_ver->invm_img_type = + (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23; + status = E1000_SUCCESS; + break; + } + } + return status; +} + +/** * e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum * @hw: pointer to the HW structure * @@ -547,6 +671,28 @@ out: return ret_val; } +#if defined(QV_RELEASE) && defined(SPRINGVILLE_FLASHLESS_HW) +/** + * e1000_get_flash_presence_i210 - Check if flash device is detected. + * @hw: pointer to the HW structure + * + **/ +static bool e1000_get_flash_presence_i210(struct e1000_hw *hw) +{ + u32 eec = 0; + bool ret_val = false; + + DEBUGFUNC("e1000_get_flash_presence_i210"); + + eec = E1000_READ_REG(hw, E1000_EECD); + + if (eec & E1000_EECD_FLASH_DETECTED_I210) + ret_val = true; + + return ret_val; +} + +#endif /* QV_RELEASE && SPRINGVILLE_FLASHLESS_HW */ /** * e1000_update_flash_i210 - Commit EEPROM to the flash * @hw: pointer to the HW structure @@ -663,7 +809,14 @@ void e1000_init_function_pointers_i210(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_i210: +#if defined(QV_RELEASE) && defined(SPRINGVILLE_FLASHLESS_HW) + if (e1000_get_flash_presence_i210(hw)) + hw->nvm.ops.init_params = e1000_init_nvm_params_i210; + else + hw->nvm.ops.init_params = e1000_init_nvm_params_i211; +#else hw->nvm.ops.init_params = e1000_init_nvm_params_i210; +#endif /* QV_RELEASE && SPRINGVILLE_FLASHLESS_HW */ break; case e1000_i211: hw->nvm.ops.init_params = e1000_init_nvm_params_i211; diff --git a/kmod/igb/e1000_i210.h b/kmod/igb/e1000_i210.h index 74bd844..83f0668 100644 --- a/kmod/igb/e1000_i210.h +++ b/kmod/igb/e1000_i210.h @@ -36,6 +36,8 @@ s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data); +s32 e1000_read_invm_version(struct e1000_hw *hw, + struct e1000_fw_version *invm_ver); s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask); void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask); @@ -60,6 +62,15 @@ enum E1000_INVM_STRUCTURE_TYPE { #define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8 #define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1 +#define E1000_INVM_ULT_BYTES_SIZE 8 +#define E1000_INVM_RECORD_SIZE_IN_BYTES 4 +#define E1000_INVM_VER_FIELD_ONE 0x1FF8 +#define E1000_INVM_VER_FIELD_TWO 0x7FE000 +#define E1000_INVM_IMGTYPE_FIELD 0x1F800000 + +#define E1000_INVM_MAJOR_MASK 0x3F0 +#define E1000_INVM_MINOR_MASK 0xF +#define E1000_INVM_MAJOR_SHIFT 4 #define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ @@ -68,4 +79,9 @@ enum E1000_INVM_STRUCTURE_TYPE { (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_DEF1_DEF2)) +/* NVM offset defaults for Pearsonville device */ +#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243 +#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1 +#define NVM_LED_1_CFG_DEFAULT_I211 0x0184 +#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C #endif diff --git a/kmod/igb/e1000_mac.c b/kmod/igb/e1000_mac.c index e54fd8f..7b03600 100644 --- a/kmod/igb/e1000_mac.c +++ b/kmod/igb/e1000_mac.c @@ -30,6 +30,7 @@ static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); static void e1000_config_collision_dist_generic(struct e1000_hw *hw); +static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); /** * e1000_init_mac_ops_generic - Initialize MAC function pointers @@ -378,7 +379,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) * Sets the receive address array register at index to the address passed * in by addr. **/ -void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) +static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; @@ -846,7 +847,7 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) return ret_val; } - if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) + if (!(nvm_data & NVM_WORD0F_PAUSE_MASK)) hw->fc.requested_mode = e1000_fc_none; else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) @@ -877,7 +878,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) * In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ - if (hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) return E1000_SUCCESS; /* @@ -1235,6 +1236,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; + u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; u16 speed, duplex; @@ -1413,6 +1415,138 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) } } + /* + * Check for the case where we have SerDes media and auto-neg is + * enabled. In this case, we need to check and see if Auto-Neg + * has completed, and if so, how the PHY and link partner has + * flow control configured. + */ + if ((hw->phy.media_type == e1000_media_type_internal_serdes) + && mac->autoneg) { + /* + * Read the PCS_LSTS and check to see if AutoNeg + * has completed. + */ + pcs_status_reg = E1000_READ_REG(hw, E1000_PCS_LSTAT); + + if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { + DEBUGOUT("PCS Auto Neg has not completed.\n"); + return ret_val; + } + + /* + * The AutoNeg process has completed, so we now need to + * read both the Auto Negotiation Advertisement + * Register (PCS_ANADV) and the Auto_Negotiation Base + * Page Ability Register (PCS_LPAB) to determine how + * flow control was negotiated. + */ + pcs_adv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); + pcs_lp_ability_reg = E1000_READ_REG(hw, E1000_PCS_LPAB); + + /* + * Two bits in the Auto Negotiation Advertisement Register + * (PCS_ANADV) and two bits in the Auto Negotiation Base + * Page Ability Register (PCS_LPAB) determine flow control + * for both the PHY and the link partner. The following + * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, + * 1999, describes these PAUSE resolution bits and how flow + * control is determined based upon these settings. + * NOTE: DC = Don't Care + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution + *-------|---------|-------|---------|-------------------- + * 0 | 0 | DC | DC | e1000_fc_none + * 0 | 1 | 0 | DC | e1000_fc_none + * 0 | 1 | 1 | 0 | e1000_fc_none + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + * 1 | 0 | 0 | DC | e1000_fc_none + * 1 | DC | 1 | DC | e1000_fc_full + * 1 | 1 | 0 | 0 | e1000_fc_none + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + * + * Are both PAUSE bits set to 1? If so, this implies + * Symmetric Flow Control is enabled at both ends. The + * ASM_DIR bits are irrelevant per the spec. + * + * For Symmetric Flow Control: + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | DC | 1 | DC | e1000_fc_full + * + */ + if ((pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { + /* + * Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise Rx + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == e1000_fc_full) { + hw->fc.current_mode = e1000_fc_full; + DEBUGOUT("Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = e1000_fc_rx_pause; + DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); + } + } + /* + * For receiving PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + */ + else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_adv_reg & E1000_TXCW_ASM_DIR) && + (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { + hw->fc.current_mode = e1000_fc_tx_pause; + DEBUGOUT("Flow Control = Tx PAUSE frames only.\n"); + } + /* + * For transmitting PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + */ + else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_adv_reg & E1000_TXCW_ASM_DIR) && + !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { + hw->fc.current_mode = e1000_fc_rx_pause; + DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); + } else { + /* + * Per the IEEE spec, at this point flow control + * should be disabled. + */ + hw->fc.current_mode = e1000_fc_none; + DEBUGOUT("Flow Control = NONE.\n"); + } + + /* + * Now we call a subroutine to actually force the MAC + * controller to use the correct flow control settings. + */ + pcs_ctrl_reg = E1000_READ_REG(hw, E1000_PCS_LCTL); + pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; + E1000_WRITE_REG(hw, E1000_PCS_LCTL, pcs_ctrl_reg); + + ret_val = e1000_force_mac_fc_generic(hw); + if (ret_val) { + DEBUGOUT("Error forcing flow control settings\n"); + return ret_val; + } + } return E1000_SUCCESS; } @@ -1947,6 +2081,19 @@ static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) hw->phy.mdix = 1; return -E1000_ERR_CONFIG; } + return E1000_SUCCESS; +} + +/** + * e1000_validate_mdi_setting_crossover_generic - Verify MDI/MDIx settings + * @hw: pointer to the HW structure + * + * Validate the MDI/MDIx setting, allowing for auto-crossover during forced + * operation. + **/ +s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_validate_mdi_setting_crossover_generic"); return E1000_SUCCESS; } diff --git a/kmod/igb/e1000_mac.h b/kmod/igb/e1000_mac.h index 36bba5f..385b125 100644 --- a/kmod/igb/e1000_mac.h +++ b/kmod/igb/e1000_mac.h @@ -65,6 +65,7 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); s32 e1000_setup_led_generic(struct e1000_hw *hw); s32 e1000_setup_link_generic(struct e1000_hw *hw); +s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw); s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, u32 offset, u8 data); @@ -75,7 +76,6 @@ void e1000_clear_vfta_generic(struct e1000_hw *hw); void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count); void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw); void e1000_put_hw_semaphore_generic(struct e1000_hw *hw); -void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); void e1000_reset_adaptive_generic(struct e1000_hw *hw); void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); diff --git a/kmod/igb/e1000_manage.c b/kmod/igb/e1000_manage.c index 38a1b8c..f61c176 100644 --- a/kmod/igb/e1000_manage.c +++ b/kmod/igb/e1000_manage.c @@ -75,7 +75,7 @@ s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); - if ((hicr & E1000_HICR_EN) == 0) { + if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } @@ -398,7 +398,7 @@ s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length) /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); - if ((hicr & E1000_HICR_EN) == 0) { + if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } @@ -461,11 +461,11 @@ s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length) /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); - if ((hicr & E1000_HICR_EN) == 0) { + if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_CONFIG; } - if ((hicr & E1000_HICR_MEMORY_BASE_EN) == 0) { + if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) { DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n"); return -E1000_ERR_CONFIG; } diff --git a/kmod/igb/e1000_nvm.c b/kmod/igb/e1000_nvm.c index 3ffb749..ef28069 100644 --- a/kmod/igb/e1000_nvm.c +++ b/kmod/igb/e1000_nvm.c @@ -27,7 +27,6 @@ #include "e1000_api.h" -static void e1000_stop_nvm(struct e1000_hw *hw); static void e1000_reload_nvm_generic(struct e1000_hw *hw); /** @@ -51,10 +50,6 @@ void e1000_init_nvm_ops_generic(struct e1000_hw *hw) nvm->ops.valid_led_default = e1000_null_led_default; nvm->ops.validate = e1000_null_ops_generic; nvm->ops.write = e1000_null_write_nvm; - nvm->ops.get_protected_block_size = - e1000_get_protected_block_size_generic; - nvm->ops.read_protected_blocks = e1000_read_protected_blocks_generic; - nvm->ops.write_protected_blocks = e1000_write_protected_blocks_generic; } /** @@ -623,8 +618,8 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, if (nvm_data != NVM_PBA_PTR_GUARD) { DEBUGOUT("NVM PBA number is not stored as string\n"); - /* we will need 11 characters to store the PBA */ - if (pba_num_size < 11) { + /* make sure callers buffer is big enough to store the PBA */ + if (pba_num_size < E1000_PBANUM_LENGTH) { DEBUGOUT("PBA string buffer too small\n"); return E1000_ERR_NO_SPACE; } @@ -725,7 +720,7 @@ s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size) /* if data is not ptr guard the PBA must be in legacy format */ if (nvm_data != NVM_PBA_PTR_GUARD) { - *pba_num_size = 11; + *pba_num_size = E1000_PBANUM_LENGTH; return E1000_SUCCESS; } @@ -863,404 +858,79 @@ static void e1000_reload_nvm_generic(struct e1000_hw *hw) } /** - * e1000_get_protected_block_size_generic - Get the size of EEPROM block - * @hw: pointer to hardware structure - * @block: pointer to the protected block structure describing our block - * @eeprom_buffer: pointer to eeprom image buffer. - * @eeprom_buffer_size: size of eeprom_buffer + * e1000_get_fw_version - Get firmware version information + * @hw: pointer to the HW structure + * @fw_vers: pointer to output version structure * - * This function reads the size of protected EEPROM block from the EEPROM - * content (if eeprom_buffer = NULL) or from eeprom_buffer. + * unsupported/not present features return 0 in version structure **/ -s32 e1000_get_protected_block_size_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *block, - u16 *eeprom_buffer, u32 eeprom_buffer_size) +void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) { - s32 status; - u16 pointer, size_word; - - DEBUGFUNC("e1000_get_protected_block_size_generic"); - - if ( (!block) || (0 == block->pointer) ) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - - if (block->block_size) { - status = E1000_SUCCESS; - goto out; - } - - if (block->pointer) { - if (eeprom_buffer) { - if (block->word_address > eeprom_buffer_size) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - pointer = eeprom_buffer[block->word_address]; - status = E1000_SUCCESS; - } else - status = e1000_read_nvm(hw, block->word_address, 1, - &pointer); - if (status != E1000_SUCCESS) - goto out; - - if (pointer == 0xFFFF) { - block->block_size = 0; - goto out; - } - } - - switch (block->block_type) { - case e1000_block_iscsi_boot_config: - /* size of the 'iSCSI Module Structure' is in 'Block Size' - * at word offset [0x01] */ - pointer += E1000_ISCSI_BLOCK_SIZE_WORD_OFFSET; - if (eeprom_buffer) { - if ((u32)pointer + 1 > eeprom_buffer_size) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - size_word = eeprom_buffer[pointer]; - status = E1000_SUCCESS; - } else { - status = e1000_read_nvm(hw, pointer, 1, &size_word); - if (status != E1000_SUCCESS) - goto out; - } - - /* Block size is in bytes, so we need to conver it to words */ - block->block_size = size_word / 2; + u16 eeprom_verh, eeprom_verl, fw_version; + u16 comb_verh, comb_verl, comb_offset; + + memset(fw_vers, 0, sizeof(struct e1000_fw_version)); + + /* this code only applies to certain mac types */ + switch (hw->mac.type) { + case e1000_i211: + e1000_read_invm_version(hw, fw_vers); + return; + case e1000_82575: + case e1000_82576: + case e1000_82580: + case e1000_i350: + case e1000_i210: break; default: - status = -E1000_ERR_INVALID_ARGUMENT; - break; - } -out: - return status; -} - -/** - * e1000_read_protected_block_generic - Read EEPROM protected block - * @hw: pointer to hardware structure - * @block: pointer to the protected block to read - * @eeprom_buffer: pointer to eeprom image buffer. - * @eeprom_buffer_size: size of eeprom_buffer - * - * This function reads the content of EEPROM protected block from buffer (if - * provided) or EEPROM. - **/ -s32 e1000_read_protected_block_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *block, - u16 *eeprom_buffer, u32 eeprom_buffer_size) -{ - s32 status; - u32 max_address; - u16 pointer; - - DEBUGFUNC("e1000_read_eeprom_protected_block_generic"); - - if (!block || !block->buffer) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - - /* Read raw word */ - if (!block->pointer) { - max_address = block->block_size + block->word_address; - if (eeprom_buffer) { - if (max_address > eeprom_buffer_size) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - memcpy(block->buffer, - eeprom_buffer + block->word_address, - 2 * (max_address - block->word_address)); - status = E1000_SUCCESS; - } else - status = e1000_read_nvm(hw, block->word_address, - block->block_size, block->buffer); - } - /* Read pointer */ - else { - if (eeprom_buffer) { - if (block->word_address > eeprom_buffer_size) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - pointer = eeprom_buffer[block->word_address]; - status = E1000_SUCCESS; - } else - status = e1000_read_nvm(hw, block->word_address, 1, - &pointer); - if (status != E1000_SUCCESS) - goto out; - - pointer += block->pointed_word_offset; - max_address = block->block_size + pointer; - if (eeprom_buffer) { - if (max_address > eeprom_buffer_size) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - memcpy(block->buffer, eeprom_buffer + pointer, - 2 * (max_address - pointer)); - status = E1000_SUCCESS; - } else - status = e1000_read_nvm(hw, pointer, block->block_size, - block->buffer); - } -out: - return status; -} - -/** - * e1000_read_protected_blocks_generic - Read EEPROM protected blocks - * @hw: pointer to hardware structure - * @blocks: pointer to the protected blocks to read - * @blocks_number: number of blocks to read - * @eeprom_buffer: pointer to eeprom image buffer. - * @eeprom_buffer_size: size of eeprom_buffer - * - * This function reads the content of EEPROM protected blocks from buffer (if - * provided) or EEPROM. - **/ -s32 e1000_read_protected_blocks_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 blocks_number, u16 *eeprom_buffer, - u32 eeprom_buffer_size) -{ - s32 status = E1000_SUCCESS; - u16 i; - - DEBUGFUNC("e1000_read_protected_blocks_generic"); - - if (!blocks) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - - /* Check if all buffers are allocated */ - for (i = 0; i < blocks_number; i++) { - if (!blocks[i].buffer) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - } - - /* Read all protected blocks */ - for (i = 0; i < blocks_number; i++) { - status = e1000_read_protected_block_generic(hw, - blocks + i, eeprom_buffer, eeprom_buffer_size); - if (status != E1000_SUCCESS) - goto out; - } -out: - return status; + return; } -/** - * e1000_write_eeprom_protected_block_generic - Write EEPROM protected block - * @hw: pointer to hardware structure - * @block: pointer to the protected block to write - * @eeprom_buffer: pointer to eeprom image buffer. - * @eeprom_buffer_size: size of eeprom_buffer - * - * This function writes the content of EEPROM protected block to buffer (if - * provided) or EEPROM. - **/ -s32 e1000_write_protected_block_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *block, - u16 *eeprom_buffer, u32 eeprom_buffer_size) -{ - s32 status = E1000_SUCCESS; - u32 start_address, end_address, address; - u16 pointer, word; - - DEBUGFUNC("e1000_write_eeprom_protected_block_generic"); - - if (!block || !block->buffer) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - - /* Write raw word */ - if (!block->pointer) { - start_address = block->word_address; - end_address = start_address + block->block_size; - if (eeprom_buffer) { - if (end_address > eeprom_buffer_size) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - status = E1000_SUCCESS; - } - } - /* Write pointer */ - else { - if (eeprom_buffer) { - if (block->word_address > eeprom_buffer_size) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; + /* basic eeprom version numbers */ + hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); + fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT; + fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK); + + /* etrack id */ + hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl); + hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh); + fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl; + + switch (hw->mac.type) { + case e1000_i210: + case e1000_i350: + /* find combo image version */ + hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset); + if ((comb_offset != 0x0) && + (comb_offset != NVM_VER_INVALID)) { + + hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset + + 1), 1, &comb_verh); + hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset), + 1, &comb_verl); + + /* get Option Rom version if it exists and is valid */ + if ((comb_verh && comb_verl) && + ((comb_verh != NVM_VER_INVALID) && + (comb_verl != NVM_VER_INVALID))) { + + fw_vers->or_valid = true; + fw_vers->or_major = + comb_verl >> NVM_COMB_VER_SHFT; + fw_vers->or_build = + (comb_verl << NVM_COMB_VER_SHFT) + | (comb_verh >> NVM_COMB_VER_SHFT); + fw_vers->or_patch = + comb_verh & NVM_COMB_VER_MASK; } - pointer = eeprom_buffer[block->word_address]; - status = E1000_SUCCESS; - } else - status = e1000_read_nvm(hw, block->word_address, 1, - &pointer); - if (status != E1000_SUCCESS) - goto out; - /* Check if current pointer isn't 0xFFFF (not allocated) */ - if (pointer == 0xFFFF) { - status = -E1000_ERR_NVM; - DEBUGOUT1("Error. Cannot merge record %d", - block->word_address); - goto out; - } - start_address = pointer + block->pointed_word_offset; - end_address = start_address + block->block_size; - if (eeprom_buffer) { - if (end_address > eeprom_buffer_size) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - } - } - - /* Finally write the changes to the EEPROM */ - for (address = start_address; address < end_address; address++) { - status = e1000_read_nvm(hw, address, 1, &word); - if (status != E1000_SUCCESS) - break; - /* apply the mask */ - word &= ~block->word_mask; - word |= (block->buffer[address - start_address] & - block->word_mask); - if (eeprom_buffer) - eeprom_buffer[address] = word; - else - status = e1000_write_nvm(hw, address, 1, &word); - if (status != E1000_SUCCESS) - break; - } -out: - return status; -} - -/** - * e1000_write_protected_blocks_generic - Read EEPROM protected blocks - * @hw: pointer to hardware structure - * @blocks: pointer to the protected blocks to write - * @blocks_number: number of blocks to read - * @eeprom_buffer: pointer to eeprom image buffer. - * @eeprom_buffer_size: size of eeprom_buffer - * - * This function writes the content of EEPROM protected blocks from buffer (if - * provided) or EEPROM. - **/ -s32 e1000_write_protected_blocks_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 blocks_number, u16 *eeprom_buffer, - u32 eeprom_buffer_size) -{ - s32 status = E1000_SUCCESS; - u16 i; - - DEBUGFUNC("ixgbe_write_protected_blocks_generic"); - - if (!blocks) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; - } - /* Check if all buffers are allocated */ - for (i = 0; i < blocks_number; i++) { - if (!blocks[i].buffer) { - status = -E1000_ERR_INVALID_ARGUMENT; - goto out; } - } + break; - /* Write all protected blocks */ - for (i = 0; i < blocks_number; i++) { - status = e1000_write_protected_block_generic(hw, blocks + i, - eeprom_buffer, eeprom_buffer_size); - if (status != E1000_SUCCESS) + default: break; } -out: - return status; + return; } -/** - * e1000_get_protected_blocks_from_table - Get the masked list of protected - * EEPROM words from device specific table - * @hw: pointer to hardware structure - * @protected_blocks_table: pointer to device-specific list of protected blocks - * @protected_blocks_table_size: size of protected_blocks_table list - * @blocks: buffer to contain the list of protected blocks - * @blocks_size: size of the blocks buffer - * @block_type_mask: any combination of e1000_nvm_block_type types. - * - * This function gets masked list of protected EEPROM blocks from device - * specific list. If blocks is set to NULL, the function return the size - * of blocks buffer required to hold masked list - **/ -s32 e1000_get_protected_blocks_from_table(struct e1000_hw *hw, - struct e1000_nvm_protected_block *protected_blocks_table, - u16 protected_blocks_table_size, - struct e1000_nvm_protected_block *blocks, u16 *blocks_size, - u32 block_type_mask, u16 *eeprom_buffer, u32 eeprom_size) -{ - struct e1000_nvm_protected_block *current_block; - s32 status = E1000_SUCCESS; - u16 i, pointer_value, masked_blocks_count; - - DEBUGFUNC("e1000_get_protected_blocks_from_table"); - - masked_blocks_count = 0; - - /* get the number of blocks to copy */ - for (i = 0; i < protected_blocks_table_size; i++) { - current_block = &protected_blocks_table[i]; - if ((current_block->block_type & block_type_mask) == 0) - continue; - - /* If it's a pointer read its value */ - if (current_block->pointer) { - status = e1000_read_nvm(hw, - current_block->word_address, 1, - &pointer_value); - if (status != E1000_SUCCESS) - goto out; - /* Skip empty pointers */ - if (pointer_value == 0xFFFF) - continue; - } - - /* Copy blocks listed in table to the provided buffer */ - if (blocks) { - if (masked_blocks_count >= *blocks_size) { - status = -E1000_ERR_NO_SPACE; - goto out; - } - status = e1000_get_protected_block_size(hw, - current_block, - eeprom_buffer, - eeprom_size); - memcpy(&blocks[masked_blocks_count], current_block, - sizeof(struct e1000_nvm_protected_block)); - if (status != E1000_SUCCESS) - goto out; - } - masked_blocks_count++; - } - - if (!blocks) { - *blocks_size = masked_blocks_count; - status = E1000_SUCCESS; - } -out: - return status; -} diff --git a/kmod/igb/e1000_nvm.h b/kmod/igb/e1000_nvm.h index 6e86fd7..93ab8b7 100644 --- a/kmod/igb/e1000_nvm.h +++ b/kmod/igb/e1000_nvm.h @@ -28,6 +28,20 @@ #ifndef _E1000_NVM_H_ #define _E1000_NVM_H_ +struct e1000_fw_version { + u32 etrack_id; + u16 eep_major; + u16 eep_minor; + + u8 invm_major; + u8 invm_minor; + u8 invm_img_type; + + bool or_valid; + u16 or_major; + u16 or_build; + u16 or_patch; +}; void e1000_init_nvm_ops_generic(struct e1000_hw *hw); s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); void e1000_null_nvm_generic(struct e1000_hw *hw); @@ -49,29 +63,9 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw); void e1000_release_nvm_generic(struct e1000_hw *hw); +void e1000_get_fw_version(struct e1000_hw *hw, + struct e1000_fw_version *fw_vers); #define E1000_STM_OPCODE 0xDB00 -s32 e1000_get_protected_block_size_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *block, - u16 *eeprom_buffer, u32 eeprom_buffer_size); -s32 e1000_read_protected_block_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *block, - u16 *eeprom_buffer, u32 eeprom_buffer_size); -s32 e1000_read_protected_blocks_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 blocks_number, u16 *eeprom_buffer, - u32 eeprom_buffer_size); -s32 e1000_write_protected_block_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *block, - u16 *eeprom_buffer, u32 eeprom_buffer_size); -s32 e1000_write_protected_blocks_generic(struct e1000_hw *hw, - struct e1000_nvm_protected_block *blocks, - u16 blocks_number, u16 *eeprom_buffer, - u32 eeprom_buffer_size); -s32 e1000_get_protected_blocks_from_table(struct e1000_hw *hw, - struct e1000_nvm_protected_block *protected_blocks_table, - u16 protected_blocks_table_size, - struct e1000_nvm_protected_block *blocks, u16 *blocks_size, - u32 block_type_mask, u16 *eeprom_buffer, u32 eeprom_size); #endif diff --git a/kmod/igb/e1000_osdep.h b/kmod/igb/e1000_osdep.h index 22847a4..f819b6f 100644 --- a/kmod/igb/e1000_osdep.h +++ b/kmod/igb/e1000_osdep.h @@ -67,10 +67,19 @@ #endif +#ifdef DEBUG +#define DEBUGOUT(S) printk(KERN_DEBUG S) +#define DEBUGOUT1(S, A...) printk(KERN_DEBUG S, ## A) +#else #define DEBUGOUT(S) #define DEBUGOUT1(S, A...) +#endif +#ifdef DEBUG_FUNC +#define DEBUGFUNC(F) DEBUGOUT(F "\n") +#else #define DEBUGFUNC(F) +#endif #define DEBUGOUT2 DEBUGOUT1 #define DEBUGOUT3 DEBUGOUT2 #define DEBUGOUT7 DEBUGOUT3 diff --git a/kmod/igb/e1000_phy.c b/kmod/igb/e1000_phy.c index a4a9a1e..942b3c2 100644 --- a/kmod/igb/e1000_phy.c +++ b/kmod/igb/e1000_phy.c @@ -1035,6 +1035,31 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) if (ret_val) return ret_val; + /* Set MDI/MDIX mode */ + ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data); + if (ret_val) + return ret_val; + phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; + /* + * Options: + * 0 - Auto (default) + * 1 - MDI mode + * 2 - MDI-X mode + */ + switch (hw->phy.mdix) { + case 1: + break; + case 2: + phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX; + break; + case 0: + default: + phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX; + break; + } + ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data); + if (ret_val) + return ret_val; return e1000_set_master_slave_mode(hw); } @@ -1097,7 +1122,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) * 1 - Enabled */ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (phy->disable_polarity_correction == 1) + if (phy->disable_polarity_correction) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); @@ -1210,7 +1235,7 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw) * 1 - Enabled */ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (phy->disable_polarity_correction == 1) + if (phy->disable_polarity_correction) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; /* Enable downshift and setting it to X6 */ @@ -1519,7 +1544,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) * If autoneg_advertised is zero, we assume it was not defaulted * by the calling code so we set to advertise full capability. */ - if (phy->autoneg_advertised == 0) + if (!phy->autoneg_advertised) phy->autoneg_advertised = phy->autoneg_mask; DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); @@ -1701,18 +1726,23 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); + /* I210 and I211 devices support Auto-Crossover in forced operation. */ + if (phy->type != e1000_phy_i210) { /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. + * Clear Auto-Crossover to force MDI manually. M88E1000 + * requires MDI forced whenever speed and duplex are forced. */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); if (ret_val) return ret_val; phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); if (ret_val) return ret_val; + } DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); @@ -2737,9 +2767,11 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_phy_hw_reset_generic"); + if (phy->ops.check_reset_block) { ret_val = phy->ops.check_reset_block(hw); if (ret_val) return E1000_SUCCESS; + } ret_val = phy->ops.acquire(hw); if (ret_val) @@ -2873,7 +2905,6 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) enum e1000_phy_type phy_type = e1000_phy_unknown; switch (phy_id) { - case M88E1145_E_PHY_ID: case M88E1000_I_PHY_ID: case M88E1000_E_PHY_ID: case M88E1111_I_PHY_ID: diff --git a/kmod/igb/e1000_phy.h b/kmod/igb/e1000_phy.h index 4aabf71..9e7b84a 100644 --- a/kmod/igb/e1000_phy.h +++ b/kmod/igb/e1000_phy.h @@ -147,8 +147,9 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); #define I82577_PHY_STATUS2_SPEED_100MBPS 0x0100 /* I82577 PHY Control 2 */ -#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400 -#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 +#define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200 +#define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 +#define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600 /* I82577 PHY Diagnostics Status */ #define I82577_DSTATUS_CABLE_LENGTH 0x03FC @@ -159,6 +160,7 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); #define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */ #define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */ #define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */ +#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */ #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 #define IGP01E1000_PHY_POLARITY_MASK 0x0078 diff --git a/kmod/igb/e1000_regs.h b/kmod/igb/e1000_regs.h index a0e99c9..11093a7 100644 --- a/kmod/igb/e1000_regs.h +++ b/kmod/igb/e1000_regs.h @@ -49,8 +49,10 @@ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ #define E1000_FEXT 0x0002C /* Future Extended - RW */ -#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ +#define E1000_FEXTNVM2 0x00030 /* Future Extended NVM 2 - RW */ +#define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ +#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ @@ -153,6 +155,25 @@ #define E1000_TQAVHC(_n) (0x0300C + ((_n) * 0x40)) #define E1000_TQAVCC(_n) (0x03004 + ((_n) * 0x40)) +/* QAV Tx mode control register */ +#define E1000_I210_TQAVCTRL 0x3570 + +/* High credit registers where _n can be 0 or 1. */ +#define E1000_I210_TQAVHC(_n) (0x300C + 0x40 * (_n)) + +/* Queues fetch arbitration priority control register */ +#define E1000_I210_TQAVARBCTRL 0x3574 +/* Queues priority masks where _n and _p can be 0-3. */ +#define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p) ((_p) << (2 * _n)) +/* QAV Tx mode control registers where _n can be 0 or 1. */ +#define E1000_I210_TQAVCC(_n) (0x3004 + 0x40 * (_n)) + +/* Good transmitted packets counter registers */ +#define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n))) + +/* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */ +#define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * _n)) + /* * Convenience macros * @@ -523,6 +544,8 @@ #define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ #define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ #define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ +#define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */ +#define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */ #define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ #define E1000_TSICR 0x0B66C /* Interrupt Cause Register */ @@ -591,10 +614,6 @@ /* PCIe Parity Status Register */ #define E1000_PCIEERRSTS 0x05BA8 -#define E1000_LTRMINV 0x5BB0 /* LTR Minimum Value */ -#define E1000_LTRMAXV 0x5BB4 /* LTR Maximum Value */ -#define E1000_DOBFFCTL 0x3F24 /* DMA OBFF Control Register */ - #define E1000_PROXYS 0x5F64 /* Proxying Status */ #define E1000_PROXYFC 0x5F60 /* Proxying Filter Control */ /* Thermal sensor configuration and status registers */ diff --git a/kmod/igb/igb.h b/kmod/igb/igb.h index a9ae32b..a434b02 100644 --- a/kmod/igb/igb.h +++ b/kmod/igb/igb.h @@ -46,13 +46,6 @@ #include #endif -#include -#include -#ifdef CONFIG_PTP -#include -#endif -#include -#include struct igb_adapter; @@ -91,6 +84,11 @@ struct igb_user_page { printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ __FUNCTION__ , ## args)) +#ifdef CONFIG_IGB_PTP +#include +#include +#include +#endif /* CONFIG_IGB_PTP */ /* Interrupt defines */ #define IGB_START_ITR 648 /* ~6000 ints/sec */ #define IGB_4K_ITR 980 @@ -104,9 +102,9 @@ struct igb_user_page { /* TX/RX descriptor defines */ #define IGB_DEFAULT_TXD 256 -#define IGB_DEFAULT_TX_WORK 128 #define IGB_MIN_TXD 80 #define IGB_MAX_TXD 4096 +#define IGB_DEFAULT_TX_WORK 128 #define IGB_DEFAULT_RXD 256 #define IGB_MIN_RXD 80 @@ -131,7 +129,6 @@ struct igb_user_page { #define OUI_LEN 3 #define IGB_MAX_VMDQ_QUEUES 8 -#define E1000_DMACDC 0x3F1C struct vf_data_storage { unsigned char vf_mac_addresses[ETH_ALEN]; @@ -187,8 +184,6 @@ struct vf_data_storage { */ /* Supported Rx Buffer Sizes */ #define IGB_RXBUFFER_512 512 -#define IGB_RXBUFFER_2048 2048 -#define IGB_RXBUFFER_256 256 #define IGB_RXBUFFER_16384 16384 #define IGB_RX_HDR_LEN IGB_RXBUFFER_512 @@ -206,9 +201,7 @@ struct vf_data_storage { #define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define IGB_EEPROM_APME 0x0400 -#ifndef ETH_TP_MDI_X #define AUTO_ALL_MODES 0 -#endif #ifndef IGB_MASTER_SLAVE /* Switch to override PHY master/slave setting */ @@ -309,10 +302,6 @@ struct igb_rx_queue_stats { u64 drops; u64 csum_err; u64 alloc_failed; - u64 csum_good; - u64 rx_hdr_split; - u64 lli_int; - u64 pif_count; }; struct igb_ring_container { @@ -332,7 +321,6 @@ struct igb_q_vector { struct igb_ring_container rx, tx; struct napi_struct napi; - int numa_node; u16 itr_val; u8 set_itr; @@ -387,7 +375,6 @@ struct igb_ring { #endif /* Items past this point are only used during ring alloc / free */ dma_addr_t dma; /* phys address of the ring */ - int numa_node; /* node to alloc ring memory on */ } ____cacheline_internodealigned_in_smp; @@ -510,6 +497,10 @@ struct igb_adapter { bool fc_autoneg; u8 tx_timeout_factor; +#ifdef DEBUG + bool tx_hang_detected; + bool disable_hw_reset; +#endif u32 max_frame_size; /* OS defined structs */ @@ -543,7 +534,7 @@ struct igb_adapter { u32 eims_other; /* to not mess up cache alignment, always add to the bottom */ - u32 eeprom_wol; + bool wol_supported; u32 *config_space; u16 tx_ring_count; @@ -560,8 +551,7 @@ struct igb_adapter { int int_mode; u32 rss_queues; u32 vmdq_pools; - u16 fw_version; - int node; + char fw_version[32]; u32 wvbr; struct igb_mac_addr *mac_table; #ifdef CONFIG_IGB_VMDQ_NETDEV @@ -569,21 +559,8 @@ struct igb_adapter { #endif int vferr_refcount; int dmac; - u64 dmac_entries; - int count; u32 *shadow_vfta; -#ifdef CONFIG_PTP - struct ptp_clock *ptp_clock; - struct ptp_clock_info ptp_caps; - struct delayed_work ptp_overflow_work; - struct work_struct ptp_tx_work; - struct sk_buff *ptp_tx_skb; - spinlock_t tmreg_lock; - struct cyclecounter cc; - struct timecounter tc; -#endif /* CONFIG_PTP */ - /* External Thermal Sensor support flag */ bool ets; #ifdef IGB_SYSFS @@ -597,6 +574,18 @@ struct igb_adapter { struct igb_therm_proc_data therm_data[E1000_MAX_SENSORS]; #endif /* IGB_PROCFS */ #endif /* IGB_SYSFS */ + u32 etrack_id; + +#ifdef CONFIG_IGB_PTP + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_caps; + struct delayed_work ptp_overflow_work; + struct work_struct ptp_tx_work; + struct sk_buff *ptp_tx_skb; + spinlock_t tmreg_lock; + struct cyclecounter cc; + struct timecounter tc; +#endif /* CONFIG_IGB_PTP */ }; #ifdef CONFIG_IGB_VMDQ_NETDEV @@ -625,6 +614,7 @@ struct igb_vmdq_adapter { #define IGB_FLAG_EEE (1 << 6) #define IGB_FLAG_DMAC (1 << 7) #define IGB_FLAG_DETECT_BAD_DMA (1 << 8) +#define IGB_FLAG_PTP (1 << 9) #define IGB_MIN_TXPBSIZE 20408 #define IGB_TX_BUF_4096 4096 @@ -674,6 +664,7 @@ struct e1000_fw_hdr { } cmd_or_resp; u8 checksum; }; +#pragma pack(push,1) struct e1000_fw_drv_info { struct e1000_fw_hdr hdr; u8 port_num; @@ -681,6 +672,7 @@ struct e1000_fw_drv_info { u16 pad; /* end spacing to ensure length is mult. of dword */ u8 pad2; /* end spacing to ensure length is mult. of dword2 */ }; +#pragma pack(pop) enum e1000_state_t { __IGB_TESTING, __IGB_RESETTING, @@ -716,6 +708,7 @@ extern void igb_power_up_link(struct igb_adapter *); #ifdef CONFIG_PTP extern void igb_ptp_init(struct igb_adapter *adapter); extern void igb_ptp_stop(struct igb_adapter *adapter); +extern void igb_ptp_reset(struct igb_adapter *adapter); extern void igb_ptp_tx_work(struct work_struct *work); extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter); extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, @@ -738,24 +731,6 @@ extern void igb_enable_vlan_tags(struct igb_adapter *adapter); extern void igb_vlan_mode(struct net_device *, u32); #endif -/* TLP Processing Hints (TPH) definitions */ -#define E1000_DCA_CTRL_TPH_READ_DISABLE (1 << 8) /* TPH Read Hint disable */ -#define E1000_DCA_CTRL_TPH_DATA_PH 0x00001000 /* TPH Data hint mode */ - -#define E1000_TPH_RXCTRL_CPUID_MASK 0xFF000000 /* Rx CPUID Mask */ -#define E1000_TPH_RXCTRL_FTCH_DCA_EN (1 << 0) /* TPH Rx Desc fetch enable */ -#define E1000_TPH_RXCTRL_DESC_DCA_EN (1 << 1) /* TPH Rx Desc writeback enable */ -#define E1000_TPH_RXCTRL_HEAD_DCA_EN (1 << 2) /* TPH Rx Data header enable */ -#define E1000_TPH_RXCTRL_DATA_DCA_EN (1 << 3) /* TPH Rx Data payload enable */ -#define E1000_TPH_RXCTRL_AUTOLEARN_EN (1 << 23) /* TPH Rx Autolearn enable */ - -#define E1000_TPH_TXCTRL_CPUID_MASK 0xFF000000 /* Tx CPUID Mask */ -#define E1000_TPH_TXCTRL_FTCH_DCA_EN (1 << 0) /* TPH Tx Desc fetch enable */ -#define E1000_TPH_TXCTRL_DESC_DCA_EN (1 << 1) /* TPH Tx Desc writeback enable */ -#define E1000_TPH_TXCTRL_DATA_DCA_EN (1 << 3) /* TPH Tx Data payload enable */ -#define E1000_TPH_TXCTRL_AUTOLEARN_EN (1 << 23) /* TPH Tx Autolearn enable */ - - #ifdef IGB_SYSFS void igb_sysfs_exit(struct igb_adapter *adapter); int igb_sysfs_init(struct igb_adapter *adapter); diff --git a/kmod/igb/igb_ethtool.c b/kmod/igb/igb_ethtool.c index 9625098..7b851fa 100644 --- a/kmod/igb/igb_ethtool.c +++ b/kmod/igb/igb_ethtool.c @@ -157,39 +157,58 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full| SUPPORTED_Autoneg | - SUPPORTED_TP); - ecmd->advertising = (ADVERTISED_TP | - ADVERTISED_Pause); + SUPPORTED_TP | + SUPPORTED_Pause); + ecmd->advertising = ADVERTISED_TP; if (hw->mac.autoneg == 1) { ecmd->advertising |= ADVERTISED_Autoneg; /* the e1000 autoneg seems to match ethtool nicely */ ecmd->advertising |= hw->phy.autoneg_advertised; } + if (hw->mac.autoneg != 1) + ecmd->advertising &= ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + + if (hw->fc.requested_mode == e1000_fc_full) + ecmd->advertising |= ADVERTISED_Pause; + else if (hw->fc.requested_mode == e1000_fc_rx_pause) + ecmd->advertising |= (ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + else if (hw->fc.requested_mode == e1000_fc_tx_pause) + ecmd->advertising |= ADVERTISED_Asym_Pause; + else + ecmd->advertising &= ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); ecmd->port = PORT_TP; ecmd->phy_address = hw->phy.addr; + ecmd->transceiver = XCVR_INTERNAL; } else { ecmd->supported = (SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full | SUPPORTED_FIBRE | - SUPPORTED_Autoneg); + SUPPORTED_Autoneg | + SUPPORTED_Pause); - ecmd->advertising = (ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | + ecmd->advertising = (ADVERTISED_FIBRE | ADVERTISED_Autoneg | ADVERTISED_Pause); + if (adapter->link_speed == SPEED_100) + ecmd->advertising = ADVERTISED_100baseT_Full; + else + ecmd->advertising = ADVERTISED_1000baseT_Full; ecmd->port = PORT_FIBRE; + ecmd->transceiver = XCVR_EXTERNAL; } - ecmd->transceiver = XCVR_INTERNAL; status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_LU) { - if ((status & E1000_STATUS_SPEED_1000) || - hw->phy.media_type != e1000_media_type_copper) + if (status & E1000_STATUS_SPEED_1000) ecmd->speed = SPEED_1000; else if (status & E1000_STATUS_SPEED_100) ecmd->speed = SPEED_100; @@ -206,17 +225,27 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->duplex = -1; } - ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; + if ((hw->phy.media_type == e1000_media_type_fiber) || + hw->mac.autoneg) + ecmd->autoneg = AUTONEG_ENABLE; + else + ecmd->autoneg = AUTONEG_DISABLE; #ifdef ETH_TP_MDI_X /* MDI-X => 2; MDI =>1; Invalid =>0 */ - if ((hw->phy.media_type == e1000_media_type_copper) && - netif_carrier_ok(netdev)) + if (hw->phy.media_type == e1000_media_type_copper) ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : ETH_TP_MDI; else ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; +#ifdef ETH_TP_MDI_AUTO + if (hw->phy.mdix == AUTO_ALL_MODES) + ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; + else + ecmd->eth_tp_mdix_ctrl = hw->phy.mdix; + +#endif #endif /* ETH_TP_MDI_X */ return 0; } @@ -234,14 +263,43 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) return -EINVAL; } +#ifdef ETH_TP_MDI_AUTO + /* + * MDI setting is only allowed when autoneg enabled because + * some hardware doesn't allow MDI setting when speed or + * duplex is forced. + */ + if (ecmd->eth_tp_mdix_ctrl) { + if (hw->phy.media_type != e1000_media_type_copper) + return -EOPNOTSUPP; + + if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && + (ecmd->autoneg != AUTONEG_ENABLE)) { + dev_err(&adapter->pdev->dev, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); + return -EINVAL; + } + } + +#endif /* ETH_TP_MDI_AUTO */ while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) usleep_range(1000, 2000); if (ecmd->autoneg == AUTONEG_ENABLE) { hw->mac.autoneg = 1; + if (hw->phy.media_type == e1000_media_type_fiber) { + hw->phy.autoneg_advertised = ADVERTISED_FIBRE | + ADVERTISED_Autoneg; + if (adapter->link_speed == SPEED_1000) + hw->phy.autoneg_advertised = + ADVERTISED_1000baseT_Full; + else + hw->phy.autoneg_advertised = + ADVERTISED_100baseT_Full; + } else { hw->phy.autoneg_advertised = ecmd->advertising | ADVERTISED_TP | ADVERTISED_Autoneg; + } ecmd->advertising = hw->phy.autoneg_advertised; if (adapter->fc_autoneg) hw->fc.requested_mode = e1000_fc_default; @@ -350,8 +408,7 @@ static int igb_set_pauseparam(struct net_device *netdev, hw->fc.current_mode = hw->fc.requested_mode; - retval = ((hw->phy.media_type == e1000_media_type_copper) ? - e1000_force_mac_fc(hw) : hw->mac.ops.setup_link(hw)); + retval = hw->mac.ops.setup_link(hw); } clear_bit(__IGB_RESETTING, &adapter->state); @@ -719,12 +776,8 @@ static void igb_get_drvinfo(struct net_device *netdev, strncpy(drvinfo->driver, igb_driver_name, sizeof(drvinfo->driver) - 1); strncpy(drvinfo->version, igb_driver_version, sizeof(drvinfo->version) - 1); - /* EEPROM image version # is reported as firmware version # for - * 82575 controllers */ - snprintf(drvinfo->fw_version, 32, "%d.%d-%d", - (adapter->fw_version & 0xF000) >> 12, - (adapter->fw_version & 0x0FF0) >> 4, - adapter->fw_version & 0x000F); + strncpy(drvinfo->fw_version, adapter->fw_version, + sizeof(drvinfo->fw_version) - 1); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info) -1); drvinfo->n_stats = IGB_STATS_LEN; @@ -1012,22 +1065,11 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data) { - u16 temp; - u16 checksum = 0; - u16 i; *data = 0; - /* Read and add up the contents of the EEPROM */ - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) { - *data = 1; - break; - } - checksum += temp; - } - /* If Checksum is not Correct return error else test passed */ - if ((checksum != (u16) NVM_SUM) && !(*data)) + /* Validate NVM checksum */ + if (e1000_validate_nvm_checksum(&adapter->hw) < 0) *data = 2; return *data; @@ -1094,9 +1136,11 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) ics_mask = 0x77DCFED5; break; case e1000_i350: + ics_mask = 0x77DCFED5; + break; case e1000_i210: case e1000_i211: - ics_mask = 0x77DCFED5; + ics_mask = 0x774CFED5; break; default: ics_mask = 0x7FFFFFFF; @@ -1311,7 +1355,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter) if (hw->phy.type == e1000_phy_m88) igb_phy_disable_receiver(adapter); - udelay(500); + mdelay(500); return 0; } @@ -1645,8 +1689,6 @@ static void igb_diag_test(struct net_device *netdev, dev_info(pci_dev_to_dev(adapter->pdev), "offline testing starting\n"); /* power up link for link test */ - if ((adapter->hw.mac.type != e1000_i210) && - (adapter->hw.mac.type != e1000_i211)) igb_power_up_link(adapter); /* Link test performed before hardware reset so autoneg doesn't @@ -1673,8 +1715,6 @@ static void igb_diag_test(struct net_device *netdev, igb_reset(adapter); /* power up link for loopback test */ - if ((adapter->hw.mac.type != e1000_i210) && - (adapter->hw.mac.type != e1000_i211)) igb_power_up_link(adapter); if (igb_loopback_test(adapter, &data[3])) @@ -1713,54 +1753,6 @@ static void igb_diag_test(struct net_device *netdev, msleep_interruptible(4 * 1000); } -static int igb_wol_exclusion(struct igb_adapter *adapter, - struct ethtool_wolinfo *wol) -{ - struct e1000_hw *hw = &adapter->hw; - int retval = 1; /* fail by default */ - - switch (hw->device_id) { - case E1000_DEV_ID_82575GB_QUAD_COPPER: - /* WoL not supported */ - wol->supported = 0; - break; - case E1000_DEV_ID_82575EB_FIBER_SERDES: - case E1000_DEV_ID_82576_FIBER: - case E1000_DEV_ID_82576_SERDES: - /* Wake events not supported on port B */ - if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; - case E1000_DEV_ID_82576_QUAD_COPPER: - case E1000_DEV_ID_82576_QUAD_COPPER_ET2: - /* quad port adapters only support WoL on port A */ - if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; - default: - /* dual port cards only support WoL on port A from now on - * unless it was enabled in the eeprom for port B - * so exclude FUNC_1 ports from having WoL enabled */ - if ((E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_MASK) && - !adapter->eeprom_wol) { - wol->supported = 0; - break; - } - - retval = 0; - } - - return retval; -} - static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct igb_adapter *adapter = netdev_priv(netdev); @@ -1770,10 +1762,7 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) WAKE_PHY; wol->wolopts = 0; - /* this function will set ->supported = 0 and return 1 if wol is not - * supported by this hardware */ - if (igb_wol_exclusion(adapter, wol) || - !device_can_wakeup(&adapter->pdev->dev)) + if (!adapter->wol_supported || !device_can_wakeup(&adapter->pdev->dev)) return; /* apply any specific unsupported masks here */ @@ -1801,8 +1790,7 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; - if (igb_wol_exclusion(adapter, wol) || - !device_can_wakeup(&adapter->pdev->dev)) + if (!adapter->wol_supported || !device_can_wakeup(&adapter->pdev->dev)) return wol->wolopts ? -EOPNOTSUPP : 0; /* these settings will always override what we currently have */ adapter->wol = 0; @@ -2067,27 +2055,20 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_alloc_failed", i); p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_csum_good", i); - p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_hdr_split", i); - p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_lli_int", i); - p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_pif_count", i); - p += ETH_GSTRING_LEN; } /* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */ break; } } -#ifdef CONFIG_PTP +#ifdef HAVE_ETHTOOL_GET_TS_INFO static int igb_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) { struct igb_adapter *adapter = netdev_priv(dev); switch (adapter->hw.mac.type) { +#ifdef CONFIG_PTP case e1000_82576: case e1000_82580: case e1000_i350: @@ -2116,20 +2097,21 @@ static int igb_get_ts_info(struct net_device *dev, info->rx_filters |= (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | + (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | + (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) | (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); - break; + return 0; +#endif /* CONFIG_PTP */ default: - return ethtool_op_get_ts_info(dev, info); - break; + return -EOPNOTSUPP; } - return 0; } -#endif /* CONFIG_IGB_PTP */ +#endif /* HAVE_ETHTOOL_GET_TS_INFO */ #ifdef CONFIG_PM_RUNTIME static int igb_ethtool_begin(struct net_device *netdev) @@ -2345,7 +2327,80 @@ static void igb_get_dmac(struct net_device *netdev, return; } #endif -static struct ethtool_ops igb_ethtool_ops = { +#ifdef ETHTOOL_GEEE +static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 ipcnfg, eeer; + + if ((hw->mac.type < e1000_i350) || + (hw->phy.media_type != e1000_media_type_copper)) + return -EOPNOTSUPP; + + edata->supported = (SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full); + + ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG); + eeer = E1000_READ_REG(hw, E1000_EEER); + + /* EEE status on negotiated link */ + if (ipcnfg & E1000_IPCNFG_EEE_1G_AN) + edata->advertised |= ADVERTISED_1000baseT_Full; + + if (ipcnfg & E1000_IPCNFG_EEE_100M_AN) + edata->advertised |= ADVERTISED_100baseT_Full; + + if (eeer & E1000_EEER_EEE_NEG) + edata->eee_active = true; + + edata->eee_enabled = !hw->dev_spec._82575.eee_disable; + + if (eeer & E1000_EEER_TX_LPI_EN) + edata->tx_lpi_enabled = true; + + /* + * report correct negotiated EEE status for devices that + * wrongly report EEE at half-duplex + */ + if (adapter->link_duplex == HALF_DUPLEX) { + edata->eee_enabled = false; + edata->eee_active = false; + edata->tx_lpi_enabled = false; + } + + return 0; +} +#endif + +#ifdef ETHTOOL_SEEE +static int igb_set_eee(struct net_device *netdev, + struct ethtool_eee *edata) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + if ((hw->mac.type < e1000_i350) || + (hw->phy.media_type != e1000_media_type_copper)) + return -EOPNOTSUPP; + + while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + + if (!edata->eee_enabled) { + hw->dev_spec._82575.eee_disable = true; + e1000_set_eee_i350(hw); + } else if (edata->eee_enabled) { + hw->dev_spec._82575.eee_disable = false; + e1000_set_eee_i350(hw); + } + + clear_bit(__IGB_RESETTING, &adapter->state); + return 0; +} +#endif /* ETHTOOL_SEEE */ + +static const struct ethtool_ops igb_ethtool_ops = { .get_settings = igb_get_settings, .set_settings = igb_set_settings, .get_drvinfo = igb_get_drvinfo, @@ -2383,9 +2438,9 @@ static struct ethtool_ops igb_ethtool_ops = { #endif .get_coalesce = igb_get_coalesce, .set_coalesce = igb_set_coalesce, -#ifdef CONFIG_PTP +#ifdef HAVE_ETHTOOL_GET_TS_INFO .get_ts_info = igb_get_ts_info, -#endif +#endif /* HAVE_ETHTOOL_GET_TS_INFO */ #ifdef CONFIG_PM_RUNTIME .begin = igb_ethtool_begin, .complete = igb_ethtool_complete, @@ -2408,13 +2463,20 @@ static struct ethtool_ops igb_ethtool_ops = { #endif /* HAVE_NDO_SET_FEATURES */ #ifdef ETHTOOL_GADV_COAL .get_advcoal = igb_get_adv_coal, - .set_advcoal = igb_set_dmac_coal + .set_advcoal = igb_set_dmac_coal, #endif /* ETHTOOL_GADV_COAL */ +#ifdef ETHTOOL_GEEE + .get_eee = igb_get_eee, +#endif +#ifdef ETHTOOL_SEEE + .set_eee = igb_set_eee, +#endif }; void igb_set_ethtool_ops(struct net_device *netdev) { - SET_ETHTOOL_OPS(netdev, &igb_ethtool_ops); + /* have to "undeclare" const on this struct to remove warnings */ + SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igb_ethtool_ops); } #endif /* SIOCETHTOOL */ diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index d2e5a23..9ccf640 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -73,20 +73,25 @@ #include "igb.h" #include "igb_vmdq.h" +#if defined(DEBUG) || defined (DEBUG_DUMP) || defined (DEBUG_ICR) || defined(DEBUG_ITR) +#define DRV_DEBUG "_debug" +#else #define DRV_DEBUG +#endif #define DRV_HW_PERF #define VERSION_SUFFIX "_AVB" -#define MAJ 3 -#define MIN 4 -#define BUILD 7 +#define MAJ 4 +#define MIN 0 +#define BUILD 17 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." __stringify(BUILD) VERSION_SUFFIX DRV_DEBUG DRV_HW_PERF char igb_driver_name[] = "igb_avb"; char igb_driver_version[] = DRV_VERSION; static const char igb_driver_string[] = "Intel(R) Gigabit Ethernet Network Driver"; -static const char igb_copyright[] = "Copyright (c) 2007-2012 Intel Corporation."; +static const char igb_copyright[] = + "Copyright (c) 2007-2012 Intel Corporation."; static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER) }, @@ -131,8 +136,6 @@ static void igb_set_uta(struct igb_adapter *adapter); static irqreturn_t igb_intr(int irq, void *); static irqreturn_t igb_intr_msi(int irq, void *); static irqreturn_t igb_msix_other(int irq, void *); -static void igb_update_tph(struct igb_q_vector *); -static void igb_setup_tph(struct igb_adapter *); static irqreturn_t igb_msix_ring(int irq, void *); #ifdef IGB_DCA static void igb_update_dca(struct igb_q_vector *); @@ -216,6 +219,9 @@ static const struct dev_pm_ops igb_pm_ops = { igb_runtime_idle) #endif /* CONFIG_PM_RUNTIME */ }; +#else +static int igb_suspend(struct pci_dev *pdev, pm_message_t state); +static int igb_resume(struct pci_dev *pdev); #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ #endif /* CONFIG_PM */ #ifndef USE_REBOOT_NOTIFIER @@ -284,6 +290,9 @@ static struct pci_driver igb_driver = { #ifdef CONFIG_PM #ifdef HAVE_SYSTEM_SLEEP_PM_OPS .driver.pm = &igb_pm_ops, +#else + .suspend = igb_suspend, + .resume = igb_resume, #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ #endif /* CONFIG_PM */ #ifndef USE_REBOOT_NOTIFIER @@ -469,60 +478,29 @@ static int igb_alloc_queues(struct igb_adapter *adapter) { struct igb_ring *ring; int i; -#ifdef HAVE_DEVICE_NUMA_NODE - int orig_node = adapter->node; -#endif /* HAVE_DEVICE_NUMA_NODE */ for (i = 0; i < adapter->num_tx_queues; i++) { -#ifdef HAVE_DEVICE_NUMA_NODE - if (orig_node == -1) { - int cur_node = next_online_node(adapter->node); - if (cur_node == MAX_NUMNODES) - cur_node = first_online_node; - adapter->node = cur_node; - } -#endif /* HAVE_DEVICE_NUMA_NODE */ - ring = kzalloc_node(sizeof(struct igb_ring), GFP_KERNEL, - adapter->node); - if (!ring) - ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); + ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); if (!ring) goto err; ring->count = adapter->tx_ring_count; ring->queue_index = i; ring->dev = pci_dev_to_dev(adapter->pdev); ring->netdev = adapter->netdev; - ring->numa_node = adapter->node; /* For 82575, context index must be unique per ring. */ if (adapter->hw.mac.type == e1000_82575) set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); adapter->tx_ring[3-i] = ring; /* I210 rebase */ } -#ifdef HAVE_DEVICE_NUMA_NODE - /* Restore the adapter's original node */ - adapter->node = orig_node; -#endif /* HAVE_DEVICE_NUMA_NODE */ for (i = 0; i < adapter->num_rx_queues; i++) { -#ifdef HAVE_DEVICE_NUMA_NODE - if (orig_node == -1) { - int cur_node = next_online_node(adapter->node); - if (cur_node == MAX_NUMNODES) - cur_node = first_online_node; - adapter->node = cur_node; - } -#endif /* HAVE_DEVICE_NUMA_NODE */ - ring = kzalloc_node(sizeof(struct igb_ring), GFP_KERNEL, - adapter->node); - if (!ring) - ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); + ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); if (!ring) goto err; ring->count = adapter->rx_ring_count; ring->queue_index = i; ring->dev = pci_dev_to_dev(adapter->pdev); ring->netdev = adapter->netdev; - ring->numa_node = adapter->node; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT ring->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; #endif @@ -535,29 +513,18 @@ static int igb_alloc_queues(struct igb_adapter *adapter) if (adapter->hw.mac.type >= e1000_82576) set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); - /* - * On i350, i210, and i211, loopback VLAN packets - * have the tag byte-swapped. - * */ - if (adapter->hw.mac.type >= e1000_i350) + /* On i350, loopback VLAN packets have the tag byte-swapped */ + if (adapter->hw.mac.type == e1000_i350) set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); adapter->rx_ring[i] = ring; } -#ifdef HAVE_DEVICE_NUMA_NODE - /* Restore the adapter's original node */ - adapter->node = orig_node; -#endif /* HAVE_DEVICE_NUMA_NODE */ igb_cache_ring_register(adapter); return E1000_SUCCESS; err: -#ifdef HAVE_DEVICE_NUMA_NODE - /* Restore the adapter's original node */ - adapter->node = orig_node; -#endif /* HAVE_DEVICE_NUMA_NODE */ igb_free_queues(adapter); return -ENOMEM; @@ -781,7 +748,7 @@ static int igb_request_msix(struct igb_adapter *adapter) int i, err = 0, vector = 0; err = request_irq(adapter->msix_entries[vector].vector, - igb_msix_other, 0, netdev->name, adapter); + &igb_msix_other, 0, netdev->name, adapter); if (err) goto out; vector++; @@ -907,9 +874,9 @@ static void igb_process_mdd_event(struct igb_adapter *adapter) vfre &= ~(1 << vf_queue); E1000_WRITE_REG(hw, E1000_VFRE, vfre); - /* Disable MDFB related bit */ + /* Disable MDFB related bit. Clear on write */ mdfb = E1000_READ_REG(hw, E1000_MDFB); - mdfb &= ~(1 << vf_queue); + mdfb |= (1 << vf_queue); E1000_WRITE_REG(hw, E1000_MDFB, mdfb); /* Reset the specific VF */ @@ -941,14 +908,13 @@ static void igb_disable_mdd(struct igb_adapter *adapter) * * Enable the HW to detect malicious driver and sends an interrupt to * the driver. - * - * Only available on i350 device **/ static void igb_enable_mdd(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 reg; + /* Only available on i350 device */ if (hw->mac.type != e1000_i350) return; @@ -1158,28 +1124,9 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter) struct igb_q_vector *q_vector; struct e1000_hw *hw = &adapter->hw; int v_idx; -#ifdef HAVE_DEVICE_NUMA_NODE - int orig_node = adapter->node; -#endif /* HAVE_DEVICE_NUMA_NODE */ for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { -#ifdef HAVE_DEVICE_NUMA_NODE - if ((adapter->num_q_vectors == (adapter->num_rx_queues + - adapter->num_tx_queues)) && - (adapter->num_rx_queues == v_idx)) - adapter->node = orig_node; - if (orig_node == -1) { - int cur_node = next_online_node(adapter->node); - if (cur_node == MAX_NUMNODES) - cur_node = first_online_node; - adapter->node = cur_node; - } -#endif /* HAVE_DEVICE_NUMA_NODE */ - q_vector = kzalloc_node(sizeof(struct igb_q_vector), GFP_KERNEL, - adapter->node); - if (!q_vector) - q_vector = kzalloc(sizeof(struct igb_q_vector), - GFP_KERNEL); + q_vector = kzalloc(sizeof(struct igb_q_vector), GFP_KERNEL); if (!q_vector) goto err_out; q_vector->adapter = adapter; @@ -1190,8 +1137,6 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter) #ifndef IGB_NO_LRO if (v_idx < adapter->num_rx_queues) { int size = sizeof(struct igb_lro_list); - q_vector->lrolist = vzalloc_node(size, q_vector->numa_node); - if (!q_vector->lrolist) q_vector->lrolist = vzalloc(size); if (!q_vector->lrolist) goto err_out; @@ -1199,18 +1144,10 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter) } #endif /* IGB_NO_LRO */ } -#ifdef HAVE_DEVICE_NUMA_NODE - /* Restore the adapter's original node */ - adapter->node = orig_node; -#endif /* HAVE_DEVICE_NUMA_NODE */ return 0; err_out: -#ifdef HAVE_DEVICE_NUMA_NODE - /* Restore the adapter's original node */ - adapter->node = orig_node; -#endif /* HAVE_DEVICE_NUMA_NODE */ igb_free_q_vectors(adapter); return -ENOMEM; } @@ -1577,12 +1514,12 @@ static void igb_configure(struct igb_adapter *adapter) **/ void igb_power_up_link(struct igb_adapter *adapter) { + e1000_phy_hw_reset(&adapter->hw); if (adapter->hw.phy.media_type == e1000_media_type_copper) e1000_power_up_phy(&adapter->hw); else e1000_power_up_fiber_serdes_link(&adapter->hw); - e1000_phy_hw_reset(&adapter->hw); } /** @@ -1700,7 +1637,6 @@ void igb_down(struct igb_adapter *adapter) /* since we reset the hardware DCA settings were cleared */ igb_setup_dca(adapter); #endif - igb_setup_tph(adapter); } void igb_reinit_locked(struct igb_adapter *adapter) @@ -1713,94 +1649,13 @@ void igb_reinit_locked(struct igb_adapter *adapter) clear_bit(__IGB_RESETTING, &adapter->state); } -static void igb_setup_flex_filter(struct igb_adapter *adapter, int filter_id, - int filter_len, u8 *filter, u8 *mask) -{ - struct e1000_hw *hw = &adapter->hw; - int i = 0, j, k; - u32 fhft; - - while (i < filter_len) { - for (j = 0; j < 8; j+= 4) { - fhft = 0; - for (k = 0; k < 4; k++) - fhft |= ((u32)(filter[i + j + k])) << (k * 8); - E1000_WRITE_REG_ARRAY(hw, E1000_FHFT(filter_id), - (i/2) + (j/4), fhft); - } - E1000_WRITE_REG_ARRAY(hw, E1000_FHFT(filter_id), - (i/2) + 2, mask[i/8]); - i += 8; - } - E1000_WRITE_REG_ARRAY(hw, E1000_FHFT(filter_id), - 63, filter_len); - E1000_WRITE_FLUSH(hw); -} - -static void igb_setup_flex_filter_wakeup(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u8 pattern[64]; - u8 mask[8]; - - /* clear pattern to match and mask */ - memset(pattern, 0, 64); - memset(mask, 0, 8); - - /* - * This pattern is set to match on the following in a packet: - * 0x00: xx xx xx xx xx xx xx xx xx xx xx xx 08 00 45 00 - * 0x10: xx xx xx xx xx xx xx 11 xx xx xx xx xx xx xx xx - * 0x20: xx xx xx xx 00 07 00 86 xx xx ff ff ff ff ff ff - * 0x30: m0 m1 m2 m3 m4 m5 xx xx xx xx xx xx xx xx xx xx - * - * Where m0-m5 are the 6 bytes of the mac address in network order - */ - - /* ethertype should be IP which is 0x8000 */ - pattern[0x0C] = 0x08; - pattern[0x0D] = 0x00; - - /* verify IPv4 and header length 20 */ - pattern[0x0E] = 0x45; - pattern[0x0F] = 0x00; - mask[1] = 0xF0; - - /* verify L3 protocol is UDP */ - pattern[0x17] = 0x11; - mask[2] = 0x80; - - /* verify source and destination port numbers */ - pattern[0x24] = 0x00; - pattern[0x25] = 0x07; - pattern[0x26] = 0x00; - pattern[0x27] = 0x86; - mask[4] = 0xF0; - - /* add start pattern of 6 bytes all 0xFF */ - memset(&pattern[0x2a], 0xff, 6); - mask[5] = 0xFC; - - /* add mac address */ - memcpy(&pattern[0x30], hw->mac.addr, 6); - mask[6] |= 0x3F; - - E1000_WRITE_REG(hw, E1000_WUC, 0); - E1000_WRITE_REG(hw, E1000_WUFC, 0); - - igb_setup_flex_filter(adapter, 0, 64, pattern, mask); - - E1000_WRITE_REG(hw, E1000_WUC, E1000_WUC_PME_EN); - E1000_WRITE_REG(hw, E1000_WUFC, E1000_WUFC_FLX0); -} void igb_reset(struct igb_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &hw->mac; struct e1000_fc_info *fc = &hw->fc; - u32 pba = 0, tx_space, min_tx_space, min_rx_space; - u16 hwm; + u32 pba = 0, tx_space, min_tx_space, min_rx_space, hwm; /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. @@ -1875,7 +1730,7 @@ void igb_reset(struct igb_adapter *adapter) hwm = min(((pba << 10) * 9 / 10), ((pba << 10) - 2 * adapter->max_frame_size)); - fc->high_water = hwm & 0xFFF0; /* 16-byte granularity */ + fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */ fc->low_water = fc->high_water - 16; fc->pause_time = 0xFFFF; fc->send_xon = 1; @@ -1905,11 +1760,21 @@ void igb_reset(struct igb_adapter *adapter) if (e1000_init_hw(hw)) dev_err(pci_dev_to_dev(pdev), "Hardware Error\n"); + /* + * Flow control settings reset on hardware reset, so guarantee flow + * control is off when forcing speed. + */ + if (!hw->mac.autoneg) + e1000_force_mac_fc(hw); igb_init_dmac(adapter, pba); - /* External thermal sensor support is limited to certain i350 devices */ - if (adapter->ets) { - /* Re-initialize external thermal sensor interface */ + /* Re-initialize the thermal sensor on i350 devices. */ + if (mac->type == e1000_i350 && hw->bus.func == 0) { + /* + * If present, re-initialize the external thermal sensor + * interface. + */ + if (adapter->ets) e1000_set_i2c_bb(hw); e1000_init_thermal_sensor_thresh(hw); } @@ -1924,7 +1789,10 @@ void igb_reset(struct igb_adapter *adapter) /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ E1000_WRITE_REG(hw, E1000_VET, ETHERNET_IEEE_VLAN_TYPE); - igb_setup_flex_filter_wakeup(adapter); +#ifdef CONFIG_PTP + /* Re-enable PTP, where applicable. */ + igb_ptp_reset(adapter); +#endif /* CONFIG_IGB_PTP */ e1000_get_phy_info(hw); } @@ -2087,6 +1955,45 @@ int igb_remove_vmdq_netdevs(struct igb_adapter *adapter) #endif /* CONFIG_IGB_VMDQ_NETDEV */ /** + * igb_set_fw_version - Configure version string for ethtool + * @adapter: adapter struct + * + **/ +static void igb_set_fw_version(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_fw_version fw; + + e1000_get_fw_version(hw, &fw); + + switch (hw->mac.type) { + case e1000_i211: + snprintf(adapter->fw_version, sizeof(adapter->fw_version), + "%2d.%2d-%d", + fw.invm_major, fw.invm_minor, fw.invm_img_type); + break; + default: + /* if option rom is valid, display its version too*/ + if (fw.or_valid) { + snprintf(adapter->fw_version, + sizeof(adapter->fw_version), + "%d.%d, 0x%08x, %d.%d.%d", + fw.eep_major, fw.eep_minor, fw.etrack_id, + fw.or_major, fw.or_build, fw.or_patch); + /* no option rom */ + } else { + snprintf(adapter->fw_version, + sizeof(adapter->fw_version), + "%d.%d, 0x%08x", + fw.eep_major, fw.eep_minor, fw.etrack_id); + } + break; + } + + return; +} + +/** * igb_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in igb_pci_tbl @@ -2236,11 +2143,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, /* Copper options */ if (hw->phy.media_type == e1000_media_type_copper) { -#ifdef ETH_TP_MDI_X - hw->phy.mdix = ETH_TP_MDI_INVALID; -#else hw->phy.mdix = AUTO_ALL_MODES; -#endif /* ETH_TP_MDI_X */ hw->phy.disable_polarity_correction = FALSE; hw->phy.ms_type = e1000_ms_hw_default; } @@ -2308,6 +2211,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_SCTP_CSUM; adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); +#ifdef DEBUG + if (adapter->dmac != IGB_DMAC_DISABLE) + printk("%s: DMA Coalescing is enabled..\n", netdev->name); +#endif /* before reading the NVM, reset the controller to put the device in a * known good starting state */ @@ -2343,7 +2250,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, igb_rar_set(adapter, 0); /* get firmware version for ethtool -i */ - e1000_read_nvm(&adapter->hw, 5, 1, &adapter->fw_version); + igb_set_fw_version(adapter); setup_timer(&adapter->watchdog_timer, &igb_watchdog, (unsigned long) adapter); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) @@ -2371,9 +2278,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, * enable the ACPI Magic Packet filter */ - if (hw->bus.func == 0) - e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - else if (hw->mac.type >= e1000_82580) + /* Check the NVM for wake support for non-port A ports */ + if (hw->mac.type >= e1000_82580) hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, &eeprom_data); @@ -2381,14 +2287,14 @@ static int __devinit igb_probe(struct pci_dev *pdev, e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); if (eeprom_data & IGB_EEPROM_APME) - adapter->eeprom_wol |= E1000_WUFC_MAG; + adapter->wol_supported = true; /* now that we have the eeprom settings, apply the special cases where * the eeprom may be wrong or the board simply won't support wake on * lan on a particular port */ switch (pdev->device) { case E1000_DEV_ID_82575GB_QUAD_COPPER: - adapter->eeprom_wol = 0; + adapter->wol_supported = false; break; case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82576_FIBER: @@ -2396,24 +2302,39 @@ static int __devinit igb_probe(struct pci_dev *pdev, /* Wake events only supported on port A for dual fiber * regardless of eeprom setting */ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) - adapter->eeprom_wol = 0; + adapter->wol_supported = false; break; case E1000_DEV_ID_82576_QUAD_COPPER: case E1000_DEV_ID_82576_QUAD_COPPER_ET2: /* if quad port adapter, disable WoL on all but port A */ if (global_quad_port_a != 0) - adapter->eeprom_wol = 0; + adapter->wol_supported = false; else adapter->flags |= IGB_FLAG_QUAD_PORT_A; /* Reset for multiple quad port adapters */ if (++global_quad_port_a == 4) global_quad_port_a = 0; break; + default: + /* For all other devices, support wake on port A */ + if (hw->bus.func == 0) + adapter->wol_supported = true; + break; } /* initialize the wol settings based on the eeprom settings */ - adapter->wol = adapter->eeprom_wol; - device_set_wakeup_enable(pci_dev_to_dev(adapter->pdev), adapter->wol); + if (adapter->wol_supported) + adapter->wol |= E1000_WUFC_MAG; + + /* Some vendors want WoL disabled by default, but still supported */ + if ((hw->mac.type == e1000_i350) && + (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) { + adapter->wol_supported = true; + adapter->wol = 0; + } + + device_set_wakeup_enable(pci_dev_to_dev(adapter->pdev), + adapter->wol_supported); /* reset the hardware with the new settings */ igb_reset(adapter); @@ -2454,9 +2375,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5GT/s" : (hw->bus.speed == e1000_bus_speed_5000) ? "5.0GT/s" : "unknown"), - ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4\n" : - (hw->bus.width == e1000_bus_width_pcie_x2) ? "Width x2\n" : - (hw->bus.width == e1000_bus_width_pcie_x1) ? "Width x1\n" : + ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : + (hw->bus.width == e1000_bus_width_pcie_x2) ? "Width x2" : + (hw->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" : "unknown")); dev_info(pci_dev_to_dev(pdev), "%s: MAC: ", netdev->name); for (i = 0; i < 6; i++) @@ -2469,27 +2390,26 @@ static int __devinit igb_probe(struct pci_dev *pdev, pba_str); - /* External thermal sensor support is limited to certain i350 devices */ + /* Initialize the thermal sensor on i350 devices. */ if (hw->mac.type == e1000_i350 && hw->bus.func == 0) { u16 ets_word; /* - * Read the external sensor to determine if this i350 device - * supports an external thermal sensor + * Read the NVM to determine if this i350 device supports an + * external thermal sensor. */ e1000_read_nvm(hw, NVM_ETS_CFG, 1, &ets_word); - if (ets_word != 0x0000 && ets_word != 0xFFFF) { + if (ets_word != 0x0000 && ets_word != 0xFFFF) adapter->ets = true; + else + adapter->ets = false; #ifdef IGB_SYSFS - igb_sysfs_init(adapter); + igb_sysfs_init(adapter); #else #ifdef IGB_PROCFS - igb_procfs_init(adapter); + igb_procfs_init(adapter); #endif /* IGB_PROCFS */ #endif /* IGB_SYSFS */ - } else { - adapter->ets = false; - } } else { adapter->ets = false; } @@ -2568,10 +2488,8 @@ static void __devexit igb_remove(struct pci_dev *pdev) igb_ptp_stop(adapter); #endif /* CONFIG_IGB_PTP */ - /* - * The watchdog timer may be rescheduled, so explicitly - * disable watchdog from being rescheduled. - */ + /* flush_scheduled work may reschedule our watchdog task, so + * explicitly disable watchdog tasks from being rescheduled */ set_bit(__IGB_DOWN, &adapter->state); del_timer_sync(&adapter->watchdog_timer); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) @@ -2607,13 +2525,6 @@ static void __devexit igb_remove(struct pci_dev *pdev) pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); - kfree(adapter->mac_table); - kfree(adapter->shadow_vfta); - free_netdev(netdev); - - pci_disable_pcie_error_reporting(pdev); - - pci_disable_device(pdev); #ifdef IGB_SYSFS igb_sysfs_exit(adapter); @@ -2622,6 +2533,13 @@ static void __devexit igb_remove(struct pci_dev *pdev) igb_procfs_exit(adapter); #endif /* IGB_PROCFS */ #endif /* IGB_SYSFS */ + kfree(adapter->mac_table); + kfree(adapter->shadow_vfta); + free_netdev(netdev); + + pci_disable_pcie_error_reporting(pdev); + + pci_disable_device(pdev); } /** @@ -2857,12 +2775,9 @@ static int igb_close(struct net_device *netdev) int igb_setup_tx_resources(struct igb_ring *tx_ring) { struct device *dev = tx_ring->dev; - int orig_node = dev_to_node(dev); int size; size = sizeof(struct igb_tx_buffer) * tx_ring->count; - tx_ring->tx_buffer_info = vzalloc_node(size, tx_ring->numa_node); - if (!tx_ring->tx_buffer_info) tx_ring->tx_buffer_info = vzalloc(size); if (!tx_ring->tx_buffer_info) goto err; @@ -2871,17 +2786,8 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring) tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); - set_dev_node(dev, tx_ring->numa_node); - tx_ring->desc = dma_alloc_coherent(dev, - tx_ring->size, - &tx_ring->dma, - GFP_KERNEL); - set_dev_node(dev, orig_node); - if (!tx_ring->desc) - tx_ring->desc = dma_alloc_coherent(dev, - tx_ring->size, - &tx_ring->dma, - GFP_KERNEL); + tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, + &tx_ring->dma, GFP_KERNEL); if (!tx_ring->desc) goto err; @@ -3011,13 +2917,10 @@ static void igb_configure_tx(struct igb_adapter *adapter) int igb_setup_rx_resources(struct igb_ring *rx_ring) { struct device *dev = rx_ring->dev; - int orig_node = dev_to_node(dev); int size, desc_len; size = sizeof(struct igb_rx_buffer) * rx_ring->count; - rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node); - if (!rx_ring->rx_buffer_info) - rx_ring->rx_buffer_info = vzalloc(size); + rx_ring->rx_buffer_info = vzalloc(size); if (!rx_ring->rx_buffer_info) goto err; @@ -3027,17 +2930,8 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring) rx_ring->size = rx_ring->count * desc_len; rx_ring->size = ALIGN(rx_ring->size, 4096); - set_dev_node(dev, rx_ring->numa_node); - rx_ring->desc = dma_alloc_coherent(dev, - rx_ring->size, - &rx_ring->dma, - GFP_KERNEL); - set_dev_node(dev, orig_node); - if (!rx_ring->desc) - rx_ring->desc = dma_alloc_coherent(dev, - rx_ring->size, - &rx_ring->dma, - GFP_KERNEL); + rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, + &rx_ring->dma, GFP_KERNEL); if (!rx_ring->desc) goto err; @@ -3227,10 +3121,6 @@ void igb_setup_rctl(struct igb_adapter *adapter) /* enable LPE to prevent packets larger than max_frame_size */ rctl |= E1000_RCTL_LPE; - /* enable store bad packets for SV driver only */ - rctl |= E1000_RCTL_SBP; - /* initalize counter for other SV stuff */ - adapter->count = 0; /* disable queue 0 to prevent tail write w/o re-config */ E1000_WRITE_REG(hw, E1000_RXDCTL(0), 0); @@ -3402,7 +3292,11 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, srrctl |= (PAGE_SIZE / 2) >> E1000_SRRCTL_BSIZEPKT_SHIFT; #endif srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; -#endif +#else /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ + srrctl = ALIGN(ring->rx_buffer_len, 1024) >> + E1000_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; +#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ #ifdef CONFIG_PTP if (hw->mac.type >= e1000_82580) srrctl |= E1000_SRRCTL_TIMESTAMP; @@ -4097,10 +3991,6 @@ static void igb_watchdog_task(struct work_struct *work) if (hw->mac.type == e1000_i350) { thstat = E1000_READ_REG(hw, E1000_THSTAT); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - printk("%s: Checking for Thermal Status..thstat=%x \n", - netdev->name, thstat); - printk("%s: Thermal Status..ctrl_ext=%x \n", - netdev->name, ctrl_ext); if ((hw->phy.media_type == e1000_media_type_copper) && !(ctrl_ext & @@ -4630,7 +4520,7 @@ static __le32 igb_tx_cmd_type(u32 tx_flags) #ifdef CONFIG_PTP /* set timestamp bit if present */ - if (tx_flags & IGB_TX_FLAGS_TSTAMP) + if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP)) cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP); #endif /* CONFIG_IGB_PTP */ @@ -4852,8 +4742,8 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, struct igb_ring *tx_ring) { #ifdef CONFIG_PTP - struct igb_adapter *adapter = tx_ring->q_vector->adapter; -#endif /* CONFIG_IGB_PTP */ + struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); +#endif /* CONFIG_PTP */ struct igb_tx_buffer *first; int tso; u32 tx_flags = 0; @@ -5045,11 +4935,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) adapter->max_frame_size = max_frame; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT -#ifdef IGB_PER_PKT_TIMESTAMP - if (adapter->hw.mac.type >= e1000_82580) - max_frame += IGB_TS_HDR_LEN; - -#endif /* * RLPML prevents us from receiving a frame larger than max_frame so * it is safe to just set the rx_buffer_len to max_frame without the @@ -5191,7 +5076,6 @@ void igb_update_stats(struct igb_adapter *adapter) adapter->stats.prc1522 += E1000_READ_REG(hw, E1000_PRC1522); adapter->stats.symerrs += E1000_READ_REG(hw, E1000_SYMERRS); adapter->stats.sec += E1000_READ_REG(hw, E1000_SEC); - adapter->dmac_entries += E1000_READ_REG(hw, E1000_DMACDC); mpc = E1000_READ_REG(hw, E1000_MPC); adapter->stats.mpc += mpc; @@ -5236,6 +5120,9 @@ void igb_update_stats(struct igb_adapter *adapter) reg = E1000_READ_REG(hw, E1000_CTRL_EXT); if (!(reg & E1000_CTRL_EXT_LINK_MODE_MASK)) { adapter->stats.rxerrc += E1000_READ_REG(hw, E1000_RXERRC); + /* this stat has invalid values on i210/i211 */ + if ((hw->mac.type != e1000_i210) && + (hw->mac.type != e1000_i211)) adapter->stats.tncrs += E1000_READ_REG(hw, E1000_TNCRS); } @@ -5333,9 +5220,12 @@ static irqreturn_t igb_msix_other(int irq, void *data) if (icr & E1000_ICR_TS) { u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); - if (tsicr & E1000_TSICR_TXTS) + if (tsicr & E1000_TSICR_TXTS) { + /* acknowledge the interrupt */ + E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); /* retrieve hardware timestamp */ - igb_ptp_tx_hwtstamp(adapter); + schedule_work(&adapter->ptp_tx_work); + } } #endif /* CONFIG_PTP */ /* Check for MDD event */ @@ -5347,57 +5237,6 @@ static irqreturn_t igb_msix_other(int irq, void *data) return IRQ_HANDLED; } -static void igb_update_tph(struct igb_q_vector *q_vector) -{ - struct igb_adapter *adapter = q_vector->adapter; - struct e1000_hw *hw = &adapter->hw; - int cpu = get_cpu(); - int tag = ~(cpu / 8) & 0x7; // JKT 2-socket system - - if (q_vector->cpu == cpu) - goto out_no_update; - - if (q_vector->tx.ring) { - int q = q_vector->tx.ring->reg_idx; - u32 dca_txctrl = E1000_READ_REG(hw, E1000_DCA_TXCTRL(q)); - dca_txctrl &= ~E1000_TPH_TXCTRL_CPUID_MASK; - dca_txctrl |= tag << E1000_DCA_TXCTRL_CPUID_SHIFT_82576; -// dca_txctrl |= E1000_TPH_TXCTRL_FTCH_DCA_EN; - dca_txctrl |= E1000_TPH_TXCTRL_DESC_DCA_EN; -// dca_txctrl |= E1000_TPH_TXCTRL_DATA_DCA_EN; -// dca_txctrl |= E1000_TPH_TXCTRL_AUTOLEARN_EN; - E1000_WRITE_REG(hw, E1000_DCA_TXCTRL(q), dca_txctrl); - } - if (q_vector->rx.ring) { - int q = q_vector->rx.ring->reg_idx; - u32 dca_rxctrl = E1000_READ_REG(hw, E1000_DCA_RXCTRL(q)); - dca_rxctrl &= ~E1000_TPH_RXCTRL_CPUID_MASK; - dca_rxctrl |= tag << E1000_DCA_RXCTRL_CPUID_SHIFT_82576; -// dca_rxctrl |= E1000_TPH_RXCTRL_FTCH_DCA_EN; - dca_rxctrl |= E1000_TPH_RXCTRL_DESC_DCA_EN; - dca_rxctrl |= E1000_TPH_RXCTRL_HEAD_DCA_EN; - dca_rxctrl |= E1000_TPH_RXCTRL_DATA_DCA_EN; -// dca_rxctrl |= E1000_TPH_RXCTRL_AUTOLEARN_EN; - E1000_WRITE_REG(hw, E1000_DCA_RXCTRL(q), dca_rxctrl); - } - q_vector->cpu = cpu; -out_no_update: - put_cpu(); -} - -static void igb_setup_tph(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - int i; - - /* Disable DCA, enable TPH read hint mode, and set TPH Data PH mode */ - E1000_WRITE_REG(hw, E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_DISABLE | E1000_DCA_CTRL_TPH_DATA_PH); - - for (i = 0; i < adapter->num_q_vectors; i++) { - adapter->q_vector[i]->cpu = -1; - igb_update_tph(adapter->q_vector[i]); - } -} static void igb_write_itr(struct igb_q_vector *q_vector) { struct igb_adapter *adapter = q_vector->adapter; @@ -6274,11 +6113,14 @@ static irqreturn_t igb_intr_msi(int irq, void *data) if (icr & E1000_ICR_TS) { u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); - if (tsicr & E1000_TSICR_TXTS) + if (tsicr & E1000_TSICR_TXTS) { + /* acknowledge the interrupt */ + E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); /* retrieve hardware timestamp */ - igb_ptp_tx_hwtstamp(adapter); + schedule_work(&adapter->ptp_tx_work); + } } -#endif /* CONFIG_PTP */ +#endif /* CONFIG_IGB_PTP */ napi_schedule(&q_vector->napi); @@ -6325,9 +6167,12 @@ static irqreturn_t igb_intr(int irq, void *data) if (icr & E1000_ICR_TS) { u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); - if (tsicr & E1000_TSICR_TXTS) + if (tsicr & E1000_TSICR_TXTS) { + /* acknowledge the interrupt */ + E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); /* retrieve hardware timestamp */ - igb_ptp_tx_hwtstamp(adapter); + schedule_work(&adapter->ptp_tx_work); + } } #endif /* CONFIG_PTP */ @@ -6439,7 +6284,6 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) /* free the skb */ dev_kfree_skb_any(tx_buffer->skb); - tx_buffer->skb = NULL; /* unmap skb header data */ dma_unmap_single(tx_ring->dev, @@ -6495,7 +6339,12 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) q_vector->tx.total_bytes += total_bytes; q_vector->tx.total_packets += total_packets; +#ifdef DEBUG + if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags) && + !(adapter->disable_hw_reset && adapter->tx_hang_detected)) { +#else if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { +#endif struct e1000_hw *hw = &adapter->hw; eop_desc = tx_buffer->next_to_watch; @@ -6510,6 +6359,18 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) E1000_STATUS_TXOFF)) { /* detected Tx unit hang */ +#ifdef DEBUG + adapter->tx_hang_detected = TRUE; + if (adapter->disable_hw_reset) { + DPRINTK(DRV, WARNING, + "Deactivating netdev watchdog timer\n"); + if (del_timer(&netdev_ring(tx_ring)->watchdog_timer)) + dev_put(netdev_ring(tx_ring)); +#ifndef HAVE_NET_DEVICE_OPS + netdev_ring(tx_ring)->tx_timeout = NULL; +#endif + } +#endif /* DEBUG */ dev_err(tx_ring->dev, "Detected Tx Unit Hang\n" " Tx Queue <%d>\n" @@ -6631,7 +6492,6 @@ static inline void igb_rx_checksum(struct igb_ring *ring, if (igb_test_staterr(rx_desc, E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) skb->ip_summed = CHECKSUM_UNNECESSARY; - ring->rx_stats.csum_good++; } #ifdef NETIF_F_RXHASH @@ -6642,8 +6502,8 @@ static inline void igb_rx_hash(struct igb_ring *ring, if (netdev_ring(ring)->features & NETIF_F_RXHASH) skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); } -#endif +#endif static void igb_rx_vlan(struct igb_ring *ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) @@ -7189,7 +7049,7 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) skb->len += length; skb->data_len += length; - skb->truesize += length; + skb->truesize += PAGE_SIZE / 2; if ((page_count(buffer_info->page) != 1) || (page_to_nid(buffer_info->page) != current_node)) @@ -7229,15 +7089,6 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) igb_rx_checksum(rx_ring, rx_desc, skb); igb_rx_vlan(rx_ring, rx_desc, skb); - if (rx_desc->wb.lower.lo_dword.hs_rss.hdr_info & - cpu_to_le16(E1000_RXDADV_SPH)) - rx_ring->rx_stats.rx_hdr_split++; - if (igb_test_staterr(rx_desc, E1000_RXDADV_ERR_HBO)) - printk("igb_rx:HBO bit set..\n"); - if (igb_test_staterr(rx_desc, E1000_RXD_STAT_DYNINT)) - rx_ring->rx_stats.lli_int++; - if (igb_test_staterr(rx_desc, E1000_RXD_STAT_PIF)) - rx_ring->rx_stats.pif_count++; total_bytes += skb->len; total_packets++; @@ -7460,7 +7311,7 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) default: return -EOPNOTSUPP; } - return 0; + return E1000_SUCCESS; } #endif /** @@ -7482,6 +7333,10 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) case SIOCSHWTSTAMP: return igb_ptp_hwtstamp_ioctl(netdev, ifr, cmd); #endif /* CONFIG_IGB_PTP */ +#ifdef ETHTOOL_OPS_COMPAT + case SIOCETHTOOL: + return ethtool_ioctl(ifr); +#endif default: return -EOPNOTSUPP; } @@ -7539,6 +7394,10 @@ void igb_vlan_mode(struct net_device *netdev, u32 features) #endif if (enable) { + /* enable VLAN tag insert/strip */ + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= E1000_CTRL_VME; + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Disable CFI check */ rctl = E1000_READ_REG(hw, E1000_RCTL); @@ -7685,9 +7544,13 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) mac->autoneg = 0; - /* Fiber NIC's only allow 1000 gbps Full duplex */ - if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes ) && - spddplx != (SPEED_1000 + DUPLEX_FULL)) { + /* + * Fiber NIC's only allow 1000 gbps Full duplex + * and 100Mbps Full duplex for 100baseFx sfp + */ + if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) + if (spddplx != (SPEED_1000 + DUPLEX_FULL) || + spddplx != (SPEED_100 + DUPLEX_FULL)) { dev_err(pci_dev_to_dev(pdev), "Unsupported Speed/Duplex configuration\n"); return -EINVAL; @@ -7715,6 +7578,8 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) dev_err(pci_dev_to_dev(pdev), "Unsupported Speed/Duplex configuration\n"); return -EINVAL; } + /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ + adapter->hw.phy.mdix = AUTO_ALL_MODES; return 0; } @@ -7731,6 +7596,9 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, #endif netif_device_detach(netdev); + status = E1000_READ_REG(hw, E1000_STATUS); + if (status & E1000_STATUS_LU) + wufc &= ~E1000_WUFC_LNKC; if (netif_running(netdev)) __igb_close(netdev, true); @@ -7743,10 +7611,6 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, return retval; #endif - status = E1000_READ_REG(hw, E1000_STATUS); - if (status & E1000_STATUS_LU) - wufc &= ~E1000_WUFC_LNKC; - if (wufc) { igb_setup_rctl(adapter); igb_set_rx_mode(netdev); @@ -7792,10 +7656,15 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, #ifdef CONFIG_PM #ifdef HAVE_SYSTEM_SLEEP_PM_OPS static int igb_suspend(struct device *dev) +#else +static int igb_suspend(struct pci_dev *pdev, pm_message_t state) +#endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ { +#ifdef HAVE_SYSTEM_SLEEP_PM_OPS + struct pci_dev *pdev = to_pci_dev(dev); +#endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ int retval; bool wake; - struct pci_dev *pdev = to_pci_dev(dev); retval = __igb_shutdown(pdev, &wake, 0); if (retval) @@ -7811,9 +7680,15 @@ static int igb_suspend(struct device *dev) return 0; } +#ifdef HAVE_SYSTEM_SLEEP_PM_OPS static int igb_resume(struct device *dev) +#else +static int igb_resume(struct pci_dev *pdev) +#endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ { +#ifdef HAVE_SYSTEM_SLEEP_PM_OPS struct pci_dev *pdev = to_pci_dev(dev); +#endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -7874,6 +7749,7 @@ static int igb_resume(struct device *dev) } #ifdef CONFIG_PM_RUNTIME +#ifdef HAVE_SYSTEM_SLEEP_PM_OPS static int igb_runtime_idle(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -7910,8 +7786,8 @@ static int igb_runtime_resume(struct device *dev) { return igb_resume(dev); } -#endif /* CONFIG_PM_RUNTIME */ #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ +#endif /* CONFIG_PM_RUNTIME */ #endif /* CONFIG_PM */ #ifdef USE_REBOOT_NOTIFIER @@ -8334,8 +8210,6 @@ static void igb_vmm_control(struct igb_adapter *adapter) switch (hw->mac.type) { case e1000_82575: - case e1000_i210: - case e1000_i211: default: /* replication is not supported for 82575 */ return; @@ -8364,8 +8238,8 @@ static void igb_vmm_control(struct igb_adapter *adapter) e1000_vmdq_set_loopback_pf(hw, adapter->vfs_allocated_count || adapter->vmdq_pools); - e1000_vmdq_set_anti_spoofing_pf(hw, adapter->vfs_allocated_count || - adapter->vmdq_pools, + e1000_vmdq_set_anti_spoofing_pf(hw, + adapter->vfs_allocated_count || adapter->vmdq_pools, adapter->vfs_allocated_count); e1000_vmdq_set_replication_pf(hw, adapter->vfs_allocated_count || adapter->vmdq_pools); @@ -8382,6 +8256,9 @@ static void igb_init_fw(struct igb_adapter *adapter) mask = E1000_SWFW_EEP_SM; else mask = E1000_SWFW_PHY0_SM; + /* i211 parts do not support this feature */ + if (hw->mac.type == e1000_i211) + hw->mac.arc_subsystem_valid = false; if (!hw->mac.ops.acquire_swfw_sync(hw, mask)) { for (i = 0; i <= FW_MAX_RETRIES; i++) { @@ -8391,6 +8268,7 @@ static void igb_init_fw(struct igb_adapter *adapter) fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CMD_RESERVED; fw_cmd.port_num = hw->bus.func; fw_cmd.drv_version = FW_FAMILY_DRV_VER; + fw_cmd.hdr.checksum = 0; fw_cmd.hdr.checksum = e1000_calculate_checksum((u8 *)&fw_cmd, (FW_HDR_LEN + fw_cmd.hdr.buf_len)); @@ -8411,6 +8289,9 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) u32 dmac_thr; u16 hwm; + if (hw->mac.type == e1000_i211) + return; + if (hw->mac.type > e1000_82580) { if (adapter->dmac != IGB_DMAC_DISABLE) { u32 reg; @@ -8449,6 +8330,11 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) /* watchdog timer= msec values in 32usec intervals */ reg |= ((adapter->dmac) >> 5); + /* + * Disable BMC-to-OS Watchdog enable + * on devices that support OS-to-BMC + */ + reg &= ~E1000_DMACR_DC_BMC2OSW_EN; E1000_WRITE_REG(hw, E1000_DMACR, reg); /* no lower threshold to disable coalescing(smart fifb)-UTRESH=0*/ @@ -8725,7 +8611,6 @@ static long igb_mapbuf(struct file *file, void __user *arg, int ring) ring->queue_index = req.queue; ring->dev = pci_dev_to_dev(adapter->pdev); ring->netdev = adapter->netdev; - ring->numa_node = adapter->node; adapter->tx_ring[req.queue] = ring; err = igb_setup_tx_resources(adapter->tx_ring[req.queue]); diff --git a/kmod/igb/igb_param.c b/kmod/igb/igb_param.c index 7b54dc3..39853cb 100644 --- a/kmod/igb/igb_param.c +++ b/kmod/igb/igb_param.c @@ -134,7 +134,7 @@ IGB_PARAM(LLISize, "Low Latency Interrupt on Packet Size (0-1500), default 0=off * * Default Value: 1 */ -IGB_PARAM(RSS, "Number of Receive-Side Scaling Descriptor Queues (0-8), default 1=number of cpus"); +IGB_PARAM(RSS, "Number of Receive-Side Scaling Descriptor Queues (0-8), default 1, 0=number of cpus"); #define DEFAULT_RSS 1 #define MAX_RSS 8 @@ -175,6 +175,25 @@ IGB_PARAM(max_vfs, "Number of Virtual Functions: 0 = disable, 1-7 enable, defaul IGB_PARAM(MDD, "Malicious Driver Detection (0/1), default 1 = enabled. " "Only available when max_vfs is greater than 0"); +#ifdef DEBUG + +/* Disable Hardware Reset on Tx Hang + * + * Valid Range: 0, 1 + * + * Default Value: 0 (disabled, i.e. h/w will reset) + */ +IGB_PARAM(DisableHwReset, "Disable reset of hardware on Tx hang"); + +/* Dump Transmit and Receive buffers + * + * Valid Range: 0, 1 + * + * Default Value: 0 + */ +IGB_PARAM(DumpBuffers, "Dump Tx/Rx buffers on Tx hang or by request"); + +#endif /* DEBUG */ /* QueuePairs (Enable TX/RX queue pairs for interrupt handling) * @@ -182,7 +201,7 @@ IGB_PARAM(MDD, "Malicious Driver Detection (0/1), default 1 = enabled. " * * Default Value: 1 */ -IGB_PARAM(QueuePairs, "Enable TX/RX queue pairs for interrupt handling (0,1), default 1=on"); +IGB_PARAM(QueuePairs, "Enable Tx/Rx queue pairs for interrupt handling (0,1), default 1=on"); #define DEFAULT_QUEUE_PAIRS 1 #define MAX_QUEUE_PAIRS 1 @@ -546,34 +565,41 @@ void __devinit igb_check_options(struct igb_adapter *adapter) .arg = { .r = { .min = MIN_RSS, .max = MAX_RSS } } }; - - if (adapter->vmdq_pools) { switch (hw->mac.type) { -#ifndef CONFIG_IGB_VMDQ_NETDEV - case e1000_82576: - opt.arg.r.max = 2; - break; case e1000_82575: +#ifndef CONFIG_IGB_VMDQ_NETDEV + if (!!adapter->vmdq_pools) { + if (adapter->vmdq_pools <= 2) { if (adapter->vmdq_pools == 2) opt.arg.r.max = 3; - if (adapter->vmdq_pools <= 2) - break; -#endif - default: + } else { opt.arg.r.max = 1; - break; } + } else { + opt.arg.r.max = 4; } - switch (hw->mac.type) { - case e1000_i211: - opt.arg.r.max = 2; +#else + opt.arg.r.max = !!adapter->vmdq_pools ? 1 : 4; +#endif /* CONFIG_IGB_VMDQ_NETDEV */ break; - case e1000_82575: case e1000_i210: opt.arg.r.max = 4; break; + case e1000_i211: + opt.arg.r.max = 2; + break; + case e1000_82576: +#ifndef CONFIG_IGB_VMDQ_NETDEV + if (!!adapter->vmdq_pools) + opt.arg.r.max = 2; + break; +#endif /* CONFIG_IGB_VMDQ_NETDEV */ + case e1000_82580: + case e1000_i350: default: + if (!!adapter->vmdq_pools) + opt.arg.r.max = 1; break; } @@ -598,10 +624,10 @@ void __devinit igb_check_options(struct igb_adapter *adapter) } #endif } - { /* QueuePairs - Enable TX/RX queue pairs for interrupt handling */ + { /* QueuePairs - Enable Tx/Rx queue pairs for interrupt handling */ struct igb_option opt = { .type = enable_option, - .name = "QueuePairs - TX/RX queue pairs for interrupt handling", + .name = "QueuePairs - Tx/Rx queue pairs for interrupt handling", .err = "defaulting to Enabled", .def = OPTION_ENABLED }; @@ -610,20 +636,31 @@ void __devinit igb_check_options(struct igb_adapter *adapter) #endif unsigned int qp = QueuePairs[bd]; /* - * we must enable queue pairs if the number of queues - * exceeds the number of avaialble interrupts. We are - * limited to 10, or 3 per unallocated vf. + * We must enable queue pairs if the number of queues + * exceeds the number of available interrupts. We are + * limited to 10, or 3 per unallocated vf. On I210 and + * I211 devices, we are limited to 5 interrupts. + * However, since I211 only supports 2 queues, we do not + * need to check and override the user option. */ - if ((adapter->rss_queues > 4) || - (adapter->vmdq_pools > 4) || - ((adapter->rss_queues > 1) && - ((adapter->vmdq_pools > 3) || - (adapter->vfs_allocated_count > 6)))) { if (qp == OPTION_DISABLED) { + if (adapter->rss_queues > 4) qp = OPTION_ENABLED; - DPRINTK(PROBE, INFO, - "Number of queues exceeds available interrupts, %s\n",opt.err); - } + if (adapter->vmdq_pools > 4) + qp = OPTION_ENABLED; + + if (adapter->rss_queues > 1 && + (adapter->vmdq_pools > 3 || + adapter->vfs_allocated_count > 6)) + qp = OPTION_ENABLED; + + if (hw->mac.type == e1000_i210 && + adapter->rss_queues > 2) + qp = OPTION_ENABLED; + + if (qp == OPTION_ENABLED) + DPRINTK(PROBE, INFO, "Number of queues exceeds available interrupts, %s\n", + opt.err); } igb_validate_option(&qp, &opt, adapter); adapter->flags |= qp ? IGB_FLAG_QUEUE_PAIRS : 0; @@ -773,52 +810,6 @@ void __devinit igb_check_options(struct igb_adapter *adapter) #endif } #endif /* IGB_NO_LRO */ - { /* Node assignment */ - static struct igb_option opt = { - .type = range_option, - .name = "Node to start on", - .err = "defaulting to -1", -#ifdef HAVE_EARLY_VMALLOC_NODE - .def = 0, -#else - .def = -1, -#endif - .arg = { .r = { .min = 0, - .max = (MAX_NUMNODES - 1)}} - }; - int node_param = opt.def; - - /* if the default was zero then we need to set the - * default value to an online node, which is not - * necessarily zero, and the constant initializer - * above can't take first_online_node */ - if (node_param == 0) - /* must set opt.def for validate */ - opt.def = node_param = first_online_node; - -#ifdef module_param_array - if (num_Node > bd) { -#endif - node_param = Node[bd]; - igb_validate_option((uint *)&node_param, &opt, adapter); - - if (node_param != OPTION_UNSET) { - DPRINTK(PROBE, INFO, "node set to %d\n", node_param); - } -#ifdef module_param_array - } -#endif - - /* check sanity of the value */ - if (node_param != -1 && !node_online(node_param)) { - DPRINTK(PROBE, INFO, - "ignoring node set to invalid value %d\n", - node_param); - node_param = opt.def; - } - - adapter->node = node_param; - } { /* MDD - Enable Malicious Driver Detection. Only available when SR-IOV is enabled. */ struct igb_option opt = { diff --git a/kmod/igb/igb_procfs.c b/kmod/igb/igb_procfs.c index 56559c7..33b708c 100644 --- a/kmod/igb/igb_procfs.c +++ b/kmod/igb/igb_procfs.c @@ -68,9 +68,15 @@ bool igb_thermal_present(struct igb_adapter *adapter) return false; hw = &adapter->hw; - status = e1000_set_i2c_bb(hw); - if (status != E1000_SUCCESS) - return false; + /* + * Only set I2C bit-bang mode if an external thermal sensor is + * supported on this device. + */ + if (adapter->ets) { + status = e1000_set_i2c_bb(hw); + if (status != E1000_SUCCESS) + return false; + } status = hw->mac.ops.init_thermal_sensor_thresh(hw); if (status != E1000_SUCCESS) @@ -86,10 +92,7 @@ static int igb_fwbanner(char *page, char **start, off_t off, int count, if (adapter == NULL) return snprintf(page, count, "error: no adapter\n"); - return snprintf(page, count, "%d.%d-%d\n", - (adapter->fw_version & 0xF000) >> 12, - (adapter->fw_version & 0x0FF0) >> 4, - adapter->fw_version & 0x000F); + return snprintf(page, count, "0x%08x\n", adapter->etrack_id); } static int igb_numeports(char *page, char **start, off_t off, int count, diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 069bcb7..3f96846 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -1,30 +1,42 @@ -/* - * PTP Hardware Clock (PHC) driver for the Intel 82576 and 82580 - * - * Copyright (C) 2011 Richard Cochran - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver + Copyright(c) 2007-2012 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". -#ifdef CONFIG_PTP + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +*******************************************************************************/ + +/****************************************************************************** + Copyright(c) 2011 Richard Cochran for some of the + 82576 and 82580 code +******************************************************************************/ + +#include "igb.h" + +#ifdef CONFIG_IGB_PTP #include #include #include -#include "igb.h" #define INCVALUE_MASK 0x7fffffff #define ISGN 0x80000000 @@ -535,18 +547,6 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, case HWTSTAMP_FILTER_NONE: tsync_rx_ctl = 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 |= E1000_TSYNCRXCTL_TYPE_ALL; - config.rx_filter = HWTSTAMP_FILTER_ALL; - break; case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; @@ -557,31 +557,34 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; is_l4 = true; break; + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; - tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE; - is_l2 = true; - is_l4 = true; - config.rx_filter = HWTSTAMP_FILTER_SOME; - break; + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; - tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE; - is_l2 = true; - is_l4 = true; - 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 |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; is_l2 = true; is_l4 = true; break; + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_ALL: + /* + * 82576 cannot timestamp all packets, which it needs to do to + * support both V1 Sync and Delay_Req messages + */ + if (hw->mac.type != e1000_82576) { + tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + } + /* fall through */ default: + config.rx_filter = HWTSTAMP_FILTER_NONE; return -ERANGE; } @@ -599,6 +602,9 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; + config.rx_filter = HWTSTAMP_FILTER_ALL; + is_l2 = true; + is_l4 = true; if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { @@ -687,7 +693,8 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->cc.mult = 1; adapter->cc.shift = IGB_82576_TSYNC_SHIFT; /* Dial the nominal frequency. */ - E1000_WRITE_REG(hw,E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); + E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | + INCVALUE_82576); break; case e1000_82580: case e1000_i350: @@ -729,6 +736,8 @@ void igb_ptp_init(struct igb_adapter *adapter) } E1000_WRITE_FLUSH(hw); + spin_lock_init(&adapter->tmreg_lock); + INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work); /* Initialize the clock and overflow work for devices that need it. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { @@ -742,10 +751,6 @@ void igb_ptp_init(struct igb_adapter *adapter) INIT_DELAYED_WORK(&adapter->ptp_overflow_work, igb_ptp_overflow_check); - spin_lock_init(&adapter->tmreg_lock); - - if (hw->mac.type == e1000_82576) - INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work); schedule_delayed_work(&adapter->ptp_overflow_work, IGB_SYSTIM_OVERFLOW_PERIOD); @@ -764,6 +769,7 @@ void igb_ptp_init(struct igb_adapter *adapter) } else { dev_info(&adapter->pdev->dev, "added PHC on %s\n", adapter->netdev->name); + adapter->flags |= IGB_FLAG_PTP; } } @@ -777,24 +783,68 @@ void igb_ptp_stop(struct igb_adapter *adapter) { switch (adapter->hw.mac.type) { case e1000_82576: - cancel_work_sync(&adapter->ptp_tx_work); - /* fall through */ case e1000_82580: case e1000_i350: cancel_delayed_work_sync(&adapter->ptp_overflow_work); break; case e1000_i210: case e1000_i211: - /* No work to cancel, but we need to unregister the clock. */ + /* No delayed work to cancel. */ + break; default: return; } + cancel_work_sync(&adapter->ptp_tx_work); if (adapter->ptp_clock) { ptp_clock_unregister(adapter->ptp_clock); dev_info(&adapter->pdev->dev, "removed PHC on %s\n", adapter->netdev->name); + adapter->flags &= ~IGB_FLAG_PTP; } } -#endif +/** + * igb_ptp_reset - Re-enable the adapter for PTP following a reset. + * @adapter: Board private structure. + * + * This function handles the reset work required to re-enable the PTP device. + **/ +void igb_ptp_reset(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + + if (!(adapter->flags & IGB_FLAG_PTP)) + return; + + switch (adapter->hw.mac.type) { + case e1000_82576: + /* Dial the nominal frequency. */ + E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | + INCVALUE_82576); + break; + case e1000_82580: + case e1000_i350: + case e1000_i210: + case e1000_i211: + /* Enable the timer functions and interrupts. */ + E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); + E1000_WRITE_REG(hw, E1000_TSIM, E1000_TSIM_TXTS); + E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); + break; + default: + /* No work to do. */ + return; + } + + /* Re-initialize the timer. */ + if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { + struct timespec ts = ktime_to_timespec(ktime_get_real()); + + igb_ptp_settime_i210(&adapter->ptp_caps, &ts); + } else { + timecounter_init(&adapter->tc, &adapter->cc, + ktime_to_ns(ktime_get_real())); + } +} +#endif /* CONFIG_IGB_PTP */ diff --git a/kmod/igb/igb_regtest.h b/kmod/igb/igb_regtest.h index d28215b..55fad1d 100644 --- a/kmod/igb/igb_regtest.h +++ b/kmod/igb/igb_regtest.h @@ -62,7 +62,7 @@ static struct igb_reg_test reg_test_i210[] = { { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, /* RDH is read-only for i210, only test RDT. */ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, - { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, + { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 }, { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, diff --git a/kmod/igb/igb_sysfs.c b/kmod/igb/igb_sysfs.c index 76ccc2e..c7fe788 100644 --- a/kmod/igb/igb_sysfs.c +++ b/kmod/igb/igb_sysfs.c @@ -91,9 +91,15 @@ bool igb_thermal_present(struct kobject *kobj) if (adapter == NULL) return false; + /* + * Only set I2C bit-bang mode if an external thermal sensor is + * supported on this device. + */ + if (adapter->ets) { status = e1000_set_i2c_bb(&(adapter->hw)); if (status != E1000_SUCCESS) return false; + } status = e1000_init_thermal_sensor_thresh(&(adapter->hw)); if (status != E1000_SUCCESS) @@ -135,13 +141,11 @@ static ssize_t igb_fwbanner(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct igb_adapter *adapter = igb_get_adapter(kobj); - u16 nvm_ver; if (adapter == NULL) return snprintf(buf, PAGE_SIZE, "error: no adapter\n"); - nvm_ver = adapter->fw_version; - return snprintf(buf, PAGE_SIZE, "0x%08x\n", nvm_ver); + return snprintf(buf, PAGE_SIZE, "0x%08x\n", adapter->etrack_id); } static ssize_t igb_numeports(struct kobject *kobj, @@ -157,7 +161,7 @@ static ssize_t igb_numeports(struct kobject *kobj, if (hw == NULL) return snprintf(buf, PAGE_SIZE, "error: no hw data\n"); - /* CMW taking the original out so and assigning ports generally + /* CMW taking the original out so assigning ports generally * by mac type for now. Want to have the daemon handle this some * other way due to the variability of the 1GB parts. */ @@ -766,10 +770,6 @@ static ssize_t igb_sysfs_location(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "error: invalid sensor name %s\n", kobj->name); - if (idx >= E1000_MAX_SENSORS) - return snprintf(buf, PAGE_SIZE, - "error: invalid sensor name %s\n", kobj->name); - return snprintf(buf, PAGE_SIZE, "%d\n", adapter->hw.mac.thermal_sensor_data.sensor[idx].location); } @@ -787,18 +787,12 @@ static ssize_t igb_sysfs_temp(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "error: status %d returned", status); - if (NULL == adapter) - return snprintf(buf, PAGE_SIZE, "error: failed to map adapter from kobj"); idx = igb_name_to_idx(kobj->name); if (idx == -1) return snprintf(buf, PAGE_SIZE, "error: invalid sensor name %s\n", kobj->name); - if (idx >= E1000_MAX_SENSORS) - return snprintf(buf, PAGE_SIZE, - "error: invalid sensor name %s\n", kobj->name); - return snprintf(buf, PAGE_SIZE, "%d\n", adapter->hw.mac.thermal_sensor_data.sensor[idx].temp); } @@ -817,10 +811,6 @@ static ssize_t igb_sysfs_maxopthresh(struct kobject *kobj, return snprintf(buf, PAGE_SIZE, "error: invalid sensor name %s\n", kobj->name); - if (idx >= E1000_MAX_SENSORS) - return snprintf(buf, PAGE_SIZE, - "error: invalid sensor name %s\n", kobj->name); - return snprintf(buf, PAGE_SIZE, "%d\n", adapter->hw.mac.thermal_sensor_data.sensor[idx].max_op_thresh); } diff --git a/kmod/igb/kcompat.c b/kmod/igb/kcompat.c index cde6907..64c7e84 100644 --- a/kmod/igb/kcompat.c +++ b/kmod/igb/kcompat.c @@ -601,6 +601,42 @@ size_t _kc_strlcpy(char *dest, const char *src, size_t size) return ret; } +#ifndef do_div +#if BITS_PER_LONG == 32 +uint32_t __attribute__((weak)) _kc__div64_32(uint64_t *n, uint32_t base) +{ + uint64_t rem = *n; + uint64_t b = base; + uint64_t res, d = 1; + uint32_t high = rem >> 32; + + /* Reduce the thing a bit first */ + res = 0; + if (high >= base) { + high /= base; + res = (uint64_t) high << 32; + rem -= (uint64_t) (high*base) << 32; + } + + while ((int64_t)b > 0 && b < rem) { + b = b+b; + d = d+d; + } + + do { + if (rem >= b) { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + + *n = res; + return rem; +} +#endif /* BITS_PER_LONG == 32 */ +#endif /* do_div */ #endif /* 2.6.0 => 2.4.6 */ /*****************************************************************************/ @@ -1024,19 +1060,33 @@ _kc_pci_wake_from_d3(struct pci_dev *dev, bool enable) out: return err; } +#endif /* < 2.6.28 */ -void _kc_skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, - int off, int size) +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) ) +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,0)) +int _kc_pci_num_vf(struct pci_dev *dev) { - skb_fill_page_desc(skb, i, page, off, size); - skb->len += size; - skb->data_len += size; - skb->truesize += size; + int num_vf = 0; +#ifdef CONFIG_PCI_IOV + struct pci_dev *vfdev; + + /* loop through all ethernet devices starting at PF dev */ + vfdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, NULL); + while (vfdev) { + if (vfdev->is_virtfn && vfdev->physfn == dev) + num_vf++; + + vfdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, vfdev); } -#endif /* < 2.6.28 */ +#endif + return num_vf; +} +#endif /* RHEL_RELEASE_CODE */ +#endif /* < 2.6.34 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ) #ifdef HAVE_TX_MQ +#if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0))) #ifndef CONFIG_NETDEVICES_MULTIQUEUE void _kc_netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) { @@ -1061,6 +1111,7 @@ void _kc_netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) } } #endif /* CONFIG_NETDEVICES_MULTIQUEUE */ +#endif /* !(RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0)) */ #endif /* HAVE_TX_MQ */ #endif /* < 2.6.35 */ @@ -1130,3 +1181,6 @@ u16 ___kc_skb_tx_hash(struct net_device *dev, const struct sk_buff *skb, #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0))) #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0)) */ #endif /* < 2.6.39 */ +/******************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) ) +#endif /* < 3.4.0 */ diff --git a/kmod/igb/kcompat.h b/kmod/igb/kcompat.h index c3661e6..1026f22 100644 --- a/kmod/igb/kcompat.h +++ b/kmod/igb/kcompat.h @@ -314,6 +314,9 @@ struct _kc_vlan_hdr { #define __GFP_COLD 0 #endif +#ifndef __GFP_COMP +#define __GFP_COMP 0 +#endif /*****************************************************************************/ /* Installations with ethtool version without eeprom, adapter id, or statistics * support */ @@ -1120,6 +1123,8 @@ static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) pdev_printk(KERN_INFO, to_pci_dev(dev), fmt, ## args) #define dev_warn(dev, fmt, args...) \ pdev_printk(KERN_WARNING, to_pci_dev(dev), fmt, ## args) +#define dev_notice(dev, fmt, args...) \ + pdev_printk(KERN_NOTICE, to_pci_dev(dev), fmt, ## args) /* NOTE: dangerous! we ignore the 'gfp' argument */ #define dma_alloc_coherent(dev,sz,dma,gfp) \ @@ -1137,6 +1142,10 @@ static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) #define dma_unmap_single(dev,a,b,c) \ pci_unmap_single(to_pci_dev(dev),(a),(b),(c)) +#define dma_map_sg(dev, sg, nents, dir) \ + pci_map_sg(to_pci_dev(dev), (sg), (nents), (dir) +#define dma_unmap_sg(dev, sg, nents, dir) \ + pci_unmap_sg(to_pci_dev(dev), (sg), (nents), (dir) #define dma_sync_single(dev,a,b,c) \ pci_dma_sync_single(to_pci_dev(dev),(a),(b),(c)) @@ -1306,9 +1315,45 @@ static inline const char *_kc_netdev_name(const struct net_device *dev) extern size_t _kc_strlcpy(char *dest, const char *src, size_t size); #endif /* strlcpy */ +#ifndef do_div +#if BITS_PER_LONG == 64 +# define do_div(n,base) ({ \ + uint32_t __base = (base); \ + uint32_t __rem; \ + __rem = ((uint64_t)(n)) % __base; \ + (n) = ((uint64_t)(n)) / __base; \ + __rem; \ + }) +#elif BITS_PER_LONG == 32 +extern uint32_t _kc__div64_32(uint64_t *dividend, uint32_t divisor); +# define do_div(n,base) ({ \ + uint32_t __base = (base); \ + uint32_t __rem; \ + if (likely(((n) >> 32) == 0)) { \ + __rem = (uint32_t)(n) % __base; \ + (n) = (uint32_t)(n) / __base; \ + } else \ + __rem = _kc__div64_32(&(n), __base); \ + __rem; \ + }) +#else /* BITS_PER_LONG == ?? */ +# error do_div() does not yet support the C64 +#endif /* BITS_PER_LONG */ +#endif /* do_div */ #endif /* 2.6.0 => 2.5.28 */ /*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ) +#define dma_pool pci_pool +#define dma_pool_destroy pci_pool_destroy +#define dma_pool_alloc pci_pool_alloc +#define dma_pool_free pci_pool_free + +#define dma_pool_create(name,dev,size,align,allocation) \ + pci_pool_create((name),to_pci_dev(dev),(size),(align),(allocation)) +#endif /* < 2.6.3 */ + +/*****************************************************************************/ /* 2.6.4 => 2.6.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) #define MODULE_VERSION(_version) MODULE_INFO(version, _version) @@ -1524,6 +1569,7 @@ static inline void *_kc_skb_header_pointer(const struct sk_buff *skb, extern DECLARE_BITMAP(_kcompat_node_online_map, MAX_NUMNODES); #undef node_online_map #define node_online_map _kcompat_node_online_map +#define pci_get_class pci_find_class #endif /* < 2.6.10 */ /*****************************************************************************/ @@ -1627,6 +1673,8 @@ extern void *_kc_kzalloc(size_t size, int flags); #define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ #define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ +#define SUPPORTED_Pause (1 << 13) +#define SUPPORTED_Asym_Pause (1 << 14) #define ADVERTISED_Pause (1 << 13) #define ADVERTISED_Asym_Pause (1 << 14) @@ -1642,10 +1690,10 @@ typedef unsigned gfp_t; #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) ) #ifdef CONFIG_X86_64 -#define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir) \ - dma_sync_single_for_cpu(dev, dma_handle, size, dir) -#define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir) \ - dma_sync_single_for_device(dev, dma_handle, size, dir) +#define dma_sync_single_range_for_cpu(dev, addr, off, sz, dir) \ + dma_sync_single_for_cpu((dev), (addr), (off) + (sz), (dir)) +#define dma_sync_single_range_for_device(dev, addr, off, sz, dir) \ + dma_sync_single_for_device((dev), (addr), (off) + (sz), (dir)) #endif #endif #endif /* < 2.6.14 */ @@ -1704,6 +1752,10 @@ static inline unsigned _kc_compare_ether_addr(const u8 *addr1, const u8 *addr2) /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) ) +#ifndef dev_notice +#define dev_notice(dev, fmt, args...) \ + dev_printk(KERN_NOTICE, dev, fmt, ## args) +#endif #ifndef first_online_node #define first_online_node 0 #endif @@ -1796,6 +1848,9 @@ static inline int _kc_skb_padto(struct sk_buff *skb, unsigned int len) #ifndef DIV_ROUND_UP #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #endif +#ifndef __ALIGN_MASK +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#endif #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) #if (!((RHEL_RELEASE_CODE && \ ((RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,4) && \ @@ -1886,6 +1941,9 @@ do { \ PCI_ANY_ID, PCI_ANY_ID, 0, 0 #endif +#ifndef PCI_VENDOR_ID_INTEL +#define PCI_VENDOR_ID_INTEL 0x8086 +#endif #ifndef round_jiffies #define round_jiffies(x) x #endif @@ -2120,6 +2178,10 @@ static inline int _kc_skb_is_gso_v6(const struct sk_buff *skb) #ifndef KERN_CONT #define KERN_CONT "" #endif +#ifndef pr_err +#define pr_err(fmt, arg...) \ + printk(KERN_ERR fmt, ##arg) +#endif #else /* < 2.6.24 */ #define HAVE_ETHTOOL_GET_SSET_COUNT #define HAVE_NETDEV_NAPI_LIST @@ -2331,10 +2393,6 @@ static inline void __kc_skb_queue_head_init(struct sk_buff_head *list) } #define __skb_queue_head_init(_q) __kc_skb_queue_head_init(_q) #endif -#ifndef skb_add_rx_frag -#define skb_add_rx_frag _kc_skb_add_rx_frag -extern void _kc_skb_add_rx_frag(struct sk_buff *, int, struct page *, int, int); -#endif #endif /* < 2.6.28 */ /*****************************************************************************/ @@ -2395,7 +2453,16 @@ extern void _kc_skb_add_rx_frag(struct sk_buff *, int, struct page *, int, int); #define netdev_for_each_uc_addr(uclist, dev) \ for (uclist = dev->uc_list; uclist; uclist = uclist->next) #endif -#else +#ifndef PORT_OTHER +#define PORT_OTHER 0xff +#endif +#ifndef MDIO_PHY_ID_PRTAD +#define MDIO_PHY_ID_PRTAD 0x03e0 +#endif +#ifndef MDIO_PHY_ID_DEVAD +#define MDIO_PHY_ID_DEVAD 0x001f +#endif +#else /* < 2.6.31 */ #ifndef HAVE_NETDEV_STORAGE_ADDRESS #define HAVE_NETDEV_STORAGE_ADDRESS #endif @@ -2405,6 +2472,9 @@ extern void _kc_skb_add_rx_frag(struct sk_buff *, int, struct page *, int, int); #ifndef HAVE_TRANS_START_IN_QUEUE #define HAVE_TRANS_START_IN_QUEUE #endif +#ifndef HAVE_INCLUDE_LINUX_MDIO_H +#define HAVE_INCLUDE_LINUX_MDIO_H +#endif #endif /* < 2.6.31 */ /*****************************************************************************/ @@ -2489,17 +2559,48 @@ extern void _kc_skb_add_rx_frag(struct sk_buff *, int, struct page *, int, int); #ifndef __percpu #define __percpu #endif /* __percpu */ +#ifndef PORT_DA +#define PORT_DA PORT_OTHER +#endif +#ifndef PORT_NONE +#define PORT_NONE PORT_OTHER +#endif + +#if ((RHEL_RELEASE_CODE && \ + (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,3)) && \ + (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0)))) +#if !defined(CONFIG_X86_32) && !defined(CONFIG_NEED_DMA_MAP_STATE) +#undef DEFINE_DMA_UNMAP_ADDR +#define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME +#undef DEFINE_DMA_UNMAP_LEN +#define DEFINE_DMA_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME +#undef dma_unmap_addr +#define dma_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) +#undef dma_unmap_addr_set +#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) +#undef dma_unmap_len +#define dma_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) +#undef dma_unmap_len_set +#define dma_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) +#endif /* CONFIG_X86_64 && !CONFIG_NEED_DMA_MAP_STATE */ +#endif /* RHEL_RELEASE_CODE */ #else /* < 2.6.33 */ #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_GETWWN #define HAVE_NETDEV_OPS_FCOE_GETWWN #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ -#define HAVE_ETHTOOL_SFP_DISPLAY_PORT + #endif /* < 2.6.33 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) ) +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,0)) +#ifndef pci_num_vf +#define pci_num_vf(pdev) _kc_pci_num_vf(pdev) +extern int _kc_pci_num_vf(struct pci_dev *dev); +#endif +#endif /* RHEL_RELEASE_CODE */ #ifndef ETH_FLAG_NTUPLE #define ETH_FLAG_NTUPLE NETIF_F_NTUPLE #endif @@ -2549,8 +2650,7 @@ static inline const char *_kc_netdev_name(const struct net_device *dev) do { \ struct adapter_struct *kc_adapter = netdev_priv(netdev);\ struct pci_dev *pdev = kc_adapter->pdev; \ - printk("%s %s: " format, level, pci_name(pdev), \ - ##args); \ + printk(level "%s: " format, pci_name(pdev), ##args); \ } while(0) #elif ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) #define netdev_printk(level, netdev, format, args...) \ @@ -2589,7 +2689,10 @@ do { \ #define netdev_info(dev, format, args...) \ netdev_printk(KERN_INFO, dev, format, ##args) #undef netdev_dbg -#if defined(CONFIG_DYNAMIC_DEBUG) +#if defined(DEBUG) +#define netdev_dbg(__dev, format, args...) \ + netdev_printk(KERN_DEBUG, __dev, format, ##args) +#elif defined(CONFIG_DYNAMIC_DEBUG) #define netdev_dbg(__dev, format, args...) \ do { \ dynamic_dev_dbg((__dev)->dev.parent, "%s: " format, \ @@ -2668,15 +2771,17 @@ do { \ #ifdef HAVE_TX_MQ #include #ifndef CONFIG_NETDEVICES_MULTIQUEUE +#if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0))) void _kc_netif_set_real_num_tx_queues(struct net_device *, unsigned int); #define netif_set_real_num_tx_queues _kc_netif_set_real_num_tx_queues +#endif /* !(RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0)) */ #else /* CONFIG_NETDEVICES_MULTI_QUEUE */ #define netif_set_real_num_tx_queues(_netdev, _count) \ do { \ (_netdev)->egress_subqueue_count = _count; \ } while (0) #endif /* CONFIG_NETDEVICES_MULTI_QUEUE */ -#else +#else /* HAVE_TX_MQ */ #define netif_set_real_num_tx_queues(_netdev, _count) do {} while(0) #endif /* HAVE_TX_MQ */ #ifndef ETH_FLAG_RXHASH @@ -2749,6 +2854,15 @@ do { \ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ) +#ifndef netif_set_real_num_rx_queues +static inline int __kc_netif_set_real_num_rx_queues(struct net_device *dev, + unsigned int rxq) +{ + return 0; +} +#define netif_set_real_num_rx_queues(dev, rxq) \ + __kc_netif_set_real_num_rx_queues((dev), (rxq)) +#endif #ifndef ETHTOOL_RXNTUPLE_ACTION_CLEAR #define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) #endif @@ -2800,6 +2914,11 @@ static inline __be16 __kc_vlan_get_protocol(const struct sk_buff *skb) } #define vlan_get_protocol(_skb) __kc_vlan_get_protocol(_skb) #endif +#ifdef HAVE_HW_TIME_STAMP +#define SKBTX_HW_TSTAMP (1 << 0) +#define SKBTX_IN_PROGRESS (1 << 2) +#define SKB_SHARED_TX_IS_UNION +#endif #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,18) ) #ifndef HAVE_VLAN_RX_REGISTER #define HAVE_VLAN_RX_REGISTER @@ -2920,6 +3039,19 @@ struct _kc_ethtool_rx_flow_spec { #else /* < 2.6.40 */ #define HAVE_ETHTOOL_SET_PHYS_ID #endif /* < 2.6.40 */ +/*****************************************************************************/ + +/*****************************************************************************/ +#undef CONFIG_IGB_PTP +#ifdef CONFIG_PTP +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) ) && (defined(CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE)) +#define CONFIG_IGB_PTP +#else +#error Cannot enable PTP Hardware Clock due to insufficient kernel support +#endif +#endif /* IGB_PTP */ + +/*****************************************************************************/ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ) @@ -2993,6 +3125,12 @@ static inline void __kc_skb_frag_unref(skb_frag_t *frag) put_page(skb_frag_page(frag)); } #endif /* __skb_frag_unref */ +#ifndef SPEED_UNKNOWN +#define SPEED_UNKNOWN -1 +#endif +#ifndef DUPLEX_UNKNOWN +#define DUPLEX_UNKNOWN 0xff +#endif #else /* < 3.2.0 */ #ifndef HAVE_PCI_DEV_FLAGS_ASSIGNED #define HAVE_PCI_DEV_FLAGS_ASSIGNED @@ -3031,7 +3169,69 @@ typedef u32 netdev_features_t; /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) ) +#define skb_tx_timestamp(skb) do {} while (0) #else #define HAVE_FDB_OPS +#define HAVE_ETHTOOL_GET_TS_INFO #endif /* < 3.5.0 */ +/******************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) ) +#ifdef ETHTOOL_GEEE +#include +/** + * mmd_eee_cap_to_ethtool_sup_t + * @eee_cap: value of the MMD EEE Capability register + * + * A small helper function that translates MMD EEE Capability (3.20) bits + * to ethtool supported settings. + */ +static inline u32 mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap) +{ + u32 supported = 0; + + if (eee_cap & MDIO_EEE_100TX) + supported |= SUPPORTED_100baseT_Full; + if (eee_cap & MDIO_EEE_1000T) + supported |= SUPPORTED_1000baseT_Full; + if (eee_cap & MDIO_EEE_10GT) + supported |= SUPPORTED_10000baseT_Full; + if (eee_cap & MDIO_EEE_1000KX) + supported |= SUPPORTED_1000baseKX_Full; + if (eee_cap & MDIO_EEE_10GKX4) + supported |= SUPPORTED_10000baseKX4_Full; + if (eee_cap & MDIO_EEE_10GKR) + supported |= SUPPORTED_10000baseKR_Full; + + return supported; +} + +/** + * mmd_eee_adv_to_ethtool_adv_t + * @eee_adv: value of the MMD EEE Advertisement/Link Partner Ability registers + * + * A small helper function that translates the MMD EEE Advertisment (7.60) + * and MMD EEE Link Partner Ability (7.61) bits to ethtool advertisement + * settings. + */ +static inline u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv) +{ + u32 adv = 0; + + if (eee_adv & MDIO_EEE_100TX) + adv |= ADVERTISED_100baseT_Full; + if (eee_adv & MDIO_EEE_1000T) + adv |= ADVERTISED_1000baseT_Full; + if (eee_adv & MDIO_EEE_10GT) + adv |= ADVERTISED_10000baseT_Full; + if (eee_adv & MDIO_EEE_1000KX) + adv |= ADVERTISED_1000baseKX_Full; + if (eee_adv & MDIO_EEE_10GKX4) + adv |= ADVERTISED_10000baseKX4_Full; + if (eee_adv & MDIO_EEE_10GKR) + adv |= ADVERTISED_10000baseKR_Full; + + return adv; +} +#endif /* ETHTOOL_GEEE */ +#endif /* < 3.7.0 */ #endif /* _KCOMPAT_H_ */ -- 2.7.4