diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2013-08-05 19:58:07 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2013-08-05 19:58:07 +0000 |
commit | 118d662edbb41625655a577d96c1fed1e2996131 (patch) | |
tree | 969135293175029f2fb59f14d91fae790e656674 /sys/dev/pci/if_ix.c | |
parent | c769d1a992247045cf7682bfc1dbbe6221bc383a (diff) |
First stab at updating this monster to the Intel/FreeBSD current version.
This syncs PHY and chip dependent parts as well as brings support for the
flow control and additional (untested) bits for 1G fiber versions.
Tested by Hrvoje Popovski <hrvoje at srce ! hr> on 82599/SFP+DA, florian@
and benno@ on 82599/SFP+SR and on 82598/CX4-BP, 82599/SFP+DA and X540/RJ45
by me.
Diffstat (limited to 'sys/dev/pci/if_ix.c')
-rw-r--r-- | sys/dev/pci/if_ix.c | 500 |
1 files changed, 212 insertions, 288 deletions
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c index 6ce6b998b24..ef88367449e 100644 --- a/sys/dev/pci/if_ix.c +++ b/sys/dev/pci/if_ix.c @@ -1,8 +1,8 @@ -/* $OpenBSD: if_ix.c,v 1.89 2013/06/14 16:25:54 mikeb Exp $ */ +/* $OpenBSD: if_ix.c,v 1.90 2013/08/05 19:58:05 mikeb Exp $ */ /****************************************************************************** - Copyright (c) 2001-2008, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/*$FreeBSD: src/sys/dev/ixgbe/ixgbe.c,v 1.5 2008/05/16 18:46:30 jfv Exp $*/ +/* FreeBSD: src/sys/dev/ixgbe/ixgbe.c 251964 Jun 18 21:28:19 2013 UTC */ #include <dev/pci/if_ix.h> #include <dev/pci/ixgbe_type.h> @@ -40,8 +40,7 @@ /********************************************************************* * Driver version *********************************************************************/ - -#define IXGBE_DRIVER_VERSION "1.4.4" +/* char ixgbe_driver_version[] = "2.5.13"; */ /********************************************************************* * PCI Device ID Table @@ -75,9 +74,6 @@ const struct pci_matchid ixgbe_devices[] = { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP_SF2 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP_FCOE }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X540T }, -#if 0 - { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599VF } -#endif }; /********************************************************************* @@ -145,17 +141,16 @@ uint8_t *ixgbe_mc_array_itr(struct ixgbe_hw *, uint8_t **, uint32_t *); void ixgbe_setup_vlan_hw_support(struct ix_softc *); /* Support for pluggable optic modules */ -int ixgbe_sfp_probe(struct ix_softc *); +bool ixgbe_sfp_probe(struct ix_softc *); void ixgbe_setup_optics(struct ix_softc *); void ixgbe_handle_mod(struct ix_softc *); void ixgbe_handle_msf(struct ix_softc *); /* Legacy (single vector interrupt handler */ -int ixgbe_legacy_irq(void *); +int ixgbe_intr(void *); void ixgbe_enable_queue(struct ix_softc *, uint32_t); void ixgbe_disable_queue(struct ix_softc *, uint32_t); void ixgbe_rearm_queue(struct ix_softc *, uint32_t); -void ixgbe_handle_que(void *, int); /********************************************************************* * OpenBSD Device Interface Entry Points @@ -214,9 +209,6 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux) sc->osdep.os_sc = sc; sc->osdep.os_pa = *pa; - /* Core Lock Init*/ - mtx_init(&sc->core_mtx, IPL_NET); - /* Set up the timer callout */ timeout_set(&sc->timer, ixgbe_local_timer, sc); timeout_set(&sc->rx_refill, ixgbe_rxrefill, sc); @@ -239,43 +231,14 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux) /* Allocate multicast array memory. */ sc->mta = malloc(sizeof(uint8_t) * IXGBE_ETH_LENGTH_OF_ADDRESS * MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT); - if (sc->mta == 0) { + if (sc->mta == NULL) { printf(": Can not allocate multicast setup array\n"); goto err_late; } /* Initialize the shared code */ - switch (hw->mac.type) { - case ixgbe_mac_82598EB: - error = ixgbe_init_ops_82598(hw); - break; - case ixgbe_mac_82599EB: - error = ixgbe_init_ops_82599(hw); - break; -#if 0 - case ixgbe_mac_82599_vf: - error = ixgbe_init_ops_vf(hw); - break; -#endif - case ixgbe_mac_X540: - error = ixgbe_init_ops_X540(hw); - break; - default: - error = IXGBE_ERR_DEVICE_NOT_SUPPORTED; - break; - } - if (error == IXGBE_ERR_SFP_NOT_PRESENT) { - /* - * No optics in this port, set up - * so the timer routine will probe - * for later insertion. - */ - sc->sfp_probe = TRUE; - error = 0; - } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { - printf(": Unsupported SFP+ module detected!\n"); - goto err_late; - } else if (error) { + error = ixgbe_init_shared_code(hw); + if (error) { printf(": Unable to initialize the shared code\n"); goto err_late; } @@ -286,14 +249,7 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux) goto err_late; } - /* Get Hardware Flow Control setting */ - hw->fc.requested_mode = ixgbe_fc_full; - hw->fc.pause_time = IXGBE_FC_PAUSE; - hw->fc.low_water = IXGBE_FC_LO; - hw->fc.high_water = IXGBE_FC_HI; - hw->fc.send_xon = TRUE; - - error = sc->hw.mac.ops.init_hw(hw); + error = ixgbe_init_hw(hw); if (error == IXGBE_ERR_EEPROM_VERSION) { printf(": This device is a pre-production adapter/" "LOM. Please be aware there may be issues associated " @@ -315,7 +271,6 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux) bcopy(sc->hw.mac.addr, sc->arpcom.ac_enaddr, IXGBE_ETH_LENGTH_OF_ADDRESS); - /* XXX sc->msix > 1 && ixgbe_allocate_msix() */ error = ixgbe_allocate_legacy(sc); if (error) goto err_late; @@ -326,9 +281,12 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux) /* Initialize statistics */ ixgbe_update_stats_counters(sc); - /* Print PCIE bus type/speed/width info */ + /* Get the PCI-E bus info and determine LAN ID */ hw->mac.ops.get_bus_info(hw); + /* Set an initial default flow control value */ + sc->fc = ixgbe_fc_full; + /* let hardware know driver is loaded */ ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT); ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; @@ -403,7 +361,6 @@ ixgbe_start(struct ifnet * ifp) struct ix_softc *sc = ifp->if_softc; struct tx_ring *txr = sc->tx_rings; struct mbuf *m_head; - uint32_t queue = 0; int post = 0; if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) @@ -411,20 +368,6 @@ ixgbe_start(struct ifnet * ifp) if (!sc->link_up) return; -#if 0 - /* - * This is really just here for testing - * TX multiqueue, ultimately what is - * needed is the flow support in the stack - * and appropriate logic here to deal with - * it. -jfv - */ - if (sc->num_queues > 1) - queue = (curcpu % sc->num_queues); -#endif - - txr = &sc->tx_rings[queue]; - bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, 0, txr->txdma.dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); @@ -548,9 +491,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) /********************************************************************* * Watchdog entry point * - * This routine is called by the local timer - * to detect hardware hangs . - * **********************************************************************/ void @@ -584,7 +524,7 @@ ixgbe_watchdog(struct ifnet * ifp) * If we are in this routine because of pause frames, then don't * reset the hardware. */ - if (IXGBE_READ_REG(hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) { + if (!(IXGBE_READ_REG(hw, IXGBE_TFCS) & IXGBE_TFCS_TXON)) { for (i = 0; i < sc->num_queues; i++, txr++) txr->watchdog_timer = IXGBE_TX_TIMEOUT; ifp->if_timer = IXGBE_TX_TIMEOUT; @@ -634,12 +574,12 @@ ixgbe_init(void *arg) ixgbe_stop(sc); /* reprogram the RAR[0] in case user changed it. */ - ixgbe_hw(&sc->hw, set_rar, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV); + ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV); /* Get the latest mac address, User can use a LAA */ bcopy(sc->arpcom.ac_enaddr, sc->hw.mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); - ixgbe_hw(&sc->hw, set_rar, 0, sc->hw.mac.addr, 0, 1); + ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, 1); sc->hw.addr_ctrl.rar_used_count = 1; /* Prepare transmit descriptors and buffers */ @@ -651,10 +591,10 @@ ixgbe_init(void *arg) return; } - ixgbe_hw0(&sc->hw, init_hw); + ixgbe_init_hw(&sc->hw); ixgbe_initialize_transmit_units(sc); - /* Determine the correct buffer size for jumbo */ + /* Determine the correct mbuf pool for doing jumbo frames */ if (sc->max_frame_size <= 2048) sc->rx_mbuf_sz = MCLBYTES; else if (sc->max_frame_size <= 4096) @@ -758,7 +698,7 @@ ixgbe_init(void *arg) else msec_delay(1); } - /* XXX wmb() : memory barrier */ + IXGBE_WRITE_FLUSH(&sc->hw); IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(i), rxr->last_desc_filled); } @@ -770,13 +710,12 @@ ixgbe_init(void *arg) if (sc->hw.mac.type == ixgbe_mac_82598EB) rxctrl |= IXGBE_RXCTRL_DMBYPS; rxctrl |= IXGBE_RXCTRL_RXEN; - ixgbe_hw(&sc->hw, enable_rx_dma, rxctrl); + sc->hw.mac.ops.enable_rx_dma(&sc->hw, rxctrl); timeout_add_sec(&sc->timer, 1); -#ifdef MSI /* Set up MSI/X routing */ - if (ixgbe_enable_msix) { + if (sc->msix > 1) { ixgbe_configure_ivars(sc); /* Set up auto-mask */ if (sc->hw.mac.type == ixgbe_mac_82598EB) @@ -785,14 +724,11 @@ ixgbe_init(void *arg) IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); } - } else /* Simple settings for Legacy/MSI */ -#else - { + } else { /* Simple settings for Legacy/MSI */ ixgbe_set_ivar(sc, 0, 0, 0); ixgbe_set_ivar(sc, 0, 0, 1); IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); } -#endif /* Check on any SFP devices that need to be kick-started */ if (sc->hw.phy.type == ixgbe_phy_none) { @@ -813,6 +749,35 @@ ixgbe_init(void *arg) /* Config/Enable Link */ ixgbe_config_link(sc); + /* Hardware Packet Buffer & Flow Control setup */ + { + uint32_t rxpb, frame, size, tmp; + + frame = sc->max_frame_size; + + /* Calculate High Water */ + if (sc->hw.mac.type == ixgbe_mac_X540) + tmp = IXGBE_DV_X540(frame, frame); + else + tmp = IXGBE_DV(frame, frame); + size = IXGBE_BT2KB(tmp); + rxpb = IXGBE_READ_REG(&sc->hw, IXGBE_RXPBSIZE(0)) >> 10; + sc->hw.fc.high_water[0] = rxpb - size; + + /* Now calculate Low Water */ + if (sc->hw.mac.type == ixgbe_mac_X540) + tmp = IXGBE_LOW_DV_X540(frame); + else + tmp = IXGBE_LOW_DV(frame); + sc->hw.fc.low_water[0] = IXGBE_BT2KB(tmp); + + sc->hw.fc.requested_mode = sc->fc; + sc->hw.fc.pause_time = IXGBE_FC_PAUSE; + sc->hw.fc.send_xon = TRUE; + } + /* Initialize the FC settings */ + sc->hw.mac.ops.start_hw(&sc->hw); + /* And now turn on interrupts */ ixgbe_enable_intr(sc); @@ -864,51 +829,6 @@ ixgbe_disable_queue(struct ix_softc *sc, uint32_t vector) } } -void -ixgbe_rearm_queue(struct ix_softc *sc, uint32_t vector) -{ - uint64_t queue = 1ULL << vector; - uint32_t mask; - - if (sc->hw.mac.type == ixgbe_mac_82598EB) { - mask = (IXGBE_EIMS_RTX_QUEUE & queue); - IXGBE_WRITE_REG(&sc->hw, IXGBE_EICS, mask); - } else { - mask = (queue & 0xFFFFFFFF); - if (mask) - IXGBE_WRITE_REG(&sc->hw, IXGBE_EICS_EX(0), mask); - mask = (queue >> 32); - if (mask) - IXGBE_WRITE_REG(&sc->hw, IXGBE_EICS_EX(1), mask); - } -} - -void -ixgbe_handle_que(void *context, int pending) -{ - struct ix_queue *que = context; - struct ix_softc *sc = que->sc; - struct tx_ring *txr = que->txr; - struct ifnet *ifp = &que->sc->arpcom.ac_if; - - if (ifp->if_flags & IFF_RUNNING) { - ixgbe_rxeof(que); - ixgbe_txeof(txr); - - if (ixgbe_rxfill(que->rxr)) { - /* Advance the Rx Queue "Tail Pointer" */ - IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(que->rxr->me), - que->rxr->last_desc_filled); - } - - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - ixgbe_start(ifp); - } - - /* Reenable this interrupt */ - ixgbe_enable_queue(que->sc, que->msix); -} - /********************************************************************* * * Legacy Interrupt Service routine @@ -916,7 +836,7 @@ ixgbe_handle_que(void *context, int pending) **********************************************************************/ int -ixgbe_legacy_irq(void *arg) +ixgbe_intr(void *arg) { struct ix_softc *sc = (struct ix_softc *)arg; struct ix_queue *que = sc->queues; @@ -932,23 +852,6 @@ ixgbe_legacy_irq(void *arg) return (0); } - /* Check for fan failure */ - if ((hw->phy.media_type == ixgbe_media_type_copper) && - (reg_eicr & IXGBE_EICR_GPI_SDP1)) { - printf("%s: CRITICAL: FAN FAILURE!! " - "REPLACE IMMEDIATELY!!\n", ifp->if_xname); - IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS, - IXGBE_EICR_GPI_SDP1); - } - - /* Check for over temp condition */ - if ((hw->mac.type == ixgbe_mac_X540) && - (reg_eicr & IXGBE_EICR_GPI_SDP0)) { - printf("%s: CRITICAL: OVER TEMP!! " - "PHY IS SHUT DOWN!!\n", ifp->if_xname); - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0); - } - /* Link status change */ if (reg_eicr & IXGBE_EICR_LSC) { timeout_del(&sc->timer); @@ -961,19 +864,28 @@ ixgbe_legacy_irq(void *arg) /* Clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2); ixgbe_handle_mod(sc); - } -#if 0 - /* - * XXX: Processing of SDP1 (multispeed fiber) interrupts is - * disabled due to the lack of testing - */ - else if ((hw->phy.media_type != ixgbe_media_type_copper) && + } else if ((hw->phy.media_type != ixgbe_media_type_copper) && (reg_eicr & IXGBE_EICR_GPI_SDP1)) { /* Clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); ixgbe_handle_msf(sc); } -#endif + } + + /* Check for fan failure */ + if ((hw->device_id == IXGBE_DEV_ID_82598AT) && + (reg_eicr & IXGBE_EICR_GPI_SDP1)) { + printf("%s: CRITICAL: FAN FAILURE!! " + "REPLACE IMMEDIATELY!!\n", ifp->if_xname); + IXGBE_WRITE_REG(&sc->hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); + } + + /* Check for over temp condition */ + if ((hw->mac.type == ixgbe_mac_X540) && + (reg_eicr & IXGBE_EICR_TS)) { + printf("%s: CRITICAL: OVER TEMP!! " + "PHY IS SHUT DOWN!!\n", ifp->if_xname); + IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); } if (ifp->if_flags & IFF_RUNNING) { @@ -1027,7 +939,8 @@ ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) ifmr->ifm_active |= IFM_100_TX | IFM_FDX; break; case IXGBE_LINK_SPEED_1GB_FULL: - ifmr->ifm_active |= IFM_1000_T | IFM_FDX; + ifmr->ifm_active |= ((sc->optics == IFM_1000_SX) ? + IFM_1000_SX : IFM_1000_T) | IFM_FDX; break; case IXGBE_LINK_SPEED_10GB_FULL: ifmr->ifm_active |= sc->optics | IFM_FDX; @@ -1062,26 +975,41 @@ ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) * **********************************************************************/ int -ixgbe_media_change(struct ifnet * ifp) +ixgbe_media_change(struct ifnet *ifp) { - /* ignore */ + struct ix_softc *sc = ifp->if_softc; + struct ifmedia *ifm = &sc->media; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + switch (IFM_SUBTYPE(ifm->ifm_media)) { + case IFM_AUTO: + sc->hw.phy.autoneg_advertised = + IXGBE_LINK_SPEED_100_FULL | + IXGBE_LINK_SPEED_1GB_FULL | + IXGBE_LINK_SPEED_10GB_FULL; + break; + default: + return (EINVAL); + } + return (0); } /********************************************************************* * - * This routine maps the mbufs to tx descriptors. - * WARNING: while this code is using an MQ style infrastructure, - * it would NOT work as is with more than 1 queue. + * This routine maps the mbufs to tx descriptors, allowing the + * TX engine to transmit the packets. + * - return 0 on success, positive on failure * - * return 0 on success, positive on failure **********************************************************************/ int ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head) { struct ix_softc *sc = txr->sc; - uint32_t olinfo_status = 0, cmd_type_len = 0; + uint32_t olinfo_status = 0, cmd_type_len; int i, j, error; int first, last = 0; bus_dmamap_t map; @@ -1089,8 +1017,8 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head) union ixgbe_adv_tx_desc *txd = NULL; /* Basic descriptor defines */ - cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA | - IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT; + cmd_type_len = (IXGBE_ADVTXD_DTYP_DATA | + IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT); #if NVLAN > 0 if (m_head->m_flags & M_VLANTAG) @@ -1121,9 +1049,18 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head) /* * Map the packet for DMA. */ - error = bus_dmamap_load_mbuf(txr->txdma.dma_tag, map, - m_head, BUS_DMA_NOWAIT); - if (error != 0) { + error = bus_dmamap_load_mbuf(txr->txdma.dma_tag, map, m_head, + BUS_DMA_NOWAIT); + switch (error) { + case 0: + break; + case EFBIG: + if (m_defrag(m_head, M_NOWAIT) == 0 && + (error = bus_dmamap_load_mbuf(txr->txdma.dma_tag, map, + m_head, BUS_DMA_NOWAIT)) == 0) + break; + /* FALLTHROUGH */ + default: sc->no_tx_dma_setup++; return (error); } @@ -1136,10 +1073,10 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head) /* * Set the appropriate offload context - * this becomes the first descriptor. + * this will becomes the first descriptor. */ - if ((error = ixgbe_tx_ctx_setup(txr, m_head, &cmd_type_len, - &olinfo_status)) != 0) + error = ixgbe_tx_ctx_setup(txr, m_head, &cmd_type_len, &olinfo_status); + if (error) goto xmit_fail; i = txr->next_avail_desc; @@ -1166,7 +1103,12 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head) txr->next_avail_desc = i; txbuf->m_head = m_head; - /* swap maps because last tx descriptor is tracking all the data */ + /* + * Here we swap the map so the last descriptor, + * which gets the completion interrupt has the + * real map, and the first descriptor gets the + * unused map from this descriptor. + */ txr->tx_buffers[first].map = txbuf->map; txbuf->map = map; bus_dmamap_sync(txr->txdma.dma_tag, map, 0, map->dm_mapsize, @@ -1225,8 +1167,8 @@ ixgbe_iff(struct ix_softc *sc) } update_ptr = mta; - ixgbe_hw(&sc->hw, update_mc_addr_list, - update_ptr, mcnt, ixgbe_mc_array_itr); + sc->hw.mac.ops.update_mc_addr_list(&sc->hw, update_ptr, mcnt, + ixgbe_mc_array_itr, TRUE); } IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, fctrl); @@ -1254,7 +1196,7 @@ ixgbe_mc_array_itr(struct ixgbe_hw *hw, uint8_t **update_ptr, uint32_t *vmdq) * Timer routine * * This routine checks for link status,updates statistics, - * and runs the watchdog timer. + * and runs the watchdog check. * **********************************************************************/ @@ -1294,7 +1236,7 @@ ixgbe_update_link_status(struct ix_softc *sc) struct ifnet *ifp = &sc->arpcom.ac_if; int link_state = LINK_STATE_DOWN; - ixgbe_hw(&sc->hw, check_link, &sc->link_speed, &sc->link_up, 0); + ixgbe_check_link(&sc->hw, &sc->link_speed, &sc->link_up, 0); if (sc->link_up) link_state = LINK_STATE_FULL_DUPLEX; @@ -1317,15 +1259,16 @@ ixgbe_update_link_status(struct ix_softc *sc) break; } } + if (sc->link_up) /* Update any Flow Control changes */ + sc->hw.mac.ops.fc_enable(&sc->hw); ifp->if_link_state = link_state; if_link_state_change(ifp); } - /********************************************************************* * - * This routine disables all traffic on the sc by issuing a + * This routine disables all traffic on the adapter by issuing a * global reset on the MAC and deallocates TX/RX buffers. * **********************************************************************/ @@ -1342,17 +1285,19 @@ ixgbe_stop(void *arg) INIT_DEBUGOUT("ixgbe_stop: begin\n"); ixgbe_disable_intr(sc); - ixgbe_hw0(&sc->hw, reset_hw); + sc->hw.mac.ops.reset_hw(&sc->hw); sc->hw.adapter_stopped = FALSE; - ixgbe_hw0(&sc->hw, stop_adapter); + sc->hw.mac.ops.stop_adapter(&sc->hw); + if (sc->hw.mac.type == ixgbe_mac_82599EB) + sc->hw.mac.ops.stop_mac_link_on_d3(&sc->hw); /* Turn off the laser */ if (sc->hw.phy.multispeed_fiber) - ixgbe_hw0(&sc->hw, disable_tx_laser); + sc->hw.mac.ops.disable_tx_laser(&sc->hw); timeout_del(&sc->timer); timeout_del(&sc->rx_refill); /* reprogram the RAR[0] in case user changed it. */ - ixgbe_hw(&sc->hw, set_rar, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV); + ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV); /* Should we really clear all structures on stop? */ ixgbe_free_transmit_structures(sc); @@ -1390,20 +1335,12 @@ ixgbe_identify_hardware(struct ix_softc *sc) case PCI_PRODUCT_INTEL_82598AF: case PCI_PRODUCT_INTEL_82598_SR_DUAL_EM: case PCI_PRODUCT_INTEL_82598EB_SFP: - sc->hw.mac.type = ixgbe_mac_82598EB; - break; case PCI_PRODUCT_INTEL_82598EB_CX4_DUAL: case PCI_PRODUCT_INTEL_82598EB_CX4: - sc->hw.mac.type = ixgbe_mac_82598EB; - break; case PCI_PRODUCT_INTEL_82598EB_XF_LR: - sc->hw.mac.type = ixgbe_mac_82598EB; - break; case PCI_PRODUCT_INTEL_82598AT: case PCI_PRODUCT_INTEL_82598AT2: case PCI_PRODUCT_INTEL_82598AT_DUAL: - sc->hw.mac.type = ixgbe_mac_82598EB; - break; case PCI_PRODUCT_INTEL_82598_BX: sc->hw.mac.type = ixgbe_mac_82598EB; break; @@ -1411,36 +1348,31 @@ ixgbe_identify_hardware(struct ix_softc *sc) case PCI_PRODUCT_INTEL_82599_SFP_EM: case PCI_PRODUCT_INTEL_82599_SFP_FCOE: case PCI_PRODUCT_INTEL_82599_SFP_SF2: - sc->hw.mac.type = ixgbe_mac_82599EB; - sc->hw.phy.smart_speed = ixgbe_smart_speed; - break; case PCI_PRODUCT_INTEL_82599_KX4: case PCI_PRODUCT_INTEL_82599_KX4_MEZZ: case PCI_PRODUCT_INTEL_82599_CX4: - sc->hw.mac.type = ixgbe_mac_82599EB; - sc->hw.phy.smart_speed = ixgbe_smart_speed; - break; case PCI_PRODUCT_INTEL_82599_T3_LOM: - sc->hw.mac.type = ixgbe_mac_82599EB; - sc->hw.phy.smart_speed = ixgbe_smart_speed; - break; case PCI_PRODUCT_INTEL_82599_XAUI: case PCI_PRODUCT_INTEL_82599_COMBO_BP: case PCI_PRODUCT_INTEL_82599_BPLANE_FCOE: sc->hw.mac.type = ixgbe_mac_82599EB; - sc->hw.phy.smart_speed = ixgbe_smart_speed; break; case PCI_PRODUCT_INTEL_82599VF: sc->hw.mac.type = ixgbe_mac_82599_vf; - sc->hw.phy.smart_speed = ixgbe_smart_speed; break; case PCI_PRODUCT_INTEL_X540T: sc->hw.mac.type = ixgbe_mac_X540; - sc->hw.phy.smart_speed = ixgbe_smart_speed; break; default: break; } + + /* Pick up the 82599 and VF settings */ + if (sc->hw.mac.type != ixgbe_mac_82598EB) { + sc->hw.phy.smart_speed = ixgbe_smart_speed; + sc->num_segs = IXGBE_82599_SCATTER; + } else + sc->num_segs = IXGBE_82598_SCATTER; } /********************************************************************* @@ -1454,22 +1386,26 @@ ixgbe_setup_optics(struct ix_softc *sc) struct ixgbe_hw *hw = &sc->hw; int layer; - layer = ixgbe_hw(hw, get_supported_physical_layer); + layer = hw->mac.ops.get_supported_physical_layer(hw); if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) sc->optics = IFM_10G_T; else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) sc->optics = IFM_1000_T; + else if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) + sc->optics = IFM_100_TX; + else if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) + sc->optics = IFM_10G_SFP_CU; else if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_LR | IXGBE_PHYSICAL_LAYER_10GBASE_LRM)) sc->optics = IFM_10G_LR; else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) sc->optics = IFM_10G_SR; - else if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) - sc->optics = IFM_10G_SFP_CU; else if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | IXGBE_PHYSICAL_LAYER_10GBASE_CX4)) sc->optics = IFM_10G_CX4; + else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) + sc->optics = IFM_1000_SX; else sc->optics = IFM_ETHER | IFM_AUTO; } @@ -1506,7 +1442,7 @@ ixgbe_allocate_legacy(struct ix_softc *sc) intrstr = pci_intr_string(pc, ih); sc->tag = pci_intr_establish(pc, ih, IPL_NET, - ixgbe_legacy_irq, sc, ifp->if_xname); + ixgbe_intr, sc, ifp->if_xname); if (sc->tag == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) @@ -1586,9 +1522,7 @@ ixgbe_free_pci_resources(struct ix_softc * sc) void ixgbe_setup_interface(struct ix_softc *sc) { - struct ixgbe_hw *hw = &sc->hw; struct ifnet *ifp = &sc->arpcom.ac_if; - INIT_DEBUGOUT("ixgbe_setup_interface: begin"); strlcpy(ifp->if_xname, sc->dev.dv_xname, IFNAMSIZ); ifp->if_softc = sc; @@ -1620,15 +1554,9 @@ ixgbe_setup_interface(struct ix_softc *sc) */ ifmedia_init(&sc->media, IFM_IMASK, ixgbe_media_change, ixgbe_media_status); - ifmedia_add(&sc->media, IFM_ETHER | sc->optics | - IFM_FDX, 0, NULL); - if ((hw->device_id == PCI_PRODUCT_INTEL_82598AT) || - (hw->device_id == PCI_PRODUCT_INTEL_82598AT_DUAL)) { - ifmedia_add(&sc->media, - IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); - ifmedia_add(&sc->media, - IFM_ETHER | IFM_1000_T, 0, NULL); - } + if (sc->optics) + ifmedia_add(&sc->media, IFM_ETHER | sc->optics | + IFM_FDX, 0, NULL); ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); @@ -1643,7 +1571,7 @@ void ixgbe_config_link(struct ix_softc *sc) { uint32_t autoneg, err = 0; - int sfp, negotiate = FALSE; + bool sfp, negotiate; switch (sc->hw.phy.type) { case ixgbe_phy_sfp_avago: @@ -1652,42 +1580,38 @@ ixgbe_config_link(struct ix_softc *sc) case ixgbe_phy_sfp_unknown: case ixgbe_phy_sfp_passive_tyco: case ixgbe_phy_sfp_passive_unknown: - sfp = 1; + sfp = TRUE; break; default: - sfp = 0; + sfp = FALSE; break; } if (sfp) { if (&sc->hw.phy.multispeed_fiber) { sc->hw.mac.ops.setup_sfp(&sc->hw); - ixgbe_hw0(&sc->hw, enable_tx_laser); - /* XXX taskqueue_enqueue(sc->tq, &sc->msf_task); */ - } /* else */ - /* XXX taskqueue_enqueue(sc->tq, &sc->mod_task); */ + sc->hw.mac.ops.enable_tx_laser(&sc->hw); + ixgbe_handle_msf(sc); + } else + ixgbe_handle_mod(sc); } else { if (sc->hw.mac.ops.check_link) err = sc->hw.mac.ops.check_link(&sc->hw, &autoneg, &sc->link_up, FALSE); if (err) return; - /* XXX: must be changeable in ixgbe_media_change */ - autoneg = IXGBE_LINK_SPEED_100_FULL | - IXGBE_LINK_SPEED_1GB_FULL | - IXGBE_LINK_SPEED_10GB_FULL; + autoneg = sc->hw.phy.autoneg_advertised; if ((!autoneg) && (sc->hw.mac.ops.get_link_capabilities)) err = sc->hw.mac.ops.get_link_capabilities(&sc->hw, &autoneg, &negotiate); if (err) return; if (sc->hw.mac.ops.setup_link) - err = sc->hw.mac.ops.setup_link(&sc->hw, autoneg, - negotiate, sc->link_up); + err = sc->hw.mac.ops.setup_link(&sc->hw, + autoneg, sc->link_up); } } - /******************************************************************** * Manage DMA'able memory. *******************************************************************/ @@ -1724,9 +1648,8 @@ ixgbe_dma_malloc(struct ix_softc *sc, bus_size_t size, goto fail_2; } - r = bus_dmamap_load(dma->dma_tag, dma->dma_map, - dma->dma_vaddr, size, NULL, - mapflags | BUS_DMA_NOWAIT); + r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, + size, NULL, mapflags | BUS_DMA_NOWAIT); if (r != 0) { printf("%s: ixgbe_dma_malloc: bus_dmamap_load failed; " "error %u\n", ifp->if_xname, r); @@ -1808,7 +1731,7 @@ ixgbe_allocate_queues(struct ix_softc *sc) /* For the ring itself */ tsize = roundup2(sc->num_tx_desc * - sizeof(union ixgbe_adv_tx_desc), 4096); + sizeof(union ixgbe_adv_tx_desc), DBA_ALIGN); /* * Now set up the TX queues, txconf is needed to handle the @@ -1821,9 +1744,6 @@ ixgbe_allocate_queues(struct ix_softc *sc) txr->sc = sc; txr->me = i; - /* Initialize the TX side lock */ - mtx_init(&txr->tx_mtx, IPL_NET); - if (ixgbe_dma_malloc(sc, tsize, &txr->txdma, BUS_DMA_NOWAIT)) { printf("%s: Unable to allocate TX Descriptor memory\n", @@ -1845,9 +1765,6 @@ ixgbe_allocate_queues(struct ix_softc *sc) rxr->sc = sc; rxr->me = i; - /* Initialize the TX side lock */ - mtx_init(&rxr->rx_mtx, IPL_NET); - if (ixgbe_dma_malloc(sc, rsize, &rxr->rxdma, BUS_DMA_NOWAIT)) { printf("%s: Unable to allocate RxDescriptor memory\n", @@ -1874,9 +1791,8 @@ err_rx_desc: for (rxr = sc->rx_rings; rxconf > 0; rxr++, rxconf--) ixgbe_dma_free(sc, &rxr->rxdma); err_tx_desc: - for (txr = sc->tx_rings; txconf > 0; txr++, txconf--) { + for (txr = sc->tx_rings; txconf > 0; txr++, txconf--) ixgbe_dma_free(sc, &txr->txdma); - } free(sc->rx_rings, M_DEVBUF); sc->rx_rings = NULL; rx_fail: @@ -1896,21 +1812,10 @@ fail: int ixgbe_allocate_transmit_buffers(struct tx_ring *txr) { - struct ix_softc *sc; - struct ixgbe_osdep *os; - struct ifnet *ifp; + struct ix_softc *sc = txr->sc; + struct ifnet *ifp = &sc->arpcom.ac_if; struct ixgbe_tx_buf *txbuf; int error, i; - int max_segs; - - sc = txr->sc; - os = &sc->osdep; - ifp = &sc->arpcom.ac_if; - - if (sc->hw.mac.type == ixgbe_mac_82598EB) - max_segs = IXGBE_82598_SCATTER; - else - max_segs = IXGBE_82599_SCATTER; if (!(txr->tx_buffers = (struct ixgbe_tx_buf *) malloc(sizeof(struct ixgbe_tx_buf) * @@ -1926,7 +1831,7 @@ ixgbe_allocate_transmit_buffers(struct tx_ring *txr) for (i = 0; i < sc->num_tx_desc; i++) { txbuf = &txr->tx_buffers[i]; error = bus_dmamap_create(txr->txdma.dma_tag, IXGBE_TSO_SIZE, - max_segs, PAGE_SIZE, 0, + sc->num_segs, PAGE_SIZE, 0, BUS_DMA_NOWAIT, &txbuf->map); if (error != 0) { @@ -2044,7 +1949,7 @@ ixgbe_initialize_transmit_units(struct ix_softc *sc) txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); break; } - txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; switch (hw->mac.type) { case ixgbe_mac_82598EB: IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl); @@ -2277,7 +2182,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, /********************************************************************** * * Setup work for hardware segmentation offload (TSO) on - * scs using advanced tx descriptors + * adapters using advanced tx descriptors * **********************************************************************/ int @@ -2368,7 +2273,7 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT; vlan_macip_lens |= ip_hlen; - TXD->vlan_macip_lens |= htole32(vlan_macip_lens); + TXD->vlan_macip_lens = htole32(vlan_macip_lens); /* ADV DTYPE TUCMD */ type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT; @@ -2696,13 +2601,11 @@ ixgbe_setup_receive_structures(struct ix_softc *sc) struct rx_ring *rxr = sc->rx_rings; int i; - for (i = 0; i < sc->num_queues; i++, rxr++) { + for (i = 0; i < sc->num_queues; i++, rxr++) if (ixgbe_setup_receive_ring(rxr)) goto fail; - } return (0); - fail: ixgbe_free_receive_structures(sc); return (ENOBUFS); @@ -2710,7 +2613,7 @@ fail: /********************************************************************* * - * Enable receive unit. + * Setup receive registers and features. * **********************************************************************/ #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 @@ -3045,16 +2948,13 @@ ixgbe_rx_checksum(uint32_t staterr, struct mbuf * mp, uint32_t ptype) uint8_t errors = (uint8_t) (staterr >> 24); if (status & IXGBE_RXD_STAT_IPCS) { - /* Did it pass? */ if (!(errors & IXGBE_RXD_ERR_IPE)) { /* IP Checksum Good */ mp->m_pkthdr.csum_flags = M_IPV4_CSUM_IN_OK; } else mp->m_pkthdr.csum_flags = 0; } - if (status & IXGBE_RXD_STAT_L4CS) { - /* Did it pass? */ if (!(errors & IXGBE_RXD_ERR_TCPE)) mp->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK; @@ -3104,25 +3004,38 @@ ixgbe_enable_intr(struct ix_softc *sc) { struct ixgbe_hw *hw = &sc->hw; struct ix_queue *que = sc->queues; - uint32_t mask = IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE; + uint32_t mask, fwsm; int i; + mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); /* Enable Fan Failure detection */ if (hw->device_id == IXGBE_DEV_ID_82598AT) mask |= IXGBE_EIMS_GPI_SDP1; - else { + + switch (sc->hw.mac.type) { + case ixgbe_mac_82599EB: mask |= IXGBE_EIMS_ECC; mask |= IXGBE_EIMS_GPI_SDP0; mask |= IXGBE_EIMS_GPI_SDP1; mask |= IXGBE_EIMS_GPI_SDP2; + break; + case ixgbe_mac_X540: + mask |= IXGBE_EIMS_ECC; + /* Detect if Thermal Sensor is enabled */ + fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); + if (fwsm & IXGBE_FWSM_TS_ENABLED) + mask |= IXGBE_EIMS_TS; + break; + default: + break; } IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); /* With RSS we use auto clear */ - if (sc->msix) { + if (sc->msix > 1) { mask = IXGBE_EIMS_ENABLE_MASK; - /* Dont autoclear Link */ + /* Don't autoclear Link */ mask &= ~IXGBE_EIMS_OTHER; mask &= ~IXGBE_EIMS_LSC; IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, mask); @@ -3142,7 +3055,7 @@ ixgbe_enable_intr(struct ix_softc *sc) void ixgbe_disable_intr(struct ix_softc *sc) { - if (sc->msix) + if (sc->msix > 1) IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, 0); if (sc->hw.mac.type == ixgbe_mac_82598EB) { IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, ~0); @@ -3248,15 +3161,14 @@ ixgbe_set_ivar(struct ix_softc *sc, uint8_t entry, uint8_t vector, int8_t type) void ixgbe_configure_ivars(struct ix_softc *sc) { +#if notyet struct ix_queue *que = sc->queues; uint32_t newitr; int i; -#if 0 if (ixgbe_max_interrupt_rate > 0) - newitr = (8000000 / ixgbe_max_interrupt_rate) & 0x0FF8; + newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; else -#endif newitr = 0; for (i = 0; i < sc->num_queues; i++, que++) { @@ -3271,16 +3183,17 @@ ixgbe_configure_ivars(struct ix_softc *sc) /* For the Link interrupt */ ixgbe_set_ivar(sc, 1, sc->linkvec, -1); +#endif } /* * ixgbe_sfp_probe - called in the local timer to * determine if a port had optics inserted. */ -int +bool ixgbe_sfp_probe(struct ix_softc *sc) { - int result = FALSE; + bool result = FALSE; if ((sc->hw.phy.type == ixgbe_phy_nl) && (sc->hw.phy.sfp_type == ixgbe_sfp_type_not_present)) { @@ -3339,13 +3252,13 @@ ixgbe_handle_msf(struct ix_softc *sc) { struct ixgbe_hw *hw = &sc->hw; uint32_t autoneg; - int negotiate; + bool negotiate; autoneg = hw->phy.autoneg_advertised; if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); if (hw->mac.ops.setup_link) - hw->mac.ops.setup_link(hw, autoneg, negotiate, TRUE); + hw->mac.ops.setup_link(hw, autoneg, TRUE); } /********************************************************************** @@ -3381,9 +3294,23 @@ ixgbe_update_stats_counters(struct ix_softc *sc) sc->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); sc->stats.gprc -= missed_rx; - sc->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); - sc->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); - sc->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH); + if (hw->mac.type != ixgbe_mac_82598EB) { + sc->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) + + ((uint64_t)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32); + sc->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) + + ((uint64_t)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32); + sc->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORL) + + ((uint64_t)IXGBE_READ_REG(hw, IXGBE_TORH) << 32); + sc->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); + sc->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); + } else { + sc->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); + sc->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); + /* 82598 only has a counter in the high register */ + sc->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); + sc->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); + sc->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH); + } /* * Workaround: mprc hardware is incorrectly counting @@ -3404,9 +3331,6 @@ ixgbe_update_stats_counters(struct ix_softc *sc) sc->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); sc->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); - sc->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); - sc->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); - lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); sc->stats.lxontxc += lxon; lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); |