linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2] b43: Changes to enable BCM4311 rev 02 with wireless core revision 13
@ 2007-11-21 21:38 Larry Finger
  2007-11-22 17:34 ` Michael Buesch
  0 siblings, 1 reply; 4+ messages in thread
From: Larry Finger @ 2007-11-21 21:38 UTC (permalink / raw)
  To: John Linville, Michael Buesch; +Cc: Bcm43xx-dev, linux-wireless

The BCM94311MCG rev 02 chip has an 802.11 core with revision 13 and
has not been supported until now. The changes include the following:

(1) Add the 802.11 rev 13 device to the ssb_device_id table to load b43=
=2E
(2) Add PHY revision 9 to the supported list.
(3) Fix 64-bit addressing errors.
(4) Remove some magic numbers in the DMA setup.

The DMA implementation for this chip supports full 64-bit addressing wi=
th
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 pres=
ent,
this problem is thought to arise from a hardware error.

This patch has been tested on my system and by C=C3=A9dric Caumont
<icare40@hotmail.com>.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

John,

This patch is intended for the everything branch of wireless-2.6.

Larry
---

 dma.c  |   50 ++++++++++++++++++++++++++------------------------
 main.c |    3 ++-
 wa.c   |    1 +
 3 files changed, 29 insertions(+), 25 deletions(-)

Index: wireless-2.6/drivers/net/wireless/b43/dma.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- wireless-2.6.orig/drivers/net/wireless/b43/dma.c
+++ wireless-2.6/drivers/net/wireless/b43/dma.c
@@ -165,7 +165,7 @@ static void op64_fill_descriptor(struct=20
 	addrhi =3D (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
 	addrext =3D (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
 	    >> SSB_DMA_TRANSLATION_SHIFT;
-	addrhi |=3D ssb_dma_translation(ring->dev->dev);
+	addrhi |=3D (ssb_dma_translation(ring->dev->dev) << 1);
 	if (slot =3D=3D ring->nr_slots - 1)
 		ctl0 |=3D B43_DMA64_DCTL0_DTABLEEND;
 	if (start)
@@ -426,9 +426,21 @@ static inline
 static int alloc_ringmemory(struct b43_dmaring *ring)
 {
 	struct device *dev =3D ring->dev->dev->dev;
+	gfp_t flags =3D GFP_KERNEL;
=20
+	/* 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 buff=
er
+	 * 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 memor=
y,
+	 * which accounts for the GFP_DMA flag below.
+	 */
+	if (ring->dma64)
+		flags =3D GFP_DMA;
 	ring->descbase =3D 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 b4
 	return 0;
 }
=20
-/* Reset the RX DMA channel */
+/* Reset the TX DMA channel */
 int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, i=
nt dma64)
 {
 	int i;
@@ -636,18 +648,12 @@ static int dmacontroller_setup(struct b4
 		if (ring->dma64) {
 			u64 ringbase =3D (u64) (ring->dmabase);
=20
-			addrext =3D ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
-			    >> SSB_DMA_TRANSLATION_SHIFT;
-			value =3D B43_DMA64_TXENABLE;
-			value |=3D (addrext << B43_DMA64_TXADDREXT_SHIFT)
-			    & B43_DMA64_TXADDREXT_MASK;
-			b43_dma_write(ring, B43_DMA64_TXCTL, value);
+			b43_dma_write(ring, B43_DMA64_TXCTL,
+				      B43_DMA64_TXENABLE);
 			b43_dma_write(ring, B43_DMA64_TXRINGLO,
 				      (ringbase & 0xFFFFFFFF));
 			b43_dma_write(ring, B43_DMA64_TXRINGHI,
-				      ((ringbase >> 32) &
-				       ~SSB_DMA_TRANSLATION_MASK)
-				      | trans);
+				      (ringbase >> 32));
 		} else {
 			u32 ringbase =3D (u32) (ring->dmabase);
=20
@@ -668,20 +674,15 @@ static int dmacontroller_setup(struct b4
 		if (ring->dma64) {
 			u64 ringbase =3D (u64) (ring->dmabase);
=20
-			addrext =3D ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
-			    >> SSB_DMA_TRANSLATION_SHIFT;
-			value =3D (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT);
-			value |=3D B43_DMA64_RXENABLE;
-			value |=3D (addrext << B43_DMA64_RXADDREXT_SHIFT)
-			    & B43_DMA64_RXADDREXT_MASK;
+			value =3D (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT)
+				| B43_DMA64_RXENABLE;
 			b43_dma_write(ring, B43_DMA64_RXCTL, value);
 			b43_dma_write(ring, B43_DMA64_RXRINGLO,
 				      (ringbase & 0xFFFFFFFF));
 			b43_dma_write(ring, B43_DMA64_RXRINGHI,
-				      ((ringbase >> 32) &
-				       ~SSB_DMA_TRANSLATION_MASK)
-				      | trans);
-			b43_dma_write(ring, B43_DMA64_RXINDEX, 200);
+				      (ringbase >> 32));
+			b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
+				      sizeof(struct b43_dmadesc64));
 		} else {
 			u32 ringbase =3D (u32) (ring->dmabase);
=20
@@ -695,11 +696,12 @@ static int dmacontroller_setup(struct b4
 			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));
 		}
 	}
=20
-      out:
+out:
 	return err;
 }
=20
Index: wireless-2.6/drivers/net/wireless/b43/main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- wireless-2.6.orig/drivers/net/wireless/b43/main.c
+++ wireless-2.6/drivers/net/wireless/b43/main.c
@@ -93,6 +93,7 @@ static const struct ssb_device_id b43_ss
 	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
 };
=20
@@ -3064,7 +3065,7 @@ static int b43_phy_versioning(struct b43
 			unsupported =3D 1;
 		break;
 	case B43_PHYTYPE_G:
-		if (phy_rev > 8)
+		if (phy_rev > 9)
 			unsupported =3D 1;
 		break;
 	default:
Index: wireless-2.6/drivers/net/wireless/b43/wa.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- wireless-2.6.orig/drivers/net/wireless/b43/wa.c
+++ wireless-2.6/drivers/net/wireless/b43/wa.c
@@ -642,6 +642,7 @@ void b43_wa_all(struct b43_wldev *dev)
 		case 6:
 		case 7:
 		case 8:
+		case 9:
 			b43_wa_tr_ltov(dev);
 			b43_wa_crs_ed(dev);
 			b43_wa_rssi_lt(dev);
-
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] b43: Changes to enable BCM4311 rev 02 with wireless core revision 13
  2007-11-21 21:38 [PATCH V2] b43: Changes to enable BCM4311 rev 02 with wireless core revision 13 Larry Finger
@ 2007-11-22 17:34 ` Michael Buesch
  2007-11-23  5:36   ` Larry Finger
  0 siblings, 1 reply; 4+ messages in thread
From: Michael Buesch @ 2007-11-22 17:34 UTC (permalink / raw)
  To: Larry Finger; +Cc: John Linville, Bcm43xx-dev, linux-wireless

On Wednesday 21 November 2007 22:38:12 Larry Finger wrote:
> The BCM94311MCG rev 02 chip has an 802.11 core with revision 13 and
> has not been supported until now. The changes include the following:
>=20
> (1) Add the 802.11 rev 13 device to the ssb_device_id table to load b=
43.
> (2) Add PHY revision 9 to the supported list.
> (3) Fix 64-bit addressing errors.
> (4) Remove some magic numbers in the DMA setup.
>=20
> 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 du=
e
> 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 pr=
esent,
> this problem is thought to arise from a hardware error.
>=20
> This patch has been tested on my system and by C=C3=A9dric Caumont
> <icare40@hotmail.com>.
>=20
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> ---
>=20
> John,
>=20
> This patch is intended for the everything branch of wireless-2.6.
>=20
> Larry
> ---
>=20
>  dma.c  |   50 ++++++++++++++++++++++++++------------------------
>  main.c |    3 ++-
>  wa.c   |    1 +
>  3 files changed, 29 insertions(+), 25 deletions(-)
>=20
> Index: wireless-2.6/drivers/net/wireless/b43/dma.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- wireless-2.6.orig/drivers/net/wireless/b43/dma.c
> +++ wireless-2.6/drivers/net/wireless/b43/dma.c
> @@ -165,7 +165,7 @@ static void op64_fill_descriptor(struct=20
>  	addrhi =3D (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
>  	addrext =3D (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
>  	    >> SSB_DMA_TRANSLATION_SHIFT;
> -	addrhi |=3D ssb_dma_translation(ring->dev->dev);
> +	addrhi |=3D (ssb_dma_translation(ring->dev->dev) << 1);
>  	if (slot =3D=3D ring->nr_slots - 1)
>  		ctl0 |=3D B43_DMA64_DCTL0_DTABLEEND;
>  	if (start)
> @@ -426,9 +426,21 @@ static inline
>  static int alloc_ringmemory(struct b43_dmaring *ring)
>  {
>  	struct device *dev =3D ring->dev->dev->dev;
> +	gfp_t flags =3D GFP_KERNEL;
> =20
> +	/* 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. Testi=
ng
> +	 * has shown that 4K is sufficient for the latter as long as the bu=
ffer
> +	 * does not cross an 8K boundary.
> +	 *
> +	 * For unknown reasons - possibly a hardware error - the BCM4311 re=
v
> +	 * 02, which uses 64-bit DMA, needs the ring buffer in very low mem=
ory,
> +	 * which accounts for the GFP_DMA flag below.
> +	 */
> +	if (ring->dma64)
> +		flags =3D GFP_DMA;
>  	ring->descbase =3D 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 b4
>  	return 0;
>  }
> =20
> -/* 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;
> @@ -636,18 +648,12 @@ static int dmacontroller_setup(struct b4
>  		if (ring->dma64) {
>  			u64 ringbase =3D (u64) (ring->dmabase);
> =20
> -			addrext =3D ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
> -			    >> SSB_DMA_TRANSLATION_SHIFT;
> -			value =3D B43_DMA64_TXENABLE;
> -			value |=3D (addrext << B43_DMA64_TXADDREXT_SHIFT)
> -			    & B43_DMA64_TXADDREXT_MASK;
> -			b43_dma_write(ring, B43_DMA64_TXCTL, value);
> +			b43_dma_write(ring, B43_DMA64_TXCTL,
> +				      B43_DMA64_TXENABLE);
>  			b43_dma_write(ring, B43_DMA64_TXRINGLO,
>  				      (ringbase & 0xFFFFFFFF));
>  			b43_dma_write(ring, B43_DMA64_TXRINGHI,
> -				      ((ringbase >> 32) &
> -				       ~SSB_DMA_TRANSLATION_MASK)
> -				      | trans);
> +				      (ringbase >> 32));
>  		} else {
>  			u32 ringbase =3D (u32) (ring->dmabase);
> =20
> @@ -668,20 +674,15 @@ static int dmacontroller_setup(struct b4
>  		if (ring->dma64) {
>  			u64 ringbase =3D (u64) (ring->dmabase);
> =20
> -			addrext =3D ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
> -			    >> SSB_DMA_TRANSLATION_SHIFT;
> -			value =3D (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT);
> -			value |=3D B43_DMA64_RXENABLE;
> -			value |=3D (addrext << B43_DMA64_RXADDREXT_SHIFT)
> -			    & B43_DMA64_RXADDREXT_MASK;
> +			value =3D (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT)
> +				| B43_DMA64_RXENABLE;
>  			b43_dma_write(ring, B43_DMA64_RXCTL, value);
>  			b43_dma_write(ring, B43_DMA64_RXRINGLO,
>  				      (ringbase & 0xFFFFFFFF));
>  			b43_dma_write(ring, B43_DMA64_RXRINGHI,
> -				      ((ringbase >> 32) &
> -				       ~SSB_DMA_TRANSLATION_MASK)
> -				      | trans);
> -			b43_dma_write(ring, B43_DMA64_RXINDEX, 200);
> +				      (ringbase >> 32));
> +			b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
> +				      sizeof(struct b43_dmadesc64));
>  		} else {
>  			u32 ringbase =3D (u32) (ring->dmabase);
> =20
> @@ -695,11 +696,12 @@ static int dmacontroller_setup(struct b4
>  			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));
>  		}
>  	}
> =20
> -      out:
> +out:
>  	return err;
>  }
> =20
> Index: wireless-2.6/drivers/net/wireless/b43/main.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- wireless-2.6.orig/drivers/net/wireless/b43/main.c
> +++ wireless-2.6/drivers/net/wireless/b43/main.c
> @@ -93,6 +93,7 @@ static const struct ssb_device_id b43_ss
>  	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
>  };
> =20
> @@ -3064,7 +3065,7 @@ static int b43_phy_versioning(struct b43
>  			unsupported =3D 1;
>  		break;
>  	case B43_PHYTYPE_G:
> -		if (phy_rev > 8)
> +		if (phy_rev > 9)
>  			unsupported =3D 1;
>  		break;
>  	default:
> Index: wireless-2.6/drivers/net/wireless/b43/wa.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- wireless-2.6.orig/drivers/net/wireless/b43/wa.c
> +++ wireless-2.6/drivers/net/wireless/b43/wa.c
> @@ -642,6 +642,7 @@ void b43_wa_all(struct b43_wldev *dev)
>  		case 6:
>  		case 7:
>  		case 8:
> +		case 9:
>  			b43_wa_tr_ltov(dev);
>  			b43_wa_crs_ed(dev);
>  			b43_wa_rssi_lt(dev);
>=20
>=20

partially acked.
Though, I'm not quite sure yet why you remove that
address extension bits. The specs clearly say that they _are_ there.
And it makes sense to use them, as two bytes of the address are used
for the routing stuff. So the highest 2 bits of the address have to be =
put
somewhere else. That's the "Transmit Channel Control Word" and
"Receive Channel Control Word" where 0x00030000 are the extension bits.

However I do think that this might be related to the bug you are explai=
ning
in the comment:
> +	 * For unknown reasons - possibly a hardware error - the BCM4311 re=
v
> +	 * 02, which uses 64-bit DMA, needs the ring buffer in very low mem=
ory,
> +	 * which accounts for the GFP_DMA flag below.

--=20
Greetings Michael.
-
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] b43: Changes to enable BCM4311 rev 02 with wireless core revision 13
  2007-11-22 17:34 ` Michael Buesch
@ 2007-11-23  5:36   ` Larry Finger
  2007-11-23 13:47     ` Michael Buesch
  0 siblings, 1 reply; 4+ messages in thread
From: Larry Finger @ 2007-11-23  5:36 UTC (permalink / raw)
  To: Michael Buesch; +Cc: John Linville, Bcm43xx-dev, linux-wireless

Michael Buesch wrote:
> 
> partially acked.
> Though, I'm not quite sure yet why you remove that
> address extension bits. The specs clearly say that they _are_ there.
> And it makes sense to use them, as two bytes of the address are used
> for the routing stuff. So the highest 2 bits of the address have to be put
> somewhere else. That's the "Transmit Channel Control Word" and
> "Receive Channel Control Word" where 0x00030000 are the extension bits.
> 

The appropriate section of dmacontroller_setup() in my patched source is as follows:

        if (ring->tx) {
                if (ring->dma64) {
                        u64 ringbase = (u64) (ring->dmabase);

                        b43_dma_write(ring, B43_DMA64_TXCTL,
                                      B43_DMA64_TXENABLE);
                        b43_dma_write(ring, B43_DMA64_TXRINGLO,
                                      (ringbase & 0xFFFFFFFF));
                        b43_dma_write(ring, B43_DMA64_TXRINGHI,
                                      (ringbase >> 32));
                } else {
			...... untouched 32-bit stuff ....
		}
        } else {
                err = alloc_initial_descbuffers(ring);
                if (err)
                        goto out;
                if (ring->dma64) {
                        u64 ringbase = (u64) (ring->dmabase);

                        value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT)
                                | B43_DMA64_RXENABLE;
                        b43_dma_write(ring, B43_DMA64_RXCTL, value);
                        b43_dma_write(ring, B43_DMA64_RXRINGLO,
                                      (ringbase & 0xFFFFFFFF));
                        b43_dma_write(ring, B43_DMA64_RXRINGHI,
                                      (ringbase >> 32));
                        b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
                                      sizeof(struct b43_dmadesc64));
                } else {
			........... 32-bit stuff ........
	}

No address extensions are used here because the specs clearly state that a flat 64-bit address is
used to specify the Descriptor Ring address. My code matches the specs.

In the 64-bit fill_descriptor routine, the my patches result in the following code:

        addrlo = (u32) (dmaaddr & 0xFFFFFFFF);
        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) << 1);
        if (slot == ring->nr_slots - 1)
                ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
        if (start)
                ctl0 |= B43_DMA64_DCTL0_FRAMESTART;
        if (end)
                ctl0 |= B43_DMA64_DCTL0_FRAMEEND;
        if (irq)
                ctl0 |= B43_DMA64_DCTL0_IRQ;
        ctl1 |= (bufsize - ring->frameoffset)
            & B43_DMA64_DCTL1_BYTECNT;
        ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT)
            & B43_DMA64_DCTL1_ADDREXT_MASK;

In this case, the specs do call for the upper two bits to be masked off the high 32 bits of the
address to be used for the routing code. These are saved in 'addrext' above. The routing bits, which
must be '10' for the 64-bit case, are then shifted into that 2-bit field, and the masked address
bits are encoded into the second control word 'ctl1' in the above snippet. As far as I can tell, my
code is doing exactly what the specs require - address extensions and all. If not, please show me
the error.

> However I do think that this might be related to the bug you are explaining
> in the comment:
>> +	 * 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.
>

Not true for two reasons. The first one is that it is the address of the ring buffer that is getting
the error, and that part does not use any extension bits. Secondly, the address extension stuff
would only apply if my computer had more than 2^(62) bytes of RAM, which is something like 10
billion GB - an amount that probably exceeds the total RAM in the world. As best I can tell, this
bug triggers when the Ring Buffer is placed above the 64-Megabyte level.

Larry



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] b43: Changes to enable BCM4311 rev 02 with wireless core revision 13
  2007-11-23  5:36   ` Larry Finger
@ 2007-11-23 13:47     ` Michael Buesch
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Buesch @ 2007-11-23 13:47 UTC (permalink / raw)
  To: Larry Finger; +Cc: John Linville, Bcm43xx-dev, linux-wireless

On Friday 23 November 2007 06:36:55 Larry Finger wrote:
> Michael Buesch wrote:
> > 
> > partially acked.
> > Though, I'm not quite sure yet why you remove that
> > address extension bits. The specs clearly say that they _are_ there.
> > And it makes sense to use them, as two bytes of the address are used
> > for the routing stuff. So the highest 2 bits of the address have to be put
> > somewhere else. That's the "Transmit Channel Control Word" and
> > "Receive Channel Control Word" where 0x00030000 are the extension bits.
> > 
> 
> The appropriate section of dmacontroller_setup() in my patched source is as follows:
> 
>         if (ring->tx) {
>                 if (ring->dma64) {
>                         u64 ringbase = (u64) (ring->dmabase);
> 
>                         b43_dma_write(ring, B43_DMA64_TXCTL,
>                                       B43_DMA64_TXENABLE);
>                         b43_dma_write(ring, B43_DMA64_TXRINGLO,
>                                       (ringbase & 0xFFFFFFFF));
>                         b43_dma_write(ring, B43_DMA64_TXRINGHI,
>                                       (ringbase >> 32));
>                 } else {
> 			...... untouched 32-bit stuff ....
> 		}
>         } else {
>                 err = alloc_initial_descbuffers(ring);
>                 if (err)
>                         goto out;
>                 if (ring->dma64) {
>                         u64 ringbase = (u64) (ring->dmabase);
> 
>                         value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT)
>                                 | B43_DMA64_RXENABLE;
>                         b43_dma_write(ring, B43_DMA64_RXCTL, value);
>                         b43_dma_write(ring, B43_DMA64_RXRINGLO,
>                                       (ringbase & 0xFFFFFFFF));
>                         b43_dma_write(ring, B43_DMA64_RXRINGHI,
>                                       (ringbase >> 32));
>                         b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
>                                       sizeof(struct b43_dmadesc64));
>                 } else {
> 			........... 32-bit stuff ........
> 	}
> 
> No address extensions are used here because the specs clearly state that a flat 64-bit address is
> used to specify the Descriptor Ring address. My code matches the specs.

I'm not sure which specifications you use, but here it clearly describes the
extension bits:
http://bcm-v4.sipsolutions.net/802.11/DMA#TransmitChannelControlWord-1

> > However I do think that this might be related to the bug you are explaining
> > in the comment:
> >> +	 * 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.

> the error, and that part does not use any extension bits. Secondly, the address extension stuff
> would only apply if my computer had more than 2^(62) bytes of RAM, which is something like 10
> billion GB - an amount that probably exceeds the total RAM in the world.

This is not true. We live in a world with IO-MMUs.

-- 
Greetings Michael.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2007-11-23 13:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-21 21:38 [PATCH V2] b43: Changes to enable BCM4311 rev 02 with wireless core revision 13 Larry Finger
2007-11-22 17:34 ` Michael Buesch
2007-11-23  5:36   ` Larry Finger
2007-11-23 13:47     ` Michael Buesch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).