0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include "b43.h"
0014 #include "pio.h"
0015 #include "dma.h"
0016 #include "main.h"
0017 #include "xmit.h"
0018
0019 #include <linux/delay.h>
0020 #include <linux/sched.h>
0021 #include <linux/slab.h>
0022
0023
0024 static u16 generate_cookie(struct b43_pio_txqueue *q,
0025 struct b43_pio_txpacket *pack)
0026 {
0027 u16 cookie;
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 cookie = (((u16)q->index + 1) << 12);
0038 cookie |= pack->index;
0039
0040 return cookie;
0041 }
0042
0043 static
0044 struct b43_pio_txqueue *parse_cookie(struct b43_wldev *dev,
0045 u16 cookie,
0046 struct b43_pio_txpacket **pack)
0047 {
0048 struct b43_pio *pio = &dev->pio;
0049 struct b43_pio_txqueue *q = NULL;
0050 unsigned int pack_index;
0051
0052 switch (cookie & 0xF000) {
0053 case 0x1000:
0054 q = pio->tx_queue_AC_BK;
0055 break;
0056 case 0x2000:
0057 q = pio->tx_queue_AC_BE;
0058 break;
0059 case 0x3000:
0060 q = pio->tx_queue_AC_VI;
0061 break;
0062 case 0x4000:
0063 q = pio->tx_queue_AC_VO;
0064 break;
0065 case 0x5000:
0066 q = pio->tx_queue_mcast;
0067 break;
0068 }
0069 if (B43_WARN_ON(!q))
0070 return NULL;
0071 pack_index = (cookie & 0x0FFF);
0072 if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
0073 return NULL;
0074 *pack = &q->packets[pack_index];
0075
0076 return q;
0077 }
0078
0079 static u16 index_to_pioqueue_base(struct b43_wldev *dev,
0080 unsigned int index)
0081 {
0082 static const u16 bases[] = {
0083 B43_MMIO_PIO_BASE0,
0084 B43_MMIO_PIO_BASE1,
0085 B43_MMIO_PIO_BASE2,
0086 B43_MMIO_PIO_BASE3,
0087 B43_MMIO_PIO_BASE4,
0088 B43_MMIO_PIO_BASE5,
0089 B43_MMIO_PIO_BASE6,
0090 B43_MMIO_PIO_BASE7,
0091 };
0092 static const u16 bases_rev11[] = {
0093 B43_MMIO_PIO11_BASE0,
0094 B43_MMIO_PIO11_BASE1,
0095 B43_MMIO_PIO11_BASE2,
0096 B43_MMIO_PIO11_BASE3,
0097 B43_MMIO_PIO11_BASE4,
0098 B43_MMIO_PIO11_BASE5,
0099 };
0100
0101 if (dev->dev->core_rev >= 11) {
0102 B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
0103 return bases_rev11[index];
0104 }
0105 B43_WARN_ON(index >= ARRAY_SIZE(bases));
0106 return bases[index];
0107 }
0108
0109 static u16 pio_txqueue_offset(struct b43_wldev *dev)
0110 {
0111 if (dev->dev->core_rev >= 11)
0112 return 0x18;
0113 return 0;
0114 }
0115
0116 static u16 pio_rxqueue_offset(struct b43_wldev *dev)
0117 {
0118 if (dev->dev->core_rev >= 11)
0119 return 0x38;
0120 return 8;
0121 }
0122
0123 static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
0124 unsigned int index)
0125 {
0126 struct b43_pio_txqueue *q;
0127 struct b43_pio_txpacket *p;
0128 unsigned int i;
0129
0130 q = kzalloc(sizeof(*q), GFP_KERNEL);
0131 if (!q)
0132 return NULL;
0133 q->dev = dev;
0134 q->rev = dev->dev->core_rev;
0135 q->mmio_base = index_to_pioqueue_base(dev, index) +
0136 pio_txqueue_offset(dev);
0137 q->index = index;
0138
0139 q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
0140 if (q->rev >= 8) {
0141 q->buffer_size = 1920;
0142 } else {
0143 q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
0144 q->buffer_size -= 80;
0145 }
0146
0147 INIT_LIST_HEAD(&q->packets_list);
0148 for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
0149 p = &(q->packets[i]);
0150 INIT_LIST_HEAD(&p->list);
0151 p->index = i;
0152 p->queue = q;
0153 list_add(&p->list, &q->packets_list);
0154 }
0155
0156 return q;
0157 }
0158
0159 static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
0160 unsigned int index)
0161 {
0162 struct b43_pio_rxqueue *q;
0163
0164 q = kzalloc(sizeof(*q), GFP_KERNEL);
0165 if (!q)
0166 return NULL;
0167 q->dev = dev;
0168 q->rev = dev->dev->core_rev;
0169 q->mmio_base = index_to_pioqueue_base(dev, index) +
0170 pio_rxqueue_offset(dev);
0171
0172
0173 b43_dma_direct_fifo_rx(dev, index, 1);
0174
0175 return q;
0176 }
0177
0178 static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
0179 {
0180 struct b43_pio_txpacket *pack;
0181 unsigned int i;
0182
0183 for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
0184 pack = &(q->packets[i]);
0185 if (pack->skb) {
0186 ieee80211_free_txskb(q->dev->wl->hw, pack->skb);
0187 pack->skb = NULL;
0188 }
0189 }
0190 }
0191
0192 static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
0193 const char *name)
0194 {
0195 if (!q)
0196 return;
0197 b43_pio_cancel_tx_packets(q);
0198 kfree(q);
0199 }
0200
0201 static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
0202 const char *name)
0203 {
0204 if (!q)
0205 return;
0206 kfree(q);
0207 }
0208
0209 #define destroy_queue_tx(pio, queue) do { \
0210 b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \
0211 (pio)->queue = NULL; \
0212 } while (0)
0213
0214 #define destroy_queue_rx(pio, queue) do { \
0215 b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \
0216 (pio)->queue = NULL; \
0217 } while (0)
0218
0219 void b43_pio_free(struct b43_wldev *dev)
0220 {
0221 struct b43_pio *pio;
0222
0223 if (!b43_using_pio_transfers(dev))
0224 return;
0225 pio = &dev->pio;
0226
0227 destroy_queue_rx(pio, rx_queue);
0228 destroy_queue_tx(pio, tx_queue_mcast);
0229 destroy_queue_tx(pio, tx_queue_AC_VO);
0230 destroy_queue_tx(pio, tx_queue_AC_VI);
0231 destroy_queue_tx(pio, tx_queue_AC_BE);
0232 destroy_queue_tx(pio, tx_queue_AC_BK);
0233 }
0234
0235 int b43_pio_init(struct b43_wldev *dev)
0236 {
0237 struct b43_pio *pio = &dev->pio;
0238 int err = -ENOMEM;
0239
0240 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
0241 & ~B43_MACCTL_BE);
0242 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0);
0243
0244 pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0);
0245 if (!pio->tx_queue_AC_BK)
0246 goto out;
0247
0248 pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1);
0249 if (!pio->tx_queue_AC_BE)
0250 goto err_destroy_bk;
0251
0252 pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2);
0253 if (!pio->tx_queue_AC_VI)
0254 goto err_destroy_be;
0255
0256 pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3);
0257 if (!pio->tx_queue_AC_VO)
0258 goto err_destroy_vi;
0259
0260 pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4);
0261 if (!pio->tx_queue_mcast)
0262 goto err_destroy_vo;
0263
0264 pio->rx_queue = b43_setup_pioqueue_rx(dev, 0);
0265 if (!pio->rx_queue)
0266 goto err_destroy_mcast;
0267
0268 b43dbg(dev->wl, "PIO initialized\n");
0269 err = 0;
0270 out:
0271 return err;
0272
0273 err_destroy_mcast:
0274 destroy_queue_tx(pio, tx_queue_mcast);
0275 err_destroy_vo:
0276 destroy_queue_tx(pio, tx_queue_AC_VO);
0277 err_destroy_vi:
0278 destroy_queue_tx(pio, tx_queue_AC_VI);
0279 err_destroy_be:
0280 destroy_queue_tx(pio, tx_queue_AC_BE);
0281 err_destroy_bk:
0282 destroy_queue_tx(pio, tx_queue_AC_BK);
0283 return err;
0284 }
0285
0286
0287 static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev,
0288 u8 queue_prio)
0289 {
0290 struct b43_pio_txqueue *q;
0291
0292 if (dev->qos_enabled) {
0293
0294 switch (queue_prio) {
0295 default:
0296 B43_WARN_ON(1);
0297 fallthrough;
0298 case 0:
0299 q = dev->pio.tx_queue_AC_VO;
0300 break;
0301 case 1:
0302 q = dev->pio.tx_queue_AC_VI;
0303 break;
0304 case 2:
0305 q = dev->pio.tx_queue_AC_BE;
0306 break;
0307 case 3:
0308 q = dev->pio.tx_queue_AC_BK;
0309 break;
0310 }
0311 } else
0312 q = dev->pio.tx_queue_AC_BE;
0313
0314 return q;
0315 }
0316
0317 static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
0318 u16 ctl,
0319 const void *_data,
0320 unsigned int data_len)
0321 {
0322 struct b43_wldev *dev = q->dev;
0323 struct b43_wl *wl = dev->wl;
0324 const u8 *data = _data;
0325
0326 ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
0327 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
0328
0329 b43_block_write(dev, data, (data_len & ~1),
0330 q->mmio_base + B43_PIO_TXDATA,
0331 sizeof(u16));
0332 if (data_len & 1) {
0333 u8 *tail = wl->pio_tailspace;
0334 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
0335
0336
0337 ctl &= ~B43_PIO_TXCTL_WRITEHI;
0338 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
0339 tail[0] = data[data_len - 1];
0340 tail[1] = 0;
0341 b43_block_write(dev, tail, 2,
0342 q->mmio_base + B43_PIO_TXDATA,
0343 sizeof(u16));
0344 }
0345
0346 return ctl;
0347 }
0348
0349 static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
0350 const u8 *hdr, unsigned int hdrlen)
0351 {
0352 struct b43_pio_txqueue *q = pack->queue;
0353 const char *frame = pack->skb->data;
0354 unsigned int frame_len = pack->skb->len;
0355 u16 ctl;
0356
0357 ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
0358 ctl |= B43_PIO_TXCTL_FREADY;
0359 ctl &= ~B43_PIO_TXCTL_EOF;
0360
0361
0362 ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
0363
0364 ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
0365
0366 ctl |= B43_PIO_TXCTL_EOF;
0367 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
0368 }
0369
0370 static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
0371 u32 ctl,
0372 const void *_data,
0373 unsigned int data_len)
0374 {
0375 struct b43_wldev *dev = q->dev;
0376 struct b43_wl *wl = dev->wl;
0377 const u8 *data = _data;
0378
0379 ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
0380 B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
0381 b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
0382
0383 b43_block_write(dev, data, (data_len & ~3),
0384 q->mmio_base + B43_PIO8_TXDATA,
0385 sizeof(u32));
0386 if (data_len & 3) {
0387 u8 *tail = wl->pio_tailspace;
0388 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
0389
0390 memset(tail, 0, 4);
0391
0392 ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
0393 B43_PIO8_TXCTL_24_31);
0394 switch (data_len & 3) {
0395 case 3:
0396 ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
0397 tail[0] = data[data_len - 3];
0398 tail[1] = data[data_len - 2];
0399 tail[2] = data[data_len - 1];
0400 break;
0401 case 2:
0402 ctl |= B43_PIO8_TXCTL_8_15;
0403 tail[0] = data[data_len - 2];
0404 tail[1] = data[data_len - 1];
0405 break;
0406 case 1:
0407 tail[0] = data[data_len - 1];
0408 break;
0409 }
0410 b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
0411 b43_block_write(dev, tail, 4,
0412 q->mmio_base + B43_PIO8_TXDATA,
0413 sizeof(u32));
0414 }
0415
0416 return ctl;
0417 }
0418
0419 static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
0420 const u8 *hdr, unsigned int hdrlen)
0421 {
0422 struct b43_pio_txqueue *q = pack->queue;
0423 const char *frame = pack->skb->data;
0424 unsigned int frame_len = pack->skb->len;
0425 u32 ctl;
0426
0427 ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
0428 ctl |= B43_PIO8_TXCTL_FREADY;
0429 ctl &= ~B43_PIO8_TXCTL_EOF;
0430
0431
0432 ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
0433
0434 ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
0435
0436 ctl |= B43_PIO8_TXCTL_EOF;
0437 b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
0438 }
0439
0440 static int pio_tx_frame(struct b43_pio_txqueue *q,
0441 struct sk_buff *skb)
0442 {
0443 struct b43_wldev *dev = q->dev;
0444 struct b43_wl *wl = dev->wl;
0445 struct b43_pio_txpacket *pack;
0446 u16 cookie;
0447 int err;
0448 unsigned int hdrlen;
0449 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0450 struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
0451
0452 B43_WARN_ON(list_empty(&q->packets_list));
0453 pack = list_entry(q->packets_list.next,
0454 struct b43_pio_txpacket, list);
0455
0456 cookie = generate_cookie(q, pack);
0457 hdrlen = b43_txhdr_size(dev);
0458 BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
0459 B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
0460 err = b43_generate_txhdr(dev, (u8 *)txhdr, skb,
0461 info, cookie);
0462 if (err)
0463 return err;
0464
0465 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
0466
0467
0468 b43_shm_write16(dev, B43_SHM_SHARED,
0469 B43_SHM_SH_MCASTCOOKIE, cookie);
0470 }
0471
0472 pack->skb = skb;
0473 if (q->rev >= 8)
0474 pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen);
0475 else
0476 pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen);
0477
0478
0479
0480 list_del(&pack->list);
0481
0482
0483 q->buffer_used += roundup(skb->len + hdrlen, 4);
0484 q->free_packet_slots -= 1;
0485
0486 return 0;
0487 }
0488
0489 int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
0490 {
0491 struct b43_pio_txqueue *q;
0492 struct ieee80211_hdr *hdr;
0493 unsigned int hdrlen, total_len;
0494 int err = 0;
0495 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0496
0497 hdr = (struct ieee80211_hdr *)skb->data;
0498
0499 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
0500
0501 q = dev->pio.tx_queue_mcast;
0502
0503
0504 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
0505 } else {
0506
0507 q = select_queue_by_priority(dev, skb_get_queue_mapping(skb));
0508 }
0509
0510 hdrlen = b43_txhdr_size(dev);
0511 total_len = roundup(skb->len + hdrlen, 4);
0512
0513 if (unlikely(total_len > q->buffer_size)) {
0514 err = -ENOBUFS;
0515 b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
0516 goto out;
0517 }
0518 if (unlikely(q->free_packet_slots == 0)) {
0519 err = -ENOBUFS;
0520 b43warn(dev->wl, "PIO: TX packet overflow.\n");
0521 goto out;
0522 }
0523 B43_WARN_ON(q->buffer_used > q->buffer_size);
0524
0525 if (total_len > (q->buffer_size - q->buffer_used)) {
0526
0527 err = -EBUSY;
0528 ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
0529 q->stopped = true;
0530 goto out;
0531 }
0532
0533
0534
0535
0536 q->queue_prio = skb_get_queue_mapping(skb);
0537
0538 err = pio_tx_frame(q, skb);
0539 if (unlikely(err == -ENOKEY)) {
0540
0541
0542 ieee80211_free_txskb(dev->wl->hw, skb);
0543 err = 0;
0544 goto out;
0545 }
0546 if (unlikely(err)) {
0547 b43err(dev->wl, "PIO transmission failure\n");
0548 goto out;
0549 }
0550
0551 B43_WARN_ON(q->buffer_used > q->buffer_size);
0552 if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
0553 (q->free_packet_slots == 0)) {
0554
0555 ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
0556 q->stopped = true;
0557 }
0558
0559 out:
0560 return err;
0561 }
0562
0563 void b43_pio_handle_txstatus(struct b43_wldev *dev,
0564 const struct b43_txstatus *status)
0565 {
0566 struct b43_pio_txqueue *q;
0567 struct b43_pio_txpacket *pack = NULL;
0568 unsigned int total_len;
0569 struct ieee80211_tx_info *info;
0570
0571 q = parse_cookie(dev, status->cookie, &pack);
0572 if (unlikely(!q))
0573 return;
0574 B43_WARN_ON(!pack);
0575
0576 info = IEEE80211_SKB_CB(pack->skb);
0577
0578 b43_fill_txstatus_report(dev, info, status);
0579
0580 total_len = pack->skb->len + b43_txhdr_size(dev);
0581 total_len = roundup(total_len, 4);
0582 q->buffer_used -= total_len;
0583 q->free_packet_slots += 1;
0584
0585 ieee80211_tx_status(dev->wl->hw, pack->skb);
0586 pack->skb = NULL;
0587 list_add(&pack->list, &q->packets_list);
0588
0589 if (q->stopped) {
0590 ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
0591 q->stopped = false;
0592 }
0593 }
0594
0595
0596 static bool pio_rx_frame(struct b43_pio_rxqueue *q)
0597 {
0598 struct b43_wldev *dev = q->dev;
0599 struct b43_wl *wl = dev->wl;
0600 u16 len;
0601 u32 macstat = 0;
0602 unsigned int i, padding;
0603 struct sk_buff *skb;
0604 const char *err_msg = NULL;
0605 struct b43_rxhdr_fw4 *rxhdr =
0606 (struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
0607 size_t rxhdr_size = sizeof(*rxhdr);
0608
0609 BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
0610 switch (dev->fw.hdr_format) {
0611 case B43_FW_HDR_410:
0612 case B43_FW_HDR_351:
0613 rxhdr_size -= sizeof(rxhdr->format_598) -
0614 sizeof(rxhdr->format_351);
0615 break;
0616 case B43_FW_HDR_598:
0617 break;
0618 }
0619 memset(rxhdr, 0, rxhdr_size);
0620
0621
0622 if (q->rev >= 8) {
0623 u32 ctl;
0624
0625 ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
0626 if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
0627 return false;
0628 b43_piorx_write32(q, B43_PIO8_RXCTL,
0629 B43_PIO8_RXCTL_FRAMERDY);
0630 for (i = 0; i < 10; i++) {
0631 ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
0632 if (ctl & B43_PIO8_RXCTL_DATARDY)
0633 goto data_ready;
0634 udelay(10);
0635 }
0636 } else {
0637 u16 ctl;
0638
0639 ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
0640 if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
0641 return false;
0642 b43_piorx_write16(q, B43_PIO_RXCTL,
0643 B43_PIO_RXCTL_FRAMERDY);
0644 for (i = 0; i < 10; i++) {
0645 ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
0646 if (ctl & B43_PIO_RXCTL_DATARDY)
0647 goto data_ready;
0648 udelay(10);
0649 }
0650 }
0651 b43dbg(q->dev->wl, "PIO RX timed out\n");
0652 return true;
0653 data_ready:
0654
0655
0656 if (q->rev >= 8) {
0657 b43_block_read(dev, rxhdr, rxhdr_size,
0658 q->mmio_base + B43_PIO8_RXDATA,
0659 sizeof(u32));
0660 } else {
0661 b43_block_read(dev, rxhdr, rxhdr_size,
0662 q->mmio_base + B43_PIO_RXDATA,
0663 sizeof(u16));
0664 }
0665
0666 len = le16_to_cpu(rxhdr->frame_len);
0667 if (unlikely(len > 0x700)) {
0668 err_msg = "len > 0x700";
0669 goto rx_error;
0670 }
0671 if (unlikely(len == 0)) {
0672 err_msg = "len == 0";
0673 goto rx_error;
0674 }
0675
0676 switch (dev->fw.hdr_format) {
0677 case B43_FW_HDR_598:
0678 macstat = le32_to_cpu(rxhdr->format_598.mac_status);
0679 break;
0680 case B43_FW_HDR_410:
0681 case B43_FW_HDR_351:
0682 macstat = le32_to_cpu(rxhdr->format_351.mac_status);
0683 break;
0684 }
0685 if (macstat & B43_RX_MAC_FCSERR) {
0686 if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
0687
0688 err_msg = "Frame FCS error";
0689 goto rx_error;
0690 }
0691 }
0692
0693
0694
0695
0696 padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
0697 skb = dev_alloc_skb(len + padding + 2);
0698 if (unlikely(!skb)) {
0699 err_msg = "Out of memory";
0700 goto rx_error;
0701 }
0702 skb_reserve(skb, 2);
0703 skb_put(skb, len + padding);
0704 if (q->rev >= 8) {
0705 b43_block_read(dev, skb->data + padding, (len & ~3),
0706 q->mmio_base + B43_PIO8_RXDATA,
0707 sizeof(u32));
0708 if (len & 3) {
0709 u8 *tail = wl->pio_tailspace;
0710 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
0711
0712
0713 b43_block_read(dev, tail, 4,
0714 q->mmio_base + B43_PIO8_RXDATA,
0715 sizeof(u32));
0716 switch (len & 3) {
0717 case 3:
0718 skb->data[len + padding - 3] = tail[0];
0719 skb->data[len + padding - 2] = tail[1];
0720 skb->data[len + padding - 1] = tail[2];
0721 break;
0722 case 2:
0723 skb->data[len + padding - 2] = tail[0];
0724 skb->data[len + padding - 1] = tail[1];
0725 break;
0726 case 1:
0727 skb->data[len + padding - 1] = tail[0];
0728 break;
0729 }
0730 }
0731 } else {
0732 b43_block_read(dev, skb->data + padding, (len & ~1),
0733 q->mmio_base + B43_PIO_RXDATA,
0734 sizeof(u16));
0735 if (len & 1) {
0736 u8 *tail = wl->pio_tailspace;
0737 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
0738
0739
0740 b43_block_read(dev, tail, 2,
0741 q->mmio_base + B43_PIO_RXDATA,
0742 sizeof(u16));
0743 skb->data[len + padding - 1] = tail[0];
0744 }
0745 }
0746
0747 b43_rx(q->dev, skb, rxhdr);
0748
0749 return true;
0750
0751 rx_error:
0752 if (err_msg)
0753 b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
0754 if (q->rev >= 8)
0755 b43_piorx_write32(q, B43_PIO8_RXCTL, B43_PIO8_RXCTL_DATARDY);
0756 else
0757 b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
0758
0759 return true;
0760 }
0761
0762 void b43_pio_rx(struct b43_pio_rxqueue *q)
0763 {
0764 unsigned int count = 0;
0765 bool stop;
0766
0767 while (1) {
0768 stop = !pio_rx_frame(q);
0769 if (stop)
0770 break;
0771 cond_resched();
0772 if (WARN_ON_ONCE(++count > 10000))
0773 break;
0774 }
0775 }
0776
0777 static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
0778 {
0779 if (q->rev >= 8) {
0780 b43_piotx_write32(q, B43_PIO8_TXCTL,
0781 b43_piotx_read32(q, B43_PIO8_TXCTL)
0782 | B43_PIO8_TXCTL_SUSPREQ);
0783 } else {
0784 b43_piotx_write16(q, B43_PIO_TXCTL,
0785 b43_piotx_read16(q, B43_PIO_TXCTL)
0786 | B43_PIO_TXCTL_SUSPREQ);
0787 }
0788 }
0789
0790 static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
0791 {
0792 if (q->rev >= 8) {
0793 b43_piotx_write32(q, B43_PIO8_TXCTL,
0794 b43_piotx_read32(q, B43_PIO8_TXCTL)
0795 & ~B43_PIO8_TXCTL_SUSPREQ);
0796 } else {
0797 b43_piotx_write16(q, B43_PIO_TXCTL,
0798 b43_piotx_read16(q, B43_PIO_TXCTL)
0799 & ~B43_PIO_TXCTL_SUSPREQ);
0800 }
0801 }
0802
0803 void b43_pio_tx_suspend(struct b43_wldev *dev)
0804 {
0805 b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
0806 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK);
0807 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE);
0808 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI);
0809 b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO);
0810 b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast);
0811 }
0812
0813 void b43_pio_tx_resume(struct b43_wldev *dev)
0814 {
0815 b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast);
0816 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO);
0817 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI);
0818 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE);
0819 b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK);
0820 b43_power_saving_ctl_bits(dev, 0);
0821 }