addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
        addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
            >> SSB_DMA_TRANSLATION_SHIFT;
-       addrhi |= ssb_dma_translation(ring->dev->dev);
+       addrhi |= (ssb_dma_translation(ring->dev->dev) << 1);
        if (slot == ring->nr_slots - 1)
                ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
        if (start)
 static int alloc_ringmemory(struct b43_dmaring *ring)
 {
        struct device *dev = ring->dev->dev->dev;
-
+       gfp_t flags = GFP_KERNEL;
+
+       /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
+        * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing
+        * has shown that 4K is sufficient for the latter as long as the buffer
+        * does not cross an 8K boundary.
+        *
+        * For unknown reasons - possibly a hardware error - the BCM4311 rev
+        * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
+        * which accounts for the GFP_DMA flag below.
+        */
+       if (ring->dma64)
+               flags |= GFP_DMA;
        ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE,
-                                           &(ring->dmabase), GFP_KERNEL);
+                                           &(ring->dmabase), flags);
        if (!ring->descbase) {
                b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
                return -ENOMEM;
        return 0;
 }
 
-/* Reset the RX DMA channel */
+/* Reset the TX DMA channel */
 int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
 {
        int i;
                        b43_dma_write(ring, B43_DMA64_TXRINGHI,
                                      ((ringbase >> 32) &
                                       ~SSB_DMA_TRANSLATION_MASK)
-                                     | trans);
+                                     | (trans << 1));
                } else {
                        u32 ringbase = (u32) (ring->dmabase);
 
                        b43_dma_write(ring, B43_DMA64_RXRINGHI,
                                      ((ringbase >> 32) &
                                       ~SSB_DMA_TRANSLATION_MASK)
-                                     | trans);
-                       b43_dma_write(ring, B43_DMA64_RXINDEX, 200);
+                                     | (trans << 1));
+                       b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
+                                     sizeof(struct b43_dmadesc64));
                } else {
                        u32 ringbase = (u32) (ring->dmabase);
 
                        b43_dma_write(ring, B43_DMA32_RXRING,
                                      (ringbase & ~SSB_DMA_TRANSLATION_MASK)
                                      | trans);
-                       b43_dma_write(ring, B43_DMA32_RXINDEX, 200);
+                       b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
+                                     sizeof(struct b43_dmadesc32));
                }
        }
 
-      out:
+out:
        return err;
 }