Lines Matching +full:pio +full:- +full:transfer
1 // SPDX-License-Identifier: GPL-2.0-or-later
6 PIO data transfer
8 Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
14 #include "pio.h"
30 * PIO controller ID and store the packet index number in generate_cookie()
37 cookie = (((u16)q->index + 1) << 12); in generate_cookie()
38 cookie |= pack->index; in generate_cookie()
48 struct b43_pio *pio = &dev->pio; in parse_cookie() local
54 q = pio->tx_queue_AC_BK; in parse_cookie()
57 q = pio->tx_queue_AC_BE; in parse_cookie()
60 q = pio->tx_queue_AC_VI; in parse_cookie()
63 q = pio->tx_queue_AC_VO; in parse_cookie()
66 q = pio->tx_queue_mcast; in parse_cookie()
72 if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets))) in parse_cookie()
74 *pack = &q->packets[pack_index]; in parse_cookie()
101 if (dev->dev->core_rev >= 11) { in index_to_pioqueue_base()
111 if (dev->dev->core_rev >= 11) in pio_txqueue_offset()
118 if (dev->dev->core_rev >= 11) in pio_rxqueue_offset()
133 q->dev = dev; in b43_setup_pioqueue_tx()
134 q->rev = dev->dev->core_rev; in b43_setup_pioqueue_tx()
135 q->mmio_base = index_to_pioqueue_base(dev, index) + in b43_setup_pioqueue_tx()
137 q->index = index; in b43_setup_pioqueue_tx()
139 q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS; in b43_setup_pioqueue_tx()
140 if (q->rev >= 8) { in b43_setup_pioqueue_tx()
141 q->buffer_size = 1920; //FIXME this constant is wrong. in b43_setup_pioqueue_tx()
143 q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE); in b43_setup_pioqueue_tx()
144 q->buffer_size -= 80; in b43_setup_pioqueue_tx()
147 INIT_LIST_HEAD(&q->packets_list); in b43_setup_pioqueue_tx()
148 for (i = 0; i < ARRAY_SIZE(q->packets); i++) { in b43_setup_pioqueue_tx()
149 p = &(q->packets[i]); in b43_setup_pioqueue_tx()
150 INIT_LIST_HEAD(&p->list); in b43_setup_pioqueue_tx()
151 p->index = i; in b43_setup_pioqueue_tx()
152 p->queue = q; in b43_setup_pioqueue_tx()
153 list_add(&p->list, &q->packets_list); in b43_setup_pioqueue_tx()
167 q->dev = dev; in b43_setup_pioqueue_rx()
168 q->rev = dev->dev->core_rev; in b43_setup_pioqueue_rx()
169 q->mmio_base = index_to_pioqueue_base(dev, index) + in b43_setup_pioqueue_rx()
172 /* Enable Direct FIFO RX (PIO) on the engine. */ in b43_setup_pioqueue_rx()
183 for (i = 0; i < ARRAY_SIZE(q->packets); i++) { in b43_pio_cancel_tx_packets()
184 pack = &(q->packets[i]); in b43_pio_cancel_tx_packets()
185 if (pack->skb) { in b43_pio_cancel_tx_packets()
186 ieee80211_free_txskb(q->dev->wl->hw, pack->skb); in b43_pio_cancel_tx_packets()
187 pack->skb = NULL; in b43_pio_cancel_tx_packets()
209 #define destroy_queue_tx(pio, queue) do { \ argument
210 b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \
211 (pio)->queue = NULL; \
214 #define destroy_queue_rx(pio, queue) do { \ argument
215 b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \
216 (pio)->queue = NULL; \
221 struct b43_pio *pio; in b43_pio_free() local
225 pio = &dev->pio; in b43_pio_free()
227 destroy_queue_rx(pio, rx_queue); in b43_pio_free()
228 destroy_queue_tx(pio, tx_queue_mcast); in b43_pio_free()
229 destroy_queue_tx(pio, tx_queue_AC_VO); in b43_pio_free()
230 destroy_queue_tx(pio, tx_queue_AC_VI); in b43_pio_free()
231 destroy_queue_tx(pio, tx_queue_AC_BE); in b43_pio_free()
232 destroy_queue_tx(pio, tx_queue_AC_BK); in b43_pio_free()
237 struct b43_pio *pio = &dev->pio; in b43_pio_init() local
238 int err = -ENOMEM; in b43_pio_init()
244 pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0); in b43_pio_init()
245 if (!pio->tx_queue_AC_BK) in b43_pio_init()
248 pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1); in b43_pio_init()
249 if (!pio->tx_queue_AC_BE) in b43_pio_init()
252 pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2); in b43_pio_init()
253 if (!pio->tx_queue_AC_VI) in b43_pio_init()
256 pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3); in b43_pio_init()
257 if (!pio->tx_queue_AC_VO) in b43_pio_init()
260 pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4); in b43_pio_init()
261 if (!pio->tx_queue_mcast) in b43_pio_init()
264 pio->rx_queue = b43_setup_pioqueue_rx(dev, 0); in b43_pio_init()
265 if (!pio->rx_queue) in b43_pio_init()
268 b43dbg(dev->wl, "PIO initialized\n"); in b43_pio_init()
274 destroy_queue_tx(pio, tx_queue_mcast); in b43_pio_init()
276 destroy_queue_tx(pio, tx_queue_AC_VO); in b43_pio_init()
278 destroy_queue_tx(pio, tx_queue_AC_VI); in b43_pio_init()
280 destroy_queue_tx(pio, tx_queue_AC_BE); in b43_pio_init()
282 destroy_queue_tx(pio, tx_queue_AC_BK); in b43_pio_init()
286 /* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
292 if (dev->qos_enabled) { in select_queue_by_priority()
299 q = dev->pio.tx_queue_AC_VO; in select_queue_by_priority()
302 q = dev->pio.tx_queue_AC_VI; in select_queue_by_priority()
305 q = dev->pio.tx_queue_AC_BE; in select_queue_by_priority()
308 q = dev->pio.tx_queue_AC_BK; in select_queue_by_priority()
312 q = dev->pio.tx_queue_AC_BE; in select_queue_by_priority()
322 struct b43_wldev *dev = q->dev; in tx_write_2byte_queue()
323 struct b43_wl *wl = dev->wl; in tx_write_2byte_queue()
330 q->mmio_base + B43_PIO_TXDATA, in tx_write_2byte_queue()
333 u8 *tail = wl->pio_tailspace; in tx_write_2byte_queue()
334 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); in tx_write_2byte_queue()
339 tail[0] = data[data_len - 1]; in tx_write_2byte_queue()
342 q->mmio_base + B43_PIO_TXDATA, in tx_write_2byte_queue()
352 struct b43_pio_txqueue *q = pack->queue; in pio_tx_frame_2byte_queue()
353 const char *frame = pack->skb->data; in pio_tx_frame_2byte_queue()
354 unsigned int frame_len = pack->skb->len; in pio_tx_frame_2byte_queue()
361 /* Transfer the header data. */ in pio_tx_frame_2byte_queue()
363 /* Transfer the frame data. */ in pio_tx_frame_2byte_queue()
375 struct b43_wldev *dev = q->dev; in tx_write_4byte_queue()
376 struct b43_wl *wl = dev->wl; in tx_write_4byte_queue()
384 q->mmio_base + B43_PIO8_TXDATA, in tx_write_4byte_queue()
387 u8 *tail = wl->pio_tailspace; in tx_write_4byte_queue()
388 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); in tx_write_4byte_queue()
397 tail[0] = data[data_len - 3]; in tx_write_4byte_queue()
398 tail[1] = data[data_len - 2]; in tx_write_4byte_queue()
399 tail[2] = data[data_len - 1]; in tx_write_4byte_queue()
403 tail[0] = data[data_len - 2]; in tx_write_4byte_queue()
404 tail[1] = data[data_len - 1]; in tx_write_4byte_queue()
407 tail[0] = data[data_len - 1]; in tx_write_4byte_queue()
412 q->mmio_base + B43_PIO8_TXDATA, in tx_write_4byte_queue()
422 struct b43_pio_txqueue *q = pack->queue; in pio_tx_frame_4byte_queue()
423 const char *frame = pack->skb->data; in pio_tx_frame_4byte_queue()
424 unsigned int frame_len = pack->skb->len; in pio_tx_frame_4byte_queue()
431 /* Transfer the header data. */ in pio_tx_frame_4byte_queue()
433 /* Transfer the frame data. */ in pio_tx_frame_4byte_queue()
443 struct b43_wldev *dev = q->dev; in pio_tx_frame()
444 struct b43_wl *wl = dev->wl; in pio_tx_frame()
450 struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace; in pio_tx_frame()
452 B43_WARN_ON(list_empty(&q->packets_list)); in pio_tx_frame()
453 pack = list_entry(q->packets_list.next, in pio_tx_frame()
458 BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr)); in pio_tx_frame()
459 B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen); in pio_tx_frame()
465 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { in pio_tx_frame()
467 * mcast frame, so it can clear the more-data bit in it. */ in pio_tx_frame()
472 pack->skb = skb; in pio_tx_frame()
473 if (q->rev >= 8) in pio_tx_frame()
480 list_del(&pack->list); in pio_tx_frame()
483 q->buffer_used += roundup(skb->len + hdrlen, 4); in pio_tx_frame()
484 q->free_packet_slots -= 1; in pio_tx_frame()
497 hdr = (struct ieee80211_hdr *)skb->data; in b43_pio_tx()
499 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { in b43_pio_tx()
501 q = dev->pio.tx_queue_mcast; in b43_pio_tx()
502 /* Set the frame More-Data bit. Ucode will clear it in b43_pio_tx()
504 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); in b43_pio_tx()
511 total_len = roundup(skb->len + hdrlen, 4); in b43_pio_tx()
513 if (unlikely(total_len > q->buffer_size)) { in b43_pio_tx()
514 err = -ENOBUFS; in b43_pio_tx()
515 b43dbg(dev->wl, "PIO: TX packet longer than queue.\n"); in b43_pio_tx()
518 if (unlikely(q->free_packet_slots == 0)) { in b43_pio_tx()
519 err = -ENOBUFS; in b43_pio_tx()
520 b43warn(dev->wl, "PIO: TX packet overflow.\n"); in b43_pio_tx()
523 B43_WARN_ON(q->buffer_used > q->buffer_size); in b43_pio_tx()
525 if (total_len > (q->buffer_size - q->buffer_used)) { in b43_pio_tx()
527 err = -EBUSY; in b43_pio_tx()
528 ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); in b43_pio_tx()
529 q->stopped = true; in b43_pio_tx()
534 * so TX status handling can use it. The mac80211-queue to b43-queue in b43_pio_tx()
536 q->queue_prio = skb_get_queue_mapping(skb); in b43_pio_tx()
539 if (unlikely(err == -ENOKEY)) { in b43_pio_tx()
542 ieee80211_free_txskb(dev->wl->hw, skb); in b43_pio_tx()
547 b43err(dev->wl, "PIO transmission failure\n"); in b43_pio_tx()
551 B43_WARN_ON(q->buffer_used > q->buffer_size); in b43_pio_tx()
552 if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || in b43_pio_tx()
553 (q->free_packet_slots == 0)) { in b43_pio_tx()
555 ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); in b43_pio_tx()
556 q->stopped = true; in b43_pio_tx()
571 q = parse_cookie(dev, status->cookie, &pack); in b43_pio_handle_txstatus()
576 info = IEEE80211_SKB_CB(pack->skb); in b43_pio_handle_txstatus()
580 total_len = pack->skb->len + b43_txhdr_size(dev); in b43_pio_handle_txstatus()
582 q->buffer_used -= total_len; in b43_pio_handle_txstatus()
583 q->free_packet_slots += 1; in b43_pio_handle_txstatus()
585 ieee80211_tx_status(dev->wl->hw, pack->skb); in b43_pio_handle_txstatus()
586 pack->skb = NULL; in b43_pio_handle_txstatus()
587 list_add(&pack->list, &q->packets_list); in b43_pio_handle_txstatus()
589 if (q->stopped) { in b43_pio_handle_txstatus()
590 ieee80211_wake_queue(dev->wl->hw, q->queue_prio); in b43_pio_handle_txstatus()
591 q->stopped = false; in b43_pio_handle_txstatus()
598 struct b43_wldev *dev = q->dev; in pio_rx_frame()
599 struct b43_wl *wl = dev->wl; in pio_rx_frame()
606 (struct b43_rxhdr_fw4 *)wl->pio_scratchspace; in pio_rx_frame()
609 BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr)); in pio_rx_frame()
610 switch (dev->fw.hdr_format) { in pio_rx_frame()
613 rxhdr_size -= sizeof(rxhdr->format_598) - in pio_rx_frame()
614 sizeof(rxhdr->format_351); in pio_rx_frame()
622 if (q->rev >= 8) { in pio_rx_frame()
651 b43dbg(q->dev->wl, "PIO RX timed out\n"); in pio_rx_frame()
656 if (q->rev >= 8) { in pio_rx_frame()
658 q->mmio_base + B43_PIO8_RXDATA, in pio_rx_frame()
662 q->mmio_base + B43_PIO_RXDATA, in pio_rx_frame()
666 len = le16_to_cpu(rxhdr->frame_len); in pio_rx_frame()
676 switch (dev->fw.hdr_format) { in pio_rx_frame()
678 macstat = le32_to_cpu(rxhdr->format_598.mac_status); in pio_rx_frame()
682 macstat = le32_to_cpu(rxhdr->format_351.mac_status); in pio_rx_frame()
686 if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { in pio_rx_frame()
694 * due to the RX-header being 30 bytes. In case the frame is in pio_rx_frame()
704 if (q->rev >= 8) { in pio_rx_frame()
705 b43_block_read(dev, skb->data + padding, (len & ~3), in pio_rx_frame()
706 q->mmio_base + B43_PIO8_RXDATA, in pio_rx_frame()
709 u8 *tail = wl->pio_tailspace; in pio_rx_frame()
710 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); in pio_rx_frame()
714 q->mmio_base + B43_PIO8_RXDATA, in pio_rx_frame()
718 skb->data[len + padding - 3] = tail[0]; in pio_rx_frame()
719 skb->data[len + padding - 2] = tail[1]; in pio_rx_frame()
720 skb->data[len + padding - 1] = tail[2]; in pio_rx_frame()
723 skb->data[len + padding - 2] = tail[0]; in pio_rx_frame()
724 skb->data[len + padding - 1] = tail[1]; in pio_rx_frame()
727 skb->data[len + padding - 1] = tail[0]; in pio_rx_frame()
732 b43_block_read(dev, skb->data + padding, (len & ~1), in pio_rx_frame()
733 q->mmio_base + B43_PIO_RXDATA, in pio_rx_frame()
736 u8 *tail = wl->pio_tailspace; in pio_rx_frame()
737 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); in pio_rx_frame()
741 q->mmio_base + B43_PIO_RXDATA, in pio_rx_frame()
743 skb->data[len + padding - 1] = tail[0]; in pio_rx_frame()
747 b43_rx(q->dev, skb, rxhdr); in pio_rx_frame()
753 b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg); in pio_rx_frame()
754 if (q->rev >= 8) in pio_rx_frame()
779 if (q->rev >= 8) { in b43_pio_tx_suspend_queue()
792 if (q->rev >= 8) { in b43_pio_tx_resume_queue()
806 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK); in b43_pio_tx_suspend()
807 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE); in b43_pio_tx_suspend()
808 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI); in b43_pio_tx_suspend()
809 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO); in b43_pio_tx_suspend()
810 b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast); in b43_pio_tx_suspend()
815 b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast); in b43_pio_tx_resume()
816 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO); in b43_pio_tx_resume()
817 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI); in b43_pio_tx_resume()
818 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE); in b43_pio_tx_resume()
819 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK); in b43_pio_tx_resume()