All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] b43: Always use block-I/O for the PIO data registers
@ 2009-09-23 16:51 Michael Buesch
  2009-09-28 22:30 ` Albert Herranz
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Buesch @ 2009-09-23 16:51 UTC (permalink / raw)
  To: John W. Linville; +Cc: Broadcom Wireless, linux-wireless, Albert Herranz

On SDIO the PIO data register seems to be hardwired to LE. So
the MACCTL bit has no effect on the endianness.
So also use block-I/O for the last word of the packet. block-I/O is always LE.

Signed-off-by: Michael Buesch <mb@bu3sch.de>

---


Index: wireless-testing/drivers/net/wireless/b43/pio.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/pio.c	2009-09-10 20:14:37.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/pio.c	2009-09-10 21:08:11.000000000 +0200
@@ -340,10 +340,15 @@ static u16 tx_write_2byte_queue(struct b
 			q->mmio_base + B43_PIO_TXDATA,
 			sizeof(u16));
 	if (data_len & 1) {
+		u8 tail[2] = { 0, };
+
 		/* Write the last byte. */
 		ctl &= ~B43_PIO_TXCTL_WRITEHI;
 		b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
-		b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
+		tail[0] = data[data_len - 1];
+		ssb_block_write(dev->dev, tail, 2,
+				q->mmio_base + B43_PIO_TXDATA,
+				sizeof(u16));
 	}
 
 	return ctl;
@@ -386,26 +391,31 @@ static u32 tx_write_4byte_queue(struct b
 			q->mmio_base + B43_PIO8_TXDATA,
 			sizeof(u32));
 	if (data_len & 3) {
-		u32 value = 0;
+		u8 tail[4] = { 0, };
 
 		/* Write the last few bytes. */
 		ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
 			 B43_PIO8_TXCTL_24_31);
-		data = &(data[data_len - 1]);
 		switch (data_len & 3) {
 		case 3:
-			ctl |= B43_PIO8_TXCTL_16_23;
-			value |= (u32)(*data) << 16;
-			data--;
+			ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
+			tail[0] = data[data_len - 3];
+			tail[1] = data[data_len - 2];
+			tail[2] = data[data_len - 1];
+			break;
 		case 2:
 			ctl |= B43_PIO8_TXCTL_8_15;
-			value |= (u32)(*data) << 8;
-			data--;
+			tail[0] = data[data_len - 2];
+			tail[1] = data[data_len - 1];
+			break;
 		case 1:
-			value |= (u32)(*data);
+			tail[0] = data[data_len - 1];
+			break;
 		}
 		b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
-		b43_piotx_write32(q, B43_PIO8_TXDATA, value);
+		ssb_block_write(dev->dev, tail, 4,
+				q->mmio_base + B43_PIO8_TXDATA,
+				sizeof(u32));
 	}
 
 	return ctl;
@@ -693,21 +703,25 @@ data_ready:
 			       q->mmio_base + B43_PIO8_RXDATA,
 			       sizeof(u32));
 		if (len & 3) {
-			u32 value;
-			char *data;
+			u8 tail[4] = { 0, };
 
 			/* Read the last few bytes. */
-			value = b43_piorx_read32(q, B43_PIO8_RXDATA);
-			data = &(skb->data[len + padding - 1]);
+			ssb_block_read(dev->dev, tail, 4,
+				       q->mmio_base + B43_PIO8_RXDATA,
+				       sizeof(u32));
 			switch (len & 3) {
 			case 3:
-				*data = (value >> 16);
-				data--;
+				skb->data[len + padding - 3] = tail[0];
+				skb->data[len + padding - 2] = tail[1];
+				skb->data[len + padding - 1] = tail[2];
+				break;
 			case 2:
-				*data = (value >> 8);
-				data--;
+				skb->data[len + padding - 2] = tail[0];
+				skb->data[len + padding - 1] = tail[1];
+				break;
 			case 1:
-				*data = value;
+				skb->data[len + padding - 1] = tail[0];
+				break;
 			}
 		}
 	} else {
@@ -715,11 +729,13 @@ data_ready:
 			       q->mmio_base + B43_PIO_RXDATA,
 			       sizeof(u16));
 		if (len & 1) {
-			u16 value;
+			u8 tail[2] = { 0, };
 
 			/* Read the last byte. */
-			value = b43_piorx_read16(q, B43_PIO_RXDATA);
-			skb->data[len + padding - 1] = value;
+			ssb_block_read(dev->dev, tail, 2,
+				       q->mmio_base + B43_PIO_RXDATA,
+				       sizeof(u16));
+			skb->data[len + padding - 1] = tail[0];
 		}
 	}
 

-- 
Greetings, Michael.

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

* Re: [PATCH] b43: Always use block-I/O for the PIO data registers
  2009-09-23 16:51 [PATCH] b43: Always use block-I/O for the PIO data registers Michael Buesch
@ 2009-09-28 22:30 ` Albert Herranz
  0 siblings, 0 replies; 2+ messages in thread
From: Albert Herranz @ 2009-09-28 22:30 UTC (permalink / raw)
  To: Michael Buesch, John W. Linville; +Cc: Broadcom Wireless, linux-wireless

Michael Buesch wrote:
> On SDIO the PIO data register seems to be hardwired to LE. So
> the MACCTL bit has no effect on the endianness.
> So also use block-I/O for the last word of the packet. block-I/O is always LE.
> 
> Signed-off-by: Michael Buesch <mb@bu3sch.de>
> 
> ---
> 
> 
> Index: wireless-testing/drivers/net/wireless/b43/pio.c
> ===================================================================
> --- wireless-testing.orig/drivers/net/wireless/b43/pio.c    2009-09-10 20:14:37.000000000 +0200
> +++ wireless-testing/drivers/net/wireless/b43/pio.c    2009-09-10 21:08:11.000000000 +0200
> @@ -340,10 +340,15 @@ static u16 tx_write_2byte_queue(struct b
>              q->mmio_base + B43_PIO_TXDATA,
>              sizeof(u16));
>      if (data_len & 1) {
> +        u8 tail[2] = { 0, };
> +
>          /* Write the last byte. */
>          ctl &= ~B43_PIO_TXCTL_WRITEHI;
>          b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
> -        b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
> +        tail[0] = data[data_len - 1];
> +        ssb_block_write(dev->dev, tail, 2,
> +                q->mmio_base + B43_PIO_TXDATA,
> +                sizeof(u16));
>      }
>  
>      return ctl;
> @@ -386,26 +391,31 @@ static u32 tx_write_4byte_queue(struct b
>              q->mmio_base + B43_PIO8_TXDATA,
>              sizeof(u32));
>      if (data_len & 3) {
> -        u32 value = 0;
> +        u8 tail[4] = { 0, };
>  
>          /* Write the last few bytes. */
>          ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
>               B43_PIO8_TXCTL_24_31);
> -        data = &(data[data_len - 1]);
>          switch (data_len & 3) {
>          case 3:
> -            ctl |= B43_PIO8_TXCTL_16_23;
> -            value |= (u32)(*data) << 16;
> -            data--;
> +            ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
> +            tail[0] = data[data_len - 3];
> +            tail[1] = data[data_len - 2];
> +            tail[2] = data[data_len - 1];
> +            break;
>          case 2:
>              ctl |= B43_PIO8_TXCTL_8_15;
> -            value |= (u32)(*data) << 8;
> -            data--;
> +            tail[0] = data[data_len - 2];
> +            tail[1] = data[data_len - 1];
> +            break;
>          case 1:
> -            value |= (u32)(*data);
> +            tail[0] = data[data_len - 1];
> +            break;
>          }
>          b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
> -        b43_piotx_write32(q, B43_PIO8_TXDATA, value);
> +        ssb_block_write(dev->dev, tail, 4,
> +                q->mmio_base + B43_PIO8_TXDATA,
> +                sizeof(u32));
>      }
>  
>      return ctl;
> @@ -693,21 +703,25 @@ data_ready:
>                     q->mmio_base + B43_PIO8_RXDATA,
>                     sizeof(u32));
>          if (len & 3) {
> -            u32 value;
> -            char *data;
> +            u8 tail[4] = { 0, };
>  
>              /* Read the last few bytes. */
> -            value = b43_piorx_read32(q, B43_PIO8_RXDATA);
> -            data = &(skb->data[len + padding - 1]);
> +            ssb_block_read(dev->dev, tail, 4,
> +                       q->mmio_base + B43_PIO8_RXDATA,
> +                       sizeof(u32));
>              switch (len & 3) {
>              case 3:
> -                *data = (value >> 16);
> -                data--;
> +                skb->data[len + padding - 3] = tail[0];
> +                skb->data[len + padding - 2] = tail[1];
> +                skb->data[len + padding - 1] = tail[2];
> +                break;
>              case 2:
> -                *data = (value >> 8);
> -                data--;
> +                skb->data[len + padding - 2] = tail[0];
> +                skb->data[len + padding - 1] = tail[1];
> +                break;
>              case 1:
> -                *data = value;
> +                skb->data[len + padding - 1] = tail[0];
> +                break;
>              }
>          }
>      } else {
> @@ -715,11 +729,13 @@ data_ready:
>                     q->mmio_base + B43_PIO_RXDATA,
>                     sizeof(u16));
>          if (len & 1) {
> -            u16 value;
> +            u8 tail[2] = { 0, };
>  
>              /* Read the last byte. */
> -            value = b43_piorx_read16(q, B43_PIO_RXDATA);
> -            skb->data[len + padding - 1] = value;
> +            ssb_block_read(dev->dev, tail, 2,
> +                       q->mmio_base + B43_PIO_RXDATA,
> +                       sizeof(u16));
> +            skb->data[len + padding - 1] = tail[0];
>          }
>      }
>  
> 

Without this patch, the last bytes of data sent/received to/from PIO FIFOs on SDIO-based cards get "swizzled" when its length is not multiple of 4 bytes.

Tested-by: Albert Herranz <albert_herranz@yahoo.es>


      

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

end of thread, other threads:[~2009-09-28 22:30 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-23 16:51 [PATCH] b43: Always use block-I/O for the PIO data registers Michael Buesch
2009-09-28 22:30 ` Albert Herranz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.