svn commit: r199670 - head/sys/dev/bge
Pyun YongHyeon
pyunyh at gmail.com
Mon Nov 23 20:44:34 UTC 2009
On Sun, Nov 22, 2009 at 04:48:18PM -0700, Scott Long wrote:
> By definition, PCIe can't transfer across 4GB boundaries. It's not a
> bug specific to Broadcom. If you're loading dynamic buffers (i.e.
> mbufs), setting an appropriate boundary value in the tag will allow
> busdma to take care of this. If you're allocating static buffers,
> busdma won't honor this. But what you've done here is best anyways;
Last time I tried boundary value for static buffer in dma tag it
didn't honor the boundary value so I blindly thought boundary value
also is not honored for dynamic buffers. It would be great if this
can be documented in man page.
> control buffers that are going to be frequently transferred are best
> kept in the lower 4GB of the address space. It simplifies PCIe
> handling, and it's significantly faster on PCI/PCI-X. So I'd suggest
> making this the rule rather than the exception in the driver.
>
If this is the case it would also affect other drivers(em(4) and
igb(4) etc). As John said it would be even better this could be
automatically handled in bus_dma. Patching every driver in tree to
reflect this would be pain, I guess.
Anyway I've made a new patch. Would you review this?
-------------- next part --------------
--- if_bge.c.orig 2009-11-22 13:45:55.000000000 -0800
+++ if_bge.c 2009-11-23 12:20:07.000000000 -0800
@@ -2028,7 +2028,8 @@
bus_dma_tag_destroy(sc->bge_cdata.bge_rx_mtag);
if (sc->bge_cdata.bge_tx_mtag)
bus_dma_tag_destroy(sc->bge_cdata.bge_tx_mtag);
-
+ if (sc->bge_cdata.bge_mbuf_tag)
+ bus_dma_tag_destroy(sc->bge_cdata.bge_mbuf_tag);
/* Destroy standard RX ring. */
if (sc->bge_cdata.bge_rx_std_ring_map)
@@ -2125,16 +2126,24 @@
sc = device_get_softc(dev);
- lowaddr = BUS_SPACE_MAXADDR;
- if ((sc->bge_flags & BGE_FLAG_40BIT_BUG) != 0)
- lowaddr = BGE_DMA_MAXADDR;
- if ((sc->bge_flags & BGE_FLAG_4G_BNDRY_BUG) != 0)
- lowaddr = BUS_SPACE_MAXADDR_32BIT;
/*
* Allocate the parent bus DMA tag appropriate for PCI.
+ * All controllers that are not 5755 or higher have 4GB
+ * boundary DMA bug.
+ * Whenever an address crosses a multiple of the 4GB boundary
+ * (including 4GB, 8Gb, 12Gb, etc.) and makes the transition
+ * from 0xX_FFFF_FFFF to 0x(X+1)_0000_0000 an internal DMA
+ * state machine will lockup and cause the device to hang.
+ * According to Scott Long, PCIe can't transfer across 4GB
+ * boundaries by definition. And control buffers that are
+ * going to frequently transferred are best kept in the lower
+ * 4GB of the address space. It simplifies PCIe handling and
+ * it's significantly faster on PCI/PCI-X. So limit the
+ * DMA address to be within 4GB address for all control
+ * buffers(TX/RX/RX return/status block/statistics block etc).
*/
error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev),
- 1, 0, lowaddr, BUS_SPACE_MAXADDR, NULL,
+ 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
NULL, BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT,
0, NULL, NULL, &sc->bge_cdata.bge_parent_tag);
@@ -2143,6 +2152,23 @@
"could not allocate parent dma tag\n");
return (ENOMEM);
}
+ /*
+ * Set 4GB boundary for mbufs such that it workarounds DMA bug
+ * of pre BCM5755 controllers.
+ */
+ lowaddr = BUS_SPACE_MAXADDR;
+ if ((sc->bge_flags & BGE_FLAG_40BIT_BUG) != 0)
+ lowaddr = BGE_DMA_MAXADDR;
+ error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev),
+ 1, BUS_SPACE_MAXSIZE_32BIT, lowaddr, BUS_SPACE_MAXADDR,
+ NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT,
+ 0, NULL, NULL, &sc->bge_cdata.bge_mbuf_tag);
+
+ if (error != 0) {
+ device_printf(sc->bge_dev,
+ "could not allocate mbuf dma tag\n");
+ return (ENOMEM);
+ }
/*
* Create tag for Tx mbufs.
@@ -2154,7 +2180,7 @@
txsegsz = MCLBYTES;
txmaxsegsz = MCLBYTES * BGE_NSEG_NEW;
}
- error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag, 1,
+ error = bus_dma_tag_create(sc->bge_cdata.bge_mbuf_tag, 1,
0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
txmaxsegsz, BGE_NSEG_NEW, txsegsz, 0, NULL, NULL,
&sc->bge_cdata.bge_tx_mtag);
@@ -2167,7 +2193,7 @@
/*
* Create tag for Rx mbufs.
*/
- error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag, 1, 0,
+ error = bus_dma_tag_create(sc->bge_cdata.bge_mbuf_tag, 1, 0,
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1,
MCLBYTES, 0, NULL, NULL, &sc->bge_cdata.bge_rx_mtag);
@@ -2607,17 +2633,6 @@
}
/*
- * All controllers that are not 5755 or higher have 4GB
- * boundary DMA bug.
- * Whenever an address crosses a multiple of the 4GB boundary
- * (including 4GB, 8Gb, 12Gb, etc.) and makes the transition
- * from 0xX_FFFF_FFFF to 0x(X+1)_0000_0000 an internal DMA
- * state machine will lockup and cause the device to hang.
- */
- if (BGE_IS_5755_PLUS(sc) == 0)
- sc->bge_flags |= BGE_FLAG_4G_BNDRY_BUG;
-
- /*
* We could possibly check for BCOM_DEVICEID_BCM5788 in bge_probe()
* but I do not know the DEVICEID for the 5788M.
*/
--- if_bgereg.h.orig 2009-11-22 13:16:30.000000000 -0800
+++ if_bgereg.h 2009-11-23 11:53:56.000000000 -0800
@@ -2537,6 +2537,7 @@
*/
struct bge_chain_data {
bus_dma_tag_t bge_parent_tag;
+ bus_dma_tag_t bge_mbuf_tag;
bus_dma_tag_t bge_rx_std_ring_tag;
bus_dma_tag_t bge_rx_jumbo_ring_tag;
bus_dma_tag_t bge_rx_return_ring_tag;
@@ -2612,7 +2613,6 @@
#define BGE_FLAG_575X_PLUS 0x00008000
#define BGE_FLAG_5755_PLUS 0x00010000
#define BGE_FLAG_40BIT_BUG 0x00020000
-#define BGE_FLAG_4G_BNDRY_BUG 0x00040000
#define BGE_FLAG_RX_ALIGNBUG 0x00100000
#define BGE_FLAG_NO_3LED 0x00200000
#define BGE_FLAG_ADC_BUG 0x00400000
More information about the svn-src-head
mailing list