diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2017-12-15 05:56:09 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2017-12-15 05:56:09 +0000 |
commit | c7b8d187d3e8a422ab83c5b5d4d534a3d8139c88 (patch) | |
tree | f31478b7db6c266a7cfe453369d1087254f6393d /sys | |
parent | 0d15d4e2c2a6c1983e2d99d53adbb502b6f8afce (diff) |
put where im up to into the tree so jmatthew@ can look at it.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_ixl.c | 510 |
1 files changed, 367 insertions, 143 deletions
diff --git a/sys/dev/pci/if_ixl.c b/sys/dev/pci/if_ixl.c index 1afb970fa5b..980214dc484 100644 --- a/sys/dev/pci/if_ixl.c +++ b/sys/dev/pci/if_ixl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ixl.c,v 1.4 2017/11/29 05:09:59 dlg Exp $ */ +/* $OpenBSD: if_ixl.c,v 1.5 2017/12/15 05:56:08 dlg Exp $ */ /* * Copyright (c) 2013-2015, Intel Corporation @@ -88,8 +88,28 @@ #define I40E_QTX_CTL_VM_QUEUE 0x1 #define I40E_QTX_CTL_PF_QUEUE 0x2 +#define I40E_QUEUE_TYPE_EOL 0x7ff +#define I40E_INTR_NOTX_QUEUE 0 + +#define I40E_QUEUE_TYPE_RX 0x0 +#define I40E_QUEUE_TYPE_TX 0x1 +#define I40E_QUEUE_TYPE_PE_CEQ 0x2 +#define I40E_QUEUE_TYPE_UNKNOWN 0x3 + +#define I40E_ITR_INDEX_RX 0x0 +#define I40E_ITR_INDEX_TX 0x1 +#define I40E_ITR_INDEX_OTHER 0x2 +#define I40E_ITR_INDEX_NONE 0x3 + #include <dev/pci/if_ixlreg.h> +#define I40E_INTR_NOTX_QUEUE 0 +#define I40E_INTR_NOTX_INTR 0 +#define I40E_INTR_NOTX_RX_QUEUE 0 +#define I40E_INTR_NOTX_TX_QUEUE 1 +#define I40E_INTR_NOTX_RX_MASK I40E_PFINT_ICR0_QUEUE_0_MASK +#define I40E_INTR_NOTX_TX_MASK I40E_PFINT_ICR0_QUEUE_1_MASK + struct ixl_aq_desc { uint16_t iaq_flags; #define IXL_AQ_DD (1U << 0) @@ -1015,6 +1035,7 @@ struct ixl_softc { uint16_t sc_veb_seid; /* le */ uint16_t sc_vsi_number; /* le */ uint16_t sc_seid; + unsigned int sc_base_queue; struct ixl_dmamem sc_vsi; @@ -1034,16 +1055,16 @@ struct ixl_softc { unsigned int sc_arq_prod; unsigned int sc_arq_cons; - struct ixl_dmamem sc_hmc; + struct ixl_dmamem sc_hmc_sd; + struct ixl_dmamem sc_hmc_pd; struct ixl_hmc_entry sc_hmc_entries[IXL_HMC_COUNT]; unsigned int sc_nrings; unsigned int sc_tx_ring_ndescs; unsigned int sc_rx_ring_ndescs; - unsigned int sc_nqueues; /* must be a power of 2 */ + unsigned int sc_nqueues; /* 1 << sc_nqueues */ - struct ixl_tx_ring *sc_tx_ring; struct ixl_rx_ring *sc_rx_ring; }; #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname) @@ -1085,6 +1106,7 @@ static int ixl_phy_mask_ints(struct ixl_softc *); static int ixl_get_phy_abilities(struct ixl_softc *, uint64_t *); static int ixl_restart_an(struct ixl_softc *); static int ixl_hmc(struct ixl_softc *); +static void ixl_hmc_free(struct ixl_softc *); static int ixl_get_vsi(struct ixl_softc *); static int ixl_set_vsi(struct ixl_softc *); static int ixl_get_link_status(struct ixl_softc *); @@ -1110,9 +1132,10 @@ static int ixl_iff(struct ixl_softc *); static struct ixl_tx_ring * ixl_txr_alloc(struct ixl_softc *, unsigned int); +static void ixl_txr_qdis(struct ixl_softc *, struct ixl_tx_ring *, int); static void ixl_txr_config(struct ixl_softc *, struct ixl_tx_ring *); -static int ixl_txr_enable(struct ixl_softc *, struct ixl_tx_ring *); -static int ixl_txr_disable(struct ixl_softc *, struct ixl_tx_ring *); +static int ixl_txr_enabled(struct ixl_softc *, struct ixl_tx_ring *); +static int ixl_txr_disabled(struct ixl_softc *, struct ixl_tx_ring *); static void ixl_txr_unconfig(struct ixl_softc *, struct ixl_tx_ring *); static void ixl_txr_clean(struct ixl_softc *, struct ixl_tx_ring *); static void ixl_txr_free(struct ixl_softc *, struct ixl_tx_ring *); @@ -1121,8 +1144,8 @@ static int ixl_txeof(struct ixl_softc *, struct ixl_tx_ring *); static struct ixl_rx_ring * ixl_rxr_alloc(struct ixl_softc *, unsigned int); static void ixl_rxr_config(struct ixl_softc *, struct ixl_rx_ring *); -static int ixl_rxr_enable(struct ixl_softc *, struct ixl_rx_ring *); -static int ixl_rxr_disable(struct ixl_softc *, struct ixl_rx_ring *); +static int ixl_rxr_enabled(struct ixl_softc *, struct ixl_rx_ring *); +static int ixl_rxr_disabled(struct ixl_softc *, struct ixl_rx_ring *); static void ixl_rxr_unconfig(struct ixl_softc *, struct ixl_rx_ring *); static void ixl_rxr_clean(struct ixl_softc *, struct ixl_rx_ring *); static void ixl_rxr_free(struct ixl_softc *, struct ixl_rx_ring *); @@ -1241,6 +1264,8 @@ static const struct ixl_aq_regs ixl_vf_aq_regs = { I40E_PFINT_DYN_CTL0_CLEARPBA_MASK | \ (IXL_NOITR << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)) +#define ixl_nqueues(_sc) (1 << (_sc)->sc_nqueues) + #ifdef __LP64__ #define ixl_dmamem_hi(_ixm) (uint32_t)(IXL_DMA_DVA(_ixm) >> 32) #else @@ -1307,7 +1332,7 @@ ixl_attach(struct device *parent, struct device *self, void *aux) sc->sc_dmat = pa->pa_dmat; sc->sc_aq_regs = &ixl_pf_aq_regs; /* VF? */ - sc->sc_nqueues = 1; + sc->sc_nqueues = 0; /* 1 << 0 is 1 queue */ sc->sc_tx_ring_ndescs = 1024; sc->sc_rx_ring_ndescs = 1024; @@ -1318,6 +1343,11 @@ ixl_attach(struct device *parent, struct device *self, void *aux) return; } + sc->sc_base_queue = (ixl_rd(sc, I40E_PFLAN_QALLOC) & + I40E_PFLAN_QALLOC_FIRSTQ_MASK) >> + I40E_PFLAN_QALLOC_FIRSTQ_SHIFT; + printf(" %u", sc->sc_base_queue); + ixl_clear_hw(sc); if (ixl_pf_reset(sc) == -1) { @@ -1443,38 +1473,38 @@ ixl_attach(struct device *parent, struct device *self, void *aux) if (ixl_lldp_shut(sc) != 0) { /* error printed by ixl_lldp_shut */ - goto shutdown; + goto free_hmc; } if (ixl_phy_mask_ints(sc) != 0) { /* error printed by ixl_phy_mask_ints */ - goto shutdown; + goto free_hmc; } if (ixl_restart_an(sc) != 0) { /* error printed by ixl_restart_an */ - goto shutdown; + goto free_hmc; } if (ixl_get_switch_config(sc) != 0) { /* error printed by ixl_get_switch_config */ - goto shutdown; + goto free_hmc; } if (ixl_get_phy_abilities(sc, &phy_types) != 0) { /* error printed by ixl_get_phy_abilities */ - goto shutdown; + goto free_hmc; } if (ixl_get_link_status(sc) != 0) { /* error printed by ixl_get_link_status */ - goto shutdown; + goto free_hmc; } if (ixl_dmamem_alloc(sc, &sc->sc_vsi, sizeof(struct ixl_aq_vsi_data), 8) != 0) { printf("%s: unable to allocate VSI data\n", DEVNAME(sc)); - goto shutdown; + goto free_hmc; } if (ixl_get_vsi(sc) != 0) { @@ -1521,7 +1551,7 @@ ixl_attach(struct device *parent, struct device *self, void *aux) if_attach(ifp); ether_ifattach(ifp); - if_attach_queues(ifp, sc->sc_nqueues); + if_attach_queues(ifp, ixl_nqueues(sc)); ixl_wr(sc, I40E_PFINT_ICR0_ENA, I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK | @@ -1535,6 +1565,8 @@ ixl_attach(struct device *parent, struct device *self, void *aux) free_vsi: ixl_dmamem_free(sc, &sc->sc_vsi); +free_hmc: + ixl_hmc_free(sc); shutdown: ixl_wr(sc, sc->sc_aq_regs->atq_head, 0); ixl_wr(sc, sc->sc_aq_regs->arq_head, 0); @@ -1618,19 +1650,6 @@ ixl_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) /* FALLTHROUGH */ case SIOCSIFFLAGS: -#if 0 - switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { - case IFF_UP|IFF_RUNNING: - error = ENETRESET; - break; - case IFF_UP: - error = ixl_up(sc); - break; - case IFF_RUNNING: - error = ixl_down(sc); - break; - } -#else if (ISSET(ifp->if_flags, IFF_UP)) { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = ENETRESET; @@ -1640,7 +1659,6 @@ ixl_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (ISSET(ifp->if_flags, IFF_RUNNING)) error = ixl_down(sc); } -#endif break; case SIOCGIFMEDIA: @@ -1668,7 +1686,7 @@ ixl_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) static inline void * ixl_hmc_kva(struct ixl_softc *sc, unsigned int type, unsigned int i) { - uint8_t *kva = IXL_DMA_KVA(&sc->sc_hmc); + uint8_t *kva = IXL_DMA_KVA(&sc->sc_hmc_pd); struct ixl_hmc_entry *e = &sc->sc_hmc_entries[type]; if (i >= e->hmc_count) @@ -1692,38 +1710,130 @@ static int ixl_up(struct ixl_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; - int rv; + struct ixl_rx_ring *rxr; + struct ixl_tx_ring *txr; + unsigned int nqueues, i; + uint32_t reg; + int rv = ENOMEM; + + nqueues = ixl_nqueues(sc); + KASSERT(nqueues == 1); /* XXX */ + + /* allocation is the only thing that can fail, so do it up front */ + for (i = 0; i < nqueues; i++) { + rxr = ixl_rxr_alloc(sc, i); + if (rxr == NULL) + goto free; + + txr = ixl_txr_alloc(sc, 0); + if (txr == NULL) { + ixl_rxr_free(sc, rxr); + goto free; + } - sc->sc_rx_ring = ixl_rxr_alloc(sc, 0); - if (sc->sc_rx_ring == NULL) { - rv = ENOMEM; - goto ret; + sc->sc_rx_ring = rxr; + ifp->if_ifqs[i]->ifq_softc = txr; } - sc->sc_tx_ring = ixl_txr_alloc(sc, 0); - if (sc->sc_tx_ring == NULL) { - rv = ENOMEM; - goto free_rxr; + /* XXX wait 50ms from completion of last RX queue disable */ + + for (i = 0; i < nqueues; i++) { + rxr = sc->sc_rx_ring; + txr = ifp->if_ifqs[i]->ifq_softc; + + ixl_rxfill(sc, rxr); + + ixl_txr_qdis(sc, txr, 1); + + ixl_rxr_config(sc, rxr); + ixl_txr_config(sc, txr); + + ixl_wr(sc, I40E_QTX_CTL(i), I40E_QTX_CTL_PF_QUEUE | + (sc->sc_pf_id << I40E_QTX_CTL_PF_INDX_SHIFT)); + + ixl_wr(sc, rxr->rxr_tail, 0); + ixl_wr(sc, rxr->rxr_tail, rxr->rxr_prod); + + reg = ixl_rd(sc, I40E_QRX_ENA(i)); + SET(reg, I40E_QRX_ENA_QENA_REQ_MASK); + ixl_wr(sc, I40E_QRX_ENA(i), reg); + + reg = ixl_rd(sc, I40E_QTX_ENA(i)); + SET(reg, I40E_QTX_ENA_QENA_REQ_MASK); + ixl_wr(sc, I40E_QTX_ENA(i), reg); } - ixl_rxr_config(sc, sc->sc_rx_ring); - ixl_txr_config(sc, sc->sc_tx_ring); + for (i = 0; i < nqueues; i++) { + rxr = sc->sc_rx_ring; + txr = ifp->if_ifqs[i]->ifq_softc; - ixl_rxfill(sc, sc->sc_rx_ring); - ixl_wr(sc, I40E_QTX_CTL(0), I40E_QTX_CTL_PF_QUEUE | - (sc->sc_pf_id << I40E_QTX_CTL_PF_INDX_SHIFT)); + if (ixl_rxr_enabled(sc, rxr) != 0) + goto down; - (void)ixl_rxr_enable(sc, sc->sc_rx_ring); - (void)ixl_txr_enable(sc, sc->sc_tx_ring); + if (ixl_txr_enabled(sc, txr) != 0) + goto down; + } SET(ifp->if_flags, IFF_RUNNING); - return (0); +#if 0 + reg = ixl_rd(sc, I40E_QINT_RQCTL(I40E_INTR_NOTX_QUEUE)); + SET(reg, I40E_QINT_RQCTL_CAUSE_ENA_MASK); + ixl_wr(sc, I40E_QINT_RQCTL(I40E_INTR_NOTX_QUEUE), reg); + + reg = ixl_rd(sc, I40E_QINT_TQCTL(I40E_INTR_NOTX_QUEUE)); + SET(reg, I40E_QINT_TQCTL_CAUSE_ENA_MASK); + ixl_wr(sc, I40E_QINT_TQCTL(I40E_INTR_NOTX_QUEUE), reg); +#endif + + ixl_wr(sc, I40E_PFINT_LNKLST0, + (I40E_INTR_NOTX_QUEUE << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT) | + (I40E_QUEUE_TYPE_RX << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)); + + ixl_wr(sc, I40E_QINT_RQCTL(I40E_INTR_NOTX_QUEUE), + (I40E_INTR_NOTX_INTR << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) | + (I40E_ITR_INDEX_RX << I40E_QINT_RQCTL_ITR_INDX_SHIFT) | + (I40E_INTR_NOTX_RX_QUEUE << I40E_QINT_RQCTL_MSIX0_INDX_SHIFT) | + (I40E_INTR_NOTX_QUEUE << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) | + (I40E_QUEUE_TYPE_TX << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)); + + ixl_wr(sc, I40E_QINT_TQCTL(I40E_INTR_NOTX_QUEUE), + (I40E_INTR_NOTX_INTR << I40E_QINT_TQCTL_MSIX_INDX_SHIFT) | + (I40E_ITR_INDEX_TX << I40E_QINT_TQCTL_ITR_INDX_SHIFT) | + (I40E_INTR_NOTX_TX_QUEUE << I40E_QINT_TQCTL_MSIX0_INDX_SHIFT) | + (I40E_QUEUE_TYPE_EOL << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT) | + (I40E_QUEUE_TYPE_RX << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)); + + ixl_wr(sc, I40E_PFINT_ITR0(0), 0x7a); + ixl_wr(sc, I40E_PFINT_ITR0(1), 0x7a); + ixl_wr(sc, I40E_PFINT_ITR0(2), 0); + + printf("%s: info %08x data %08x\n", DEVNAME(sc), + ixl_rd(sc, I40E_PFHMC_ERRORINFO), + ixl_rd(sc, I40E_PFHMC_ERRORDATA)); + + return (ENETRESET); -free_rxr: - ixl_rxr_free(sc, sc->sc_rx_ring); -ret: +free: + for (i = 0; i < nqueues; i++) { + rxr = sc->sc_rx_ring; + txr = ifp->if_ifqs[i]->ifq_softc; + + if (rxr == NULL) { + /* + * tx and rx get set at the same time, so if one + * is NULL, the other is too. + */ + continue; + } + + ixl_txr_free(sc, txr); + ixl_rxr_free(sc, rxr); + } return (rv); +down: + ixl_down(sc); + return (ETIMEDOUT); } static int @@ -1734,8 +1844,10 @@ ixl_iff(struct ixl_softc *sc) struct ixl_aq_desc *iaq; struct ixl_aq_vsi_promisc_param *param; +#if 0 if (!ISSET(ifp->if_flags, IFF_ALLMULTI)) return (0); +#endif if (!ISSET(ifp->if_flags, IFF_RUNNING)) return (0); @@ -1747,10 +1859,10 @@ ixl_iff(struct ixl_softc *sc) param = (struct ixl_aq_vsi_promisc_param *)&iaq->iaq_param; param->flags = htole16(IXL_AQ_VSI_PROMISC_FLAG_BCAST); - if (ISSET(ifp->if_flags, IFF_PROMISC)) { +// if (ISSET(ifp->if_flags, IFF_PROMISC)) { param->flags |= htole16(IXL_AQ_VSI_PROMISC_FLAG_UCAST | IXL_AQ_VSI_PROMISC_FLAG_MCAST); - } +// } param->valid_flags = htole16(IXL_AQ_VSI_PROMISC_FLAG_UCAST | IXL_AQ_VSI_PROMISC_FLAG_MCAST | IXL_AQ_VSI_PROMISC_FLAG_BCAST); param->seid = sc->sc_seid; @@ -1766,20 +1878,92 @@ ixl_iff(struct ixl_softc *sc) static int ixl_down(struct ixl_softc *sc) { - (void)ixl_txr_disable(sc, sc->sc_tx_ring); - (void)ixl_rxr_disable(sc, sc->sc_rx_ring); + struct ifnet *ifp = &sc->sc_ac.ac_if; + struct ixl_rx_ring *rxr; + struct ixl_tx_ring *txr; + unsigned int nqueues, i; + uint32_t reg; + int error = 0; + + nqueues = ixl_nqueues(sc); + + CLR(ifp->if_flags, IFF_RUNNING); + + /* mask interrupts */ + reg = ixl_rd(sc, I40E_QINT_RQCTL(I40E_INTR_NOTX_QUEUE)); + CLR(reg, I40E_QINT_RQCTL_CAUSE_ENA_MASK); + ixl_wr(sc, I40E_QINT_RQCTL(I40E_INTR_NOTX_QUEUE), reg); - ixl_txr_unconfig(sc, sc->sc_tx_ring); - ixl_rxr_unconfig(sc, sc->sc_rx_ring); + reg = ixl_rd(sc, I40E_QINT_TQCTL(I40E_INTR_NOTX_QUEUE)); + CLR(reg, I40E_QINT_TQCTL_CAUSE_ENA_MASK); + ixl_wr(sc, I40E_QINT_TQCTL(I40E_INTR_NOTX_QUEUE), reg); - ixl_txr_clean(sc, sc->sc_tx_ring); - ixl_rxr_clean(sc, sc->sc_rx_ring); + ixl_wr(sc, I40E_PFINT_LNKLST0, I40E_QUEUE_TYPE_EOL); + + /* make sure the no hw generated work is still in flight */ + intr_barrier(sc->sc_ihc); + for (i = 0; i < nqueues; i++) { + rxr = sc->sc_rx_ring; + txr = ifp->if_ifqs[i]->ifq_softc; + + ixl_txr_qdis(sc, txr, 0); + + if (!timeout_del(&rxr->rxr_refill)) + timeout_barrier(&rxr->rxr_refill); + } + + /* XXX wait at least 400 usec for all tx queues in one go */ + delay(500); + + for (i = 0; i < nqueues; i++) { + rxr = sc->sc_rx_ring; + txr = ifp->if_ifqs[i]->ifq_softc; + + reg = ixl_rd(sc, I40E_QTX_ENA(i)); + CLR(reg, I40E_QTX_ENA_QENA_REQ_MASK); + ixl_wr(sc, I40E_QTX_ENA(i), reg); + + reg = ixl_rd(sc, I40E_QRX_ENA(i)); + CLR(reg, I40E_QRX_ENA_QENA_REQ_MASK); + ixl_wr(sc, I40E_QRX_ENA(i), reg); + } - ixl_txr_free(sc, sc->sc_tx_ring); - ixl_rxr_free(sc, sc->sc_rx_ring); + for (i = 0; i < nqueues; i++) { + rxr = sc->sc_rx_ring; + txr = ifp->if_ifqs[i]->ifq_softc; - sc->sc_rx_ring = NULL; - sc->sc_tx_ring = NULL; + if (ixl_txr_disabled(sc, txr) != 0) + error = ETIMEDOUT; + + if (ixl_rxr_disabled(sc, rxr) != 0) + error = ETIMEDOUT; + } + + if (error) { + printf("%s: info %08x data %08x\n", DEVNAME(sc), + ixl_rd(sc, I40E_PFHMC_ERRORINFO), + ixl_rd(sc, I40E_PFHMC_ERRORDATA)); + + printf("%s: failed to shut down rings\n", DEVNAME(sc)); + return (error); + } + + for (i = 0; i < nqueues; i++) { + rxr = sc->sc_rx_ring; + txr = ifp->if_ifqs[i]->ifq_softc; + + ixl_txr_unconfig(sc, txr); + ixl_rxr_unconfig(sc, rxr); + + ixl_txr_clean(sc, txr); + ixl_rxr_clean(sc, rxr); + + ixl_txr_free(sc, txr); + ixl_rxr_free(sc, rxr); + + sc->sc_rx_ring = NULL; + ifp->if_ifqs[i]->ifq_softc = NULL; + } return (0); } @@ -1820,6 +2004,7 @@ ixl_txr_alloc(struct ixl_softc *sc, unsigned int qid) txr->txr_cons = txr->txr_prod = 0; txr->txr_maps = maps; + txr->txr_tail = I40E_QTX_TAIL(qid); txr->txr_qid = qid; @@ -1844,6 +2029,25 @@ free: } static void +ixl_txr_qdis(struct ixl_softc *sc, struct ixl_tx_ring *txr, int enable) +{ + unsigned int qid; + bus_size_t reg; + uint32_t r; + + qid = txr->txr_qid + sc->sc_base_queue; + reg = I40E_GLLAN_TXPRE_QDIS(qid / 128); + qid %= 128; + + r = ixl_rd(sc, reg); + CLR(r, I40E_GLLAN_TXPRE_QDIS_QINDX_MASK); + SET(r, qid << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT); + SET(r, enable ? I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK : + I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK); + ixl_wr(sc, reg, r); +} + +static void ixl_txr_config(struct ixl_softc *sc, struct ixl_tx_ring *txr) { struct ixl_hmc_txq txq; @@ -1854,15 +2058,15 @@ ixl_txr_config(struct ixl_softc *sc, struct ixl_tx_ring *txr) txq.head = htole16(0); txq.new_context = 1; htolem64(&txq.base, - IXL_DMA_DVA(&sc->sc_tx_ring->txr_mem) / IXL_HMC_TXQ_BASE_UNIT); + IXL_DMA_DVA(&txr->txr_mem) / IXL_HMC_TXQ_BASE_UNIT); txq.head_wb_ena = IXL_HMC_TXQ_DESC_WB; htolem16(&txq.qlen, sc->sc_tx_ring_ndescs); + txq.tphrdesc_ena = 0; + txq.tphrpacket_ena = 0; + txq.tphwdesc_ena = 0; txq.rdylist = data->qs_handle[0]; - txq.tphrdesc_ena = 1; - txq.tphrpacket_ena = 1; - txq.tphwdesc_ena = 1; - hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_TX, 0); + hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_TX, txr->txr_qid); memset(hmc, 0, ixl_hmc_len(sc, IXL_HMC_LAN_TX)); ixl_hmc_pack(hmc, &txq, ixl_hmc_pack_txq, nitems(ixl_hmc_pack_txq)); } @@ -1872,7 +2076,7 @@ ixl_txr_unconfig(struct ixl_softc *sc, struct ixl_tx_ring *txr) { void *hmc; - hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_TX, 0); + hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_TX, txr->txr_qid); memset(hmc, 0, ixl_hmc_len(sc, IXL_HMC_LAN_TX)); } @@ -1901,15 +2105,12 @@ ixl_txr_clean(struct ixl_softc *sc, struct ixl_tx_ring *txr) } static int -ixl_txr_enable(struct ixl_softc *sc, struct ixl_tx_ring *txr) +ixl_txr_enabled(struct ixl_softc *sc, struct ixl_tx_ring *txr) { bus_size_t ena = I40E_QTX_ENA(txr->txr_qid); uint32_t reg; int i; - reg = ixl_rd(sc, ena); - SET(reg, I40E_QTX_ENA_QENA_REQ_MASK | I40E_QTX_ENA_QENA_STAT_MASK); - ixl_wr(sc, ena, reg); for (i = 0; i < 10; i++) { reg = ixl_rd(sc, ena); if (ISSET(reg, I40E_QTX_ENA_QENA_STAT_MASK)) @@ -1922,18 +2123,15 @@ ixl_txr_enable(struct ixl_softc *sc, struct ixl_tx_ring *txr) } static int -ixl_txr_disable(struct ixl_softc *sc, struct ixl_tx_ring *txr) +ixl_txr_disabled(struct ixl_softc *sc, struct ixl_tx_ring *txr) { bus_size_t ena = I40E_QTX_ENA(txr->txr_qid); uint32_t reg; int i; - reg = ixl_rd(sc, ena); - CLR(reg, I40E_QTX_ENA_QENA_REQ_MASK); - ixl_wr(sc, ena, reg); - for (i = 0; i < 10; i++) { + for (i = 0; i < 20; i++) { reg = ixl_rd(sc, ena); - if (!ISSET(reg, I40E_QTX_ENA_QENA_STAT_MASK)) + if (ISSET(reg, I40E_QTX_ENA_QENA_STAT_MASK) == 0) return (0); delaymsec(10); @@ -2230,15 +2428,12 @@ ixl_rxr_clean(struct ixl_softc *sc, struct ixl_rx_ring *rxr) } static int -ixl_rxr_enable(struct ixl_softc *sc, struct ixl_rx_ring *rxr) +ixl_rxr_enabled(struct ixl_softc *sc, struct ixl_rx_ring *rxr) { bus_size_t ena = I40E_QRX_ENA(rxr->rxr_qid); uint32_t reg; int i; - reg = ixl_rd(sc, ena); - SET(reg, I40E_QRX_ENA_QENA_REQ_MASK | I40E_QRX_ENA_QENA_STAT_MASK); - ixl_wr(sc, ena, reg); for (i = 0; i < 10; i++) { reg = ixl_rd(sc, ena); if (ISSET(reg, I40E_QRX_ENA_QENA_STAT_MASK)) @@ -2250,6 +2445,24 @@ ixl_rxr_enable(struct ixl_softc *sc, struct ixl_rx_ring *rxr) return (ETIMEDOUT); } +static int +ixl_rxr_disabled(struct ixl_softc *sc, struct ixl_rx_ring *rxr) +{ + bus_size_t ena = I40E_QRX_ENA(rxr->rxr_qid); + uint32_t reg; + int i; + + for (i = 0; i < 20; i++) { + reg = ixl_rd(sc, ena); + if (ISSET(reg, I40E_QRX_ENA_QENA_STAT_MASK) == 0) + return (0); + + delaymsec(10); + } + + return (ETIMEDOUT); +} + static void ixl_rxr_config(struct ixl_softc *sc, struct ixl_rx_ring *rxr) { @@ -2262,19 +2475,19 @@ ixl_rxr_config(struct ixl_softc *sc, struct ixl_rx_ring *rxr) htolem64(&rxq.base, IXL_DMA_DVA(&sc->sc_rx_ring->rxr_mem) / IXL_HMC_RXQ_BASE_UNIT); htolem16(&rxq.qlen, sc->sc_rx_ring_ndescs); - htolem16(&rxq.dbuff, MCLBYTES / IXL_HMC_RXQ_DBUFF_UNIT); + rxq.dbuff = htole16(MCLBYTES / IXL_HMC_RXQ_DBUFF_UNIT); rxq.hbuff = 0; rxq.dtype = IXL_HMC_RXQ_DTYPE_NOSPLIT; rxq.dsize = IXL_HMC_RXQ_DSIZE_16; rxq.crcstrip = 1; rxq.l2sel = 0; rxq.showiv = 0; - rxq.rxmax = htole16(MCLBYTES * 5); /* XXX */ - rxq.tphrdesc_ena = 1; - rxq.tphwdesc_ena = 1; - rxq.tphdata_ena = 0; - rxq.tphhead_ena = 0; - rxq.lrxqthresh = 1; + rxq.rxmax = htole16(MCLBYTES); /* XXX */ + rxq.tphrdesc_ena = 0; + rxq.tphwdesc_ena = 0; + rxq.tphdata_ena = 0; + rxq.tphhead_ena = 0; + rxq.lrxqthresh = 0; rxq.prefena = 1; hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_RX, rxr->rxr_qid); @@ -2291,27 +2504,6 @@ ixl_rxr_unconfig(struct ixl_softc *sc, struct ixl_rx_ring *rxr) memset(hmc, 0, ixl_hmc_len(sc, IXL_HMC_LAN_RX)); } -static int -ixl_rxr_disable(struct ixl_softc *sc, struct ixl_rx_ring *rxr) -{ - bus_size_t ena = I40E_QRX_ENA(rxr->rxr_qid); - uint32_t reg; - int i; - - reg = ixl_rd(sc, ena); - CLR(reg, I40E_QRX_ENA_QENA_REQ_MASK); - ixl_wr(sc, ena, reg); - for (i = 0; i < 10; i++) { - reg = ixl_rd(sc, ena); - if (!ISSET(reg, I40E_QRX_ENA_QENA_STAT_MASK)) - return (0); - - delaymsec(10); - } - - return (ETIMEDOUT); -} - static void ixl_rxr_free(struct ixl_softc *sc, struct ixl_rx_ring *rxr) { @@ -2409,8 +2601,8 @@ ixl_rxeof(struct ixl_softc *sc, struct ixl_rx_ring *rxr) if (done) { rxr->rxr_cons = cons; + ixl_rxfill(sc, rxr); if_input(ifp, &ml); - // rxefill } bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&rxr->rxr_mem), @@ -2503,19 +2695,16 @@ ixl_intr(void *xsc) icr = ixl_rd(sc, I40E_PFINT_ICR0); -// if (ISSET(icr, I40E_PFINT_ICR0_ADMINQ_MASK)) { + if (ISSET(icr, I40E_PFINT_ICR0_ADMINQ_MASK)) { + ixl_atq_done(sc); task_add(systq, &sc->sc_arq_task); rv = 1; -// } - - ixl_atq_done(sc); + } - if (ISSET(icr, I40E_PFINT_ICR0_QUEUE_0_MASK)) { + if (ISSET(icr, I40E_INTR_NOTX_RX_MASK)) rv |= ixl_rxeof(sc, NULL); - } - if (ISSET(icr, I40E_PFINT_ICR0_QUEUE_1_MASK)) { + if (ISSET(icr, I40E_INTR_NOTX_TX_MASK)) rv |= ixl_txeof(sc, NULL); - } return (rv); } @@ -3153,6 +3342,7 @@ ixl_set_vsi(struct ixl_softc *sc) CLR(data->mapping_flags, htole16(IXL_AQ_VSI_QUE_MAP_MASK)); SET(data->mapping_flags, htole16(IXL_AQ_VSI_QUE_MAP_CONTIG)); + data->queue_mapping[0] = htole16(0); data->tc_mapping[0] = htole16((0 << IXL_AQ_VSI_TC_Q_OFFSET_SHIFT) | (sc->sc_nqueues << IXL_AQ_VSI_TC_Q_NUMBER_SHIFT)); @@ -3298,27 +3488,43 @@ static int ixl_hmc(struct ixl_softc *sc) { struct { + uint32_t count; uint32_t minsize; bus_size_t maxcnt; bus_size_t setoff; bus_size_t setcnt; - } regs[2] = { + } regs[] = { { + 0, IXL_HMC_TXQ_MINSIZE, I40E_GLHMC_LANTXOBJSZ, I40E_GLHMC_LANTXBASE(sc->sc_pf_id), I40E_GLHMC_LANTXCNT(sc->sc_pf_id), }, { + 0, IXL_HMC_RXQ_MINSIZE, I40E_GLHMC_LANRXOBJSZ, I40E_GLHMC_LANRXBASE(sc->sc_pf_id), I40E_GLHMC_LANRXCNT(sc->sc_pf_id), - } + }, + { + 0, + 0, + I40E_GLHMC_FCOEMAX, + I40E_GLHMC_FCOEDDPBASE(sc->sc_pf_id), + I40E_GLHMC_FCOEDDPCNT(sc->sc_pf_id), + }, + { + 0, + 0, + I40E_GLHMC_FCOEFMAX, + I40E_GLHMC_FCOEFBASE(sc->sc_pf_id), + I40E_GLHMC_FCOEFCNT(sc->sc_pf_id), + }, }; struct ixl_hmc_entry *e; - uint64_t size, pdpage; - uint32_t count; + uint64_t size, dva; uint8_t *kva; uint64_t *sdpage; unsigned int i; @@ -3326,13 +3532,14 @@ ixl_hmc(struct ixl_softc *sc) CTASSERT(nitems(regs) <= nitems(sc->sc_hmc_entries)); - count = ixl_rd(sc, I40E_GLHMC_LANQMAX); + regs[IXL_HMC_LAN_TX].count = regs[IXL_HMC_LAN_RX].count = + ixl_rd(sc, I40E_GLHMC_LANQMAX); size = 0; for (i = 0; i < nitems(regs); i++) { e = &sc->sc_hmc_entries[i]; - e->hmc_count = count; + e->hmc_count = regs[i].count; e->hmc_size = 1U << ixl_rd(sc, regs[i].maxcnt); e->hmc_base = size; @@ -3344,34 +3551,43 @@ ixl_hmc(struct ixl_softc *sc) size += roundup(e->hmc_size * e->hmc_count, IXL_HMC_ROUNDUP); } - size = roundup(size, IXL_HMC_PGSIZE); npages = size / IXL_HMC_PGSIZE; + tables = roundup(size, IXL_HMC_L2SZ) / IXL_HMC_L2SZ; - size += tables * IXL_HMC_PGSIZE; - if (ixl_dmamem_alloc(sc, &sc->sc_hmc, size, IXL_HMC_PGSIZE) != 0) { - printf("%s: unable to allocate hmc memory\n", DEVNAME(sc)); + if (ixl_dmamem_alloc(sc, &sc->sc_hmc_pd, size, IXL_HMC_PGSIZE) != 0) { + printf("%s: unable to allocate hmc pd memory\n", DEVNAME(sc)); return (-1); } - kva = IXL_DMA_KVA(&sc->sc_hmc); - memset(kva, 0, IXL_DMA_LEN(&sc->sc_hmc)); - sdpage = (uint64_t *)kva; + if (ixl_dmamem_alloc(sc, &sc->sc_hmc_sd, tables * IXL_HMC_PGSIZE, + IXL_HMC_PGSIZE) != 0) { + printf("%s: unable to allocate hmc sd memory\n", DEVNAME(sc)); + ixl_dmamem_free(sc, &sc->sc_hmc_pd); + return (-1); + } - pdpage = IXL_DMA_DVA(&sc->sc_hmc); - pdpage += tables * IXL_HMC_PGSIZE; + kva = IXL_DMA_KVA(&sc->sc_hmc_pd); + memset(kva, 0, IXL_DMA_LEN(&sc->sc_hmc_pd)); + bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_hmc_pd), + 0, IXL_DMA_LEN(&sc->sc_hmc_pd), + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + + dva = IXL_DMA_DVA(&sc->sc_hmc_pd); + sdpage = IXL_DMA_KVA(&sc->sc_hmc_sd); for (i = 0; i < npages; i++) { - htolem64(sdpage++, pdpage | IXL_HMC_PDVALID); + htolem64(sdpage++, dva | IXL_HMC_PDVALID); - pdpage += IXL_HMC_PGSIZE; - } + dva += IXL_HMC_PGSIZE; + } - bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_hmc), - 0, IXL_DMA_LEN(&sc->sc_hmc), + bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_hmc_sd), + 0, IXL_DMA_LEN(&sc->sc_hmc_sd), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + dva = IXL_DMA_DVA(&sc->sc_hmc_sd); for (i = 0; i < tables; i++) { uint32_t count; @@ -3379,8 +3595,8 @@ ixl_hmc(struct ixl_softc *sc) count = (npages > IXL_HMC_PGS) ? IXL_HMC_PGS : npages; - ixl_wr(sc, I40E_PFHMC_SDDATAHIGH, ixl_dmamem_hi(&sc->sc_hmc)); - ixl_wr(sc, I40E_PFHMC_SDDATALOW, ixl_dmamem_lo(&sc->sc_hmc) | + ixl_wr(sc, I40E_PFHMC_SDDATAHIGH, dva >> 32); + ixl_wr(sc, I40E_PFHMC_SDDATALOW, dva | (count << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | (1U << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)); ixl_barrier(sc, 0, sc->sc_mems, BUS_SPACE_BARRIER_WRITE); @@ -3388,6 +3604,7 @@ ixl_hmc(struct ixl_softc *sc) (1U << I40E_PFHMC_SDCMD_PMSDWR_SHIFT) | i); npages -= IXL_HMC_PGS; + dva += IXL_HMC_PGSIZE; } for (i = 0; i < nitems(regs); i++) { @@ -3401,6 +3618,13 @@ ixl_hmc(struct ixl_softc *sc) } static void +ixl_hmc_free(struct ixl_softc *sc) +{ + ixl_dmamem_free(sc, &sc->sc_hmc_sd); + ixl_dmamem_free(sc, &sc->sc_hmc_pd); +} + +static void ixl_hmc_pack(void *d, const void *s, const struct ixl_hmc_pack *packing, unsigned int npacking) { |