aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/pio.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-04-02 13:58:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 16:44:41 -0400
commitd8c17e159758c2a4f8c3319fe8a6cf313f7a6733 (patch)
tree7246a95b8ed3872e1772563715c4264976008dad /drivers/net/wireless/b43/pio.c
parent36316126e90b058ad7bd5b9e3d6079814e0a17e2 (diff)
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>
Diffstat (limited to 'drivers/net/wireless/b43/pio.c')
-rw-r--r--drivers/net/wireless/b43/pio.c173
1 files changed, 90 insertions, 83 deletions
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index e73769ac027..fcacafb0434 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -338,27 +338,28 @@ static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev,
338 return q; 338 return q;
339} 339}
340 340
341static inline void tx_write_2byte_queue(struct b43_pio_txqueue *q, 341static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
342 u16 *ctl, 342 u16 ctl,
343 const void *_data, 343 const void *_data,
344 unsigned int data_len) 344 unsigned int data_len)
345{ 345{
346 struct b43_wldev *dev = q->dev;
346 const u8 *data = _data; 347 const u8 *data = _data;
347 unsigned int i; 348
348 u16 value; 349 ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
349 350 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
350 *ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; 351
351 b43_piotx_write16(q, B43_PIO_TXCTL, *ctl); 352 ssb_block_write(dev->dev, data, (data_len & ~1),
352 for (i = 0; i < data_len; i += 2) { 353 q->mmio_base + B43_PIO_TXDATA,
353 value = data[i]; 354 sizeof(u16));
354 if (i + 1 < data_len) { 355 if (data_len & 1) {
355 value |= (u16)(data[i + 1]) << 8; 356 /* Write the last byte. */
356 } else { 357 ctl &= ~B43_PIO_TXCTL_WRITEHI;
357 *ctl &= ~B43_PIO_TXCTL_WRITEHI; 358 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
358 b43_piotx_write16(q, B43_PIO_TXCTL, *ctl); 359 b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
359 }
360 b43_piotx_write16(q, B43_PIO_TXDATA, value);
361 } 360 }
361
362 return ctl;
362} 363}
363 364
364static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack, 365static 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 ctl &= ~B43_PIO_TXCTL_EOF; 375 ctl &= ~B43_PIO_TXCTL_EOF;
375 376
376 /* Transfer the header data. */ 377 /* Transfer the header data. */
377 tx_write_2byte_queue(q, &ctl, hdr, hdrlen); 378 ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
378 /* Transfer the frame data. */ 379 /* Transfer the frame data. */
379 tx_write_2byte_queue(q, &ctl, frame, frame_len); 380 ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
380 381
381 ctl |= B43_PIO_TXCTL_EOF; 382 ctl |= B43_PIO_TXCTL_EOF;
382 b43_piotx_write16(q, B43_PIO_TXCTL, ctl); 383 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
383} 384}
384 385
385static inline void tx_write_4byte_queue(struct b43_pio_txqueue *q, 386static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
386 u32 *ctl, 387 u32 ctl,
387 const void *_data, 388 const void *_data,
388 unsigned int data_len) 389 unsigned int data_len)
389{ 390{
391 struct b43_wldev *dev = q->dev;
390 const u8 *data = _data; 392 const u8 *data = _data;
391 unsigned int i; 393
392 u32 value; 394 ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
393 bool ctl_changed = 0; 395 B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
394 396 b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
395 *ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 | 397
396 B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; 398 ssb_block_write(dev->dev, data, (data_len & ~3),
397 b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl); 399 q->mmio_base + B43_PIO8_TXDATA,
398 for (i = 0; i < data_len; i += 4) { 400 sizeof(u32));
399 value = data[i]; 401 if (data_len & 3) {
400 if (i + 1 < data_len) { 402 u32 value = 0;
401 value |= (u32)(data[i + 1]) << 8; 403
402 } else { 404 /* Write the last few bytes. */
403 *ctl &= ~B43_PIO8_TXCTL_8_15; 405 ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
404 ctl_changed = 1; 406 B43_PIO8_TXCTL_24_31);
405 } 407 data = &(data[data_len - 1]);
406 if (i + 2 < data_len) { 408 switch (data_len & 3) {
407 value |= (u32)(data[i + 2]) << 16; 409 case 3:
408 } else { 410 ctl |= B43_PIO8_TXCTL_16_23;
409 *ctl &= ~B43_PIO8_TXCTL_16_23; 411 value |= (u32)(*data) << 16;
410 ctl_changed = 1; 412 data--;
411 } 413 case 2:
412 if (i + 3 < data_len) { 414 ctl |= B43_PIO8_TXCTL_8_15;
413 value |= (u32)(data[i + 3]) << 24; 415 value |= (u32)(*data) << 8;
414 } else { 416 data--;
415 *ctl &= ~B43_PIO8_TXCTL_24_31; 417 case 1:
416 ctl_changed = 1; 418 value |= (u32)(*data);
417 } 419 }
418 if (ctl_changed) 420 b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
419 b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl);
420 b43_piotx_write32(q, B43_PIO8_TXDATA, value); 421 b43_piotx_write32(q, B43_PIO8_TXDATA, value);
421 } 422 }
423
424 return ctl;
422} 425}
423 426
424static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack, 427static 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 ctl &= ~B43_PIO8_TXCTL_EOF; 437 ctl &= ~B43_PIO8_TXCTL_EOF;
435 438
436 /* Transfer the header data. */ 439 /* Transfer the header data. */
437 tx_write_4byte_queue(q, &ctl, hdr, hdrlen); 440 ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
438 /* Transfer the frame data. */ 441 /* Transfer the frame data. */
439 tx_write_4byte_queue(q, &ctl, frame, frame_len); 442 ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
440 443
441 ctl |= B43_PIO8_TXCTL_EOF; 444 ctl |= B43_PIO8_TXCTL_EOF;
442 b43_piotx_write32(q, B43_PIO_TXCTL, ctl); 445 b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
@@ -627,6 +630,7 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev,
627/* Returns whether we should fetch another frame. */ 630/* Returns whether we should fetch another frame. */
628static bool pio_rx_frame(struct b43_pio_rxqueue *q) 631static bool pio_rx_frame(struct b43_pio_rxqueue *q)
629{ 632{
633 struct b43_wldev *dev = q->dev;
630 struct b43_rxhdr_fw4 rxhdr; 634 struct b43_rxhdr_fw4 rxhdr;
631 u16 len; 635 u16 len;
632 u32 macstat; 636 u32 macstat;
@@ -672,21 +676,13 @@ data_ready:
672 676
673 /* Get the preamble (RX header) */ 677 /* Get the preamble (RX header) */
674 if (q->rev >= 8) { 678 if (q->rev >= 8) {
675 u32 *preamble = (u32 *)&rxhdr; 679 ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
676 u32 value; 680 q->mmio_base + B43_PIO8_RXDATA,
677 681 sizeof(u32));
678 for (i = 0; i < sizeof(rxhdr); i += 4) {
679 value = b43_piorx_read32(q, B43_PIO8_RXDATA);
680 preamble[i / 4] = cpu_to_le32(value);
681 }
682 } else { 682 } else {
683 u16 *preamble = (u16 *)&rxhdr; 683 ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
684 u16 value; 684 q->mmio_base + B43_PIO_RXDATA,
685 685 sizeof(u16));
686 for (i = 0; i < sizeof(rxhdr); i += 2) {
687 value = b43_piorx_read16(q, B43_PIO_RXDATA);
688 preamble[i / 2] = cpu_to_le16(value);
689 }
690 } 686 }
691 /* Sanity checks. */ 687 /* Sanity checks. */
692 len = le16_to_cpu(rxhdr.frame_len); 688 len = le16_to_cpu(rxhdr.frame_len);
@@ -720,26 +716,37 @@ data_ready:
720 skb_reserve(skb, 2); 716 skb_reserve(skb, 2);
721 skb_put(skb, len + padding); 717 skb_put(skb, len + padding);
722 if (q->rev >= 8) { 718 if (q->rev >= 8) {
723 u32 value; 719 ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
724 720 q->mmio_base + B43_PIO8_RXDATA,
725 for (i = padding; i < len + padding; i += 4) { 721 sizeof(u32));
722 if (len & 3) {
723 u32 value;
724 char *data;
725
726 /* Read the last few bytes. */
726 value = b43_piorx_read32(q, B43_PIO8_RXDATA); 727 value = b43_piorx_read32(q, B43_PIO8_RXDATA);
727 skb->data[i] = value; 728 data = &(skb->data[len + padding - 1]);
728 if ((i + 1) < (len + padding)) 729 switch (len & 3) {
729 skb->data[i + 1] = value >> 8; 730 case 3:
730 if ((i + 2) < (len + padding)) 731 *data = (value >> 16);
731 skb->data[i + 2] = value >> 16; 732 data--;
732 if ((i + 3) < (len + padding)) 733 case 2:
733 skb->data[i + 3] = value >> 24; 734 *data = (value >> 8);
735 data--;
736 case 1:
737 *data = value;
738 }
734 } 739 }
735 } else { 740 } else {
736 u16 value; 741 ssb_block_read(dev->dev, skb->data + padding, (len & ~1),
742 q->mmio_base + B43_PIO_RXDATA,
743 sizeof(u16));
744 if (len & 1) {
745 u16 value;
737 746
738 for (i = padding; i < len + padding; i += 2) { 747 /* Read the last byte. */
739 value = b43_piorx_read16(q, B43_PIO_RXDATA); 748 value = b43_piorx_read16(q, B43_PIO_RXDATA);
740 skb->data[i] = value; 749 skb->data[len + padding - 1] = value;
741 if ((i + 1) < (len + padding))
742 skb->data[i + 1] = value >> 8;
743 } 750 }
744 } 751 }
745 752