The recently added bgmac ethernet driver uses "dma_sync_single_for_cpu"; 
however,
that function only does anything for a few select CPU types.  This patch 
resolves
DMA issues (resulting in packet loss) that become evident if you do a flood ping
to the router with full size packets; there will be a lot of 
"Found poisoned packet at slot x, DMA issue!" messages generated to the 
console/dmesg.

Note that this same call is used in other Broadcom ethernet drivers (e.g., b44 
and tg3).

Signed-off-by: Nathan Hintz <[email protected]>

--- /dev/null
+++ 
target/linux/brcm47xx/patches-3.6/262-MIPS-BCM47XX-cpu_74k-is-non-coherent.patch
@@ -0,0 +1,44 @@
+--- a/arch/mips/mm/dma-default.c
++++ b/arch/mips/mm/dma-default.c
+@@ -35,11 +35,12 @@
+  * coherent.
+  */
+ 
+-static inline int cpu_is_noncoherent_r10000(struct device *dev)
++static inline int cpu_is_noncoherent(struct device *dev)
+ {
+       return !plat_device_is_coherent(dev) &&
+              (current_cpu_type() == CPU_R10000 ||
+-             current_cpu_type() == CPU_R12000);
++             current_cpu_type() == CPU_R12000 ||
++             current_cpu_type() == CPU_74K);
+ }
+ 
+ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
+@@ -209,7 +210,7 @@
+ static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
+       size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
+ {
+-      if (cpu_is_noncoherent_r10000(dev))
++      if (cpu_is_noncoherent(dev))
+               __dma_sync(dma_addr_to_page(dev, dma_addr),
+                          dma_addr & ~PAGE_MASK, size, direction);
+ 
+@@ -260,7 +261,7 @@
+ static void mips_dma_sync_single_for_cpu(struct device *dev,
+       dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
+ {
+-      if (cpu_is_noncoherent_r10000(dev))
++      if (cpu_is_noncoherent(dev))
+               __dma_sync(dma_addr_to_page(dev, dma_handle),
+                          dma_handle & ~PAGE_MASK, size, direction);
+ }
+@@ -281,7 +282,7 @@
+ 
+       /* Make sure that gcc doesn't leave the empty loop body.  */
+       for (i = 0; i < nelems; i++, sg++) {
+-              if (cpu_is_noncoherent_r10000(dev))
++              if (cpu_is_noncoherent(dev))
+                       __dma_sync(sg_page(sg), sg->offset, sg->length,
+                                  direction);
+       }

_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to