Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd803241 authored by Jeff Kirsher's avatar Jeff Kirsher Committed by Jeff Garzik
Browse files

e1000: Fixes for 8357x



- TSO workaround
- Fixes eeprom version reporting
- Fix loopback test
- Fix for WOL

Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarJohn Ronciak <john.ronciak@intel.com>
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
parent ff7eba15
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -188,11 +188,13 @@ struct e1000_tx_ring {
	/* array of buffer information structs */
	struct e1000_buffer *buffer_info;

	struct e1000_buffer previous_buffer_info;
	spinlock_t tx_lock;
	uint16_t tdh;
	uint16_t tdt;
	uint64_t pkt;

	boolean_t last_tx_tso;

};

struct e1000_rx_ring {
+72 −23
Original line number Diff line number Diff line
@@ -562,10 +562,29 @@ e1000_get_drvinfo(struct net_device *netdev,
                       struct ethtool_drvinfo *drvinfo)
{
	struct e1000_adapter *adapter = netdev_priv(netdev);
	char firmware_version[32];
	uint16_t eeprom_data;

	strncpy(drvinfo->driver,  e1000_driver_name, 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);
	drvinfo->n_stats = E1000_STATS_LEN;
	drvinfo->testinfo_len = E1000_TEST_LEN;
@@ -1309,21 +1328,32 @@ static int
e1000_setup_loopback_test(struct e1000_adapter *adapter)
{
	uint32_t rctl;
	struct e1000_hw *hw = &adapter->hw;

	if(adapter->hw.media_type == e1000_media_type_fiber ||
	   adapter->hw.media_type == e1000_media_type_internal_serdes) {
		if(adapter->hw.mac_type == e1000_82545 ||
		   adapter->hw.mac_type == e1000_82546 ||
		   adapter->hw.mac_type == e1000_82545_rev_3 ||
		   adapter->hw.mac_type == e1000_82546_rev_3)
	if (hw->media_type == e1000_media_type_fiber ||
	   hw->media_type == e1000_media_type_internal_serdes) {
		switch (hw->mac_type) {
		case e1000_82545:
		case e1000_82546:
		case e1000_82545_rev_3:
		case e1000_82546_rev_3:
			return e1000_set_phy_loopback(adapter);
		else {
			rctl = E1000_READ_REG(&adapter->hw, RCTL);
			break;
		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;
			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
			E1000_WRITE_REG(hw, RCTL, rctl);
			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 7;
@@ -1334,25 +1364,36 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
	uint32_t rctl;
	uint16_t phy_reg;
	struct e1000_hw *hw = &adapter->hw;

	rctl = E1000_READ_REG(&adapter->hw, RCTL);
	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);

	if(adapter->hw.media_type == e1000_media_type_copper ||
	   ((adapter->hw.media_type == e1000_media_type_fiber ||
	     adapter->hw.media_type == e1000_media_type_internal_serdes) &&
	    (adapter->hw.mac_type == e1000_82545 ||
	     adapter->hw.mac_type == e1000_82546 ||
	     adapter->hw.mac_type == e1000_82545_rev_3 ||
	     adapter->hw.mac_type == e1000_82546_rev_3))) {
		adapter->hw.autoneg = TRUE;
		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
	switch (hw->mac_type) {
	case e1000_82571:
	case e1000_82572:
		if (hw->media_type == e1000_media_type_fiber ||
		   hw->media_type == e1000_media_type_internal_serdes){
#define E1000_SERDES_LB_OFF 0x400
			E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
			msec_delay(10);
			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) {
			phy_reg &= ~MII_CR_LOOPBACK;
			e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
			e1000_phy_reset(&adapter->hw);
			e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
			e1000_phy_reset(hw);
		}
		break;
	}
}

@@ -1681,6 +1722,14 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
		msleep_interruptible(data * 1000);
		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 {
		E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
			E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | 
+48 −19
Original line number Diff line number Diff line
@@ -563,11 +563,13 @@ e1000_reset_hw(struct e1000_hw *hw)
            msec_delay(20);
            break;
        case e1000_82573:
            if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
                udelay(10);
                ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
                ctrl_ext |= E1000_CTRL_EXT_EE_RST;
                E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
                E1000_WRITE_FLUSH(hw);
            }
            /* fall through */
        case e1000_82571:
        case e1000_82572:
@@ -844,12 +846,18 @@ e1000_setup_link(struct e1000_hw *hw)
     * control setting, then the variable hw->fc will
     * 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");
                return -E1000_ERR_EEPROM;
            }

    if(hw->fc == e1000_fc_default) {
            if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
                hw->fc = e1000_fc_none;
            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;
            else
                hw->fc = e1000_fc_full;
            break;
        }
    }

    /* 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) {
        /* Read the device control register and assert the E1000_CTRL_PHY_RST
         * 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);
        E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
        E1000_WRITE_FLUSH(hw);
        
        if (hw->mac_type < e1000_82571) 
            msec_delay(10);
        
        E1000_WRITE_REG(hw, CTRL, ctrl);
        E1000_WRITE_FLUSH(hw);
        
        if (hw->mac_type >= e1000_82571)
            msec_delay(10);
    } else {
        /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
         * 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_width = e1000_bus_width_unknown;
        break;
    case e1000_82571:
    case e1000_82572:
    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_speed = e1000_bus_speed_2500;
        hw->bus_width = e1000_bus_width_pciex_4;
@@ -6650,6 +6673,12 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
        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;
}

+3 −1
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ typedef enum {
    e1000_bus_width_32,
    e1000_bus_width_64,
    e1000_bus_width_pciex_1,
    e1000_bus_width_pciex_2,
    e1000_bus_width_pciex_4,
    e1000_bus_width_reserved
} e1000_bus_width;
@@ -149,6 +150,7 @@ typedef enum {
    e1000_igp_cable_length_90  = 90,
    e1000_igp_cable_length_100 = 100,
    e1000_igp_cable_length_110 = 110,
    e1000_igp_cable_length_115 = 115,
    e1000_igp_cable_length_120 = 120,
    e1000_igp_cable_length_130 = 130,
    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_SHADV     0x00200000 /* Shadow RAM Data Valid */
#define E1000_EECD_SEC1VAL   0x00400000 /* Sector One Valid */
#define E1000_EECD_SECVAL_SHIFT      22
#define E1000_STM_OPCODE     0xDB00
#define E1000_HICR_FW_RESET  0xC0

@@ -1951,7 +1954,6 @@ struct e1000_host_command_info {

#define E1000_MDALIGN          4096

#define E1000_GCR_BEM32                 0x00400000
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Function Active and Power State to MNG */
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK         0x00000003
+24 −40
Original line number Diff line number Diff line
@@ -711,6 +711,7 @@ e1000_probe(struct pci_dev *pdev,
		break;
	case e1000_82546:
	case e1000_82546_rev_3:
	case e1000_82571:
		if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
		   && (adapter->hw.media_type == e1000_media_type_copper)) {
			e1000_read_eeprom(&adapter->hw,
@@ -1158,7 +1159,6 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
		return -ENOMEM;
	}
	memset(txdr->buffer_info, 0, size);
	memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));

	/* round up to nearest 4K */

@@ -1813,11 +1813,6 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,

	/* 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++) {
		buffer_info = &tx_ring->buffer_info[i];
		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_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->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];
		size = min(len, max_per_txd);
#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
		 * in TSO mode.  Append 4-byte sentinel desc */
		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)
		count++;
#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);

	if(adapter->pcix_82544)
@@ -2774,9 +2788,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
		return NETDEV_TX_OK;
	}

	if (likely(tso))
	if (likely(tso)) {
		tx_ring->last_tx_tso = 1;
		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;

	/* 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);

	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; ) {
			tx_desc = E1000_TX_DESC(*tx_ring, i);
			buffer_info = &tx_ring->buffer_info[i];
			cleaned = (i == eop);

#ifdef NETIF_F_TSO
			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
			e1000_unmap_and_free_tx_resource(adapter, buffer_info);

			tx_desc->buffer_addr = 0;
			tx_desc->lower.data = 0;
@@ -3318,12 +3308,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
			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;
}