2009-09-23 16:51:58

by Michael Büsch

[permalink] [raw]
Subject: [PATCH] b43: Always use block-I/O for the PIO data registers

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 <[email protected]>

---


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.


2009-09-28 22:30:21

by Albert Herranz

[permalink] [raw]
Subject: Re: [PATCH] b43: Always use block-I/O for the PIO data registers

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 <[email protected]>
>
> ---
>
>
> 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 <[email protected]>