xref: /linux/drivers/net/wireless/broadcom/b43/pio.c (revision f8f24ece219204333ac825e9c8aaf3403e201d92)
1ca47d344SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
258619b14SKalle Valo /*
358619b14SKalle Valo 
458619b14SKalle Valo   Broadcom B43 wireless driver
558619b14SKalle Valo 
658619b14SKalle Valo   PIO data transfer
758619b14SKalle Valo 
858619b14SKalle Valo   Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
958619b14SKalle Valo 
1058619b14SKalle Valo 
1158619b14SKalle Valo */
1258619b14SKalle Valo 
1358619b14SKalle Valo #include "b43.h"
1458619b14SKalle Valo #include "pio.h"
1558619b14SKalle Valo #include "dma.h"
1658619b14SKalle Valo #include "main.h"
1758619b14SKalle Valo #include "xmit.h"
1858619b14SKalle Valo 
1958619b14SKalle Valo #include <linux/delay.h>
2058619b14SKalle Valo #include <linux/sched.h>
2158619b14SKalle Valo #include <linux/slab.h>
2258619b14SKalle Valo 
2358619b14SKalle Valo 
2458619b14SKalle Valo static u16 generate_cookie(struct b43_pio_txqueue *q,
2558619b14SKalle Valo 			   struct b43_pio_txpacket *pack)
2658619b14SKalle Valo {
2758619b14SKalle Valo 	u16 cookie;
2858619b14SKalle Valo 
2958619b14SKalle Valo 	/* Use the upper 4 bits of the cookie as
3058619b14SKalle Valo 	 * PIO controller ID and store the packet index number
3158619b14SKalle Valo 	 * in the lower 12 bits.
3258619b14SKalle Valo 	 * Note that the cookie must never be 0, as this
3358619b14SKalle Valo 	 * is a special value used in RX path.
3458619b14SKalle Valo 	 * It can also not be 0xFFFF because that is special
3558619b14SKalle Valo 	 * for multicast frames.
3658619b14SKalle Valo 	 */
3758619b14SKalle Valo 	cookie = (((u16)q->index + 1) << 12);
3858619b14SKalle Valo 	cookie |= pack->index;
3958619b14SKalle Valo 
4058619b14SKalle Valo 	return cookie;
4158619b14SKalle Valo }
4258619b14SKalle Valo 
4358619b14SKalle Valo static
4458619b14SKalle Valo struct b43_pio_txqueue *parse_cookie(struct b43_wldev *dev,
4558619b14SKalle Valo 				     u16 cookie,
4658619b14SKalle Valo 				      struct b43_pio_txpacket **pack)
4758619b14SKalle Valo {
4858619b14SKalle Valo 	struct b43_pio *pio = &dev->pio;
4958619b14SKalle Valo 	struct b43_pio_txqueue *q = NULL;
5058619b14SKalle Valo 	unsigned int pack_index;
5158619b14SKalle Valo 
5258619b14SKalle Valo 	switch (cookie & 0xF000) {
5358619b14SKalle Valo 	case 0x1000:
5458619b14SKalle Valo 		q = pio->tx_queue_AC_BK;
5558619b14SKalle Valo 		break;
5658619b14SKalle Valo 	case 0x2000:
5758619b14SKalle Valo 		q = pio->tx_queue_AC_BE;
5858619b14SKalle Valo 		break;
5958619b14SKalle Valo 	case 0x3000:
6058619b14SKalle Valo 		q = pio->tx_queue_AC_VI;
6158619b14SKalle Valo 		break;
6258619b14SKalle Valo 	case 0x4000:
6358619b14SKalle Valo 		q = pio->tx_queue_AC_VO;
6458619b14SKalle Valo 		break;
6558619b14SKalle Valo 	case 0x5000:
6658619b14SKalle Valo 		q = pio->tx_queue_mcast;
6758619b14SKalle Valo 		break;
6858619b14SKalle Valo 	}
6958619b14SKalle Valo 	if (B43_WARN_ON(!q))
7058619b14SKalle Valo 		return NULL;
7158619b14SKalle Valo 	pack_index = (cookie & 0x0FFF);
7258619b14SKalle Valo 	if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
7358619b14SKalle Valo 		return NULL;
7458619b14SKalle Valo 	*pack = &q->packets[pack_index];
7558619b14SKalle Valo 
7658619b14SKalle Valo 	return q;
7758619b14SKalle Valo }
7858619b14SKalle Valo 
7958619b14SKalle Valo static u16 index_to_pioqueue_base(struct b43_wldev *dev,
8058619b14SKalle Valo 				  unsigned int index)
8158619b14SKalle Valo {
8258619b14SKalle Valo 	static const u16 bases[] = {
8358619b14SKalle Valo 		B43_MMIO_PIO_BASE0,
8458619b14SKalle Valo 		B43_MMIO_PIO_BASE1,
8558619b14SKalle Valo 		B43_MMIO_PIO_BASE2,
8658619b14SKalle Valo 		B43_MMIO_PIO_BASE3,
8758619b14SKalle Valo 		B43_MMIO_PIO_BASE4,
8858619b14SKalle Valo 		B43_MMIO_PIO_BASE5,
8958619b14SKalle Valo 		B43_MMIO_PIO_BASE6,
9058619b14SKalle Valo 		B43_MMIO_PIO_BASE7,
9158619b14SKalle Valo 	};
9258619b14SKalle Valo 	static const u16 bases_rev11[] = {
9358619b14SKalle Valo 		B43_MMIO_PIO11_BASE0,
9458619b14SKalle Valo 		B43_MMIO_PIO11_BASE1,
9558619b14SKalle Valo 		B43_MMIO_PIO11_BASE2,
9658619b14SKalle Valo 		B43_MMIO_PIO11_BASE3,
9758619b14SKalle Valo 		B43_MMIO_PIO11_BASE4,
9858619b14SKalle Valo 		B43_MMIO_PIO11_BASE5,
9958619b14SKalle Valo 	};
10058619b14SKalle Valo 
10158619b14SKalle Valo 	if (dev->dev->core_rev >= 11) {
10258619b14SKalle Valo 		B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
10358619b14SKalle Valo 		return bases_rev11[index];
10458619b14SKalle Valo 	}
10558619b14SKalle Valo 	B43_WARN_ON(index >= ARRAY_SIZE(bases));
10658619b14SKalle Valo 	return bases[index];
10758619b14SKalle Valo }
10858619b14SKalle Valo 
10958619b14SKalle Valo static u16 pio_txqueue_offset(struct b43_wldev *dev)
11058619b14SKalle Valo {
11158619b14SKalle Valo 	if (dev->dev->core_rev >= 11)
11258619b14SKalle Valo 		return 0x18;
11358619b14SKalle Valo 	return 0;
11458619b14SKalle Valo }
11558619b14SKalle Valo 
11658619b14SKalle Valo static u16 pio_rxqueue_offset(struct b43_wldev *dev)
11758619b14SKalle Valo {
11858619b14SKalle Valo 	if (dev->dev->core_rev >= 11)
11958619b14SKalle Valo 		return 0x38;
12058619b14SKalle Valo 	return 8;
12158619b14SKalle Valo }
12258619b14SKalle Valo 
12358619b14SKalle Valo static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
12458619b14SKalle Valo 						     unsigned int index)
12558619b14SKalle Valo {
12658619b14SKalle Valo 	struct b43_pio_txqueue *q;
12758619b14SKalle Valo 	struct b43_pio_txpacket *p;
12858619b14SKalle Valo 	unsigned int i;
12958619b14SKalle Valo 
13058619b14SKalle Valo 	q = kzalloc(sizeof(*q), GFP_KERNEL);
13158619b14SKalle Valo 	if (!q)
13258619b14SKalle Valo 		return NULL;
13358619b14SKalle Valo 	q->dev = dev;
13458619b14SKalle Valo 	q->rev = dev->dev->core_rev;
13558619b14SKalle Valo 	q->mmio_base = index_to_pioqueue_base(dev, index) +
13658619b14SKalle Valo 		       pio_txqueue_offset(dev);
13758619b14SKalle Valo 	q->index = index;
13858619b14SKalle Valo 
13958619b14SKalle Valo 	q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
14058619b14SKalle Valo 	if (q->rev >= 8) {
14158619b14SKalle Valo 		q->buffer_size = 1920; //FIXME this constant is wrong.
14258619b14SKalle Valo 	} else {
14358619b14SKalle Valo 		q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
14458619b14SKalle Valo 		q->buffer_size -= 80;
14558619b14SKalle Valo 	}
14658619b14SKalle Valo 
14758619b14SKalle Valo 	INIT_LIST_HEAD(&q->packets_list);
14858619b14SKalle Valo 	for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
14958619b14SKalle Valo 		p = &(q->packets[i]);
15058619b14SKalle Valo 		INIT_LIST_HEAD(&p->list);
15158619b14SKalle Valo 		p->index = i;
15258619b14SKalle Valo 		p->queue = q;
15358619b14SKalle Valo 		list_add(&p->list, &q->packets_list);
15458619b14SKalle Valo 	}
15558619b14SKalle Valo 
15658619b14SKalle Valo 	return q;
15758619b14SKalle Valo }
15858619b14SKalle Valo 
15958619b14SKalle Valo static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
16058619b14SKalle Valo 						     unsigned int index)
16158619b14SKalle Valo {
16258619b14SKalle Valo 	struct b43_pio_rxqueue *q;
16358619b14SKalle Valo 
16458619b14SKalle Valo 	q = kzalloc(sizeof(*q), GFP_KERNEL);
16558619b14SKalle Valo 	if (!q)
16658619b14SKalle Valo 		return NULL;
16758619b14SKalle Valo 	q->dev = dev;
16858619b14SKalle Valo 	q->rev = dev->dev->core_rev;
16958619b14SKalle Valo 	q->mmio_base = index_to_pioqueue_base(dev, index) +
17058619b14SKalle Valo 		       pio_rxqueue_offset(dev);
17158619b14SKalle Valo 
17258619b14SKalle Valo 	/* Enable Direct FIFO RX (PIO) on the engine. */
17358619b14SKalle Valo 	b43_dma_direct_fifo_rx(dev, index, 1);
17458619b14SKalle Valo 
17558619b14SKalle Valo 	return q;
17658619b14SKalle Valo }
17758619b14SKalle Valo 
17858619b14SKalle Valo static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
17958619b14SKalle Valo {
18058619b14SKalle Valo 	struct b43_pio_txpacket *pack;
18158619b14SKalle Valo 	unsigned int i;
18258619b14SKalle Valo 
18358619b14SKalle Valo 	for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
18458619b14SKalle Valo 		pack = &(q->packets[i]);
18558619b14SKalle Valo 		if (pack->skb) {
18658619b14SKalle Valo 			ieee80211_free_txskb(q->dev->wl->hw, pack->skb);
18758619b14SKalle Valo 			pack->skb = NULL;
18858619b14SKalle Valo 		}
18958619b14SKalle Valo 	}
19058619b14SKalle Valo }
19158619b14SKalle Valo 
19258619b14SKalle Valo static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
19358619b14SKalle Valo 				    const char *name)
19458619b14SKalle Valo {
19558619b14SKalle Valo 	if (!q)
19658619b14SKalle Valo 		return;
19758619b14SKalle Valo 	b43_pio_cancel_tx_packets(q);
19858619b14SKalle Valo 	kfree(q);
19958619b14SKalle Valo }
20058619b14SKalle Valo 
20158619b14SKalle Valo static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
20258619b14SKalle Valo 				    const char *name)
20358619b14SKalle Valo {
20458619b14SKalle Valo 	if (!q)
20558619b14SKalle Valo 		return;
20658619b14SKalle Valo 	kfree(q);
20758619b14SKalle Valo }
20858619b14SKalle Valo 
20958619b14SKalle Valo #define destroy_queue_tx(pio, queue) do {				\
21058619b14SKalle Valo 	b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue));	\
21158619b14SKalle Valo 	(pio)->queue = NULL;						\
21258619b14SKalle Valo   } while (0)
21358619b14SKalle Valo 
21458619b14SKalle Valo #define destroy_queue_rx(pio, queue) do {				\
21558619b14SKalle Valo 	b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue));	\
21658619b14SKalle Valo 	(pio)->queue = NULL;						\
21758619b14SKalle Valo   } while (0)
21858619b14SKalle Valo 
21958619b14SKalle Valo void b43_pio_free(struct b43_wldev *dev)
22058619b14SKalle Valo {
22158619b14SKalle Valo 	struct b43_pio *pio;
22258619b14SKalle Valo 
22358619b14SKalle Valo 	if (!b43_using_pio_transfers(dev))
22458619b14SKalle Valo 		return;
22558619b14SKalle Valo 	pio = &dev->pio;
22658619b14SKalle Valo 
22758619b14SKalle Valo 	destroy_queue_rx(pio, rx_queue);
22858619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_mcast);
22958619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_AC_VO);
23058619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_AC_VI);
23158619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_AC_BE);
23258619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_AC_BK);
23358619b14SKalle Valo }
23458619b14SKalle Valo 
23558619b14SKalle Valo int b43_pio_init(struct b43_wldev *dev)
23658619b14SKalle Valo {
23758619b14SKalle Valo 	struct b43_pio *pio = &dev->pio;
23858619b14SKalle Valo 	int err = -ENOMEM;
23958619b14SKalle Valo 
24058619b14SKalle Valo 	b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
24158619b14SKalle Valo 		    & ~B43_MACCTL_BE);
24258619b14SKalle Valo 	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0);
24358619b14SKalle Valo 
24458619b14SKalle Valo 	pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0);
24558619b14SKalle Valo 	if (!pio->tx_queue_AC_BK)
24658619b14SKalle Valo 		goto out;
24758619b14SKalle Valo 
24858619b14SKalle Valo 	pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1);
24958619b14SKalle Valo 	if (!pio->tx_queue_AC_BE)
25058619b14SKalle Valo 		goto err_destroy_bk;
25158619b14SKalle Valo 
25258619b14SKalle Valo 	pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2);
25358619b14SKalle Valo 	if (!pio->tx_queue_AC_VI)
25458619b14SKalle Valo 		goto err_destroy_be;
25558619b14SKalle Valo 
25658619b14SKalle Valo 	pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3);
25758619b14SKalle Valo 	if (!pio->tx_queue_AC_VO)
25858619b14SKalle Valo 		goto err_destroy_vi;
25958619b14SKalle Valo 
26058619b14SKalle Valo 	pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4);
26158619b14SKalle Valo 	if (!pio->tx_queue_mcast)
26258619b14SKalle Valo 		goto err_destroy_vo;
26358619b14SKalle Valo 
26458619b14SKalle Valo 	pio->rx_queue = b43_setup_pioqueue_rx(dev, 0);
26558619b14SKalle Valo 	if (!pio->rx_queue)
26658619b14SKalle Valo 		goto err_destroy_mcast;
26758619b14SKalle Valo 
26858619b14SKalle Valo 	b43dbg(dev->wl, "PIO initialized\n");
26958619b14SKalle Valo 	err = 0;
27058619b14SKalle Valo out:
27158619b14SKalle Valo 	return err;
27258619b14SKalle Valo 
27358619b14SKalle Valo err_destroy_mcast:
27458619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_mcast);
27558619b14SKalle Valo err_destroy_vo:
27658619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_AC_VO);
27758619b14SKalle Valo err_destroy_vi:
27858619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_AC_VI);
27958619b14SKalle Valo err_destroy_be:
28058619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_AC_BE);
28158619b14SKalle Valo err_destroy_bk:
28258619b14SKalle Valo 	destroy_queue_tx(pio, tx_queue_AC_BK);
28358619b14SKalle Valo 	return err;
28458619b14SKalle Valo }
28558619b14SKalle Valo 
28658619b14SKalle Valo /* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
28758619b14SKalle Valo static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev,
28858619b14SKalle Valo 							u8 queue_prio)
28958619b14SKalle Valo {
29058619b14SKalle Valo 	struct b43_pio_txqueue *q;
29158619b14SKalle Valo 
29258619b14SKalle Valo 	if (dev->qos_enabled) {
29358619b14SKalle Valo 		/* 0 = highest priority */
29458619b14SKalle Valo 		switch (queue_prio) {
29558619b14SKalle Valo 		default:
29658619b14SKalle Valo 			B43_WARN_ON(1);
29758619b14SKalle Valo 			/* fallthrough */
29858619b14SKalle Valo 		case 0:
29958619b14SKalle Valo 			q = dev->pio.tx_queue_AC_VO;
30058619b14SKalle Valo 			break;
30158619b14SKalle Valo 		case 1:
30258619b14SKalle Valo 			q = dev->pio.tx_queue_AC_VI;
30358619b14SKalle Valo 			break;
30458619b14SKalle Valo 		case 2:
30558619b14SKalle Valo 			q = dev->pio.tx_queue_AC_BE;
30658619b14SKalle Valo 			break;
30758619b14SKalle Valo 		case 3:
30858619b14SKalle Valo 			q = dev->pio.tx_queue_AC_BK;
30958619b14SKalle Valo 			break;
31058619b14SKalle Valo 		}
31158619b14SKalle Valo 	} else
31258619b14SKalle Valo 		q = dev->pio.tx_queue_AC_BE;
31358619b14SKalle Valo 
31458619b14SKalle Valo 	return q;
31558619b14SKalle Valo }
31658619b14SKalle Valo 
31758619b14SKalle Valo static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
31858619b14SKalle Valo 				u16 ctl,
31958619b14SKalle Valo 				const void *_data,
32058619b14SKalle Valo 				unsigned int data_len)
32158619b14SKalle Valo {
32258619b14SKalle Valo 	struct b43_wldev *dev = q->dev;
32358619b14SKalle Valo 	struct b43_wl *wl = dev->wl;
32458619b14SKalle Valo 	const u8 *data = _data;
32558619b14SKalle Valo 
32658619b14SKalle Valo 	ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
32758619b14SKalle Valo 	b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
32858619b14SKalle Valo 
32958619b14SKalle Valo 	b43_block_write(dev, data, (data_len & ~1),
33058619b14SKalle Valo 			q->mmio_base + B43_PIO_TXDATA,
33158619b14SKalle Valo 			sizeof(u16));
33258619b14SKalle Valo 	if (data_len & 1) {
33358619b14SKalle Valo 		u8 *tail = wl->pio_tailspace;
33458619b14SKalle Valo 		BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
33558619b14SKalle Valo 
33658619b14SKalle Valo 		/* Write the last byte. */
33758619b14SKalle Valo 		ctl &= ~B43_PIO_TXCTL_WRITEHI;
33858619b14SKalle Valo 		b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
33958619b14SKalle Valo 		tail[0] = data[data_len - 1];
34058619b14SKalle Valo 		tail[1] = 0;
34158619b14SKalle Valo 		b43_block_write(dev, tail, 2,
34258619b14SKalle Valo 				q->mmio_base + B43_PIO_TXDATA,
34358619b14SKalle Valo 				sizeof(u16));
34458619b14SKalle Valo 	}
34558619b14SKalle Valo 
34658619b14SKalle Valo 	return ctl;
34758619b14SKalle Valo }
34858619b14SKalle Valo 
34958619b14SKalle Valo static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
35058619b14SKalle Valo 				     const u8 *hdr, unsigned int hdrlen)
35158619b14SKalle Valo {
35258619b14SKalle Valo 	struct b43_pio_txqueue *q = pack->queue;
35358619b14SKalle Valo 	const char *frame = pack->skb->data;
35458619b14SKalle Valo 	unsigned int frame_len = pack->skb->len;
35558619b14SKalle Valo 	u16 ctl;
35658619b14SKalle Valo 
35758619b14SKalle Valo 	ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
35858619b14SKalle Valo 	ctl |= B43_PIO_TXCTL_FREADY;
35958619b14SKalle Valo 	ctl &= ~B43_PIO_TXCTL_EOF;
36058619b14SKalle Valo 
36158619b14SKalle Valo 	/* Transfer the header data. */
36258619b14SKalle Valo 	ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
36358619b14SKalle Valo 	/* Transfer the frame data. */
36458619b14SKalle Valo 	ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
36558619b14SKalle Valo 
36658619b14SKalle Valo 	ctl |= B43_PIO_TXCTL_EOF;
36758619b14SKalle Valo 	b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
36858619b14SKalle Valo }
36958619b14SKalle Valo 
37058619b14SKalle Valo static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
37158619b14SKalle Valo 				u32 ctl,
37258619b14SKalle Valo 				const void *_data,
37358619b14SKalle Valo 				unsigned int data_len)
37458619b14SKalle Valo {
37558619b14SKalle Valo 	struct b43_wldev *dev = q->dev;
37658619b14SKalle Valo 	struct b43_wl *wl = dev->wl;
37758619b14SKalle Valo 	const u8 *data = _data;
37858619b14SKalle Valo 
37958619b14SKalle Valo 	ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
38058619b14SKalle Valo 	       B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
38158619b14SKalle Valo 	b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
38258619b14SKalle Valo 
38358619b14SKalle Valo 	b43_block_write(dev, data, (data_len & ~3),
38458619b14SKalle Valo 			q->mmio_base + B43_PIO8_TXDATA,
38558619b14SKalle Valo 			sizeof(u32));
38658619b14SKalle Valo 	if (data_len & 3) {
38758619b14SKalle Valo 		u8 *tail = wl->pio_tailspace;
38858619b14SKalle Valo 		BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
38958619b14SKalle Valo 
39058619b14SKalle Valo 		memset(tail, 0, 4);
39158619b14SKalle Valo 		/* Write the last few bytes. */
39258619b14SKalle Valo 		ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
39358619b14SKalle Valo 			 B43_PIO8_TXCTL_24_31);
39458619b14SKalle Valo 		switch (data_len & 3) {
39558619b14SKalle Valo 		case 3:
39658619b14SKalle Valo 			ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
39758619b14SKalle Valo 			tail[0] = data[data_len - 3];
39858619b14SKalle Valo 			tail[1] = data[data_len - 2];
39958619b14SKalle Valo 			tail[2] = data[data_len - 1];
40058619b14SKalle Valo 			break;
40158619b14SKalle Valo 		case 2:
40258619b14SKalle Valo 			ctl |= B43_PIO8_TXCTL_8_15;
40358619b14SKalle Valo 			tail[0] = data[data_len - 2];
40458619b14SKalle Valo 			tail[1] = data[data_len - 1];
40558619b14SKalle Valo 			break;
40658619b14SKalle Valo 		case 1:
40758619b14SKalle Valo 			tail[0] = data[data_len - 1];
40858619b14SKalle Valo 			break;
40958619b14SKalle Valo 		}
41058619b14SKalle Valo 		b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
41158619b14SKalle Valo 		b43_block_write(dev, tail, 4,
41258619b14SKalle Valo 				q->mmio_base + B43_PIO8_TXDATA,
41358619b14SKalle Valo 				sizeof(u32));
41458619b14SKalle Valo 	}
41558619b14SKalle Valo 
41658619b14SKalle Valo 	return ctl;
41758619b14SKalle Valo }
41858619b14SKalle Valo 
41958619b14SKalle Valo static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
42058619b14SKalle Valo 				     const u8 *hdr, unsigned int hdrlen)
42158619b14SKalle Valo {
42258619b14SKalle Valo 	struct b43_pio_txqueue *q = pack->queue;
42358619b14SKalle Valo 	const char *frame = pack->skb->data;
42458619b14SKalle Valo 	unsigned int frame_len = pack->skb->len;
42558619b14SKalle Valo 	u32 ctl;
42658619b14SKalle Valo 
42758619b14SKalle Valo 	ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
42858619b14SKalle Valo 	ctl |= B43_PIO8_TXCTL_FREADY;
42958619b14SKalle Valo 	ctl &= ~B43_PIO8_TXCTL_EOF;
43058619b14SKalle Valo 
43158619b14SKalle Valo 	/* Transfer the header data. */
43258619b14SKalle Valo 	ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
43358619b14SKalle Valo 	/* Transfer the frame data. */
43458619b14SKalle Valo 	ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
43558619b14SKalle Valo 
43658619b14SKalle Valo 	ctl |= B43_PIO8_TXCTL_EOF;
43758619b14SKalle Valo 	b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
43858619b14SKalle Valo }
43958619b14SKalle Valo 
44058619b14SKalle Valo static int pio_tx_frame(struct b43_pio_txqueue *q,
44158619b14SKalle Valo 			struct sk_buff *skb)
44258619b14SKalle Valo {
44358619b14SKalle Valo 	struct b43_wldev *dev = q->dev;
44458619b14SKalle Valo 	struct b43_wl *wl = dev->wl;
44558619b14SKalle Valo 	struct b43_pio_txpacket *pack;
44658619b14SKalle Valo 	u16 cookie;
44758619b14SKalle Valo 	int err;
44858619b14SKalle Valo 	unsigned int hdrlen;
44958619b14SKalle Valo 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
45058619b14SKalle Valo 	struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
45158619b14SKalle Valo 
45258619b14SKalle Valo 	B43_WARN_ON(list_empty(&q->packets_list));
45358619b14SKalle Valo 	pack = list_entry(q->packets_list.next,
45458619b14SKalle Valo 			  struct b43_pio_txpacket, list);
45558619b14SKalle Valo 
45658619b14SKalle Valo 	cookie = generate_cookie(q, pack);
45758619b14SKalle Valo 	hdrlen = b43_txhdr_size(dev);
45858619b14SKalle Valo 	BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
45958619b14SKalle Valo 	B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
46058619b14SKalle Valo 	err = b43_generate_txhdr(dev, (u8 *)txhdr, skb,
46158619b14SKalle Valo 				 info, cookie);
46258619b14SKalle Valo 	if (err)
46358619b14SKalle Valo 		return err;
46458619b14SKalle Valo 
46558619b14SKalle Valo 	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
46658619b14SKalle Valo 		/* Tell the firmware about the cookie of the last
46758619b14SKalle Valo 		 * mcast frame, so it can clear the more-data bit in it. */
46858619b14SKalle Valo 		b43_shm_write16(dev, B43_SHM_SHARED,
46958619b14SKalle Valo 				B43_SHM_SH_MCASTCOOKIE, cookie);
47058619b14SKalle Valo 	}
47158619b14SKalle Valo 
47258619b14SKalle Valo 	pack->skb = skb;
47358619b14SKalle Valo 	if (q->rev >= 8)
47458619b14SKalle Valo 		pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen);
47558619b14SKalle Valo 	else
47658619b14SKalle Valo 		pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen);
47758619b14SKalle Valo 
47858619b14SKalle Valo 	/* Remove it from the list of available packet slots.
47958619b14SKalle Valo 	 * It will be put back when we receive the status report. */
48058619b14SKalle Valo 	list_del(&pack->list);
48158619b14SKalle Valo 
48258619b14SKalle Valo 	/* Update the queue statistics. */
48358619b14SKalle Valo 	q->buffer_used += roundup(skb->len + hdrlen, 4);
48458619b14SKalle Valo 	q->free_packet_slots -= 1;
48558619b14SKalle Valo 
48658619b14SKalle Valo 	return 0;
48758619b14SKalle Valo }
48858619b14SKalle Valo 
48958619b14SKalle Valo int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
49058619b14SKalle Valo {
49158619b14SKalle Valo 	struct b43_pio_txqueue *q;
49258619b14SKalle Valo 	struct ieee80211_hdr *hdr;
49358619b14SKalle Valo 	unsigned int hdrlen, total_len;
49458619b14SKalle Valo 	int err = 0;
49558619b14SKalle Valo 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
49658619b14SKalle Valo 
49758619b14SKalle Valo 	hdr = (struct ieee80211_hdr *)skb->data;
49858619b14SKalle Valo 
49958619b14SKalle Valo 	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
50058619b14SKalle Valo 		/* The multicast queue will be sent after the DTIM. */
50158619b14SKalle Valo 		q = dev->pio.tx_queue_mcast;
50258619b14SKalle Valo 		/* Set the frame More-Data bit. Ucode will clear it
50358619b14SKalle Valo 		 * for us on the last frame. */
50458619b14SKalle Valo 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
50558619b14SKalle Valo 	} else {
50658619b14SKalle Valo 		/* Decide by priority where to put this frame. */
50758619b14SKalle Valo 		q = select_queue_by_priority(dev, skb_get_queue_mapping(skb));
50858619b14SKalle Valo 	}
50958619b14SKalle Valo 
51058619b14SKalle Valo 	hdrlen = b43_txhdr_size(dev);
51158619b14SKalle Valo 	total_len = roundup(skb->len + hdrlen, 4);
51258619b14SKalle Valo 
51358619b14SKalle Valo 	if (unlikely(total_len > q->buffer_size)) {
51458619b14SKalle Valo 		err = -ENOBUFS;
51558619b14SKalle Valo 		b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
51658619b14SKalle Valo 		goto out;
51758619b14SKalle Valo 	}
51858619b14SKalle Valo 	if (unlikely(q->free_packet_slots == 0)) {
51958619b14SKalle Valo 		err = -ENOBUFS;
52058619b14SKalle Valo 		b43warn(dev->wl, "PIO: TX packet overflow.\n");
52158619b14SKalle Valo 		goto out;
52258619b14SKalle Valo 	}
52358619b14SKalle Valo 	B43_WARN_ON(q->buffer_used > q->buffer_size);
52458619b14SKalle Valo 
52558619b14SKalle Valo 	if (total_len > (q->buffer_size - q->buffer_used)) {
52658619b14SKalle Valo 		/* Not enough memory on the queue. */
52758619b14SKalle Valo 		err = -EBUSY;
52858619b14SKalle Valo 		ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
52958619b14SKalle Valo 		q->stopped = true;
53058619b14SKalle Valo 		goto out;
53158619b14SKalle Valo 	}
53258619b14SKalle Valo 
53358619b14SKalle Valo 	/* Assign the queue number to the ring (if not already done before)
53458619b14SKalle Valo 	 * so TX status handling can use it. The mac80211-queue to b43-queue
53558619b14SKalle Valo 	 * mapping is static, so we don't need to store it per frame. */
53658619b14SKalle Valo 	q->queue_prio = skb_get_queue_mapping(skb);
53758619b14SKalle Valo 
53858619b14SKalle Valo 	err = pio_tx_frame(q, skb);
53958619b14SKalle Valo 	if (unlikely(err == -ENOKEY)) {
54058619b14SKalle Valo 		/* Drop this packet, as we don't have the encryption key
54158619b14SKalle Valo 		 * anymore and must not transmit it unencrypted. */
54258619b14SKalle Valo 		ieee80211_free_txskb(dev->wl->hw, skb);
54358619b14SKalle Valo 		err = 0;
54458619b14SKalle Valo 		goto out;
54558619b14SKalle Valo 	}
54658619b14SKalle Valo 	if (unlikely(err)) {
54758619b14SKalle Valo 		b43err(dev->wl, "PIO transmission failure\n");
54858619b14SKalle Valo 		goto out;
54958619b14SKalle Valo 	}
55058619b14SKalle Valo 
55158619b14SKalle Valo 	B43_WARN_ON(q->buffer_used > q->buffer_size);
55258619b14SKalle Valo 	if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
55358619b14SKalle Valo 	    (q->free_packet_slots == 0)) {
55458619b14SKalle Valo 		/* The queue is full. */
55558619b14SKalle Valo 		ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
55658619b14SKalle Valo 		q->stopped = true;
55758619b14SKalle Valo 	}
55858619b14SKalle Valo 
55958619b14SKalle Valo out:
56058619b14SKalle Valo 	return err;
56158619b14SKalle Valo }
56258619b14SKalle Valo 
56358619b14SKalle Valo void b43_pio_handle_txstatus(struct b43_wldev *dev,
56458619b14SKalle Valo 			     const struct b43_txstatus *status)
56558619b14SKalle Valo {
56658619b14SKalle Valo 	struct b43_pio_txqueue *q;
56758619b14SKalle Valo 	struct b43_pio_txpacket *pack = NULL;
56858619b14SKalle Valo 	unsigned int total_len;
56958619b14SKalle Valo 	struct ieee80211_tx_info *info;
57058619b14SKalle Valo 
57158619b14SKalle Valo 	q = parse_cookie(dev, status->cookie, &pack);
57258619b14SKalle Valo 	if (unlikely(!q))
57358619b14SKalle Valo 		return;
57458619b14SKalle Valo 	B43_WARN_ON(!pack);
57558619b14SKalle Valo 
57658619b14SKalle Valo 	info = IEEE80211_SKB_CB(pack->skb);
57758619b14SKalle Valo 
57858619b14SKalle Valo 	b43_fill_txstatus_report(dev, info, status);
57958619b14SKalle Valo 
58058619b14SKalle Valo 	total_len = pack->skb->len + b43_txhdr_size(dev);
58158619b14SKalle Valo 	total_len = roundup(total_len, 4);
58258619b14SKalle Valo 	q->buffer_used -= total_len;
58358619b14SKalle Valo 	q->free_packet_slots += 1;
58458619b14SKalle Valo 
58558619b14SKalle Valo 	ieee80211_tx_status(dev->wl->hw, pack->skb);
58658619b14SKalle Valo 	pack->skb = NULL;
58758619b14SKalle Valo 	list_add(&pack->list, &q->packets_list);
58858619b14SKalle Valo 
58958619b14SKalle Valo 	if (q->stopped) {
59058619b14SKalle Valo 		ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
59158619b14SKalle Valo 		q->stopped = false;
59258619b14SKalle Valo 	}
59358619b14SKalle Valo }
59458619b14SKalle Valo 
59558619b14SKalle Valo /* Returns whether we should fetch another frame. */
59658619b14SKalle Valo static bool pio_rx_frame(struct b43_pio_rxqueue *q)
59758619b14SKalle Valo {
59858619b14SKalle Valo 	struct b43_wldev *dev = q->dev;
59958619b14SKalle Valo 	struct b43_wl *wl = dev->wl;
60058619b14SKalle Valo 	u16 len;
60158619b14SKalle Valo 	u32 macstat = 0;
60258619b14SKalle Valo 	unsigned int i, padding;
60358619b14SKalle Valo 	struct sk_buff *skb;
60458619b14SKalle Valo 	const char *err_msg = NULL;
60558619b14SKalle Valo 	struct b43_rxhdr_fw4 *rxhdr =
60658619b14SKalle Valo 		(struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
60758619b14SKalle Valo 	size_t rxhdr_size = sizeof(*rxhdr);
60858619b14SKalle Valo 
60958619b14SKalle Valo 	BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
61058619b14SKalle Valo 	switch (dev->fw.hdr_format) {
61158619b14SKalle Valo 	case B43_FW_HDR_410:
61258619b14SKalle Valo 	case B43_FW_HDR_351:
61358619b14SKalle Valo 		rxhdr_size -= sizeof(rxhdr->format_598) -
61458619b14SKalle Valo 			sizeof(rxhdr->format_351);
61558619b14SKalle Valo 		break;
61658619b14SKalle Valo 	case B43_FW_HDR_598:
61758619b14SKalle Valo 		break;
61858619b14SKalle Valo 	}
61958619b14SKalle Valo 	memset(rxhdr, 0, rxhdr_size);
62058619b14SKalle Valo 
62158619b14SKalle Valo 	/* Check if we have data and wait for it to get ready. */
62258619b14SKalle Valo 	if (q->rev >= 8) {
62358619b14SKalle Valo 		u32 ctl;
62458619b14SKalle Valo 
62558619b14SKalle Valo 		ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
62658619b14SKalle Valo 		if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
62758619b14SKalle Valo 			return false;
62858619b14SKalle Valo 		b43_piorx_write32(q, B43_PIO8_RXCTL,
62958619b14SKalle Valo 				  B43_PIO8_RXCTL_FRAMERDY);
63058619b14SKalle Valo 		for (i = 0; i < 10; i++) {
63158619b14SKalle Valo 			ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
63258619b14SKalle Valo 			if (ctl & B43_PIO8_RXCTL_DATARDY)
63358619b14SKalle Valo 				goto data_ready;
63458619b14SKalle Valo 			udelay(10);
63558619b14SKalle Valo 		}
63658619b14SKalle Valo 	} else {
63758619b14SKalle Valo 		u16 ctl;
63858619b14SKalle Valo 
63958619b14SKalle Valo 		ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
64058619b14SKalle Valo 		if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
64158619b14SKalle Valo 			return false;
64258619b14SKalle Valo 		b43_piorx_write16(q, B43_PIO_RXCTL,
64358619b14SKalle Valo 				  B43_PIO_RXCTL_FRAMERDY);
64458619b14SKalle Valo 		for (i = 0; i < 10; i++) {
64558619b14SKalle Valo 			ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
64658619b14SKalle Valo 			if (ctl & B43_PIO_RXCTL_DATARDY)
64758619b14SKalle Valo 				goto data_ready;
64858619b14SKalle Valo 			udelay(10);
64958619b14SKalle Valo 		}
65058619b14SKalle Valo 	}
65158619b14SKalle Valo 	b43dbg(q->dev->wl, "PIO RX timed out\n");
65258619b14SKalle Valo 	return true;
65358619b14SKalle Valo data_ready:
65458619b14SKalle Valo 
65558619b14SKalle Valo 	/* Get the preamble (RX header) */
65658619b14SKalle Valo 	if (q->rev >= 8) {
65758619b14SKalle Valo 		b43_block_read(dev, rxhdr, rxhdr_size,
65858619b14SKalle Valo 			       q->mmio_base + B43_PIO8_RXDATA,
65958619b14SKalle Valo 			       sizeof(u32));
66058619b14SKalle Valo 	} else {
66158619b14SKalle Valo 		b43_block_read(dev, rxhdr, rxhdr_size,
66258619b14SKalle Valo 			       q->mmio_base + B43_PIO_RXDATA,
66358619b14SKalle Valo 			       sizeof(u16));
66458619b14SKalle Valo 	}
66558619b14SKalle Valo 	/* Sanity checks. */
66658619b14SKalle Valo 	len = le16_to_cpu(rxhdr->frame_len);
66758619b14SKalle Valo 	if (unlikely(len > 0x700)) {
66858619b14SKalle Valo 		err_msg = "len > 0x700";
66958619b14SKalle Valo 		goto rx_error;
67058619b14SKalle Valo 	}
67158619b14SKalle Valo 	if (unlikely(len == 0)) {
67258619b14SKalle Valo 		err_msg = "len == 0";
67358619b14SKalle Valo 		goto rx_error;
67458619b14SKalle Valo 	}
67558619b14SKalle Valo 
67658619b14SKalle Valo 	switch (dev->fw.hdr_format) {
67758619b14SKalle Valo 	case B43_FW_HDR_598:
67858619b14SKalle Valo 		macstat = le32_to_cpu(rxhdr->format_598.mac_status);
67958619b14SKalle Valo 		break;
68058619b14SKalle Valo 	case B43_FW_HDR_410:
68158619b14SKalle Valo 	case B43_FW_HDR_351:
68258619b14SKalle Valo 		macstat = le32_to_cpu(rxhdr->format_351.mac_status);
68358619b14SKalle Valo 		break;
68458619b14SKalle Valo 	}
68558619b14SKalle Valo 	if (macstat & B43_RX_MAC_FCSERR) {
68658619b14SKalle Valo 		if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
68758619b14SKalle Valo 			/* Drop frames with failed FCS. */
68858619b14SKalle Valo 			err_msg = "Frame FCS error";
68958619b14SKalle Valo 			goto rx_error;
69058619b14SKalle Valo 		}
69158619b14SKalle Valo 	}
69258619b14SKalle Valo 
69358619b14SKalle Valo 	/* We always pad 2 bytes, as that's what upstream code expects
69458619b14SKalle Valo 	 * due to the RX-header being 30 bytes. In case the frame is
69558619b14SKalle Valo 	 * unaligned, we pad another 2 bytes. */
69658619b14SKalle Valo 	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
69758619b14SKalle Valo 	skb = dev_alloc_skb(len + padding + 2);
69858619b14SKalle Valo 	if (unlikely(!skb)) {
69958619b14SKalle Valo 		err_msg = "Out of memory";
70058619b14SKalle Valo 		goto rx_error;
70158619b14SKalle Valo 	}
70258619b14SKalle Valo 	skb_reserve(skb, 2);
70358619b14SKalle Valo 	skb_put(skb, len + padding);
70458619b14SKalle Valo 	if (q->rev >= 8) {
70558619b14SKalle Valo 		b43_block_read(dev, skb->data + padding, (len & ~3),
70658619b14SKalle Valo 			       q->mmio_base + B43_PIO8_RXDATA,
70758619b14SKalle Valo 			       sizeof(u32));
70858619b14SKalle Valo 		if (len & 3) {
70958619b14SKalle Valo 			u8 *tail = wl->pio_tailspace;
71058619b14SKalle Valo 			BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
71158619b14SKalle Valo 
71258619b14SKalle Valo 			/* Read the last few bytes. */
71358619b14SKalle Valo 			b43_block_read(dev, tail, 4,
71458619b14SKalle Valo 				       q->mmio_base + B43_PIO8_RXDATA,
71558619b14SKalle Valo 				       sizeof(u32));
71658619b14SKalle Valo 			switch (len & 3) {
71758619b14SKalle Valo 			case 3:
71858619b14SKalle Valo 				skb->data[len + padding - 3] = tail[0];
71958619b14SKalle Valo 				skb->data[len + padding - 2] = tail[1];
72058619b14SKalle Valo 				skb->data[len + padding - 1] = tail[2];
72158619b14SKalle Valo 				break;
72258619b14SKalle Valo 			case 2:
72358619b14SKalle Valo 				skb->data[len + padding - 2] = tail[0];
72458619b14SKalle Valo 				skb->data[len + padding - 1] = tail[1];
72558619b14SKalle Valo 				break;
72658619b14SKalle Valo 			case 1:
72758619b14SKalle Valo 				skb->data[len + padding - 1] = tail[0];
72858619b14SKalle Valo 				break;
72958619b14SKalle Valo 			}
73058619b14SKalle Valo 		}
73158619b14SKalle Valo 	} else {
73258619b14SKalle Valo 		b43_block_read(dev, skb->data + padding, (len & ~1),
73358619b14SKalle Valo 			       q->mmio_base + B43_PIO_RXDATA,
73458619b14SKalle Valo 			       sizeof(u16));
73558619b14SKalle Valo 		if (len & 1) {
73658619b14SKalle Valo 			u8 *tail = wl->pio_tailspace;
73758619b14SKalle Valo 			BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
73858619b14SKalle Valo 
73958619b14SKalle Valo 			/* Read the last byte. */
74058619b14SKalle Valo 			b43_block_read(dev, tail, 2,
74158619b14SKalle Valo 				       q->mmio_base + B43_PIO_RXDATA,
74258619b14SKalle Valo 				       sizeof(u16));
74358619b14SKalle Valo 			skb->data[len + padding - 1] = tail[0];
74458619b14SKalle Valo 		}
74558619b14SKalle Valo 	}
74658619b14SKalle Valo 
74758619b14SKalle Valo 	b43_rx(q->dev, skb, rxhdr);
74858619b14SKalle Valo 
74958619b14SKalle Valo 	return true;
75058619b14SKalle Valo 
75158619b14SKalle Valo rx_error:
75258619b14SKalle Valo 	if (err_msg)
75358619b14SKalle Valo 		b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
75458619b14SKalle Valo 	if (q->rev >= 8)
75558619b14SKalle Valo 		b43_piorx_write32(q, B43_PIO8_RXCTL, B43_PIO8_RXCTL_DATARDY);
75658619b14SKalle Valo 	else
75758619b14SKalle Valo 		b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
75858619b14SKalle Valo 
75958619b14SKalle Valo 	return true;
76058619b14SKalle Valo }
76158619b14SKalle Valo 
76258619b14SKalle Valo void b43_pio_rx(struct b43_pio_rxqueue *q)
76358619b14SKalle Valo {
76458619b14SKalle Valo 	unsigned int count = 0;
76558619b14SKalle Valo 	bool stop;
76658619b14SKalle Valo 
76758619b14SKalle Valo 	while (1) {
768*f8f24eceSJason Yan 		stop = !pio_rx_frame(q);
76958619b14SKalle Valo 		if (stop)
77058619b14SKalle Valo 			break;
77158619b14SKalle Valo 		cond_resched();
77258619b14SKalle Valo 		if (WARN_ON_ONCE(++count > 10000))
77358619b14SKalle Valo 			break;
77458619b14SKalle Valo 	}
77558619b14SKalle Valo }
77658619b14SKalle Valo 
77758619b14SKalle Valo static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
77858619b14SKalle Valo {
77958619b14SKalle Valo 	if (q->rev >= 8) {
78058619b14SKalle Valo 		b43_piotx_write32(q, B43_PIO8_TXCTL,
78158619b14SKalle Valo 				  b43_piotx_read32(q, B43_PIO8_TXCTL)
78258619b14SKalle Valo 				  | B43_PIO8_TXCTL_SUSPREQ);
78358619b14SKalle Valo 	} else {
78458619b14SKalle Valo 		b43_piotx_write16(q, B43_PIO_TXCTL,
78558619b14SKalle Valo 				  b43_piotx_read16(q, B43_PIO_TXCTL)
78658619b14SKalle Valo 				  | B43_PIO_TXCTL_SUSPREQ);
78758619b14SKalle Valo 	}
78858619b14SKalle Valo }
78958619b14SKalle Valo 
79058619b14SKalle Valo static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
79158619b14SKalle Valo {
79258619b14SKalle Valo 	if (q->rev >= 8) {
79358619b14SKalle Valo 		b43_piotx_write32(q, B43_PIO8_TXCTL,
79458619b14SKalle Valo 				  b43_piotx_read32(q, B43_PIO8_TXCTL)
79558619b14SKalle Valo 				  & ~B43_PIO8_TXCTL_SUSPREQ);
79658619b14SKalle Valo 	} else {
79758619b14SKalle Valo 		b43_piotx_write16(q, B43_PIO_TXCTL,
79858619b14SKalle Valo 				  b43_piotx_read16(q, B43_PIO_TXCTL)
79958619b14SKalle Valo 				  & ~B43_PIO_TXCTL_SUSPREQ);
80058619b14SKalle Valo 	}
80158619b14SKalle Valo }
80258619b14SKalle Valo 
80358619b14SKalle Valo void b43_pio_tx_suspend(struct b43_wldev *dev)
80458619b14SKalle Valo {
80558619b14SKalle Valo 	b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
80658619b14SKalle Valo 	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK);
80758619b14SKalle Valo 	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE);
80858619b14SKalle Valo 	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI);
80958619b14SKalle Valo 	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO);
81058619b14SKalle Valo 	b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast);
81158619b14SKalle Valo }
81258619b14SKalle Valo 
81358619b14SKalle Valo void b43_pio_tx_resume(struct b43_wldev *dev)
81458619b14SKalle Valo {
81558619b14SKalle Valo 	b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast);
81658619b14SKalle Valo 	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO);
81758619b14SKalle Valo 	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI);
81858619b14SKalle Valo 	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE);
81958619b14SKalle Valo 	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK);
82058619b14SKalle Valo 	b43_power_saving_ctl_bits(dev, 0);
82158619b14SKalle Valo }
822