b43: Use SSB block-I/O to do PIO
authorMichael Buesch <mb@bu3sch.de>
Wed, 2 Apr 2008 17:58:20 +0000 (19:58 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 8 Apr 2008 20:44:41 +0000 (16:44 -0400)
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>
drivers/net/wireless/b43/Kconfig
drivers/net/wireless/b43/pio.c

index 94f04559028baf554d38cf7398b64d6c100c7d25..f51b2d9b085b9eb94208df60870fa9377bc4b653 100644 (file)
@@ -67,6 +67,7 @@ config B43_PCMCIA
 config B43_PIO
        bool
        depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
+       select SSB_BLOCKIO
        default y
 
 config B43_NPHY
index e73769ac027f54cef08d5a7d692e8a4069178c0c..fcacafb043467559768582090a7c7586b51b1e06 100644 (file)
@@ -338,27 +338,28 @@ static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev,
        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,
@@ -374,51 +375,53 @@ static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
        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,
@@ -434,9 +437,9 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
        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);
@@ -627,6 +630,7 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev,
 /* 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;
@@ -672,21 +676,13 @@ 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);
@@ -720,26 +716,37 @@ data_ready:
        skb_reserve(skb, 2);
        skb_put(skb, len + padding);
        if (q->rev >= 8) {
-               u32 value;
-
-               for (i = padding; i < len + padding; i += 4) {
+               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;
+
+                       /* 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;
                }
        }