From: Michael Buesch <mb@bu3sch.de>
To: John Linville <linville@tuxdriver.com>
Cc: bcm43xx-dev@lists.berlios.de, linux-wireless@vger.kernel.org
Subject: [PATCH] b43: Use SSB block-I/O to do PIO
Date: Wed, 2 Apr 2008 19:58:20 +0200 [thread overview]
Message-ID: <200804021958.21080.mb@bu3sch.de> (raw)
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>
---
John, please apply to 2.6.26
Index: wireless-testing/drivers/net/wireless/b43/pio.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/pio.c 2008-03-30 18:19:24.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/pio.c 2008-03-30 18:21:34.000000000 +0200
@@ -335,33 +335,34 @@ static struct b43_pio_txqueue * select_q
} else
q = dev->pio.tx_queue_AC_BE;
return q;
}
-static inline void tx_write_2byte_queue(struct b43_pio_txqueue *q,
- u16 *ctl,
- const void *_data,
- unsigned int data_len)
+static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
+ u16 ctl,
+ const void *_data,
+ unsigned int data_len)
{
+ struct b43_wldev *dev = q->dev;
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);
- for (i = 0; i < data_len; i += 2) {
- value = data[i];
- if (i + 1 < data_len) {
- value |= (u16)(data[i + 1]) << 8;
- } else {
- *ctl &= ~B43_PIO_TXCTL_WRITEHI;
- b43_piotx_write16(q, B43_PIO_TXCTL, *ctl);
- }
- b43_piotx_write16(q, B43_PIO_TXDATA, value);
+ 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),
+ q->mmio_base + B43_PIO_TXDATA,
+ sizeof(u16));
+ if (data_len & 1) {
+ /* 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]);
}
+
+ return ctl;
}
static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
const u8 *hdr, unsigned int hdrlen)
{
struct b43_pio_txqueue *q = pack->queue;
@@ -371,57 +372,59 @@ static void pio_tx_frame_2byte_queue(str
ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
ctl |= B43_PIO_TXCTL_FREADY;
ctl &= ~B43_PIO_TXCTL_EOF;
/* 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. */
- tx_write_2byte_queue(q, &ctl, frame, frame_len);
+ ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
ctl |= B43_PIO_TXCTL_EOF;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
}
-static inline void tx_write_4byte_queue(struct b43_pio_txqueue *q,
- u32 *ctl,
- const void *_data,
- unsigned int data_len)
+static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
+ u32 ctl,
+ const void *_data,
+ unsigned int data_len)
{
+ struct b43_wldev *dev = q->dev;
const u8 *data = _data;
- unsigned int i;
- u32 value;
- bool ctl_changed = 0;
-
- *ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
- B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
- b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl);
- for (i = 0; i < data_len; i += 4) {
- value = data[i];
- if (i + 1 < data_len) {
- value |= (u32)(data[i + 1]) << 8;
- } else {
- *ctl &= ~B43_PIO8_TXCTL_8_15;
- ctl_changed = 1;
- }
- if (i + 2 < data_len) {
- 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;
+
+ ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
+ B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
+ b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
+
+ ssb_block_write(dev->dev, data, (data_len & ~3),
+ q->mmio_base + B43_PIO8_TXDATA,
+ sizeof(u32));
+ if (data_len & 3) {
+ u32 value = 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--;
+ case 2:
+ ctl |= B43_PIO8_TXCTL_8_15;
+ value |= (u32)(*data) << 8;
+ data--;
+ case 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);
}
+
+ return ctl;
}
static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
const u8 *hdr, unsigned int hdrlen)
{
struct b43_pio_txqueue *q = pack->queue;
@@ -431,15 +434,15 @@ static void pio_tx_frame_4byte_queue(str
ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
ctl |= B43_PIO8_TXCTL_FREADY;
ctl &= ~B43_PIO8_TXCTL_EOF;
/* 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. */
- tx_write_4byte_queue(q, &ctl, frame, frame_len);
+ ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
ctl |= B43_PIO8_TXCTL_EOF;
b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
}
static int pio_tx_frame(struct b43_pio_txqueue *q,
@@ -624,12 +627,13 @@ void b43_pio_get_tx_stats(struct b43_wld
}
}
/* Returns whether we should fetch another frame. */
static bool pio_rx_frame(struct b43_pio_rxqueue *q)
{
+ struct b43_wldev *dev = q->dev;
struct b43_rxhdr_fw4 rxhdr;
u16 len;
u32 macstat;
unsigned int i, padding;
struct sk_buff *skb;
const char *err_msg = NULL;
@@ -669,27 +673,19 @@ static bool pio_rx_frame(struct b43_pio_
b43dbg(q->dev->wl, "PIO RX timed out\n");
return 1;
data_ready:
/* Get the preamble (RX header) */
if (q->rev >= 8) {
- u32 *preamble = (u32 *)&rxhdr;
- u32 value;
-
- for (i = 0; i < sizeof(rxhdr); i += 4) {
- value = b43_piorx_read32(q, B43_PIO8_RXDATA);
- preamble[i / 4] = cpu_to_le32(value);
- }
+ ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
+ q->mmio_base + B43_PIO8_RXDATA,
+ sizeof(u32));
} else {
- u16 *preamble = (u16 *)&rxhdr;
- u16 value;
-
- for (i = 0; i < sizeof(rxhdr); i += 2) {
- value = b43_piorx_read16(q, B43_PIO_RXDATA);
- preamble[i / 2] = cpu_to_le16(value);
- }
+ ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
+ q->mmio_base + B43_PIO_RXDATA,
+ sizeof(u16));
}
/* Sanity checks. */
len = le16_to_cpu(rxhdr.frame_len);
if (unlikely(len > 0x700)) {
err_msg = "len > 0x700";
goto rx_error;
@@ -717,32 +713,43 @@ data_ready:
err_msg = "Out of memory";
goto rx_error;
}
skb_reserve(skb, 2);
skb_put(skb, len + padding);
if (q->rev >= 8) {
- u32 value;
+ ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
+ q->mmio_base + B43_PIO8_RXDATA,
+ sizeof(u32));
+ if (len & 3) {
+ 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);
- skb->data[i] = value;
- if ((i + 1) < (len + padding))
- skb->data[i + 1] = value >> 8;
- if ((i + 2) < (len + padding))
- skb->data[i + 2] = value >> 16;
- if ((i + 3) < (len + padding))
- skb->data[i + 3] = value >> 24;
+ data = &(skb->data[len + padding - 1]);
+ switch (len & 3) {
+ case 3:
+ *data = (value >> 16);
+ data--;
+ case 2:
+ *data = (value >> 8);
+ data--;
+ case 1:
+ *data = value;
+ }
}
} 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);
- skb->data[i] = value;
- if ((i + 1) < (len + padding))
- skb->data[i + 1] = value >> 8;
+ skb->data[len + padding - 1] = value;
}
}
b43_rx(q->dev, skb, &rxhdr);
return 1;
Index: wireless-testing/drivers/net/wireless/b43/Kconfig
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/Kconfig 2008-03-30 18:19:24.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/Kconfig 2008-03-30 18:21:34.000000000 +0200
@@ -64,12 +64,13 @@ config B43_PCMCIA
# Data transfers to the device via PIO
# This is only needed on PCMCIA devices. All others can do DMA properly.
config B43_PIO
bool
depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
+ select SSB_BLOCKIO
default y
config B43_NPHY
bool "Pre IEEE 802.11n support (BROKEN)"
depends on B43 && EXPERIMENTAL
---help---
reply other threads:[~2008-04-02 17:59 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200804021958.21080.mb@bu3sch.de \
--to=mb@bu3sch.de \
--cc=bcm43xx-dev@lists.berlios.de \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.