diff options
-rw-r--r-- | sys/dev/ixgbe/ixgbe.c | 607 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe.h | 78 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe_82598.c | 342 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe_api.c | 76 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe_api.h | 3 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe_common.c | 4 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe_osdep.h | 2 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe_phy.c | 191 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe_phy.h | 10 | ||||
-rw-r--r-- | sys/dev/ixgbe/ixgbe_type.h | 106 | ||||
-rw-r--r-- | sys/modules/ixgbe/Makefile | 15 |
11 files changed, 958 insertions, 476 deletions
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c index 6e1707d..fbb24d7 100644 --- a/sys/dev/ixgbe/ixgbe.c +++ b/sys/dev/ixgbe/ixgbe.c @@ -46,7 +46,7 @@ int ixgbe_display_debug_stats = 0; /********************************************************************* * Driver version *********************************************************************/ -char ixgbe_driver_version[] = "1.1.3"; +char ixgbe_driver_version[] = "1.2.6"; /********************************************************************* * PCI Device ID Table @@ -60,10 +60,9 @@ char ixgbe_driver_version[] = "1.1.3"; static ixgbe_vendor_info_t ixgbe_vendor_info_array[] = { - {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0}, - {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT_DUAL_PORT, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0}, /* required last entry */ {0, 0, 0, 0, 0} }; @@ -100,8 +99,9 @@ static int ixgbe_hardware_init(struct adapter *); static void ixgbe_setup_interface(device_t, struct adapter *); static int ixgbe_allocate_queues(struct adapter *); static int ixgbe_allocate_msix_resources(struct adapter *); +#if __FreeBSD_version >= 700000 static int ixgbe_setup_msix(struct adapter *); - +#endif static int ixgbe_allocate_transmit_buffers(struct tx_ring *); static int ixgbe_setup_transmit_structures(struct adapter *); static void ixgbe_setup_transmit_ring(struct tx_ring *); @@ -119,7 +119,7 @@ static void ixgbe_free_receive_buffers(struct rx_ring *); static void ixgbe_enable_intr(struct adapter *); static void ixgbe_disable_intr(struct adapter *); static void ixgbe_update_stats_counters(struct adapter *); -static boolean_t ixgbe_txeof(struct tx_ring *); +static bool ixgbe_txeof(struct tx_ring *); static int ixgbe_rxeof(struct rx_ring *, int); static void ixgbe_rx_checksum(struct adapter *, uint32_t, struct mbuf *); static void ixgbe_set_promisc(struct adapter *); @@ -133,6 +133,7 @@ static void ixgbe_enable_vlans(struct adapter * adapter); static int ixgbe_encap(struct adapter *, struct mbuf **); static int ixgbe_sysctl_stats(SYSCTL_HANDLER_ARGS); static int ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS); +static int ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS); static int ixgbe_dma_malloc(struct adapter *, bus_size_t, struct ixgbe_dma_alloc *, int); static void ixgbe_dma_free(struct adapter *, struct ixgbe_dma_alloc *); @@ -143,14 +144,23 @@ static boolean_t ixgbe_tso_setup(struct tx_ring *, struct mbuf *, u32 *); static void ixgbe_set_ivar(struct adapter *, u16, u8); static void ixgbe_configure_ivars(struct adapter *); -/* Legacy Interrupt handler */ -static void ixgbe_intr(void *); - +/* Legacy Fast Interrupt routine and handlers */ +#if __FreeBSD_version >= 700000 +static int ixgbe_fast_irq(void *); /* The MSI/X Interrupt handlers */ -static void ixgbe_txint(void *); -static void ixgbe_rxint(void *); -static void ixgbe_linkint(void *); +static void ixgbe_msix_tx(void *); +static void ixgbe_msix_rx(void *); +static void ixgbe_msix_link(void *); +#else +static void ixgbe_fast_irq(void *); +#endif + +static void ixgbe_rxtx(void *context, int pending); +static void ixgbe_link(void *context, int pending); +#ifndef NO_82598_A0_SUPPORT +static void desc_flip(void *); +#endif /********************************************************************* * FreeBSD Device Interface Entry Points @@ -175,27 +185,41 @@ DRIVER_MODULE(ixgbe, pci, ixgbe_driver, ixgbe_devclass, 0, 0); MODULE_DEPEND(ixgbe, pci, 1, 1, 1); MODULE_DEPEND(ixgbe, ether, 1, 1, 1); +/* +** TUNEABLE PARAMETERS: +*/ + /* How many packets rxeof tries to clean at a time */ static int ixgbe_rx_process_limit = 100; TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit); -/* - * Should the driver do MSI/X and RSS/MQ? - * - default to MSI/X and RSS enabled - */ -static int ixgbe_disable_msix = 0; -TUNABLE_INT("hw.ixgbe.disable_msix", &ixgbe_disable_msix); - -/* -** Flow control tuneable: -** 0 - off -** 1 - rx pause -** 2 - tx pause -** 3 - full -*/ -static int ixgbe_flow_control = 0; +/* Flow control setting, default to full */ +static int ixgbe_flow_control = 3; TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control); +/* Number of TX Queues, note multi tx is not working */ +static int ixgbe_tx_queues = 1; +TUNABLE_INT("hw.ixgbe.tx_queues", &ixgbe_tx_queues); + +/* Number of RX Queues */ +static int ixgbe_rx_queues = 8; +TUNABLE_INT("hw.ixgbe.rx_queues", &ixgbe_rx_queues); + +/* Number of Other Queues, this is used for link interrupts */ +static int ixgbe_other_queues = 1; +TUNABLE_INT("hw.ixgbe.other_queues", &ixgbe_other_queues); + +/* Number of TX descriptors per ring */ +static int ixgbe_txd = DEFAULT_TXD; +TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd); + +/* Number of RX descriptors per ring */ +static int ixgbe_rxd = DEFAULT_RXD; +TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd); + +/* Total number of Interfaces - need for config sanity check */ +static int ixgbe_total_ports; + /********************************************************************* * Device identification routine * @@ -239,6 +263,15 @@ ixgbe_probe(device_t dev) sprintf(adapter_name, "%s, Version - %s", ixgbe_strings[ent->index], ixgbe_driver_version); + switch (pci_device_id) { + case IXGBE_DEV_ID_82598AF_DUAL_PORT : + ixgbe_total_ports += 2; + break; + case IXGBE_DEV_ID_82598AF_SINGLE_PORT : + ixgbe_total_ports += 1; + default: + break; + } device_set_desc_copy(dev, adapter_name); return (0); } @@ -264,13 +297,17 @@ ixgbe_attach(device_t dev) struct adapter *adapter; int error = 0; uint32_t ctrl_ext; + char name_string[16]; INIT_DEBUGOUT("ixgbe_attach: begin"); /* Allocate, clear, and link in our adapter structure */ adapter = device_get_softc(dev); adapter->dev = adapter->osdep.dev = dev; - IXGBE_LOCK_INIT(adapter, device_get_nameunit(dev)); + /* General Lock Init*/ + snprintf(name_string, sizeof(name_string), "%s:core", + device_get_nameunit(dev)); + mtx_init(&adapter->core_mtx, name_string, NULL, MTX_DEF); /* SYSCTL APIs */ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), @@ -283,25 +320,17 @@ ixgbe_attach(device_t dev) OID_AUTO, "debug", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_debug, "I", "Debug Info"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "flow control", CTLFLAG_RW, - &ixgbe_flow_control, 0, "Flow Control"); + OID_AUTO, "flow_control", CTLTYPE_INT | CTLFLAG_RW, + adapter, 0, ixgbe_set_flowcntl, "I", "Flow Control"); /* Set up the timer callout */ - callout_init_mtx(&adapter->timer, &adapter->mtx, 0); + callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); /* Determine hardware revision */ ixgbe_identify_hardware(adapter); - /* - ** Descriptors: (configurable by user), note these are - ** constant for all rings, I saw no reason to vary - ** them, but perhaps someone later would. - */ - adapter->num_tx_desc = DEFAULT_TXD; - adapter->num_rx_desc = DEFAULT_RXD; - /* Indicate to RX setup to use Jumbo Clusters */ adapter->bigbufs = TRUE; @@ -312,17 +341,50 @@ ixgbe_attach(device_t dev) goto err_out; } + /* Do descriptor calc and sanity checks */ + if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 || + ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) { + device_printf(dev, "TXD config issue, using default!\n"); + adapter->num_tx_desc = DEFAULT_TXD; + } else + adapter->num_tx_desc = ixgbe_txd; + + /* + ** With many RX rings it is easy to exceed the + ** system mbuf allocation. Tuning nmbclusters + ** can alleviate this. + */ + if ((adapter->num_rx_queues > 1) && (nmbclusters > 0 )){ + int s; + /* Calculate the total RX mbuf needs */ + s = (ixgbe_rxd * adapter->num_rx_queues) * ixgbe_total_ports; + if (s > nmbclusters) { + device_printf(dev, "RX Descriptors exceed " + "system mbuf max, using default instead!\n"); + ixgbe_rxd = DEFAULT_RXD; + } + } + + if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 || + ixgbe_rxd < MIN_TXD || ixgbe_rxd > MAX_TXD) { + device_printf(dev, "RXD config issue, using default!\n"); + adapter->num_rx_desc = DEFAULT_RXD; + } else + adapter->num_rx_desc = ixgbe_rxd; + /* Allocate our TX/RX Queues */ if (ixgbe_allocate_queues(adapter)) { error = ENOMEM; goto err_out; } +#if __FreeBSD_version >= 700000 if (adapter->msix) { error = ixgbe_setup_msix(adapter); if (error) goto err_out; } +#endif /* Initialize the shared code */ if (ixgbe_init_shared_code(&adapter->hw)) { @@ -382,14 +444,25 @@ ixgbe_detach(device_t dev) INIT_DEBUGOUT("ixgbe_detach: begin"); /* Make sure VLANS are not using driver */ +#if __FreeBSD_version >= 700000 if (adapter->ifp->if_vlantrunk != NULL) { +#else + if (adapter->ifp->if_nvlans != 0) { +#endif device_printf(dev,"Vlan in use, detach first\n"); return (EBUSY); } - IXGBE_LOCK(adapter); + mtx_lock(&adapter->core_mtx); ixgbe_stop(adapter); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->core_mtx); + + if (adapter->tq != NULL) { + taskqueue_drain(adapter->tq, &adapter->rxtx_task); + taskqueue_drain(taskqueue_fast, &adapter->link_task); + taskqueue_free(adapter->tq); + adapter->tq = NULL; + } /* let hardware know driver is unloading */ ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); @@ -405,7 +478,7 @@ ixgbe_detach(device_t dev) ixgbe_free_transmit_structures(adapter); ixgbe_free_receive_structures(adapter); - IXGBE_LOCK_DESTROY(adapter); + mtx_destroy(&adapter->core_mtx); return (0); } @@ -419,9 +492,9 @@ static int ixgbe_shutdown(device_t dev) { struct adapter *adapter = device_get_softc(dev); - IXGBE_LOCK(adapter); + mtx_lock(&adapter->core_mtx); ixgbe_stop(adapter); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->core_mtx); return (0); } @@ -442,7 +515,7 @@ ixgbe_start_locked(struct ifnet * ifp) struct mbuf *m_head; struct adapter *adapter = ifp->if_softc; - IXGBE_LOCK_ASSERT(adapter); + mtx_assert(&adapter->tx_mtx, MA_OWNED); if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) @@ -464,7 +537,7 @@ ixgbe_start_locked(struct ifnet * ifp) break; } /* Send a copy of the frame to the BPF listener */ - BPF_MTAP(ifp, m_head); + ETHER_BPF_MTAP(ifp, m_head); /* Set timeout in case hardware has problems transmitting */ adapter->watchdog_timer = IXGBE_TX_TIMEOUT; @@ -478,10 +551,10 @@ ixgbe_start(struct ifnet *ifp) { struct adapter *adapter = ifp->if_softc; - IXGBE_LOCK(adapter); + mtx_lock(&adapter->tx_mtx); if (ifp->if_drv_flags & IFF_DRV_RUNNING) ixgbe_start_locked(ifp); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->tx_mtx); return; } @@ -508,9 +581,9 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) if (ifa->ifa_addr->sa_family == AF_INET) { ifp->if_flags |= IFF_UP; if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - IXGBE_LOCK(adapter); + mtx_lock(&adapter->core_mtx); ixgbe_init_locked(adapter); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->core_mtx); } arp_ifinit(ifp, ifa); } else @@ -521,17 +594,17 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) { error = EINVAL; } else { - IXGBE_LOCK(adapter); + mtx_lock(&adapter->core_mtx); ifp->if_mtu = ifr->ifr_mtu; adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; ixgbe_init_locked(adapter); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->core_mtx); } break; case SIOCSIFFLAGS: IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)"); - IXGBE_LOCK(adapter); + mtx_lock(&adapter->core_mtx); if (ifp->if_flags & IFF_UP) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { if ((ifp->if_flags ^ adapter->if_flags) & @@ -545,17 +618,17 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) if (ifp->if_drv_flags & IFF_DRV_RUNNING) ixgbe_stop(adapter); adapter->if_flags = ifp->if_flags; - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->core_mtx); break; case SIOCADDMULTI: case SIOCDELMULTI: IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI"); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - IXGBE_LOCK(adapter); + mtx_lock(&adapter->core_mtx); ixgbe_disable_intr(adapter); ixgbe_set_multi(adapter); ixgbe_enable_intr(adapter); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->core_mtx); } break; case SIOCSIFMEDIA: @@ -575,7 +648,9 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; if (ifp->if_drv_flags & IFF_DRV_RUNNING) ixgbe_init(adapter); +#if __FreeBSD_version >= 700000 VLAN_CAPABILITIES(ifp); +#endif break; } default: @@ -598,7 +673,7 @@ static void ixgbe_watchdog(struct adapter *adapter) { - IXGBE_LOCK_ASSERT(adapter); + mtx_assert(&adapter->core_mtx, MA_OWNED); /* * The timer is set to 5 every time ixgbe_start() queues a packet. @@ -651,13 +726,15 @@ ixgbe_init_locked(struct adapter *adapter) INIT_DEBUGOUT("ixgbe_init: begin"); - IXGBE_LOCK_ASSERT(adapter); + mtx_assert(&adapter->core_mtx, MA_OWNED); ixgbe_stop(adapter); /* Get the latest mac address, User can use a LAA */ bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); + ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, 1); + adapter->hw.addr_ctrl.rar_used_count = 1; /* Initialize the hardware */ if (ixgbe_hardware_init(adapter)) { @@ -756,60 +833,91 @@ ixgbe_init(void *arg) { struct adapter *adapter = arg; - IXGBE_LOCK(adapter); + mtx_lock(&adapter->core_mtx); ixgbe_init_locked(adapter); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->core_mtx); return; } +static void +ixgbe_link(void *context, int pending) +{ + struct adapter *adapter = context; + struct ifnet *ifp = adapter->ifp; + + mtx_lock(&adapter->core_mtx); + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + mtx_unlock(&adapter->core_mtx); + return; + } + + callout_stop(&adapter->timer); + ixgbe_update_link_status(adapter); + callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); + mtx_unlock(&adapter->core_mtx); +} + +/* +** MSI and Legacy Deferred Handler +** - note this runs without the general lock +*/ +static void +ixgbe_rxtx(void *context, int pending) +{ + struct adapter *adapter = context; + struct ifnet *ifp = adapter->ifp; + /* For legacy there is only one of each */ + struct rx_ring *rxr = adapter->rx_rings; + struct tx_ring *txr = adapter->tx_rings; + + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + if (ixgbe_rxeof(rxr, adapter->rx_process_limit) != 0) + taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); + mtx_lock(&adapter->tx_mtx); + ixgbe_txeof(txr); + + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + ixgbe_start_locked(ifp); + mtx_unlock(&adapter->tx_mtx); + } + + ixgbe_enable_intr(adapter); +} + + /********************************************************************* * * Legacy Interrupt Service routine * **********************************************************************/ +#if __FreeBSD_version >= 700000 +static int +#else static void -ixgbe_intr(void *arg) +#endif +ixgbe_fast_irq(void *arg) { - u32 loop_cnt = MAX_INTR; u32 reg_eicr; struct adapter *adapter = arg; - struct ifnet *ifp = adapter->ifp; - struct rx_ring *rxr = adapter->rx_rings; - struct tx_ring *txr = adapter->tx_rings; - - IXGBE_LOCK(adapter); reg_eicr = IXGBE_READ_REG(&adapter->hw, IXGBE_EICR); - if (reg_eicr == 0) { - IXGBE_UNLOCK(adapter); - return; - } + if (reg_eicr == 0) + return FILTER_STRAY; - /* Link status change */ - if (reg_eicr & IXGBE_EICR_LSC) { - callout_stop(&adapter->timer); - ixgbe_update_link_status(adapter); - callout_reset(&adapter->timer, hz, - ixgbe_local_timer, adapter); - } + ixgbe_disable_intr(adapter); + taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); - while ((--loop_cnt > 0) && - (ifp->if_drv_flags & IFF_DRV_RUNNING)) { - ixgbe_rxeof(rxr, adapter->rx_process_limit); - ixgbe_txeof(txr); - } - - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_snd.ifq_head != NULL) - ixgbe_start_locked(ifp); + /* Link status change */ + if (reg_eicr & IXGBE_EICR_LSC) + taskqueue_enqueue(taskqueue_fast, &adapter->link_task); - IXGBE_UNLOCK(adapter); - return; + return FILTER_HANDLED; } +#if __FreeBSD_version >= 700000 /********************************************************************* * * MSI TX Interrupt Service routine @@ -817,14 +925,14 @@ ixgbe_intr(void *arg) **********************************************************************/ void -ixgbe_txint(void *arg) +ixgbe_msix_tx(void *arg) { struct tx_ring *txr = arg; struct adapter *adapter = txr->adapter; struct ifnet *ifp = adapter->ifp; uint32_t loop_cnt = MAX_INTR; - IXGBE_LOCK(adapter); + mtx_lock(&adapter->tx_mtx); while (loop_cnt > 0) { if (__predict_false(!ixgbe_txeof(txr))) @@ -836,7 +944,7 @@ ixgbe_txint(void *arg) ifp->if_snd.ifq_head != NULL) ixgbe_start_locked(ifp); ixgbe_enable_intr(adapter); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->tx_mtx); return; } @@ -847,31 +955,27 @@ ixgbe_txint(void *arg) **********************************************************************/ static void -ixgbe_rxint(void *arg) +ixgbe_msix_rx(void *arg) { struct rx_ring *rxr = arg; struct adapter *adapter = rxr->adapter; struct ifnet *ifp = adapter->ifp; - //uint32_t reg_eicr, loop = MAX_INTR; uint32_t loop = MAX_INTR; - IXGBE_LOCK(adapter); - while ((loop-- > 0) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) ixgbe_rxeof(rxr, adapter->rx_process_limit); ixgbe_enable_intr(adapter); - IXGBE_UNLOCK(adapter); } static void -ixgbe_linkint(void *arg) +ixgbe_msix_link(void *arg) { struct adapter *adapter = arg; uint32_t reg_eicr; - IXGBE_LOCK(adapter); + mtx_lock(&adapter->core_mtx); reg_eicr = IXGBE_READ_REG(&adapter->hw, IXGBE_EICR); @@ -884,8 +988,9 @@ ixgbe_linkint(void *arg) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); ixgbe_enable_intr(adapter); - IXGBE_UNLOCK(adapter); + mtx_unlock(&adapter->core_mtx); } +#endif /* __FreeBSD_version >= 700000 */ /********************************************************************* * @@ -966,6 +1071,7 @@ ixgbe_encap(struct adapter *adapter, struct mbuf **m_headp) /* Basic descriptor defines */ cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA; cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT; + if (m_head->m_flags & M_VLANTAG) cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE; @@ -1086,6 +1192,10 @@ ixgbe_encap(struct adapter *adapter, struct mbuf **m_headp) if (j == (nsegs -1)) /* Last descriptor gets EOP and RS */ txd->read.cmd_type_len |= htole32(IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS); +#ifndef NO_82598_A0_SUPPORT + if (adapter->hw.revision_id == 0) + desc_flip(txd); +#endif } txr->tx_avail -= nsegs; @@ -1211,7 +1321,7 @@ ixgbe_local_timer(void *arg) struct adapter *adapter = arg; struct ifnet *ifp = adapter->ifp; - IXGBE_LOCK_ASSERT(adapter); + mtx_assert(&adapter->core_mtx, MA_OWNED); ixgbe_update_link_status(adapter); ixgbe_update_stats_counters(adapter); @@ -1273,7 +1383,7 @@ ixgbe_stop(void *arg) struct adapter *adapter = arg; ifp = adapter->ifp; - IXGBE_LOCK_ASSERT(adapter); + mtx_assert(&adapter->core_mtx, MA_OWNED); INIT_DEBUGOUT("ixgbe_stop: begin\n"); ixgbe_disable_intr(adapter); @@ -1286,7 +1396,8 @@ ixgbe_stop(void *arg) ixgbe_stop_adapter(&adapter->hw); callout_stop(&adapter->timer); - ixgbe_reset_hw(&adapter->hw); + /* reprogram the RAR[0] in case user changed it. */ + ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); return; } @@ -1314,6 +1425,7 @@ ixgbe_identify_hardware(struct adapter *adapter) return; } +#if __FreeBSD_version >= 700000 /********************************************************************* * * Setup MSIX: this is a prereq for doing Multiqueue/RSS. @@ -1341,7 +1453,7 @@ ixgbe_setup_msix(struct adapter *adapter) /* Set the handler function */ error = bus_setup_intr(dev, adapter->res[vector], INTR_TYPE_NET | INTR_MPSAFE, NULL, - ixgbe_txint, txr, &adapter->tag[vector]); + ixgbe_msix_tx, txr, &adapter->tag[vector]); if (error) { adapter->res[vector] = NULL; device_printf(dev, "Failed to register TX handler"); @@ -1363,7 +1475,7 @@ ixgbe_setup_msix(struct adapter *adapter) } /* Set the handler function */ error = bus_setup_intr(dev, adapter->res[vector], - INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_rxint, + INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_rx, rxr, &adapter->tag[vector]); if (error) { adapter->res[vector] = NULL; @@ -1383,7 +1495,7 @@ ixgbe_setup_msix(struct adapter *adapter) } /* Set the link handler function */ error = bus_setup_intr(dev, adapter->res[vector], - INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_linkint, + INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_link, adapter, &adapter->tag[vector]); if (error) { adapter->res[vector] = NULL; @@ -1394,6 +1506,7 @@ ixgbe_setup_msix(struct adapter *adapter) return (0); } +#endif static int ixgbe_allocate_pci_resources(struct adapter *adapter) @@ -1421,10 +1534,24 @@ ixgbe_allocate_pci_resources(struct adapter *adapter) * if that fails fall back to Legacy. */ if (ixgbe_allocate_msix_resources(adapter)) { + int val; + adapter->num_tx_queues = 1; adapter->num_rx_queues = 1; - adapter->msix = 0; - rid = 0; + val = 0; + +#if __FreeBSD_version >= 700000 + /* Attempt to use MSI */ + val = pci_msi_count(dev); + if ((val) && pci_alloc_msi(dev, &val) == 0) { + adapter->rid[0] = 1; + device_printf(dev, "MSI Interrupts enabled\n"); + } else +#endif + { + adapter->rid[0] = 0; + device_printf(dev, "Legacy Interrupts enabled\n"); + } adapter->res[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &adapter->rid[0], RF_SHAREABLE | RF_ACTIVE); if (adapter->res[0] == NULL) { @@ -1432,13 +1559,25 @@ ixgbe_allocate_pci_resources(struct adapter *adapter) "resource: interrupt\n"); return (ENXIO); } - /* Set the handler function */ + /* Set the handler contexts */ + TASK_INIT(&adapter->rxtx_task, 0, ixgbe_rxtx, adapter); + TASK_INIT(&adapter->link_task, 0, ixgbe_link, adapter); + adapter->tq = taskqueue_create_fast("ix_taskq", M_NOWAIT, + taskqueue_thread_enqueue, &adapter->tq); + taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq", + device_get_nameunit(adapter->dev)); +#if __FreeBSD_version < 700000 error = bus_setup_intr(dev, adapter->res[0], - INTR_TYPE_NET | INTR_MPSAFE, NULL, - ixgbe_intr, adapter, &adapter->tag[0]); + INTR_TYPE_NET | INTR_FAST, ixgbe_fast_irq, +#else + error = bus_setup_intr(dev, adapter->res[0], + INTR_TYPE_NET, ixgbe_fast_irq, NULL, +#endif + adapter, &adapter->tag[0]); if (error) { adapter->res[0] = NULL; - device_printf(dev, "Failed to register Legacy handler"); + device_printf(dev, "Failed to register" + " Fast Legacy handler"); return (error); } } @@ -1447,6 +1586,7 @@ ixgbe_allocate_pci_resources(struct adapter *adapter) return (0); } +#if __FreeBSD_version >= 700000 /* * Attempt to configure MSI/X, the prefered * interrupt option. @@ -1458,9 +1598,6 @@ ixgbe_allocate_msix_resources(struct adapter *adapter) device_t dev = adapter->dev; int vector = 1; - /* An artificial means to force it off */ - if (ixgbe_disable_msix) - return (-1); /* First map the MSIX table */ rid = PCIR_BAR(3); @@ -1475,20 +1612,15 @@ ixgbe_allocate_msix_resources(struct adapter *adapter) val = pci_msix_count(dev); /* check configured values */ - want = IXGBE_TX_QUEUES + IXGBE_RX_QUEUES + IXGBE_OTHER; + want = ixgbe_tx_queues + ixgbe_rx_queues + ixgbe_other_queues; /* * We arent going to do anything fancy for now, * we either can meet desired config or we fail. */ if (val >= want) val = want; - else { - device_printf(dev, "FAIL MSI/X setup:\n" - "\tqueues wanted = %d\n" - "\tqueues available = %d\n" - "\tPlease reconfigure settings\n", want, val); + else return (ENXIO); - } /* Initialize the resource arrays */ for (int i = 0; i < IXGBE_MSGS; i++, vector++) { @@ -1497,8 +1629,8 @@ ixgbe_allocate_msix_resources(struct adapter *adapter) adapter->res[i] = NULL; } - adapter->num_tx_queues = IXGBE_TX_QUEUES; - adapter->num_rx_queues = IXGBE_RX_QUEUES; + adapter->num_tx_queues = ixgbe_tx_queues; + adapter->num_rx_queues = ixgbe_rx_queues; /* Now allocate the vectors */ if ((error = pci_alloc_msix(dev, &val)) == 0) { @@ -1512,6 +1644,13 @@ ixgbe_allocate_msix_resources(struct adapter *adapter) } return (0); } +#else /* FreeBSD 6.2 */ +static int +ixgbe_allocate_msix_resources(struct adapter *adapter) +{ + return (1); /* Force Legacy behavior for 6.2 */ +} +#endif static void ixgbe_free_pci_resources(struct adapter * adapter) @@ -1545,9 +1684,9 @@ ixgbe_free_pci_resources(struct adapter * adapter) } } - if (adapter->msix) - pci_release_msi(dev); - +#if __FreeBSD_version >= 700000 + pci_release_msi(dev); +#endif if (adapter->res_memory != NULL) bus_release_resource(dev, SYS_RES_MEMORY, IXGBE_MMBA, adapter->res_memory); @@ -1581,7 +1720,11 @@ ixgbe_hardware_init(struct adapter *adapter) } /* Get Hardware Flow Control setting */ - adapter->hw.fc.original_type = ixgbe_flow_control; + adapter->hw.fc.original_type = ixgbe_fc_full; + adapter->hw.fc.pause_time = IXGBE_FC_PAUSE; + adapter->hw.fc.low_water = IXGBE_FC_LO; + adapter->hw.fc.high_water = IXGBE_FC_HI; + adapter->hw.fc.send_xon = TRUE; if (ixgbe_init_hw(&adapter->hw)) { device_printf(dev,"Hardware Initialization Failed"); @@ -1619,9 +1762,6 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) ether_ifattach(ifp, adapter->hw.mac.addr); - /* Override ether_ifattach */ - ifp->if_mtu = PERFORMANCE_MTU; /* set to 9K by default */ - adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; @@ -1630,7 +1770,7 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); - if (adapter->msix) /* Don't use CSUM with RSS */ + if (adapter->msix) /* RSS and HWCSUM not compatible */ ifp->if_capabilities |= IFCAP_TSO4; else ifp->if_capabilities |= (IFCAP_HWCSUM | IFCAP_TSO4); @@ -1721,6 +1861,8 @@ fail_0: static void ixgbe_dma_free(struct adapter *adapter, struct ixgbe_dma_alloc *dma) { + bus_dmamap_sync(dma->dma_tag, dma->dma_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(dma->dma_tag, dma->dma_map); bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); bus_dma_tag_destroy(dma->dma_tag); @@ -1739,7 +1881,7 @@ ixgbe_allocate_queues(struct adapter *adapter) device_t dev = adapter->dev; struct tx_ring *txr; struct rx_ring *rxr; - int rsize, error = IXGBE_SUCCESS; + int rsize, tsize, error = IXGBE_SUCCESS; int txconf = 0, rxconf = 0; /* First allocate the TX ring struct memory */ @@ -1762,8 +1904,7 @@ ixgbe_allocate_queues(struct adapter *adapter) } rxr = adapter->rx_rings; - /* Only do this once, RX and TX desc are the same size */ - rsize = roundup2(adapter->num_tx_desc * + tsize = roundup2(adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc), 4096); /* * Now set up the TX queues, txconf is needed to handle the @@ -1771,12 +1912,20 @@ ixgbe_allocate_queues(struct adapter *adapter) * undo memory gracefully */ for (int i = 0; i < adapter->num_tx_queues; i++, txconf++) { + char name_string[16]; /* Set up some basics */ txr = &adapter->tx_rings[i]; txr->adapter = adapter; txr->me = i; - - if (ixgbe_dma_malloc(adapter, rsize, + /* + * Initialize the TX side lock + * -this has to change for multi tx + */ + snprintf(name_string, sizeof(name_string), "%s:tx", + device_get_nameunit(dev)); + mtx_init(&adapter->tx_mtx, name_string, NULL, MTX_DEF); + + if (ixgbe_dma_malloc(adapter, tsize, &txr->txdma, BUS_DMA_NOWAIT)) { device_printf(dev, "Unable to allocate TX Descriptor memory\n"); @@ -1784,7 +1933,7 @@ ixgbe_allocate_queues(struct adapter *adapter) goto err_tx_desc; } txr->tx_base = (union ixgbe_adv_tx_desc *)txr->txdma.dma_vaddr; - bzero((void *)txr->tx_base, rsize); + bzero((void *)txr->tx_base, tsize); /* Now allocate transmit buffers for the ring */ if (ixgbe_allocate_transmit_buffers(txr)) { @@ -1799,6 +1948,8 @@ ixgbe_allocate_queues(struct adapter *adapter) /* * Next the RX queues... */ + rsize = roundup2(adapter->num_rx_desc * + sizeof(union ixgbe_adv_rx_desc), 4096); for (int i = 0; i < adapter->num_rx_queues; i++, rxconf++) { rxr = &adapter->rx_rings[i]; /* Set up some basics */ @@ -1997,11 +2148,13 @@ static void ixgbe_free_transmit_structures(struct adapter *adapter) { struct tx_ring *txr = adapter->tx_rings; + mtx_lock(&adapter->tx_mtx); for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { ixgbe_free_transmit_buffers(txr); ixgbe_dma_free(adapter, &txr->txdma); } - + mtx_unlock(&adapter->tx_mtx); + mtx_destroy(&adapter->tx_mtx); free(adapter->tx_rings, M_DEVBUF); } @@ -2076,7 +2229,12 @@ ixgbe_tx_csum_setup(struct tx_ring *txr, struct mbuf *mp) u16 etype; u8 ipproto; int ctxd = txr->next_avail_tx_desc; +#if __FreeBSD_version < 700000 + struct m_tag *mtag; +#else u16 vtag = 0; +#endif + tx_buffer = &txr->tx_buffers[ctxd]; TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd]; @@ -2085,11 +2243,17 @@ ixgbe_tx_csum_setup(struct tx_ring *txr, struct mbuf *mp) ** In advanced descriptors the vlan tag must ** be placed into the descriptor itself. */ +#if __FreeBSD_version < 700000 + mtag = VLAN_OUTPUT_TAG(ifp, mp); + if (mtag != NULL) + vlan_macip_lens |= + htole16(VLAN_TAG_VALUE(mtag)) << IXGBE_ADVTXD_VLAN_SHIFT; +#else if (mp->m_flags & M_VLANTAG) { vtag = htole16(mp->m_pkthdr.ether_vtag); vlan_macip_lens |= (vtag << IXGBE_ADVTXD_VLAN_SHIFT); } - +#endif /* * Determine where frame payload starts. * Jump over vlan headers if already present, @@ -2148,6 +2312,11 @@ ixgbe_tx_csum_setup(struct tx_ring *txr, struct mbuf *mp) TXD->seqnum_seed = htole32(0); TXD->mss_l4len_idx = htole32(0); +#ifndef NO_82598_A0_SUPPORT + if (adapter->hw.revision_id == 0) + desc_flip(TXD); +#endif + tx_buffer->m_head = NULL; tx_buffer->next_eop = -1; @@ -2160,6 +2329,7 @@ ixgbe_tx_csum_setup(struct tx_ring *txr, struct mbuf *mp) return TRUE; } +#if __FreeBSD_version >= 700000 /********************************************************************** * * Setup work for hardware segmentation offload (TSO) on @@ -2242,6 +2412,11 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen) tx_buffer->m_head = NULL; tx_buffer->next_eop = -1; +#ifndef NO_82598_A0_SUPPORT + if (adapter->hw.revision_id == 0) + desc_flip(TXD); +#endif + if (++ctxd == adapter->num_tx_desc) ctxd = 0; @@ -2250,6 +2425,14 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen) return TRUE; } +#else /* For 6.2 RELEASE */ +/* This makes it easy to keep the code common */ +static boolean_t +ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen) +{ + return (FALSE); +} +#endif /********************************************************************** * @@ -2267,7 +2450,7 @@ ixgbe_txeof(struct tx_ring *txr) struct ixgbe_tx_buf *tx_buffer; struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc; - IXGBE_LOCK_ASSERT(adapter); + mtx_assert(&adapter->tx_mtx, MA_OWNED); if (txr->tx_avail == adapter->num_tx_desc) return FALSE; @@ -2419,9 +2602,22 @@ ixgbe_get_buf(struct rx_ring *rxr, int i) rxr->spare_map[old] = map; bus_dmamap_sync(rxr->rxtag[s], rxbuf->map[s], BUS_DMASYNC_PREREAD); rxbuf->m_head = mp; + rxbuf->bigbuf = s; rxr->rx_base[i].read.pkt_addr = htole64(segs[0].ds_addr); +#ifndef NO_82598_A0_SUPPORT + /* A0 needs to One's Compliment descriptors */ + if (adapter->hw.revision_id == 0) { + struct dhack {u32 a1; u32 a2; u32 b1; u32 b2;}; + struct dhack *d; + + d = (struct dhack *)&rxr->rx_base[i]; + d->a1 = ~(d->a1); + d->a2 = ~(d->a2); + } +#endif + return (0); } @@ -2578,7 +2774,7 @@ fail: * 'j' is the failing index, decrement it to get the * last success. */ - for (--j; j > 0; j--) { + for (--j; j < 0; j--) { rxbuf = &rxr->rx_buffers[j]; if (rxbuf->m_head != NULL) { bus_dmamap_sync(rxr->rxtag[s], rxbuf->map[s], @@ -2904,9 +3100,15 @@ ixgbe_rxeof(struct rx_ring *rxr, int count) staterr, rxr->fmp); if (staterr & IXGBE_RXD_STAT_VP) { +#if __FreeBSD_version < 700000 + VLAN_INPUT_TAG_NEW(ifp, rxr->fmp, + (le16toh(cur->wb.upper.vlan) & + IXGBE_RX_DESC_SPECIAL_VLAN_MASK)); +#else rxr->fmp->m_pkthdr.ether_vtag = le16toh(cur->wb.upper.vlan); rxr->fmp->m_flags |= M_VLANTAG; +#endif } m = rxr->fmp; rxr->fmp = NULL; @@ -2944,9 +3146,7 @@ discard: /* Now send up to the stack */ if (m != NULL) { rxr->next_to_check = i; - IXGBE_UNLOCK(adapter); (*ifp->if_input)(ifp, m); - IXGBE_LOCK(adapter); i = rxr->next_to_check; } /* Get next descriptor */ @@ -3013,7 +3213,7 @@ ixgbe_enable_vlans(struct adapter *adapter) ixgbe_disable_intr(adapter); ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); - ctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE; + ctrl |= IXGBE_VLNCTRL_VME; ctrl &= ~IXGBE_VLNCTRL_CFIEN; IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); ixgbe_enable_intr(adapter); @@ -3027,7 +3227,7 @@ ixgbe_enable_intr(struct adapter *adapter) { u32 mask; - /* Set up what to auto clear */ + /* With RSS set up what to auto clear */ if (adapter->msix) { mask = IXGBE_EIMS_ENABLE_MASK; mask &= ~IXGBE_EIMS_OTHER; @@ -3165,7 +3365,7 @@ ixgbe_update_stats_counters(struct adapter *adapter) /* Rx Errors */ ifp->if_ierrors = - adapter->dropped_pkts + + adapter->stats.mpc[0] + adapter->stats.crcerrs + adapter->stats.rlec; @@ -3185,40 +3385,41 @@ ixgbe_print_hw_stats(struct adapter * adapter) device_t dev = adapter->dev; - device_printf(dev,"Tx Descriptors not Avail1 = %ld\n", + device_printf(dev,"Tx Descriptors not Avail1 = %lu\n", adapter->no_tx_desc_avail1); - device_printf(dev,"Tx Descriptors not Avail2 = %ld\n", + device_printf(dev,"Tx Descriptors not Avail2 = %lu\n", adapter->no_tx_desc_avail2); - device_printf(dev,"Std Mbuf Failed = %ld\n", + device_printf(dev,"Std Mbuf Failed = %lu\n", adapter->mbuf_alloc_failed); - device_printf(dev,"Std Cluster Failed = %ld\n", + device_printf(dev,"Std Cluster Failed = %lu\n", adapter->mbuf_cluster_failed); - device_printf(dev,"Missed Packets = %lld\n", - (long long)adapter->stats.mprc); - device_printf(dev,"Receive length errors = %lld\n", - (long long)adapter->stats.rlec); - device_printf(dev,"Crc errors = %lld\n", + device_printf(dev,"Missed Packets = %llu\n", + (long long)adapter->stats.mpc[0]); + device_printf(dev,"Receive length errors = %llu\n", + ((long long)adapter->stats.roc + + (long long)adapter->stats.ruc)); + device_printf(dev,"Crc errors = %llu\n", (long long)adapter->stats.crcerrs); - device_printf(dev,"Driver dropped packets = %ld\n", + device_printf(dev,"Driver dropped packets = %lu\n", adapter->dropped_pkts); - device_printf(dev,"XON Rcvd = %lld\n", + device_printf(dev,"XON Rcvd = %llu\n", (long long)adapter->stats.lxonrxc); - device_printf(dev,"XON Xmtd = %lld\n", + device_printf(dev,"XON Xmtd = %llu\n", (long long)adapter->stats.lxontxc); - device_printf(dev,"XOFF Rcvd = %lld\n", + device_printf(dev,"XOFF Rcvd = %llu\n", (long long)adapter->stats.lxoffrxc); - device_printf(dev,"XOFF Xmtd = %lld\n", + device_printf(dev,"XOFF Xmtd = %llu\n", (long long)adapter->stats.lxofftxc); - device_printf(dev,"Total Packets Rcvd = %lld\n", + device_printf(dev,"Total Packets Rcvd = %llu\n", (long long)adapter->stats.tpr); - device_printf(dev,"Good Packets Rcvd = %lld\n", + device_printf(dev,"Good Packets Rcvd = %llu\n", (long long)adapter->stats.gprc); - device_printf(dev,"Good Packets Xmtd = %lld\n", + device_printf(dev,"Good Packets Xmtd = %llu\n", (long long)adapter->stats.gptc); - device_printf(dev,"TSO Transmissions = %ld\n", + device_printf(dev,"TSO Transmissions = %lu\n", adapter->tso_tx); return; @@ -3259,23 +3460,17 @@ ixgbe_print_debug_info(struct adapter *adapter) device_printf(dev,"Queue(0) tdh = %d, hw tdt = %d\n", IXGBE_READ_REG(hw, IXGBE_TDH(0)), IXGBE_READ_REG(hw, IXGBE_TDT(0))); - device_printf(dev,"Total Packets Received = %d \n", - IXGBE_READ_REG(hw, IXGBE_TPR)); - device_printf(dev,"Error Byte Count = %d \n", + device_printf(dev,"Error Byte Count = %u \n", IXGBE_READ_REG(hw, IXGBE_ERRBC)); - device_printf(dev,"Rx Length Errors = %d \n", - IXGBE_READ_REG(hw, IXGBE_RLEC)); - device_printf(dev,"Rx CRC Errors = %d \n", - IXGBE_READ_REG(hw, IXGBE_CRCERRS)); for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) { - device_printf(dev,"Queue %d Packets Received: %lx\n", + device_printf(dev,"Queue %d Packets Received: %lu\n", rxr->me, (long)rxr->packet_count); } rxr = adapter->rx_rings; // Reset for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) { - device_printf(dev,"Queue %d Bytes Received: %lx\n", + device_printf(dev,"Queue %d Bytes Received: %lu\n", rxr->me, (long)rxr->byte_count); } @@ -3284,12 +3479,6 @@ ixgbe_print_debug_info(struct adapter *adapter) i, IXGBE_READ_REG(hw, IXGBE_RDH(i)), IXGBE_READ_REG(hw, IXGBE_RDT(i))); } - device_printf(dev,"Std mbuf failed = %ld\n", - adapter->mbuf_alloc_failed); - device_printf(dev,"Std mbuf cluster failed = %ld\n", - adapter->mbuf_cluster_failed); - device_printf(dev,"Driver dropped packets = %ld\n", - adapter->dropped_pkts); return; } @@ -3333,6 +3522,41 @@ ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS) return error; } +/* +** Set flow control using sysctl: +** Flow control values: +** 0 - off +** 1 - rx pause +** 2 - tx pause +** 3 - full +*/ +static int +ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS) +{ + int error; + struct adapter *adapter; + + error = sysctl_handle_int(oidp, &ixgbe_flow_control, 0, req); + + if (error) + return (error); + + adapter = (struct adapter *) arg1; + switch (ixgbe_flow_control) { + case ixgbe_fc_rx_pause: + case ixgbe_fc_tx_pause: + case ixgbe_fc_full: + adapter->hw.fc.original_type = ixgbe_flow_control; + break; + case ixgbe_fc_none: + default: + adapter->hw.fc.original_type = ixgbe_fc_none; + } + + ixgbe_setup_fc(&adapter->hw, 0); + return error; +} + static void ixgbe_add_rx_process_limit(struct adapter *adapter, const char *name, const char *description, int *limit, int value) @@ -3342,3 +3566,26 @@ ixgbe_add_rx_process_limit(struct adapter *adapter, const char *name, SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); } + +#ifndef NO_82598_A0_SUPPORT +/* + * A0 Workaround: invert descriptor for hardware + */ +void +desc_flip(void *desc) +{ + struct dhack {u32 a1; u32 a2; u32 b1; u32 b2;}; + struct dhack *d; + + d = (struct dhack *)desc; + d->a1 = ~(d->a1); + d->a2 = ~(d->a2); + d->b1 = ~(d->b1); + d->b2 = ~(d->b2); + d->b2 &= 0xFFFFFFF0; + d->b1 &= ~IXGBE_ADVTXD_DCMD_RS; +} +#endif + + + diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index c75c167..c496244 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -86,39 +86,35 @@ POSSIBILITY OF SUCH DAMAGE. /* Tunables */ /* -** The number of queues: right now significant performance -** seems to be gained by using muliple RX queues. The -** infrastructure for multiple TX is there but its not -** completely working, dont set greater than 1 for now. -** OTHER is the vector used for link changes, it also -** should only be set to 1. -*/ -#define IXGBE_TX_QUEUES 1 -#define IXGBE_RX_QUEUES 8 -#define IXGBE_OTHER 1 - -/* - * TxDescriptors Valid Range: 64-4096 Default Value: 2048 This value is the + * TxDescriptors Valid Range: 64-4096 Default Value: 256 This value is the * number of transmit descriptors allocated by the driver. Increasing this * value allows the driver to queue more transmits. Each descriptor is 16 - * bytes. + * bytes. Performance tests have show the 2K value to be optimal for top + * performance. */ -#define DEFAULT_TXD 2048 +#define DEFAULT_TXD 256 +#define PERFORM_TXD 2048 #define MAX_TXD 4096 #define MIN_TXD 64 /* - * RxDescriptors Valid Range: 64-4096 Default Value: 2048 This value is the - * number of receive descriptors allocated by the driver. Increasing this + * RxDescriptors Valid Range: 64-4096 Default Value: 256 This value is the + * number of receive descriptors allocated for each RX queue. Increasing this * value allows the driver to buffer more incoming packets. Each descriptor - * is 16 bytes. A receive buffer is also allocated for each descriptor. The - * maximum MTU size is 16110. + * is 16 bytes. A receive buffer is also allocated for each descriptor. * + * Note: with 8 rings and a dual port card, it is possible to bump up + * against the system mbuf pool limit, you can tune nmbclusters + * to adjust for this. */ -#define DEFAULT_RXD 2048 +#define DEFAULT_RXD 256 +#define PERFORM_RXD 2048 #define MAX_RXD 4096 #define MIN_RXD 64 +/* Alignment for rings */ +#define DBA_ALIGN 128 + /* * This parameter controls the maximum no of times the driver will loop in * the isr. Minimum Value = 1 @@ -138,15 +134,11 @@ POSSIBILITY OF SUCH DAMAGE. #define IXGBE_TX_OP_THRESHOLD (adapter->num_tx_desc / 32) #define IXGBE_MAX_FRAME_SIZE 0x3F00 -#define PERFORMANCE_MTU 9000 /* Best thruput results */ -/* -** This controls the size mbuf pool used, it -** may ultimately be automatic, but for now its -** a compile time option. -** - use MCLBYTES for legacy size -*/ -#define IXGBE_RXBUF MJUMPAGESIZE +/* Flow control constants */ +#define IXGBE_FC_PAUSE 0x680 +#define IXGBE_FC_HI 0x20000 +#define IXGBE_FC_LO 0x10000 /* Defines for printing debug information */ #define DEBUG_INIT 0 @@ -174,13 +166,23 @@ POSSIBILITY OF SUCH DAMAGE. /* The number of MSIX messages the 82598 supports */ #define IXGBE_MSGS 18 +/* For 6.X code compatibility */ +#if __FreeBSD_version < 700000 +#define ETHER_BPF_MTAP BPF_MTAP +#define CSUM_TSO 0 +#define IFCAP_TSO4 0 +#define FILTER_STRAY +#define FILTER_HANDLED +#endif + /* * Interrupt Moderation parameters * for now we hardcode, later * it would be nice to do dynamic */ -#define DEFAULT_ITR 8000 -#define LINK_ITR 1950 +#define MAX_IRQ_SEC 8000 +#define DEFAULT_ITR 1000000000/(MAX_IRQ_SEC * 256) +#define LINK_ITR 1000000000/(1950 * 256) /* * ****************************************************************************** @@ -232,7 +234,6 @@ struct ixgbe_dma_alloc { struct tx_ring { struct adapter *adapter; u32 me; - struct mtx mtx; union ixgbe_adv_tx_desc *tx_base; struct ixgbe_dma_alloc txdma; uint32_t next_avail_tx_desc; @@ -250,7 +251,6 @@ struct tx_ring { struct rx_ring { struct adapter *adapter; u32 me; - struct mtx mtx; u32 payload; union ixgbe_adv_rx_desc *rx_base; struct ixgbe_dma_alloc rxdma; @@ -292,7 +292,12 @@ struct adapter { int watchdog_timer; int msix; int if_flags; - struct mtx mtx; + struct mtx core_mtx; + struct mtx tx_mtx; + /* Legacy Fast Intr handling */ + struct task link_task; + struct task rxtx_task; + struct taskqueue *tq; /* Info about the board itself */ uint32_t part_num; @@ -338,11 +343,4 @@ struct adapter { struct ixgbe_hw_stats stats; }; -#define IXGBE_LOCK_INIT(_sc, _name) \ - mtx_init(&(_sc)->mtx, _name, MTX_NETWORK_LOCK, MTX_DEF) -#define IXGBE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx) -#define IXGBE_LOCK(_sc) mtx_lock(&(_sc)->mtx) -#define IXGBE_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) -#define IXGBE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED) - #endif /* _IXGBE_H_ */ diff --git a/sys/dev/ixgbe/ixgbe_82598.c b/sys/dev/ixgbe/ixgbe_82598.c index f7e5b21..35d7e5e 100644 --- a/sys/dev/ixgbe/ixgbe_82598.c +++ b/sys/dev/ixgbe/ixgbe_82598.c @@ -32,6 +32,7 @@ *******************************************************************************/ /* $FreeBSD$ */ + #include "ixgbe_type.h" #include "ixgbe_api.h" #include "ixgbe_common.h" @@ -73,6 +74,10 @@ s32 ixgbe_reset_hw_rev_0_82598(struct ixgbe_hw *hw); #endif s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); u32 ixgbe_get_num_rx_addrs_82598(struct ixgbe_hw *hw); +s32 ixgbe_configure_fiber_serdes_fc_82598(struct ixgbe_hw *hw); +s32 ixgbe_setup_fiber_serdes_link_82598(struct ixgbe_hw *hw); +s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val); +s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val); /** @@ -84,9 +89,6 @@ u32 ixgbe_get_num_rx_addrs_82598(struct ixgbe_hw *hw); **/ s32 ixgbe_init_shared_code_82598(struct ixgbe_hw *hw) { - /* Set MAC type */ - hw->mac.type = ixgbe_mac_82598EB; - /* Assign function pointers */ ixgbe_assign_func_pointers_82598(hw); @@ -109,6 +111,10 @@ s32 ixgbe_assign_func_pointers_82598(struct ixgbe_hw *hw) &ixgbe_get_num_of_tx_queues_82598; hw->func.ixgbe_func_get_num_of_rx_queues = &ixgbe_get_num_of_rx_queues_82598; + hw->func.ixgbe_func_read_analog_reg8 = + &ixgbe_read_analog_reg8_82598; + hw->func.ixgbe_func_write_analog_reg8 = + &ixgbe_write_analog_reg8_82598; #ifndef NO_82598_A0_SUPPORT if (hw->revision_id == 0) { hw->func.ixgbe_func_reset_hw = @@ -250,18 +256,11 @@ enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) /* Media type for I82598 is based on device ID */ switch (hw->device_id) { - case IXGBE_DEV_ID_82598: - /* Default device ID is mezzanine card KX/KX4 */ - media_type = ixgbe_media_type_backplane; - break; - case IXGBE_DEV_ID_82598_FPGA: case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: + case IXGBE_DEV_ID_82598EB_CX4: media_type = ixgbe_media_type_fiber; break; - case IXGBE_DEV_ID_82598AT_DUAL_PORT: - media_type = ixgbe_media_type_copper; - break; default: media_type = ixgbe_media_type_unknown; break; @@ -278,9 +277,6 @@ enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) **/ u32 ixgbe_get_num_of_tx_queues_82598(struct ixgbe_hw *hw) { - if (hw->device_id == IXGBE_DEV_ID_82598_FPGA) - return 8; - return IXGBE_82598_MAX_TX_QUEUES; } @@ -292,9 +288,6 @@ u32 ixgbe_get_num_of_tx_queues_82598(struct ixgbe_hw *hw) **/ u32 ixgbe_get_num_of_rx_queues_82598(struct ixgbe_hw *hw) { - if (hw->device_id == IXGBE_DEV_ID_82598_FPGA) - return 8; - return IXGBE_82598_MAX_RX_QUEUES; } @@ -307,6 +300,8 @@ u32 ixgbe_get_num_of_rx_queues_82598(struct ixgbe_hw *hw) **/ s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) { + ixgbe_link_speed speed; + bool link_up; u32 autoc_reg; u32 links_reg; u32 i; @@ -346,6 +341,22 @@ s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) } } + /* + * We want to save off the original Flow Control configuration just in + * case we get disconnected and then reconnected into a different hub + * or switch with different Flow Control capabilities. + */ + hw->fc.type = hw->fc.original_type; + /* + * Set up the SerDes link if in 1Gb mode, otherwise just set up + * 10Gb flow control. + */ + ixgbe_check_link(hw, &speed, &link_up); + if (speed == IXGBE_LINK_SPEED_1GB_FULL) + status = ixgbe_setup_fiber_serdes_link_82598(hw); + else + ixgbe_setup_fc_generic(hw, 0); + /* Add delay to filter out noises during initial link setup */ msec_delay(50); @@ -381,6 +392,236 @@ s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, } /** + * ixgbe_configure_fiber_serdes_fc_82598 - Configure fiber flow control + * @hw: pointer to hardware structure + * + * Reads PCS registers and sets flow control settings, based on + * link-partner's abilities. + **/ +s32 ixgbe_configure_fiber_serdes_fc_82598(struct ixgbe_hw *hw) +{ + s32 ret_val = IXGBE_SUCCESS; + u32 delay = 300, pcs_anadv_reg, pcs_lpab_reg, pcs_lstat_reg, i; + + DEBUGFUNC("ixgbe_configure_fiber_serdes_fc_82598"); + + /* Check that autonegotiation has completed */ + for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { + /* + * Delay 300msec before reading PCS1GLSTA. Reading PCS1GLSTA + * before then will sometimes result in AN_COMPLETE not being + * set. + */ + msec_delay(delay); + pcs_lstat_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); + if (pcs_lstat_reg & IXGBE_PCS1GLSTA_AN_COMPLETE) { + if (pcs_lstat_reg & (IXGBE_PCS1GLSTA_LINK_OK)) { + if (!(pcs_lstat_reg & + (IXGBE_PCS1GLSTA_AN_TIMED_OUT))) + hw->mac.autoneg_failed = 0; + else + hw->mac.autoneg_failed = 1; + break; + } else { + hw->mac.autoneg_failed = 1; + break; + } + } + + /* + * Increment the delay time by 50ms to wait before reading + * PCS1GLSTA again. + */ + delay += 50; + } + + if (i == FIBER_LINK_UP_LIMIT) + hw->mac.autoneg_failed = 1; + + if (hw->mac.autoneg_failed) { + /* + * AutoNeg failed to achieve a link, so we will turn + * flow control off. + */ + hw->fc.type = ixgbe_fc_none; + DEBUGOUT("Flow Control = NONE.\n"); + ret_val = ixgbe_setup_fc_generic(hw, 0); + goto out; + } + + /* + * Read the AN advertisement and LP ability registers and resolve + * local flow control settings accordingly + */ + pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); + pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); + if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { + /* + * Now we need to check if the user selected RX ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.original_type == ixgbe_fc_full) { + hw->fc.type = ixgbe_fc_full; + DEBUGOUT("Flow Control = FULL.\n"); + } else { + hw->fc.type = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); + } + } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { + hw->fc.type = ixgbe_fc_tx_pause; + DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); + } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && + !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { + hw->fc.type = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); + } else if ((hw->fc.original_type == ixgbe_fc_none || + hw->fc.original_type == ixgbe_fc_tx_pause) || + hw->fc.strict_ieee) { + hw->fc.type = ixgbe_fc_none; + DEBUGOUT("Flow Control = NONE.\n"); + } else { + hw->fc.type = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); + } + + ret_val = ixgbe_setup_fc_generic(hw, 0); + if (ret_val) { + DEBUGOUT("Error forcing flow control settings\n"); + goto out; + } + +out: + return ret_val; +} + +/** + * ixgbe_setup_fiber_serdes_link_82598 - Configure fiber serdes link + * @hw: pointer to hardware structure + * + * Sets up PCS registers and sets flow control settings, based on + * link-partner's abilities. + **/ +s32 ixgbe_setup_fiber_serdes_link_82598(struct ixgbe_hw *hw) +{ + u32 reg; + s32 ret_val; + + DEBUGFUNC("ixgbe_setup_fiber_serdes_link_82598"); + + /* + * 82598 fiber/serdes devices require that flow control be resolved in + * software. Set up flow control advertisement if autoneg is enabled. + */ + if (hw->mac.autoneg) { + reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); + + /* + * Check for a software override of the flow control settings, + * and setup the device accordingly. If auto-negotiation is + * enabled, then software will have to set the "PAUSE" bits to + * the correct value and re-start auto- negotiation. However, + * if auto-negotiation is disabled, then software will have to + * manually configure flow control. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but + * we do not support receiving pause frames). + * 3: Both Rx and TX flow control (symmetric) are enabled. + */ + + switch (hw->fc.type) { + case ixgbe_fc_none: + /* + * Flow control completely disabled by a software + * over-ride. + */ + reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | + IXGBE_PCS1GANA_ASM_PAUSE); + break; + case ixgbe_fc_rx_pause: + /* + * RX Flow control is enabled and TX Flow control is + * disabled by a software over-ride. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric RX PAUSE. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + reg |= (IXGBE_PCS1GANA_SYM_PAUSE | + IXGBE_PCS1GANA_ASM_PAUSE); + break; + case ixgbe_fc_tx_pause: + /* + * TX Flow control is enabled, and RX Flow control is + * disabled, by a software over-ride. + */ + reg |= (IXGBE_PCS1GANA_ASM_PAUSE); + reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE); + break; + case ixgbe_fc_full: + /* + * Flow control (both RX and TX) is enabled by a + * software over-ride. + */ + reg |= (IXGBE_PCS1GANA_SYM_PAUSE | + IXGBE_PCS1GANA_ASM_PAUSE); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + ret_val = -IXGBE_ERR_CONFIG; + goto out; + break; + } + + IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); + } + + /* + * New SerDes mode allows for forcing speed or autonegotiating speed + * at 1gb. Autoneg should be default set by most drivers. This is the + * mode that will be compatible with older link partners and switches. + * However, both are supported by the hardware and some drivers/tools. + */ + reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); + reg &= ~(IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN); + + if (hw->mac.autoneg) { + /* Set PCS register for autoneg */ + reg |= IXGBE_PCS1GLCTL_AN_ENABLE | /* Enable Autoneg */ + IXGBE_PCS1GLCTL_AN_RESTART; /* Restart autoneg */ + DEBUGOUT1("Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg); + } else { + /* Set PCS register for forced speed */ + reg |= IXGBE_PCS1GLCTL_FLV_LINK_UP | /* Force link up */ + IXGBE_PCS1GLCTL_FORCE_LINK; /* Force Link */ + DEBUGOUT1("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg); + } + IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); + + /* + * Configure flow control. If we aren't auto-negotiating, + * just setup the flow control and do not worry about PCS autoneg. + */ + if (hw->mac.autoneg) + ixgbe_configure_fiber_serdes_fc_82598(hw); + +out: + return IXGBE_SUCCESS; +} + +/** * ixgbe_setup_mac_link_speed_82598 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed @@ -644,10 +885,36 @@ s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) u32 gheccr; u32 i; u32 autoc; + u8 analog_val; /* Call adapter stop to disable tx/rx and clear interrupts */ ixgbe_stop_adapter(hw); + /* + * Power up the Atlas TX lanes if they are currently powered down. + * Atlas TX lanes are powered down for MAC loopback tests, but + * they are not automatically restored on reset. + */ + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); + if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) { + /* Enable TX Atlas so packets can be transmitted again */ + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); + analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN; + ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val); + + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val); + analog_val &= ~ IXGBE_ATLAS_PDN_TX_10G_QL_ALL; + ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val); + + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val); + analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL; + ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val); + + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val); + analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL; + ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val); + } + /* Reset PHY */ ixgbe_reset_phy(hw); @@ -714,6 +981,47 @@ s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) } /** + * ixgbe_read_analog_reg8_82598 - Reads 8 bit 82598 Atlas analog register + * @hw: pointer to hardware structure + * @reg: analog register to read + * @val: read value + * + * Performs write operation to analog register specified. + **/ +s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val) +{ + u32 atlas_ctl; + + IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); + IXGBE_WRITE_FLUSH(hw); + usec_delay(10); + atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); + *val = (u8)atlas_ctl; + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_write_analog_reg8_82598 - Writes 8 bit 82598 Atlas analog register + * @hw: pointer to hardware structure + * @reg: atlas register to write + * @val: value to write + * + * Performs write operation to Atlas analog register specified. + **/ +s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val) +{ + u32 atlas_ctl; + + atlas_ctl = (reg << 8) | val; + IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); + IXGBE_WRITE_FLUSH(hw); + usec_delay(10); + + return IXGBE_SUCCESS; +} + +/** * ixgbe_get_num_rx_addrs_82598 - Get RX address registers * @hw: pointer to hardware structure * diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c index d881c3d..57b5678 100644 --- a/sys/dev/ixgbe/ixgbe_api.c +++ b/sys/dev/ixgbe/ixgbe_api.c @@ -32,6 +32,7 @@ *******************************************************************************/ /* $FreeBSD$ */ + #include "ixgbe_api.h" #include "ixgbe_common.h" @@ -52,7 +53,7 @@ extern s32 ixgbe_init_shared_code_phy(struct ixgbe_hw *hw); **/ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw) { - s32 status = IXGBE_ERR_DEVICE_NOT_SUPPORTED; + s32 status; /* * Assign generic function pointers before entering adapter-specific @@ -60,23 +61,53 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw) */ ixgbe_assign_func_pointers_generic(hw); + /* + * Set the mac type + */ + ixgbe_set_mac_type(hw); + + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + status = ixgbe_init_shared_code_82598(hw); + status = ixgbe_init_shared_code_phy(hw); + break; + default: + status = IXGBE_ERR_DEVICE_NOT_SUPPORTED; + break; + } + + return status; +} + +/** + * ixgbe_set_mac_type - Sets MAC type + * @hw: pointer to the HW structure + * + * This function sets the mac type of the adapter based on the + * vendor ID and device ID stored in the hw structure. + **/ +s32 ixgbe_set_mac_type(struct ixgbe_hw *hw) +{ + s32 ret_val = IXGBE_SUCCESS; + + DEBUGFUNC("ixgbe_set_mac_type"); + if (hw->vendor_id == IXGBE_INTEL_VENDOR_ID) { switch (hw->device_id) { - case IXGBE_DEV_ID_82598: - case IXGBE_DEV_ID_82598_FPGA: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598AF_DUAL_PORT: - case IXGBE_DEV_ID_82598AT_DUAL_PORT: - status = ixgbe_init_shared_code_82598(hw); - status = ixgbe_init_shared_code_phy(hw); + case IXGBE_DEV_ID_82598EB_CX4: + hw->mac.type = ixgbe_mac_82598EB; break; default: - status = IXGBE_ERR_DEVICE_NOT_SUPPORTED; + ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED; break; } + } else { + ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED; } - return status; + return ret_val; } /** @@ -643,3 +674,32 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) IXGBE_NOT_IMPLEMENTED); } + +/** + * ixgbe_read_analog_reg8 - Reads 8 bit analog register + * @hw: pointer to hardware structure + * @reg: analog register to read + * @val: read value + * + * Performs write operation to analog register specified. + **/ +s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val) +{ + return ixgbe_call_func(hw, ixgbe_func_read_analog_reg8, (hw, reg, val), + IXGBE_NOT_IMPLEMENTED); +} + +/** + * ixgbe_write_analog_reg8 - Writes 8 bit analog register + * @hw: pointer to hardware structure + * @reg: analog register to write + * @val: value to write + * + * Performs write operation to Atlas analog register specified. + **/ +s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val) +{ + return ixgbe_call_func(hw, ixgbe_func_write_analog_reg8, (hw, reg, val), + IXGBE_NOT_IMPLEMENTED); +} + diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h index 691957f..5154cf7 100644 --- a/sys/dev/ixgbe/ixgbe_api.h +++ b/sys/dev/ixgbe/ixgbe_api.h @@ -39,6 +39,7 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw); +s32 ixgbe_set_mac_type(struct ixgbe_hw *hw); s32 ixgbe_init_hw(struct ixgbe_hw *hw); s32 ixgbe_reset_hw(struct ixgbe_hw *hw); s32 ixgbe_start_hw(struct ixgbe_hw *hw); @@ -90,5 +91,7 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num); void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr); +s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val); +s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val); #endif /* _IXGBE_API_H_ */ diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index 30a2625..f9cc69c 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -32,6 +32,7 @@ *******************************************************************************/ /* $FreeBSD$ */ + #include "ixgbe_common.h" #include "ixgbe_api.h" @@ -133,9 +134,6 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) /* Clear statistics registers */ ixgbe_clear_hw_cntrs(hw); - /* Set up flow control */ - ixgbe_setup_fc(hw, 0); - /* Set No Snoop Disable */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h index a150908..d995c7c 100644 --- a/sys/dev/ixgbe/ixgbe_osdep.h +++ b/sys/dev/ixgbe/ixgbe_osdep.h @@ -87,7 +87,7 @@ typedef uint16_t u16; typedef uint32_t u32; typedef int32_t s32; typedef uint64_t u64; -typedef booleant bool; +typedef boolean_t bool; #define le16_to_cpu diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c index 5043109..e19d303 100644 --- a/sys/dev/ixgbe/ixgbe_phy.c +++ b/sys/dev/ixgbe/ixgbe_phy.c @@ -32,6 +32,7 @@ *******************************************************************************/ /* $FreeBSD$ */ + #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" @@ -66,24 +67,6 @@ s32 ixgbe_assign_func_pointers_phy(struct ixgbe_hw *hw) hw->func.ixgbe_func_identify_phy = &ixgbe_identify_phy_generic; - if (ixgbe_get_media_type(hw) == ixgbe_media_type_copper) { - /* Call PHY identify routine to get the phy type */ - ixgbe_identify_phy(hw); - - switch (hw->phy.type) { - case ixgbe_phy_tn: - hw->func.ixgbe_func_setup_phy_link = - &ixgbe_setup_tnx_phy_link; - hw->func.ixgbe_func_check_phy_link = - &ixgbe_check_tnx_phy_link; - hw->func.ixgbe_func_setup_phy_link_speed = - &ixgbe_setup_tnx_phy_link_speed; - break; - default: - break; - } - } - return IXGBE_SUCCESS; } @@ -171,14 +154,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) enum ixgbe_phy_type phy_type; switch (phy_id) { - case TN1010_PHY_ID: - phy_type = ixgbe_phy_tn; - break; - case QT2022_PHY_ID: phy_type = ixgbe_phy_qt; break; - default: phy_type = ixgbe_phy_unknown; break; @@ -213,7 +191,6 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, { u32 command; u32 i; - u32 timeout = 10; u32 data; s32 status = IXGBE_SUCCESS; u16 gssr; @@ -240,7 +217,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, * The MDI Command bit will clear when the operation is * complete */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { usec_delay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); @@ -251,7 +228,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { - DEBUGFUNC("PHY address command did not complete.\n"); + DEBUGOUT("PHY address command did not complete.\n"); status = IXGBE_ERR_PHY; } @@ -272,7 +249,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, * completed. The MDI Command bit will clear when the * operation is complete */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { usec_delay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); @@ -282,7 +259,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { - DEBUGFUNC("PHY read command didn't complete\n"); + DEBUGOUT("PHY read command didn't complete\n"); status = IXGBE_ERR_PHY; } else { /* @@ -312,7 +289,6 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, { u32 command; u32 i; - u32 timeout = 10; s32 status = IXGBE_SUCCESS; u16 gssr; @@ -341,7 +317,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, * The MDI Command bit will clear when the operation is * complete */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { usec_delay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); @@ -372,7 +348,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, * completed. The MDI Command bit will clear when the * operation is complete */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { usec_delay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); @@ -437,156 +413,3 @@ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, IXGBE_NOT_IMPLEMENTED); } -/** - * ixgbe_setup_tnx_phy_link - Set and restart autoneg - * @hw: pointer to hardware structure - * - * Restart autonegotiation and PHY and waits for completion. - **/ -s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw) -{ - s32 status = IXGBE_NOT_IMPLEMENTED; - u32 time_out; - u32 max_time_out = 10; - u16 autoneg_speed_selection_register = 0x10; - u16 autoneg_restart_mask = 0x0200; - u16 autoneg_complete_mask = 0x0020; - u16 autoneg_reg = 0; - - /* - * Set advertisement settings in PHY based on autoneg_advertised - * settings. If autoneg_advertised = 0, then advertise default values - * txn devices cannot be "forced" to a autoneg 10G and fail. But can - * for a 1G. - */ - ixgbe_read_phy_reg(hw, - autoneg_speed_selection_register, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - &autoneg_reg); - - if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL) - autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */ - else - autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */ - - ixgbe_write_phy_reg(hw, - autoneg_speed_selection_register, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - autoneg_reg); - - - /* Restart PHY autonegotiation and wait for completion */ - ixgbe_read_phy_reg(hw, - IXGBE_MDIO_AUTO_NEG_CONTROL, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - &autoneg_reg); - - autoneg_reg |= autoneg_restart_mask; - - ixgbe_write_phy_reg(hw, - IXGBE_MDIO_AUTO_NEG_CONTROL, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - autoneg_reg); - - /* Wait for autonegotiation to finish */ - for (time_out = 0; time_out < max_time_out; time_out++) { - usec_delay(10); - /* Restart PHY autonegotiation and wait for completion */ - status = ixgbe_read_phy_reg(hw, - IXGBE_MDIO_AUTO_NEG_STATUS, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - &autoneg_reg); - - autoneg_reg &= autoneg_complete_mask; - if (autoneg_reg == autoneg_complete_mask) { - status = IXGBE_SUCCESS; - break; - } - } - - if (time_out == max_time_out) - status = IXGBE_ERR_LINK_SETUP; - - return status; -} - -/** - * ixgbe_check_tnx_phy_link - Determine link and speed status - * @hw: pointer to hardware structure - * - * Reads the VS1 register to determine if link is up and the current speed for - * the PHY. - **/ -s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, - bool *link_up) -{ - s32 status = IXGBE_SUCCESS; - u32 time_out; - u32 max_time_out = 10; - u16 phy_link = 0; - u16 phy_speed = 0; - u16 phy_data = 0; - - /* Initialize speed and link to default case */ - *link_up = FALSE; - *speed = IXGBE_LINK_SPEED_10GB_FULL; - - /* - * Check current speed and link status of the PHY register. - * This is a vendor specific register and may have to - * be changed for other copper PHYs. - */ - for (time_out = 0; time_out < max_time_out; time_out++) { - usec_delay(10); - if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) { - *link_up = TRUE; - if (phy_speed == - IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS) - *speed = IXGBE_LINK_SPEED_1GB_FULL; - break; - } else { - status = ixgbe_read_phy_reg(hw, - IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - &phy_data); - phy_link = phy_data & - IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; - phy_speed = phy_data & - IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS; - } - } - - return status; -} - -/** - * ixgbe_setup_tnx_phy_link_speed - Sets the auto advertised capabilities - * @hw: pointer to hardware structure - * @speed: new link speed - * @autoneg: TRUE if autonegotiation enabled - **/ -s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, - bool autoneg, - bool autoneg_wait_to_complete) -{ - UNREFERENCED_PARAMETER(autoneg); - UNREFERENCED_PARAMETER(autoneg_wait_to_complete); - - /* - * Clear autoneg_advertised and set new values based on input link - * speed. - */ - hw->phy.autoneg_advertised = 0; - - if (speed & IXGBE_LINK_SPEED_10GB_FULL) { - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; - } - if (speed & IXGBE_LINK_SPEED_1GB_FULL) { - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; - } - - /* Setup link based on the new speed settings */ - ixgbe_setup_tnx_phy_link(hw); - - return IXGBE_SUCCESS; -} diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h index 9f04732..4313de1 100644 --- a/sys/dev/ixgbe/ixgbe_phy.h +++ b/sys/dev/ixgbe/ixgbe_phy.h @@ -57,14 +57,4 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); -/* PHY specific */ -s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw); -s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *link_up); -s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg, - bool autoneg_wait_to_complete); - #endif /* _IXGBE_PHY_H_ */ diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h index 3168c3e..bfbd701 100644 --- a/sys/dev/ixgbe/ixgbe_type.h +++ b/sys/dev/ixgbe/ixgbe_type.h @@ -41,11 +41,9 @@ #define IXGBE_INTEL_VENDOR_ID 0x8086 /* Device IDs */ -#define IXGBE_DEV_ID_82598 0x10B6 -#define IXGBE_DEV_ID_82598_FPGA 0xF0C0 #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 -#define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8 +#define IXGBE_DEV_ID_82598EB_CX4 0x10DD /* General Registers */ #define IXGBE_CTRL 0x00000 @@ -280,23 +278,17 @@ #define IXGBE_DCA_CTRL 0x11074 /* Diagnostic Registers */ -#define IXGBE_RDSTATCTL 0x02C20 -#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */ -#define IXGBE_RDHMPN 0x02F08 -#define IXGBE_RIC_DW0 0x02F10 -#define IXGBE_RIC_DW1 0x02F14 -#define IXGBE_RIC_DW2 0x02F18 -#define IXGBE_RIC_DW3 0x02F1C -#define IXGBE_RDPROBE 0x02F20 -#define IXGBE_TDSTATCTL 0x07C20 -#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */ -#define IXGBE_TDHMPN 0x07F08 -#define IXGBE_TIC_DW0 0x07F10 -#define IXGBE_TIC_DW1 0x07F14 -#define IXGBE_TIC_DW2 0x07F18 -#define IXGBE_TIC_DW3 0x07F1C -#define IXGBE_TDPROBE 0x07F20 -#define IXGBE_TXBUFCTRL 0x0C600 +#define IXGBE_RDSTATCTL 0x02C20 +#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */ +#define IXGBE_RDHMPN 0x02F08 +#define IXGBE_RIC_DW(_i) (0x02F10 + ((_i) * 4)) +#define IXGBE_RDPROBE 0x02F20 +#define IXGBE_TDSTATCTL 0x07C20 +#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */ +#define IXGBE_TDHMPN 0x07F08 +#define IXGBE_TIC_DW(_i) (0x07F10 + ((_i) * 4)) +#define IXGBE_TDPROBE 0x07F20 +#define IXGBE_TXBUFCTRL 0x0C600 #define IXGBE_TXBUFDATA0 0x0C610 #define IXGBE_TXBUFDATA1 0x0C614 #define IXGBE_TXBUFDATA2 0x0C618 @@ -393,6 +385,8 @@ #define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ +#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* TX Desc writeback RO bit */ +#define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */ /* MSCA Bit Masks */ #define IXGBE_MSCA_NP_ADDR_MASK 0x0000FFFF /* MDI Address (new protocol) */ @@ -415,10 +409,23 @@ #define IXGBE_MSCA_MDI_IN_PROG_EN 0x80000000 /* MDI in progress enable */ /* MSRWD bit masks */ -#define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF -#define IXGBE_MSRWD_WRITE_DATA_SHIFT 0 -#define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000 -#define IXGBE_MSRWD_READ_DATA_SHIFT 16 +#define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF +#define IXGBE_MSRWD_WRITE_DATA_SHIFT 0 +#define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000 +#define IXGBE_MSRWD_READ_DATA_SHIFT 16 + +/* Atlas registers */ +#define IXGBE_ATLAS_PDN_LPBK 0x24 +#define IXGBE_ATLAS_PDN_10G 0xB +#define IXGBE_ATLAS_PDN_1G 0xC +#define IXGBE_ATLAS_PDN_AN 0xD + +/* Atlas bit masks */ +#define IXGBE_ATLASCTL_WRITE_CMD 0x00010000 +#define IXGBE_ATLAS_PDN_TX_REG_EN 0x10 +#define IXGBE_ATLAS_PDN_TX_10G_QL_ALL 0xF0 +#define IXGBE_ATLAS_PDN_TX_1G_QL_ALL 0xF0 +#define IXGBE_ATLAS_PDN_TX_AN_QL_ALL 0xF0 /* Device Type definitions for new protocol MDIO commands */ #define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1 @@ -427,6 +434,8 @@ #define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */ +#define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */ + #define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL 0x0 /* VS1 Control Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS 0x1 /* VS1 Status Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS 0x0008 /* 1 = Link Up */ @@ -448,7 +457,6 @@ #define IXGBE_MAX_PHY_ADDR 32 /* PHY IDs*/ -#define TN1010_PHY_ID 0x00A19410 #define QT2022_PHY_ID 0x0043A400 /* General purpose Interrupt Enable */ @@ -689,7 +697,29 @@ #define IXGBE_LINKS_TL_FAULT 0x00001000 #define IXGBE_LINKS_SIGNAL 0x00000F00 -#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ +#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ + +#define FIBER_LINK_UP_LIMIT 50 + +/* PCS1GLSTA Bit Masks */ +#define IXGBE_PCS1GLSTA_LINK_OK 1 +#define IXGBE_PCS1GLSTA_SYNK_OK 0x10 +#define IXGBE_PCS1GLSTA_AN_COMPLETE 0x10000 +#define IXGBE_PCS1GLSTA_AN_PAGE_RX 0x20000 +#define IXGBE_PCS1GLSTA_AN_TIMED_OUT 0x40000 +#define IXGBE_PCS1GLSTA_AN_REMOTE_FAULT 0x80000 +#define IXGBE_PCS1GLSTA_AN_ERROR_RWS 0x100000 + +#define IXGBE_PCS1GANA_SYM_PAUSE 0x80 +#define IXGBE_PCS1GANA_ASM_PAUSE 0x100 + +/* PCS1GLCTL Bit Masks */ +#define IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN 0x00040000 /* PCS 1G autoneg timeout enable (bit 18) */ +#define IXGBE_PCS1GLCTL_FLV_LINK_UP 1 +#define IXGBE_PCS1GLCTL_FORCE_LINK 0x20 +#define IXGBE_PCS1GLCTL_LOW_LINK_LATCH 0x40 +#define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000 +#define IXGBE_PCS1GLCTL_AN_RESTART 0x20000 /* SW Semaphore Register bitmasks */ #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ @@ -741,6 +771,11 @@ #define IXGBE_CSR1_CONFIG_PTR 0x0E #define IXGBE_FW_PTR 0x0F +/* Legacy EEPROM word offsets */ +#define IXGBE_ISCSI_BOOT_CAPS 0x0033 +#define IXGBE_ISCSI_SETUP_PORT_0 0x0030 +#define IXGBE_ISCSI_SETUP_PORT_1 0x0034 + /* EEPROM Commands - SPI */ #define IXGBE_EEPROM_MAX_RETRY_SPI 5000 /* Max wait 5ms for RDY signal */ #define IXGBE_EEPROM_STATUS_RDY_SPI 0x01 @@ -783,6 +818,8 @@ #define IXGBE_PCI_LINK_SPEED 0xF #define IXGBE_PCI_LINK_SPEED_2500 0x1 #define IXGBE_PCI_LINK_SPEED_5000 0x2 +#define IXGBE_PCI_HEADER_TYPE_REGISTER 0x0E +#define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80 /* Number of 100 microseconds we wait for PCI Express master disable */ #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800 @@ -911,14 +948,15 @@ #define IXGBE_RXD_CFI_SHIFT 12 /* SRRCTL bit definitions */ -#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ -#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F -#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00 -#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000 +#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ +#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F +#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00 +#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000 #define IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 +#define IXGBE_SRRCTL_DESCTYPE_MASK 0x0E000000 #define IXGBE_RXDPS_HDRSTAT_HDRSP 0x00008000 #define IXGBE_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF @@ -1107,6 +1145,7 @@ typedef u32 ixgbe_autoneg_advertised; /* Link speed */ typedef u32 ixgbe_link_speed; #define IXGBE_LINK_SPEED_UNKNOWN 0 +#define IXGBE_LINK_SPEED_100_FULL 0x0008 #define IXGBE_LINK_SPEED_1GB_FULL 0x0020 #define IXGBE_LINK_SPEED_10GB_FULL 0x0080 @@ -1125,7 +1164,6 @@ enum ixgbe_mac_type { enum ixgbe_phy_type { ixgbe_phy_unknown = 0, - ixgbe_phy_tn, ixgbe_phy_qt, ixgbe_phy_xaui }; @@ -1287,8 +1325,8 @@ struct ixgbe_functions u32 (*ixgbe_func_get_num_of_rx_queues)(struct ixgbe_hw *); s32 (*ixgbe_func_stop_adapter)(struct ixgbe_hw *); s32 (*ixgbe_func_get_bus_info)(struct ixgbe_hw *); - - + s32 (*ixgbe_func_read_analog_reg8)(struct ixgbe_hw*, u32, u8*); + s32 (*ixgbe_func_write_analog_reg8)(struct ixgbe_hw*, u32, u8); /* PHY */ s32 (*ixgbe_func_identify_phy)(struct ixgbe_hw *); s32 (*ixgbe_func_reset_phy)(struct ixgbe_hw *); @@ -1347,6 +1385,8 @@ struct ixgbe_mac_info { u32 link_attach_type; u32 link_mode_select; bool link_settings_loaded; + bool autoneg; + bool autoneg_failed; }; struct ixgbe_phy_info { diff --git a/sys/modules/ixgbe/Makefile b/sys/modules/ixgbe/Makefile new file mode 100644 index 0000000..ae31c15 --- /dev/null +++ b/sys/modules/ixgbe/Makefile @@ -0,0 +1,15 @@ +#$FreeBSD$ +.PATH: ${.CURDIR}/../../dev/ixgbe +KMOD = ixgbe +SRCS = device_if.h bus_if.h pci_if.h opt_bdg.h +SRCS += ixgbe.c +# Shared source +SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_82598.c +CFLAGS+= -I${.CURDIR}/../../dev/ixgbe + +clean: + rm -f opt_bdg.h device_if.h bus_if.h pci_if.h setdef* *_StripErr + rm -f *.o *.kld *.ko + rm -f @ machine + +.include <bsd.kmod.mk> |