Index: if_ix.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_ix.c,v retrieving revision 1.150 diff -u -p -r1.150 if_ix.c --- if_ix.c 24 Jan 2017 03:57:35 -0000 1.150 +++ if_ix.c 24 Jan 2017 08:31:41 -0000 @@ -133,14 +133,17 @@ void ixgbe_rxrefill(void *); void ixgbe_enable_intr(struct ix_softc *); void ixgbe_disable_intr(struct ix_softc *); void ixgbe_update_stats_counters(struct ix_softc *); -int ixgbe_txeof(struct tx_ring *); -int ixgbe_rxeof(struct ix_queue *); +void ixgbe_txeof(void *); +void ixgbe_rxeof(void *); +void ixgbe_rxfill_tmo(void *); +void ixgbe_rxfill_task(void *); void ixgbe_rx_checksum(uint32_t, struct mbuf *, uint32_t); void ixgbe_iff(struct ix_softc *); #ifdef IX_DEBUG void ixgbe_print_hw_stats(struct ix_softc *); #endif -void ixgbe_update_link_status(struct ix_softc *); +//void ixgbe_update_link_status(struct ix_softc *); +void ixgbe_update_link_status(void *); int ixgbe_get_buf(struct rx_ring *, int); int ixgbe_encap(struct tx_ring *, struct mbuf *); int ixgbe_dma_malloc(struct ix_softc *, bus_size_t, @@ -227,7 +230,6 @@ ixgbe_attach(struct device *parent, stru /* Set up the timer callout */ timeout_set(&sc->timer, ixgbe_local_timer, sc); - timeout_set(&sc->rx_refill, ixgbe_rxrefill, sc); /* Determine hardware revision */ ixgbe_identify_hardware(sc); @@ -357,7 +359,7 @@ ixgbe_detach(struct device *self, int fl if_detach(ifp); timeout_del(&sc->timer); - timeout_del(&sc->rx_refill); + //timeout_del(&sc->rx_refill); ixgbe_free_pci_resources(sc); ixgbe_free_transmit_structures(sc); @@ -383,14 +385,14 @@ ixgbe_start(struct ifqueue *ifq) { struct ifnet *ifp = ifq->ifq_if; struct ix_softc *sc = ifp->if_softc; - struct tx_ring *txr = sc->tx_rings; + struct tx_ring *txr = ifq->ifq_softc; struct mbuf *m_head; int post = 0; - if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(ifq)) - return; - if (!sc->link_up) + if (!sc->link_up) { + ifq_purge(ifq); return; + } bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, 0, txr->txdma.dma_map->dm_mapsize, @@ -521,7 +523,7 @@ ixgbe_rxrinfo(struct ix_softc *sc, struc for (i = 0; i < sc->num_queues; i++) { rxr = &sc->rx_rings[i]; ifr[n].ifr_size = sc->rx_mbuf_sz; - snprintf(ifr[n].ifr_name, sizeof(ifr[n].ifr_name), "/%d", i); + snprintf(ifr[n].ifr_name, sizeof(ifr[n].ifr_name), "%d", i); ifr[n].ifr_info = rxr->rx_ring; n++; } @@ -714,9 +716,10 @@ ixgbe_init(void *arg) timeout_add_sec(&sc->timer, 1); + /* set up interrupt routing */ + ixgbe_configure_ivars(sc); /* Set up MSI/X routing */ if (sc->msix > 1) { - ixgbe_configure_ivars(sc); /* Set up auto-mask */ if (sc->hw.mac.type == ixgbe_mac_82598EB) IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); @@ -725,8 +728,8 @@ ixgbe_init(void *arg) IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); } } else { /* Simple settings for Legacy/MSI */ - ixgbe_set_ivar(sc, 0, 0, 0); - ixgbe_set_ivar(sc, 0, 0, 1); + //ixgbe_set_ivar(sc, 0, 0, 0); + //ixgbe_set_ivar(sc, 0, 0, 1); IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); } @@ -744,7 +747,7 @@ ixgbe_init(void *arg) itr = (4000000 / IXGBE_INTS_PER_SEC) & 0xff8; if (sc->hw.mac.type != ixgbe_mac_82598EB) itr |= IXGBE_EITR_LLI_MOD | IXGBE_EITR_CNT_WDIS; - IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(0), itr); +// IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(0), itr); /* Enable power to the phy */ if (sc->hw.phy.ops.set_phy_power) @@ -917,12 +920,12 @@ int ixgbe_intr(void *arg) { struct ix_softc *sc = (struct ix_softc *)arg; - struct ix_queue *que = sc->queues; struct ifnet *ifp = &sc->arpcom.ac_if; - struct tx_ring *txr = sc->tx_rings; struct ixgbe_hw *hw = &sc->hw; uint32_t reg_eicr, mod_mask, msf_mask; - int i, refill = 0; + int i; + struct tx_ring *txr; + struct rx_ring *rxr; reg_eicr = IXGBE_READ_REG(&sc->hw, IXGBE_EICR); if (reg_eicr == 0) { @@ -930,28 +933,25 @@ ixgbe_intr(void *arg) return (0); } - if (ISSET(ifp->if_flags, IFF_RUNNING)) { - ixgbe_rxeof(que); - ixgbe_txeof(txr); - refill = 1; - } + if (ISSET(ifp->if_flags, IFF_RUNNING) && + (reg_eicr & IXGBE_EICR_RTX_QUEUE)) { + struct ix_queue *que; - if (refill) { - if (ixgbe_rxfill(que->rxr)) { - /* Advance the Rx Queue "Tail Pointer" */ - IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(que->rxr->me), - que->rxr->last_desc_filled); - } else - timeout_add(&sc->rx_refill, 1); + for (i = 0; i < sc->num_queues; i++) { + txr = &sc->tx_rings[i]; + rxr = &sc->rx_rings[i]; + que = &sc->queues[i]; + + if (ISSET(reg_eicr, 1 << rxr->msix)) + task_add(que->tq, &rxr->rxeof); + if (ISSET(reg_eicr, 1 << txr->msix)) + task_add(que->tq, &txr->txeof); + } } /* Link status change */ - if (reg_eicr & IXGBE_EICR_LSC) { - KERNEL_LOCK(); - ixgbe_update_link_status(sc); - KERNEL_UNLOCK(); - ifq_start(&ifp->if_snd); - } + if (reg_eicr & IXGBE_EICR_LSC) + task_add(systq, &sc->linkch); if (hw->mac.type != ixgbe_mac_82598EB) { if (reg_eicr & IXGBE_EICR_ECC) { @@ -1015,8 +1015,14 @@ ixgbe_intr(void *arg) KERNEL_UNLOCK(); } - for (i = 0; i < sc->num_queues; i++, que++) - ixgbe_enable_queue(sc, que->msix); +#if 1 + for (i = 0; i < sc->num_queues; i++) { + txr = &sc->tx_rings[i]; + rxr = &sc->rx_rings[i]; + ixgbe_enable_queue(sc, txr->msix); + ixgbe_enable_queue(sc, rxr->msix); + } +#endif return (1); } @@ -1343,8 +1349,9 @@ ixgbe_local_timer(void *arg) } void -ixgbe_update_link_status(struct ix_softc *sc) +ixgbe_update_link_status(void *arg) { + struct ix_softc *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; int link_state = LINK_STATE_DOWN; @@ -1407,7 +1414,7 @@ ixgbe_stop(void *arg) if (sc->hw.mac.ops.disable_tx_laser) sc->hw.mac.ops.disable_tx_laser(&sc->hw); timeout_del(&sc->timer); - timeout_del(&sc->rx_refill); + /* stop queues */ //timeout_del(&sc->rx_refill); /* reprogram the RAR[0] in case user changed it. */ ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV); @@ -1564,7 +1571,7 @@ ixgbe_allocate_pci_resources(struct ix_s sc->hw.hw_addr = (uint8_t *)os->os_membase; /* Legacy defaults */ - sc->num_queues = 1; + sc->num_queues = 8; /* XXX */ sc->hw.back = os; #ifdef notyet @@ -1607,6 +1614,7 @@ void ixgbe_setup_interface(struct ix_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; + int i; strlcpy(ifp->if_xname, sc->dev.dv_xname, IFNAMSIZ); ifp->if_softc = sc; @@ -1639,9 +1647,20 @@ ixgbe_setup_interface(struct ix_softc *s ixgbe_add_media_types(sc); ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); + task_set(&sc->linkch, ixgbe_update_link_status, sc); + if_attach(ifp); ether_ifattach(ifp); + if_attach_queues(ifp, sc->num_queues); + for (i = 0; i < sc->num_queues; i++) { + struct ifqueue *ifq = ifp->if_ifqs[i]; + struct tx_ring *txr = &sc->tx_rings[i]; + + ifq->ifq_softc = txr; + txr->ifq = ifq; + } + sc->max_frame_size = IXGBE_MAX_FRAME_SIZE; } @@ -1853,6 +1872,7 @@ ixgbe_allocate_queues(struct ix_softc *s txr = &sc->tx_rings[i]; txr->sc = sc; txr->me = i; + txr->msix = i; if (ixgbe_dma_malloc(sc, tsize, &txr->txdma, BUS_DMA_NOWAIT)) { @@ -1862,6 +1882,8 @@ ixgbe_allocate_queues(struct ix_softc *s } txr->tx_base = (union ixgbe_adv_tx_desc *)txr->txdma.dma_vaddr; bzero((void *)txr->tx_base, tsize); + + task_set(&txr->txeof, ixgbe_txeof, txr); } /* @@ -1874,6 +1896,8 @@ ixgbe_allocate_queues(struct ix_softc *s /* Set up some basics */ rxr->sc = sc; rxr->me = i; + rxr->msix = i + 8; + rxr->que = &sc->queues[i]; if (ixgbe_dma_malloc(sc, rsize, &rxr->rxdma, BUS_DMA_NOWAIT)) { @@ -1883,6 +1907,10 @@ ixgbe_allocate_queues(struct ix_softc *s } rxr->rx_base = (union ixgbe_adv_rx_desc *)rxr->rxdma.dma_vaddr; bzero((void *)rxr->rx_base, rsize); + + task_set(&rxr->rxeof, ixgbe_rxeof, rxr); + task_set(&rxr->rxfill, ixgbe_rxfill_task, rxr); + timeout_set(&rxr->refill, ixgbe_rxfill_tmo, rxr); } /* @@ -1893,6 +1921,11 @@ ixgbe_allocate_queues(struct ix_softc *s que->sc = sc; que->txr = &sc->tx_rings[i]; que->rxr = &sc->rx_rings[i]; + snprintf(que->tqname, sizeof(que->tqname), "%s.%d", + sc->dev.dv_xname, i); + que->tq = taskq_create(que->tqname, 1, IPL_NET, TASKQ_MPSAFE); + if (que->tq == NULL) + goto err_rx_desc; } return (0); @@ -2313,37 +2346,35 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, * tx_buffer is put back on the free queue. * **********************************************************************/ -int -ixgbe_txeof(struct tx_ring *txr) +void +ixgbe_txeof(void *arg) { + struct tx_ring *txr = arg; struct ix_softc *sc = txr->sc; - struct ifnet *ifp = &sc->arpcom.ac_if; + struct ifqueue *ifq = txr->ifq; + struct ifnet *ifp = ifq->ifq_if; uint32_t first, last, done, processed; uint32_t num_avail; struct ixgbe_tx_buf *tx_buffer; struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc; - if (!ISSET(ifp->if_flags, IFF_RUNNING)) - return FALSE; - if (txr->tx_avail == sc->num_tx_desc) { txr->queue_status = IXGBE_QUEUE_IDLE; - return FALSE; + return; } - membar_consumer(); - processed = 0; first = txr->next_to_clean; /* was the txt queue cleaned up in the meantime */ if (txr->tx_buffers == NULL) - return FALSE; + return; + tx_buffer = &txr->tx_buffers[first]; /* For cleanup we just use legacy struct */ tx_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[first]; last = tx_buffer->eop_index; if (last == -1) - return FALSE; + return; eop_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last]; /* @@ -2357,7 +2388,7 @@ ixgbe_txeof(struct tx_ring *txr) bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, 0, txr->txdma.dma_map->dm_mapsize, - BUS_DMASYNC_POSTREAD); + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); while (eop_desc->upper.fields.status & IXGBE_TXD_STAT_DD) { /* We clean the range of the packet */ @@ -2411,10 +2442,10 @@ ixgbe_txeof(struct tx_ring *txr) if (num_avail == sc->num_tx_desc) ifp->if_timer = 0; - if (ifq_is_oactive(&ifp->if_snd)) - ifq_restart(&ifp->if_snd); + ixgbe_enable_queue(sc, txr->msix); - return TRUE; + if (ifq_is_oactive(ifq)) + ifq_restart(ifq); } /********************************************************************* @@ -2578,20 +2609,25 @@ ixgbe_rxfill(struct rx_ring *rxr) } void -ixgbe_rxrefill(void *xsc) +ixgbe_rxfill_tmo(void *arg) { - struct ix_softc *sc = xsc; - struct ix_queue *que = sc->queues; - int s; + struct rx_ring *rxr = arg; + /* serialise the refill with rxeof */ + task_add(rxr->que->tq, &rxr->rxfill); +} - s = splnet(); - if (ixgbe_rxfill(que->rxr)) { +void +ixgbe_rxfill_task(void *arg) +{ + struct rx_ring *rxr = arg; + struct ix_softc *sc = rxr->sc; + + if (ixgbe_rxfill(rxr)) { /* Advance the Rx Queue "Tail Pointer" */ - IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(que->rxr->me), - que->rxr->last_desc_filled); + IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(rxr->me), + rxr->last_desc_filled); } else - timeout_add(&sc->rx_refill, 1); - splx(s); + timeout_add(&rxr->refill, 1); } /********************************************************************* @@ -2822,11 +2858,11 @@ ixgbe_free_receive_buffers(struct rx_rin * dma'ed into host memory to upper layer. * *********************************************************************/ -int -ixgbe_rxeof(struct ix_queue *que) +void +ixgbe_rxeof(void *arg) { - struct ix_softc *sc = que->sc; - struct rx_ring *rxr = que->rxr; + struct rx_ring *rxr = arg; + struct ix_softc *sc = rxr->sc; struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf_list ml = MBUF_LIST_INITIALIZER(); struct mbuf *mp, *sendmp; @@ -2839,7 +2875,7 @@ ixgbe_rxeof(struct ix_queue *que) int i, nextp; if (!ISSET(ifp->if_flags, IFF_RUNNING)) - return FALSE; + return; i = rxr->next_to_check; while (if_rxr_inuse(&rxr->rx_ring) > 0) { @@ -2958,12 +2994,11 @@ next_desc: } rxr->next_to_check = i; - if_input(ifp, &ml); + ixgbe_rxfill_task(rxr); - if (!(staterr & IXGBE_RXD_STAT_DD)) - return FALSE; + if_input(ifp, &ml); - return TRUE; + ixgbe_enable_queue(sc, rxr->msix); } /********************************************************************* @@ -3035,11 +3070,11 @@ void ixgbe_enable_intr(struct ix_softc *sc) { struct ixgbe_hw *hw = &sc->hw; - struct ix_queue *que = sc->queues; uint32_t mask, fwsm; int i; mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); + //mask = IXGBE_EIMS_ENABLE_MASK; /* Enable Fan Failure detection */ if (hw->device_id == IXGBE_DEV_ID_82598AT) mask |= IXGBE_EIMS_GPI_SDP1; @@ -3089,8 +3124,12 @@ ixgbe_enable_intr(struct ix_softc *sc) * allow for handling the extended (beyond 32) MSIX * vectors that can be used by 82599 */ - for (i = 0; i < sc->num_queues; i++, que++) - ixgbe_enable_queue(sc, que->msix); + for (i = 0; i < sc->num_queues; i++) { + struct rx_ring *rxr = &sc->rx_rings[i]; + struct tx_ring *txr = &sc->tx_rings[i]; + ixgbe_enable_queue(sc, rxr->msix); + ixgbe_enable_queue(sc, txr->msix); + } IXGBE_WRITE_FLUSH(hw); } @@ -3167,7 +3206,6 @@ ixgbe_set_ivar(struct ix_softc *sc, uint vector |= IXGBE_IVAR_ALLOC_VAL; switch (hw->mac.type) { - case ixgbe_mac_82598EB: if (type == -1) entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; @@ -3193,8 +3231,10 @@ ixgbe_set_ivar(struct ix_softc *sc, uint } else { /* RX/TX IVARS */ index = (16 * (entry & 1)) + (8 * type); ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1)); +printf("%s: ivar entry %u type %u pre %u=%08x\n", sc->dev.dv_xname, entry, type, IXGBE_IVAR(entry >> 1), ivar); ivar &= ~(0xFF << index); ivar |= (vector << index); +printf("%s: ivar entry %u type %u post %u=%08x\n", sc->dev.dv_xname, entry, type, IXGBE_IVAR(entry >> 1), ivar); IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar); } @@ -3206,29 +3246,24 @@ ixgbe_set_ivar(struct ix_softc *sc, uint void ixgbe_configure_ivars(struct ix_softc *sc) { -#if notyet struct ix_queue *que = sc->queues; uint32_t newitr; int i; - if (ixgbe_max_interrupt_rate > 0) - newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; - else - newitr = 0; + newitr = (4000000 / IXGBE_INTS_PER_SEC) & 0x0FF8; for (i = 0; i < sc->num_queues; i++, que++) { /* First the RX queue entry */ - ixgbe_set_ivar(sc, i, que->msix, 0); + ixgbe_set_ivar(sc, i, que->rxr->msix, 0); /* ... and the TX */ - ixgbe_set_ivar(sc, i, que->msix, 1); + ixgbe_set_ivar(sc, i, que->txr->msix, 1); /* Set an Initial EITR value */ - IXGBE_WRITE_REG(&sc->hw, - IXGBE_EITR(que->msix), newitr); + IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(que->rxr->msix), newitr); + IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(que->txr->msix), newitr); } /* For the Link interrupt */ - ixgbe_set_ivar(sc, 1, sc->linkvec, -1); -#endif +// ixgbe_set_ivar(sc, 1, sc->linkvec, -1); } /* Index: if_ix.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_ix.h,v retrieving revision 1.32 diff -u -p -r1.32 if_ix.h --- if_ix.h 21 Nov 2016 17:21:33 -0000 1.32 +++ if_ix.h 24 Jan 2017 08:31:41 -0000 @@ -151,12 +151,13 @@ struct ixgbe_dma_alloc { */ struct ix_queue { struct ix_softc *sc; - uint32_t msix; /* This queue's MSIX vector */ uint32_t eims; /* This queue's EIMS bit */ uint32_t eitr_setting; void *tag; struct tx_ring *txr; struct rx_ring *rxr; + char tqname[8]; + struct taskq *tq; /* fake multiple cpus */ }; /* @@ -165,6 +166,7 @@ struct ix_queue { struct tx_ring { struct ix_softc *sc; uint32_t me; + uint32_t msix; /* This queue's MSIX vector */ uint32_t watchdog_timer; union ixgbe_adv_tx_desc *tx_base; struct ixgbe_tx_buf *tx_buffers; @@ -183,6 +185,9 @@ struct tx_ring { uint32_t packets; /* Soft Stats */ uint64_t tx_packets; + + struct ifqueue *ifq; + struct task txeof; }; @@ -191,7 +196,9 @@ struct tx_ring { */ struct rx_ring { struct ix_softc *sc; + struct ix_queue *que; uint32_t me; + uint32_t msix; /* This queue's MSIX vector */ union ixgbe_adv_rx_desc *rx_base; struct ixgbe_dma_alloc rxdma; #if 0 @@ -215,6 +222,10 @@ struct rx_ring { uint64_t rx_bytes; uint64_t rx_discarded; uint64_t rsc_num; + + struct timeout refill; + struct task rxfill; + struct task rxeof; }; /* Our adapter structure */ @@ -229,7 +240,7 @@ struct ix_softc { struct ifmedia media; struct timeout timer; - struct timeout rx_refill; + struct task linkch; int msix; int if_flags;