e1000: Fixes for 8357x
- TSO workaround - Fixes eeprom version reporting - Fix loopback test - Fix for WOL Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: John Ronciak <john.ronciak@intel.com> Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
This commit is contained in:
parent
ff7eba15ae
commit
fd80324174
5 changed files with 151 additions and 85 deletions
|
@ -188,11 +188,13 @@ struct e1000_tx_ring {
|
||||||
/* array of buffer information structs */
|
/* array of buffer information structs */
|
||||||
struct e1000_buffer *buffer_info;
|
struct e1000_buffer *buffer_info;
|
||||||
|
|
||||||
struct e1000_buffer previous_buffer_info;
|
|
||||||
spinlock_t tx_lock;
|
spinlock_t tx_lock;
|
||||||
uint16_t tdh;
|
uint16_t tdh;
|
||||||
uint16_t tdt;
|
uint16_t tdt;
|
||||||
uint64_t pkt;
|
uint64_t pkt;
|
||||||
|
|
||||||
|
boolean_t last_tx_tso;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct e1000_rx_ring {
|
struct e1000_rx_ring {
|
||||||
|
|
|
@ -562,10 +562,29 @@ e1000_get_drvinfo(struct net_device *netdev,
|
||||||
struct ethtool_drvinfo *drvinfo)
|
struct ethtool_drvinfo *drvinfo)
|
||||||
{
|
{
|
||||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||||
|
char firmware_version[32];
|
||||||
|
uint16_t eeprom_data;
|
||||||
|
|
||||||
strncpy(drvinfo->driver, e1000_driver_name, 32);
|
strncpy(drvinfo->driver, e1000_driver_name, 32);
|
||||||
strncpy(drvinfo->version, e1000_driver_version, 32);
|
strncpy(drvinfo->version, e1000_driver_version, 32);
|
||||||
strncpy(drvinfo->fw_version, "N/A", 32);
|
|
||||||
|
/* EEPROM image version # is reported as firware version # for
|
||||||
|
* 8257{1|2|3} controllers */
|
||||||
|
e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
|
||||||
|
switch (adapter->hw.mac_type) {
|
||||||
|
case e1000_82571:
|
||||||
|
case e1000_82572:
|
||||||
|
case e1000_82573:
|
||||||
|
sprintf(firmware_version, "%d.%d-%d",
|
||||||
|
(eeprom_data & 0xF000) >> 12,
|
||||||
|
(eeprom_data & 0x0FF0) >> 4,
|
||||||
|
eeprom_data & 0x000F);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(firmware_version, "n/a");
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(drvinfo->fw_version, firmware_version, 32);
|
||||||
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
|
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
|
||||||
drvinfo->n_stats = E1000_STATS_LEN;
|
drvinfo->n_stats = E1000_STATS_LEN;
|
||||||
drvinfo->testinfo_len = E1000_TEST_LEN;
|
drvinfo->testinfo_len = E1000_TEST_LEN;
|
||||||
|
@ -1309,21 +1328,32 @@ static int
|
||||||
e1000_setup_loopback_test(struct e1000_adapter *adapter)
|
e1000_setup_loopback_test(struct e1000_adapter *adapter)
|
||||||
{
|
{
|
||||||
uint32_t rctl;
|
uint32_t rctl;
|
||||||
|
struct e1000_hw *hw = &adapter->hw;
|
||||||
|
|
||||||
if(adapter->hw.media_type == e1000_media_type_fiber ||
|
if (hw->media_type == e1000_media_type_fiber ||
|
||||||
adapter->hw.media_type == e1000_media_type_internal_serdes) {
|
hw->media_type == e1000_media_type_internal_serdes) {
|
||||||
if(adapter->hw.mac_type == e1000_82545 ||
|
switch (hw->mac_type) {
|
||||||
adapter->hw.mac_type == e1000_82546 ||
|
case e1000_82545:
|
||||||
adapter->hw.mac_type == e1000_82545_rev_3 ||
|
case e1000_82546:
|
||||||
adapter->hw.mac_type == e1000_82546_rev_3)
|
case e1000_82545_rev_3:
|
||||||
|
case e1000_82546_rev_3:
|
||||||
return e1000_set_phy_loopback(adapter);
|
return e1000_set_phy_loopback(adapter);
|
||||||
else {
|
break;
|
||||||
rctl = E1000_READ_REG(&adapter->hw, RCTL);
|
case e1000_82571:
|
||||||
|
case e1000_82572:
|
||||||
|
#define E1000_SERDES_LB_ON 0x410
|
||||||
|
e1000_set_phy_loopback(adapter);
|
||||||
|
E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
|
||||||
|
msec_delay(10);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rctl = E1000_READ_REG(hw, RCTL);
|
||||||
rctl |= E1000_RCTL_LBM_TCVR;
|
rctl |= E1000_RCTL_LBM_TCVR;
|
||||||
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
|
E1000_WRITE_REG(hw, RCTL, rctl);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if(adapter->hw.media_type == e1000_media_type_copper)
|
} else if (hw->media_type == e1000_media_type_copper)
|
||||||
return e1000_set_phy_loopback(adapter);
|
return e1000_set_phy_loopback(adapter);
|
||||||
|
|
||||||
return 7;
|
return 7;
|
||||||
|
@ -1334,25 +1364,36 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
|
||||||
{
|
{
|
||||||
uint32_t rctl;
|
uint32_t rctl;
|
||||||
uint16_t phy_reg;
|
uint16_t phy_reg;
|
||||||
|
struct e1000_hw *hw = &adapter->hw;
|
||||||
|
|
||||||
rctl = E1000_READ_REG(&adapter->hw, RCTL);
|
rctl = E1000_READ_REG(&adapter->hw, RCTL);
|
||||||
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
|
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
|
||||||
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
|
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
|
||||||
|
|
||||||
if(adapter->hw.media_type == e1000_media_type_copper ||
|
switch (hw->mac_type) {
|
||||||
((adapter->hw.media_type == e1000_media_type_fiber ||
|
case e1000_82571:
|
||||||
adapter->hw.media_type == e1000_media_type_internal_serdes) &&
|
case e1000_82572:
|
||||||
(adapter->hw.mac_type == e1000_82545 ||
|
if (hw->media_type == e1000_media_type_fiber ||
|
||||||
adapter->hw.mac_type == e1000_82546 ||
|
hw->media_type == e1000_media_type_internal_serdes){
|
||||||
adapter->hw.mac_type == e1000_82545_rev_3 ||
|
#define E1000_SERDES_LB_OFF 0x400
|
||||||
adapter->hw.mac_type == e1000_82546_rev_3))) {
|
E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
|
||||||
adapter->hw.autoneg = TRUE;
|
msec_delay(10);
|
||||||
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
|
break;
|
||||||
|
}
|
||||||
|
/* fall thru for Cu adapters */
|
||||||
|
case e1000_82545:
|
||||||
|
case e1000_82546:
|
||||||
|
case e1000_82545_rev_3:
|
||||||
|
case e1000_82546_rev_3:
|
||||||
|
default:
|
||||||
|
hw->autoneg = TRUE;
|
||||||
|
e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
|
||||||
if (phy_reg & MII_CR_LOOPBACK) {
|
if (phy_reg & MII_CR_LOOPBACK) {
|
||||||
phy_reg &= ~MII_CR_LOOPBACK;
|
phy_reg &= ~MII_CR_LOOPBACK;
|
||||||
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
|
e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
|
||||||
e1000_phy_reset(&adapter->hw);
|
e1000_phy_reset(hw);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1681,6 +1722,14 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
|
||||||
msleep_interruptible(data * 1000);
|
msleep_interruptible(data * 1000);
|
||||||
del_timer_sync(&adapter->blink_timer);
|
del_timer_sync(&adapter->blink_timer);
|
||||||
}
|
}
|
||||||
|
else if(adapter->hw.mac_type < e1000_82573) {
|
||||||
|
E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
|
||||||
|
E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
|
||||||
|
(E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
|
||||||
|
(E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
|
||||||
|
(E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
|
||||||
|
msleep_interruptible(data * 1000);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
|
E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
|
||||||
E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
|
E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
|
||||||
|
|
|
@ -563,11 +563,13 @@ e1000_reset_hw(struct e1000_hw *hw)
|
||||||
msec_delay(20);
|
msec_delay(20);
|
||||||
break;
|
break;
|
||||||
case e1000_82573:
|
case e1000_82573:
|
||||||
|
if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
|
||||||
udelay(10);
|
udelay(10);
|
||||||
ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
|
ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
|
||||||
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
|
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
|
||||||
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
|
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
|
||||||
E1000_WRITE_FLUSH(hw);
|
E1000_WRITE_FLUSH(hw);
|
||||||
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case e1000_82571:
|
case e1000_82571:
|
||||||
case e1000_82572:
|
case e1000_82572:
|
||||||
|
@ -844,12 +846,18 @@ e1000_setup_link(struct e1000_hw *hw)
|
||||||
* control setting, then the variable hw->fc will
|
* control setting, then the variable hw->fc will
|
||||||
* be initialized based on a value in the EEPROM.
|
* be initialized based on a value in the EEPROM.
|
||||||
*/
|
*/
|
||||||
if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data)) {
|
if (hw->fc == e1000_fc_default) {
|
||||||
|
switch (hw->mac_type) {
|
||||||
|
case e1000_82573:
|
||||||
|
hw->fc = e1000_fc_full;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
|
||||||
|
1, &eeprom_data);
|
||||||
|
if (ret_val) {
|
||||||
DEBUGOUT("EEPROM Read Error\n");
|
DEBUGOUT("EEPROM Read Error\n");
|
||||||
return -E1000_ERR_EEPROM;
|
return -E1000_ERR_EEPROM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hw->fc == e1000_fc_default) {
|
|
||||||
if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
|
if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
|
||||||
hw->fc = e1000_fc_none;
|
hw->fc = e1000_fc_none;
|
||||||
else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
|
else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
|
||||||
|
@ -857,6 +865,8 @@ e1000_setup_link(struct e1000_hw *hw)
|
||||||
hw->fc = e1000_fc_tx_pause;
|
hw->fc = e1000_fc_tx_pause;
|
||||||
else
|
else
|
||||||
hw->fc = e1000_fc_full;
|
hw->fc = e1000_fc_full;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want to save off the original Flow Control configuration just
|
/* We want to save off the original Flow Control configuration just
|
||||||
|
@ -2962,13 +2972,22 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
|
||||||
if(hw->mac_type > e1000_82543) {
|
if(hw->mac_type > e1000_82543) {
|
||||||
/* Read the device control register and assert the E1000_CTRL_PHY_RST
|
/* Read the device control register and assert the E1000_CTRL_PHY_RST
|
||||||
* bit. Then, take it out of reset.
|
* bit. Then, take it out of reset.
|
||||||
|
* For pre-e1000_82571 hardware, we delay for 10ms between the assert
|
||||||
|
* and deassert. For e1000_82571 hardware and later, we instead delay
|
||||||
|
* for 10ms after the deassertion.
|
||||||
*/
|
*/
|
||||||
ctrl = E1000_READ_REG(hw, CTRL);
|
ctrl = E1000_READ_REG(hw, CTRL);
|
||||||
E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
|
E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
|
||||||
E1000_WRITE_FLUSH(hw);
|
E1000_WRITE_FLUSH(hw);
|
||||||
|
|
||||||
|
if (hw->mac_type < e1000_82571)
|
||||||
msec_delay(10);
|
msec_delay(10);
|
||||||
|
|
||||||
E1000_WRITE_REG(hw, CTRL, ctrl);
|
E1000_WRITE_REG(hw, CTRL, ctrl);
|
||||||
E1000_WRITE_FLUSH(hw);
|
E1000_WRITE_FLUSH(hw);
|
||||||
|
|
||||||
|
if (hw->mac_type >= e1000_82571)
|
||||||
|
msec_delay(10);
|
||||||
} else {
|
} else {
|
||||||
/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
|
/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
|
||||||
* bit to put the PHY into reset. Then, take it out of reset.
|
* bit to put the PHY into reset. Then, take it out of reset.
|
||||||
|
@ -5278,9 +5297,13 @@ e1000_get_bus_info(struct e1000_hw *hw)
|
||||||
hw->bus_speed = e1000_bus_speed_unknown;
|
hw->bus_speed = e1000_bus_speed_unknown;
|
||||||
hw->bus_width = e1000_bus_width_unknown;
|
hw->bus_width = e1000_bus_width_unknown;
|
||||||
break;
|
break;
|
||||||
case e1000_82571:
|
|
||||||
case e1000_82572:
|
case e1000_82572:
|
||||||
case e1000_82573:
|
case e1000_82573:
|
||||||
|
hw->bus_type = e1000_bus_type_pci_express;
|
||||||
|
hw->bus_speed = e1000_bus_speed_2500;
|
||||||
|
hw->bus_width = e1000_bus_width_pciex_1;
|
||||||
|
break;
|
||||||
|
case e1000_82571:
|
||||||
hw->bus_type = e1000_bus_type_pci_express;
|
hw->bus_type = e1000_bus_type_pci_express;
|
||||||
hw->bus_speed = e1000_bus_speed_2500;
|
hw->bus_speed = e1000_bus_speed_2500;
|
||||||
hw->bus_width = e1000_bus_width_pciex_4;
|
hw->bus_width = e1000_bus_width_pciex_4;
|
||||||
|
@ -6650,6 +6673,12 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
|
||||||
|
* Need to wait for PHY configuration completion before accessing NVM
|
||||||
|
* and PHY. */
|
||||||
|
if (hw->mac_type == e1000_82573)
|
||||||
|
msec_delay(25);
|
||||||
|
|
||||||
return E1000_SUCCESS;
|
return E1000_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,7 @@ typedef enum {
|
||||||
e1000_bus_width_32,
|
e1000_bus_width_32,
|
||||||
e1000_bus_width_64,
|
e1000_bus_width_64,
|
||||||
e1000_bus_width_pciex_1,
|
e1000_bus_width_pciex_1,
|
||||||
|
e1000_bus_width_pciex_2,
|
||||||
e1000_bus_width_pciex_4,
|
e1000_bus_width_pciex_4,
|
||||||
e1000_bus_width_reserved
|
e1000_bus_width_reserved
|
||||||
} e1000_bus_width;
|
} e1000_bus_width;
|
||||||
|
@ -149,6 +150,7 @@ typedef enum {
|
||||||
e1000_igp_cable_length_90 = 90,
|
e1000_igp_cable_length_90 = 90,
|
||||||
e1000_igp_cable_length_100 = 100,
|
e1000_igp_cable_length_100 = 100,
|
||||||
e1000_igp_cable_length_110 = 110,
|
e1000_igp_cable_length_110 = 110,
|
||||||
|
e1000_igp_cable_length_115 = 115,
|
||||||
e1000_igp_cable_length_120 = 120,
|
e1000_igp_cable_length_120 = 120,
|
||||||
e1000_igp_cable_length_130 = 130,
|
e1000_igp_cable_length_130 = 130,
|
||||||
e1000_igp_cable_length_140 = 140,
|
e1000_igp_cable_length_140 = 140,
|
||||||
|
@ -1457,6 +1459,7 @@ struct e1000_hw {
|
||||||
#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
|
#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
|
||||||
#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
|
#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
|
||||||
#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
|
#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
|
||||||
|
#define E1000_EECD_SECVAL_SHIFT 22
|
||||||
#define E1000_STM_OPCODE 0xDB00
|
#define E1000_STM_OPCODE 0xDB00
|
||||||
#define E1000_HICR_FW_RESET 0xC0
|
#define E1000_HICR_FW_RESET 0xC0
|
||||||
|
|
||||||
|
@ -1951,7 +1954,6 @@ struct e1000_host_command_info {
|
||||||
|
|
||||||
#define E1000_MDALIGN 4096
|
#define E1000_MDALIGN 4096
|
||||||
|
|
||||||
#define E1000_GCR_BEM32 0x00400000
|
|
||||||
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
|
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
|
||||||
/* Function Active and Power State to MNG */
|
/* Function Active and Power State to MNG */
|
||||||
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
|
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
|
||||||
|
|
|
@ -711,6 +711,7 @@ e1000_probe(struct pci_dev *pdev,
|
||||||
break;
|
break;
|
||||||
case e1000_82546:
|
case e1000_82546:
|
||||||
case e1000_82546_rev_3:
|
case e1000_82546_rev_3:
|
||||||
|
case e1000_82571:
|
||||||
if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
|
if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
|
||||||
&& (adapter->hw.media_type == e1000_media_type_copper)) {
|
&& (adapter->hw.media_type == e1000_media_type_copper)) {
|
||||||
e1000_read_eeprom(&adapter->hw,
|
e1000_read_eeprom(&adapter->hw,
|
||||||
|
@ -1158,7 +1159,6 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
memset(txdr->buffer_info, 0, size);
|
memset(txdr->buffer_info, 0, size);
|
||||||
memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
|
|
||||||
|
|
||||||
/* round up to nearest 4K */
|
/* round up to nearest 4K */
|
||||||
|
|
||||||
|
@ -1813,11 +1813,6 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
|
||||||
|
|
||||||
/* Free all the Tx ring sk_buffs */
|
/* Free all the Tx ring sk_buffs */
|
||||||
|
|
||||||
if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
|
|
||||||
e1000_unmap_and_free_tx_resource(adapter,
|
|
||||||
&tx_ring->previous_buffer_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < tx_ring->count; i++) {
|
for(i = 0; i < tx_ring->count; i++) {
|
||||||
buffer_info = &tx_ring->buffer_info[i];
|
buffer_info = &tx_ring->buffer_info[i];
|
||||||
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
|
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
|
||||||
|
@ -1832,6 +1827,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
|
||||||
|
|
||||||
tx_ring->next_to_use = 0;
|
tx_ring->next_to_use = 0;
|
||||||
tx_ring->next_to_clean = 0;
|
tx_ring->next_to_clean = 0;
|
||||||
|
tx_ring->last_tx_tso = 0;
|
||||||
|
|
||||||
writel(0, adapter->hw.hw_addr + tx_ring->tdh);
|
writel(0, adapter->hw.hw_addr + tx_ring->tdh);
|
||||||
writel(0, adapter->hw.hw_addr + tx_ring->tdt);
|
writel(0, adapter->hw.hw_addr + tx_ring->tdt);
|
||||||
|
@ -2437,6 +2433,16 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
|
||||||
buffer_info = &tx_ring->buffer_info[i];
|
buffer_info = &tx_ring->buffer_info[i];
|
||||||
size = min(len, max_per_txd);
|
size = min(len, max_per_txd);
|
||||||
#ifdef NETIF_F_TSO
|
#ifdef NETIF_F_TSO
|
||||||
|
/* Workaround for Controller erratum --
|
||||||
|
* descriptor for non-tso packet in a linear SKB that follows a
|
||||||
|
* tso gets written back prematurely before the data is fully
|
||||||
|
* DMAd to the controller */
|
||||||
|
if (!skb->data_len && tx_ring->last_tx_tso &&
|
||||||
|
!skb_shinfo(skb)->tso_size) {
|
||||||
|
tx_ring->last_tx_tso = 0;
|
||||||
|
size -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
/* Workaround for premature desc write-backs
|
/* Workaround for premature desc write-backs
|
||||||
* in TSO mode. Append 4-byte sentinel desc */
|
* in TSO mode. Append 4-byte sentinel desc */
|
||||||
if(unlikely(mss && !nr_frags && size == len && size > 8))
|
if(unlikely(mss && !nr_frags && size == len && size > 8))
|
||||||
|
@ -2693,6 +2699,14 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
||||||
if(skb->ip_summed == CHECKSUM_HW)
|
if(skb->ip_summed == CHECKSUM_HW)
|
||||||
count++;
|
count++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NETIF_F_TSO
|
||||||
|
/* Controller Erratum workaround */
|
||||||
|
if (!skb->data_len && tx_ring->last_tx_tso &&
|
||||||
|
!skb_shinfo(skb)->tso_size)
|
||||||
|
count++;
|
||||||
|
#endif
|
||||||
|
|
||||||
count += TXD_USE_COUNT(len, max_txd_pwr);
|
count += TXD_USE_COUNT(len, max_txd_pwr);
|
||||||
|
|
||||||
if(adapter->pcix_82544)
|
if(adapter->pcix_82544)
|
||||||
|
@ -2774,9 +2788,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(tso))
|
if (likely(tso)) {
|
||||||
|
tx_ring->last_tx_tso = 1;
|
||||||
tx_flags |= E1000_TX_FLAGS_TSO;
|
tx_flags |= E1000_TX_FLAGS_TSO;
|
||||||
else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
|
} else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
|
||||||
tx_flags |= E1000_TX_FLAGS_CSUM;
|
tx_flags |= E1000_TX_FLAGS_CSUM;
|
||||||
|
|
||||||
/* Old method was to assume IPv4 packet by default if TSO was enabled.
|
/* Old method was to assume IPv4 packet by default if TSO was enabled.
|
||||||
|
@ -3227,37 +3242,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||||
eop_desc = E1000_TX_DESC(*tx_ring, eop);
|
eop_desc = E1000_TX_DESC(*tx_ring, eop);
|
||||||
|
|
||||||
while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
|
while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
|
||||||
/* Premature writeback of Tx descriptors clear (free buffers
|
|
||||||
* and unmap pci_mapping) previous_buffer_info */
|
|
||||||
if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
|
|
||||||
e1000_unmap_and_free_tx_resource(adapter,
|
|
||||||
&tx_ring->previous_buffer_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(cleaned = FALSE; !cleaned; ) {
|
for(cleaned = FALSE; !cleaned; ) {
|
||||||
tx_desc = E1000_TX_DESC(*tx_ring, i);
|
tx_desc = E1000_TX_DESC(*tx_ring, i);
|
||||||
buffer_info = &tx_ring->buffer_info[i];
|
buffer_info = &tx_ring->buffer_info[i];
|
||||||
cleaned = (i == eop);
|
cleaned = (i == eop);
|
||||||
|
|
||||||
#ifdef NETIF_F_TSO
|
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
|
||||||
if (!(netdev->features & NETIF_F_TSO)) {
|
|
||||||
#endif
|
|
||||||
e1000_unmap_and_free_tx_resource(adapter,
|
|
||||||
buffer_info);
|
|
||||||
#ifdef NETIF_F_TSO
|
|
||||||
} else {
|
|
||||||
if (cleaned) {
|
|
||||||
memcpy(&tx_ring->previous_buffer_info,
|
|
||||||
buffer_info,
|
|
||||||
sizeof(struct e1000_buffer));
|
|
||||||
memset(buffer_info, 0,
|
|
||||||
sizeof(struct e1000_buffer));
|
|
||||||
} else {
|
|
||||||
e1000_unmap_and_free_tx_resource(
|
|
||||||
adapter, buffer_info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tx_desc->buffer_addr = 0;
|
tx_desc->buffer_addr = 0;
|
||||||
tx_desc->lower.data = 0;
|
tx_desc->lower.data = 0;
|
||||||
|
@ -3318,12 +3308,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||||
netif_stop_queue(netdev);
|
netif_stop_queue(netdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef NETIF_F_TSO
|
|
||||||
if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
|
|
||||||
time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
|
|
||||||
e1000_unmap_and_free_tx_resource(
|
|
||||||
adapter, &tx_ring->previous_buffer_info);
|
|
||||||
#endif
|
|
||||||
return cleaned;
|
return cleaned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue