Add Intel Skylake/I219 Support

- New em(4) device in currently shipping products

Differential Revision:	https://reviews.freebsd.org/D3163
Submitted by:	erj@freebsd.org
Reviewed by:	jfv@freebsd.org
MFC after:	2 weeks
Sponsored by:	Intel Corporation
This commit is contained in:
Sean Bruno 2015-09-17 15:11:45 +00:00
parent 042e9bdc41
commit 25fd5dd9a0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=287914
2 changed files with 165 additions and 3 deletions

View File

@ -103,7 +103,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
char em_driver_version[] = "7.4.2";
char em_driver_version[] = "7.5.2";
/*********************************************************************
* PCI Device ID Table
@ -191,6 +191,11 @@ static em_vendor_info_t em_vendor_info_array[] =
{ 0x8086, E1000_DEV_ID_PCH_I218_V2, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH_I218_LM3, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH_I218_V3, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH_SPT_I219_V, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM2,
PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH_SPT_I219_V2, PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@ -238,6 +243,7 @@ static void em_free_pci_resources(struct adapter *);
static void em_local_timer(void *);
static void em_reset(struct adapter *);
static int em_setup_interface(device_t, struct adapter *);
static void em_flush_desc_rings(struct adapter *);
static void em_setup_transmit_structures(struct adapter *);
static void em_initialize_transmit_unit(struct adapter *);
@ -583,6 +589,20 @@ em_attach(device_t dev)
goto err_pci;
}
/*
** In the new SPT device flash is not a
** separate BAR, rather it is also in BAR0,
** so use the same tag and handle for the
** FLASH read/write macros in the shared
** code.
*/
if (hw->mac.type == e1000_pch_spt) {
adapter->osdep.flash_bus_space_tag =
adapter->osdep.mem_bus_space_tag;
adapter->osdep.flash_bus_space_handle =
adapter->osdep.mem_bus_space_handle;
}
/*
* Setup MSI/X or MSI if PCI Express
*/
@ -1168,6 +1188,7 @@ em_ioctl(if_t ifp, u_long command, caddr_t data)
case e1000_ich10lan:
case e1000_pch2lan:
case e1000_pch_lpt:
case e1000_pch_spt:
case e1000_82574:
case e1000_82583:
case e1000_80003es2lan: /* 9K Jumbo Frame size */
@ -1369,8 +1390,15 @@ em_init_locked(struct adapter *adapter)
if_clearhwassist(ifp);
if (if_getcapenable(ifp) & IFCAP_TXCSUM)
if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP, 0);
if (if_getcapenable(ifp) & IFCAP_TSO4)
if_sethwassistbits(ifp, CSUM_TSO, 0);
/*
** There have proven to be problems with TSO when not
** at full gigabit speed, so disable the assist automatically
** when at lower speeds. -jfv
*/
if (if_getcapenable(ifp) & IFCAP_TSO4) {
if (adapter->link_speed == SPEED_1000)
if_sethwassistbits(ifp, CSUM_TSO, 0);
}
/* Configure for OS presence */
em_init_manageability(adapter);
@ -2350,6 +2378,8 @@ em_update_link_status(struct adapter *adapter)
switch (hw->phy.media_type) {
case e1000_media_type_copper:
if (hw->mac.get_link_status) {
if (hw->mac.type == e1000_pch_spt)
msec_delay(50);
/* Do the work to read phy */
e1000_check_for_link(hw);
link_check = !hw->mac.get_link_status;
@ -2441,6 +2471,10 @@ em_stop(void *arg)
EM_TX_UNLOCK(txr);
}
/* I219 needs some special flushing to avoid hangs */
if (adapter->hw.mac.type == e1000_pch_spt)
em_flush_desc_rings(adapter);
e1000_reset_hw(&adapter->hw);
E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0);
@ -2860,6 +2894,116 @@ em_setup_msix(struct adapter *adapter)
}
/*
** The 3 following flush routines are used as a workaround in the
** I219 client parts and only for them.
**
** em_flush_tx_ring - remove all descriptors from the tx_ring
**
** We want to clear all pending descriptors from the TX ring.
** zeroing happens when the HW reads the regs. We assign the ring itself as
** the data of the next descriptor. We don't care about the data we are about
** to reset the HW.
*/
static void
em_flush_tx_ring(struct adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct tx_ring *txr = adapter->tx_rings;
struct e1000_tx_desc *txd;
u32 tctl, txd_lower = E1000_TXD_CMD_IFCS;
u16 size = 512;
tctl = E1000_READ_REG(hw, E1000_TCTL);
E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN);
txd = &txr->tx_base[txr->next_avail_desc++];
if (txr->next_avail_desc == adapter->num_tx_desc)
txr->next_avail_desc = 0;
/* Just use the ring as a dummy buffer addr */
txd->buffer_addr = txr->txdma.dma_paddr;
txd->lower.data = htole32(txd_lower | size);
txd->upper.data = 0;
/* flush descriptors to memory before notifying the HW */
wmb();
E1000_WRITE_REG(hw, E1000_TDT(0), txr->next_avail_desc);
mb();
usec_delay(250);
}
/*
** em_flush_rx_ring - remove all descriptors from the rx_ring
**
** Mark all descriptors in the RX ring as consumed and disable the rx ring
*/
static void
em_flush_rx_ring(struct adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 rctl, rxdctl;
rctl = E1000_READ_REG(hw, E1000_RCTL);
E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
E1000_WRITE_FLUSH(hw);
usec_delay(150);
rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0));
/* zero the lower 14 bits (prefetch and host thresholds) */
rxdctl &= 0xffffc000;
/*
* update thresholds: prefetch threshold to 31, host threshold to 1
* and make sure the granularity is "descriptors" and not "cache lines"
*/
rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC);
E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl);
/* momentarily enable the RX ring for the changes to take effect */
E1000_WRITE_REG(hw, E1000_RCTL, rctl | E1000_RCTL_EN);
E1000_WRITE_FLUSH(hw);
usec_delay(150);
E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
}
/*
** em_flush_desc_rings - remove all descriptors from the descriptor rings
**
** In i219, the descriptor rings must be emptied before resetting the HW
** or before changing the device state to D3 during runtime (runtime PM).
**
** Failure to do this will cause the HW to enter a unit hang state which can
** only be released by PCI reset on the device
**
*/
static void
em_flush_desc_rings(struct adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
device_t dev = adapter->dev;
u16 hang_state;
u32 fext_nvm11, tdlen;
/* First, disable MULR fix in FEXTNVM11 */
fext_nvm11 = E1000_READ_REG(hw, E1000_FEXTNVM11);
fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX;
E1000_WRITE_REG(hw, E1000_FEXTNVM11, fext_nvm11);
/* do nothing if we're not in faulty state, or if the queue is empty */
tdlen = E1000_READ_REG(hw, E1000_TDLEN(0));
hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2);
if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen)
return;
em_flush_tx_ring(adapter);
/* recheck, maybe the fault is caused by the rx ring */
hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2);
if (hang_state & FLUSH_DESC_REQUIRED)
em_flush_rx_ring(adapter);
}
/*********************************************************************
*
* Initialize the hardware to a configuration
@ -2921,6 +3065,7 @@ em_reset(struct adapter *adapter)
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
case e1000_pch_spt:
pba = E1000_PBA_26K;
break;
default:
@ -2979,6 +3124,7 @@ em_reset(struct adapter *adapter)
break;
case e1000_pch2lan:
case e1000_pch_lpt:
case e1000_pch_spt:
hw->fc.high_water = 0x5C20;
hw->fc.low_water = 0x5048;
hw->fc.pause_time = 0x0650;
@ -3003,6 +3149,10 @@ em_reset(struct adapter *adapter)
break;
}
/* I219 needs some special flushing to avoid hangs */
if (hw->mac.type == e1000_pch_spt)
em_flush_desc_rings(adapter);
/* Issue a global reset */
e1000_reset_hw(hw);
E1000_WRITE_REG(hw, E1000_WUC, 0);
@ -3599,6 +3749,15 @@ em_initialize_transmit_unit(struct adapter *adapter)
/* This write will effectively turn on the transmit unit. */
E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl);
if (hw->mac.type == e1000_pch_spt) {
u32 reg;
reg = E1000_READ_REG(hw, E1000_IOSFPC);
reg |= E1000_RCTL_RDMTS_HEX;
E1000_WRITE_REG(hw, E1000_IOSFPC, reg);
reg = E1000_READ_REG(hw, E1000_TARC(0));
reg |= E1000_TARC0_CB_MULTIQ_3_REQ;
E1000_WRITE_REG(hw, E1000_TARC(0), reg);
}
}

View File

@ -218,6 +218,9 @@
#define EM_TX_HUNG 0x80000000
#define EM_TX_MAXTRIES 10
#define PCICFG_DESC_RING_STATUS 0xe4
#define FLUSH_DESC_REQUIRED 0x100
/*
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
* multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will