From 74dc37549af2a2c5a84a4b9aa9493437b50f294f Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sat, 9 Dec 2017 12:10:25 +0800 Subject: [PATCH] em/emx: Sync with Intel's em 7.6.2 - Fix RX filter settings when exiting promiscous mode. - Add workaround for I219 resetting. - Fix some settings for 82574. Tested-by: dillon@ (I219) --- share/man/man4/em.4 | 30 +- sys/dev/netif/em/if_em.c | 253 ++++++++- sys/dev/netif/em/if_em.h | 7 +- sys/dev/netif/emx/if_emx.c | 234 +++++++- sys/dev/netif/emx/if_emx.h | 10 + sys/dev/netif/ig_hal/e1000_80003es2lan.c | 4 +- sys/dev/netif/ig_hal/e1000_80003es2lan.h | 4 +- sys/dev/netif/ig_hal/e1000_82540.c | 4 +- sys/dev/netif/ig_hal/e1000_82541.c | 4 +- sys/dev/netif/ig_hal/e1000_82541.h | 4 +- sys/dev/netif/ig_hal/e1000_82542.c | 4 +- sys/dev/netif/ig_hal/e1000_82543.c | 4 +- sys/dev/netif/ig_hal/e1000_82543.h | 4 +- sys/dev/netif/ig_hal/e1000_82571.c | 4 +- sys/dev/netif/ig_hal/e1000_82571.h | 4 +- sys/dev/netif/ig_hal/e1000_api.c | 12 +- sys/dev/netif/ig_hal/e1000_api.h | 8 +- sys/dev/netif/ig_hal/e1000_defines.h | 18 +- sys/dev/netif/ig_hal/e1000_hw.h | 34 +- sys/dev/netif/ig_hal/e1000_ich8lan.c | 694 ++++++++++++++--------- sys/dev/netif/ig_hal/e1000_ich8lan.h | 36 +- sys/dev/netif/ig_hal/e1000_mac.c | 11 +- sys/dev/netif/ig_hal/e1000_mac.h | 9 +- sys/dev/netif/ig_hal/e1000_manage.c | 7 +- sys/dev/netif/ig_hal/e1000_manage.h | 5 +- sys/dev/netif/ig_hal/e1000_nvm.c | 8 +- sys/dev/netif/ig_hal/e1000_nvm.h | 6 +- sys/dev/netif/ig_hal/e1000_osdep.h | 50 +- sys/dev/netif/ig_hal/e1000_phy.c | 11 +- sys/dev/netif/ig_hal/e1000_phy.h | 4 +- sys/dev/netif/ig_hal/e1000_regs.h | 15 +- 31 files changed, 1001 insertions(+), 501 deletions(-) diff --git a/share/man/man4/em.4 b/share/man/man4/em.4 index 418ee40dc2..a625301f13 100644 --- a/share/man/man4/em.4 +++ b/share/man/man4/em.4 @@ -31,7 +31,7 @@ .\" .\" $FreeBSD: src/share/man/man4/em.4,v 1.30 2008/10/06 21:55:53 simon Exp $ .\" -.Dd May 26, 2017 +.Dd December 17, 2017 .Dt EM 4 .Os .Sh NAME @@ -217,16 +217,14 @@ Intel 82540EP Gigabit Ethernet Controller .It Intel 82543GC Gigabit Ethernet Controller .It -Intel 82544 Gigabit Ethernet Controller -.It Intel 82544EI Gigabit Ethernet Controller .It +Intel 82544GC Gigabit Ethernet Controller +.It Intel 82545GM Gigabit Ethernet Controller .It Intel 82546EB Gigabit Ethernet Controller .It -Intel 82547EI Gigabit Ethernet Controller -.It Intel 82547GI Gigabit Ethernet Controller .It Intel 82567 Gigabit Ethernet Controller @@ -241,11 +239,17 @@ Intel 82573L Gigabit Ethernet Controller .It Intel 82573V Gigabit Ethernet Controller .It -Intel 82574 Gigabit Ethernet Controller +Intel 82574IT Gigabit Ethernet Controller +.It +Intel 82574L Gigabit Ethernet Controller +.It +Intel 82578DC Gigabit Ethernet PHY +.It +Intel 82578DM Gigabit Ethernet PHY .It -Intel 82578 Gigabit Ethernet PHY +Intel 82579LM Gigabit Ethernet PHY .It -Intel 82579 Gigabit Ethernet Controller +Intel 82579V Gigabit Ethernet PHY .It Intel Ethernet Connection I217-LM .It @@ -263,8 +267,6 @@ Intel Gigabit CT Desktop Adapter .It Intel PRO/1000 F Server Adapter .It -Intel PRO/1000 GT Quad Port Server Adapter -.It Intel PRO/1000 MF Dual Port Server Adapter .It Intel PRO/1000 MF Server Adapter @@ -275,22 +277,14 @@ Intel PRO/1000 MT Dual Port Server Adapter .It Intel PRO/1000 MT Quad Port Server Adapter .It -Intel PRO/1000 MT Server Adapter -.It Intel PRO/1000 PF Dual Port Server Adapter .It -Intel PRO/1000 PF Quad Port Server Adapter -.It -Intel PRO/1000 PF Server Adapter -.It Intel PRO/1000 PT Dual Port Server Adapter .It Intel PRO/1000 PT Quad Port Low Profile Server Adapter .It Intel PRO/1000 PT Quad Port Server Adapter .It -Intel PRO/1000 PT Server Adapter -.It Intel PRO/1000 T Server Adapter .It Intel PRO/1000 XT Low Profile Server Adapter diff --git a/sys/dev/netif/em/if_em.c b/sys/dev/netif/em/if_em.c index f4b6381dbc..0e8cc39764 100644 --- a/sys/dev/netif/em/if_em.c +++ b/sys/dev/netif/em/if_em.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2004 Joerg Sonnenberger . All rights reserved. * - * Copyright (c) 2001-2014, Intel Corporation + * Copyright (c) 2001-2015, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -117,7 +117,7 @@ #define DEBUG_HW 0 #define EM_NAME "Intel(R) PRO/1000 Network Connection " -#define EM_VER " 7.4.2" +#define EM_VER " 7.6.2" #define _EM_DEVICE(id, ret) \ { EM_VENDOR_ID, E1000_DEV_ID_##id, ret, EM_NAME #id EM_VER } @@ -246,7 +246,7 @@ static const struct em_vendor_info em_vendor_info_array[] = { EM_EMX_DEVICE(PCH_SPT_I219_V), EM_EMX_DEVICE(PCH_SPT_I219_LM2), EM_EMX_DEVICE(PCH_SPT_I219_V2), - EM_EMX_DEVICE(PCH_SPT_I219_LM3), + EM_EMX_DEVICE(PCH_LBG_I219_LM3), EM_EMX_DEVICE(PCH_SPT_I219_LM4), EM_EMX_DEVICE(PCH_SPT_I219_V4), EM_EMX_DEVICE(PCH_SPT_I219_LM5), @@ -322,6 +322,9 @@ static void em_update_link_status(struct adapter *); static void em_smartspeed(struct adapter *); static void em_set_itr(struct adapter *, uint32_t); static void em_disable_aspm(struct adapter *); +static void em_flush_tx_ring(struct adapter *); +static void em_flush_rx_ring(struct adapter *); +static void em_flush_txrx_ring(struct adapter *); /* Hardware workarounds */ static int em_82547_fifo_workaround(struct adapter *, int); @@ -501,12 +504,19 @@ em_attach(device_t dev) struct ifnet *ifp = &adapter->arpcom.ac_if; int tsize, rsize; int error = 0; + int cap; uint16_t eeprom_data, device_id, apme_mask; driver_intr_t *intr_func; char flowctrl[IFM_ETH_FC_STRLEN]; adapter->dev = adapter->osdep.dev = dev; + /* + * Some versions of I219 only have PCI AF. + */ + if (pci_is_pcie(dev) || pci_find_extcap(dev, PCIY_PCIAF, &cap) == 0) + adapter->flags |= EM_FLAG_GEN2; + callout_init_mp(&adapter->timer); callout_init_mp(&adapter->tx_fifo_timer); callout_init_mp(&adapter->tx_gc_timer); @@ -559,6 +569,17 @@ em_attach(device_t dev) * XXX this goof is actually not used. */ adapter->hw.flash_address = (uint8_t *)adapter->flash; + } else if (adapter->hw.mac.type == e1000_pch_spt) { + /* + * In the new SPT device flash is not a seperate BAR, + * rather it is also in BAR0, so use the same tag and + * an offset handle for the FLASH read/write macros + * in the shared code. + */ + adapter->osdep.flash_bus_space_tag = + adapter->osdep.mem_bus_space_tag; + adapter->osdep.flash_bus_space_handle = + adapter->osdep.mem_bus_space_handle + E1000_FLASH_BASE_ADDR; } switch (adapter->hw.mac.type) { @@ -582,7 +603,7 @@ em_attach(device_t dev) /* FALL THROUGH */ default: - if (pci_is_pcie(dev)) + if (adapter->flags & EM_FLAG_GEN2) adapter->flags |= EM_FLAG_TSO; break; } @@ -2077,13 +2098,30 @@ em_set_promisc(struct adapter *adapter) static void em_disable_promisc(struct adapter *adapter) { + struct ifnet *ifp = &adapter->arpcom.ac_if; uint32_t reg_rctl; + int mcnt = 0; reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); + reg_rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_SBP); + + if (ifp->if_flags & IFF_ALLMULTI) { + mcnt = MAX_NUM_MULTICAST_ADDRESSES; + } else { + const struct ifmultiaddr *ifma; + + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) + break; + mcnt++; + } + } + /* Don't disable if in MAX groups */ + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + reg_rctl &= ~E1000_RCTL_MPE; - reg_rctl &= ~E1000_RCTL_UPE; - reg_rctl &= ~E1000_RCTL_MPE; - reg_rctl &= ~E1000_RCTL_SBP; E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); } @@ -2180,6 +2218,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; @@ -2221,7 +2261,7 @@ em_update_link_status(struct adapter *adapter) int tarc0; tarc0 = E1000_READ_REG(hw, E1000_TARC(0)); - tarc0 &= ~SPEED_MODE_BIT; + tarc0 &= ~TARC_SPEED_MODE_BIT; E1000_WRITE_REG(hw, E1000_TARC(0), tarc0); } if (bootverbose) { @@ -2277,6 +2317,10 @@ em_stop(struct adapter *adapter) adapter->tx_running = 0; callout_stop(&adapter->tx_gc_timer); + /* I219 needs some special flushing to avoid hangs */ + if (adapter->hw.mac.type == e1000_pch_spt) + em_flush_txrx_ring(adapter); + e1000_reset_hw(&adapter->hw); if (adapter->hw.mac.type >= e1000_82544) E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0); @@ -2338,7 +2382,7 @@ em_alloc_pci_res(struct adapter *adapter) { device_t dev = adapter->dev; u_int intr_flags; - int val, rid, msi_enable, cap; + int val, rid, msi_enable; /* Enable bus mastering */ pci_enable_busmaster(dev); @@ -2401,13 +2445,10 @@ em_alloc_pci_res(struct adapter *adapter) * * Don't enable MSI on 82571/82572, see: * 82571/82572 specification update errata #63 - * - * Some versions of I219 only have PCI AF. */ msi_enable = em_msi_enable; if (msi_enable && - (!(pci_is_pcie(dev) || - pci_find_extcap(dev, PCIY_PCIAF, &cap) == 0) || + ((adapter->flags & EM_FLAG_GEN2) == 0 || adapter->hw.mac.type == e1000_82571 || adapter->hw.mac.type == e1000_82572)) msi_enable = 0; @@ -2648,6 +2689,10 @@ em_reset(struct adapter *adapter) break; } + /* I219 needs some special flushing to avoid hangs */ + if (adapter->hw.mac.type == e1000_pch_spt) + em_flush_txrx_ring(adapter); + /* Issue a global reset */ e1000_reset_hw(&adapter->hw); if (adapter->hw.mac.type >= e1000_82544) @@ -2902,6 +2947,18 @@ em_init_tx_unit(struct adapter *adapter) /* Setup the HW Tx Head and Tail descriptor pointers */ E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0); E1000_WRITE_REG(&adapter->hw, E1000_TDH(0), 0); + if (adapter->flags & EM_FLAG_GEN2) { + uint32_t txdctl = 0; + + txdctl |= 0x1f; /* PTHRESH */ + txdctl |= 1 << 8; /* HTHRESH */ + txdctl |= 1 << 16; /* WTHRESH */ + txdctl |= 1 << 22; /* Reserved bit 22 must always be 1 */ + txdctl |= E1000_TXDCTL_GRAN; + txdctl |= 1 << 25; /* LWTHRESH */ + + E1000_WRITE_REG(&adapter->hw, E1000_TXDCTL(0), txdctl); + } /* Set the default values for the Tx Inter Packet Gap timer */ switch (adapter->hw.mac.type) { @@ -2939,15 +2996,20 @@ em_init_tx_unit(struct adapter *adapter) if (adapter->hw.mac.type == e1000_82571 || adapter->hw.mac.type == e1000_82572) { tarc = E1000_READ_REG(&adapter->hw, E1000_TARC(0)); - tarc |= SPEED_MODE_BIT; + tarc |= TARC_SPEED_MODE_BIT; E1000_WRITE_REG(&adapter->hw, E1000_TARC(0), tarc); } else if (adapter->hw.mac.type == e1000_80003es2lan) { + /* errata: program both queues to unweighted RR */ tarc = E1000_READ_REG(&adapter->hw, E1000_TARC(0)); tarc |= 1; E1000_WRITE_REG(&adapter->hw, E1000_TARC(0), tarc); tarc = E1000_READ_REG(&adapter->hw, E1000_TARC(1)); tarc |= 1; E1000_WRITE_REG(&adapter->hw, E1000_TARC(1), tarc); + } else if (adapter->hw.mac.type == e1000_82574) { + tarc = E1000_READ_REG(&adapter->hw, E1000_TARC(0)); + tarc |= TARC_ERRATA_BIT; + E1000_WRITE_REG(&adapter->hw, E1000_TARC(0), tarc); } /* Program the Transmit Control Register */ @@ -2969,6 +3031,15 @@ em_init_tx_unit(struct adapter *adapter) tarc = E1000_READ_REG(&adapter->hw, E1000_TARC(1)); tarc &= ~(1 << 28); E1000_WRITE_REG(&adapter->hw, E1000_TARC(1), tarc); + } else if (adapter->hw.mac.type == e1000_pch_spt) { + uint32_t reg; + + reg = E1000_READ_REG(&adapter->hw, E1000_IOSFPC); + reg |= E1000_RCTL_RDMTS_HEX; + E1000_WRITE_REG(&adapter->hw, E1000_IOSFPC, reg); + reg = E1000_READ_REG(&adapter->hw, E1000_TARC(0)); + reg |= E1000_TARC0_CB_MULTIQ_3_REQ; + E1000_WRITE_REG(&adapter->hw, E1000_TARC(0), reg); } } @@ -3388,14 +3459,17 @@ em_init_rx_unit(struct adapter *adapter) { struct ifnet *ifp = &adapter->arpcom.ac_if; uint64_t bus_addr; - uint32_t rctl; + uint32_t rctl, rxcsum; /* * Make sure receives are disabled while setting * up the descriptor ring */ rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); - E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); + /* Do not disable if ever enabled on this hardware */ + if (adapter->hw.mac.type != e1000_82574 && + adapter->hw.mac.type != e1000_82583) + E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); if (adapter->hw.mac.type >= e1000_82540) { uint32_t itr; @@ -3413,18 +3487,20 @@ em_init_rx_unit(struct adapter *adapter) /* Disable accelerated ackknowledge */ if (adapter->hw.mac.type == e1000_82574) { - E1000_WRITE_REG(&adapter->hw, - E1000_RFCTL, E1000_RFCTL_ACK_DIS); - } + uint32_t rfctl; - /* Receive Checksum Offload for TCP and UDP */ - if (ifp->if_capenable & IFCAP_RXCSUM) { - uint32_t rxcsum; + rfctl = E1000_READ_REG(&adapter->hw, E1000_RFCTL); + rfctl |= E1000_RFCTL_ACK_DIS; + E1000_WRITE_REG(&adapter->hw, E1000_RFCTL, rfctl); + } - rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM); + /* Receive Checksum Offload for IP and TCP/UDP */ + rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM); + if (ifp->if_capenable & IFCAP_RXCSUM) rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); - E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum); - } + else + rxcsum &= ~(E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); + E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum); /* * XXX TEMPORARY WORKAROUND: on some systems with 82573 @@ -3456,14 +3532,23 @@ em_init_rx_unit(struct adapter *adapter) E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), adapter->num_rx_desc - 1); /* Set PTHRESH for improved jumbo performance */ - if (((adapter->hw.mac.type == e1000_ich9lan) || - (adapter->hw.mac.type == e1000_pch2lan) || - (adapter->hw.mac.type == e1000_ich10lan)) && - (ifp->if_mtu > ETHERMTU)) { + if (ifp->if_mtu > ETHERMTU) { uint32_t rxdctl; - rxdctl = E1000_READ_REG(&adapter->hw, E1000_RXDCTL(0)); - E1000_WRITE_REG(&adapter->hw, E1000_RXDCTL(0), rxdctl | 3); + if (adapter->hw.mac.type == e1000_ich9lan || + adapter->hw.mac.type == e1000_pch2lan || + adapter->hw.mac.type == e1000_ich10lan) { + rxdctl = E1000_READ_REG(&adapter->hw, E1000_RXDCTL(0)); + E1000_WRITE_REG(&adapter->hw, E1000_RXDCTL(0), + rxdctl | 3); + } else if (adapter->hw.mac.type == e1000_82574) { + rxdctl = E1000_READ_REG(&adapter->hw, E1000_RXDCTL(0)); + rxdctl |= 0x20; /* PTHRESH */ + rxdctl |= 4 << 8; /* HTHRESH */ + rxdctl |= 4 << 16; /* WTHRESH */ + rxdctl |= 1 << 24; /* Switch to granularity */ + E1000_WRITE_REG(&adapter->hw, E1000_RXDCTL(0), rxdctl); + } } if (adapter->hw.mac.type >= e1000_pch2lan) { @@ -4559,3 +4644,109 @@ em_tso_setup(struct adapter *adapter, struct mbuf *mp, adapter->next_avail_tx_desc = curr_txd; return 1; } + +/* + * 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 e1000_tx_desc *txd; + uint32_t tctl; + + tctl = E1000_READ_REG(hw, E1000_TCTL); + E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN); + + txd = &adapter->tx_desc_base[adapter->next_avail_tx_desc++]; + if (adapter->next_avail_tx_desc == adapter->num_tx_desc) + adapter->next_avail_tx_desc = 0; + + /* Just use the ring as a dummy buffer addr */ + txd->buffer_addr = adapter->txdma.dma_paddr; + txd->lower.data = htole32(E1000_TXD_CMD_IFCS | 512); + txd->upper.data = 0; + + E1000_WRITE_REG(hw, E1000_TDT(0), adapter->next_avail_tx_desc); + usec_delay(250); +} + +/* + * 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; + uint32_t 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); +} + +/* + * 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_txrx_ring(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + device_t dev = adapter->dev; + uint16_t hang_state; + uint32_t fext_nvm11; + + /* + * 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. + */ + hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2); + if ((hang_state & FLUSH_DESC_REQUIRED) && + E1000_READ_REG(hw, E1000_TDLEN(0))) + 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); +} diff --git a/sys/dev/netif/em/if_em.h b/sys/dev/netif/em/if_em.h index 2fc84c6b21..eaa475d248 100644 --- a/sys/dev/netif/em/if_em.h +++ b/sys/dev/netif/em/if_em.h @@ -191,6 +191,9 @@ #define EM_FC_PAUSE_TIME 1000 #define EM_EEPROM_APME 0x400; +#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 @@ -198,7 +201,8 @@ */ #define EM_DBA_ALIGN 128 -#define SPEED_MODE_BIT (1 << 21) /* On PCI-E MACs only */ +#define TARC_SPEED_MODE_BIT (1 << 21) /* On PCI-E MACs only */ +#define TARC_ERRATA_BIT (1 << 26) /* Note from errata on 82574 */ /* PCI Config defines */ #define EM_BAR_TYPE(v) ((v) & EM_BAR_TYPE_MASK) @@ -255,6 +259,7 @@ struct adapter { #define EM_FLAG_HW_CTRL 0x0008 #define EM_FLAG_TSO 0x0010 #define EM_FLAG_TSO_PULLEX 0x0020 +#define EM_FLAG_GEN2 0x0040 /* DragonFly operating-system-specific structures. */ struct e1000_osdep osdep; diff --git a/sys/dev/netif/emx/if_emx.c b/sys/dev/netif/emx/if_emx.c index 06469628f7..061ebea01f 100644 --- a/sys/dev/netif/emx/if_emx.c +++ b/sys/dev/netif/emx/if_emx.c @@ -175,7 +175,7 @@ static const struct emx_device { EMX_DEVICE(PCH_SPT_I219_V), EMX_DEVICE(PCH_SPT_I219_LM2), EMX_DEVICE(PCH_SPT_I219_V2), - EMX_DEVICE(PCH_SPT_I219_LM3), + EMX_DEVICE(PCH_LBG_I219_LM3), EMX_DEVICE(PCH_SPT_I219_LM4), EMX_DEVICE(PCH_SPT_I219_V4), EMX_DEVICE(PCH_SPT_I219_LM5), @@ -257,6 +257,9 @@ static void emx_update_link_status(struct emx_softc *); static void emx_smartspeed(struct emx_softc *); static void emx_set_itr(struct emx_softc *, uint32_t); static void emx_disable_aspm(struct emx_softc *); +static void emx_flush_tx_ring(struct emx_softc *); +static void emx_flush_rx_ring(struct emx_softc *); +static void emx_flush_txrx_ring(struct emx_softc *); static void emx_print_debug_info(struct emx_softc *); static void emx_print_nvm_info(struct emx_softc *); @@ -665,6 +668,16 @@ again: * XXX this goof is actually not used. */ sc->hw.flash_address = (uint8_t *)sc->flash; + } else if (sc->hw.mac.type == e1000_pch_spt) { + /* + * In the new SPT device flash is not a seperate BAR, + * rather it is also in BAR0, so use the same tag and + * an offset handle for the FLASH read/write macros + * in the shared code. + */ + sc->osdep.flash_bus_space_tag = sc->osdep.mem_bus_space_tag; + sc->osdep.flash_bus_space_handle = + sc->osdep.mem_bus_space_handle + E1000_FLASH_BASE_ADDR; } /* Do Shared Code initialization */ @@ -1791,13 +1804,30 @@ emx_set_promisc(struct emx_softc *sc) static void emx_disable_promisc(struct emx_softc *sc) { + struct ifnet *ifp = &sc->arpcom.ac_if; uint32_t reg_rctl; + int mcnt = 0; reg_rctl = E1000_READ_REG(&sc->hw, E1000_RCTL); + reg_rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_SBP); + + if (ifp->if_flags & IFF_ALLMULTI) { + mcnt = EMX_MCAST_ADDR_MAX; + } else { + const struct ifmultiaddr *ifma; + + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (mcnt == EMX_MCAST_ADDR_MAX) + break; + mcnt++; + } + } + /* Don't disable if in MAX groups */ + if (mcnt < EMX_MCAST_ADDR_MAX) + reg_rctl &= ~E1000_RCTL_MPE; - reg_rctl &= ~E1000_RCTL_UPE; - reg_rctl &= ~E1000_RCTL_MPE; - reg_rctl &= ~E1000_RCTL_SBP; E1000_WRITE_REG(&sc->hw, E1000_RCTL, reg_rctl); } @@ -1874,6 +1904,8 @@ emx_update_link_status(struct emx_softc *sc) 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; @@ -1971,6 +2003,10 @@ emx_stop(struct emx_softc *sc) callout_stop(&tdata->tx_gc_timer); } + /* I219 needs some special flushing to avoid hangs */ + if (sc->hw.mac.type == e1000_pch_spt) + emx_flush_txrx_ring(sc); + /* * Disable multiple receive queues. * @@ -2087,6 +2123,10 @@ emx_reset(struct emx_softc *sc) sc->hw.fc.pause_time = 0xFFFF; } + /* I219 needs some special flushing to avoid hangs */ + if (sc->hw.mac.type == e1000_pch_spt) + emx_flush_txrx_ring(sc); + /* Issue a global reset */ e1000_reset_hw(&sc->hw); E1000_WRITE_REG(&sc->hw, E1000_WUC, 0); @@ -2410,6 +2450,15 @@ emx_init_tx_unit(struct emx_softc *sc) /* Setup the HW Tx Head and Tail descriptor pointers */ E1000_WRITE_REG(&sc->hw, E1000_TDT(i), 0); E1000_WRITE_REG(&sc->hw, E1000_TDH(i), 0); + + txdctl = 0x1f; /* PTHRESH */ + txdctl |= 1 << 8; /* HTHRESH */ + txdctl |= 1 << 16; /* WTHRESH */ + txdctl |= 1 << 22; /* Reserved bit 22 must always be 1 */ + txdctl |= E1000_TXDCTL_GRAN; + txdctl |= 1 << 25; /* LWTHRESH */ + + E1000_WRITE_REG(&sc->hw, E1000_TXDCTL(i), txdctl); } /* Set the default values for the Tx Inter Packet Gap timer */ @@ -2451,12 +2500,23 @@ emx_init_tx_unit(struct emx_softc *sc) tarc |= EMX_TARC_SPEED_MODE; E1000_WRITE_REG(&sc->hw, E1000_TARC(0), tarc); } else if (sc->hw.mac.type == e1000_80003es2lan) { + /* errata: program both queues to unweighted RR */ tarc = E1000_READ_REG(&sc->hw, E1000_TARC(0)); tarc |= 1; E1000_WRITE_REG(&sc->hw, E1000_TARC(0), tarc); tarc = E1000_READ_REG(&sc->hw, E1000_TARC(1)); tarc |= 1; E1000_WRITE_REG(&sc->hw, E1000_TARC(1), tarc); + } else if (sc->hw.mac.type == e1000_82574) { + tarc = E1000_READ_REG(&sc->hw, E1000_TARC(0)); + tarc |= EMX_TARC_ERRATA; + if (sc->tx_ring_inuse > 1) { + tarc |= (EMX_TARC_COMPENSATION_MODE | EMX_TARC_MQ_FIX); + E1000_WRITE_REG(&sc->hw, E1000_TARC(0), tarc); + E1000_WRITE_REG(&sc->hw, E1000_TARC(1), tarc); + } else { + E1000_WRITE_REG(&sc->hw, E1000_TARC(0), tarc); + } } /* Program the Transmit Control Register */ @@ -2476,6 +2536,15 @@ emx_init_tx_unit(struct emx_softc *sc) tarc = E1000_READ_REG(&sc->hw, E1000_TARC(1)); tarc &= ~(1 << 28); E1000_WRITE_REG(&sc->hw, E1000_TARC(1), tarc); + } else if (sc->hw.mac.type == e1000_pch_spt) { + uint32_t reg; + + reg = E1000_READ_REG(&sc->hw, E1000_IOSFPC); + reg |= E1000_RCTL_RDMTS_HEX; + E1000_WRITE_REG(&sc->hw, E1000_IOSFPC, reg); + reg = E1000_READ_REG(&sc->hw, E1000_TARC(0)); + reg |= E1000_TARC0_CB_MULTIQ_3_REQ; + E1000_WRITE_REG(&sc->hw, E1000_TARC(0), reg); } if (sc->tx_ring_inuse > 1) { @@ -2997,7 +3066,7 @@ emx_init_rx_unit(struct emx_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; uint64_t bus_addr; - uint32_t rctl, itr, rfctl; + uint32_t rctl, itr, rfctl, rxcsum; int i; /* @@ -3005,7 +3074,9 @@ emx_init_rx_unit(struct emx_softc *sc) * up the descriptor ring */ rctl = E1000_READ_REG(&sc->hw, E1000_RCTL); - E1000_WRITE_REG(&sc->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); + /* Do not disable if ever enabled on this hardware */ + if (sc->hw.mac.type != e1000_82574) + E1000_WRITE_REG(&sc->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); /* * Set the interrupt throttling rate. Value is calculated @@ -3018,12 +3089,11 @@ emx_init_rx_unit(struct emx_softc *sc) emx_set_itr(sc, itr); /* Use extended RX descriptor */ - rfctl = E1000_RFCTL_EXTEN; - + rfctl = E1000_READ_REG(&sc->hw, E1000_RFCTL); + rfctl |= E1000_RFCTL_EXTEN; /* Disable accelerated ackknowledge */ if (sc->hw.mac.type == e1000_82574) rfctl |= E1000_RFCTL_ACK_DIS; - E1000_WRITE_REG(&sc->hw, E1000_RFCTL, rfctl); /* @@ -3033,12 +3103,9 @@ emx_init_rx_unit(struct emx_softc *sc) * queue is to be supported, since we need it to figure out * packet type. */ + rxcsum = E1000_READ_REG(&sc->hw, E1000_RXCSUM); if ((ifp->if_capenable & IFCAP_RXCSUM) || sc->rx_ring_cnt > 1) { - uint32_t rxcsum; - - rxcsum = E1000_READ_REG(&sc->hw, E1000_RXCSUM); - /* * NOTE: * PCSD must be enabled to enable multiple @@ -3046,8 +3113,11 @@ emx_init_rx_unit(struct emx_softc *sc) */ rxcsum |= E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL | E1000_RXCSUM_PCSD; - E1000_WRITE_REG(&sc->hw, E1000_RXCSUM, rxcsum); + } else { + rxcsum &= ~(E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL | + E1000_RXCSUM_PCSD); } + E1000_WRITE_REG(&sc->hw, E1000_RXCSUM, rxcsum); /* * Configure multiple receive queue (RSS) @@ -3145,6 +3215,20 @@ emx_init_rx_unit(struct emx_softc *sc) sc->rx_data[i].num_rx_desc - 1); } + /* Set PTHRESH for improved jumbo performance */ + if (ifp->if_mtu > ETHERMTU && sc->hw.mac.type == e1000_82574) { + uint32_t rxdctl; + + for (i = 0; i < sc->rx_ring_cnt; ++i) { + rxdctl = E1000_READ_REG(&sc->hw, E1000_RXDCTL(i)); + rxdctl |= 0x20; /* PTHRESH */ + rxdctl |= 4 << 8; /* HTHRESH */ + rxdctl |= 4 << 16; /* WTHRESH */ + rxdctl |= 1 << 24; /* Switch to granularity */ + E1000_WRITE_REG(&sc->hw, E1000_RXDCTL(i), rxdctl); + } + } + if (sc->hw.mac.type >= e1000_pch2lan) { if (ifp->if_mtu > ETHERMTU) e1000_lv_jumbo_workaround_ich8lan(&sc->hw, TRUE); @@ -4361,3 +4445,125 @@ emx_get_txring_inuse(const struct emx_softc *sc, boolean_t polling) else return 1; } + +/* + * 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 +emx_flush_tx_ring(struct emx_softc *sc) +{ + struct e1000_hw *hw = &sc->hw; + uint32_t tctl; + int i; + + tctl = E1000_READ_REG(hw, E1000_TCTL); + E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN); + + for (i = 0; i < sc->tx_ring_inuse; ++i) { + struct emx_txdata *tdata = &sc->tx_data[i]; + struct e1000_tx_desc *txd; + + if (E1000_READ_REG(hw, E1000_TDLEN(i)) == 0) + continue; + + txd = &tdata->tx_desc_base[tdata->next_avail_tx_desc++]; + if (tdata->next_avail_tx_desc == tdata->num_tx_desc) + tdata->next_avail_tx_desc = 0; + + /* Just use the ring as a dummy buffer addr */ + txd->buffer_addr = tdata->tx_desc_paddr; + txd->lower.data = htole32(E1000_TXD_CMD_IFCS | 512); + txd->upper.data = 0; + + E1000_WRITE_REG(hw, E1000_TDT(i), tdata->next_avail_tx_desc); + usec_delay(250); + } +} + +/* + * Remove all descriptors from the RX rings. + * + * Mark all descriptors in the RX rings as consumed and disable the RX rings. + */ +static void +emx_flush_rx_ring(struct emx_softc *sc) +{ + struct e1000_hw *hw = &sc->hw; + uint32_t rctl; + int i; + + rctl = E1000_READ_REG(hw, E1000_RCTL); + E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); + E1000_WRITE_FLUSH(hw); + usec_delay(150); + + for (i = 0; i < sc->rx_ring_cnt; ++i) { + uint32_t rxdctl; + + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); + /* 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(i), rxdctl); + } + + /* Momentarily enable the RX rings 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); +} + +/* + * 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 +emx_flush_txrx_ring(struct emx_softc *sc) +{ + struct e1000_hw *hw = &sc->hw; + device_t dev = sc->dev; + uint16_t hang_state; + uint32_t fext_nvm11, tdlen; + int i; + + /* + * 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 = 0; + for (i = 0; i < sc->tx_ring_inuse; ++i) + tdlen += E1000_READ_REG(hw, E1000_TDLEN(i)); + hang_state = pci_read_config(dev, EMX_PCICFG_DESC_RING_STATUS, 2); + if ((hang_state & EMX_FLUSH_DESC_REQUIRED) && tdlen) + emx_flush_tx_ring(sc); + + /* + * Recheck, maybe the fault is caused by the RX ring. + */ + hang_state = pci_read_config(dev, EMX_PCICFG_DESC_RING_STATUS, 2); + if (hang_state & EMX_FLUSH_DESC_REQUIRED) + emx_flush_rx_ring(sc); +} diff --git a/sys/dev/netif/emx/if_emx.h b/sys/dev/netif/emx/if_emx.h index 9d416e5eac..c25be0565f 100644 --- a/sys/dev/netif/emx/if_emx.h +++ b/sys/dev/netif/emx/if_emx.h @@ -140,6 +140,9 @@ #define EMX_FC_PAUSE_TIME 1000 #define EMX_EEPROM_APME 0x400; +#define EMX_PCICFG_DESC_RING_STATUS 0xe4 +#define EMX_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 @@ -153,6 +156,13 @@ */ #define EMX_TARC_SPEED_MODE (1 << 21) +#define EMX_TARC_COMPENSATION_MODE (1 << 7) /* Compensation Mode */ + +#define EMX_TARC_MQ_FIX (1 << 23) | \ + (1 << 24) | \ + (1 << 25) /* Handle errata in MQ mode */ +#define EMX_TARC_ERRATA (1 << 26) /* 82574 errata */ + /* * Multiple TX queues arbitration count mask in TARC0/TARC1. */ diff --git a/sys/dev/netif/ig_hal/e1000_80003es2lan.c b/sys/dev/netif/ig_hal/e1000_80003es2lan.c index eb45158176..e7c42d5386 100644 --- a/sys/dev/netif/ig_hal/e1000_80003es2lan.c +++ b/sys/dev/netif/ig_hal/e1000_80003es2lan.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ /* 80003ES2LAN Gigabit Ethernet Controller (Copper) * 80003ES2LAN Gigabit Ethernet Controller (Serdes) diff --git a/sys/dev/netif/ig_hal/e1000_80003es2lan.h b/sys/dev/netif/ig_hal/e1000_80003es2lan.h index ae923c7811..89b15512bf 100644 --- a/sys/dev/netif/ig_hal/e1000_80003es2lan.h +++ b/sys/dev/netif/ig_hal/e1000_80003es2lan.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_80003ES2LAN_H_ #define _E1000_80003ES2LAN_H_ diff --git a/sys/dev/netif/ig_hal/e1000_82540.c b/sys/dev/netif/ig_hal/e1000_82540.c index efa95233d2..2d03b8ff8e 100644 --- a/sys/dev/netif/ig_hal/e1000_82540.c +++ b/sys/dev/netif/ig_hal/e1000_82540.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ /* * 82540EM Gigabit Ethernet Controller diff --git a/sys/dev/netif/ig_hal/e1000_82541.c b/sys/dev/netif/ig_hal/e1000_82541.c index 7483dd2587..c8ac3561a2 100644 --- a/sys/dev/netif/ig_hal/e1000_82541.c +++ b/sys/dev/netif/ig_hal/e1000_82541.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ /* * 82541EI Gigabit Ethernet Controller diff --git a/sys/dev/netif/ig_hal/e1000_82541.h b/sys/dev/netif/ig_hal/e1000_82541.h index df06f0f8cd..7a01fd43ad 100644 --- a/sys/dev/netif/ig_hal/e1000_82541.h +++ b/sys/dev/netif/ig_hal/e1000_82541.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_82541_H_ #define _E1000_82541_H_ diff --git a/sys/dev/netif/ig_hal/e1000_82542.c b/sys/dev/netif/ig_hal/e1000_82542.c index cf20d88fa1..4cca9b2b2c 100644 --- a/sys/dev/netif/ig_hal/e1000_82542.c +++ b/sys/dev/netif/ig_hal/e1000_82542.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ /* * 82542 Gigabit Ethernet Controller diff --git a/sys/dev/netif/ig_hal/e1000_82543.c b/sys/dev/netif/ig_hal/e1000_82543.c index 4d29f3dda0..279e41e8b4 100644 --- a/sys/dev/netif/ig_hal/e1000_82543.c +++ b/sys/dev/netif/ig_hal/e1000_82543.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ /* * 82543GC Gigabit Ethernet Controller (Fiber) diff --git a/sys/dev/netif/ig_hal/e1000_82543.h b/sys/dev/netif/ig_hal/e1000_82543.h index b7b90789ed..e8edda5d2b 100644 --- a/sys/dev/netif/ig_hal/e1000_82543.h +++ b/sys/dev/netif/ig_hal/e1000_82543.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_82543_H_ #define _E1000_82543_H_ diff --git a/sys/dev/netif/ig_hal/e1000_82571.c b/sys/dev/netif/ig_hal/e1000_82571.c index c362c8cdeb..ec855c236f 100644 --- a/sys/dev/netif/ig_hal/e1000_82571.c +++ b/sys/dev/netif/ig_hal/e1000_82571.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ /* 82571EB Gigabit Ethernet Controller * 82571EB Gigabit Ethernet Controller (Copper) diff --git a/sys/dev/netif/ig_hal/e1000_82571.h b/sys/dev/netif/ig_hal/e1000_82571.h index 8c48b02895..8e5ca56ae8 100644 --- a/sys/dev/netif/ig_hal/e1000_82571.h +++ b/sys/dev/netif/ig_hal/e1000_82571.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_82571_H_ #define _E1000_82571_H_ diff --git a/sys/dev/netif/ig_hal/e1000_api.c b/sys/dev/netif/ig_hal/e1000_api.c index 254691da99..492ef5ec67 100644 --- a/sys/dev/netif/ig_hal/e1000_api.c +++ b/sys/dev/netif/ig_hal/e1000_api.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #include "e1000_api.h" @@ -155,11 +155,9 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) DEBUGFUNC("e1000_set_mac_type"); switch (hw->device_id) { -#ifndef NO_82542_SUPPORT case E1000_DEV_ID_82542: mac->type = e1000_82542; break; -#endif case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82543GC_COPPER: mac->type = e1000_82543; @@ -301,12 +299,12 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_PCH_I218_LM3: case E1000_DEV_ID_PCH_I218_V3: mac->type = e1000_pch_lpt; - break; + break; case E1000_DEV_ID_PCH_SPT_I219_LM: case E1000_DEV_ID_PCH_SPT_I219_V: case E1000_DEV_ID_PCH_SPT_I219_LM2: case E1000_DEV_ID_PCH_SPT_I219_V2: - case E1000_DEV_ID_PCH_SPT_I219_LM3: + case E1000_DEV_ID_PCH_LBG_I219_LM3: case E1000_DEV_ID_PCH_SPT_I219_LM4: case E1000_DEV_ID_PCH_SPT_I219_V4: case E1000_DEV_ID_PCH_SPT_I219_LM5: @@ -427,11 +425,9 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) * the functions in that family. */ switch (hw->mac.type) { -#ifndef NO_82542_SUPPORT case e1000_82542: e1000_init_function_pointers_82542(hw); break; -#endif case e1000_82543: case e1000_82544: e1000_init_function_pointers_82543(hw); diff --git a/sys/dev/netif/ig_hal/e1000_api.h b/sys/dev/netif/ig_hal/e1000_api.h index e8d64103f3..86075f8e61 100644 --- a/sys/dev/netif/ig_hal/e1000_api.h +++ b/sys/dev/netif/ig_hal/e1000_api.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,16 +30,14 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_API_H_ #define _E1000_API_H_ #include "e1000_hw.h" -#ifndef NO_82542_SUPPORT extern void e1000_init_function_pointers_82542(struct e1000_hw *hw); -#endif extern void e1000_init_function_pointers_82543(struct e1000_hw *hw); extern void e1000_init_function_pointers_82540(struct e1000_hw *hw); extern void e1000_init_function_pointers_82571(struct e1000_hw *hw); @@ -119,9 +117,7 @@ s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr); s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); -#ifndef NO_82542_SUPPORT u32 e1000_translate_register_82542(u32 reg); -#endif diff --git a/sys/dev/netif/ig_hal/e1000_defines.h b/sys/dev/netif/ig_hal/e1000_defines.h index aa82e39fad..78321ee4cb 100644 --- a/sys/dev/netif/ig_hal/e1000_defines.h +++ b/sys/dev/netif/ig_hal/e1000_defines.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_DEFINES_H_ #define _E1000_DEFINES_H_ @@ -727,9 +727,7 @@ #define E1000_COLD_SHIFT 12 /* Default values for the transmit IPG register */ -#ifndef NO_82542_SUPPORT #define DEFAULT_82542_TIPG_IPGT 10 -#endif #define DEFAULT_82543_TIPG_IPGT_FIBER 9 #define DEFAULT_82543_TIPG_IPGT_COPPER 8 @@ -737,15 +735,11 @@ #define E1000_TIPG_IPGR1_MASK 0x000FFC00 #define E1000_TIPG_IPGR2_MASK 0x3FF00000 -#ifndef NO_82542_SUPPORT #define DEFAULT_82542_TIPG_IPGR1 2 -#endif #define DEFAULT_82543_TIPG_IPGR1 8 #define E1000_TIPG_IPGR1_SHIFT 10 -#ifndef NO_82542_SUPPORT #define DEFAULT_82542_TIPG_IPGR2 10 -#endif #define DEFAULT_82543_TIPG_IPGR2 6 #define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 #define E1000_TIPG_IPGR2_SHIFT 20 @@ -755,6 +749,8 @@ #define ETHERNET_FCS_SIZE 4 #define MAX_JUMBO_FRAME_SIZE 0x3F00 +/* The datasheet maximum supported RX size is 9.5KB (9728 bytes) */ +#define MAX_RX_JUMBO_FRAME_SIZE 0x2600 #define E1000_TX_PTR_GAP 0x1F /* Extended Configuration Control and Size */ @@ -1142,6 +1138,12 @@ #define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ +/* HH Time Sync */ +#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */ +#define E1000_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */ +#define E1000_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */ +#define E1000_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */ + #define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ #define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ #define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 diff --git a/sys/dev/netif/ig_hal/e1000_hw.h b/sys/dev/netif/ig_hal/e1000_hw.h index 9c19d05b48..e383e56368 100644 --- a/sys/dev/netif/ig_hal/e1000_hw.h +++ b/sys/dev/netif/ig_hal/e1000_hw.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_HW_H_ #define _E1000_HW_H_ @@ -41,9 +41,7 @@ struct e1000_hw; -#ifndef NO_82542_SUPPORT #define E1000_DEV_ID_82542 0x1000 -#endif #define E1000_DEV_ID_82543GC_FIBER 0x1001 #define E1000_DEV_ID_82543GC_COPPER 0x1004 #define E1000_DEV_ID_82544EI_COPPER 0x1008 @@ -126,27 +124,25 @@ struct e1000_hw; #define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE #define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF #define E1000_DEV_ID_ICH10_D_BM_V 0x1525 - #define E1000_DEV_ID_PCH_M_HV_LM 0x10EA #define E1000_DEV_ID_PCH_M_HV_LC 0x10EB #define E1000_DEV_ID_PCH_D_HV_DM 0x10EF #define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 #define E1000_DEV_ID_PCH2_LV_LM 0x1502 #define E1000_DEV_ID_PCH2_LV_V 0x1503 - #define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A #define E1000_DEV_ID_PCH_LPT_I217_V 0x153B #define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A #define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559 #define E1000_DEV_ID_PCH_I218_LM2 0x15A0 #define E1000_DEV_ID_PCH_I218_V2 0x15A1 -#define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */ -#define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */ -#define E1000_DEV_ID_PCH_SPT_I219_LM 0x156F /* SPT */ -#define E1000_DEV_ID_PCH_SPT_I219_V 0x1570 -#define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 -#define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 -#define E1000_DEV_ID_PCH_SPT_I219_LM3 0x15B9 /* LEWISBURG PCH */ +#define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */ +#define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_LM 0x156F /* Sunrise Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_V 0x1570 /* Sunrise Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* Sunrise Point-H PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* Sunrise Point-H PCH */ +#define E1000_DEV_ID_PCH_LBG_I219_LM3 0x15B9 /* LEWISBURG PCH */ #define E1000_DEV_ID_PCH_SPT_I219_LM4 0x15D7 #define E1000_DEV_ID_PCH_SPT_I219_V4 0x15D8 #define E1000_DEV_ID_PCH_SPT_I219_LM5 0x15E3 @@ -213,9 +209,7 @@ struct e1000_hw; enum e1000_mac_type { e1000_undefined = 0, -#ifndef NO_82542_SUPPORT e1000_82542, -#endif e1000_82543, e1000_82544, e1000_82540, @@ -819,9 +813,7 @@ struct e1000_mac_info { bool autoneg_failed; bool get_link_status; bool in_ifs_mode; -#ifndef NO_82542_SUPPORT bool report_tx_early; -#endif enum e1000_serdes_link_state serdes_link_state; bool serdes_has_link; bool tx_pkt_filtering; @@ -903,12 +895,10 @@ struct e1000_dev_spec_82541 { bool phy_init_script; }; -#ifndef NO_82542_SUPPORT struct e1000_dev_spec_82542 { bool dma_fairness; }; -#endif /* NO_82542_SUPPORT */ struct e1000_dev_spec_82543 { u32 tbi_compatibility; bool dma_fairness; @@ -969,7 +959,7 @@ struct e1000_dev_spec_82575 { bool media_changed; }; -#define E1000_SHADOW_RAM_WORDS 2048 +#define E1000_SHADOW_RAM_WORDS 2048 /* I218 PHY Ultra Low Power (ULP) states */ enum e1000_ulp_state { @@ -1009,9 +999,7 @@ struct e1000_hw { union { struct e1000_dev_spec_82541 _82541; -#ifndef NO_82542_SUPPORT struct e1000_dev_spec_82542 _82542; -#endif struct e1000_dev_spec_82543 _82543; struct e1000_dev_spec_82571 _82571; struct e1000_dev_spec_80003es2lan _80003es2lan; @@ -1037,10 +1025,8 @@ struct e1000_hw { #include "e1000_i210.h" /* These functions must be implemented by drivers */ -#ifndef NO_82542_SUPPORT void e1000_pci_clear_mwi(struct e1000_hw *hw); void e1000_pci_set_mwi(struct e1000_hw *hw); -#endif s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); s32 e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); diff --git a/sys/dev/netif/ig_hal/e1000_ich8lan.c b/sys/dev/netif/ig_hal/e1000_ich8lan.c index 17cae6883e..74996e3bcf 100644 --- a/sys/dev/netif/ig_hal/e1000_ich8lan.c +++ b/sys/dev/netif/ig_hal/e1000_ich8lan.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ /* 82562G 10/100 Network Connection * 82562G-2 10/100 Network Connection @@ -92,8 +92,8 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active); static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); +static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data); static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); @@ -127,15 +127,17 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, u8 size, u16 *data); static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, - u32 *data); + u32 *data); +static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 *data); +static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, + u32 offset, u32 data); +static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 dword); static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data); -static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, - u32 offset, u32 *data); static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 byte); -static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, - u32 offset, u32 dword); static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw); @@ -241,17 +243,21 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) if (ret_val) return FALSE; out: - if (hw->mac.type == e1000_pch_lpt || - hw->mac.type == e1000_pch_spt) { - /* Unforce SMBus mode in PHY */ - hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg); - phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; - hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg); - - /* Unforce SMBus mode in MAC */ - mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); - mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { + /* Only unforce SMBus if ME is not active */ + if (!(E1000_READ_REG(hw, E1000_FWSM) & + E1000_ICH_FWSM_FW_VALID)) { + /* Unforce SMBus mode in PHY */ + hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg); + phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; + hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg); + + /* Unforce SMBus mode in MAC */ + mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + } } return TRUE; @@ -633,28 +639,26 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_init_nvm_params_ich8lan"); - /* Can't read flash registers if the register set isn't mapped. */ nvm->type = e1000_nvm_flash_sw; - /* XXX turn flash_address into flash_reg_off or something more appropriate */ -#define E1000_FLASH_BASE_ADDR 0xE000 /* offset of NVM access regs */ -#define NVM_SIZE_MULTIPLIER 4096 - if (hw->mac.type == e1000_pch_spt) { - /* - * In SPT the flash is in the GbE flash region of the - * main hw map. GFPREG does not exist. Take NVM size from - * the STRAP register. + /* in SPT, gfpreg doesn't exist. NVM size is taken from the + * STRAP register. This is because in SPT the GbE Flash region + * is no longer accessed through the flash registers. Instead, + * the mechanism has changed, and the Flash region access + * registers are now implemented in GbE memory space. */ nvm->flash_base_addr = 0; - nvm_size = (((E1000_READ_REG(hw, E1000_STRAP) >> 1) & 0x1F) + 1) - * NVM_SIZE_MULTIPLIER; + nvm_size = + (((E1000_READ_REG(hw, E1000_STRAP) >> 1) & 0x1F) + 1) + * NVM_SIZE_MULTIPLIER; nvm->flash_bank_size = nvm_size / 2; /* Adjust to word count */ nvm->flash_bank_size /= sizeof(u16); /* Set the base address for flash register access */ hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR; } else { + /* Can't read flash registers if register set isn't mapped. */ if (!hw->flash_address) { DEBUGOUT("ERROR: Flash registers not mapped\n"); return -E1000_ERR_CONFIG; @@ -670,7 +674,8 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; /* flash_base_addr is byte-aligned */ - nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; + nvm->flash_base_addr = sector_base_addr + << FLASH_SECTOR_ADDR_SHIFT; /* find total size of the NVM, then cut in half since the total * size represents two separate NVM banks. @@ -694,11 +699,11 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) nvm->ops.acquire = e1000_acquire_nvm_ich8lan; nvm->ops.release = e1000_release_nvm_ich8lan; if (hw->mac.type == e1000_pch_spt) { - nvm->ops.read = e1000_read_nvm_spt; - nvm->ops.update = e1000_update_nvm_checksum_spt; + nvm->ops.read = e1000_read_nvm_spt; + nvm->ops.update = e1000_update_nvm_checksum_spt; } else { - nvm->ops.read = e1000_read_nvm_ich8lan; - nvm->ops.update = e1000_update_nvm_checksum_ich8lan; + nvm->ops.read = e1000_read_nvm_ich8lan; + nvm->ops.update = e1000_update_nvm_checksum_ich8lan; } nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan; nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; @@ -717,7 +722,6 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - u16 pci_cfg; DEBUGFUNC("e1000_init_mac_params_ich8lan"); @@ -790,10 +794,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) /* multicast address update for pch2 */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_pch2lan; + /* fall-through */ case e1000_pchlan: - /* save PCH revision_id */ - e1000_read_pci_cfg(hw, E1000_PCI_REVISION_ID_REG, &pci_cfg); - hw->revision_id = (u8)(pci_cfg &= 0x000F); /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; /* ID LED init */ @@ -810,8 +812,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) break; } - if (mac->type == e1000_pch_lpt || - mac->type == e1000_pch_spt) { + if ((mac->type == e1000_pch_lpt) || + (mac->type == e1000_pch_spt)) { mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES; mac->ops.rar_set = e1000_rar_set_pch_lpt; mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt; @@ -1041,8 +1043,9 @@ release: /* clear FEXTNVM6 bit 8 on link down or 10/100 */ fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK; - if (!link || ((status & E1000_STATUS_SPEED_100) && - (status & E1000_STATUS_FD))) + if ((hw->phy.revision > 5) || !link || + ((status & E1000_STATUS_SPEED_100) && + (status & E1000_STATUS_FD))) goto update_fextnvm6; ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, ®); @@ -1121,7 +1124,7 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link) u16 speed, duplex, scale = 0; u16 max_snoop, max_nosnoop; u16 max_ltr_enc; /* max LTR latency encoded */ - s64 lat_ns; /* latency (ns) */ + s64 lat_ns; s64 value; u32 rxa; @@ -1153,8 +1156,8 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link) lat_ns = 0; else lat_ns /= speed; - value = lat_ns; + while (value > E1000_LTRV_VALUE_MASK) { scale++; value = E1000_DIVIDE_ROUND_UP(value, (1 << 5)); @@ -1255,6 +1258,7 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) u32 mac_reg; s32 ret_val = E1000_SUCCESS; u16 phy_reg; + u16 oem_reg = 0; if ((hw->mac.type < e1000_pch_lpt) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) || @@ -1310,6 +1314,25 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable + * LPLU and disable Gig speed when entering ULP + */ + if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) { + ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS, + &oem_reg); + if (ret_val) + goto release; + + phy_reg = oem_reg; + phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS; + + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, + phy_reg); + + if (ret_val) + goto release; + } + /* Set Inband ULP Exit, Reset to SMBus mode and * Disable SMBus Release on PERST# in PHY */ @@ -1321,10 +1344,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) if (to_sx) { if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC) phy_reg |= I218_ULP_CONFIG1_WOL_HOST; + else + phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST; phy_reg |= I218_ULP_CONFIG1_STICKY_ULP; + phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT; } else { phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT; + phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP; + phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST; } e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); @@ -1336,6 +1364,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) /* Commit ULP changes in PHY by starting auto ULP configuration */ phy_reg |= I218_ULP_CONFIG1_START; e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); + + if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) && + to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, + oem_reg); + if (ret_val) + goto release; + } + release: hw->phy.ops.release(hw); out: @@ -1386,10 +1423,10 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) E1000_WRITE_REG(hw, E1000_H2ME, mac_reg); } - /* Poll up to 100msec for ME to clear ULP_CFG_DONE */ + /* Poll up to 300msec for ME to clear ULP_CFG_DONE. */ while (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_ULP_CFG_DONE) { - if (i++ == 10) { + if (i++ == 30) { ret_val = -E1000_ERR_PHY; goto out; } @@ -1458,22 +1495,24 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); if (ret_val) goto release; - phy_reg &= ~(I218_ULP_CONFIG1_IND | - I218_ULP_CONFIG1_STICKY_ULP | - I218_ULP_CONFIG1_RESET_TO_SMBUS | - I218_ULP_CONFIG1_WOL_HOST | - I218_ULP_CONFIG1_INBAND_EXIT | - I218_ULP_CONFIG1_DISABLE_SMB_PERST); - e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); - - /* Commit ULP changes by starting auto ULP configuration */ - phy_reg |= I218_ULP_CONFIG1_START; - e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); - - /* Clear Disable SMBus Release on PERST# in MAC */ - mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7); - mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST; - E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg); + phy_reg &= ~(I218_ULP_CONFIG1_IND | + I218_ULP_CONFIG1_STICKY_ULP | + I218_ULP_CONFIG1_RESET_TO_SMBUS | + I218_ULP_CONFIG1_WOL_HOST | + I218_ULP_CONFIG1_INBAND_EXIT | + I218_ULP_CONFIG1_EN_ULP_LANPHYPC | + I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST | + I218_ULP_CONFIG1_DISABLE_SMB_PERST); + e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); + + /* Commit ULP changes by starting auto ULP configuration */ + phy_reg |= I218_ULP_CONFIG1_START; + e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); + + /* Clear Disable SMBus Release on PERST# in MAC */ + mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7); + mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST; + E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg); release: hw->phy.ops.release(hw); @@ -1501,7 +1540,8 @@ out: static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; + s32 ret_val, tipg_reg = 0; + u16 emi_addr, emi_val = 0; bool link; u16 phy_reg; @@ -1515,13 +1555,13 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (!mac->get_link_status) return E1000_SUCCESS; - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; + /* First we want to see if the MII Status Register reports + * link. If so, then we want to get the current speed/duplex + * of the PHY. + */ + ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + return ret_val; if (hw->mac.type == e1000_pchlan) { ret_val = e1000_k1_gig_workaround_hv(hw, link); @@ -1536,76 +1576,99 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (((hw->mac.type == e1000_pch2lan) || (hw->mac.type == e1000_pch_lpt) || (hw->mac.type == e1000_pch_spt)) && link) { - u32 reg; - reg = E1000_READ_REG(hw, E1000_STATUS); - if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { - u16 emi_addr; + u16 speed, duplex; - reg = E1000_READ_REG(hw, E1000_TIPG); - reg &= ~E1000_TIPG_IPGT_MASK; - reg |= 0xFF; - E1000_WRITE_REG(hw, E1000_TIPG, reg); + e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex); + tipg_reg = E1000_READ_REG(hw, E1000_TIPG); + tipg_reg &= ~E1000_TIPG_IPGT_MASK; + if (duplex == HALF_DUPLEX && speed == SPEED_10) { + tipg_reg |= 0xFF; /* Reduce Rx latency in analog PHY */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - if (hw->mac.type == e1000_pch2lan) - emi_addr = I82579_RX_CONFIG; - else - emi_addr = I217_RX_CONFIG; - ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0); - - hw->phy.ops.release(hw); - - if (ret_val) - return ret_val; + emi_val = 0; } else if (hw->mac.type == e1000_pch_spt && - (reg & E1000_STATUS_FD) && - (reg & E1000_STATUS_SPEED_MASK) == E1000_STATUS_SPEED_1000) { - reg &= ~E1000_TIPG_IPGT_MASK; - reg |= 0x0C; - E1000_WRITE_REG(hw, E1000_TIPG, reg); + duplex == FULL_DUPLEX && speed != SPEED_1000) { + tipg_reg |= 0xC; + emi_val = 1; + } else { + /* Roll back the default values */ + tipg_reg |= 0x08; + emi_val = 1; + } - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; + E1000_WRITE_REG(hw, E1000_TIPG, tipg_reg); + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; - ret_val = e1000_write_emi_reg_locked(hw, I217_RX_CONFIG, 1); + if (hw->mac.type == e1000_pch2lan) + emi_addr = I82579_RX_CONFIG; + else + emi_addr = I217_RX_CONFIG; + ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val); - hw->phy.ops.release(hw); + if (hw->mac.type == e1000_pch_lpt || + hw->mac.type == e1000_pch_spt) { + u16 phy_reg; - if (ret_val) - return ret_val; + hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG, + &phy_reg); + phy_reg &= ~I217_PLL_CLOCK_GATE_MASK; + if (speed == SPEED_100 || speed == SPEED_10) + phy_reg |= 0x3E8; + else + phy_reg |= 0xFA; + hw->phy.ops.write_reg_locked(hw, + I217_PLL_CLOCK_GATE_REG, + phy_reg); } + hw->phy.ops.release(hw); - /* - * What is this for? - */ - reg = E1000_READ_REG(hw, E1000_STATUS); - if (hw->mac.type == e1000_pch_spt && - (reg & E1000_STATUS_FD) && - (reg & E1000_STATUS_SPEED_MASK) == E1000_STATUS_SPEED_1000) { + if (ret_val) + return ret_val; + + if (hw->mac.type == e1000_pch_spt) { u16 data; u16 ptr_gap; - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - hw->phy.ops.read_reg_locked(hw, PHY_REG(776, 20), &data); - ptr_gap = (data & (0x3FF << 2)) >> 2; - if (ptr_gap < 0x18) { - data &= ~(0x3FF << 2); - data |= (0x18 << 2); - hw->phy.ops.write_reg_locked(hw, - PHY_REG(776, 20), - data); - } - hw->phy.ops.release(hw); + if (speed == SPEED_1000) { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + ret_val = hw->phy.ops.read_reg_locked(hw, + PHY_REG(776, 20), + &data); + if (ret_val) { + hw->phy.ops.release(hw); + return ret_val; + } + + ptr_gap = (data & (0x3FF << 2)) >> 2; + if (ptr_gap < 0x18) { + data &= ~(0x3FF << 2); + data |= (0x18 << 2); + ret_val = + hw->phy.ops.write_reg_locked(hw, + PHY_REG(776, 20), data); + } + hw->phy.ops.release(hw); + if (ret_val) + return ret_val; + } else { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; - if (ret_val) - return ret_val; + ret_val = hw->phy.ops.write_reg_locked(hw, + PHY_REG(776, 20), + 0xC023); + hw->phy.ops.release(hw); + if (ret_val) + return ret_val; + + } } } @@ -1614,7 +1677,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) * on power up. * Set the Beacon Duration for I217 to 8 usec */ - if ((hw->mac.type == e1000_pch_lpt) || (hw->mac.type == e1000_pch_spt)) { + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { u32 mac_reg; mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4); @@ -1632,9 +1696,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; } - - if (hw->mac.type == e1000_pch_lpt || - hw->mac.type == e1000_pch_spt) { + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { /* Set platform power management values for * Latency Tolerance Reporting (LTR) * Optimized Buffer Flush/Fill (OBFF) @@ -1656,6 +1719,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE; else fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE; + E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6); } @@ -2121,7 +2185,7 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) continue; } blocked = FALSE; - } while (blocked && (i++ < 10)); + } while (blocked && (i++ < 30)); return blocked ? E1000_BLK_PHY_RESET : E1000_SUCCESS; } @@ -3093,7 +3157,6 @@ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) u16 oem_reg; DEBUGFUNC("e1000_set_lplu_state_pchlan"); - ret_val = hw->phy.ops.read_reg(hw, HV_OEM_BITS, &oem_reg); if (ret_val) return ret_val; @@ -3313,6 +3376,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) struct e1000_nvm_info *nvm = &hw->nvm; u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; + u32 nvm_dword = 0; u8 sig_byte = 0; s32 ret_val; @@ -3320,14 +3384,39 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) switch (hw->mac.type) { case e1000_pch_spt: - *bank = E1000_READ_REG(hw, E1000_CTRL_EXT) & E1000_CTRL_EXT_NVMVS; - if (*bank == 0 || *bank == 1) { - return -E1000_ERR_NVM; - } else { - *bank = *bank - 2; - return 0; + bank1_offset = nvm->flash_bank_size; + act_offset = E1000_ICH_NVM_SIG_WORD; + + /* set bank to 0 in case flash read fails */ + *bank = 0; + + /* Check bank 0 */ + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, + &nvm_dword); + if (ret_val) + return ret_val; + sig_byte = (u8)((nvm_dword & 0xFF00) >> 8); + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == + E1000_ICH_NVM_SIG_VALUE) { + *bank = 0; + return E1000_SUCCESS; } - break; + + /* Check bank 1 */ + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset + + bank1_offset, + &nvm_dword); + if (ret_val) + return ret_val; + sig_byte = (u8)((nvm_dword & 0xFF00) >> 8); + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == + E1000_ICH_NVM_SIG_VALUE) { + *bank = 1; + return E1000_SUCCESS; + } + + DEBUGOUT("ERROR: No valid NVM bank present\n"); + return -E1000_ERR_NVM; case e1000_ich8lan: case e1000_ich9lan: eecd = E1000_READ_REG(hw, E1000_EECD); @@ -3375,13 +3464,13 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) } /** - * e1000_read_nvm_spt - Read word(s) from the NVM + * e1000_read_nvm_spt - NVM access for SPT * @hw: pointer to the HW structure * @offset: The offset (in bytes) of the word(s) to read. - * @words: Size of data to read in words - * @data: Pointer to the word(s) to read at offset. + * @words: Size of data to read in words. + * @data: pointer to the word(s) to read at offset. * - * Reads a word(s) from the NVM using the flash access registers. + * Reads a word(s) from the NVM **/ static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) @@ -3391,8 +3480,8 @@ static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, u32 act_offset; s32 ret_val = E1000_SUCCESS; u32 bank = 0; - u32 dword; - u16 use_offset; + u32 dword = 0; + u16 offset_to_read; u16 i; DEBUGFUNC("e1000_read_nvm_spt"); @@ -3416,17 +3505,18 @@ static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, act_offset += offset; ret_val = E1000_SUCCESS; + for (i = 0; i < words; i += 2) { if (words - i == 1) { if (dev_spec->shadow_ram[offset+i].modified) { data[i] = dev_spec->shadow_ram[offset+i].value; } else { - use_offset = act_offset + i - - (act_offset + i) % 2; - ret_val = e1000_read_flash_dword_ich8lan( - hw, - use_offset, - &dword); + offset_to_read = act_offset + i - + ((act_offset + i) % 2); + ret_val = + e1000_read_flash_dword_ich8lan(hw, + offset_to_read, + &dword); if (ret_val) break; if ((act_offset + i) % 2 == 0) @@ -3435,25 +3525,25 @@ static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, data[i] = (u16)((dword >> 16) & 0xFFFF); } } else { - use_offset = act_offset + i; - dword = 0; /* avoid gcc warnings */ - if (!(dev_spec->shadow_ram[offset + i].modified) || - !(dev_spec->shadow_ram[offset + i + 1].modified)) { + offset_to_read = act_offset + i; + if (!(dev_spec->shadow_ram[offset+i].modified) || + !(dev_spec->shadow_ram[offset+i+1].modified)) { ret_val = - e1000_read_flash_dword_ich8lan(hw, - use_offset, &dword); + e1000_read_flash_dword_ich8lan(hw, + offset_to_read, + &dword); if (ret_val) break; } - if (dev_spec->shadow_ram[offset + i].modified) - data[i] = dev_spec->shadow_ram[offset + i].value; + if (dev_spec->shadow_ram[offset+i].modified) + data[i] = dev_spec->shadow_ram[offset+i].value; else - data[i] = (u16)(dword & 0xFFFF); - if (dev_spec->shadow_ram[offset + i].modified) - data[i + 1] = - dev_spec->shadow_ram[offset + i + 1].value; + data[i] = (u16) (dword & 0xFFFF); + if (dev_spec->shadow_ram[offset+i].modified) + data[i+1] = + dev_spec->shadow_ram[offset+i+1].value; else - data[i + 1] = (u16)(dword >> 16 & 0xFFFF); + data[i+1] = (u16) (dword >> 16 & 0xFFFF); } } @@ -3554,7 +3644,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) hsfsts.hsf_status.flcerr = 1; hsfsts.hsf_status.dael = 1; if (hw->mac.type == e1000_pch_spt) - E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFF); + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsfsts.regval & 0xFFFF); else E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); @@ -3573,9 +3664,11 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) */ hsfsts.hsf_status.flcdone = 1; if (hw->mac.type == e1000_pch_spt) - E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFF); + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsfsts.regval & 0xFFFF); else - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, + hsfsts.regval); ret_val = E1000_SUCCESS; } else { s32 i; @@ -3599,7 +3692,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) hsfsts.hsf_status.flcdone = 1; if (hw->mac.type == e1000_pch_spt) E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, - hsfsts.regval & 0xFFFF); + hsfsts.regval & 0xFFFF); else E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); @@ -3628,13 +3721,14 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ if (hw->mac.type == e1000_pch_spt) - hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS) >> 16; + hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; else hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcgo = 1; if (hw->mac.type == e1000_pch_spt) - E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, hsflctl.regval << 16); + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); else E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); @@ -3653,30 +3747,30 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) } /** - * e1000_read_flash_word_ich8lan - Read word from flash + * e1000_read_flash_dword_ich8lan - Read dword from flash * @hw: pointer to the HW structure * @offset: offset to data location * @data: pointer to the location for storing the data * - * Reads the flash word at offset into data. Offset is converted + * Reads the flash dword at offset into data. Offset is converted * to bytes before read. **/ -static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, - u16 *data) +static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset, + u32 *data) { - DEBUGFUNC("e1000_read_flash_word_ich8lan"); + DEBUGFUNC("e1000_read_flash_dword_ich8lan"); if (!data) return -E1000_ERR_NVM; - /* Must convert offset into bytes. */ + /* Must convert word offset into bytes. */ offset <<= 1; - return e1000_read_flash_data_ich8lan(hw, offset, 2, data); + return e1000_read_flash_data32_ich8lan(hw, offset, data); } /** - * e1000_read_flash_dword_ich8lan - Read dword from flash + * e1000_read_flash_word_ich8lan - Read word from flash * @hw: pointer to the HW structure * @offset: offset to data location * @data: pointer to the location for storing the data @@ -3684,10 +3778,10 @@ static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, * Reads the flash word at offset into data. Offset is converted * to bytes before read. **/ -static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset, - u32 *data) +static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, + u16 *data) { - DEBUGFUNC("e1000_read_flash_dword_ich8lan"); + DEBUGFUNC("e1000_read_flash_word_ich8lan"); if (!data) return -E1000_ERR_NVM; @@ -3695,7 +3789,7 @@ static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset, /* Must convert offset into bytes. */ offset <<= 1; - return e1000_read_flash_data32_ich8lan(hw, offset, data); + return e1000_read_flash_data_ich8lan(hw, offset, 2, data); } /** @@ -3712,9 +3806,13 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, s32 ret_val; u16 word = 0; + /* In SPT, only 32 bits access is supported, + * so this function should not be called. + */ if (hw->mac.type == e1000_pch_spt) return -E1000_ERR_NVM; - ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); + else + ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); if (ret_val) return ret_val; @@ -3803,14 +3901,13 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, /** * e1000_read_flash_data32_ich8lan - Read dword from NVM * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the byte or word to read. - * @size: Size of data to read, 1=byte 2=word - * @data: Pointer to the word to store the value read. + * @offset: The offset (in bytes) of the dword to read. + * @data: Pointer to the dword to store the value read. * * Reads a byte or word from the NVM using the flash access registers. **/ static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, - u32 *data) + u32 *data) { union ich8_hws_flash_status hsfsts; union ich8_hws_flash_ctrl hsflctl; @@ -3818,14 +3915,11 @@ static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, s32 ret_val = -E1000_ERR_NVM; u8 count = 0; - DEBUGFUNC("e1000_read_flash_data32_ich8lan"); - - *data = 0; /* avoid gcc warning */ - - if (offset > ICH_FLASH_LINEAR_ADDR_MASK || - hw->mac.type != e1000_pch_spt) - return -E1000_ERR_NVM; + DEBUGFUNC("e1000_read_flash_data_ich8lan"); + if (offset > ICH_FLASH_LINEAR_ADDR_MASK || + hw->mac.type != e1000_pch_spt) + return -E1000_ERR_NVM; flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + hw->nvm.flash_base_addr); @@ -3835,12 +3929,19 @@ static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val != E1000_SUCCESS) break; - hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS) >> 16; + /* In SPT, This register is in Lan memory space, not flash. + * Therefore, only 32 bit access is supported + */ + hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = sizeof(int32_t) - 1; + hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1; hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; - E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, hsflctl.regval << 16); + /* In SPT, This register is in Lan memory space, not flash. + * Therefore, only 32 bit access is supported + */ + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + (u32)hsflctl.regval << 16); E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); ret_val = e1000_flash_cycle_ich8lan(hw, @@ -3875,7 +3976,6 @@ static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, return ret_val; } - /** * e1000_write_nvm_ich8lan - Write word(s) to the NVM * @hw: pointer to the HW structure @@ -3929,7 +4029,7 @@ static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw) struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 i, act_offset, new_bank_offset, old_bank_offset, bank; s32 ret_val; - u32 data32 = 0; + u32 dword = 0; DEBUGFUNC("e1000_update_nvm_checksum_spt"); @@ -3972,15 +4072,16 @@ static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw) */ ret_val = e1000_read_flash_dword_ich8lan(hw, i + old_bank_offset, - &data32); + &dword); + if (dev_spec->shadow_ram[i].modified) { - data32 &= 0xFFFF0000; - data32 |= dev_spec->shadow_ram[i].value & 0xffff; + dword &= 0xffff0000; + dword |= (dev_spec->shadow_ram[i].value & 0xffff); } if (dev_spec->shadow_ram[i + 1].modified) { - data32 &= 0x0000FFFF; - data32 |= (dev_spec->shadow_ram[i + 1].value & 0xffff) - << 16; + dword &= 0x0000ffff; + dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff) + << 16); } if (ret_val) break; @@ -3993,18 +4094,17 @@ static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw) * while the write is still in progress */ if (i == E1000_ICH_NVM_SIG_WORD - 1) - data32 |= E1000_ICH_NVM_SIG_MASK << 16; + dword |= E1000_ICH_NVM_SIG_MASK << 16; /* Convert offset to bytes. */ - /*act_offset = (i + new_bank_offset) << 1;*/ + act_offset = (i + new_bank_offset) << 1; usec_delay(100); - /* Write the bytes to the new bank. */ + /* Write the data to the new bank. Offset in words*/ act_offset = i + new_bank_offset; - ret_val = e1000_retry_write_flash_dword_ich8lan(hw, - act_offset, - data32); + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, + dword); if (ret_val) break; } @@ -4024,16 +4124,16 @@ static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw) */ act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; - /*offset in words but we read dword */ + /*offset in words but we read dword*/ --act_offset; + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword); - ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &data32); if (ret_val) goto release; - data32 &= 0xBFFFFFFF; - ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset * 2 + 1, - data32); + dword &= 0xBFFFFFFF; + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword); + if (ret_val) goto release; @@ -4042,11 +4142,17 @@ static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw) * done without an erase because flash erase sets all bits * to 1's. We can write 1's to 0's without an erase */ - /*act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;*/ + act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; - /* offset in words but we read dwords */ + /* offset in words but we read dword*/ act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1; - ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &data32); + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword); + + if (ret_val) + goto release; + + dword &= 0x00FFFFFF; + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword); if (ret_val) goto release; @@ -4317,18 +4423,29 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val != E1000_SUCCESS) break; + /* In SPT, This register is in Lan memory space, not + * flash. Therefore, only 32 bit access is supported + */ if (hw->mac.type == e1000_pch_spt) - hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS) >> 16; + hsflctl.regval = + E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; else - hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + hsflctl.regval = + E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size - 1; hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; + /* In SPT, This register is in Lan memory space, + * not flash. Therefore, only 32 bit access is + * supported + */ if (hw->mac.type == e1000_pch_spt) - E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, hsflctl.regval << 16); + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); else - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, + hsflctl.regval); E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); @@ -4367,13 +4484,13 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, } /** - * e1000_write_flash_data32_ich8lan - Writes 32-bit words to the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the 32-bit word to read. - * @data: The byte(s) to write to the NVM. - * - * Writes one/two bytes to the NVM using the flash access registers. - **/ +* e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM +* @hw: pointer to the HW structure +* @offset: The offset (in bytes) of the dwords to read. +* @data: The 4 bytes to write to the NVM. +* +* Writes one/two/four bytes to the NVM using the flash access registers. +**/ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, u32 data) { @@ -4383,7 +4500,7 @@ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, s32 ret_val; u8 count = 0; - DEBUGFUNC("e1000_write_ich8_data"); + DEBUGFUNC("e1000_write_flash_data32_ich8lan"); if (hw->mac.type == e1000_pch_spt) { if (offset > ICH_FLASH_LINEAR_ADDR_MASK) @@ -4391,32 +4508,37 @@ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, } flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + hw->nvm.flash_base_addr); - do { usec_delay(1); /* Steps */ ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val != E1000_SUCCESS) break; - if (hw->mac.type == e1000_pch_spt) { - hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS) >> 16; - } else { - hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); - } - /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = sizeof(int32_t) - 1; + /* In SPT, This register is in Lan memory space, not + * flash. Therefore, only 32 bit access is supported + */ + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = E1000_READ_FLASH_REG(hw, + ICH_FLASH_HSFSTS) + >> 16; + else + hsflctl.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFCTL); + + hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1; hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; /* In SPT, This register is in Lan memory space, * not flash. Therefore, only 32 bit access is * supported */ - if (hw->mac.type == e1000_pch_spt) { - E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, hsflctl.regval << 16); - } else { - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); - } + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, + hsflctl.regval); E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); @@ -4425,9 +4547,9 @@ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, /* check if FCERR is set to 1 , if set to 1, clear it * and try the whole sequence a few more times else done */ - ret_val = - e1000_flash_cycle_ich8lan(hw, - ICH_FLASH_WRITE_COMMAND_TIMEOUT); + ret_val = e1000_flash_cycle_ich8lan(hw, + ICH_FLASH_WRITE_COMMAND_TIMEOUT); + if (ret_val == E1000_SUCCESS) break; @@ -4437,6 +4559,7 @@ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. */ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr) /* Repeat for some time before giving up. */ continue; @@ -4449,7 +4572,6 @@ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, return ret_val; } - /** * e1000_write_flash_byte_ich8lan - Write a single byte to NVM * @hw: pointer to the HW structure @@ -4469,30 +4591,33 @@ static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, } /** - * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM - * @hw: pointer to the HW structure - * @offset: The offset of the byte to write. - * @byte: The byte to write to the NVM. - * - * Writes a single byte to the NVM using the flash access registers. - * Goes through a retry algorithm before giving up. - **/ -static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 byte) +* e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM +* @hw: pointer to the HW structure +* @offset: The offset of the word to write. +* @dword: The dword to write to the NVM. +* +* Writes a single dword to the NVM using the flash access registers. +* Goes through a retry algorithm before giving up. +**/ +static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 dword) { s32 ret_val; u16 program_retries; - DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan"); + DEBUGFUNC("e1000_retry_write_flash_dword_ich8lan"); + + /* Must convert word offset into bytes. */ + offset <<= 1; + + ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); - ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); if (!ret_val) return ret_val; - for (program_retries = 0; program_retries < 100; program_retries++) { - DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset); + DEBUGOUT2("Retrying Byte %8.8X at offset %u\n", dword, offset); usec_delay(100); - ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); + ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); if (ret_val == E1000_SUCCESS) break; } @@ -4503,30 +4628,30 @@ static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, } /** - * e1000_retry_write_flash_dword_ich8lan - Writes a 32-bit word to NVM + * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM * @hw: pointer to the HW structure * @offset: The offset of the byte to write. - * @dword: The dword to write to the NVM. + * @byte: The byte to write to the NVM. * - * Writes a single 32-bit word to the NVM using the flash access registers. + * Writes a single byte to the NVM using the flash access registers. * Goes through a retry algorithm before giving up. **/ -static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, - u32 offset, u32 dword) +static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, + u32 offset, u8 byte) { s32 ret_val; u16 program_retries; DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan"); - ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); + ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); if (!ret_val) return ret_val; for (program_retries = 0; program_retries < 100; program_retries++) { - DEBUGOUT2("Retrying DWord %08X at offset %u\n", dword, offset); + DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset); usec_delay(100); - ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); + ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); if (ret_val == E1000_SUCCESS) break; } @@ -4612,15 +4737,17 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) */ if (hw->mac.type == e1000_pch_spt) hsflctl.regval = - E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS) >> 16; + E1000_READ_FLASH_REG(hw, + ICH_FLASH_HSFSTS)>>16; else hsflctl.regval = - E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; if (hw->mac.type == e1000_pch_spt) E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, - hsflctl.regval << 16); + hsflctl.regval << 16); else E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); @@ -5053,8 +5180,8 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_RFCTL, reg); /* Enable ECC on Lynxpoint */ - if (hw->mac.type == e1000_pch_lpt || - hw->mac.type == e1000_pch_spt) { + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { reg = E1000_READ_REG(hw, E1000_PBECCSTS); reg |= E1000_PBECCSTS_ECC_ENABLE; E1000_WRITE_REG(hw, E1000_PBECCSTS, reg); @@ -5603,19 +5730,18 @@ out: * the PHY. * On i217, setup Intel Rapid Start Technology. **/ -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) +u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_resume_workarounds_pchlan"); - if (hw->mac.type < e1000_pch2lan) - return; + return E1000_SUCCESS; ret_val = e1000_init_phy_workarounds_pchlan(hw); if (ret_val) { DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val); - return; + return ret_val; } /* For i217 Intel Rapid Start Technology support when the system @@ -5629,7 +5755,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire(hw); if (ret_val) { DEBUGOUT("Failed to setup iRST\n"); - return; + return ret_val; } /* Clear Auto Enable LPI after link up */ @@ -5663,7 +5789,9 @@ release: if (ret_val) DEBUGOUT1("Error %d in resume workarounds\n", ret_val); hw->phy.ops.release(hw); + return ret_val; } + return E1000_SUCCESS; } /** diff --git a/sys/dev/netif/ig_hal/e1000_ich8lan.h b/sys/dev/netif/ig_hal/e1000_ich8lan.h index 81a9384998..edc1dd14cc 100644 --- a/sys/dev/netif/ig_hal/e1000_ich8lan.h +++ b/sys/dev/netif/ig_hal/e1000_ich8lan.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_ICH8LAN_H_ #define _E1000_ICH8LAN_H_ @@ -108,12 +108,22 @@ #define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 #define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200 #define E1000_FEXTNVM6_K1_OFF_ENABLE 0x80000000 - - +/* bit for disabling packet buffer read */ +#define E1000_FEXTNVM7_DISABLE_PB_READ 0x00040000 +#define E1000_FEXTNVM7_SIDE_CLK_UNGATE 0x00000004 #define E1000_FEXTNVM7_DISABLE_SMB_PERST 0x00000020 - -#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */ - +#define E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS 0x00000800 +#define E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS 0x00001000 +#define E1000_FEXTNVM11_DISABLE_PB_READ 0x00000200 +#define E1000_FEXTNVM11_DISABLE_MULR_FIX 0x00002000 + +/* bit24: RXDCTL thresholds granularity: 0 - cache lines, 1 - descriptors */ +#define E1000_RXDCTL_THRESH_UNIT_DESC 0x01000000 + +#define NVM_SIZE_MULTIPLIER 4096 /*multiplier for NVMS field*/ +#define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs*/ +#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */ +#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29) #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 @@ -175,6 +185,8 @@ #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ +#define K1_ENTRY_LATENCY 0 +#define K1_MIN_TIME 1 /* SMBus Control Phy Register */ #define CV_SMB_CTRL PHY_REG(769, 23) @@ -188,6 +200,10 @@ #define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */ #define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */ #define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */ +/* enable ULP even if when phy powered down via lanphypc */ +#define I218_ULP_CONFIG1_EN_ULP_LANPHYPC 0x0400 +/* disable clear of sticky ULP on PERST */ +#define I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST 0x0800 #define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */ /* SMBus Address Phy Register */ @@ -226,6 +242,9 @@ #define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 #define HV_PM_CTRL_K1_ENABLE 0x4000 +#define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) +#define I217_PLL_CLOCK_GATE_MASK 0x07FF + #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ /* Inband Control */ @@ -306,13 +325,12 @@ #define E1000_SVCR_OFF_TIMER_SHIFT 16 #define E1000_SVT_OFF_HWM_MASK 0x0000001F -#define E1000_PCI_REVISION_ID_REG 0x08 void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, bool state); void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); +u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw); s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); diff --git a/sys/dev/netif/ig_hal/e1000_mac.c b/sys/dev/netif/ig_hal/e1000_mac.c index 7be02eff28..bea38fb0cd 100644 --- a/sys/dev/netif/ig_hal/e1000_mac.c +++ b/sys/dev/netif/ig_hal/e1000_mac.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #include "e1000_api.h" @@ -944,11 +944,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) * Read the EEPROM for the default values for flow control and store the * values. **/ -#ifdef NO_82542_SUPPORT -static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) -#else s32 e1000_set_default_fc_generic(struct e1000_hw *hw) -#endif { s32 ret_val; u16 nvm_data; @@ -2102,8 +2098,7 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw) while (timeout) { if (!(E1000_READ_REG(hw, E1000_STATUS) & - E1000_STATUS_GIO_MASTER_ENABLE) || - E1000_REMOVED(hw->hw_addr)) + E1000_STATUS_GIO_MASTER_ENABLE)) break; usec_delay(100); timeout--; diff --git a/sys/dev/netif/ig_hal/e1000_mac.h b/sys/dev/netif/ig_hal/e1000_mac.h index a52086d429..5066611c66 100644 --- a/sys/dev/netif/ig_hal/e1000_mac.h +++ b/sys/dev/netif/ig_hal/e1000_mac.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,15 +30,12 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_MAC_H_ #define _E1000_MAC_H_ void e1000_init_mac_ops_generic(struct e1000_hw *hw); -#ifndef E1000_REMOVED -#define E1000_REMOVED(a) (0) -#endif /* E1000_REMOVED */ void e1000_null_mac_generic(struct e1000_hw *hw); s32 e1000_null_ops_generic(struct e1000_hw *hw); s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d); @@ -72,9 +69,7 @@ s32 e1000_led_on_generic(struct e1000_hw *hw); s32 e1000_led_off_generic(struct e1000_hw *hw); void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count); -#ifndef NO_82542_SUPPORT s32 e1000_set_default_fc_generic(struct e1000_hw *hw); -#endif 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); diff --git a/sys/dev/netif/ig_hal/e1000_manage.c b/sys/dev/netif/ig_hal/e1000_manage.c index f0a32a9c25..75bdd7a1ed 100644 --- a/sys/dev/netif/ig_hal/e1000_manage.c +++ b/sys/dev/netif/ig_hal/e1000_manage.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,10 +30,9 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #include "e1000_api.h" - /** * e1000_calculate_checksum - Calculate checksum for buffer * @buffer: pointer to EEPROM @@ -42,7 +41,7 @@ * Calculates the checksum for some buffer on a specified length. The * checksum calculated is returned. **/ -u8 e1000_calculate_checksum(u8 *buffer, u32 length) +static u8 e1000_calculate_checksum(u8 *buffer, u32 length) { u32 i; u8 sum = 0; diff --git a/sys/dev/netif/ig_hal/e1000_manage.h b/sys/dev/netif/ig_hal/e1000_manage.h index 64fee06b6a..f451bd712b 100644 --- a/sys/dev/netif/ig_hal/e1000_manage.h +++ b/sys/dev/netif/ig_hal/e1000_manage.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_MANAGE_H_ #define _E1000_MANAGE_H_ @@ -45,7 +45,6 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, u16 length); bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); -u8 e1000_calculate_checksum(u8 *buffer, u32 length); s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length); s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length); diff --git a/sys/dev/netif/ig_hal/e1000_nvm.c b/sys/dev/netif/ig_hal/e1000_nvm.c index ab7164d70a..ff20dcf2d9 100644 --- a/sys/dev/netif/ig_hal/e1000_nvm.c +++ b/sys/dev/netif/ig_hal/e1000_nvm.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #include "e1000_api.h" @@ -333,11 +333,7 @@ static void e1000_standby_nvm(struct e1000_hw *hw) * * Terminates the current command by inverting the EEPROM's chip select pin. **/ -#ifdef NO_82542_SUPPORT -static void e1000_stop_nvm(struct e1000_hw *hw) -#else void e1000_stop_nvm(struct e1000_hw *hw) -#endif { u32 eecd; diff --git a/sys/dev/netif/ig_hal/e1000_nvm.h b/sys/dev/netif/ig_hal/e1000_nvm.h index a74e23ef8d..66461c7084 100644 --- a/sys/dev/netif/ig_hal/e1000_nvm.h +++ b/sys/dev/netif/ig_hal/e1000_nvm.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_NVM_H_ #define _E1000_NVM_H_ @@ -89,9 +89,7 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, 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); -#ifndef NO_82542_SUPPORT void e1000_stop_nvm(struct e1000_hw *hw); -#endif void e1000_release_nvm_generic(struct e1000_hw *hw); void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers); diff --git a/sys/dev/netif/ig_hal/e1000_osdep.h b/sys/dev/netif/ig_hal/e1000_osdep.h index f47b2f3dd2..f1dab09a71 100644 --- a/sys/dev/netif/ig_hal/e1000_osdep.h +++ b/sys/dev/netif/ig_hal/e1000_osdep.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -42,25 +42,23 @@ #include #include -#define usec_delay(x) DELAY(x) -#define usec_delay_irq usec_delay -#define msec_delay(x) DELAY(1000*(x)) -/* TODO: Should we be paranoid about delaying in interrupt context? */ -#define msec_delay_irq(x) DELAY(1000*(x)) +#define usec_delay(x) DELAY(x) +#define usec_delay_irq(x) usec_delay(x) +#define msec_delay(x) DELAY(1000*(x)) +#define msec_delay_irq(x) DELAY(1000*(x)) extern int e1000_debug; -#define DEBUGPRINT(S, args...) \ +#define DEBUGOUT(S, args...) \ do { \ if (e1000_debug) \ kprintf(S, ##args); \ } while (0) -#define DEBUGFUNC(F) DEBUGOUT(F) -#define DEBUGOUT(S) DEBUGPRINT(S) -#define DEBUGOUT1(S,A) DEBUGPRINT(S, A) -#define DEBUGOUT2(S,A,B) DEBUGPRINT(S, A, B) -#define DEBUGOUT3(S,A,B,C) DEBUGPRINT(S, A, B, C) -#define DEBUGOUT7(S,A,B,C,D,E,F,G) DEBUGPRINT(S, A, B, C, D, E, F, G) +#define DEBUGOUT1(S, args...) DEBUGOUT(S, ##args) +#define DEBUGOUT2(S, args...) DEBUGOUT(S, ##args) +#define DEBUGOUT3(S, args...) DEBUGOUT(S, ##args) +#define DEBUGOUT7(S, args...) DEBUGOUT(S, ##args) +#define DEBUGFUNC(F) DEBUGOUT(F "\n") #define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */ #define PCI_COMMAND_REGISTER PCIR_COMMAND @@ -114,21 +112,11 @@ struct e1000_osdep { ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ E1000_REGISTER(hw, reg)) -#define E1000_READ_REG16(hw, reg) \ - bus_space_read_2(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ - E1000_REGISTER(hw, reg)) - #define E1000_WRITE_REG(hw, reg, value) \ bus_space_write_4(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ E1000_REGISTER(hw, reg), value) -#define E1000_WRITE_REG16(hw, reg, value) \ - bus_space_write_2(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ - E1000_REGISTER(hw, reg), value) - #define E1000_READ_REG_ARRAY(hw, reg, index) \ bus_space_read_4(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ @@ -139,8 +127,8 @@ struct e1000_osdep { ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ E1000_REGISTER(hw, reg) + ((index)<< 2), value) -#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY -#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY +#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY +#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY #define E1000_READ_REG_ARRAY_BYTE(hw, reg, index) \ bus_space_read_1(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ @@ -166,23 +154,19 @@ struct e1000_osdep { (hw)->io_base + 4, value); } while (0) #define E1000_READ_FLASH_REG(hw, reg) \ - (((hw)->mac.type == e1000_pch_spt) ? E1000_READ_REG(hw, (reg) + 0xE000): \ bus_space_read_4(((struct e1000_osdep *)(hw)->back)->flash_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg)) + ((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg) #define E1000_READ_FLASH_REG16(hw, reg) \ - (((hw)->mac.type == e1000_pch_spt) ? E1000_READ_REG16(hw, (reg) + 0xE000): \ bus_space_read_2(((struct e1000_osdep *)(hw)->back)->flash_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg)) + ((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg) #define E1000_WRITE_FLASH_REG(hw, reg, value) \ - (((hw)->mac.type == e1000_pch_spt) ? E1000_WRITE_REG(hw, (reg) + 0xE000, value): \ bus_space_write_4(((struct e1000_osdep *)(hw)->back)->flash_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg, value)) + ((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg, value) #define E1000_WRITE_FLASH_REG16(hw, reg, value) \ - (((hw)->mac.type == e1000_pch_spt) ? E1000_WRITE_REG16(hw, (reg) + 0xE000, value): \ bus_space_write_2(((struct e1000_osdep *)(hw)->back)->flash_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg, value)) + ((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg, value) #endif /* _DRAGONFLY_OS_H_ */ diff --git a/sys/dev/netif/ig_hal/e1000_phy.c b/sys/dev/netif/ig_hal/e1000_phy.c index a1c69a037f..20299734f5 100644 --- a/sys/dev/netif/ig_hal/e1000_phy.c +++ b/sys/dev/netif/ig_hal/e1000_phy.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #include "e1000_api.h" @@ -3431,12 +3431,11 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read, bool page_set) { s32 ret_val; - u16 reg, page; + u16 reg = BM_PHY_REG_NUM(offset); + u16 page = BM_PHY_REG_PAGE(offset); u16 phy_reg = 0; DEBUGFUNC("e1000_access_phy_wakeup_reg_bm"); - reg = BM_PHY_REG_NUM(offset); - page = BM_PHY_REG_PAGE(offset); /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */ if ((hw->mac.type == e1000_pchlan) && @@ -3546,7 +3545,6 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, if (ret_val) return ret_val; } - /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, @@ -3656,7 +3654,6 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, if (ret_val) return ret_val; } - /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, diff --git a/sys/dev/netif/ig_hal/e1000_phy.h b/sys/dev/netif/ig_hal/e1000_phy.h index d54f227e31..7802a86c2a 100644 --- a/sys/dev/netif/ig_hal/e1000_phy.h +++ b/sys/dev/netif/ig_hal/e1000_phy.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_PHY_H_ #define _E1000_PHY_H_ diff --git a/sys/dev/netif/ig_hal/e1000_regs.h b/sys/dev/netif/ig_hal/e1000_regs.h index c1ace9fd34..902e903b0e 100644 --- a/sys/dev/netif/ig_hal/e1000_regs.h +++ b/sys/dev/netif/ig_hal/e1000_regs.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2014, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD:$*/ +/*$FreeBSD$*/ #ifndef _E1000_REGS_H_ #define _E1000_REGS_H_ @@ -65,9 +65,9 @@ #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ #define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ -#define E1000_FEXTNVM9 0x5BB4 -#define E1000_FEXTNVM11 0x5BBC -#define E1000_PCIEANACFG 0x00F18 +#define E1000_FEXTNVM9 0x5BB4 /* Future Extended NVM 9 - RW */ +#define E1000_FEXTNVM11 0x5BBC /* Future Extended NVM 11 - RW */ +#define E1000_PCIEANACFG 0x00F18 /* PCIE Analog Config */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ @@ -111,6 +111,7 @@ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ #define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ +#define E1000_IOSFPC 0x00F28 /* TX corrupted data */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ #define E1000_EEMNGCTL_I210 0x01010 /* i210 MNG EEprom Mode Control */ #define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ @@ -602,6 +603,10 @@ #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_SYSSTMPL 0x0B648 /* HH Timesync system stamp low register */ +#define E1000_SYSSTMPH 0x0B64C /* HH Timesync system stamp hi register */ +#define E1000_PLTSTMPL 0x0B640 /* HH Timesync platform stamp low register */ +#define E1000_PLTSTMPH 0x0B644 /* HH Timesync platform stamp hi register */ #define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ #define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ -- 2.41.0