]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
b43: Backport bcm4311 fix
authorMichael Buesch <mb@bu3sch.de>
Fri, 29 Feb 2008 11:55:41 +0000 (12:55 +0100)
committerChris Wright <chrisw@sous-sol.org>
Mon, 24 Mar 2008 18:47:31 +0000 (11:47 -0700)
This is a backport of upstream commit 013978b6 ("b43: Changes to enable
BCM4311 rev 02 with wireless core revision 13") and the changes include
the following:

(1) Add the 802.11 rev 13 device to the ssb_device_id table to load b43.
(2) Add PHY revision 9 to the supported list.
(3) Change the 2-bit routing code for address extensions to 0b10 rather
    than the 0b01 used for the 32-bit case.
(4) Remove some magic numbers in the DMA setup.

The DMA implementation for this chip supports full 64-bit addressing with
one exception. Whenever the Descriptor Ring Buffer is in high memory, a
fatal DMA error occurs. This problem was not present in 2.6.24-rc2 due
to code to "Bias the placement of kernel pages at lower PFNs". When
commit 44048d70 reverted that code, the DMA error appeared. As a "fix",
use the GFP_DMA flag when allocating the buffer for 64-bit DMA. At present,
this problem is thought to arise from a hardware error.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Cc: John W. Linville <linville@tuxdriver.com>
Cc: Alexey Zaytsev <alexey.zaytsev@gmail.com>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/main.c

index 559a9a961f0429d02b1ece997e7c47d27475324f..ddcc0c49a7dfb7fe90ac9c0b7cbb0ed70c9149dc 100644 (file)
@@ -165,7 +165,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
        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)
@@ -426,9 +426,21 @@ static inline
 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;
@@ -483,7 +495,7 @@ int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
        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;
@@ -647,7 +659,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
                        b43_dma_write(ring, B43_DMA64_TXRINGHI,
                                      ((ringbase >> 32) &
                                       ~SSB_DMA_TRANSLATION_MASK)
-                                     | trans);
+                                     | (trans << 1));
                } else {
                        u32 ringbase = (u32) (ring->dmabase);
 
@@ -680,8 +692,9 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
                        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);
 
@@ -695,11 +708,12 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
                        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;
 }
 
index 69795fd847895614c5acd30a7d95df81ba5e7426..36a1de20478d4e243f7623a9d6b7a6409f642c86 100644 (file)
@@ -101,6 +101,7 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
+       SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13),
        SSB_DEVTABLE_END
 };
 
@@ -3079,7 +3080,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
                        unsupported = 1;
                break;
        case B43_PHYTYPE_G:
-               if (phy_rev > 8)
+               if (phy_rev > 9)
                        unsupported = 1;
                break;
        default: