Date: Sat, 25 Apr 2015 01:29:41 +0000 (UTC) From: Sean Bruno <sbruno@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r281965 - in projects/em_mq: share/man/man4 sys/dev/e1000 sys/dev/netmap Message-ID: <201504250129.t3P1Tf3R054066@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sbruno Date: Sat Apr 25 01:29:40 2015 New Revision: 281965 URL: https://svnweb.freebsd.org/changeset/base/281965 Log: Combine rx/tx queue handling into a single thread. Combine rx/tx msi-x handling into a single interrupt. This was seriously suggested by jhb and scottl during discussions. This rips off much from igb(4) and removes a lock around drbr_enqueue() that needed to be inplace to keep rx handling initiating a tx on the same interrupt. Modified: projects/em_mq/share/man/man4/em.4 projects/em_mq/sys/dev/e1000/if_em.c projects/em_mq/sys/dev/e1000/if_em.h projects/em_mq/sys/dev/netmap/if_em_netmap.h Modified: projects/em_mq/share/man/man4/em.4 ============================================================================== --- projects/em_mq/share/man/man4/em.4 Sat Apr 25 01:23:29 2015 (r281964) +++ projects/em_mq/share/man/man4/em.4 Sat Apr 25 01:29:40 2015 (r281965) @@ -244,7 +244,6 @@ If .Va hw.em.tx_int_delay is non-zero, this tunable limits the maximum delay in which a transmit interrupt is generated. -.It Va hw.em.num_rx_queues .It Va hw.em.num_tx_queues Number of h/w queues that we will run on this adapter. Max 2. Defaults to 1. Only valid with kernel configuration Modified: projects/em_mq/sys/dev/e1000/if_em.c ============================================================================== --- projects/em_mq/sys/dev/e1000/if_em.c Sat Apr 25 01:23:29 2015 (r281964) +++ projects/em_mq/sys/dev/e1000/if_em.c Sat Apr 25 01:29:40 2015 (r281965) @@ -256,7 +256,7 @@ static void em_disable_intr(struct adapt static void em_update_stats_counters(struct adapter *); static void em_add_hw_stats(struct adapter *adapter); static void em_txeof(struct tx_ring *); -static bool em_rxeof(struct rx_ring *, int, int *); +static bool em_rxeof(struct em_queue *, int, int *); #ifndef __NO_STRICT_ALIGNMENT static int em_fixup_rx(struct rx_ring *); #endif @@ -299,17 +299,11 @@ static void em_disable_aspm(struct adapt static int em_irq_fast(void *); /* MSIX handlers */ -static void em_msix_tx(void *); -static void em_msix_rx(void *); +static void em_msix_que(void *); static void em_msix_link(void *); -static void em_handle_tx(void *context, int pending); -static void em_handle_rx(void *context, int pending); +static void em_handle_que(void *context, int pending); static void em_handle_link(void *context, int pending); -#ifdef EM_MULTIQUEUE -static void em_enable_vectors_82574(struct adapter *); -#endif - static void em_set_sysctl_value(struct adapter *, const char *, const char *, int *, int); static int em_set_flowcntl(SYSCTL_HANDLER_ARGS); @@ -400,13 +394,9 @@ SYSCTL_INT(_hw_em, OID_AUTO, enable_msix "Enable MSI-X interrupts"); #ifdef EM_MULTIQUEUE -static int em_num_tx_queues = 1; -SYSCTL_INT(_hw_em, OID_AUTO, num_tx_queues, CTLFLAG_RDTUN, &em_num_tx_queues, 0, - "82574 only: Number of tx queues to configure, 0 indicates autoconfigure"); - -static int em_num_rx_queues = 1; -SYSCTL_INT(_hw_em, OID_AUTO, num_rx_queues, CTLFLAG_RDTUN, &em_num_rx_queues, 0, - "82574 only: Number of rx queues to configure, 0 indicates autoconfigure"); +static int em_num_queues = 1; +SYSCTL_INT(_hw_em, OID_AUTO, num_queues, CTLFLAG_RDTUN, &em_num_queues, 0, + "82574 only: Number of hw queues to configure, 0 indicates autoconfigure"); #endif /* @@ -909,7 +899,7 @@ em_resume(device_t dev) if ((if_getflags(ifp) & IFF_UP) && (if_getdrvflags(ifp) & IFF_DRV_RUNNING) && adapter->link_active) { - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, txr++) { EM_TX_LOCK(txr); #ifdef EM_MULTIQUEUE if (!drbr_empty(ifp, txr->br)) @@ -1005,19 +995,19 @@ static int em_mq_start(if_t ifp, struct mbuf *m) { struct adapter *adapter = if_getsoftc(ifp); - struct tx_ring *txr = adapter->tx_rings; + struct tx_ring *txr; + struct em_queue *que; unsigned int i, error; if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) - i = m->m_pkthdr.flowid % adapter->num_tx_queues; + i = m->m_pkthdr.flowid % adapter->num_queues; else - i = curcpu % adapter->num_tx_queues; + i = curcpu % adapter->num_queues; txr = &adapter->tx_rings[i]; + que = &adapter->queues[i]; - EM_TX_LOCK(txr); error = drbr_enqueue(ifp, txr->br, m); - EM_TX_UNLOCK(txr); if (error) return (error); @@ -1025,7 +1015,7 @@ em_mq_start(if_t ifp, struct mbuf *m) em_mq_start_locked(ifp, txr); EM_TX_UNLOCK(txr); } else - taskqueue_enqueue(txr->tq, &txr->tx_task); + taskqueue_enqueue(que->tq, &que->que_task); return (0); } @@ -1094,7 +1084,7 @@ em_qflush(if_t ifp) struct tx_ring *txr = adapter->tx_rings; struct mbuf *m; - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, txr++) { EM_TX_LOCK(txr); while ((m = buf_ring_dequeue_sc(txr->br)) != NULL) m_freem(m); @@ -1518,6 +1508,7 @@ static int em_irq_fast(void *arg) { struct adapter *adapter = arg; + struct em_queue *que = adapter->queues; if_t ifp; u32 reg_icr; @@ -1542,7 +1533,7 @@ em_irq_fast(void *arg) return FILTER_STRAY; em_disable_intr(adapter); - taskqueue_enqueue(adapter->tq, &adapter->que_task); + taskqueue_enqueue(que->tq, &que->que_task); /* Link status change */ if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { @@ -1559,13 +1550,13 @@ em_irq_fast(void *arg) static void em_handle_que(void *context, int pending) { - struct adapter *adapter = context; + struct em_queue *que = context; + struct adapter *adapter = que->adapter; if_t ifp = adapter->ifp; - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct tx_ring *txr = que->txr; if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { - bool more = em_rxeof(rxr, adapter->rx_process_limit, NULL); + bool more = em_rxeof(que, adapter->rx_process_limit, NULL); EM_TX_LOCK(txr); em_txeof(txr); @@ -1578,7 +1569,7 @@ em_handle_que(void *context, int pending #endif EM_TX_UNLOCK(txr); if (more) { - taskqueue_enqueue(adapter->tq, &adapter->que_task); + taskqueue_enqueue(que->tq, &que->que_task); return; } } @@ -1594,13 +1585,20 @@ em_handle_que(void *context, int pending * **********************************************************************/ static void -em_msix_tx(void *arg) +em_msix_que(void *arg) { - struct tx_ring *txr = arg; - struct adapter *adapter = txr->adapter; + struct em_queue *que = arg; + struct adapter *adapter = que->adapter; + struct tx_ring *txr = que->txr; + bool more; if_t ifp = adapter->ifp; - ++txr->tx_irq; + if (!(if_getdrvflags(adapter->ifp) & IFF_DRV_RUNNING)) + return; + + E1000_WRITE_REG(&adapter->hw, E1000_IMS, que->ims); + ++que->irqs; + EM_TX_LOCK(txr); em_txeof(txr); #ifdef EM_MULTIQUEUE @@ -1610,35 +1608,14 @@ em_msix_tx(void *arg) if (!if_sendq_empty(ifp)) em_start_locked(ifp, txr); #endif - - /* Reenable this interrupt */ - E1000_WRITE_REG(&adapter->hw, E1000_IMS, txr->ims); EM_TX_UNLOCK(txr); - return; -} - -/********************************************************************* - * - * MSIX RX Interrupt Service routine - * - **********************************************************************/ -static void -em_msix_rx(void *arg) -{ - struct rx_ring *rxr = arg; - struct adapter *adapter = rxr->adapter; - bool more; - - ++rxr->rx_irq; - if (!(if_getdrvflags(adapter->ifp) & IFF_DRV_RUNNING)) - return; - more = em_rxeof(rxr, adapter->rx_process_limit, NULL); + more = em_rxeof(que, adapter->rx_process_limit, NULL); if (more) - taskqueue_enqueue(rxr->tq, &rxr->rx_task); + taskqueue_enqueue(que->tq, &que->que_task); else { /* Reenable this interrupt */ - E1000_WRITE_REG(&adapter->hw, E1000_IMS, rxr->ims); + E1000_WRITE_REG(&adapter->hw, E1000_IMS, que->ims); } return; } @@ -1667,42 +1644,6 @@ em_msix_link(void *arg) } static void -em_handle_rx(void *context, int pending) -{ - struct rx_ring *rxr = context; - struct adapter *adapter = rxr->adapter; - bool more; - - more = em_rxeof(rxr, adapter->rx_process_limit, NULL); - if (more) - taskqueue_enqueue(rxr->tq, &rxr->rx_task); - else { - /* Reenable this interrupt */ - E1000_WRITE_REG(&adapter->hw, E1000_IMS, rxr->ims); - } -} - -static void -em_handle_tx(void *context, int pending) -{ - struct tx_ring *txr = context; - struct adapter *adapter = txr->adapter; - if_t ifp = adapter->ifp; - - EM_TX_LOCK(txr); - em_txeof(txr); -#ifdef EM_MULTIQUEUE - if (!drbr_empty(ifp, txr->br)) - em_mq_start_locked(ifp, txr); -#else - if (!if_sendq_empty(ifp)) - em_start_locked(ifp, txr); -#endif - E1000_WRITE_REG(&adapter->hw, E1000_IMS, txr->ims); - EM_TX_UNLOCK(txr); -} - -static void em_handle_link(void *context, int pending) { struct adapter *adapter = context; @@ -1719,7 +1660,7 @@ em_handle_link(void *context, int pendin E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_LINK | E1000_IMS_LSC); if (adapter->link_active) { - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, txr++) { EM_TX_LOCK(txr); #ifdef EM_MULTIQUEUE if (!drbr_empty(ifp, txr->br)) @@ -2267,8 +2208,8 @@ em_local_timer(void *arg) { struct adapter *adapter = arg; if_t ifp = adapter->ifp; + struct em_queue *que = adapter->queues; struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; u32 trigger; EM_CORE_LOCK_ASSERT(adapter); @@ -2283,7 +2224,7 @@ em_local_timer(void *arg) /* Mask to use in the irq trigger */ if (adapter->msix_mem) - trigger = rxr->ims; + trigger = adapter->que_mask; else trigger = E1000_ICS_RXDMT0; @@ -2292,7 +2233,7 @@ em_local_timer(void *arg) ** can be done without the lock because its RO ** and the HUNG state will be static if set. */ - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, que++, txr++) { if ((txr->queue_status == EM_QUEUE_HUNG) && (adapter->pause_frames == 0)) { em_print_debug_info(adapter); @@ -2300,7 +2241,7 @@ em_local_timer(void *arg) } /* Schedule a TX tasklet if needed */ if (txr->tx_avail <= EM_MAX_SCATTER) - taskqueue_enqueue(txr->tq, &txr->tx_task); + taskqueue_enqueue(que->tq, &que->que_task); } adapter->pause_frames = 0; @@ -2387,7 +2328,7 @@ em_update_link_status(struct adapter *ad device_printf(dev, "Link is Down\n"); adapter->link_active = 0; /* Link down, disable watchdog */ - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) + for (int i = 0; i < adapter->num_queues; i++, txr++) txr->queue_status = EM_QUEUE_IDLE; if_link_state_change(ifp, LINK_STATE_DOWN); } @@ -2420,7 +2361,7 @@ em_stop(void *arg) if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING); /* Unarm watchdog timer. */ - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, txr++) { EM_TX_LOCK(txr); txr->queue_status = EM_QUEUE_IDLE; EM_TX_UNLOCK(txr); @@ -2497,7 +2438,7 @@ int em_allocate_legacy(struct adapter *adapter) { device_t dev = adapter->dev; - struct tx_ring *txr = adapter->tx_rings; + struct em_queue *que = adapter->queues; int error, rid = 0; /* Manually turn off all interrupts */ @@ -2518,17 +2459,11 @@ em_allocate_legacy(struct adapter *adapt * Allocate a fast interrupt and the associated * deferred processing contexts. */ - TASK_INIT(&adapter->que_task, 0, em_handle_que, adapter); + TASK_INIT(&adapter->que_task, 0, em_handle_que, que); adapter->tq = taskqueue_create_fast("em_taskq", M_NOWAIT, taskqueue_thread_enqueue, &adapter->tq); taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s que", device_get_nameunit(adapter->dev)); - /* Use a TX only tasklet for local timer */ - TASK_INIT(&txr->tx_task, 0, em_handle_tx, txr); - txr->tq = taskqueue_create_fast("em_txq", M_NOWAIT, - taskqueue_thread_enqueue, &txr->tq); - taskqueue_start_threads(&txr->tq, 1, PI_NET, "%s txq", - device_get_nameunit(adapter->dev)); TASK_INIT(&adapter->link_task, 0, em_handle_link, adapter); if ((error = bus_setup_intr(dev, adapter->res, INTR_TYPE_NET, em_irq_fast, NULL, adapter, &adapter->tag)) != 0) { @@ -2554,8 +2489,7 @@ int em_allocate_msix(struct adapter *adapter) { device_t dev = adapter->dev; - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct em_queue *que = adapter->queues; int error, rid, vector = 0; int cpu_id = 0; @@ -2564,92 +2498,51 @@ em_allocate_msix(struct adapter *adapter E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff); /* First set up ring resources */ - for (int i = 0; i < adapter->num_rx_queues; i++, rxr++, vector++) { + for (int i = 0; i < adapter->num_queues; i++, vector++, que++) { /* RX ring */ rid = vector + 1; - rxr->res = bus_alloc_resource_any(dev, - SYS_RES_IRQ, &rid, RF_ACTIVE); - if (rxr->res == NULL) { + que->res = bus_alloc_resource_any(dev, + SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); + if (que->res == NULL) { device_printf(dev, "Unable to allocate bus resource: " - "RX MSIX Interrupt %d\n", i); + "MSIX QUEUE Interrupt %d\n", i); return (ENXIO); } - if ((error = bus_setup_intr(dev, rxr->res, - INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_rx, - rxr, &rxr->tag)) != 0) { - device_printf(dev, "Failed to register RX handler"); + if ((error = bus_setup_intr(dev, que->res, + INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_que, + que, &que->tag)) != 0) { + device_printf(dev, "Failed to register QUEUE handler"); return (error); } #if __FreeBSD_version >= 800504 - bus_describe_intr(dev, rxr->res, rxr->tag, "rx %d", i); + bus_describe_intr(dev, que->res, que->tag, "que %d", i); #endif - rxr->msix = vector; + que->msix = vector; if (em_last_bind_cpu < 0) em_last_bind_cpu = CPU_FIRST(); cpu_id = em_last_bind_cpu; - bus_bind_intr(dev, rxr->res, cpu_id); + bus_bind_intr(dev, que->res, cpu_id); - TASK_INIT(&rxr->rx_task, 0, em_handle_rx, rxr); - rxr->tq = taskqueue_create_fast("em_rxq", M_NOWAIT, - taskqueue_thread_enqueue, &rxr->tq); - taskqueue_start_threads(&rxr->tq, 1, PI_NET, "%s rxq (qid %d)", + TASK_INIT(&que->que_task, 0, em_handle_que, que); + que->tq = taskqueue_create_fast("em_queue", M_NOWAIT, + taskqueue_thread_enqueue, &que->tq); + taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que (qid %d)", device_get_nameunit(adapter->dev), cpu_id); /* ** Set the bit to enable interrupt ** in E1000_IMS -- bits 20 and 21 - ** are for RX0 and RX1, note this has + ** are for RX0 and RX1, bits 22 and 23 + ** are for TX0 and TX1. note this has ** NOTHING to do with the MSIX vector */ - rxr->ims = 1 << (20 + i); - adapter->ivars |= (8 | rxr->msix) << (i * 4); - - em_last_bind_cpu = CPU_NEXT(em_last_bind_cpu); - } - - for (int i = 0; i < adapter->num_tx_queues; i++, txr++, vector++) { - /* TX ring */ - rid = vector + 1; - txr->res = bus_alloc_resource_any(dev, - SYS_RES_IRQ, &rid, RF_ACTIVE); - if (txr->res == NULL) { - device_printf(dev, - "Unable to allocate bus resource: " - "TX MSIX Interrupt %d\n", i); - return (ENXIO); - } - if ((error = bus_setup_intr(dev, txr->res, - INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_tx, - txr, &txr->tag)) != 0) { - device_printf(dev, "Failed to register TX handler"); - return (error); - } -#if __FreeBSD_version >= 800504 - bus_describe_intr(dev, txr->res, txr->tag, "tx %d", i); -#endif - txr->msix = vector; - - if (em_last_bind_cpu < 0) - em_last_bind_cpu = CPU_FIRST(); - cpu_id = em_last_bind_cpu; - bus_bind_intr(dev, txr->res, cpu_id); - - TASK_INIT(&txr->tx_task, 0, em_handle_tx, txr); - txr->tq = taskqueue_create_fast("em_txq", M_NOWAIT, - taskqueue_thread_enqueue, &txr->tq); - taskqueue_start_threads(&txr->tq, 1, PI_NET, "%s txq (qid %d)", - device_get_nameunit(adapter->dev), cpu_id); - /* - ** Set the bit to enable interrupt - ** in E1000_IMS -- bits 22 and 23 - ** are for TX0 and TX1, note this has - ** NOTHING to do with the MSIX vector - */ - txr->ims = 1 << (22 + i); - adapter->ivars |= (8 | txr->msix) << (8 + (i * 4)); + que->ims = (1 << (20 + i)) | (1 << (22 + i)); + adapter->ivars |= (8 | que->msix) << (i * 4); + adapter->ivars |= (8 | que->msix) << (8 + (i * 4)); + adapter->que_mask |= que->ims; em_last_bind_cpu = CPU_NEXT(em_last_bind_cpu); } @@ -2686,43 +2579,23 @@ em_allocate_msix(struct adapter *adapter static void em_free_pci_resources(struct adapter *adapter) { + struct em_queue *que = adapter->queues; device_t dev = adapter->dev; - struct tx_ring *txr; - struct rx_ring *rxr; int rid; /* ** Release all the queue interrupt resources: */ - for (int i = 0; i < adapter->num_tx_queues; i++) { - txr = &adapter->tx_rings[i]; - /* an early abort? */ - if (txr == NULL) - break; - rid = txr->msix +1; - if (txr->tag != NULL) { - bus_teardown_intr(dev, txr->res, txr->tag); - txr->tag = NULL; + for (int i = 0; i < adapter->num_queues; i++, que++) { + rid = que->msix +1; + if (que->tag != NULL) { + bus_teardown_intr(dev, que->res, que->tag); + que->tag = NULL; } - if (txr->res != NULL) + if (que->res != NULL) bus_release_resource(dev, SYS_RES_IRQ, - rid, txr->res); - } - - for (int i = 0; i < adapter->num_tx_queues; i++) { - rxr = &adapter->rx_rings[i]; - /* an early abort? */ - if (rxr == NULL) - break; - rid = rxr->msix +1; - if (rxr->tag != NULL) { - bus_teardown_intr(dev, rxr->res, rxr->tag); - rxr->tag = NULL; - } - if (rxr->res != NULL) - bus_release_resource(dev, SYS_RES_IRQ, - rid, rxr->res); + rid, que->res); } if (adapter->linkvec) /* we are doing MSIX */ @@ -2765,19 +2638,14 @@ em_setup_msix(struct adapter *adapter) int val; /* Nearly always going to use one queue */ - adapter->num_rx_queues = 1; - adapter->num_tx_queues = 1; + adapter->num_queues = 1; /* ** Try using MSI-X for Hartwell adapters */ - if ((adapter->hw.mac.type == e1000_82574) && - (em_enable_msix == TRUE)) { + if (em_enable_msix == TRUE) { #ifdef EM_MULTIQUEUE - adapter->num_tx_queues = (em_num_tx_queues == 1) ? 1 : 2; - adapter->num_rx_queues = (em_num_rx_queues == 1) ? 1 : 2; - if (adapter->num_rx_queues > 1 || adapter->num_tx_queues > 1) - em_enable_vectors_82574(adapter); + adapter->num_queues = (em_num_queues == 1) ? 1 : 2; #endif /* Map the MSIX BAR */ int rid = PCIR_BAR(EM_MSIX_BAR); @@ -2793,12 +2661,11 @@ em_setup_msix(struct adapter *adapter) #ifdef EM_MULTIQUEUE /* We need 5 vectors in the multiqueue case */ - if (adapter->num_rx_queues > 1 || adapter->num_tx_queues > 1) { - if (val >= 5) - val = 5; + if (adapter->num_queues > 1 || adapter->num_queues > 1) { + if (val >= 3) + val = 3; else { - adapter->num_tx_queues = 1; - adapter->num_rx_queues = 1; + adapter->num_queues = 1; device_printf(adapter->dev, "Insufficient MSIX vectors for >1 queue, " "using single queue...\n"); @@ -3210,25 +3077,35 @@ static int em_allocate_queues(struct adapter *adapter) { device_t dev = adapter->dev; + struct em_queue *que = NULL; struct tx_ring *txr = NULL; struct rx_ring *rxr = NULL; int rsize, tsize, error = E1000_SUCCESS; int txconf = 0, rxconf = 0; + /* First allocate the top level queue structs */ + if (!(adapter->queues = + (struct em_queue *) malloc(sizeof(struct em_queue) * + adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + device_printf(dev, "Unable to allocate queue memory\n"); + error = ENOMEM; + goto fail; + } + /* Allocate the TX ring struct memory */ if (!(adapter->tx_rings = (struct tx_ring *) malloc(sizeof(struct tx_ring) * - adapter->num_tx_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { device_printf(dev, "Unable to allocate TX ring memory\n"); error = ENOMEM; - goto fail; + goto tx_fail; } /* Now allocate the RX */ if (!(adapter->rx_rings = (struct rx_ring *) malloc(sizeof(struct rx_ring) * - adapter->num_rx_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { device_printf(dev, "Unable to allocate RX ring memory\n"); error = ENOMEM; goto rx_fail; @@ -3241,7 +3118,7 @@ em_allocate_queues(struct adapter *adapt * possibility that things fail midcourse and we need to * undo memory gracefully */ - for (int i = 0; i < adapter->num_tx_queues; i++, txconf++) { + for (int i = 0; i < adapter->num_queues; i++, txconf++) { /* Set up some basics */ txr = &adapter->tx_rings[i]; txr->adapter = adapter; @@ -3280,7 +3157,7 @@ em_allocate_queues(struct adapter *adapt */ rsize = roundup2(adapter->num_rx_desc * sizeof(struct e1000_rx_desc), EM_DBA_ALIGN); - for (int i = 0; i < adapter->num_rx_queues; i++, rxconf++) { + for (int i = 0; i < adapter->num_queues; i++, rxconf++) { rxr = &adapter->rx_rings[i]; rxr->adapter = adapter; rxr->me = i; @@ -3309,6 +3186,16 @@ em_allocate_queues(struct adapter *adapt } } + /* + ** Finally set up the queue holding structs + */ + for (int i = 0; i < adapter->num_queues; i++) { + que = &adapter->queues[i]; + que->adapter = adapter; + que->txr = &adapter->tx_rings[i]; + que->rxr = &adapter->rx_rings[i]; + } + return (0); err_rx_desc: @@ -3323,6 +3210,8 @@ rx_fail: buf_ring_free(txr->br, M_DEVBUF); #endif free(adapter->tx_rings, M_DEVBUF); +tx_fail: + free(adapter->queues, M_DEVBUF); fail: return (error); } @@ -3468,7 +3357,7 @@ em_setup_transmit_structures(struct adap { struct tx_ring *txr = adapter->tx_rings; - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) + for (int i = 0; i < adapter->num_queues; i++, txr++) em_setup_transmit_ring(txr); return; @@ -3488,7 +3377,7 @@ em_initialize_transmit_unit(struct adapt INIT_DEBUGOUT("em_initialize_transmit_unit: begin"); - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, txr++) { u64 bus_addr = txr->txdma.dma_paddr; /* Base and Len of TX Ring */ E1000_WRITE_REG(hw, E1000_TDLEN(i), @@ -3585,7 +3474,7 @@ em_free_transmit_structures(struct adapt { struct tx_ring *txr = adapter->tx_rings; - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, txr++) { EM_TX_LOCK(txr); em_free_transmit_buffers(txr); em_dma_free(adapter, &txr->txdma); @@ -4236,7 +4125,7 @@ em_setup_receive_structures(struct adapt struct rx_ring *rxr = adapter->rx_rings; int q; - for (q = 0; q < adapter->num_rx_queues; q++, rxr++) + for (q = 0; q < adapter->num_queues; q++, rxr++) if (em_setup_receive_ring(rxr)) goto fail; @@ -4277,7 +4166,7 @@ em_free_receive_structures(struct adapte { struct rx_ring *rxr = adapter->rx_rings; - for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) { + for (int i = 0; i < adapter->num_queues; i++, rxr++) { em_free_receive_buffers(rxr); /* Free the ring memory as well */ em_dma_free(adapter, &rxr->rxdma); @@ -4397,7 +4286,7 @@ em_initialize_receive_unit(struct adapte E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); #ifdef EM_MULTIQUEUE - if (adapter->num_rx_queues > 1) { + if (adapter->num_queues > 1) { uint32_t rss_key[10]; uint32_t reta; int i; @@ -4416,7 +4305,7 @@ em_initialize_receive_unit(struct adapte reta = 0; for (i = 0; i < 4; ++i) { uint32_t q; - q = (i % adapter->num_rx_queues) << 7; + q = (i % adapter->num_queues) << 7; reta |= q << (8 * i); } for (i = 0; i < 32; ++i) @@ -4441,7 +4330,7 @@ em_initialize_receive_unit(struct adapte if (hw->mac.type == e1000_82573) E1000_WRITE_REG(hw, E1000_RDTR, 0x20); - for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) { + 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 */ @@ -4480,7 +4369,7 @@ em_initialize_receive_unit(struct adapte E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 3); } else if ((adapter->hw.mac.type == e1000_82574) && (if_getmtu(ifp) > ETHERMTU)) { - for (int i = 0; i < adapter->num_rx_queues; i++) { + for (int i = 0; i < adapter->num_queues; i++) { u32 rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); rxdctl |= 0x20; /* PTHRESH */ @@ -4542,9 +4431,10 @@ em_initialize_receive_unit(struct adapte * For polling we also now return the number of cleaned packets *********************************************************************/ static bool -em_rxeof(struct rx_ring *rxr, int count, int *done) +em_rxeof(struct em_queue *que, int count, int *done) { - struct adapter *adapter = rxr->adapter; + struct adapter *adapter = que->adapter; + struct rx_ring *rxr = que->rxr; if_t ifp = adapter->ifp; struct mbuf *mp, *sendmp; u8 status = 0; @@ -5411,6 +5301,7 @@ em_add_hw_stats(struct adapter *adapter) struct tx_ring *txr = adapter->tx_rings; struct rx_ring *rxr = adapter->rx_rings; + struct em_queue *que = adapter->queues; struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); struct sysctl_oid *tree = device_get_sysctl_tree(dev); @@ -5461,7 +5352,7 @@ em_add_hw_stats(struct adapter *adapter) CTLFLAG_RD, &adapter->hw.fc.low_water, 0, "Flow Control Low Watermark"); - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, txr++, rxr++, que++) { snprintf(namebuf, QUEUE_NAME_LEN, "queue_tx_%d", i); queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, CTLFLAG_RD, NULL, "TX Queue Name"); @@ -5477,14 +5368,13 @@ em_add_hw_stats(struct adapter *adapter) E1000_TDT(txr->me), em_sysctl_reg_handler, "IU", "Transmit Descriptor Tail"); - SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tx_irq", - CTLFLAG_RD, &txr->tx_irq, + SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "queue_irq", + CTLFLAG_RD, &que->irqs, "Queue MSI-X Transmit Interrupts"); SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "no_desc_avail", CTLFLAG_RD, &txr->no_desc_avail, "Queue No Descriptor Available"); - } - for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) { + snprintf(namebuf, QUEUE_NAME_LEN, "queue_rx_%d", i); queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, CTLFLAG_RD, NULL, "RX Queue Name"); @@ -5500,9 +5390,6 @@ em_add_hw_stats(struct adapter *adapter) E1000_RDT(rxr->me), em_sysctl_reg_handler, "IU", "Receive Descriptor Tail"); - SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "rx_irq", - CTLFLAG_RD, &rxr->rx_irq, - "Queue MSI-X Receive Interrupts"); } /* MAC stats get their own sub node */ @@ -5923,7 +5810,7 @@ em_print_debug_info(struct adapter *adap else printf("and ACTIVE\n"); - for (int i = 0; i < adapter->num_tx_queues; i++, txr++) { + for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) { device_printf(dev, "TX Queue %d ------\n", i); device_printf(dev, "hw tdh = %d, hw tdt = %d\n", E1000_READ_REG(&adapter->hw, E1000_TDH(i)), @@ -5933,8 +5820,6 @@ em_print_debug_info(struct adapter *adap txr->tx_avail); device_printf(dev, "Tx Descriptors avail failure = %ld\n", txr->no_desc_avail); - } - for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) { device_printf(dev, "RX Queue %d ------\n", i); device_printf(dev, "hw rdh = %d, hw rdt = %d\n", E1000_READ_REG(&adapter->hw, E1000_RDH(i)), @@ -5946,33 +5831,6 @@ em_print_debug_info(struct adapter *adap } } -#ifdef EM_MULTIQUEUE -/* - * 82574 only: - * Write a new value to the EEPROM increasing the number of MSIX - * vectors from 3 to 5, for proper multiqueue support. - */ -static void -em_enable_vectors_82574(struct adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - device_t dev = adapter->dev; - u16 edata; - - e1000_read_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata); - printf("Current cap: %#06x\n", edata); - if (((edata & EM_NVM_MSIX_N_MASK) >> EM_NVM_MSIX_N_SHIFT) != 4) { - device_printf(dev, "Writing to eeprom: increasing " - "reported MSIX vectors from 3 to 5...\n"); - edata &= ~(EM_NVM_MSIX_N_MASK); - edata |= 4 << EM_NVM_MSIX_N_SHIFT; - e1000_write_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata); - e1000_update_nvm_checksum(hw); - device_printf(dev, "Writing to eeprom: done\n"); - } -} -#endif - #ifdef DDB DB_COMMAND(em_dump_queue, em_ddb_dump_queue) { Modified: projects/em_mq/sys/dev/e1000/if_em.h ============================================================================== --- projects/em_mq/sys/dev/e1000/if_em.h Sat Apr 25 01:23:29 2015 (r281964) +++ projects/em_mq/sys/dev/e1000/if_em.h Sat Apr 25 01:29:40 2015 (r281965) @@ -265,14 +265,6 @@ * solve it just using this define. */ #define EM_EIAC 0x000DC -/* - * 82574 only reports 3 MSI-X vectors by default; - * defines assisting with making it report 5 are - * located here. - */ -#define EM_NVM_PCIE_CTRL 0x1B -#define EM_NVM_MSIX_N_MASK (0x7 << EM_NVM_MSIX_N_SHIFT) -#define EM_NVM_MSIX_N_SHIFT 7 /* * Bus dma allocation structure used by @@ -296,6 +288,24 @@ struct em_int_delay_info { }; /* +** Driver queue struct: this is the interrupt container +** for the associated tx and rx ring. +*/ +struct em_queue { + struct adapter *adapter; + u32 msix; /* This queue's MSIX vector */ + u32 ims; /* This queue's EIMS bit */ + u32 eitr_setting; + struct resource *res; + void *tag; + struct tx_ring *txr; + struct rx_ring *rxr; + struct task que_task; + struct taskqueue *tq; + u64 irqs; +}; + +/* * The transmit ring, one per tx queue */ struct tx_ring { @@ -303,14 +313,10 @@ struct tx_ring { struct mtx tx_mtx; char mtx_name[16]; u32 me; - u32 msix; - u32 ims; int queue_status; int watchdog_time; struct em_dma_alloc txdma; struct e1000_tx_desc *tx_base; - struct task tx_task; - struct taskqueue *tq; u32 next_avail_desc; u32 next_to_clean; struct em_buffer *tx_buffers; @@ -326,9 +332,6 @@ struct tx_ring { #endif /* Interrupt resources */ bus_dma_tag_t txtag; - void *tag; - struct resource *res; - unsigned long tx_irq; unsigned long no_desc_avail; }; @@ -338,13 +341,9 @@ struct tx_ring { struct rx_ring { struct adapter *adapter; u32 me; - u32 msix; - u32 ims; struct mtx rx_mtx; char mtx_name[16]; u32 payload; - struct task rx_task; - struct taskqueue *tq; struct e1000_rx_desc *rx_base; struct em_dma_alloc rxdma; u32 next_to_refresh; @@ -354,13 +353,10 @@ struct rx_ring { struct mbuf *lmp; /* Interrupt resources */ - void *tag; - struct resource *res; bus_dma_tag_t rxtag; bool discard; /* Soft stats */ - unsigned long rx_irq; unsigned long rx_discarded; unsigned long rx_packets; unsigned long rx_bytes; @@ -407,10 +403,10 @@ struct adapter { eventhandler_tag vlan_detach; u16 num_vlans; - /* Allow number of tx queues != num of rx_queues */ - u8 num_tx_queues; - u8 num_rx_queues; + u8 num_queues; + /* Interface queues */ + struct em_queue *queues; /* * Transmit rings: * Allocated at run time, an array of rings. @@ -428,6 +424,8 @@ struct adapter { u32 rx_process_limit; u32 rx_mbuf_sz; + u64 que_mask; + /* Management and WOL features */ u32 wol; bool has_manage; Modified: projects/em_mq/sys/dev/netmap/if_em_netmap.h ============================================================================== --- projects/em_mq/sys/dev/netmap/if_em_netmap.h Sat Apr 25 01:23:29 2015 (r281964) +++ projects/em_mq/sys/dev/netmap/if_em_netmap.h Sat Apr 25 01:29:40 2015 (r281965) @@ -45,16 +45,11 @@ em_netmap_block_tasks(struct adapter *ad { if (adapter->msix > 1) { /* MSIX */ int i; - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct em_queue *que = adapter->queues; - for (i = 0; i < adapter->num_tx_queues; i++, txr++) { - taskqueue_block(txr->tq); - taskqueue_drain(txr->tq, &txr->tx_task); - } - for (i = 0; i < adapter->num_rx_queues; i++, rxr++) { - taskqueue_block(rxr->tq); - taskqueue_drain(rxr->tq, &rxr->rx_task); + for (i = 0; i < adapter->num_queues; i++, que++) { + taskqueue_block(que->tq); + taskqueue_drain(que->tq, &que->que_task); } } else { /* legacy */ taskqueue_block(adapter->tq); @@ -68,15 +63,11 @@ static void em_netmap_unblock_tasks(struct adapter *adapter) { if (adapter->msix > 1) { - struct tx_ring *txr = adapter->tx_rings; - struct rx_ring *rxr = adapter->rx_rings; + struct em_queue *que = adapter->queues; int i; - for (i = 0; i < adapter->num_tx_queues; i++) { - taskqueue_unblock(txr->tq); - } - for (i = 0; i < adapter->num_rx_queues; i++) { - taskqueue_unblock(rxr->tq); + for (i = 0; i < adapter->num_queues; i++) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504250129.t3P1Tf3R054066>