1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3
4 Broadcom B43 wireless driver
5
6 PIO data transfer
7
8 Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
9
10
11*/
12
13#include "b43.h"
14#include "pio.h"
15#include "dma.h"
16#include "main.h"
17#include "xmit.h"
18
19#include <linux/delay.h>
20#include <linux/sched.h>
21#include <linux/slab.h>
22
23
24static u16 generate_cookie(struct b43_pio_txqueue *q,
25 struct b43_pio_txpacket *pack)
26{
27 u16 cookie;
28
29 /* Use the upper 4 bits of the cookie as
30 * PIO controller ID and store the packet index number
31 * in the lower 12 bits.
32 * Note that the cookie must never be 0, as this
33 * is a special value used in RX path.
34 * It can also not be 0xFFFF because that is special
35 * for multicast frames.
36 */
37 cookie = (((u16)q->index + 1) << 12);
38 cookie |= pack->index;
39
40 return cookie;
41}
42
43static
44struct b43_pio_txqueue *parse_cookie(struct b43_wldev *dev,
45 u16 cookie,
46 struct b43_pio_txpacket **pack)
47{
48 struct b43_pio *pio = &dev->pio;
49 struct b43_pio_txqueue *q = NULL;
50 unsigned int pack_index;
51
52 switch (cookie & 0xF000) {
53 case 0x1000:
54 q = pio->tx_queue_AC_BK;
55 break;
56 case 0x2000:
57 q = pio->tx_queue_AC_BE;
58 break;
59 case 0x3000:
60 q = pio->tx_queue_AC_VI;
61 break;
62 case 0x4000:
63 q = pio->tx_queue_AC_VO;
64 break;
65 case 0x5000:
66 q = pio->tx_queue_mcast;
67 break;
68 }
69 if (B43_WARN_ON(!q))
70 return NULL;
71 pack_index = (cookie & 0x0FFF);
72 if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
73 return NULL;
74 *pack = &q->packets[pack_index];
75
76 return q;
77}
78
79static u16 index_to_pioqueue_base(struct b43_wldev *dev,
80 unsigned int index)
81{
82 static const u16 bases[] = {
83 B43_MMIO_PIO_BASE0,
84 B43_MMIO_PIO_BASE1,
85 B43_MMIO_PIO_BASE2,
86 B43_MMIO_PIO_BASE3,
87 B43_MMIO_PIO_BASE4,
88 B43_MMIO_PIO_BASE5,
89 B43_MMIO_PIO_BASE6,
90 B43_MMIO_PIO_BASE7,
91 };
92 static const u16 bases_rev11[] = {
93 B43_MMIO_PIO11_BASE0,
94 B43_MMIO_PIO11_BASE1,
95 B43_MMIO_PIO11_BASE2,
96 B43_MMIO_PIO11_BASE3,
97 B43_MMIO_PIO11_BASE4,
98 B43_MMIO_PIO11_BASE5,
99 };
100
101 if (dev->dev->core_rev >= 11) {
102 B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
103 return bases_rev11[index];
104 }
105 B43_WARN_ON(index >= ARRAY_SIZE(bases));
106 return bases[index];
107}
108
109static u16 pio_txqueue_offset(struct b43_wldev *dev)
110{
111 if (dev->dev->core_rev >= 11)
112 return 0x18;
113 return 0;
114}
115
116static u16 pio_rxqueue_offset(struct b43_wldev *dev)
117{
118 if (dev->dev->core_rev >= 11)
119 return 0x38;
120 return 8;
121}
122
123static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
124 unsigned int index)
125{
126 struct b43_pio_txqueue *q;
127 struct b43_pio_txpacket *p;
128 unsigned int i;
129
130 q = kzalloc(size: sizeof(*q), GFP_KERNEL);
131 if (!q)
132 return NULL;
133 q->dev = dev;
134 q->rev = dev->dev->core_rev;
135 q->mmio_base = index_to_pioqueue_base(dev, index) +
136 pio_txqueue_offset(dev);
137 q->index = index;
138
139 q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
140 if (q->rev >= 8) {
141 q->buffer_size = 1920; //FIXME this constant is wrong.
142 } else {
143 q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
144 q->buffer_size -= 80;
145 }
146
147 INIT_LIST_HEAD(list: &q->packets_list);
148 for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
149 p = &(q->packets[i]);
150 INIT_LIST_HEAD(list: &p->list);
151 p->index = i;
152 p->queue = q;
153 list_add(new: &p->list, head: &q->packets_list);
154 }
155
156 return q;
157}
158
159static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
160 unsigned int index)
161{
162 struct b43_pio_rxqueue *q;
163
164 q = kzalloc(size: sizeof(*q), GFP_KERNEL);
165 if (!q)
166 return NULL;
167 q->dev = dev;
168 q->rev = dev->dev->core_rev;
169 q->mmio_base = index_to_pioqueue_base(dev, index) +
170 pio_rxqueue_offset(dev);
171
172 /* Enable Direct FIFO RX (PIO) on the engine. */
173 b43_dma_direct_fifo_rx(dev, engine_index: index, enable: 1);
174
175 return q;
176}
177
178static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
179{
180 struct b43_pio_txpacket *pack;
181 unsigned int i;
182
183 for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
184 pack = &(q->packets[i]);
185 if (pack->skb) {
186 ieee80211_free_txskb(hw: q->dev->wl->hw, skb: pack->skb);
187 pack->skb = NULL;
188 }
189 }
190}
191
192static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
193 const char *name)
194{
195 if (!q)
196 return;
197 b43_pio_cancel_tx_packets(q);
198 kfree(objp: q);
199}
200
201static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
202 const char *name)
203{
204 if (!q)
205 return;
206 kfree(objp: q);
207}
208
209#define destroy_queue_tx(pio, queue) do { \
210 b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \
211 (pio)->queue = NULL; \
212 } while (0)
213
214#define destroy_queue_rx(pio, queue) do { \
215 b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \
216 (pio)->queue = NULL; \
217 } while (0)
218
219void b43_pio_free(struct b43_wldev *dev)
220{
221 struct b43_pio *pio;
222
223 if (!b43_using_pio_transfers(dev))
224 return;
225 pio = &dev->pio;
226
227 destroy_queue_rx(pio, rx_queue);
228 destroy_queue_tx(pio, tx_queue_mcast);
229 destroy_queue_tx(pio, tx_queue_AC_VO);
230 destroy_queue_tx(pio, tx_queue_AC_VI);
231 destroy_queue_tx(pio, tx_queue_AC_BE);
232 destroy_queue_tx(pio, tx_queue_AC_BK);
233}
234
235int b43_pio_init(struct b43_wldev *dev)
236{
237 struct b43_pio *pio = &dev->pio;
238 int err = -ENOMEM;
239
240 b43_write32(dev, B43_MMIO_MACCTL, value: b43_read32(dev, B43_MMIO_MACCTL)
241 & ~B43_MACCTL_BE);
242 b43_shm_write16(dev, routing: B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, value: 0);
243
244 pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, index: 0);
245 if (!pio->tx_queue_AC_BK)
246 goto out;
247
248 pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, index: 1);
249 if (!pio->tx_queue_AC_BE)
250 goto err_destroy_bk;
251
252 pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, index: 2);
253 if (!pio->tx_queue_AC_VI)
254 goto err_destroy_be;
255
256 pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, index: 3);
257 if (!pio->tx_queue_AC_VO)
258 goto err_destroy_vi;
259
260 pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, index: 4);
261 if (!pio->tx_queue_mcast)
262 goto err_destroy_vo;
263
264 pio->rx_queue = b43_setup_pioqueue_rx(dev, index: 0);
265 if (!pio->rx_queue)
266 goto err_destroy_mcast;
267
268 b43dbg(wl: dev->wl, fmt: "PIO initialized\n");
269 err = 0;
270out:
271 return err;
272
273err_destroy_mcast:
274 destroy_queue_tx(pio, tx_queue_mcast);
275err_destroy_vo:
276 destroy_queue_tx(pio, tx_queue_AC_VO);
277err_destroy_vi:
278 destroy_queue_tx(pio, tx_queue_AC_VI);
279err_destroy_be:
280 destroy_queue_tx(pio, tx_queue_AC_BE);
281err_destroy_bk:
282 destroy_queue_tx(pio, tx_queue_AC_BK);
283 return err;
284}
285
286/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
287static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev,
288 u8 queue_prio)
289{
290 struct b43_pio_txqueue *q;
291
292 if (dev->qos_enabled) {
293 /* 0 = highest priority */
294 switch (queue_prio) {
295 default:
296 B43_WARN_ON(1);
297 fallthrough;
298 case 0:
299 q = dev->pio.tx_queue_AC_VO;
300 break;
301 case 1:
302 q = dev->pio.tx_queue_AC_VI;
303 break;
304 case 2:
305 q = dev->pio.tx_queue_AC_BE;
306 break;
307 case 3:
308 q = dev->pio.tx_queue_AC_BK;
309 break;
310 }
311 } else
312 q = dev->pio.tx_queue_AC_BE;
313
314 return q;
315}
316
317static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
318 u16 ctl,
319 const void *_data,
320 unsigned int data_len)
321{
322 struct b43_wldev *dev = q->dev;
323 struct b43_wl *wl = dev->wl;
324 const u8 *data = _data;
325
326 ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
327 b43_piotx_write16(q, B43_PIO_TXCTL, value: ctl);
328
329 b43_block_write(dev, buffer: data, count: (data_len & ~1),
330 offset: q->mmio_base + B43_PIO_TXDATA,
331 reg_width: sizeof(u16));
332 if (data_len & 1) {
333 u8 *tail = wl->pio_tailspace;
334 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
335
336 /* Write the last byte. */
337 ctl &= ~B43_PIO_TXCTL_WRITEHI;
338 b43_piotx_write16(q, B43_PIO_TXCTL, value: ctl);
339 tail[0] = data[data_len - 1];
340 tail[1] = 0;
341 b43_block_write(dev, buffer: tail, count: 2,
342 offset: q->mmio_base + B43_PIO_TXDATA,
343 reg_width: sizeof(u16));
344 }
345
346 return ctl;
347}
348
349static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
350 const u8 *hdr, unsigned int hdrlen)
351{
352 struct b43_pio_txqueue *q = pack->queue;
353 const char *frame = pack->skb->data;
354 unsigned int frame_len = pack->skb->len;
355 u16 ctl;
356
357 ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
358 ctl |= B43_PIO_TXCTL_FREADY;
359 ctl &= ~B43_PIO_TXCTL_EOF;
360
361 /* Transfer the header data. */
362 ctl = tx_write_2byte_queue(q, ctl, data: hdr, data_len: hdrlen);
363 /* Transfer the frame data. */
364 ctl = tx_write_2byte_queue(q, ctl, data: frame, data_len: frame_len);
365
366 ctl |= B43_PIO_TXCTL_EOF;
367 b43_piotx_write16(q, B43_PIO_TXCTL, value: ctl);
368}
369
370static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
371 u32 ctl,
372 const void *_data,
373 unsigned int data_len)
374{
375 struct b43_wldev *dev = q->dev;
376 struct b43_wl *wl = dev->wl;
377 const u8 *data = _data;
378
379 ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
380 B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
381 b43_piotx_write32(q, B43_PIO8_TXCTL, value: ctl);
382
383 b43_block_write(dev, buffer: data, count: (data_len & ~3),
384 offset: q->mmio_base + B43_PIO8_TXDATA,
385 reg_width: sizeof(u32));
386 if (data_len & 3) {
387 u8 *tail = wl->pio_tailspace;
388 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
389
390 memset(tail, 0, 4);
391 /* Write the last few bytes. */
392 ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
393 B43_PIO8_TXCTL_24_31);
394 switch (data_len & 3) {
395 case 3:
396 ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
397 tail[0] = data[data_len - 3];
398 tail[1] = data[data_len - 2];
399 tail[2] = data[data_len - 1];
400 break;
401 case 2:
402 ctl |= B43_PIO8_TXCTL_8_15;
403 tail[0] = data[data_len - 2];
404 tail[1] = data[data_len - 1];
405 break;
406 case 1:
407 tail[0] = data[data_len - 1];
408 break;
409 }
410 b43_piotx_write32(q, B43_PIO8_TXCTL, value: ctl);
411 b43_block_write(dev, buffer: tail, count: 4,
412 offset: q->mmio_base + B43_PIO8_TXDATA,
413 reg_width: sizeof(u32));
414 }
415
416 return ctl;
417}
418
419static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
420 const u8 *hdr, unsigned int hdrlen)
421{
422 struct b43_pio_txqueue *q = pack->queue;
423 const char *frame = pack->skb->data;
424 unsigned int frame_len = pack->skb->len;
425 u32 ctl;
426
427 ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
428 ctl |= B43_PIO8_TXCTL_FREADY;
429 ctl &= ~B43_PIO8_TXCTL_EOF;
430
431 /* Transfer the header data. */
432 ctl = tx_write_4byte_queue(q, ctl, data: hdr, data_len: hdrlen);
433 /* Transfer the frame data. */
434 ctl = tx_write_4byte_queue(q, ctl, data: frame, data_len: frame_len);
435
436 ctl |= B43_PIO8_TXCTL_EOF;
437 b43_piotx_write32(q, B43_PIO_TXCTL, value: ctl);
438}
439
440static int pio_tx_frame(struct b43_pio_txqueue *q,
441 struct sk_buff *skb)
442{
443 struct b43_wldev *dev = q->dev;
444 struct b43_wl *wl = dev->wl;
445 struct b43_pio_txpacket *pack;
446 u16 cookie;
447 int err;
448 unsigned int hdrlen;
449 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
450 struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
451
452 B43_WARN_ON(list_empty(&q->packets_list));
453 pack = list_entry(q->packets_list.next,
454 struct b43_pio_txpacket, list);
455
456 cookie = generate_cookie(q, pack);
457 hdrlen = b43_txhdr_size(dev);
458 BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
459 B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
460 err = b43_generate_txhdr(dev, txhdr: (u8 *)txhdr, skb_frag: skb,
461 txctl: info, cookie);
462 if (err)
463 return err;
464
465 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
466 /* Tell the firmware about the cookie of the last
467 * mcast frame, so it can clear the more-data bit in it. */
468 b43_shm_write16(dev, routing: B43_SHM_SHARED,
469 B43_SHM_SH_MCASTCOOKIE, value: cookie);
470 }
471
472 pack->skb = skb;
473 if (q->rev >= 8)
474 pio_tx_frame_4byte_queue(pack, hdr: (const u8 *)txhdr, hdrlen);
475 else
476 pio_tx_frame_2byte_queue(pack, hdr: (const u8 *)txhdr, hdrlen);
477
478 /* Remove it from the list of available packet slots.
479 * It will be put back when we receive the status report. */
480 list_del(entry: &pack->list);
481
482 /* Update the queue statistics. */
483 q->buffer_used += roundup(skb->len + hdrlen, 4);
484 q->free_packet_slots -= 1;
485
486 return 0;
487}
488
489int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
490{
491 struct b43_pio_txqueue *q;
492 struct ieee80211_hdr *hdr;
493 unsigned int hdrlen, total_len;
494 int err = 0;
495 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
496
497 hdr = (struct ieee80211_hdr *)skb->data;
498
499 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
500 /* The multicast queue will be sent after the DTIM. */
501 q = dev->pio.tx_queue_mcast;
502 /* Set the frame More-Data bit. Ucode will clear it
503 * for us on the last frame. */
504 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
505 } else {
506 /* Decide by priority where to put this frame. */
507 q = select_queue_by_priority(dev, queue_prio: skb_get_queue_mapping(skb));
508 }
509
510 hdrlen = b43_txhdr_size(dev);
511 total_len = roundup(skb->len + hdrlen, 4);
512
513 if (unlikely(total_len > q->buffer_size)) {
514 err = -ENOBUFS;
515 b43dbg(wl: dev->wl, fmt: "PIO: TX packet longer than queue.\n");
516 goto out;
517 }
518 if (unlikely(q->free_packet_slots == 0)) {
519 err = -ENOBUFS;
520 b43warn(wl: dev->wl, fmt: "PIO: TX packet overflow.\n");
521 goto out;
522 }
523 B43_WARN_ON(q->buffer_used > q->buffer_size);
524
525 if (total_len > (q->buffer_size - q->buffer_used)) {
526 /* Not enough memory on the queue. */
527 err = -EBUSY;
528 b43_stop_queue(dev, queue_prio: skb_get_queue_mapping(skb));
529 q->stopped = true;
530 goto out;
531 }
532
533 /* Assign the queue number to the ring (if not already done before)
534 * so TX status handling can use it. The mac80211-queue to b43-queue
535 * mapping is static, so we don't need to store it per frame. */
536 q->queue_prio = skb_get_queue_mapping(skb);
537
538 err = pio_tx_frame(q, skb);
539 if (unlikely(err == -ENOKEY)) {
540 /* Drop this packet, as we don't have the encryption key
541 * anymore and must not transmit it unencrypted. */
542 ieee80211_free_txskb(hw: dev->wl->hw, skb);
543 err = 0;
544 goto out;
545 }
546 if (unlikely(err)) {
547 b43err(wl: dev->wl, fmt: "PIO transmission failure\n");
548 goto out;
549 }
550
551 B43_WARN_ON(q->buffer_used > q->buffer_size);
552 if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
553 (q->free_packet_slots == 0)) {
554 /* The queue is full. */
555 b43_stop_queue(dev, queue_prio: skb_get_queue_mapping(skb));
556 q->stopped = true;
557 }
558
559out:
560 return err;
561}
562
563void b43_pio_handle_txstatus(struct b43_wldev *dev,
564 const struct b43_txstatus *status)
565{
566 struct b43_pio_txqueue *q;
567 struct b43_pio_txpacket *pack = NULL;
568 unsigned int total_len;
569 struct ieee80211_tx_info *info;
570
571 q = parse_cookie(dev, cookie: status->cookie, pack: &pack);
572 if (unlikely(!q))
573 return;
574 B43_WARN_ON(!pack);
575
576 info = IEEE80211_SKB_CB(skb: pack->skb);
577
578 b43_fill_txstatus_report(dev, report: info, status);
579
580 total_len = pack->skb->len + b43_txhdr_size(dev);
581 total_len = roundup(total_len, 4);
582 q->buffer_used -= total_len;
583 q->free_packet_slots += 1;
584
585 ieee80211_tx_status_skb(hw: dev->wl->hw, skb: pack->skb);
586 pack->skb = NULL;
587 list_add(new: &pack->list, head: &q->packets_list);
588
589 if (q->stopped) {
590 b43_wake_queue(dev, queue_prio: q->queue_prio);
591 q->stopped = false;
592 }
593}
594
595/* Returns whether we should fetch another frame. */
596static bool pio_rx_frame(struct b43_pio_rxqueue *q)
597{
598 struct b43_wldev *dev = q->dev;
599 struct b43_wl *wl = dev->wl;
600 u16 len;
601 u32 macstat = 0;
602 unsigned int i, padding;
603 struct sk_buff *skb;
604 const char *err_msg = NULL;
605 struct b43_rxhdr_fw4 *rxhdr =
606 (struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
607 size_t rxhdr_size = sizeof(*rxhdr);
608
609 BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
610 switch (dev->fw.hdr_format) {
611 case B43_FW_HDR_410:
612 case B43_FW_HDR_351:
613 rxhdr_size -= sizeof(rxhdr->format_598) -
614 sizeof(rxhdr->format_351);
615 break;
616 case B43_FW_HDR_598:
617 break;
618 }
619 memset(rxhdr, 0, rxhdr_size);
620
621 /* Check if we have data and wait for it to get ready. */
622 if (q->rev >= 8) {
623 u32 ctl;
624
625 ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
626 if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
627 return false;
628 b43_piorx_write32(q, B43_PIO8_RXCTL,
629 B43_PIO8_RXCTL_FRAMERDY);
630 for (i = 0; i < 10; i++) {
631 ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
632 if (ctl & B43_PIO8_RXCTL_DATARDY)
633 goto data_ready;
634 udelay(10);
635 }
636 } else {
637 u16 ctl;
638
639 ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
640 if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
641 return false;
642 b43_piorx_write16(q, B43_PIO_RXCTL,
643 B43_PIO_RXCTL_FRAMERDY);
644 for (i = 0; i < 10; i++) {
645 ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
646 if (ctl & B43_PIO_RXCTL_DATARDY)
647 goto data_ready;
648 udelay(10);
649 }
650 }
651 b43dbg(wl: q->dev->wl, fmt: "PIO RX timed out\n");
652 return true;
653data_ready:
654
655 /* Get the preamble (RX header) */
656 if (q->rev >= 8) {
657 b43_block_read(dev, buffer: rxhdr, count: rxhdr_size,
658 offset: q->mmio_base + B43_PIO8_RXDATA,
659 reg_width: sizeof(u32));
660 } else {
661 b43_block_read(dev, buffer: rxhdr, count: rxhdr_size,
662 offset: q->mmio_base + B43_PIO_RXDATA,
663 reg_width: sizeof(u16));
664 }
665 /* Sanity checks. */
666 len = le16_to_cpu(rxhdr->frame_len);
667 if (unlikely(len > 0x700)) {
668 err_msg = "len > 0x700";
669 goto rx_error;
670 }
671 if (unlikely(len == 0)) {
672 err_msg = "len == 0";
673 goto rx_error;
674 }
675
676 switch (dev->fw.hdr_format) {
677 case B43_FW_HDR_598:
678 macstat = le32_to_cpu(rxhdr->format_598.mac_status);
679 break;
680 case B43_FW_HDR_410:
681 case B43_FW_HDR_351:
682 macstat = le32_to_cpu(rxhdr->format_351.mac_status);
683 break;
684 }
685 if (macstat & B43_RX_MAC_FCSERR) {
686 if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
687 /* Drop frames with failed FCS. */
688 err_msg = "Frame FCS error";
689 goto rx_error;
690 }
691 }
692
693 /* We always pad 2 bytes, as that's what upstream code expects
694 * due to the RX-header being 30 bytes. In case the frame is
695 * unaligned, we pad another 2 bytes. */
696 padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
697 skb = dev_alloc_skb(length: len + padding + 2);
698 if (unlikely(!skb)) {
699 err_msg = "Out of memory";
700 goto rx_error;
701 }
702 skb_reserve(skb, len: 2);
703 skb_put(skb, len: len + padding);
704 if (q->rev >= 8) {
705 b43_block_read(dev, buffer: skb->data + padding, count: (len & ~3),
706 offset: q->mmio_base + B43_PIO8_RXDATA,
707 reg_width: sizeof(u32));
708 if (len & 3) {
709 u8 *tail = wl->pio_tailspace;
710 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
711
712 /* Read the last few bytes. */
713 b43_block_read(dev, buffer: tail, count: 4,
714 offset: q->mmio_base + B43_PIO8_RXDATA,
715 reg_width: sizeof(u32));
716 switch (len & 3) {
717 case 3:
718 skb->data[len + padding - 3] = tail[0];
719 skb->data[len + padding - 2] = tail[1];
720 skb->data[len + padding - 1] = tail[2];
721 break;
722 case 2:
723 skb->data[len + padding - 2] = tail[0];
724 skb->data[len + padding - 1] = tail[1];
725 break;
726 case 1:
727 skb->data[len + padding - 1] = tail[0];
728 break;
729 }
730 }
731 } else {
732 b43_block_read(dev, buffer: skb->data + padding, count: (len & ~1),
733 offset: q->mmio_base + B43_PIO_RXDATA,
734 reg_width: sizeof(u16));
735 if (len & 1) {
736 u8 *tail = wl->pio_tailspace;
737 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
738
739 /* Read the last byte. */
740 b43_block_read(dev, buffer: tail, count: 2,
741 offset: q->mmio_base + B43_PIO_RXDATA,
742 reg_width: sizeof(u16));
743 skb->data[len + padding - 1] = tail[0];
744 }
745 }
746
747 b43_rx(dev: q->dev, skb, rxhdr: rxhdr);
748
749 return true;
750
751rx_error:
752 if (err_msg)
753 b43dbg(wl: q->dev->wl, fmt: "PIO RX error: %s\n", err_msg);
754 if (q->rev >= 8)
755 b43_piorx_write32(q, B43_PIO8_RXCTL, B43_PIO8_RXCTL_DATARDY);
756 else
757 b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
758
759 return true;
760}
761
762void b43_pio_rx(struct b43_pio_rxqueue *q)
763{
764 unsigned int count = 0;
765 bool stop;
766
767 while (1) {
768 stop = !pio_rx_frame(q);
769 if (stop)
770 break;
771 cond_resched();
772 if (WARN_ON_ONCE(++count > 10000))
773 break;
774 }
775}
776
777static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
778{
779 if (q->rev >= 8) {
780 b43_piotx_write32(q, B43_PIO8_TXCTL,
781 value: b43_piotx_read32(q, B43_PIO8_TXCTL)
782 | B43_PIO8_TXCTL_SUSPREQ);
783 } else {
784 b43_piotx_write16(q, B43_PIO_TXCTL,
785 value: b43_piotx_read16(q, B43_PIO_TXCTL)
786 | B43_PIO_TXCTL_SUSPREQ);
787 }
788}
789
790static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
791{
792 if (q->rev >= 8) {
793 b43_piotx_write32(q, B43_PIO8_TXCTL,
794 value: b43_piotx_read32(q, B43_PIO8_TXCTL)
795 & ~B43_PIO8_TXCTL_SUSPREQ);
796 } else {
797 b43_piotx_write16(q, B43_PIO_TXCTL,
798 value: b43_piotx_read16(q, B43_PIO_TXCTL)
799 & ~B43_PIO_TXCTL_SUSPREQ);
800 }
801}
802
803void b43_pio_tx_suspend(struct b43_wldev *dev)
804{
805 b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
806 b43_pio_tx_suspend_queue(q: dev->pio.tx_queue_AC_BK);
807 b43_pio_tx_suspend_queue(q: dev->pio.tx_queue_AC_BE);
808 b43_pio_tx_suspend_queue(q: dev->pio.tx_queue_AC_VI);
809 b43_pio_tx_suspend_queue(q: dev->pio.tx_queue_AC_VO);
810 b43_pio_tx_suspend_queue(q: dev->pio.tx_queue_mcast);
811}
812
813void b43_pio_tx_resume(struct b43_wldev *dev)
814{
815 b43_pio_tx_resume_queue(q: dev->pio.tx_queue_mcast);
816 b43_pio_tx_resume_queue(q: dev->pio.tx_queue_AC_VO);
817 b43_pio_tx_resume_queue(q: dev->pio.tx_queue_AC_VI);
818 b43_pio_tx_resume_queue(q: dev->pio.tx_queue_AC_BE);
819 b43_pio_tx_resume_queue(q: dev->pio.tx_queue_AC_BK);
820 b43_power_saving_ctl_bits(dev, ps_flags: 0);
821}
822

source code of linux/drivers/net/wireless/broadcom/b43/pio.c