From owner-svn-src-all@FreeBSD.ORG Fri Nov 26 22:46:33 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1C3B4106564A; Fri, 26 Nov 2010 22:46:33 +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 099978FC1D; Fri, 26 Nov 2010 22:46:33 +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 oAQMkXVn093935; Fri, 26 Nov 2010 22:46:33 GMT (envelope-from jfv@svn.freebsd.org) Received: (from jfv@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oAQMkWL2093929; Fri, 26 Nov 2010 22:46:32 GMT (envelope-from jfv@svn.freebsd.org) Message-Id: <201011262246.oAQMkWL2093929@svn.freebsd.org> From: Jack F Vogel Date: Fri, 26 Nov 2010 22:46:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r215911 - in head/sys: conf dev/ixgbe modules/ixgbe X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Nov 2010 22:46:33 -0000 Author: jfv Date: Fri Nov 26 22:46:32 2010 New Revision: 215911 URL: http://svn.freebsd.org/changeset/base/215911 Log: Update ixgbe driver to verion 2.3.6 - This adds a VM SRIOV interface, ixv, it is however transparent to the user, it links with the ixgbe.ko, but when ixgbe is loaded in a virtualized guest with SRIOV configured this will be detected. - Sync shared code to latest - Many bug fixes and improvements, thanks to everyone who has been using the driver and reporting issues. Added: head/sys/dev/ixgbe/ixgbe_mbx.c (contents, props changed) head/sys/dev/ixgbe/ixgbe_mbx.h (contents, props changed) head/sys/dev/ixgbe/ixgbe_vf.c (contents, props changed) head/sys/dev/ixgbe/ixgbe_vf.h (contents, props changed) head/sys/dev/ixgbe/ixv.c (contents, props changed) head/sys/dev/ixgbe/ixv.h (contents, props changed) Modified: head/sys/conf/files head/sys/dev/ixgbe/ixgbe.c head/sys/dev/ixgbe/ixgbe.h head/sys/dev/ixgbe/ixgbe_82598.c head/sys/dev/ixgbe/ixgbe_82599.c head/sys/dev/ixgbe/ixgbe_api.c head/sys/dev/ixgbe/ixgbe_api.h head/sys/dev/ixgbe/ixgbe_common.c head/sys/dev/ixgbe/ixgbe_common.h head/sys/dev/ixgbe/ixgbe_osdep.h head/sys/dev/ixgbe/ixgbe_phy.c head/sys/dev/ixgbe/ixgbe_phy.h head/sys/dev/ixgbe/ixgbe_type.h head/sys/modules/ixgbe/Makefile Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Fri Nov 26 22:36:47 2010 (r215910) +++ head/sys/conf/files Fri Nov 26 22:46:32 2010 (r215911) @@ -1252,12 +1252,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: head/sys/dev/ixgbe/ixgbe.c ============================================================================== --- head/sys/dev/ixgbe/ixgbe.c Fri Nov 26 22:36:47 2010 (r215910) +++ head/sys/dev/ixgbe/ixgbe.c Fri Nov 26 22:46:32 2010 (r215911) @@ -46,7 +46,7 @@ int ixgbe_display_debug_stat /********************************************************************* * Driver version *********************************************************************/ -char ixgbe_driver_version[] = "2.2.3"; +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} }; @@ -119,7 +121,7 @@ static int ixgbe_allocate_queues(struct 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_setup_interface(device_t, struct adapter *); static void ixgbe_config_link(struct adapter *); static int ixgbe_allocate_transmit_buffers(struct tx_ring *); @@ -144,7 +146,6 @@ 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 *); @@ -212,7 +213,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); @@ -257,7 +258,7 @@ TUNABLE_INT("hw.ixgbe.enable_msix", &ixg /* * Header split: this causes the hardware to DMA - * the header into a separate mbuf from the payload, + * the header into a seperate mbuf from the payload, * it can be a performance win in some workloads, but * in others it actually hurts, its off by default. */ @@ -289,13 +290,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. @@ -446,6 +440,7 @@ ixgbe_attach(device_t dev) ixgbe_num_segs = IXGBE_82599_SCATTER; adapter->optics = IFM_10G_T; default: + ixgbe_num_segs = IXGBE_82599_SCATTER; break; } @@ -524,15 +519,6 @@ ixgbe_attach(device_t dev) goto err_out; } - /* Allocate multicast array memory. */ - adapter->mta = malloc(sizeof(u8) * IXGBE_ETH_LENGTH_OF_ADDRESS * - MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT); - if (adapter->mta == NULL) { - device_printf(dev, "Can not allocate multicast setup array\n"); - error = ENOMEM; - goto err_late; - } - /* Initialize the shared code */ error = ixgbe_init_shared_code(hw); if (error == IXGBE_ERR_SFP_NOT_PRESENT) { @@ -595,8 +581,7 @@ ixgbe_attach(device_t dev) goto err_late; /* Setup OS specific network interface */ - if (ixgbe_setup_interface(dev, adapter) != 0) - goto err_late; + ixgbe_setup_interface(dev, adapter); /* Sysctl for limiting the amount of work done in the taskqueue */ ixgbe_add_rx_process_limit(adapter, "rx_processing_limit", @@ -642,10 +627,7 @@ err_late: ixgbe_free_transmit_structures(adapter); ixgbe_free_receive_structures(adapter); err_out: - if (adapter->ifp != NULL) - if_free(adapter->ifp); ixgbe_free_pci_resources(adapter); - free(adapter->mta, M_DEVBUF); return (error); } @@ -716,7 +698,6 @@ ixgbe_detach(device_t dev) ixgbe_free_transmit_structures(adapter); ixgbe_free_receive_structures(adapter); - free(adapter->mta, M_DEVBUF); IXGBE_CORE_LOCK_DESTROY(adapter); return (0); @@ -780,8 +761,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; @@ -851,6 +832,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); @@ -883,7 +868,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; } @@ -948,7 +933,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 @@ -987,6 +971,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); @@ -1041,6 +1027,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"); @@ -1058,10 +1056,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)) { @@ -1092,18 +1092,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); @@ -1146,7 +1134,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 */ @@ -1760,10 +1748,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: @@ -1775,11 +1759,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); @@ -1792,20 +1778,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 @@ -1819,7 +1791,7 @@ static void ixgbe_set_multi(struct adapter *adapter) { u32 fctrl; - u8 *mta; + u8 mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 *update_ptr; struct ifmultiaddr *ifma; int mcnt = 0; @@ -1827,10 +1799,6 @@ ixgbe_set_multi(struct adapter *adapter) IOCTL_DEBUGOUT("ixgbe_set_multi: begin"); - mta = adapter->mta; - bzero(mta, sizeof(u8) * IXGBE_ETH_LENGTH_OF_ADDRESS * - MAX_NUM_MULTICAST_ADDRESSES); - fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); if (ifp->if_flags & IFF_PROMISC) @@ -1923,19 +1891,14 @@ ixgbe_local_timer(void *arg) */ 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); callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter); @@ -1985,7 +1948,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; } } @@ -2005,6 +1968,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); @@ -2015,9 +1979,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. */ @@ -2242,6 +2209,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 @@ -2375,7 +2345,7 @@ mem: * Setup networking device structure and register an interface. * **********************************************************************/ -static int +static void ixgbe_setup_interface(device_t dev, struct adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; @@ -2384,10 +2354,8 @@ ixgbe_setup_interface(device_t dev, stru INIT_DEBUGOUT("ixgbe_setup_interface: begin"); ifp = adapter->ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(dev, "can not allocate ifnet structure\n"); - return (-1); - } + if (ifp == NULL) + panic("%s: can not if_alloc()\n", device_get_nameunit(dev)); if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_mtu = ETHERMTU; ifp->if_baudrate = 1000000000; @@ -2414,10 +2382,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 @@ -2435,7 +2415,7 @@ ixgbe_setup_interface(device_t dev, stru ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); - return (0); + return; } static void @@ -2450,6 +2430,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); @@ -2856,7 +2837,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) { @@ -3195,7 +3176,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; @@ -3239,7 +3220,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; @@ -3274,15 +3255,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 */ @@ -3314,6 +3298,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 += @@ -3356,6 +3341,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, @@ -3364,7 +3358,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; } } @@ -3395,51 +3389,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 */ @@ -3501,9 +3503,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 */ @@ -3661,7 +3663,7 @@ ixgbe_setup_receive_ring(struct rx_ring rxbuf = &rxr->rx_buffers[j]; /* - ** Don't allocate mbufs if not + ** Dont allocate mbufs if not ** doing header split, its wasteful */ if (rxr->hdr_split == FALSE) @@ -4027,25 +4029,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; } @@ -4110,15 +4120,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; } @@ -4129,7 +4139,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 @@ -4210,7 +4220,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; } @@ -4376,12 +4387,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); } /* @@ -4401,17 +4413,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; @@ -4430,14 +4445,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); @@ -4478,14 +4495,14 @@ ixgbe_enable_intr(struct adapter *adapte /* With RSS we use auto clear */ if (adapter->msix_mem) { mask = IXGBE_EIMS_ENABLE_MASK; - /* Don't autoclear Link */ + /* Dont autoclear Link */ mask &= ~IXGBE_EIMS_OTHER; mask &= ~IXGBE_EIMS_LSC; IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); } /* - ** Now enable all queues, this is done separately to + ** Now enable all queues, this is done seperately to ** allow for handling the extended (beyond 32) MSIX ** vectors that can be used by 82599 */ Modified: head/sys/dev/ixgbe/ixgbe.h ============================================================================== --- head/sys/dev/ixgbe/ixgbe.h Fri Nov 26 22:36:47 2010 (r215910) +++ head/sys/dev/ixgbe/ixgbe.h Fri Nov 26 22:46:32 2010 (r215911) @@ -179,6 +179,9 @@ #define IXGBE_RX_HDR 128 #define IXGBE_VFTA_SIZE 128 #define IXGBE_BR_SIZE 4096 +#define IXGBE_QUEUE_IDLE 0 +#define IXGBE_QUEUE_WORKING 1 +#define IXGBE_QUEUE_HUNG 2 /* Offload bits in mbuf flag */ #if __FreeBSD_version >= 800000 @@ -205,11 +208,6 @@ #define IXGBE_BULK_LATENCY 1200 #define IXGBE_LINK_ITR 2000 -/* Header split args for get_bug */ -#define IXGBE_CLEAN_HDR 1 -#define IXGBE_CLEAN_PKT 2 -#define IXGBE_CLEAN_ALL 3 - /* ***************************************************************************** * vendor_info_array @@ -280,7 +278,7 @@ struct tx_ring { struct adapter *adapter; struct mtx tx_mtx; u32 me; - bool watchdog_check; + int queue_status; int watchdog_time; union ixgbe_adv_tx_desc *tx_base; struct ixgbe_dma_alloc txdma; @@ -374,7 +372,15 @@ struct adapter { u16 num_vlans; u16 num_queues; - /* Info about the board itself */ + /* + ** Shadow VFTA table, this is needed because + ** the real vlan filter table gets cleared during + ** a soft reset and the driver needs to be able + ** to repopulate it. + */ + u32 shadow_vfta[IXGBE_VFTA_SIZE]; + + /* Info about the interface */ u32 optics; int advertise; /* link speeds */ bool link_active; @@ -421,8 +427,6 @@ struct adapter { u64 que_mask; u32 rx_process_limit; - /* Multicast array memory */ - u8 *mta; /* Misc stats maintained by the driver */ unsigned long dropped_pkts; unsigned long mbuf_defrag_failed; Modified: head/sys/dev/ixgbe/ixgbe_82598.c ============================================================================== --- head/sys/dev/ixgbe/ixgbe_82598.c Fri Nov 26 22:36:47 2010 (r215910) +++ head/sys/dev/ixgbe/ixgbe_82598.c Fri Nov 26 22:46:32 2010 (r215911) @@ -73,7 +73,6 @@ u32 ixgbe_get_supported_physical_layer_8 s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw); void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw); void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw); -static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw); /** * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout @@ -186,6 +185,7 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw mac->mcft_size = 128; mac->vft_size = 128; mac->num_rar_entries = 16; + mac->rx_pb_size = 512; mac->max_tx_queues = 32; mac->max_rx_queues = 64; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw); @@ -196,6 +196,7 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw /* Link */ mac->ops.check_link = &ixgbe_check_mac_link_82598; mac->ops.setup_link = &ixgbe_setup_mac_link_82598; + mac->ops.flap_tx_laser = NULL; mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82598; @@ -385,11 +386,14 @@ static enum ixgbe_media_type ixgbe_get_m DEBUGFUNC("ixgbe_get_media_type_82598"); /* Detect if there is a copper PHY attached. */ - if (hw->phy.type == ixgbe_phy_cu_unknown || - hw->phy.type == ixgbe_phy_tn || - hw->phy.type == ixgbe_phy_aq) { + switch (hw->phy.type) { + case ixgbe_phy_cu_unknown: + case ixgbe_phy_tn: + case ixgbe_phy_aq: media_type = ixgbe_media_type_copper; goto out; + default: + break; } /* Media type for I82598 is based on device ID */ @@ -436,6 +440,7 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h u32 fctrl_reg; u32 rmcs_reg; u32 reg; + u32 rx_pba_size; u32 link_speed = 0; bool link_up; @@ -463,7 +468,7 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h /* Negotiate the fc mode to use */ ret_val = ixgbe_fc_autoneg(hw); - if (ret_val) + if (ret_val == IXGBE_ERR_FLOW_CONTROL) goto out; /* Disable any previous flow control settings */ @@ -485,7 +490,8 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h */ switch (hw->fc.current_mode) { case ixgbe_fc_none: - /* Flow control is disabled by software override or autoneg. + /* + * Flow control is disabled by software override or autoneg. * The code below will actually disable it in the HW. */ break; @@ -526,16 +532,19 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h /* Set up and enable Rx high/low water mark thresholds, enable XON. */ if (hw->fc.current_mode & ixgbe_fc_tx_pause) { - if (hw->fc.send_xon) { - IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), - (hw->fc.low_water | IXGBE_FCRTL_XONE)); - } else { - IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), - hw->fc.low_water); - } + rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)); + rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT; + + reg = (rx_pba_size - hw->fc.low_water) << 6; + if (hw->fc.send_xon) + reg |= IXGBE_FCRTL_XONE; + + IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg); - IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), - (hw->fc.high_water | IXGBE_FCRTH_FCEN)); + reg = (rx_pba_size - hw->fc.high_water) << 6; + reg |= IXGBE_FCRTH_FCEN; + + IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg); } /* Configure pause time (2 TCs per register) */ @@ -560,7 +569,7 @@ out: * Restarts the link. Performs autonegotiation if needed. **/ static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, - bool autoneg_wait_to_complete) + bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg; @@ -601,6 +610,41 @@ static s32 ixgbe_start_mac_link_82598(st } /** + * ixgbe_validate_link_ready - Function looks for phy link + * @hw: pointer to hardware structure + * + * Function indicates success when phy link is available. If phy is not ready + * within 5 seconds of MAC indicating link, the function returns error. + **/ +static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw) +{ + u32 timeout; + u16 an_reg; + + if (hw->device_id != IXGBE_DEV_ID_82598AT2) + return IXGBE_SUCCESS; + + for (timeout = 0; + timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***