3 Broadcom B43legacy wireless driver
7 Copyright (c) 2005 Michael Buesch <mb@bu3sch.de>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22 Boston, MA 02110-1301, USA.
26 #include "b43legacy.h"
31 #include <linux/delay.h>
34 static void tx_start(struct b43legacy_pioqueue
*queue
)
36 b43legacy_pio_write(queue
, B43legacy_PIO_TXCTL
,
37 B43legacy_PIO_TXCTL_INIT
);
40 static void tx_octet(struct b43legacy_pioqueue
*queue
,
43 if (queue
->need_workarounds
) {
44 b43legacy_pio_write(queue
, B43legacy_PIO_TXDATA
, octet
);
45 b43legacy_pio_write(queue
, B43legacy_PIO_TXCTL
,
46 B43legacy_PIO_TXCTL_WRITELO
);
48 b43legacy_pio_write(queue
, B43legacy_PIO_TXCTL
,
49 B43legacy_PIO_TXCTL_WRITELO
);
50 b43legacy_pio_write(queue
, B43legacy_PIO_TXDATA
, octet
);
54 static u16
tx_get_next_word(const u8
*txhdr
,
60 unsigned int i
= *pos
;
69 ret
= le16_to_cpu(*((__le16
*)(source
+ i
)));
75 static void tx_data(struct b43legacy_pioqueue
*queue
,
83 if (queue
->need_workarounds
) {
84 data
= tx_get_next_word(txhdr
, packet
,
85 sizeof(struct b43legacy_txhdr_fw3
), &i
);
86 b43legacy_pio_write(queue
, B43legacy_PIO_TXDATA
, data
);
88 b43legacy_pio_write(queue
, B43legacy_PIO_TXCTL
,
89 B43legacy_PIO_TXCTL_WRITELO
|
90 B43legacy_PIO_TXCTL_WRITEHI
);
91 while (i
< octets
- 1) {
92 data
= tx_get_next_word(txhdr
, packet
,
93 sizeof(struct b43legacy_txhdr_fw3
), &i
);
94 b43legacy_pio_write(queue
, B43legacy_PIO_TXDATA
, data
);
97 tx_octet(queue
, packet
[octets
-
98 sizeof(struct b43legacy_txhdr_fw3
) - 1]);
101 static void tx_complete(struct b43legacy_pioqueue
*queue
,
104 if (queue
->need_workarounds
) {
105 b43legacy_pio_write(queue
, B43legacy_PIO_TXDATA
,
106 skb
->data
[skb
->len
- 1]);
107 b43legacy_pio_write(queue
, B43legacy_PIO_TXCTL
,
108 B43legacy_PIO_TXCTL_WRITELO
|
109 B43legacy_PIO_TXCTL_COMPLETE
);
111 b43legacy_pio_write(queue
, B43legacy_PIO_TXCTL
,
112 B43legacy_PIO_TXCTL_COMPLETE
);
115 static u16
generate_cookie(struct b43legacy_pioqueue
*queue
,
116 struct b43legacy_pio_txpacket
*packet
)
121 /* We use the upper 4 bits for the PIO
122 * controller ID and the lower 12 bits
123 * for the packet index (in the cache).
125 switch (queue
->mmio_base
) {
126 case B43legacy_MMIO_PIO1_BASE
:
128 case B43legacy_MMIO_PIO2_BASE
:
131 case B43legacy_MMIO_PIO3_BASE
:
134 case B43legacy_MMIO_PIO4_BASE
:
138 B43legacy_WARN_ON(1);
140 packetindex
= pio_txpacket_getindex(packet
);
141 B43legacy_WARN_ON(!(((u16
)packetindex
& 0xF000) == 0x0000));
142 cookie
|= (u16
)packetindex
;
148 struct b43legacy_pioqueue
*parse_cookie(struct b43legacy_wldev
*dev
,
150 struct b43legacy_pio_txpacket
**packet
)
152 struct b43legacy_pio
*pio
= &dev
->pio
;
153 struct b43legacy_pioqueue
*queue
= NULL
;
156 switch (cookie
& 0xF000) {
170 B43legacy_WARN_ON(1);
172 packetindex
= (cookie
& 0x0FFF);
173 B43legacy_WARN_ON(!(packetindex
>= 0 && packetindex
174 < B43legacy_PIO_MAXTXPACKETS
));
175 *packet
= &(queue
->tx_packets_cache
[packetindex
]);
181 struct b43legacy_txhdr_fw3 txhdr_fw3
;
184 static void pio_tx_write_fragment(struct b43legacy_pioqueue
*queue
,
186 struct b43legacy_pio_txpacket
*packet
,
189 union txhdr_union txhdr_data
;
193 txhdr
= (u8
*)(&txhdr_data
.txhdr_fw3
);
195 B43legacy_WARN_ON(skb_shinfo(skb
)->nr_frags
!= 0);
196 b43legacy_generate_txhdr(queue
->dev
,
197 txhdr
, skb
->data
, skb
->len
,
198 &packet
->txstat
.control
,
199 generate_cookie(queue
, packet
));
202 octets
= skb
->len
+ txhdr_size
;
203 if (queue
->need_workarounds
)
205 tx_data(queue
, txhdr
, (u8
*)skb
->data
, octets
);
206 tx_complete(queue
, skb
);
209 static void free_txpacket(struct b43legacy_pio_txpacket
*packet
,
212 struct b43legacy_pioqueue
*queue
= packet
->queue
;
216 dev_kfree_skb_irq(packet
->skb
);
218 dev_kfree_skb(packet
->skb
);
220 list_move(&packet
->list
, &queue
->txfree
);
224 static int pio_tx_packet(struct b43legacy_pio_txpacket
*packet
)
226 struct b43legacy_pioqueue
*queue
= packet
->queue
;
227 struct sk_buff
*skb
= packet
->skb
;
230 octets
= (u16
)skb
->len
+ sizeof(struct b43legacy_txhdr_fw3
);
231 if (queue
->tx_devq_size
< octets
) {
232 b43legacywarn(queue
->dev
->wl
, "PIO queue too small. "
233 "Dropping packet.\n");
234 /* Drop it silently (return success) */
235 free_txpacket(packet
, 1);
238 B43legacy_WARN_ON(queue
->tx_devq_packets
>
239 B43legacy_PIO_MAXTXDEVQPACKETS
);
240 B43legacy_WARN_ON(queue
->tx_devq_used
> queue
->tx_devq_size
);
241 /* Check if there is sufficient free space on the device
242 * TX queue. If not, return and let the TX tasklet
245 if (queue
->tx_devq_packets
== B43legacy_PIO_MAXTXDEVQPACKETS
)
247 if (queue
->tx_devq_used
+ octets
> queue
->tx_devq_size
)
249 /* Now poke the device. */
250 pio_tx_write_fragment(queue
, skb
, packet
,
251 sizeof(struct b43legacy_txhdr_fw3
));
253 /* Account for the packet size.
254 * (We must not overflow the device TX queue)
256 queue
->tx_devq_packets
++;
257 queue
->tx_devq_used
+= octets
;
259 /* Transmission started, everything ok, move the
260 * packet to the txrunning list.
262 list_move_tail(&packet
->list
, &queue
->txrunning
);
267 static void tx_tasklet(unsigned long d
)
269 struct b43legacy_pioqueue
*queue
= (struct b43legacy_pioqueue
*)d
;
270 struct b43legacy_wldev
*dev
= queue
->dev
;
272 struct b43legacy_pio_txpacket
*packet
, *tmp_packet
;
276 spin_lock_irqsave(&dev
->wl
->irq_lock
, flags
);
277 if (queue
->tx_frozen
)
279 txctl
= b43legacy_pio_read(queue
, B43legacy_PIO_TXCTL
);
280 if (txctl
& B43legacy_PIO_TXCTL_SUSPEND
)
283 list_for_each_entry_safe(packet
, tmp_packet
, &queue
->txqueue
, list
) {
284 /* Try to transmit the packet. This can fail, if
285 * the device queue is full. In case of failure, the
286 * packet is left in the txqueue.
287 * If transmission succeed, the packet is moved to txrunning.
288 * If it is impossible to transmit the packet, it
291 err
= pio_tx_packet(packet
);
296 spin_unlock_irqrestore(&dev
->wl
->irq_lock
, flags
);
299 static void setup_txqueues(struct b43legacy_pioqueue
*queue
)
301 struct b43legacy_pio_txpacket
*packet
;
304 queue
->nr_txfree
= B43legacy_PIO_MAXTXPACKETS
;
305 for (i
= 0; i
< B43legacy_PIO_MAXTXPACKETS
; i
++) {
306 packet
= &(queue
->tx_packets_cache
[i
]);
308 packet
->queue
= queue
;
309 INIT_LIST_HEAD(&packet
->list
);
311 list_add(&packet
->list
, &queue
->txfree
);
316 struct b43legacy_pioqueue
*b43legacy_setup_pioqueue(struct b43legacy_wldev
*dev
,
319 struct b43legacy_pioqueue
*queue
;
323 queue
= kzalloc(sizeof(*queue
), GFP_KERNEL
);
328 queue
->mmio_base
= pio_mmio_base
;
329 queue
->need_workarounds
= (dev
->dev
->id
.revision
< 3);
331 INIT_LIST_HEAD(&queue
->txfree
);
332 INIT_LIST_HEAD(&queue
->txqueue
);
333 INIT_LIST_HEAD(&queue
->txrunning
);
334 tasklet_init(&queue
->txtask
, tx_tasklet
,
335 (unsigned long)queue
);
337 value
= b43legacy_read32(dev
, B43legacy_MMIO_STATUS_BITFIELD
);
338 value
&= ~B43legacy_SBF_XFER_REG_BYTESWAP
;
339 b43legacy_write32(dev
, B43legacy_MMIO_STATUS_BITFIELD
, value
);
341 qsize
= b43legacy_read16(dev
, queue
->mmio_base
342 + B43legacy_PIO_TXQBUFSIZE
);
344 b43legacyerr(dev
->wl
, "This card does not support PIO "
345 "operation mode. Please use DMA mode "
346 "(module parameter pio=0).\n");
349 if (qsize
<= B43legacy_PIO_TXQADJUST
) {
350 b43legacyerr(dev
->wl
, "PIO tx device-queue too small (%u)\n",
354 qsize
-= B43legacy_PIO_TXQADJUST
;
355 queue
->tx_devq_size
= qsize
;
357 setup_txqueues(queue
);
368 static void cancel_transfers(struct b43legacy_pioqueue
*queue
)
370 struct b43legacy_pio_txpacket
*packet
, *tmp_packet
;
372 tasklet_disable(&queue
->txtask
);
374 list_for_each_entry_safe(packet
, tmp_packet
, &queue
->txrunning
, list
)
375 free_txpacket(packet
, 0);
376 list_for_each_entry_safe(packet
, tmp_packet
, &queue
->txqueue
, list
)
377 free_txpacket(packet
, 0);
380 static void b43legacy_destroy_pioqueue(struct b43legacy_pioqueue
*queue
)
385 cancel_transfers(queue
);
389 void b43legacy_pio_free(struct b43legacy_wldev
*dev
)
391 struct b43legacy_pio
*pio
;
393 if (!b43legacy_using_pio(dev
))
397 b43legacy_destroy_pioqueue(pio
->queue3
);
399 b43legacy_destroy_pioqueue(pio
->queue2
);
401 b43legacy_destroy_pioqueue(pio
->queue1
);
403 b43legacy_destroy_pioqueue(pio
->queue0
);
407 int b43legacy_pio_init(struct b43legacy_wldev
*dev
)
409 struct b43legacy_pio
*pio
= &dev
->pio
;
410 struct b43legacy_pioqueue
*queue
;
413 queue
= b43legacy_setup_pioqueue(dev
, B43legacy_MMIO_PIO1_BASE
);
418 queue
= b43legacy_setup_pioqueue(dev
, B43legacy_MMIO_PIO2_BASE
);
423 queue
= b43legacy_setup_pioqueue(dev
, B43legacy_MMIO_PIO3_BASE
);
428 queue
= b43legacy_setup_pioqueue(dev
, B43legacy_MMIO_PIO4_BASE
);
433 if (dev
->dev
->id
.revision
< 3)
434 dev
->irq_savedstate
|= B43legacy_IRQ_PIO_WORKAROUND
;
436 b43legacydbg(dev
->wl
, "PIO initialized\n");
442 b43legacy_destroy_pioqueue(pio
->queue2
);
445 b43legacy_destroy_pioqueue(pio
->queue1
);
448 b43legacy_destroy_pioqueue(pio
->queue0
);
453 int b43legacy_pio_tx(struct b43legacy_wldev
*dev
,
455 struct ieee80211_tx_control
*ctl
)
457 struct b43legacy_pioqueue
*queue
= dev
->pio
.queue1
;
458 struct b43legacy_pio_txpacket
*packet
;
460 B43legacy_WARN_ON(queue
->tx_suspended
);
461 B43legacy_WARN_ON(list_empty(&queue
->txfree
));
463 packet
= list_entry(queue
->txfree
.next
, struct b43legacy_pio_txpacket
,
467 memset(&packet
->txstat
, 0, sizeof(packet
->txstat
));
468 memcpy(&packet
->txstat
.control
, ctl
, sizeof(*ctl
));
470 list_move_tail(&packet
->list
, &queue
->txqueue
);
472 queue
->nr_tx_packets
++;
473 B43legacy_WARN_ON(queue
->nr_txfree
>= B43legacy_PIO_MAXTXPACKETS
);
475 tasklet_schedule(&queue
->txtask
);
480 void b43legacy_pio_handle_txstatus(struct b43legacy_wldev
*dev
,
481 const struct b43legacy_txstatus
*status
)
483 struct b43legacy_pioqueue
*queue
;
484 struct b43legacy_pio_txpacket
*packet
;
486 queue
= parse_cookie(dev
, status
->cookie
, &packet
);
487 B43legacy_WARN_ON(!queue
);
489 queue
->tx_devq_packets
--;
490 queue
->tx_devq_used
-= (packet
->skb
->len
+
491 sizeof(struct b43legacy_txhdr_fw3
));
494 packet
->txstat
.flags
|= IEEE80211_TX_STATUS_ACK
;
495 packet
->txstat
.retry_count
= status
->frame_count
- 1;
496 ieee80211_tx_status_irqsafe(dev
->wl
->hw
, packet
->skb
,
500 free_txpacket(packet
, 1);
501 /* If there are packets on the txqueue, poke the tasklet
504 if (!list_empty(&queue
->txqueue
))
505 tasklet_schedule(&queue
->txtask
);
508 void b43legacy_pio_get_tx_stats(struct b43legacy_wldev
*dev
,
509 struct ieee80211_tx_queue_stats
*stats
)
511 struct b43legacy_pio
*pio
= &dev
->pio
;
512 struct b43legacy_pioqueue
*queue
;
513 struct ieee80211_tx_queue_stats_data
*data
;
516 data
= &(stats
->data
[0]);
517 data
->len
= B43legacy_PIO_MAXTXPACKETS
- queue
->nr_txfree
;
518 data
->limit
= B43legacy_PIO_MAXTXPACKETS
;
519 data
->count
= queue
->nr_tx_packets
;
522 static void pio_rx_error(struct b43legacy_pioqueue
*queue
,
528 b43legacyerr(queue
->dev
->wl
, "PIO RX error: %s\n", error
);
529 b43legacy_pio_write(queue
, B43legacy_PIO_RXCTL
,
530 B43legacy_PIO_RXCTL_READY
);
532 B43legacy_WARN_ON(queue
->mmio_base
!= B43legacy_MMIO_PIO1_BASE
);
533 for (i
= 0; i
< 15; i
++) {
535 b43legacy_pio_read(queue
, B43legacy_PIO_RXDATA
);
540 void b43legacy_pio_rx(struct b43legacy_pioqueue
*queue
)
542 __le16 preamble
[21] = { 0 };
543 struct b43legacy_rxhdr_fw3
*rxhdr
;
548 int preamble_readwords
;
551 tmp
= b43legacy_pio_read(queue
, B43legacy_PIO_RXCTL
);
552 if (!(tmp
& B43legacy_PIO_RXCTL_DATAAVAILABLE
))
554 b43legacy_pio_write(queue
, B43legacy_PIO_RXCTL
,
555 B43legacy_PIO_RXCTL_DATAAVAILABLE
);
557 for (i
= 0; i
< 10; i
++) {
558 tmp
= b43legacy_pio_read(queue
, B43legacy_PIO_RXCTL
);
559 if (tmp
& B43legacy_PIO_RXCTL_READY
)
563 b43legacydbg(queue
->dev
->wl
, "PIO RX timed out\n");
567 len
= b43legacy_pio_read(queue
, B43legacy_PIO_RXDATA
);
568 if (unlikely(len
> 0x700)) {
569 pio_rx_error(queue
, 0, "len > 0x700");
572 if (unlikely(len
== 0 && queue
->mmio_base
!=
573 B43legacy_MMIO_PIO4_BASE
)) {
574 pio_rx_error(queue
, 0, "len == 0");
577 preamble
[0] = cpu_to_le16(len
);
578 if (queue
->mmio_base
== B43legacy_MMIO_PIO4_BASE
)
579 preamble_readwords
= 14 / sizeof(u16
);
581 preamble_readwords
= 18 / sizeof(u16
);
582 for (i
= 0; i
< preamble_readwords
; i
++) {
583 tmp
= b43legacy_pio_read(queue
, B43legacy_PIO_RXDATA
);
584 preamble
[i
+ 1] = cpu_to_le16(tmp
);
586 rxhdr
= (struct b43legacy_rxhdr_fw3
*)preamble
;
587 macstat
= le16_to_cpu(rxhdr
->mac_status
);
588 if (macstat
& B43legacy_RX_MAC_FCSERR
) {
590 (queue
->mmio_base
== B43legacy_MMIO_PIO1_BASE
),
594 if (queue
->mmio_base
== B43legacy_MMIO_PIO4_BASE
) {
595 /* We received an xmit status. */
596 struct b43legacy_hwtxstatus
*hw
;
598 hw
= (struct b43legacy_hwtxstatus
*)(preamble
+ 1);
599 b43legacy_handle_hwtxstatus(queue
->dev
, hw
);
604 skb
= dev_alloc_skb(len
);
605 if (unlikely(!skb
)) {
606 pio_rx_error(queue
, 1, "OOM");
610 for (i
= 0; i
< len
- 1; i
+= 2) {
611 tmp
= b43legacy_pio_read(queue
, B43legacy_PIO_RXDATA
);
612 *((__le16
*)(skb
->data
+ i
)) = cpu_to_le16(tmp
);
615 tmp
= b43legacy_pio_read(queue
, B43legacy_PIO_RXDATA
);
616 skb
->data
[len
- 1] = (tmp
& 0x00FF);
618 b43legacy_rx(queue
->dev
, skb
, rxhdr
);
621 void b43legacy_pio_tx_suspend(struct b43legacy_pioqueue
*queue
)
623 b43legacy_power_saving_ctl_bits(queue
->dev
, -1, 1);
624 b43legacy_pio_write(queue
, B43legacy_PIO_TXCTL
,
625 b43legacy_pio_read(queue
, B43legacy_PIO_TXCTL
)
626 | B43legacy_PIO_TXCTL_SUSPEND
);
629 void b43legacy_pio_tx_resume(struct b43legacy_pioqueue
*queue
)
631 b43legacy_pio_write(queue
, B43legacy_PIO_TXCTL
,
632 b43legacy_pio_read(queue
, B43legacy_PIO_TXCTL
)
633 & ~B43legacy_PIO_TXCTL_SUSPEND
);
634 b43legacy_power_saving_ctl_bits(queue
->dev
, -1, -1);
635 tasklet_schedule(&queue
->txtask
);
638 void b43legacy_pio_freeze_txqueues(struct b43legacy_wldev
*dev
)
640 struct b43legacy_pio
*pio
;
642 B43legacy_WARN_ON(!b43legacy_using_pio(dev
));
644 pio
->queue0
->tx_frozen
= 1;
645 pio
->queue1
->tx_frozen
= 1;
646 pio
->queue2
->tx_frozen
= 1;
647 pio
->queue3
->tx_frozen
= 1;
650 void b43legacy_pio_thaw_txqueues(struct b43legacy_wldev
*dev
)
652 struct b43legacy_pio
*pio
;
654 B43legacy_WARN_ON(!b43legacy_using_pio(dev
));
656 pio
->queue0
->tx_frozen
= 0;
657 pio
->queue1
->tx_frozen
= 0;
658 pio
->queue2
->tx_frozen
= 0;
659 pio
->queue3
->tx_frozen
= 0;
660 if (!list_empty(&pio
->queue0
->txqueue
))
661 tasklet_schedule(&pio
->queue0
->txtask
);
662 if (!list_empty(&pio
->queue1
->txqueue
))
663 tasklet_schedule(&pio
->queue1
->txtask
);
664 if (!list_empty(&pio
->queue2
->txqueue
))
665 tasklet_schedule(&pio
->queue2
->txtask
);
666 if (!list_empty(&pio
->queue3
->txqueue
))
667 tasklet_schedule(&pio
->queue3
->txtask
);