summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoredavis <edavis@FreeBSD.org>2014-03-21 23:04:23 +0000
committeredavis <edavis@FreeBSD.org>2014-03-21 23:04:23 +0000
commit6b2cc0eea64831d1ea73c01b4284440bc55dfe7f (patch)
tree3afb5e6eabe63fe0bb08f2e42721643ab3fdcaf1
parent7a8191d0195779a394a594ba7b1d24e69299b362 (diff)
downloadFreeBSD-src-6b2cc0eea64831d1ea73c01b4284440bc55dfe7f.zip
FreeBSD-src-6b2cc0eea64831d1ea73c01b4284440bc55dfe7f.tar.gz
MFC 262999
Fixed MSI interrupt allocation and handling. Fixed a DMA mapping leak that occurs when defragmenting packet chains. Approved by: davidch (mentor)
-rw-r--r--sys/dev/bxe/bxe.c114
1 files changed, 36 insertions, 78 deletions
diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c
index 31f7a05..251d5ad 100644
--- a/sys/dev/bxe/bxe.c
+++ b/sys/dev/bxe/bxe.c
@@ -34,7 +34,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#define BXE_DRIVER_VERSION "1.78.77"
+#define BXE_DRIVER_VERSION "1.78.78"
#include "bxe.h"
#include "ecore_sp.h"
@@ -911,7 +911,7 @@ bxe_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
dma->paddr = segs->ds_addr;
dma->nseg = nseg;
#if 0
- BLOGD(dma->sc, DBG_LOAD,,
+ BLOGD(dma->sc, DBG_LOAD,
"DMA alloc '%s': vaddr=%p paddr=%p nseg=%d size=%lu\n",
dma->msg, dma->vaddr, (void *)dma->paddr,
dma->nseg, dma->size);
@@ -5486,7 +5486,7 @@ bxe_tx_encap(struct bxe_fastpath *fp, struct mbuf **m_head)
}
/* make sure it fits in the packet window */
- if (__predict_false(nsegs > 12)) {
+ if (__predict_false(nsegs > BXE_MAX_SEGMENTS)) {
/*
* The mbuf may be to big for the controller to handle. If the frame
* is a TSO frame we'll need to do an additional check.
@@ -5501,8 +5501,9 @@ bxe_tx_encap(struct bxe_fastpath *fp, struct mbuf **m_head)
fp->eth_q_stats.tx_window_violation_std++;
}
- /* lets try to defragment this mbuf */
+ /* lets try to defragment this mbuf and remap it */
fp->eth_q_stats.mbuf_defrag_attempts++;
+ bus_dmamap_unload(fp->tx_mbuf_tag, tx_buf->m_map);
m0 = m_defrag(*m_head, M_DONTWAIT);
if (m0 == NULL) {
@@ -5520,10 +5521,12 @@ bxe_tx_encap(struct bxe_fastpath *fp, struct mbuf **m_head)
/* No sense in trying to defrag/copy chain, drop it. :( */
rc = error;
}
-
- /* if the chain is still too long then drop it */
- if (__predict_false(nsegs > 12)) {
- rc = ENODEV;
+ else {
+ /* if the chain is still too long then drop it */
+ if (__predict_false(nsegs > BXE_MAX_SEGMENTS)) {
+ bus_dmamap_unload(fp->tx_mbuf_tag, tx_buf->m_map);
+ rc = ENODEV;
+ }
}
}
}
@@ -9397,13 +9400,13 @@ bxe_interrupt_alloc(struct bxe_softc *sc)
}
if (((sc->devinfo.pcie_cap_flags & BXE_MSI_CAPABLE_FLAG) == 0) ||
- (msi_count < 2)) {
+ (msi_count < 1)) {
sc->interrupt_mode = INTR_MODE_INTX; /* try INTx next */
break;
}
- /* ask for the necessary number of MSI vectors */
- num_requested = min((sc->num_queues + 1), msi_count);
+ /* ask for a single MSI vector */
+ num_requested = 1;
BLOGD(sc, DBG_LOAD, "Requesting %d MSI vectors\n", num_requested);
@@ -9414,8 +9417,8 @@ bxe_interrupt_alloc(struct bxe_softc *sc)
break;
}
- if (num_allocated < 2) { /* possible? */
- BLOGE(sc, "MSI allocation less than 2!\n");
+ if (num_allocated != 1) { /* possible? */
+ BLOGE(sc, "MSI allocation is not 1!\n");
sc->interrupt_mode = INTR_MODE_INTX; /* try INTx next */
pci_release_msi(sc->dev);
break;
@@ -9426,38 +9429,26 @@ bxe_interrupt_alloc(struct bxe_softc *sc)
/* best effort so use the number of vectors allocated to us */
sc->intr_count = num_allocated;
- sc->num_queues = num_allocated - 1;
+ sc->num_queues = num_allocated;
rid = 1; /* initial resource identifier */
- /* allocate the MSI vectors */
- for (i = 0; i < num_allocated; i++) {
- sc->intr[i].rid = (rid + i);
-
- if ((sc->intr[i].resource =
- bus_alloc_resource_any(sc->dev,
- SYS_RES_IRQ,
- &sc->intr[i].rid,
- RF_ACTIVE)) == NULL) {
- BLOGE(sc, "Failed to map MSI[%d] (rid=%d)!\n",
- i, (rid + i));
-
- for (j = (i - 1); j >= 0; j--) {
- bus_release_resource(sc->dev,
- SYS_RES_IRQ,
- sc->intr[j].rid,
- sc->intr[j].resource);
- }
-
- sc->intr_count = 0;
- sc->num_queues = 0;
- sc->interrupt_mode = INTR_MODE_INTX; /* try INTx next */
- pci_release_msi(sc->dev);
- break;
- }
+ sc->intr[0].rid = rid;
- BLOGD(sc, DBG_LOAD, "Mapped MSI[%d] (rid=%d)\n", i, (rid + i));
+ if ((sc->intr[0].resource =
+ bus_alloc_resource_any(sc->dev,
+ SYS_RES_IRQ,
+ &sc->intr[0].rid,
+ RF_ACTIVE)) == NULL) {
+ BLOGE(sc, "Failed to map MSI[0] (rid=%d)!\n", rid);
+ sc->intr_count = 0;
+ sc->num_queues = 0;
+ sc->interrupt_mode = INTR_MODE_INTX; /* try INTx next */
+ pci_release_msi(sc->dev);
+ break;
}
+
+ BLOGD(sc, DBG_LOAD, "Mapped MSI[0] (rid=%d)\n", rid);
} while (0);
do { /* try allocating INTx vector resources */
@@ -9636,54 +9627,21 @@ bxe_interrupt_attach(struct bxe_softc *sc)
fp->state = BXE_FP_STATE_IRQ;
}
} else if (sc->interrupt_mode == INTR_MODE_MSI) {
- BLOGD(sc, DBG_LOAD, "Enabling slowpath MSI[0] vector.\n");
+ BLOGD(sc, DBG_LOAD, "Enabling MSI[0] vector\n");
/*
- * Setup the interrupt handler. Note that we pass the driver instance
- * to the interrupt handler for the slowpath.
+ * Setup the interrupt handler. Note that we pass the
+ * driver instance to the interrupt handler which
+ * will handle both the slowpath and fastpath.
*/
if ((rc = bus_setup_intr(sc->dev, sc->intr[0].resource,
(INTR_TYPE_NET | INTR_MPSAFE),
- NULL, bxe_intr_sp, sc,
+ NULL, bxe_intr_legacy, sc,
&sc->intr[0].tag)) != 0) {
BLOGE(sc, "Failed to allocate MSI[0] vector (%d)\n", rc);
goto bxe_interrupt_attach_exit;
}
- bus_describe_intr(sc->dev, sc->intr[0].resource,
- sc->intr[0].tag, "sp");
-
- /* bus_bind_intr(sc->dev, sc->intr[0].resource, 0); */
-
- /* initialize the fastpath vectors (note the first was used for sp) */
- for (i = 0; i < sc->num_queues; i++) {
- fp = &sc->fp[i];
- BLOGD(sc, DBG_LOAD, "Enabling MSI[%d] vector\n", (i + 1));
-
- /*
- * Setup the interrupt handler. Note that we pass the
- * fastpath context to the interrupt handler in this
- * case.
- */
- if ((rc = bus_setup_intr(sc->dev, sc->intr[i + 1].resource,
- (INTR_TYPE_NET | INTR_MPSAFE),
- NULL, bxe_intr_fp, fp,
- &sc->intr[i + 1].tag)) != 0) {
- BLOGE(sc, "Failed to allocate MSI[%d] vector (%d)\n",
- (i + 1), rc);
- goto bxe_interrupt_attach_exit;
- }
-
- bus_describe_intr(sc->dev, sc->intr[i + 1].resource,
- sc->intr[i + 1].tag, "fp%02d", i);
-
- /* bind the fastpath instance to a cpu */
- if (sc->num_queues > 1) {
- bus_bind_intr(sc->dev, sc->intr[i + 1].resource, i);
- }
-
- fp->state = BXE_FP_STATE_IRQ;
- }
} else { /* (sc->interrupt_mode == INTR_MODE_INTX) */
BLOGD(sc, DBG_LOAD, "Enabling INTx interrupts\n");
OpenPOWER on IntegriCloud