From owner-svn-src-stable@FreeBSD.ORG Sun Nov 28 03:41:32 2010 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DAFD7106564A; Sun, 28 Nov 2010 03:41:32 +0000 (UTC) (envelope-from jfv@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 901A28FC0A; Sun, 28 Nov 2010 03:41:32 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oAS3fWHe044848; Sun, 28 Nov 2010 03:41:32 GMT (envelope-from jfv@svn.freebsd.org) Received: (from jfv@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oAS3fWEJ044844; Sun, 28 Nov 2010 03:41:32 GMT (envelope-from jfv@svn.freebsd.org) Message-Id: <201011280341.oAS3fWEJ044844@svn.freebsd.org> From: Jack F Vogel Date: Sun, 28 Nov 2010 03:41:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r215970 - in stable/8/sys: conf dev/ixgbe modules/ixgbe X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 28 Nov 2010 03:41:33 -0000 Author: jfv Date: Sun Nov 28 03:41:32 2010 New Revision: 215970 URL: http://svn.freebsd.org/changeset/base/215970 Log: MFC: r215911, r215913, r215914 Added: stable/8/sys/dev/ixgbe/ixgbe_mbx.c (contents, props changed) stable/8/sys/dev/ixgbe/ixgbe_mbx.h (contents, props changed) stable/8/sys/dev/ixgbe/ixgbe_vf.c (contents, props changed) stable/8/sys/dev/ixgbe/ixgbe_vf.h (contents, props changed) stable/8/sys/dev/ixgbe/ixv.c (contents, props changed) stable/8/sys/dev/ixgbe/ixv.h (contents, props changed) Modified: stable/8/sys/conf/files stable/8/sys/dev/ixgbe/ixgbe.c stable/8/sys/dev/ixgbe/ixgbe.h stable/8/sys/dev/ixgbe/ixgbe_82598.c stable/8/sys/dev/ixgbe/ixgbe_82599.c stable/8/sys/dev/ixgbe/ixgbe_api.c stable/8/sys/dev/ixgbe/ixgbe_api.h stable/8/sys/dev/ixgbe/ixgbe_common.c stable/8/sys/dev/ixgbe/ixgbe_common.h stable/8/sys/dev/ixgbe/ixgbe_osdep.h stable/8/sys/dev/ixgbe/ixgbe_phy.c stable/8/sys/dev/ixgbe/ixgbe_phy.h stable/8/sys/dev/ixgbe/ixgbe_type.h stable/8/sys/modules/ixgbe/Makefile Modified: stable/8/sys/conf/files ============================================================================== --- stable/8/sys/conf/files Sun Nov 28 01:56:44 2010 (r215969) +++ stable/8/sys/conf/files Sun Nov 28 03:41:32 2010 (r215970) @@ -1210,12 +1210,18 @@ dev/ixgb/ixgb_ee.c optional ixgb dev/ixgb/ixgb_hw.c optional ixgb dev/ixgbe/ixgbe.c optional ixgbe inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" +dev/ixgbe/ixv.c optional ixgbe inet \ + compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_phy.c optional ixgbe inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_api.c optional ixgbe inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_common.c optional ixgbe inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" +dev/ixgbe/ixgbe_mbx.c optional ixgbe inet \ + compile-with "${NORMAL_C} -I$S/dev/ixgbe" +dev/ixgbe/ixgbe_vf.c optional ixgbe inet \ + compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_82598.c optional ixgbe inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_82599.c optional ixgbe inet \ Modified: stable/8/sys/dev/ixgbe/ixgbe.c ============================================================================== --- stable/8/sys/dev/ixgbe/ixgbe.c Sun Nov 28 01:56:44 2010 (r215969) +++ stable/8/sys/dev/ixgbe/ixgbe.c Sun Nov 28 03:41:32 2010 (r215970) @@ -46,7 +46,7 @@ int ixgbe_display_debug_stat /********************************************************************* * Driver version *********************************************************************/ -char ixgbe_driver_version[] = "2.2.1"; +char ixgbe_driver_version[] = "2.3.6"; /********************************************************************* * PCI Device ID Table @@ -78,6 +78,8 @@ static ixgbe_vendor_info_t ixgbe_vendor_ {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0}, {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0}, + {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0}, /* required last entry */ {0, 0, 0, 0, 0} }; @@ -118,9 +120,9 @@ static int ixgbe_allocate_legacy(st static int ixgbe_allocate_queues(struct adapter *); static int ixgbe_setup_msix(struct adapter *); static void ixgbe_free_pci_resources(struct adapter *); -static void ixgbe_local_timer(void *); -static int ixgbe_setup_interface(device_t, struct adapter *); -static void ixgbe_config_link(struct adapter *); +static void ixgbe_local_timer(void *); +static int ixgbe_setup_interface(device_t, struct adapter *); +static void ixgbe_config_link(struct adapter *); static int ixgbe_allocate_transmit_buffers(struct tx_ring *); static int ixgbe_setup_transmit_structures(struct adapter *); @@ -144,16 +146,12 @@ static bool ixgbe_txeof(struct tx_ring * static bool ixgbe_rxeof(struct ix_queue *, int); static void ixgbe_rx_checksum(u32, struct mbuf *, u32); static void ixgbe_set_promisc(struct adapter *); -static void ixgbe_disable_promisc(struct adapter *); static void ixgbe_set_multi(struct adapter *); -static void ixgbe_print_hw_stats(struct adapter *); -static void ixgbe_print_debug_info(struct adapter *); static void ixgbe_update_link_status(struct adapter *); static void ixgbe_refresh_mbufs(struct rx_ring *, int); static int ixgbe_xmit(struct tx_ring *, 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_set_advertise(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 *); @@ -169,6 +167,8 @@ static void ixgbe_setup_vlan_hw_support( static void ixgbe_register_vlan(void *, struct ifnet *, u16); static void ixgbe_unregister_vlan(void *, struct ifnet *, u16); +static void ixgbe_add_hw_stats(struct adapter *adapter); + static __inline void ixgbe_rx_discard(struct rx_ring *, int); static __inline void ixgbe_rx_input(struct rx_ring *, struct ifnet *, struct mbuf *, u32); @@ -211,7 +211,7 @@ static driver_t ixgbe_driver = { "ix", ixgbe_methods, sizeof(struct adapter), }; -static devclass_t ixgbe_devclass; +devclass_t ixgbe_devclass; DRIVER_MODULE(ixgbe, pci, ixgbe_driver, ixgbe_devclass, 0, 0); MODULE_DEPEND(ixgbe, pci, 1, 1, 1); @@ -230,6 +230,9 @@ MODULE_DEPEND(ixgbe, ether, 1, 1, 1); static int ixgbe_enable_aim = TRUE; TUNABLE_INT("hw.ixgbe.enable_aim", &ixgbe_enable_aim); +static int ixgbe_max_interrupt_rate = (8000000 / IXGBE_LOW_LATENCY); +TUNABLE_INT("hw.ixgbe.max_interrupt_rate", &ixgbe_max_interrupt_rate); + /* How many packets rxeof tries to clean at a time */ static int ixgbe_rx_process_limit = 128; TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit); @@ -288,13 +291,6 @@ TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd); static int ixgbe_total_ports; /* -** Shadow VFTA table, this is needed because -** the real filter table gets cleared during -** a soft reset and we need to repopulate it. -*/ -static u32 ixgbe_shadow_vfta[IXGBE_VFTA_SIZE]; - -/* ** The number of scatter-gather segments ** differs for 82598 and 82599, default to ** the former. @@ -445,24 +441,21 @@ ixgbe_attach(device_t dev) ixgbe_num_segs = IXGBE_82599_SCATTER; adapter->optics = IFM_10G_T; default: + ixgbe_num_segs = IXGBE_82599_SCATTER; break; } /* SYSCTL APIs */ - SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW, - adapter, 0, ixgbe_sysctl_stats, "I", "Statistics"); SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "debug", CTLTYPE_INT | CTLFLAG_RW, - adapter, 0, ixgbe_sysctl_debug, "I", "Debug Info"); + OID_AUTO, "flow_control", CTLTYPE_INT | CTLFLAG_RW, + adapter, 0, ixgbe_set_flowcntl, "I", "Flow Control"); SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "flow_control", CTLTYPE_INT | CTLFLAG_RW, - adapter, 0, ixgbe_set_flowcntl, "I", "Flow Control"); + OID_AUTO, "advertise_gig", CTLTYPE_INT | CTLFLAG_RW, + adapter, 0, ixgbe_set_advertise, "I", "1G Link"); SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), @@ -630,6 +623,8 @@ ixgbe_attach(device_t dev) ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); + ixgbe_add_hw_stats(adapter); + INIT_DEBUGOUT("ixgbe_attach: end"); return (0); err_late: @@ -774,8 +769,8 @@ ixgbe_start_locked(struct tx_ring *txr, ETHER_BPF_MTAP(ifp, m_head); /* Set watchdog on */ - txr->watchdog_check = TRUE; txr->watchdog_time = ticks; + txr->queue_status = IXGBE_QUEUE_WORKING; } return; @@ -845,6 +840,10 @@ ixgbe_mq_start_locked(struct ifnet *ifp, return (err); } + /* Call cleanup if number of TX descriptors low */ + if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) + ixgbe_txeof(txr); + enqueued = 0; if (m == NULL) { next = drbr_dequeue(ifp, txr->br); @@ -877,7 +876,7 @@ ixgbe_mq_start_locked(struct ifnet *ifp, if (enqueued > 0) { /* Set watchdog on */ - txr->watchdog_check = TRUE; + txr->queue_status = IXGBE_QUEUE_WORKING; txr->watchdog_time = ticks; } @@ -942,7 +941,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { if ((ifp->if_flags ^ adapter->if_flags) & (IFF_PROMISC | IFF_ALLMULTI)) { - ixgbe_disable_promisc(adapter); ixgbe_set_promisc(adapter); } } else @@ -981,6 +979,8 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c ifp->if_capenable ^= IFCAP_LRO; if (mask & IFCAP_VLAN_HWTAGGING) ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + if (mask & IFCAP_VLAN_HWFILTER) + ifp->if_capenable ^= IFCAP_VLAN_HWFILTER; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { IXGBE_CORE_LOCK(adapter); ixgbe_init_locked(adapter); @@ -1035,6 +1035,18 @@ ixgbe_init_locked(struct adapter *adapte ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1); hw->addr_ctrl.rar_used_count = 1; + /* Set the various hardware offload abilities */ + ifp->if_hwassist = 0; + if (ifp->if_capenable & IFCAP_TSO4) + ifp->if_hwassist |= CSUM_TSO; + if (ifp->if_capenable & IFCAP_TXCSUM) { + ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); +#if __FreeBSD_version >= 800000 + if (hw->mac.type == ixgbe_mac_82599EB) + ifp->if_hwassist |= CSUM_SCTP; +#endif + } + /* Prepare transmit descriptors and buffers */ if (ixgbe_setup_transmit_structures(adapter)) { device_printf(dev,"Could not setup transmit structures\n"); @@ -1052,10 +1064,12 @@ ixgbe_init_locked(struct adapter *adapte ** Determine the correct mbuf pool ** for doing jumbo/headersplit */ - if (ifp->if_mtu > ETHERMTU) + if (adapter->max_frame_size <= 2048) + adapter->rx_mbuf_sz = MCLBYTES; + else if (adapter->max_frame_size <= 4096) adapter->rx_mbuf_sz = MJUMPAGESIZE; else - adapter->rx_mbuf_sz = MCLBYTES; + adapter->rx_mbuf_sz = MJUM9BYTES; /* Prepare receive descriptors and buffers */ if (ixgbe_setup_receive_structures(adapter)) { @@ -1086,18 +1100,6 @@ ixgbe_init_locked(struct adapter *adapte } IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); - /* Set the various hardware offload abilities */ - ifp->if_hwassist = 0; - if (ifp->if_capenable & IFCAP_TSO4) - ifp->if_hwassist |= CSUM_TSO; - if (ifp->if_capenable & IFCAP_TXCSUM) { - ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); -#if __FreeBSD_version >= 800000 - if (hw->mac.type == ixgbe_mac_82599EB) - ifp->if_hwassist |= CSUM_SCTP; -#endif - } - /* Set MTU size */ if (ifp->if_mtu > ETHERMTU) { mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); @@ -1140,7 +1142,7 @@ ixgbe_init_locked(struct adapter *adapte IXGBE_WRITE_REG(hw, IXGBE_RDT(i), adapter->num_rx_desc - 1); } - /* Set up VLAN offloads and filter */ + /* Set up VLAN support and filter */ ixgbe_setup_vlan_hw_support(adapter); /* Enable Receive engine */ @@ -1754,10 +1756,6 @@ ixgbe_xmit(struct tx_ring *txr, struct m ++txr->total_packets; IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(txr->me), i); - /* Do a clean if descriptors are low */ - if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) - ixgbe_txeof(txr); - return (0); xmit_fail: @@ -1769,11 +1767,13 @@ xmit_fail: static void ixgbe_set_promisc(struct adapter *adapter) { - u_int32_t reg_rctl; struct ifnet *ifp = adapter->ifp; reg_rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); + reg_rctl &= (~IXGBE_FCTRL_UPE); + reg_rctl &= (~IXGBE_FCTRL_MPE); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl); if (ifp->if_flags & IFF_PROMISC) { reg_rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); @@ -1786,20 +1786,6 @@ ixgbe_set_promisc(struct adapter *adapte return; } -static void -ixgbe_disable_promisc(struct adapter * adapter) -{ - u_int32_t reg_rctl; - - reg_rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); - - reg_rctl &= (~IXGBE_FCTRL_UPE); - reg_rctl &= (~IXGBE_FCTRL_MPE); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl); - - return; -} - /********************************************************************* * Multicast Update @@ -1893,7 +1879,6 @@ static void ixgbe_local_timer(void *arg) { struct adapter *adapter = arg; - struct ifnet *ifp = adapter->ifp; device_t dev = adapter->dev; struct tx_ring *txr = adapter->tx_rings; @@ -1907,31 +1892,22 @@ ixgbe_local_timer(void *arg) ixgbe_update_link_status(adapter); ixgbe_update_stats_counters(adapter); - /* Debug display */ - if (ixgbe_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) - ixgbe_print_hw_stats(adapter); - /* * If the interface has been paused * then don't do the watchdog check */ if (IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) goto out; + /* - ** Check for time since any descriptor was cleaned + ** Check status on the TX queues for a hang */ - for (int i = 0; i < adapter->num_queues; i++, txr++) { - IXGBE_TX_LOCK(txr); - if (txr->watchdog_check == FALSE) { - IXGBE_TX_UNLOCK(txr); - continue; - } - if ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG) + for (int i = 0; i < adapter->num_queues; i++, txr++) + if (txr->queue_status == IXGBE_QUEUE_HUNG) goto hung; - IXGBE_TX_UNLOCK(txr); - } + out: - ixgbe_rearm_queues(adapter, adapter->que_mask); + ixgbe_rearm_queues(adapter, adapter->que_mask); callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); return; @@ -1979,7 +1955,7 @@ ixgbe_update_link_status(struct adapter adapter->link_active = FALSE; for (int i = 0; i < adapter->num_queues; i++, txr++) - txr->watchdog_check = FALSE; + txr->queue_status = IXGBE_QUEUE_IDLE; } } @@ -1999,6 +1975,7 @@ ixgbe_stop(void *arg) { struct ifnet *ifp; struct adapter *adapter = arg; + struct ixgbe_hw *hw = &adapter->hw; ifp = adapter->ifp; mtx_assert(&adapter->core_mtx, MA_OWNED); @@ -2009,9 +1986,12 @@ ixgbe_stop(void *arg) /* Tell the stack that the interface is no longer active */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - ixgbe_reset_hw(&adapter->hw); - adapter->hw.adapter_stopped = FALSE; - ixgbe_stop_adapter(&adapter->hw); + ixgbe_reset_hw(hw); + hw->adapter_stopped = FALSE; + ixgbe_stop_adapter(hw); + /* Turn off the laser */ + if (hw->phy.multispeed_fiber) + ixgbe_disable_tx_laser(hw); callout_stop(&adapter->timer); /* reprogram the RAR[0] in case user changed it. */ @@ -2236,6 +2216,9 @@ ixgbe_setup_msix(struct adapter *adapter if (ixgbe_num_queues != 0) queues = ixgbe_num_queues; + /* Set max queues to 8 */ + else if (queues > 8) + queues = 8; /* ** Want one vector (RX/TX pair) per queue @@ -2408,10 +2391,22 @@ ixgbe_setup_interface(device_t dev, stru ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM; ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; - ifp->if_capabilities |= IFCAP_JUMBO_MTU | IFCAP_LRO; - + ifp->if_capabilities |= IFCAP_JUMBO_MTU; ifp->if_capenable = ifp->if_capabilities; + /* Don't enable LRO by default */ + ifp->if_capabilities |= IFCAP_LRO; + + /* + ** Dont turn this on by default, if vlans are + ** created on another pseudo device (eg. lagg) + ** then vlan events are not passed thru, breaking + ** operation, but with HW FILTER off it works. If + ** using vlans directly on the em driver you can + ** enable this and get full hardware tag filtering. + */ + ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; + /* * Specify the media types supported by this adapter and register * callbacks to update media and link information @@ -2444,6 +2439,7 @@ ixgbe_config_link(struct adapter *adapte if (sfp) { if (hw->phy.multispeed_fiber) { hw->mac.ops.setup_sfp(hw); + ixgbe_enable_tx_laser(hw); taskqueue_enqueue(adapter->tq, &adapter->msf_task); } else taskqueue_enqueue(adapter->tq, &adapter->mod_task); @@ -2850,7 +2846,7 @@ ixgbe_initialize_transmit_units(struct a /* Setup Transmit Descriptor Cmd Settings */ txr->txd_cmd = IXGBE_TXD_CMD_IFCS; - txr->watchdog_check = FALSE; + txr->queue_status = IXGBE_QUEUE_IDLE; /* Disable Head Writeback */ switch (hw->mac.type) { @@ -3189,7 +3185,7 @@ ixgbe_atr(struct tx_ring *txr, struct mb { struct adapter *adapter = txr->adapter; struct ix_queue *que; - struct ixgbe_atr_input atr_input; + union ixgbe_atr_input atr_input; struct ip *ip; struct tcphdr *th; struct udphdr *uh; @@ -3233,7 +3229,7 @@ ixgbe_atr(struct tx_ring *txr, struct mb return; } - memset(&atr_input, 0, sizeof(struct ixgbe_atr_input)); + memset(&atr_input, 0, sizeof(union ixgbe_atr_input)); vlan_id = htole16(mp->m_pkthdr.ether_vtag); src_ipv4_addr = ip->ip_src.s_addr; @@ -3268,15 +3264,18 @@ ixgbe_txeof(struct tx_ring *txr) { struct adapter *adapter = txr->adapter; struct ifnet *ifp = adapter->ifp; - u32 first, last, done; + u32 first, last, done, processed; struct ixgbe_tx_buf *tx_buffer; struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc; mtx_assert(&txr->tx_mtx, MA_OWNED); - if (txr->tx_avail == adapter->num_tx_desc) + if (txr->tx_avail == adapter->num_tx_desc) { + txr->queue_status = IXGBE_QUEUE_IDLE; return FALSE; + } + processed = 0; first = txr->next_to_clean; tx_buffer = &txr->tx_buffers[first]; /* For cleanup we just use legacy struct */ @@ -3308,6 +3307,7 @@ ixgbe_txeof(struct tx_ring *txr) tx_desc->lower.data = 0; tx_desc->buffer_addr = 0; ++txr->tx_avail; + ++processed; if (tx_buffer->m_head) { txr->bytes += @@ -3350,6 +3350,15 @@ ixgbe_txeof(struct tx_ring *txr) txr->next_to_clean = first; /* + ** Watchdog calculation, we know there's + ** work outstanding or the first return + ** would have been taken, so none processed + ** for too long indicates a hang. + */ + if ((!processed) && ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG)) + txr->queue_status = IXGBE_QUEUE_HUNG; + + /* * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that * it is OK to send packets. If there are no pending descriptors, * clear the timeout. Otherwise, if some descriptors have been freed, @@ -3358,7 +3367,7 @@ ixgbe_txeof(struct tx_ring *txr) if (txr->tx_avail > IXGBE_TX_CLEANUP_THRESHOLD) { ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; if (txr->tx_avail == adapter->num_tx_desc) { - txr->watchdog_check = FALSE; + txr->queue_status = IXGBE_QUEUE_IDLE; return FALSE; } } @@ -3389,51 +3398,59 @@ ixgbe_refresh_mbufs(struct rx_ring *rxr, cleaned = -1; /* Signify no completions */ while (i != limit) { rxbuf = &rxr->rx_buffers[i]; - if ((rxbuf->m_head == NULL) && (rxr->hdr_split)) { + if (rxr->hdr_split == FALSE) + goto no_split; + + if (rxbuf->m_head == NULL) { mh = m_gethdr(M_DONTWAIT, MT_DATA); if (mh == NULL) goto update; - mh->m_pkthdr.len = mh->m_len = MHLEN; - mh->m_len = MHLEN; - mh->m_flags |= M_PKTHDR; - m_adj(mh, ETHER_ALIGN); - /* Get the memory mapping */ - error = bus_dmamap_load_mbuf_sg(rxr->htag, - rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - printf("GET BUF: dmamap load" - " failure - %d\n", error); - m_free(mh); - goto update; - } - rxbuf->m_head = mh; - bus_dmamap_sync(rxr->htag, rxbuf->hmap, - BUS_DMASYNC_PREREAD); - rxr->rx_base[i].read.hdr_addr = - htole64(hseg[0].ds_addr); + } else + mh = rxbuf->m_head; + + mh->m_pkthdr.len = mh->m_len = MHLEN; + mh->m_len = MHLEN; + mh->m_flags |= M_PKTHDR; + /* Get the memory mapping */ + error = bus_dmamap_load_mbuf_sg(rxr->htag, + rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + printf("Refresh mbufs: hdr dmamap load" + " failure - %d\n", error); + m_free(mh); + rxbuf->m_head = NULL; + goto update; } + rxbuf->m_head = mh; + bus_dmamap_sync(rxr->htag, rxbuf->hmap, + BUS_DMASYNC_PREREAD); + rxr->rx_base[i].read.hdr_addr = htole64(hseg[0].ds_addr); +no_split: if (rxbuf->m_pack == NULL) { mp = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, adapter->rx_mbuf_sz); if (mp == NULL) goto update; - mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz; - /* Get the memory mapping */ - error = bus_dmamap_load_mbuf_sg(rxr->ptag, - rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - printf("GET BUF: dmamap load" - " failure - %d\n", error); - m_free(mp); - goto update; - } - rxbuf->m_pack = mp; - bus_dmamap_sync(rxr->ptag, rxbuf->pmap, - BUS_DMASYNC_PREREAD); - rxr->rx_base[i].read.pkt_addr = - htole64(pseg[0].ds_addr); + } else + mp = rxbuf->m_pack; + + mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz; + /* Get the memory mapping */ + error = bus_dmamap_load_mbuf_sg(rxr->ptag, + rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + printf("Refresh mbufs: payload dmamap load" + " failure - %d\n", error); + m_free(mp); + rxbuf->m_pack = NULL; + goto update; } + rxbuf->m_pack = mp; + bus_dmamap_sync(rxr->ptag, rxbuf->pmap, + BUS_DMASYNC_PREREAD); + rxr->rx_base[i].read.pkt_addr = + htole64(pseg[0].ds_addr); cleaned = i; /* Calculate next index */ @@ -3495,9 +3512,9 @@ ixgbe_allocate_receive_buffers(struct rx BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - MJUMPAGESIZE, /* maxsize */ + MJUM9BYTES, /* maxsize */ 1, /* nsegments */ - MJUMPAGESIZE, /* maxsegsize */ + MJUM9BYTES, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockfuncarg */ @@ -4021,25 +4038,33 @@ ixgbe_rx_input(struct rx_ring *rxr, stru static __inline void ixgbe_rx_discard(struct rx_ring *rxr, int i) { - struct adapter *adapter = rxr->adapter; struct ixgbe_rx_buf *rbuf; - struct mbuf *mh, *mp; rbuf = &rxr->rx_buffers[i]; - if (rbuf->fmp != NULL) /* Partial chain ? */ + + if (rbuf->fmp != NULL) {/* Partial chain ? */ + rbuf->fmp->m_flags |= M_PKTHDR; m_freem(rbuf->fmp); + rbuf->fmp = NULL; + } - mh = rbuf->m_head; - mp = rbuf->m_pack; + /* + ** With advanced descriptors the writeback + ** clobbers the buffer addrs, so its easier + ** to just free the existing mbufs and take + ** the normal refresh path to get new buffers + ** and mapping. + */ + if (rbuf->m_head) { + m_free(rbuf->m_head); + rbuf->m_head = NULL; + } + + if (rbuf->m_pack) { + m_free(rbuf->m_pack); + rbuf->m_pack = NULL; + } - /* Reuse loaded DMA map and just update mbuf chain */ - mh->m_len = MHLEN; - mh->m_flags |= M_PKTHDR; - mh->m_next = NULL; - - mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz; - mp->m_data = mp->m_ext.ext_buf; - mp->m_next = NULL; return; } @@ -4104,15 +4129,15 @@ ixgbe_rxeof(struct ix_queue *que, int co vtag = le16toh(cur->wb.upper.vlan); eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0); - /* Make sure all parts of a bad packet are discarded */ + /* Make sure bad packets are discarded */ if (((staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) || (rxr->discard)) { ifp->if_ierrors++; rxr->rx_discarded++; - if (!eop) - rxr->discard = TRUE; - else + if (eop) rxr->discard = FALSE; + else + rxr->discard = TRUE; ixgbe_rx_discard(rxr, i); goto next_desc; } @@ -4123,7 +4148,7 @@ ixgbe_rxeof(struct ix_queue *que, int co ** not be fragmented across sequential ** descriptors, rather the next descriptor ** is indicated in bits of the descriptor. - ** This also means that we might process + ** This also means that we might proceses ** more than one packet at a time, something ** that has never been true before, it ** required eliminating global chain pointers @@ -4204,7 +4229,8 @@ ixgbe_rxeof(struct ix_queue *que, int co } else { /* Singlet, prepare to send */ sendmp = mh; - if (staterr & IXGBE_RXD_STAT_VP) { + if ((adapter->num_vlans) && + (staterr & IXGBE_RXD_STAT_VP)) { sendmp->m_pkthdr.ether_vtag = vtag; sendmp->m_flags |= M_VLANTAG; } @@ -4370,12 +4396,13 @@ ixgbe_register_vlan(void *arg, struct if if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; + IXGBE_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; - ixgbe_shadow_vfta[index] |= (1 << bit); + adapter->shadow_vfta[index] |= (1 << bit); ++adapter->num_vlans; - /* Re-init to load the changes */ - ixgbe_init(adapter); + ixgbe_init_locked(adapter); + IXGBE_CORE_UNLOCK(adapter); } /* @@ -4395,17 +4422,20 @@ ixgbe_unregister_vlan(void *arg, struct if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; + IXGBE_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; - ixgbe_shadow_vfta[index] &= ~(1 << bit); + adapter->shadow_vfta[index] &= ~(1 << bit); --adapter->num_vlans; /* Re-init to load the changes */ - ixgbe_init(adapter); + ixgbe_init_locked(adapter); + IXGBE_CORE_UNLOCK(adapter); } static void ixgbe_setup_vlan_hw_support(struct adapter *adapter) { + struct ifnet *ifp = adapter->ifp; struct ixgbe_hw *hw = &adapter->hw; u32 ctrl; @@ -4424,14 +4454,16 @@ ixgbe_setup_vlan_hw_support(struct adapt ** we need to repopulate it now. */ for (int i = 0; i < IXGBE_VFTA_SIZE; i++) - if (ixgbe_shadow_vfta[i] != 0) + if (adapter->shadow_vfta[i] != 0) IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), - ixgbe_shadow_vfta[i]); + adapter->shadow_vfta[i]); - /* Enable the Filter Table */ ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); - ctrl &= ~IXGBE_VLNCTRL_CFIEN; - ctrl |= IXGBE_VLNCTRL_VFE; + /* Enable the Filter Table if enabled */ + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) { + ctrl &= ~IXGBE_VLNCTRL_CFIEN; + ctrl |= IXGBE_VLNCTRL_VFE; + } if (hw->mac.type == ixgbe_mac_82598EB) ctrl |= IXGBE_VLNCTRL_VME; IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); @@ -4580,6 +4612,12 @@ static void ixgbe_configure_ivars(struct adapter *adapter) { struct ix_queue *que = adapter->queues; + u32 newitr; + + if (ixgbe_max_interrupt_rate > 0) + newitr = (8000000 / ixgbe_max_interrupt_rate) & 0x0FF8; + else + newitr = 0; for (int i = 0; i < adapter->num_queues; i++, que++) { /* First the RX queue entry */ @@ -4588,7 +4626,7 @@ ixgbe_configure_ivars(struct adapter *ad ixgbe_set_ivar(adapter, i, que->msix, 1); /* Set an Initial EITR value */ IXGBE_WRITE_REG(&adapter->hw, - IXGBE_EITR(que->msix), IXGBE_LOW_LATENCY); + IXGBE_EITR(que->msix), newitr); } /* For the Link interrupt */ @@ -4725,6 +4763,9 @@ ixgbe_update_stats_counters(struct adapt u64 total_missed_rx = 0; adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); + adapter->stats.illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); + adapter->stats.errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); + adapter->stats.mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); for (int i = 0; i < 8; i++) { u32 mp; @@ -4736,20 +4777,45 @@ ixgbe_update_stats_counters(struct adapt /* Running comprehensive total for stats display */ total_missed_rx += adapter->stats.mpc[i]; if (hw->mac.type == ixgbe_mac_82598EB) - adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i)); + adapter->stats.rnbc[i] += + IXGBE_READ_REG(hw, IXGBE_RNBC(i)); + adapter->stats.pxontxc[i] += + IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); + adapter->stats.pxonrxc[i] += + IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); + adapter->stats.pxofftxc[i] += + IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); + adapter->stats.pxoffrxc[i] += + IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); + adapter->stats.pxon2offc[i] += + IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); + } + for (int i = 0; i < 16; i++) { + adapter->stats.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); + adapter->stats.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); + adapter->stats.qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i)); + adapter->stats.qbrc[i] += + ((u64)IXGBE_READ_REG(hw, IXGBE_QBRC(i)) << 32); + adapter->stats.qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i)); + adapter->stats.qbtc[i] += + ((u64)IXGBE_READ_REG(hw, IXGBE_QBTC(i)) << 32); + adapter->stats.qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); } + adapter->stats.mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC); + adapter->stats.mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC); + adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); /* Hardware workaround, gprc counts missed packets */ adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); adapter->stats.gprc -= missed_rx; if (hw->mac.type == ixgbe_mac_82599EB) { - adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL); - IXGBE_READ_REG(hw, IXGBE_GORCH); /* clears register */ - adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL); - IXGBE_READ_REG(hw, IXGBE_GOTCH); /* clears register */ - adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORL); - IXGBE_READ_REG(hw, IXGBE_TORH); /* clears register */ + adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) + + ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32); + adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) + + ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32); + adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORL) + + ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32); adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); } else { @@ -4770,14 +4836,12 @@ ixgbe_update_stats_counters(struct adapt adapter->stats.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); adapter->stats.mprc -= bprc; - adapter->stats.roc += IXGBE_READ_REG(hw, IXGBE_ROC); adapter->stats.prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64); adapter->stats.prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127); adapter->stats.prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255); adapter->stats.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); adapter->stats.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); - adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); adapter->stats.lxontxc += lxon; @@ -4795,14 +4859,27 @@ ixgbe_update_stats_counters(struct adapt adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); adapter->stats.rfc += IXGBE_READ_REG(hw, IXGBE_RFC); + adapter->stats.roc += IXGBE_READ_REG(hw, IXGBE_ROC); adapter->stats.rjc += IXGBE_READ_REG(hw, IXGBE_RJC); + adapter->stats.mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC); + adapter->stats.mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC); + adapter->stats.mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC); adapter->stats.tpr += IXGBE_READ_REG(hw, IXGBE_TPR); + adapter->stats.tpt += IXGBE_READ_REG(hw, IXGBE_TPT); adapter->stats.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); adapter->stats.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); adapter->stats.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); adapter->stats.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); adapter->stats.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); adapter->stats.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); + adapter->stats.xec += IXGBE_READ_REG(hw, IXGBE_XEC); + adapter->stats.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); + adapter->stats.fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST); + adapter->stats.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); + adapter->stats.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); + adapter->stats.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); + adapter->stats.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); + adapter->stats.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); /* Fill out the OS statistics structure */ @@ -4818,147 +4895,372 @@ ixgbe_update_stats_counters(struct adapt adapter->stats.rlec; } - -/********************************************************************** - * - * This routine is called only when ixgbe_display_debug_stats is enabled. - * This routine provides a way to take a look at important statistics - * maintained by the driver and hardware. - * - **********************************************************************/ -static void -ixgbe_print_hw_stats(struct adapter * adapter) +/** ixgbe_sysctl_tdh_handler - Handler function + * Retrieves the TDH value from the hardware + */ +static int +ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS) { - device_t dev = adapter->dev; - + int error; - device_printf(dev,"Std Mbuf Failed = %lu\n", - adapter->mbuf_defrag_failed); - 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 = %lu\n", - adapter->dropped_pkts); - device_printf(dev, "watchdog timeouts = %ld\n", - adapter->watchdog_events); - - device_printf(dev,"XON Rcvd = %llu\n", - (long long)adapter->stats.lxonrxc); - device_printf(dev,"XON Xmtd = %llu\n", - (long long)adapter->stats.lxontxc); - device_printf(dev,"XOFF Rcvd = %llu\n", - (long long)adapter->stats.lxoffrxc); - device_printf(dev,"XOFF Xmtd = %llu\n", - (long long)adapter->stats.lxofftxc); - - device_printf(dev,"Total Packets Rcvd = %llu\n", - (long long)adapter->stats.tpr); - device_printf(dev,"Good Packets Rcvd = %llu\n", - (long long)adapter->stats.gprc); - device_printf(dev,"Good Packets Xmtd = %llu\n", - (long long)adapter->stats.gptc); - device_printf(dev,"TSO Transmissions = %lu\n", - adapter->tso_tx); + struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); + if (!txr) return 0; - return; + unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me)); + error = sysctl_handle_int(oidp, &val, 0, req); + if (error || !req->newptr) + return error; + return 0; } -/********************************************************************** - * - * This routine is called only when em_display_debug_stats is enabled. - * This routine provides a way to take a look at important statistics - * maintained by the driver and hardware. - * - **********************************************************************/ -static void -ixgbe_print_debug_info(struct adapter *adapter) +/** ixgbe_sysctl_tdt_handler - Handler function + * Retrieves the TDT value from the hardware + */ +static int +ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS) { - device_t dev = adapter->dev; - struct ixgbe_hw *hw = &adapter->hw; - struct ix_queue *que = adapter->queues; - struct rx_ring *rxr; - struct tx_ring *txr; - struct lro_ctrl *lro; - - device_printf(dev,"Error Byte Count = %u \n", - IXGBE_READ_REG(hw, IXGBE_ERRBC)); + int error; - for (int i = 0; i < adapter->num_queues; i++, que++) { - txr = que->txr; - rxr = que->rxr; - lro = &rxr->lro; - device_printf(dev,"QUE(%d) IRQs Handled: %lu\n", - que->msix, (long)que->irqs); - device_printf(dev,"RX[%d]: rdh = %d, hw rdt = %d\n", - i, IXGBE_READ_REG(hw, IXGBE_RDH(i)), - IXGBE_READ_REG(hw, IXGBE_RDT(i))); - device_printf(dev,"TX[%d] tdh = %d, hw tdt = %d\n", i, - IXGBE_READ_REG(hw, IXGBE_TDH(i)), - IXGBE_READ_REG(hw, IXGBE_TDT(i))); - device_printf(dev,"RX(%d) Packets Received: %lld\n", - rxr->me, (long long)rxr->rx_packets); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***