diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-06 16:20:21 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-11 10:08:08 +0100 |
commit | 66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch) | |
tree | 48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/dev/e1000 | |
parent | Define __GLOBL1() and __GLOBL() (diff) | |
download | rtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2 |
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/dev/e1000')
-rw-r--r-- | freebsd/sys/dev/e1000/e1000_api.c | 3 | ||||
-rw-r--r-- | freebsd/sys/dev/e1000/if_em.c | 179 | ||||
-rw-r--r-- | freebsd/sys/dev/e1000/if_em.h | 1 | ||||
-rw-r--r-- | freebsd/sys/dev/e1000/if_igb.c | 195 | ||||
-rw-r--r-- | freebsd/sys/dev/e1000/if_igb.h | 2 | ||||
-rw-r--r-- | freebsd/sys/dev/e1000/if_lem.c | 93 | ||||
-rw-r--r-- | freebsd/sys/dev/e1000/if_lem.h | 1 |
7 files changed, 264 insertions, 210 deletions
diff --git a/freebsd/sys/dev/e1000/e1000_api.c b/freebsd/sys/dev/e1000/e1000_api.c index 40a1dd3f..3c0eb4f4 100644 --- a/freebsd/sys/dev/e1000/e1000_api.c +++ b/freebsd/sys/dev/e1000/e1000_api.c @@ -331,6 +331,9 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_I350_DA4: mac->type = e1000_i350; break; +#if defined(QV_RELEASE) && defined(SPRINGVILLE_FLASHLESS_HW) + case E1000_DEV_ID_I210_NVMLESS: +#endif /* QV_RELEASE && SPRINGVILLE_FLASHLESS_HW */ case E1000_DEV_ID_I210_COPPER: case E1000_DEV_ID_I210_COPPER_OEM1: case E1000_DEV_ID_I210_COPPER_IT: diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c index 948d5f2b..4c1d3469 100644 --- a/freebsd/sys/dev/e1000/if_em.c +++ b/freebsd/sys/dev/e1000/if_em.c @@ -34,10 +34,11 @@ ******************************************************************************/ /*$FreeBSD$*/ -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include <rtems/bsd/local/opt_device_polling.h> #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include <rtems/bsd/local/opt_device_polling.h> #endif #include <rtems/bsd/sys/param.h> @@ -96,7 +97,7 @@ int em_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char em_driver_version[] = "7.3.7"; +char em_driver_version[] = "7.3.8"; /********************************************************************* * PCI Device ID Table @@ -337,6 +338,9 @@ MODULE_DEPEND(em, ether, 1, 1, 1); #define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) #define M_TSO_LEN 66 +#define MAX_INTS_PER_SEC 8000 +#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) + /* Allow common code without TSO */ #ifndef CSUM_TSO #define CSUM_TSO 0 @@ -572,6 +576,11 @@ em_attach(device_t dev) &adapter->tx_abs_int_delay, E1000_REGISTER(hw, E1000_TADV), em_tx_abs_int_delay_dflt); + em_add_int_delay_sysctl(adapter, "itr", + "interrupt delay limit in usecs/4", + &adapter->tx_itr, + E1000_REGISTER(hw, E1000_ITR), + DEFAULT_ITR); /* Sysctl for limiting the amount of work done in the taskqueue */ em_set_sysctl_value(adapter, "rx_processing_limit", @@ -2135,12 +2144,37 @@ em_set_promisc(struct adapter *adapter) static void em_disable_promisc(struct adapter *adapter) { - u32 reg_rctl; + struct ifnet *ifp = adapter->ifp; + u32 reg_rctl; + int mcnt = 0; reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); - reg_rctl &= (~E1000_RCTL_UPE); - reg_rctl &= (~E1000_RCTL_MPE); + if (ifp->if_flags & IFF_ALLMULTI) + mcnt = MAX_NUM_MULTICAST_ADDRESSES; + else { + struct ifmultiaddr *ifma; +#if __FreeBSD_version < 800000 + IF_ADDR_LOCK(ifp); +#else + if_maddr_rlock(ifp); +#endif + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) + break; + mcnt++; + } +#if __FreeBSD_version < 800000 + IF_ADDR_UNLOCK(ifp); +#else + if_maddr_runlock(ifp); +#endif + } + /* Don't disable if in MAX groups */ + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + reg_rctl &= (~E1000_RCTL_MPE); reg_rctl &= (~E1000_RCTL_SBP); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); } @@ -2245,7 +2279,7 @@ em_local_timer(void *arg) /* Mask to use in the irq trigger */ if (adapter->msix_mem) - trigger = rxr->ims; /* RX for 82574 */ + trigger = rxr->ims; else trigger = E1000_ICS_RXDMT0; @@ -2410,16 +2444,8 @@ em_identify_hardware(struct adapter *adapter) device_t dev = adapter->dev; /* Make sure our PCI config space has the necessary stuff set */ + pci_enable_busmaster(dev); adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); - if (!((adapter->hw.bus.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && - (adapter->hw.bus.pci_cmd_word & PCIM_CMD_MEMEN))) { - device_printf(dev, "Memory Access and/or Bus Master bits " - "were not set!\n"); - adapter->hw.bus.pci_cmd_word |= - (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); - pci_write_config(dev, PCIR_COMMAND, - adapter->hw.bus.pci_cmd_word, 2); - } /* Save off the information about this board */ adapter->hw.vendor_id = pci_get_vendor(dev); @@ -2718,7 +2744,7 @@ static int em_setup_msix(struct adapter *adapter) { device_t dev = adapter->dev; - int val = 0; + int val; /* ** Setup MSI/X for Hartwell: tests have shown @@ -2732,37 +2758,43 @@ em_setup_msix(struct adapter *adapter) int rid = PCIR_BAR(EM_MSIX_BAR); adapter->msix_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (!adapter->msix_mem) { + if (adapter->msix_mem == NULL) { /* May not be enabled */ device_printf(adapter->dev, "Unable to map MSIX table \n"); goto msi; } val = pci_msix_count(dev); - /* We only need 3 vectors */ - if (val > 3) + /* We only need/want 3 vectors */ + if (val >= 3) val = 3; - if ((val != 3) && (val != 5)) { - bus_release_resource(dev, SYS_RES_MEMORY, - PCIR_BAR(EM_MSIX_BAR), adapter->msix_mem); - adapter->msix_mem = NULL; + else { device_printf(adapter->dev, - "MSIX: incorrect vectors, using MSI\n"); + "MSIX: insufficient vectors, using MSI\n"); goto msi; } - if (pci_alloc_msix(dev, &val) == 0) { + if ((pci_alloc_msix(dev, &val) == 0) && (val == 3)) { device_printf(adapter->dev, "Using MSIX interrupts " "with %d vectors\n", val); + return (val); } - return (val); + /* + ** If MSIX alloc failed or provided us with + ** less than needed, free and fall through to MSI + */ + pci_release_msi(dev); } msi: - val = pci_msi_count(dev); - if (val == 1 && pci_alloc_msi(dev, &val) == 0) { - adapter->msix = 1; + if (adapter->msix_mem != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + PCIR_BAR(EM_MSIX_BAR), adapter->msix_mem); + adapter->msix_mem = NULL; + } + val = 1; + if (pci_alloc_msi(dev, &val) == 0) { device_printf(adapter->dev,"Using an MSI interrupt\n"); return (val); } @@ -3805,17 +3837,9 @@ em_txeof(struct tx_ring *txr) EM_TX_LOCK_ASSERT(txr); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - - selwakeuppri(&na->tx_rings[txr->me].si, PI_NET); - EM_TX_UNLOCK(txr); - EM_CORE_LOCK(adapter); - selwakeuppri(&na->tx_si, PI_NET); - EM_CORE_UNLOCK(adapter); - EM_TX_LOCK(txr); + if (netmap_tx_irq(ifp, txr->me | + (NETMAP_LOCKED_ENTER | NETMAP_LOCKED_EXIT))) return; - } #endif /* DEV_NETMAP */ /* No work, make sure watchdog is off */ @@ -4256,8 +4280,6 @@ em_free_receive_buffers(struct rx_ring *rxr) * Enable receive unit. * **********************************************************************/ -#define MAX_INTS_PER_SEC 8000 -#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) static void em_initialize_receive_unit(struct adapter *adapter) @@ -4299,11 +4321,12 @@ em_initialize_receive_unit(struct adapter *adapter) E1000_WRITE_REG(hw, E1000_RFCTL, E1000_RFCTL_ACK_DIS); } - if (ifp->if_capenable & IFCAP_RXCSUM) { - rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); - rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); - E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); - } + rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); + if (ifp->if_capenable & IFCAP_RXCSUM) + rxcsum |= E1000_RXCSUM_TUOFL; + else + rxcsum &= ~E1000_RXCSUM_TUOFL; + E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); /* ** XXX TEMPORARY WORKAROUND: on some systems with 82573 @@ -4317,6 +4340,8 @@ em_initialize_receive_unit(struct adapter *adapter) for (int i = 0; i < adapter->num_queues; i++, rxr++) { /* Setup the Base and Length of the Rx Descriptor Ring */ + u32 rdt = adapter->num_rx_desc - 1; /* default */ + bus_addr = rxr->rxdma.dma_paddr; E1000_WRITE_REG(hw, E1000_RDLEN(i), adapter->num_rx_desc * sizeof(struct e1000_rx_desc)); @@ -4328,18 +4353,11 @@ em_initialize_receive_unit(struct adapter *adapter) /* * an init() while a netmap client is active must * preserve the rx buffers passed to userspace. - * In this driver it means we adjust RDT to - * something different from na->num_rx_desc - 1. */ - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(adapter->ifp); - struct netmap_kring *kring = &na->rx_rings[i]; - int t = na->num_rx_desc - 1 - kring->nr_hwavail; - - E1000_WRITE_REG(hw, E1000_RDT(i), t); - } else + if (ifp->if_capenable & IFCAP_NETMAP) + rdt -= NA(adapter->ifp)->rx_rings[i].nr_hwavail; #endif /* DEV_NETMAP */ - E1000_WRITE_REG(hw, E1000_RDT(i), adapter->num_rx_desc - 1); + E1000_WRITE_REG(hw, E1000_RDT(i), rdt); } /* Set PTHRESH for improved jumbo performance */ @@ -4416,17 +4434,8 @@ em_rxeof(struct rx_ring *rxr, int count, int *done) EM_RX_LOCK(rxr); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - - na->rx_rings[rxr->me].nr_kflags |= NKR_PENDINTR; - selwakeuppri(&na->rx_rings[rxr->me].si, PI_NET); - EM_RX_UNLOCK(rxr); - EM_CORE_LOCK(adapter); - selwakeuppri(&na->rx_si, PI_NET); - EM_CORE_UNLOCK(adapter); - return (0); - } + if (netmap_rx_irq(ifp, rxr->me | NETMAP_LOCKED_ENTER, &processed)) + return (FALSE); #endif /* DEV_NETMAP */ for (i = rxr->next_to_check, processed = 0; count != 0;) { @@ -4621,31 +4630,23 @@ em_fixup_rx(struct rx_ring *rxr) static void em_receive_checksum(struct e1000_rx_desc *rx_desc, struct mbuf *mp) { + mp->m_pkthdr.csum_flags = 0; + /* Ignore Checksum bit is set */ - if (rx_desc->status & E1000_RXD_STAT_IXSM) { - mp->m_pkthdr.csum_flags = 0; + if (rx_desc->status & E1000_RXD_STAT_IXSM) return; - } - if (rx_desc->status & E1000_RXD_STAT_IPCS) { - /* Did it pass? */ - if (!(rx_desc->errors & E1000_RXD_ERR_IPE)) { - /* IP Checksum Good */ - mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; - mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; + if (rx_desc->errors & (E1000_RXD_ERR_TCPE | E1000_RXD_ERR_IPE)) + return; - } else { - mp->m_pkthdr.csum_flags = 0; - } - } + /* IP Checksum Good? */ + if (rx_desc->status & E1000_RXD_STAT_IPCS) + mp->m_pkthdr.csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID); - if (rx_desc->status & E1000_RXD_STAT_TCPCS) { - /* Did it pass? */ - if (!(rx_desc->errors & E1000_RXD_ERR_TCPE)) { - mp->m_pkthdr.csum_flags |= - (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); - mp->m_pkthdr.csum_data = htons(0xffff); - } + /* TCP or UDP checksum */ + if (rx_desc->status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) { + mp->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); + mp->m_pkthdr.csum_data = htons(0xffff); } } @@ -5624,6 +5625,8 @@ em_sysctl_int_delay(SYSCTL_HANDLER_ARGS) return (EINVAL); info->value = usecs; ticks = EM_USECS_TO_TICKS(usecs); + if (info->offset == E1000_ITR) /* units are 256ns here */ + ticks *= 4; adapter = info->adapter; diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h index f1afbadb..09d81d25 100644 --- a/freebsd/sys/dev/e1000/if_em.h +++ b/freebsd/sys/dev/e1000/if_em.h @@ -429,6 +429,7 @@ struct adapter { struct em_int_delay_info tx_abs_int_delay; struct em_int_delay_info rx_int_delay; struct em_int_delay_info rx_abs_int_delay; + struct em_int_delay_info tx_itr; /* Misc stats maintained by the driver */ unsigned long dropped_pkts; diff --git a/freebsd/sys/dev/e1000/if_igb.c b/freebsd/sys/dev/e1000/if_igb.c index a3c7fede..e26a867c 100644 --- a/freebsd/sys/dev/e1000/if_igb.c +++ b/freebsd/sys/dev/e1000/if_igb.c @@ -35,16 +35,17 @@ /*$FreeBSD$*/ -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include <rtems/bsd/local/opt_device_polling.h> #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include <rtems/bsd/local/opt_device_polling.h> #include <rtems/bsd/local/opt_altq.h> #endif #include <rtems/bsd/sys/param.h> #include <sys/systm.h> -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX #include <sys/buf_ring.h> #endif #include <sys/bus.h> @@ -102,7 +103,7 @@ int igb_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] = "version - 2.3.9 - 8"; +char igb_driver_version[] = "version - 2.3.10"; /********************************************************************* @@ -181,7 +182,7 @@ static int igb_detach(device_t); static int igb_shutdown(device_t); static int igb_suspend(device_t); static int igb_resume(device_t); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX static int igb_mq_start(struct ifnet *, struct mbuf *); static int igb_mq_start_locked(struct ifnet *, struct tx_ring *); static void igb_qflush(struct ifnet *); @@ -376,8 +377,9 @@ SYSCTL_INT(_hw_igb, OID_AUTO, header_split, CTLFLAG_RDTUN, &igb_header_split, 0, "Enable receive mbuf header split"); /* -** This will autoconfigure based on -** the number of CPUs if left at 0. +** This will autoconfigure based on the +** number of CPUs and max supported +** MSIX messages if left at 0. */ static int igb_num_queues = 0; TUNABLE_INT("hw.igb.num_queues", &igb_num_queues); @@ -852,7 +854,7 @@ igb_resume(device_t dev) (ifp->if_drv_flags & IFF_DRV_RUNNING) && adapter->link_active) { for (int i = 0; i < adapter->num_queues; i++, txr++) { IGB_TX_LOCK(txr); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Process the stack queue only if not depleted */ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && !drbr_empty(ifp, txr->br)) @@ -870,7 +872,7 @@ igb_resume(device_t dev) } -#if __FreeBSD_version < 800000 +#ifdef IGB_LEGACY_TX /********************************************************************* * Transmit entry point @@ -948,7 +950,7 @@ igb_start(struct ifnet *ifp) return; } -#else /* __FreeBSD_version >= 800000 */ +#else /* ~IGB_LEGACY_TX */ /* ** Multiqueue Transmit Entry: @@ -972,7 +974,13 @@ igb_mq_start(struct ifnet *ifp, struct mbuf *m) que = &adapter->queues[i]; err = drbr_enqueue(ifp, txr->br, m); - taskqueue_enqueue(que->tq, &txr->txq_task); + if (err) + return (err); + if (IGB_TX_TRYLOCK(txr)) { + err = igb_mq_start_locked(ifp, txr); + IGB_TX_UNLOCK(txr); + } else + taskqueue_enqueue(que->tq, &txr->txq_task); return (err); } @@ -981,8 +989,8 @@ static int igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr) { struct adapter *adapter = txr->adapter; - struct mbuf *buf; - int err = 0, enq = 0; + struct mbuf *next; + int err = 0, enq; IGB_TX_LOCK_ASSERT(txr); @@ -990,22 +998,32 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr) adapter->link_active == 0) return (ENETDOWN); + enq = 0; + /* Process the queue */ - buf = drbr_dequeue(ifp, txr->br); - while (buf != NULL) { - if ((err = igb_xmit(txr, &buf)) != 0) { - if (buf != NULL) - err = drbr_enqueue(ifp, txr->br, buf); + while ((next = drbr_peek(ifp, txr->br)) != NULL) { + if ((err = igb_xmit(txr, &next)) != 0) { + if (next == NULL) { + /* It was freed, move forward */ + drbr_advance(ifp, txr->br); + } else { + /* + * Still have one left, it may not be + * the same since the transmit function + * may have changed it. + */ + drbr_putback(ifp, txr->br, next); + } break; } + drbr_advance(ifp, txr->br); enq++; - ifp->if_obytes += buf->m_pkthdr.len; - if (buf->m_flags & M_MCAST) + ifp->if_obytes += next->m_pkthdr.len; + if (next->m_flags & M_MCAST) ifp->if_omcasts++; - ETHER_BPF_MTAP(ifp, buf); + ETHER_BPF_MTAP(ifp, next); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) break; - buf = drbr_dequeue(ifp, txr->br); } if (enq > 0) { /* Set the watchdog */ @@ -1053,7 +1071,7 @@ igb_qflush(struct ifnet *ifp) } if_qflush(ifp); } -#endif /* __FreeBSD_version >= 800000 */ +#endif /* ~IGB_LEGACY_TX */ /********************************************************************* * Ioctl entry point @@ -1379,7 +1397,7 @@ igb_handle_que(void *context, int pending) IGB_TX_LOCK(txr); igb_txeof(txr); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Process the stack queue only if not depleted */ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && !drbr_empty(ifp, txr->br)) @@ -1430,7 +1448,7 @@ igb_handle_link_locked(struct adapter *adapter) if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && adapter->link_active) { for (int i = 0; i < adapter->num_queues; i++, txr++) { IGB_TX_LOCK(txr); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Process the stack queue only if not depleted */ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && !drbr_empty(ifp, txr->br)) @@ -1532,7 +1550,7 @@ igb_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) do { more = igb_txeof(txr); } while (loop-- && more); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX if (!drbr_empty(ifp, txr->br)) igb_mq_start_locked(ifp, txr); #else @@ -1562,12 +1580,16 @@ igb_msix_que(void *arg) u32 newitr = 0; bool more_rx; + /* Ignore spurious interrupts */ + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; + E1000_WRITE_REG(&adapter->hw, E1000_EIMC, que->eims); ++que->irqs; IGB_TX_LOCK(txr); igb_txeof(txr); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Process the stack queue only if not depleted */ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && !drbr_empty(ifp, txr->br)) @@ -2087,7 +2109,9 @@ static void igb_disable_promisc(struct adapter *adapter) { struct e1000_hw *hw = &adapter->hw; + struct ifnet *ifp = adapter->ifp; u32 reg; + int mcnt = 0; if (adapter->vf_ifp) { e1000_promisc_set_vf(hw, e1000_promisc_disabled); @@ -2095,7 +2119,31 @@ igb_disable_promisc(struct adapter *adapter) } reg = E1000_READ_REG(hw, E1000_RCTL); reg &= (~E1000_RCTL_UPE); - reg &= (~E1000_RCTL_MPE); + if (ifp->if_flags & IFF_ALLMULTI) + mcnt = MAX_NUM_MULTICAST_ADDRESSES; + else { + struct ifmultiaddr *ifma; +#if __FreeBSD_version < 800000 + IF_ADDR_LOCK(ifp); +#else + if_maddr_rlock(ifp); +#endif + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) + break; + mcnt++; + } +#if __FreeBSD_version < 800000 + IF_ADDR_UNLOCK(ifp); +#else + if_maddr_runlock(ifp); +#endif + } + /* Don't disable if in MAX groups */ + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + reg &= (~E1000_RCTL_MPE); E1000_WRITE_REG(hw, E1000_RCTL, reg); } @@ -2370,16 +2418,8 @@ igb_identify_hardware(struct adapter *adapter) device_t dev = adapter->dev; /* Make sure our PCI config space has the necessary stuff set */ + pci_enable_busmaster(dev); adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); - if (!((adapter->hw.bus.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && - (adapter->hw.bus.pci_cmd_word & PCIM_CMD_MEMEN))) { - INIT_DEBUGOUT("Memory Access and/or Bus Master " - "bits were not set!\n"); - adapter->hw.bus.pci_cmd_word |= - (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); - pci_write_config(dev, PCIR_COMMAND, - adapter->hw.bus.pci_cmd_word, 2); - } /* Save off the information about this board */ adapter->hw.vendor_id = pci_get_vendor(dev); @@ -2439,7 +2479,6 @@ igb_allocate_legacy(struct adapter *adapter) { device_t dev = adapter->dev; struct igb_queue *que = adapter->queues; - struct tx_ring *txr = adapter->tx_rings; int error, rid = 0; /* Turn off all interrupts */ @@ -2458,8 +2497,8 @@ igb_allocate_legacy(struct adapter *adapter) return (ENXIO); } -#if __FreeBSD_version >= 800000 - TASK_INIT(&txr->txq_task, 0, igb_deferred_mq_start, txr); +#ifndef IGB_LEGACY_TX + TASK_INIT(&que->txr->txq_task, 0, igb_deferred_mq_start, que->txr); #endif /* @@ -2542,7 +2581,7 @@ igb_allocate_msix(struct adapter *adapter) i,igb_last_bind_cpu); igb_last_bind_cpu = CPU_NEXT(igb_last_bind_cpu); } -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX TASK_INIT(&que->txr->txq_task, 0, igb_deferred_mq_start, que->txr); #endif @@ -2768,7 +2807,7 @@ igb_free_pci_resources(struct adapter *adapter) for (int i = 0; i < adapter->num_queues; i++, que++) { if (que->tq != NULL) { -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX taskqueue_drain(que->tq, &que->txr->txq_task); #endif taskqueue_drain(que->tq, &que->que_task); @@ -2803,24 +2842,19 @@ igb_setup_msix(struct adapter *adapter) goto msi; /* First try MSI/X */ + msgs = pci_msix_count(dev); + if (msgs == 0) + goto msi; rid = PCIR_BAR(IGB_MSIX_BAR); adapter->msix_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (!adapter->msix_mem) { + if (adapter->msix_mem == NULL) { /* May not be enabled */ device_printf(adapter->dev, "Unable to map MSIX table \n"); goto msi; } - msgs = pci_msix_count(dev); - if (msgs == 0) { /* system has msix disabled */ - bus_release_resource(dev, SYS_RES_MEMORY, - PCIR_BAR(IGB_MSIX_BAR), adapter->msix_mem); - adapter->msix_mem = NULL; - goto msi; - } - /* Figure out a reasonable auto config value */ queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus; @@ -2863,20 +2897,32 @@ igb_setup_msix(struct adapter *adapter) "MSIX Configuration Problem, " "%d vectors configured, but %d queues wanted!\n", msgs, want); - return (0); + goto msi; } - if ((msgs) && pci_alloc_msix(dev, &msgs) == 0) { + if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) { device_printf(adapter->dev, "Using MSIX interrupts with %d vectors\n", msgs); adapter->num_queues = queues; return (msgs); } + /* + ** If MSIX alloc failed or provided us with + ** less than needed, free and fall through to MSI + */ + pci_release_msi(dev); + msi: - msgs = pci_msi_count(dev); - if (msgs == 1 && pci_alloc_msi(dev, &msgs) == 0) { - device_printf(adapter->dev," Using MSI interrupt\n"); + if (adapter->msix_mem != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + PCIR_BAR(IGB_MSIX_BAR), adapter->msix_mem); + adapter->msix_mem = NULL; + } + msgs = 1; + if (pci_alloc_msi(dev, &msgs) == 0) { + device_printf(adapter->dev," Using an MSI interrupt\n"); return (msgs); } + device_printf(adapter->dev," Using a Legacy interrupt\n"); return (0); } @@ -3078,7 +3124,7 @@ igb_setup_interface(device_t dev, struct adapter *adapter) ifp->if_softc = adapter; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = igb_ioctl; -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX ifp->if_transmit = igb_mq_start; ifp->if_qflush = igb_qflush; #else @@ -3322,7 +3368,7 @@ igb_allocate_queues(struct adapter *adapter) error = ENOMEM; goto err_tx_desc; } -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Allocate a buf ring */ txr->br = buf_ring_alloc(igb_buf_ring_size, M_DEVBUF, M_WAITOK, &txr->tx_mtx); @@ -3383,7 +3429,7 @@ err_tx_desc: igb_dma_free(adapter, &txr->txdma); free(adapter->rx_rings, M_DEVBUF); rx_fail: -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX buf_ring_free(txr->br, M_DEVBUF); #endif free(adapter->tx_rings, M_DEVBUF); @@ -3641,7 +3687,7 @@ igb_free_transmit_buffers(struct tx_ring *txr) tx_buffer->map = NULL; } } -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX if (txr->br != NULL) buf_ring_free(txr->br, M_DEVBUF); #endif @@ -3863,17 +3909,9 @@ igb_txeof(struct tx_ring *txr) IGB_TX_LOCK_ASSERT(txr); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - - selwakeuppri(&na->tx_rings[txr->me].si, PI_NET); - IGB_TX_UNLOCK(txr); - IGB_CORE_LOCK(adapter); - selwakeuppri(&na->tx_si, PI_NET); - IGB_CORE_UNLOCK(adapter); - IGB_TX_LOCK(txr); - return FALSE; - } + if (netmap_tx_irq(ifp, txr->me | + (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT))) + return (FALSE); #endif /* DEV_NETMAP */ if (txr->tx_avail == adapter->num_tx_desc) { txr->queue_status = IGB_QUEUE_IDLE; @@ -4727,17 +4765,8 @@ igb_rxeof(struct igb_queue *que, int count, int *done) BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - - na->rx_rings[rxr->me].nr_kflags |= NKR_PENDINTR; - selwakeuppri(&na->rx_rings[rxr->me].si, PI_NET); - IGB_RX_UNLOCK(rxr); - IGB_CORE_LOCK(adapter); - selwakeuppri(&na->rx_si, PI_NET); - IGB_CORE_UNLOCK(adapter); - return (0); - } + if (netmap_rx_irq(ifp, rxr->me | NETMAP_LOCKED_ENTER, &processed)) + return (FALSE); #endif /* DEV_NETMAP */ /* Main clean loop */ @@ -4862,7 +4891,7 @@ igb_rxeof(struct igb_queue *que, int count, int *done) rxr->fmp->m_pkthdr.ether_vtag = vtag; rxr->fmp->m_flags |= M_VLANTAG; } -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX rxr->fmp->m_pkthdr.flowid = que->msix; rxr->fmp->m_flags |= M_FLOWID; #endif diff --git a/freebsd/sys/dev/e1000/if_igb.h b/freebsd/sys/dev/e1000/if_igb.h index f286e67a..6f3a3a54 100644 --- a/freebsd/sys/dev/e1000/if_igb.h +++ b/freebsd/sys/dev/e1000/if_igb.h @@ -297,7 +297,7 @@ struct tx_ring { u32 next_to_clean; volatile u16 tx_avail; struct igb_tx_buffer *tx_buffers; -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX struct buf_ring *br; struct task txq_task; #endif diff --git a/freebsd/sys/dev/e1000/if_lem.c b/freebsd/sys/dev/e1000/if_lem.c index aa64f655..5127445c 100644 --- a/freebsd/sys/dev/e1000/if_lem.c +++ b/freebsd/sys/dev/e1000/if_lem.c @@ -34,10 +34,11 @@ ******************************************************************************/ /*$FreeBSD$*/ -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include <rtems/bsd/local/opt_device_polling.h> #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include <rtems/bsd/local/opt_device_polling.h> #endif #include <rtems/bsd/sys/param.h> @@ -87,7 +88,7 @@ /********************************************************************* * Legacy Em Driver version: *********************************************************************/ -char lem_driver_version[] = "1.0.5"; +char lem_driver_version[] = "1.0.6"; /********************************************************************* * PCI Device ID Table @@ -283,6 +284,9 @@ MODULE_DEPEND(lem, ether, 1, 1, 1); #define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) #define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) +#define MAX_INTS_PER_SEC 8000 +#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) + static int lem_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV); static int lem_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR); static int lem_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV); @@ -444,6 +448,11 @@ lem_attach(device_t dev) &adapter->tx_abs_int_delay, E1000_REGISTER(&adapter->hw, E1000_TADV), lem_tx_abs_int_delay_dflt); + lem_add_int_delay_sysctl(adapter, "itr", + "interrupt delay limit in usecs/4", + &adapter->tx_itr, + E1000_REGISTER(&adapter->hw, E1000_ITR), + DEFAULT_ITR); } /* Sysctls for limiting the amount of work done in the taskqueue */ @@ -1339,12 +1348,16 @@ lem_handle_rxtx(void *context, int pending) if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - lem_rxeof(adapter, adapter->rx_process_limit, NULL); + bool more = lem_rxeof(adapter, adapter->rx_process_limit, NULL); EM_TX_LOCK(adapter); lem_txeof(adapter); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) lem_start_locked(ifp); EM_TX_UNLOCK(adapter); + if (more) { + taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); + return; + } } if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -1858,12 +1871,37 @@ lem_set_promisc(struct adapter *adapter) static void lem_disable_promisc(struct adapter *adapter) { - u32 reg_rctl; + struct ifnet *ifp = adapter->ifp; + u32 reg_rctl; + int mcnt = 0; reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); - reg_rctl &= (~E1000_RCTL_UPE); - reg_rctl &= (~E1000_RCTL_MPE); + if (ifp->if_flags & IFF_ALLMULTI) + mcnt = MAX_NUM_MULTICAST_ADDRESSES; + else { + struct ifmultiaddr *ifma; +#if __FreeBSD_version < 800000 + IF_ADDR_LOCK(ifp); +#else + if_maddr_rlock(ifp); +#endif + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) + break; + mcnt++; + } +#if __FreeBSD_version < 800000 + IF_ADDR_UNLOCK(ifp); +#else + if_maddr_runlock(ifp); +#endif + } + /* Don't disable if in MAX groups */ + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + reg_rctl &= (~E1000_RCTL_MPE); reg_rctl &= (~E1000_RCTL_SBP); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); } @@ -2083,16 +2121,8 @@ lem_identify_hardware(struct adapter *adapter) device_t dev = adapter->dev; /* Make sure our PCI config space has the necessary stuff set */ + pci_enable_busmaster(dev); adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); - if (!((adapter->hw.bus.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && - (adapter->hw.bus.pci_cmd_word & PCIM_CMD_MEMEN))) { - device_printf(dev, "Memory Access and/or Bus Master bits " - "were not set!\n"); - adapter->hw.bus.pci_cmd_word |= - (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); - pci_write_config(dev, PCIR_COMMAND, - adapter->hw.bus.pci_cmd_word, 2); - } /* Save off the information about this board */ adapter->hw.vendor_id = pci_get_vendor(dev); @@ -2957,10 +2987,8 @@ lem_txeof(struct adapter *adapter) EM_TX_LOCK_ASSERT(adapter); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - selwakeuppri(&NA(ifp)->tx_rings[0].si, PI_NET); + if (netmap_tx_irq(ifp, 0 | (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT))) return; - } #endif /* DEV_NETMAP */ if (adapter->num_tx_desc_avail == adapter->num_tx_desc) return; @@ -3248,8 +3276,6 @@ lem_setup_receive_structures(struct adapter *adapter) * Enable receive unit. * **********************************************************************/ -#define MAX_INTS_PER_SEC 8000 -#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) static void lem_initialize_receive_unit(struct adapter *adapter) @@ -3340,19 +3366,13 @@ lem_initialize_receive_unit(struct adapter *adapter) * Tail Descriptor Pointers */ E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0); + rctl = adapter->num_rx_desc - 1; /* default RDT value */ #ifdef DEV_NETMAP /* preserve buffers already made available to clients */ - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(adapter->ifp); - struct netmap_kring *kring = &na->rx_rings[0]; - int t = na->num_rx_desc - 1 - kring->nr_hwavail; - - if (t >= na->num_rx_desc) - t -= na->num_rx_desc; - E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), t); - } else + if (ifp->if_capenable & IFCAP_NETMAP) + rctl -= NA(adapter->ifp)->rx_rings[0].nr_hwavail; #endif /* DEV_NETMAP */ - E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), adapter->num_rx_desc - 1); + E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), rctl); return; } @@ -3436,13 +3456,8 @@ lem_rxeof(struct adapter *adapter, int count, int *done) BUS_DMASYNC_POSTREAD); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - na->rx_rings[0].nr_kflags |= NKR_PENDINTR; - selwakeuppri(&na->rx_rings[0].si, PI_NET); - EM_RX_UNLOCK(adapter); - return (0); - } + if (netmap_rx_irq(ifp, 0 | NETMAP_LOCKED_ENTER, &rx_sent)) + return (FALSE); #endif /* DEV_NETMAP */ if (!((current_desc->status) & E1000_RXD_STAT_DD)) { @@ -4586,6 +4601,8 @@ lem_sysctl_int_delay(SYSCTL_HANDLER_ARGS) return (EINVAL); info->value = usecs; ticks = EM_USECS_TO_TICKS(usecs); + if (info->offset == E1000_ITR) /* units are 256ns here */ + ticks *= 4; adapter = info->adapter; diff --git a/freebsd/sys/dev/e1000/if_lem.h b/freebsd/sys/dev/e1000/if_lem.h index c1973e55..235277d7 100644 --- a/freebsd/sys/dev/e1000/if_lem.h +++ b/freebsd/sys/dev/e1000/if_lem.h @@ -363,6 +363,7 @@ struct adapter { struct em_int_delay_info tx_abs_int_delay; struct em_int_delay_info rx_int_delay; struct em_int_delay_info rx_abs_int_delay; + struct em_int_delay_info tx_itr; /* * Transmit definitions |