From 1d7ac22714ecfd581a6eceb96151216fd68aab4d Mon Sep 17 00:00:00 2001 From: jmatthew Date: Wed, 30 Mar 2022 00:25:27 +0000 Subject: [PATCH] If enough MSI-X vectors are available, set up multiple tx and rx queues. In multi-vector mode, the MSI-X vector number is the same as the irq number on the nic, so use vector/irq 0 for link interrupts, then assign one to each pair of rx and tx queues. We don't configure RSS yet, so packets will only be received on the first queue, but they can be transmitted on any queue. ok dlg@ --- sys/dev/pci/files.pci | 4 +- sys/dev/pci/if_aq_pci.c | 103 +++++++++++++++++++++++++++++++++++----- 2 files changed, 94 insertions(+), 13 deletions(-) diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index e4611434165..25066c22d75 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.357 2021/10/31 14:52:57 patrick Exp $ +# $OpenBSD: files.pci,v 1.358 2022/03/30 00:25:27 jmatthew Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -231,7 +231,7 @@ attach sili at pci with sili_pci file dev/pci/sili_pci.c sili_pci # Aquantia/Atlantic 10-Gigabit Ethernet -device aq: ether, ifnet, ifmedia, mii +device aq: ether, ifnet, ifmedia, mii, intrmap attach aq at pci file dev/pci/if_aq_pci.c aq diff --git a/sys/dev/pci/if_aq_pci.c b/sys/dev/pci/if_aq_pci.c index f7cf6339c66..0b3ba3b3a5f 100644 --- a/sys/dev/pci/if_aq_pci.c +++ b/sys/dev/pci/if_aq_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_aq_pci.c,v 1.12 2022/03/26 06:04:20 jmatthew Exp $ */ +/* $OpenBSD: if_aq_pci.c,v 1.13 2022/03/30 00:25:27 jmatthew Exp $ */ /* $NetBSD: if_aq.c,v 1.27 2021/06/16 00:21:18 riastradh Exp $ */ /* @@ -87,6 +87,7 @@ #include #include #include +#include #include #include @@ -846,6 +847,8 @@ void aq_attach(struct device *, struct device *, void *); int aq_detach(struct device *, int); int aq_activate(struct device *, int); int aq_intr(void *); +int aq_intr_link(void *); +int aq_intr_queue(void *); void aq_global_software_reset(struct aq_softc *); int aq_fw_reset(struct aq_softc *); int aq_mac_soft_reset(struct aq_softc *, enum aq_fw_bootloader_mode *); @@ -857,7 +860,7 @@ int aq_hw_init_ucp(struct aq_softc *); int aq_fw_downld_dwords(struct aq_softc *, uint32_t, uint32_t *, uint32_t); int aq_get_mac_addr(struct aq_softc *); int aq_hw_reset(struct aq_softc *); -int aq_hw_init(struct aq_softc *, int); +int aq_hw_init(struct aq_softc *, int, int); void aq_hw_qos_set(struct aq_softc *); void aq_l3_filter_set(struct aq_softc *); void aq_hw_init_tx_path(struct aq_softc *); @@ -971,7 +974,7 @@ aq_attach(struct device *parent, struct device *self, void *aux) pcitag_t tag; struct ifnet *ifp = &sc->sc_arpcom.ac_if; int txmin, txmax, rxmin, rxmax; - int irqmode; + int irqmode, irqnum; int i; mtx_init(&sc->sc_mpi_mutex, IPL_NET); @@ -999,8 +1002,24 @@ aq_attach(struct device *parent, struct device *self, void *aux) } sc->sc_nqueues = 1; + sc->sc_linkstat_irq = AQ_LINKSTAT_IRQ; + isr = aq_intr; + irqnum = 0; if (pci_intr_map_msix(pa, 0, &ih) == 0) { + int nmsix = pci_intr_msix_count(pa); + if (nmsix > 1) { + nmsix--; + sc->sc_intrmap = intrmap_create(&sc->sc_dev, + nmsix, AQ_MAXQ, INTRMAP_POWEROF2); + sc->sc_nqueues = intrmap_count(sc->sc_intrmap); + KASSERT(sc->sc_nqueues > 0); + KASSERT(powerof2(sc->sc_nqueues)); + + sc->sc_linkstat_irq = 0; + isr = aq_intr_link; + irqnum++; + } irqmode = AQ_INTR_CTRL_IRQMODE_MSIX; } else if (pci_intr_map_msi(pa, &ih) == 0) { irqmode = AQ_INTR_CTRL_IRQMODE_MSI; @@ -1011,13 +1030,15 @@ aq_attach(struct device *parent, struct device *self, void *aux) return; } - isr = aq_intr; sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET | IPL_MPSAFE, isr, sc, self->dv_xname); intrstr = pci_intr_string(pa->pa_pc, ih); if (intrstr) printf(": %s", intrstr); + if (sc->sc_nqueues > 1) + printf(", %d queues", sc->sc_nqueues); + if (aq_fw_reset(sc)) return; @@ -1035,7 +1056,7 @@ aq_attach(struct device *parent, struct device *self, void *aux) if (aq_get_mac_addr(sc)) return; - if (aq_hw_init(sc, irqmode)) + if (aq_hw_init(sc, irqmode, (sc->sc_nqueues > 1))) return; sc->sc_media_type = aqp->aq_media_type; @@ -1117,11 +1138,11 @@ aq_attach(struct device *parent, struct device *self, void *aux) struct aq_queues *aq = &sc->sc_queues[i]; struct aq_rxring *rx = &aq->q_rx; struct aq_txring *tx = &aq->q_tx; + pci_intr_handle_t ih; aq->q_sc = sc; aq->q_index = i; rx->rx_q = i; - rx->rx_irq = i * 2; rx->rx_ifiq = ifp->if_iqs[i]; rx->rx_m_head = NULL; rx->rx_m_tail = &rx->rx_m_head; @@ -1130,12 +1151,33 @@ aq_attach(struct device *parent, struct device *self, void *aux) timeout_set(&rx->rx_refill, aq_refill, rx); tx->tx_q = i; - tx->tx_irq = rx->rx_irq + 1; tx->tx_ifq = ifp->if_ifqs[i]; ifp->if_ifqs[i]->ifq_softc = aq; + snprintf(aq->q_name, sizeof(aq->q_name), "%s:%u", + DEVNAME(sc), i); + if (sc->sc_nqueues > 1) { - /* map msix */ + if (pci_intr_map_msix(pa, irqnum, &ih)) { + printf("%s: unable to map msi-x vector %d\n", + DEVNAME(sc), irqnum); + return; + } + + aq->q_ihc = pci_intr_establish_cpu(sc->sc_pc, ih, + IPL_NET | IPL_MPSAFE, intrmap_cpu(sc->sc_intrmap, i), + aq_intr_queue, aq, aq->q_name); + if (aq->q_ihc == NULL) { + printf("%s: unable to establish interrupt %d\n", + DEVNAME(sc), irqnum); + return; + } + rx->rx_irq = irqnum; + tx->tx_irq = irqnum; + irqnum++; + } else { + rx->rx_irq = irqnum++; + tx->tx_irq = irqnum++; } AQ_WRITE_REG_BIT(sc, TX_INTR_MODERATION_CTL_REG(i), @@ -1749,7 +1791,7 @@ aq_hw_l3_filter_set(struct aq_softc *sc) } int -aq_hw_init(struct aq_softc *sc, int irqmode) +aq_hw_init(struct aq_softc *sc, int irqmode, int multivec) { uint32_t v; @@ -1776,7 +1818,7 @@ aq_hw_init(struct aq_softc *sc, int irqmode) /* Enable interrupt */ AQ_WRITE_REG(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_RESET_DIS); - AQ_WRITE_REG_BIT(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_MULTIVEC, 0); + AQ_WRITE_REG_BIT(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_MULTIVEC, multivec); AQ_WRITE_REG_BIT(sc, AQ_INTR_CTRL_REG, AQ_INTR_CTRL_IRQMODE, irqmode); @@ -1788,7 +1830,6 @@ aq_hw_init(struct aq_softc *sc, int irqmode) ); /* link interrupt */ - sc->sc_linkstat_irq = AQ_LINKSTAT_IRQ; AQ_WRITE_REG(sc, AQ_GEN_INTR_MAP_REG(3), (1 << 7) | sc->sc_linkstat_irq); @@ -2460,6 +2501,46 @@ aq_start(struct ifqueue *ifq) } } +int +aq_intr_queue(void *arg) +{ + struct aq_queues *aq = arg; + struct aq_softc *sc = aq->q_sc; + uint32_t status; + uint32_t clear; + + status = AQ_READ_REG(sc, AQ_INTR_STATUS_REG); + clear = 0; + if (status & (1 << aq->q_tx.tx_irq)) { + clear |= (1 << aq->q_tx.tx_irq); + aq_txeof(sc, &aq->q_tx); + } + + if (status & (1 << aq->q_rx.rx_irq)) { + clear |= (1 << aq->q_rx.rx_irq); + aq_rxeof(sc, &aq->q_rx); + } + + AQ_WRITE_REG(sc, AQ_INTR_STATUS_CLR_REG, clear); + return (clear != 0); +} + +int +aq_intr_link(void *arg) +{ + struct aq_softc *sc = arg; + uint32_t status; + + status = AQ_READ_REG(sc, AQ_INTR_STATUS_REG); + if (status & (1 << sc->sc_linkstat_irq)) { + aq_update_link_status(sc); + AQ_WRITE_REG(sc, AQ_INTR_STATUS_REG, (1 << sc->sc_linkstat_irq)); + return 1; + } + + return 0; +} + int aq_intr(void *arg) { -- 2.20.1