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: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
36316126e9
commit
d8c17e1597
2 changed files with 88 additions and 80 deletions
|
@ -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,
|
||||||
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;
|
ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
|
||||||
b43_piotx_write16(q, B43_PIO_TXCTL, *ctl);
|
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
|
||||||
for (i = 0; i < data_len; i += 2) {
|
|
||||||
value = data[i];
|
ssb_block_write(dev->dev, data, (data_len & ~1),
|
||||||
if (i + 1 < data_len) {
|
q->mmio_base + B43_PIO_TXDATA,
|
||||||
value |= (u16)(data[i + 1]) << 8;
|
sizeof(u16));
|
||||||
} else {
|
if (data_len & 1) {
|
||||||
*ctl &= ~B43_PIO_TXCTL_WRITEHI;
|
/* Write the last byte. */
|
||||||
b43_piotx_write16(q, B43_PIO_TXCTL, *ctl);
|
ctl &= ~B43_PIO_TXCTL_WRITEHI;
|
||||||
}
|
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
|
||||||
b43_piotx_write16(q, B43_PIO_TXDATA, value);
|
b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
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;
|
|
||||||
bool ctl_changed = 0;
|
|
||||||
|
|
||||||
*ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
|
ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
|
||||||
B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
|
B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
|
||||||
b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl);
|
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
|
||||||
for (i = 0; i < data_len; i += 4) {
|
|
||||||
value = data[i];
|
ssb_block_write(dev->dev, data, (data_len & ~3),
|
||||||
if (i + 1 < data_len) {
|
q->mmio_base + B43_PIO8_TXDATA,
|
||||||
value |= (u32)(data[i + 1]) << 8;
|
sizeof(u32));
|
||||||
} else {
|
if (data_len & 3) {
|
||||||
*ctl &= ~B43_PIO8_TXCTL_8_15;
|
u32 value = 0;
|
||||||
ctl_changed = 1;
|
|
||||||
|
/* 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--;
|
||||||
|
case 2:
|
||||||
|
ctl |= B43_PIO8_TXCTL_8_15;
|
||||||
|
value |= (u32)(*data) << 8;
|
||||||
|
data--;
|
||||||
|
case 1:
|
||||||
|
value |= (u32)(*data);
|
||||||
}
|
}
|
||||||
if (i + 2 < data_len) {
|
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
|
||||||
value |= (u32)(data[i + 2]) << 16;
|
|
||||||
} else {
|
|
||||||
*ctl &= ~B43_PIO8_TXCTL_16_23;
|
|
||||||
ctl_changed = 1;
|
|
||||||
}
|
|
||||||
if (i + 3 < data_len) {
|
|
||||||
value |= (u32)(data[i + 3]) << 24;
|
|
||||||
} else {
|
|
||||||
*ctl &= ~B43_PIO8_TXCTL_24_31;
|
|
||||||
ctl_changed = 1;
|
|
||||||
}
|
|
||||||
if (ctl_changed)
|
|
||||||
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,
|
||||||
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,
|
||||||
/* 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 @@ data_ready:
|
||||||
|
|
||||||
/* 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 @@ data_ready:
|
||||||
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) {
|
||||||
|
ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
|
||||||
|
q->mmio_base + B43_PIO8_RXDATA,
|
||||||
|
sizeof(u32));
|
||||||
|
if (len & 3) {
|
||||||
u32 value;
|
u32 value;
|
||||||
|
char *data;
|
||||||
|
|
||||||
for (i = padding; i < len + padding; i += 4) {
|
/* 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 {
|
||||||
|
ssb_block_read(dev->dev, skb->data + padding, (len & ~1),
|
||||||
|
q->mmio_base + B43_PIO_RXDATA,
|
||||||
|
sizeof(u16));
|
||||||
|
if (len & 1) {
|
||||||
u16 value;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue