Commit d8c17e15 authored by Michael Buesch's avatar Michael Buesch Committed by John W. Linville

b43: Use SSB block-I/O to do PIO

This changes the b43-PIO code to use the new SSB block-I/O.
This reduces the overhead by removing lots of function calls, pointer
dereferencing, if-conditionals any byteswapping for each packet data word.

This also fixes a harmless sparse endianness warning.
Signed-off-by: default avatarMichael Buesch <mb@bu3sch.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 36316126
...@@ -67,6 +67,7 @@ config B43_PCMCIA ...@@ -67,6 +67,7 @@ config B43_PCMCIA
config B43_PIO config B43_PIO
bool bool
depends on B43 && (B43_PCMCIA || B43_FORCE_PIO) depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
select SSB_BLOCKIO
default y default y
config B43_NPHY config B43_NPHY
......
...@@ -338,27 +338,28 @@ static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev, ...@@ -338,27 +338,28 @@ static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev,
return q; return q;
} }
static inline void tx_write_2byte_queue(struct b43_pio_txqueue *q, static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
u16 *ctl, u16 ctl,
const void *_data, const void *_data,
unsigned int data_len) unsigned int data_len)
{ {
struct b43_wldev *dev = q->dev;
const u8 *data = _data; const u8 *data = _data;
unsigned int i;
u16 value; ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
*ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
b43_piotx_write16(q, B43_PIO_TXCTL, *ctl); ssb_block_write(dev->dev, data, (data_len & ~1),
for (i = 0; i < data_len; i += 2) { q->mmio_base + B43_PIO_TXDATA,
value = data[i]; sizeof(u16));
if (i + 1 < data_len) { if (data_len & 1) {
value |= (u16)(data[i + 1]) << 8; /* Write the last byte. */
} else { ctl &= ~B43_PIO_TXCTL_WRITEHI;
*ctl &= ~B43_PIO_TXCTL_WRITEHI; b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
b43_piotx_write16(q, B43_PIO_TXCTL, *ctl); b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
}
b43_piotx_write16(q, B43_PIO_TXDATA, value);
} }
return ctl;
} }
static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack, static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
...@@ -374,51 +375,53 @@ static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack, ...@@ -374,51 +375,53 @@ static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
ctl &= ~B43_PIO_TXCTL_EOF; ctl &= ~B43_PIO_TXCTL_EOF;
/* Transfer the header data. */ /* Transfer the header data. */
tx_write_2byte_queue(q, &ctl, hdr, hdrlen); ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
/* Transfer the frame data. */ /* Transfer the frame data. */
tx_write_2byte_queue(q, &ctl, frame, frame_len); ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
ctl |= B43_PIO_TXCTL_EOF; ctl |= B43_PIO_TXCTL_EOF;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl); b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
} }
static inline void tx_write_4byte_queue(struct b43_pio_txqueue *q, static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
u32 *ctl, u32 ctl,
const void *_data, const void *_data,
unsigned int data_len) unsigned int data_len)
{ {
struct b43_wldev *dev = q->dev;
const u8 *data = _data; const u8 *data = _data;
unsigned int i;
u32 value; ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
bool ctl_changed = 0; B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
*ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; ssb_block_write(dev->dev, data, (data_len & ~3),
b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl); q->mmio_base + B43_PIO8_TXDATA,
for (i = 0; i < data_len; i += 4) { sizeof(u32));
value = data[i]; if (data_len & 3) {
if (i + 1 < data_len) { u32 value = 0;
value |= (u32)(data[i + 1]) << 8;
} else { /* Write the last few bytes. */
*ctl &= ~B43_PIO8_TXCTL_8_15; ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
ctl_changed = 1; B43_PIO8_TXCTL_24_31);
} data = &(data[data_len - 1]);
if (i + 2 < data_len) { switch (data_len & 3) {
value |= (u32)(data[i + 2]) << 16; case 3:
} else { ctl |= B43_PIO8_TXCTL_16_23;
*ctl &= ~B43_PIO8_TXCTL_16_23; value |= (u32)(*data) << 16;
ctl_changed = 1; data--;
} case 2:
if (i + 3 < data_len) { ctl |= B43_PIO8_TXCTL_8_15;
value |= (u32)(data[i + 3]) << 24; value |= (u32)(*data) << 8;
} else { data--;
*ctl &= ~B43_PIO8_TXCTL_24_31; case 1:
ctl_changed = 1; value |= (u32)(*data);
} }
if (ctl_changed) b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl);
b43_piotx_write32(q, B43_PIO8_TXDATA, value); b43_piotx_write32(q, B43_PIO8_TXDATA, value);
} }
return ctl;
} }
static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack, static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
...@@ -434,9 +437,9 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack, ...@@ -434,9 +437,9 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
ctl &= ~B43_PIO8_TXCTL_EOF; ctl &= ~B43_PIO8_TXCTL_EOF;
/* Transfer the header data. */ /* Transfer the header data. */
tx_write_4byte_queue(q, &ctl, hdr, hdrlen); ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
/* Transfer the frame data. */ /* Transfer the frame data. */
tx_write_4byte_queue(q, &ctl, frame, frame_len); ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
ctl |= B43_PIO8_TXCTL_EOF; ctl |= B43_PIO8_TXCTL_EOF;
b43_piotx_write32(q, B43_PIO_TXCTL, ctl); b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
...@@ -627,6 +630,7 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev, ...@@ -627,6 +630,7 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev,
/* Returns whether we should fetch another frame. */ /* Returns whether we should fetch another frame. */
static bool pio_rx_frame(struct b43_pio_rxqueue *q) static bool pio_rx_frame(struct b43_pio_rxqueue *q)
{ {
struct b43_wldev *dev = q->dev;
struct b43_rxhdr_fw4 rxhdr; struct b43_rxhdr_fw4 rxhdr;
u16 len; u16 len;
u32 macstat; u32 macstat;
...@@ -672,21 +676,13 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q) ...@@ -672,21 +676,13 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
/* Get the preamble (RX header) */ /* Get the preamble (RX header) */
if (q->rev >= 8) { if (q->rev >= 8) {
u32 *preamble = (u32 *)&rxhdr; ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
u32 value; q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
for (i = 0; i < sizeof(rxhdr); i += 4) {
value = b43_piorx_read32(q, B43_PIO8_RXDATA);
preamble[i / 4] = cpu_to_le32(value);
}
} else { } else {
u16 *preamble = (u16 *)&rxhdr; ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
u16 value; q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
for (i = 0; i < sizeof(rxhdr); i += 2) {
value = b43_piorx_read16(q, B43_PIO_RXDATA);
preamble[i / 2] = cpu_to_le16(value);
}
} }
/* Sanity checks. */ /* Sanity checks. */
len = le16_to_cpu(rxhdr.frame_len); len = le16_to_cpu(rxhdr.frame_len);
...@@ -720,26 +716,37 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q) ...@@ -720,26 +716,37 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
skb_reserve(skb, 2); skb_reserve(skb, 2);
skb_put(skb, len + padding); skb_put(skb, len + padding);
if (q->rev >= 8) { if (q->rev >= 8) {
u32 value; ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
q->mmio_base + B43_PIO8_RXDATA,
for (i = padding; i < len + padding; i += 4) { sizeof(u32));
if (len & 3) {
u32 value;
char *data;
/* Read the last few bytes. */
value = b43_piorx_read32(q, B43_PIO8_RXDATA); value = b43_piorx_read32(q, B43_PIO8_RXDATA);
skb->data[i] = value; data = &(skb->data[len + padding - 1]);
if ((i + 1) < (len + padding)) switch (len & 3) {
skb->data[i + 1] = value >> 8; case 3:
if ((i + 2) < (len + padding)) *data = (value >> 16);
skb->data[i + 2] = value >> 16; data--;
if ((i + 3) < (len + padding)) case 2:
skb->data[i + 3] = value >> 24; *data = (value >> 8);
data--;
case 1:
*data = value;
}
} }
} else { } else {
u16 value; ssb_block_read(dev->dev, skb->data + padding, (len & ~1),
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
if (len & 1) {
u16 value;
for (i = padding; i < len + padding; i += 2) { /* Read the last byte. */
value = b43_piorx_read16(q, B43_PIO_RXDATA); value = b43_piorx_read16(q, B43_PIO_RXDATA);
skb->data[i] = value; skb->data[len + padding - 1] = value;
if ((i + 1) < (len + padding))
skb->data[i + 1] = value >> 8;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment