aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2006-04-23 07:23:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-04-24 15:20:24 -0400
commit7c241d37fe0e6442c5cf3b5d73f7f58f2dc66352 (patch)
tree2172f8cd2947064be0fea940eace4d78697948c7 /drivers/net
parent9eac8f95d1bb2cec96340505bed2d2387780821f (diff)
[PATCH] bcm43xx: make PIO mode usable
This patch fixes PIO mode on the softmac bcm43xx driver. (A dscape patch will follow). It mainly fixes endianess issues. This patch is tested on PowerPC32 and i386. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.h8
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c92
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.h16
3 files changed, 84 insertions, 32 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
index 2d520e4b0276..b7d77638ba8c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -213,6 +213,14 @@ static inline
213void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) 213void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
214{ 214{
215} 215}
216static inline
217void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
218{
219}
220static inline
221void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
222{
223}
216 224
217#endif /* CONFIG_BCM43XX_DMA */ 225#endif /* CONFIG_BCM43XX_DMA */
218#endif /* BCM43xx_DMA_H_ */ 226#endif /* BCM43xx_DMA_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index c59ddd40680d..0aa1bd269a25 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -27,6 +27,7 @@
27#include "bcm43xx_pio.h" 27#include "bcm43xx_pio.h"
28#include "bcm43xx_main.h" 28#include "bcm43xx_main.h"
29#include "bcm43xx_xmit.h" 29#include "bcm43xx_xmit.h"
30#include "bcm43xx_power.h"
30 31
31#include <linux/delay.h> 32#include <linux/delay.h>
32 33
@@ -44,10 +45,10 @@ static void tx_octet(struct bcm43xx_pioqueue *queue,
44 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, 45 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
45 octet); 46 octet);
46 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, 47 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
47 BCM43xx_PIO_TXCTL_WRITEHI); 48 BCM43xx_PIO_TXCTL_WRITELO);
48 } else { 49 } else {
49 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, 50 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
50 BCM43xx_PIO_TXCTL_WRITEHI); 51 BCM43xx_PIO_TXCTL_WRITELO);
51 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, 52 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
52 octet); 53 octet);
53 } 54 }
@@ -103,7 +104,7 @@ static void tx_complete(struct bcm43xx_pioqueue *queue,
103 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, 104 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
104 skb->data[skb->len - 1]); 105 skb->data[skb->len - 1]);
105 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, 106 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
106 BCM43xx_PIO_TXCTL_WRITEHI | 107 BCM43xx_PIO_TXCTL_WRITELO |
107 BCM43xx_PIO_TXCTL_COMPLETE); 108 BCM43xx_PIO_TXCTL_COMPLETE);
108 } else { 109 } else {
109 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, 110 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
@@ -112,9 +113,10 @@ static void tx_complete(struct bcm43xx_pioqueue *queue,
112} 113}
113 114
114static u16 generate_cookie(struct bcm43xx_pioqueue *queue, 115static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
115 int packetindex) 116 struct bcm43xx_pio_txpacket *packet)
116{ 117{
117 u16 cookie = 0x0000; 118 u16 cookie = 0x0000;
119 int packetindex;
118 120
119 /* We use the upper 4 bits for the PIO 121 /* We use the upper 4 bits for the PIO
120 * controller ID and the lower 12 bits 122 * controller ID and the lower 12 bits
@@ -135,6 +137,7 @@ static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
135 default: 137 default:
136 assert(0); 138 assert(0);
137 } 139 }
140 packetindex = pio_txpacket_getindex(packet);
138 assert(((u16)packetindex & 0xF000) == 0x0000); 141 assert(((u16)packetindex & 0xF000) == 0x0000);
139 cookie |= (u16)packetindex; 142 cookie |= (u16)packetindex;
140 143
@@ -184,7 +187,7 @@ static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
184 bcm43xx_generate_txhdr(queue->bcm, 187 bcm43xx_generate_txhdr(queue->bcm,
185 &txhdr, skb->data, skb->len, 188 &txhdr, skb->data, skb->len,
186 (packet->xmitted_frags == 0), 189 (packet->xmitted_frags == 0),
187 generate_cookie(queue, pio_txpacket_getindex(packet))); 190 generate_cookie(queue, packet));
188 191
189 tx_start(queue); 192 tx_start(queue);
190 octets = skb->len + sizeof(txhdr); 193 octets = skb->len + sizeof(txhdr);
@@ -241,7 +244,7 @@ static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
241 queue->tx_devq_packets++; 244 queue->tx_devq_packets++;
242 queue->tx_devq_used += octets; 245 queue->tx_devq_used += octets;
243 246
244 assert(packet->xmitted_frags <= packet->txb->nr_frags); 247 assert(packet->xmitted_frags < packet->txb->nr_frags);
245 packet->xmitted_frags++; 248 packet->xmitted_frags++;
246 packet->xmitted_octets += octets; 249 packet->xmitted_octets += octets;
247 } 250 }
@@ -257,8 +260,14 @@ static void tx_tasklet(unsigned long d)
257 unsigned long flags; 260 unsigned long flags;
258 struct bcm43xx_pio_txpacket *packet, *tmp_packet; 261 struct bcm43xx_pio_txpacket *packet, *tmp_packet;
259 int err; 262 int err;
263 u16 txctl;
260 264
261 bcm43xx_lock_mmio(bcm, flags); 265 bcm43xx_lock_mmio(bcm, flags);
266
267 txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
268 if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
269 goto out_unlock;
270
262 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { 271 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
263 assert(packet->xmitted_frags < packet->txb->nr_frags); 272 assert(packet->xmitted_frags < packet->txb->nr_frags);
264 if (packet->xmitted_frags == 0) { 273 if (packet->xmitted_frags == 0) {
@@ -288,6 +297,7 @@ static void tx_tasklet(unsigned long d)
288 next_packet: 297 next_packet:
289 continue; 298 continue;
290 } 299 }
300out_unlock:
291 bcm43xx_unlock_mmio(bcm, flags); 301 bcm43xx_unlock_mmio(bcm, flags);
292} 302}
293 303
@@ -330,12 +340,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
330 (unsigned long)queue); 340 (unsigned long)queue);
331 341
332 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); 342 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
333 value |= BCM43xx_SBF_XFER_REG_BYTESWAP; 343 value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
334 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); 344 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
335 345
336 qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); 346 qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
347 if (qsize == 0) {
348 printk(KERN_ERR PFX "ERROR: This card does not support PIO "
349 "operation mode. Please use DMA mode "
350 "(module parameter pio=0).\n");
351 goto err_freequeue;
352 }
337 if (qsize <= BCM43xx_PIO_TXQADJUST) { 353 if (qsize <= BCM43xx_PIO_TXQADJUST) {
338 printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize); 354 printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
355 qsize);
339 goto err_freequeue; 356 goto err_freequeue;
340 } 357 }
341 qsize -= BCM43xx_PIO_TXQADJUST; 358 qsize -= BCM43xx_PIO_TXQADJUST;
@@ -444,15 +461,10 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
444{ 461{
445 struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; 462 struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
446 struct bcm43xx_pio_txpacket *packet; 463 struct bcm43xx_pio_txpacket *packet;
447 u16 tmp;
448 464
449 assert(!queue->tx_suspended); 465 assert(!queue->tx_suspended);
450 assert(!list_empty(&queue->txfree)); 466 assert(!list_empty(&queue->txfree));
451 467
452 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
453 if (tmp & BCM43xx_PIO_TXCTL_SUSPEND)
454 return -EBUSY;
455
456 packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); 468 packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
457 packet->txb = txb; 469 packet->txb = txb;
458 packet->xmitted_frags = 0; 470 packet->xmitted_frags = 0;
@@ -462,7 +474,7 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
462 assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); 474 assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
463 475
464 /* Suspend TX, if we are out of packets in the "free" queue. */ 476 /* Suspend TX, if we are out of packets in the "free" queue. */
465 if (unlikely(list_empty(&queue->txfree))) { 477 if (list_empty(&queue->txfree)) {
466 netif_stop_queue(queue->bcm->net_dev); 478 netif_stop_queue(queue->bcm->net_dev);
467 queue->tx_suspended = 1; 479 queue->tx_suspended = 1;
468 } 480 }
@@ -480,15 +492,15 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
480 492
481 queue = parse_cookie(bcm, status->cookie, &packet); 493 queue = parse_cookie(bcm, status->cookie, &packet);
482 assert(queue); 494 assert(queue);
483//TODO 495
484if (!queue)
485return;
486 free_txpacket(packet, 1); 496 free_txpacket(packet, 1);
487 if (unlikely(queue->tx_suspended)) { 497 if (queue->tx_suspended) {
488 queue->tx_suspended = 0; 498 queue->tx_suspended = 0;
489 netif_wake_queue(queue->bcm->net_dev); 499 netif_wake_queue(queue->bcm->net_dev);
490 } 500 }
491 /* If there are packets on the txqueue, poke the tasklet. */ 501 /* If there are packets on the txqueue, poke the tasklet
502 * to transmit them.
503 */
492 if (!list_empty(&queue->txqueue)) 504 if (!list_empty(&queue->txqueue))
493 tasklet_schedule(&queue->txtask); 505 tasklet_schedule(&queue->txtask);
494} 506}
@@ -519,12 +531,9 @@ void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
519 int i, preamble_readwords; 531 int i, preamble_readwords;
520 struct sk_buff *skb; 532 struct sk_buff *skb;
521 533
522return;
523 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); 534 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
524 if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { 535 if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
525 dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk.
526 return; 536 return;
527 }
528 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, 537 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
529 BCM43xx_PIO_RXCTL_DATAAVAILABLE); 538 BCM43xx_PIO_RXCTL_DATAAVAILABLE);
530 539
@@ -538,8 +547,7 @@ return;
538 return; 547 return;
539data_ready: 548data_ready:
540 549
541//FIXME: endianess in this function. 550 len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
542 len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
543 if (unlikely(len > 0x700)) { 551 if (unlikely(len > 0x700)) {
544 pio_rx_error(queue, 0, "len > 0x700"); 552 pio_rx_error(queue, 0, "len > 0x700");
545 return; 553 return;
@@ -555,7 +563,7 @@ data_ready:
555 preamble_readwords = 18 / sizeof(u16); 563 preamble_readwords = 18 / sizeof(u16);
556 for (i = 0; i < preamble_readwords; i++) { 564 for (i = 0; i < preamble_readwords; i++) {
557 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); 565 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
558 preamble[i + 1] = cpu_to_be16(tmp);//FIXME? 566 preamble[i + 1] = cpu_to_le16(tmp);
559 } 567 }
560 rxhdr = (struct bcm43xx_rxhdr *)preamble; 568 rxhdr = (struct bcm43xx_rxhdr *)preamble;
561 rxflags2 = le16_to_cpu(rxhdr->flags2); 569 rxflags2 = le16_to_cpu(rxhdr->flags2);
@@ -591,16 +599,40 @@ data_ready:
591 } 599 }
592 skb_put(skb, len); 600 skb_put(skb, len);
593 for (i = 0; i < len - 1; i += 2) { 601 for (i = 0; i < len - 1; i += 2) {
594 tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); 602 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
595 *((u16 *)(skb->data + i)) = tmp; 603 *((u16 *)(skb->data + i)) = cpu_to_le16(tmp);
596 } 604 }
597 if (len % 2) { 605 if (len % 2) {
598 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); 606 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
599 skb->data[len - 1] = (tmp & 0x00FF); 607 skb->data[len - 1] = (tmp & 0x00FF);
608/* The specs say the following is required, but
609 * it is wrong and corrupts the PLCP. If we don't do
610 * this, the PLCP seems to be correct. So ifdef it out for now.
611 */
612#if 0
600 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) 613 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
601 skb->data[0x20] = (tmp & 0xFF00) >> 8; 614 skb->data[2] = (tmp & 0xFF00) >> 8;
602 else 615 else
603 skb->data[0x1E] = (tmp & 0xFF00) >> 8; 616 skb->data[0] = (tmp & 0xFF00) >> 8;
617#endif
604 } 618 }
619 skb_trim(skb, len - IEEE80211_FCS_LEN);
605 bcm43xx_rx(queue->bcm, skb, rxhdr); 620 bcm43xx_rx(queue->bcm, skb, rxhdr);
606} 621}
622
623void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
624{
625 bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
626 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
627 bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
628 | BCM43xx_PIO_TXCTL_SUSPEND);
629}
630
631void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
632{
633 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
634 bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
635 & ~BCM43xx_PIO_TXCTL_SUSPEND);
636 bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
637 tasklet_schedule(&queue->txtask);
638}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
index 970627bc1769..dfc78209e3a3 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
@@ -14,8 +14,8 @@
14#define BCM43xx_PIO_RXCTL 0x08 14#define BCM43xx_PIO_RXCTL 0x08
15#define BCM43xx_PIO_RXDATA 0x0A 15#define BCM43xx_PIO_RXDATA 0x0A
16 16
17#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0) 17#define BCM43xx_PIO_TXCTL_WRITELO (1 << 0)
18#define BCM43xx_PIO_TXCTL_WRITELO (1 << 1) 18#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1)
19#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) 19#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2)
20#define BCM43xx_PIO_TXCTL_INIT (1 << 3) 20#define BCM43xx_PIO_TXCTL_INIT (1 << 3)
21#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) 21#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7)
@@ -95,6 +95,7 @@ void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
95 u16 offset, u16 value) 95 u16 offset, u16 value)
96{ 96{
97 bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); 97 bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
98 mmiowb();
98} 99}
99 100
100 101
@@ -107,6 +108,9 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
107 struct bcm43xx_xmitstatus *status); 108 struct bcm43xx_xmitstatus *status);
108void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); 109void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
109 110
111void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
112void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
113
110#else /* CONFIG_BCM43XX_PIO */ 114#else /* CONFIG_BCM43XX_PIO */
111 115
112static inline 116static inline
@@ -133,6 +137,14 @@ static inline
133void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) 137void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
134{ 138{
135} 139}
140static inline
141void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
142{
143}
144static inline
145void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
146{
147}
136 148
137#endif /* CONFIG_BCM43XX_PIO */ 149#endif /* CONFIG_BCM43XX_PIO */
138#endif /* BCM43xx_PIO_H_ */ 150#endif /* BCM43xx_PIO_H_ */