hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
....@@ -1,17 +1,6 @@
1
+// SPDX-License-Identifier: ISC
12 /*
23 * Copyright (c) 2010 Broadcom Corporation
3
- *
4
- * Permission to use, copy, modify, and/or distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
7
- *
8
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
154 */
165 #include <linux/types.h>
176 #include <linux/module.h>
....@@ -322,28 +311,6 @@
322311 /* How long to defer borrowing in jiffies */
323312 #define BRCMF_FWS_BORROW_DEFER_PERIOD (HZ / 10)
324313
325
-/**
326
- * enum brcmf_fws_fifo - fifo indices used by dongle firmware.
327
- *
328
- * @BRCMF_FWS_FIFO_FIRST: first fifo, ie. background.
329
- * @BRCMF_FWS_FIFO_AC_BK: fifo for background traffic.
330
- * @BRCMF_FWS_FIFO_AC_BE: fifo for best-effort traffic.
331
- * @BRCMF_FWS_FIFO_AC_VI: fifo for video traffic.
332
- * @BRCMF_FWS_FIFO_AC_VO: fifo for voice traffic.
333
- * @BRCMF_FWS_FIFO_BCMC: fifo for broadcast/multicast (AP only).
334
- * @BRCMF_FWS_FIFO_ATIM: fifo for ATIM (AP only).
335
- * @BRCMF_FWS_FIFO_COUNT: number of fifos.
336
- */
337
-enum brcmf_fws_fifo {
338
- BRCMF_FWS_FIFO_FIRST,
339
- BRCMF_FWS_FIFO_AC_BK = BRCMF_FWS_FIFO_FIRST,
340
- BRCMF_FWS_FIFO_AC_BE,
341
- BRCMF_FWS_FIFO_AC_VI,
342
- BRCMF_FWS_FIFO_AC_VO,
343
- BRCMF_FWS_FIFO_BCMC,
344
- BRCMF_FWS_FIFO_ATIM,
345
- BRCMF_FWS_FIFO_COUNT
346
-};
347314
348315 /**
349316 * enum brcmf_fws_txstatus - txstatus flag values.
....@@ -356,6 +323,10 @@
356323 * firmware suppress the packet as device is already in PS mode.
357324 * @BRCMF_FWS_TXSTATUS_FW_TOSSED:
358325 * firmware tossed the packet.
326
+ * @BRCMF_FWS_TXSTATUS_FW_DISCARD_NOACK:
327
+ * firmware tossed the packet after retries.
328
+ * @BRCMF_FWS_TXSTATUS_FW_SUPPRESS_ACKED:
329
+ * firmware wrongly reported suppressed previously, now fixing to acked.
359330 * @BRCMF_FWS_TXSTATUS_HOST_TOSSED:
360331 * host tossed the packet.
361332 */
....@@ -364,6 +335,8 @@
364335 BRCMF_FWS_TXSTATUS_CORE_SUPPRESS,
365336 BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS,
366337 BRCMF_FWS_TXSTATUS_FW_TOSSED,
338
+ BRCMF_FWS_TXSTATUS_FW_DISCARD_NOACK,
339
+ BRCMF_FWS_TXSTATUS_FW_SUPPRESS_ACKED,
367340 BRCMF_FWS_TXSTATUS_HOST_TOSSED
368341 };
369342
....@@ -381,6 +354,7 @@
381354 /**
382355 * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface
383356 *
357
+ * @name: name of the descriptor.
384358 * @occupied: slot is in use.
385359 * @mac_handle: handle for mac entry determined by firmware.
386360 * @interface_id: interface index.
....@@ -389,10 +363,15 @@
389363 * @generation: generation bit.
390364 * @ac_bitmap: ac queue bitmap.
391365 * @requested_credit: credits requested by firmware.
366
+ * @requested_packet: packet requested by firmware.
392367 * @ea: ethernet address.
393368 * @seq: per-node free-running sequence.
394369 * @psq: power-save queue.
395370 * @transit_count: packet in transit to firmware.
371
+ * @suppr_transit_count: suppressed packet in transit to firmware.
372
+ * @send_tim_signal: if set tim signal will be sent.
373
+ * @traffic_pending_bmp: traffic pending bitmap.
374
+ * @traffic_lastreported_bmp: traffic last reported bitmap.
396375 */
397376 struct brcmf_fws_mac_descriptor {
398377 char name[16];
....@@ -415,7 +394,8 @@
415394 u8 traffic_lastreported_bmp;
416395 };
417396
418
-#define BRCMF_FWS_HANGER_MAXITEMS 1024
397
+#define BRCMF_FWS_HANGER_MAXITEMS 3072
398
+#define BRCMF_BORROW_RATIO 3
419399
420400 /**
421401 * enum brcmf_fws_hanger_item_state - state of hanger item.
....@@ -511,7 +491,9 @@
511491 struct work_struct fws_dequeue_work;
512492 u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT];
513493 int fifo_credit[BRCMF_FWS_FIFO_COUNT];
514
- int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1];
494
+ int init_fifo_credit[BRCMF_FWS_FIFO_COUNT];
495
+ int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1]
496
+ [BRCMF_FWS_FIFO_AC_VO + 1];
515497 int deq_node_pos[BRCMF_FWS_FIFO_COUNT];
516498 u32 fifo_credit_map;
517499 u32 fifo_delay_map;
....@@ -520,20 +502,6 @@
520502 bool creditmap_received;
521503 u8 mode;
522504 bool avoid_queueing;
523
-};
524
-
525
-/*
526
- * brcmf_fws_prio2fifo - mapping from 802.1d priority to firmware fifo index.
527
- */
528
-static const int brcmf_fws_prio2fifo[] = {
529
- BRCMF_FWS_FIFO_AC_BE,
530
- BRCMF_FWS_FIFO_AC_BK,
531
- BRCMF_FWS_FIFO_AC_BK,
532
- BRCMF_FWS_FIFO_AC_BE,
533
- BRCMF_FWS_FIFO_AC_VI,
534
- BRCMF_FWS_FIFO_AC_VI,
535
- BRCMF_FWS_FIFO_AC_VO,
536
- BRCMF_FWS_FIFO_AC_VO
537505 };
538506
539507 #define BRCMF_FWS_TLV_DEF(name, id, len) \
....@@ -922,7 +890,7 @@
922890 wlh += wlh[1] + 2;
923891
924892 if (entry->send_tim_signal) {
925
- entry->send_tim_signal = 0;
893
+ entry->send_tim_signal = false;
926894 wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP;
927895 wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
928896 wlh[2] = entry->mac_handle;
....@@ -1223,11 +1191,11 @@
12231191
12241192 fws->fifo_credit_map |= 1 << fifo;
12251193
1226
- if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
1227
- (fws->credits_borrowed[0])) {
1194
+ if (fifo > BRCMF_FWS_FIFO_AC_BK &&
1195
+ fifo <= BRCMF_FWS_FIFO_AC_VO) {
12281196 for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0;
12291197 lender_ac--) {
1230
- borrowed = &fws->credits_borrowed[lender_ac];
1198
+ borrowed = &fws->credits_borrowed[fifo][lender_ac];
12311199 if (*borrowed) {
12321200 fws->fifo_credit_map |= (1 << lender_ac);
12331201 fifo_credit = &fws->fifo_credit[lender_ac];
....@@ -1244,7 +1212,13 @@
12441212 }
12451213 }
12461214
1247
- fws->fifo_credit[fifo] += credits;
1215
+ if (credits) {
1216
+ fws->fifo_credit[fifo] += credits;
1217
+ }
1218
+
1219
+ if (fws->fifo_credit[fifo] > fws->init_fifo_credit[fifo])
1220
+ fws->fifo_credit[fifo] = fws->init_fifo_credit[fifo];
1221
+
12481222 }
12491223
12501224 static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws)
....@@ -1259,6 +1233,7 @@
12591233 enum brcmf_fws_skb_state state, int fifo,
12601234 struct sk_buff *p)
12611235 {
1236
+ struct brcmf_pub *drvr = fws->drvr;
12621237 int prec = 2 * fifo;
12631238 u32 *qfull_stat = &fws->stats.delayq_full_error;
12641239 struct brcmf_fws_mac_descriptor *entry;
....@@ -1271,7 +1246,7 @@
12711246
12721247 entry = brcmf_skbcb(p)->mac;
12731248 if (entry == NULL) {
1274
- brcmf_err("no mac descriptor found for skb %p\n", p);
1249
+ bphy_err(drvr, "no mac descriptor found for skb %p\n", p);
12751250 return -ENOENT;
12761251 }
12771252
....@@ -1459,9 +1434,11 @@
14591434
14601435 static int
14611436 brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
1462
- u32 genbit, u16 seq)
1437
+ u32 genbit, u16 seq, u8 compcnt)
14631438 {
1439
+ struct brcmf_pub *drvr = fws->drvr;
14641440 u32 fifo;
1441
+ u8 cnt = 0;
14651442 int ret;
14661443 bool remove_from_hanger = true;
14671444 struct sk_buff *skb;
....@@ -1472,60 +1449,75 @@
14721449 brcmf_dbg(DATA, "flags %d\n", flags);
14731450
14741451 if (flags == BRCMF_FWS_TXSTATUS_DISCARD)
1475
- fws->stats.txs_discard++;
1452
+ fws->stats.txs_discard += compcnt;
14761453 else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) {
1477
- fws->stats.txs_supp_core++;
1454
+ fws->stats.txs_supp_core += compcnt;
14781455 remove_from_hanger = false;
14791456 } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) {
1480
- fws->stats.txs_supp_ps++;
1457
+ fws->stats.txs_supp_ps += compcnt;
14811458 remove_from_hanger = false;
14821459 } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED)
1483
- fws->stats.txs_tossed++;
1460
+ fws->stats.txs_tossed += compcnt;
1461
+ else if (flags == BRCMF_FWS_TXSTATUS_FW_DISCARD_NOACK)
1462
+ fws->stats.txs_discard += compcnt;
1463
+ else if (flags == BRCMF_FWS_TXSTATUS_FW_SUPPRESS_ACKED)
1464
+ fws->stats.txs_discard += compcnt;
14841465 else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)
1485
- fws->stats.txs_host_tossed++;
1466
+ fws->stats.txs_host_tossed += compcnt;
14861467 else
1487
- brcmf_err("unexpected txstatus\n");
1468
+ bphy_err(drvr, "unexpected txstatus\n");
14881469
1489
- ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
1490
- remove_from_hanger);
1491
- if (ret != 0) {
1492
- brcmf_err("no packet in hanger slot: hslot=%d\n", hslot);
1493
- return ret;
1470
+ while (cnt < compcnt) {
1471
+ ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
1472
+ remove_from_hanger);
1473
+ if (ret != 0) {
1474
+ bphy_err(drvr, "no packet in hanger slot: hslot=%d\n",
1475
+ hslot);
1476
+ goto cont;
1477
+ }
1478
+
1479
+ skcb = brcmf_skbcb(skb);
1480
+ entry = skcb->mac;
1481
+ if (WARN_ON(!entry)) {
1482
+ brcmu_pkt_buf_free_skb(skb);
1483
+ goto cont;
1484
+ }
1485
+ entry->transit_count--;
1486
+ if (entry->suppressed && entry->suppr_transit_count)
1487
+ entry->suppr_transit_count--;
1488
+
1489
+ brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name,
1490
+ flags, skcb->htod, seq);
1491
+
1492
+ /* pick up the implicit credit from this packet */
1493
+ fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
1494
+ if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT ||
1495
+ (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
1496
+ flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) {
1497
+ brcmf_fws_return_credits(fws, fifo, 1);
1498
+ brcmf_fws_schedule_deq(fws);
1499
+ }
1500
+ brcmf_fws_macdesc_return_req_credit(skb);
1501
+
1502
+ ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
1503
+ if (ret) {
1504
+ brcmu_pkt_buf_free_skb(skb);
1505
+ goto cont;
1506
+ }
1507
+ if (!remove_from_hanger)
1508
+ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
1509
+ genbit, seq);
1510
+ if (remove_from_hanger || ret)
1511
+ brcmf_txfinalize(ifp, skb, true);
1512
+
1513
+cont:
1514
+ hslot = (hslot + 1) & (BRCMF_FWS_TXSTAT_HSLOT_MASK >>
1515
+ BRCMF_FWS_TXSTAT_HSLOT_SHIFT);
1516
+ if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
1517
+ seq = (seq + 1) & BRCMF_SKB_HTOD_SEQ_NR_MASK;
1518
+
1519
+ cnt++;
14941520 }
1495
-
1496
- skcb = brcmf_skbcb(skb);
1497
- entry = skcb->mac;
1498
- if (WARN_ON(!entry)) {
1499
- brcmu_pkt_buf_free_skb(skb);
1500
- return -EINVAL;
1501
- }
1502
- entry->transit_count--;
1503
- if (entry->suppressed && entry->suppr_transit_count)
1504
- entry->suppr_transit_count--;
1505
-
1506
- brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags,
1507
- skcb->htod, seq);
1508
-
1509
- /* pick up the implicit credit from this packet */
1510
- fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
1511
- if ((fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT) ||
1512
- (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
1513
- (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) {
1514
- brcmf_fws_return_credits(fws, fifo, 1);
1515
- brcmf_fws_schedule_deq(fws);
1516
- }
1517
- brcmf_fws_macdesc_return_req_credit(skb);
1518
-
1519
- ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
1520
- if (ret) {
1521
- brcmu_pkt_buf_free_skb(skb);
1522
- return -EINVAL;
1523
- }
1524
- if (!remove_from_hanger)
1525
- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
1526
- genbit, seq);
1527
- if (remove_from_hanger || ret)
1528
- brcmf_txfinalize(ifp, skb, true);
15291521
15301522 return 0;
15311523 }
....@@ -1551,7 +1543,8 @@
15511543 return BRCMF_FWS_RET_OK_SCHEDULE;
15521544 }
15531545
1554
-static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
1546
+static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 type,
1547
+ u8 *data)
15551548 {
15561549 __le32 status_le;
15571550 __le16 seq_le;
....@@ -1560,23 +1553,31 @@
15601553 u32 genbit;
15611554 u8 flags;
15621555 u16 seq;
1556
+ u8 compcnt;
1557
+ u8 compcnt_offset = BRCMF_FWS_TYPE_TXSTATUS_LEN;
15631558
1564
- fws->stats.txs_indicate++;
15651559 memcpy(&status_le, data, sizeof(status_le));
15661560 status = le32_to_cpu(status_le);
15671561 flags = brcmf_txstatus_get_field(status, FLAGS);
15681562 hslot = brcmf_txstatus_get_field(status, HSLOT);
15691563 genbit = brcmf_txstatus_get_field(status, GENERATION);
15701564 if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
1571
- memcpy(&seq_le, &data[BRCMF_FWS_TYPE_PKTTAG_LEN],
1565
+ memcpy(&seq_le, &data[BRCMF_FWS_TYPE_TXSTATUS_LEN],
15721566 sizeof(seq_le));
15731567 seq = le16_to_cpu(seq_le);
1568
+ compcnt_offset += BRCMF_FWS_TYPE_SEQ_LEN;
15741569 } else {
15751570 seq = 0;
15761571 }
15771572
1573
+ if (type == BRCMF_FWS_TYPE_COMP_TXSTATUS)
1574
+ compcnt = data[compcnt_offset];
1575
+ else
1576
+ compcnt = 1;
1577
+ fws->stats.txs_indicate += compcnt;
1578
+
15781579 brcmf_fws_lock(fws);
1579
- brcmf_fws_txs_process(fws, flags, hslot, genbit, seq);
1580
+ brcmf_fws_txs_process(fws, flags, hslot, genbit, seq, compcnt);
15801581 brcmf_fws_unlock(fws);
15811582 return BRCMF_FWS_RET_OK_NOSCHEDULE;
15821583 }
....@@ -1595,27 +1596,30 @@
15951596 const struct brcmf_event_msg *e,
15961597 void *data)
15971598 {
1598
- struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
1599
+ struct brcmf_pub *drvr = ifp->drvr;
1600
+ struct brcmf_fws_info *fws = drvr_to_fws(drvr);
15991601 int i;
16001602 u8 *credits = data;
16011603
16021604 if (e->datalen < BRCMF_FWS_FIFO_COUNT) {
1603
- brcmf_err("event payload too small (%d)\n", e->datalen);
1605
+ bphy_err(drvr, "event payload too small (%d)\n", e->datalen);
16041606 return -EINVAL;
16051607 }
1606
- if (fws->creditmap_received)
1607
- return 0;
16081608
16091609 fws->creditmap_received = true;
16101610
16111611 brcmf_dbg(TRACE, "enter: credits %pM\n", credits);
16121612 brcmf_fws_lock(fws);
16131613 for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) {
1614
- if (*credits)
1614
+ fws->fifo_credit[i] += credits[i] - fws->init_fifo_credit[i];
1615
+ fws->init_fifo_credit[i] = credits[i];
1616
+ if (fws->fifo_credit[i] > 0)
16151617 fws->fifo_credit_map |= 1 << i;
16161618 else
16171619 fws->fifo_credit_map &= ~(1 << i);
1618
- fws->fifo_credit[i] = *credits++;
1620
+ WARN_ONCE(fws->fifo_credit[i] < 0,
1621
+ "fifo_credit[%d] is negative(%d)\n", i,
1622
+ fws->fifo_credit[i]);
16191623 }
16201624 brcmf_fws_schedule_deq(fws);
16211625 brcmf_fws_unlock(fws);
....@@ -1660,8 +1664,9 @@
16601664 rfi->pend_pkts -= skb_queue_len(skb_list);
16611665 }
16621666
1663
-void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
1667
+void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt, bool inirq)
16641668 {
1669
+ struct brcmf_pub *drvr = ifp->drvr;
16651670 u8 *reorder_data;
16661671 u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
16671672 struct brcmf_ampdu_rx_reorder *rfi;
....@@ -1676,8 +1681,8 @@
16761681
16771682 /* validate flags and flow id */
16781683 if (flags == 0xFF) {
1679
- brcmf_err("invalid flags...so ignore this packet\n");
1680
- brcmf_netif_rx(ifp, pkt);
1684
+ bphy_err(drvr, "invalid flags...so ignore this packet\n");
1685
+ brcmf_netif_rx(ifp, pkt, inirq);
16811686 return;
16821687 }
16831688
....@@ -1689,7 +1694,7 @@
16891694 if (rfi == NULL) {
16901695 brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
16911696 flow_id);
1692
- brcmf_netif_rx(ifp, pkt);
1697
+ brcmf_netif_rx(ifp, pkt, inirq);
16931698 return;
16941699 }
16951700
....@@ -1713,8 +1718,8 @@
17131718 flow_id, max_idx);
17141719 rfi = kzalloc(buf_size, GFP_ATOMIC);
17151720 if (rfi == NULL) {
1716
- brcmf_err("failed to alloc buffer\n");
1717
- brcmf_netif_rx(ifp, pkt);
1721
+ bphy_err(drvr, "failed to alloc buffer\n");
1722
+ brcmf_netif_rx(ifp, pkt, inirq);
17181723 return;
17191724 }
17201725
....@@ -1828,7 +1833,7 @@
18281833 netif_rx:
18291834 skb_queue_walk_safe(&reorder_list, pkt, pnext) {
18301835 __skb_unlink(pkt, &reorder_list);
1831
- brcmf_netif_rx(ifp, pkt);
1836
+ brcmf_netif_rx(ifp, pkt, inirq);
18321837 }
18331838 }
18341839
....@@ -1848,6 +1853,9 @@
18481853 ifp->ifidx, skb->len, siglen);
18491854
18501855 WARN_ON(siglen > skb->len);
1856
+
1857
+ if (siglen > skb->len)
1858
+ siglen = skb->len;
18511859
18521860 if (!siglen)
18531861 return;
....@@ -1890,8 +1898,6 @@
18901898
18911899 err = BRCMF_FWS_RET_OK_NOSCHEDULE;
18921900 switch (type) {
1893
- case BRCMF_FWS_TYPE_COMP_TXSTATUS:
1894
- break;
18951901 case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
18961902 rd = (struct brcmf_skb_reorder_data *)skb->cb;
18971903 rd->reorder = data;
....@@ -1914,7 +1920,8 @@
19141920 err = brcmf_fws_request_indicate(fws, type, data);
19151921 break;
19161922 case BRCMF_FWS_TYPE_TXSTATUS:
1917
- brcmf_fws_txstatus_indicate(fws, data);
1923
+ case BRCMF_FWS_TYPE_COMP_TXSTATUS:
1924
+ brcmf_fws_txstatus_indicate(fws, type, data);
19181925 break;
19191926 case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
19201927 err = brcmf_fws_fifocreditback_indicate(fws, data);
....@@ -1978,6 +1985,7 @@
19781985 static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
19791986 struct sk_buff *skb, int fifo)
19801987 {
1988
+ struct brcmf_pub *drvr = fws->drvr;
19811989 struct brcmf_fws_mac_descriptor *entry;
19821990 struct sk_buff *pktout;
19831991 int qidx, hslot;
....@@ -1991,11 +1999,11 @@
19911999
19922000 pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb);
19932001 if (pktout == NULL) {
1994
- brcmf_err("%s queue %d full\n", entry->name, qidx);
2002
+ bphy_err(drvr, "%s queue %d full\n", entry->name, qidx);
19952003 rc = -ENOSPC;
19962004 }
19972005 } else {
1998
- brcmf_err("%s entry removed\n", entry->name);
2006
+ bphy_err(drvr, "%s entry removed\n", entry->name);
19992007 rc = -ENOENT;
20002008 }
20012009
....@@ -2003,7 +2011,7 @@
20032011 fws->stats.rollback_failed++;
20042012 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
20052013 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
2006
- hslot, 0, 0);
2014
+ hslot, 0, 0, 1);
20072015 } else {
20082016 fws->stats.rollback_success++;
20092017 brcmf_fws_return_credits(fws, fifo, 1);
....@@ -2011,27 +2019,31 @@
20112019 }
20122020 }
20132021
2014
-static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
2022
+static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws,
2023
+ int highest_lender_ac, int borrower_ac,
2024
+ bool borrow_all)
20152025 {
2016
- int lender_ac;
2026
+ int lender_ac, borrow_limit = 0;
20172027
2018
- if (time_after(fws->borrow_defer_timestamp, jiffies)) {
2019
- fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE);
2020
- return -ENAVAIL;
2021
- }
2028
+ for (lender_ac = 0; lender_ac <= highest_lender_ac; lender_ac++) {
20222029
2023
- for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) {
2024
- if (fws->fifo_credit[lender_ac]) {
2025
- fws->credits_borrowed[lender_ac]++;
2030
+ if (!borrow_all)
2031
+ borrow_limit =
2032
+ fws->init_fifo_credit[lender_ac] / BRCMF_BORROW_RATIO;
2033
+ else
2034
+ borrow_limit = 0;
2035
+
2036
+ if (fws->fifo_credit[lender_ac] > borrow_limit) {
2037
+ fws->credits_borrowed[borrower_ac][lender_ac]++;
20262038 fws->fifo_credit[lender_ac]--;
20272039 if (fws->fifo_credit[lender_ac] == 0)
20282040 fws->fifo_credit_map &= ~(1 << lender_ac);
2029
- fws->fifo_credit_map |= (1 << BRCMF_FWS_FIFO_AC_BE);
2041
+ fws->fifo_credit_map |= (1 << borrower_ac);
20302042 brcmf_dbg(DATA, "borrow credit from: %d\n", lender_ac);
20312043 return 0;
20322044 }
20332045 }
2034
- fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE);
2046
+ fws->fifo_credit_map &= ~(1 << borrower_ac);
20352047 return -ENAVAIL;
20362048 }
20372049
....@@ -2100,7 +2112,8 @@
21002112
21012113 int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
21022114 {
2103
- struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
2115
+ struct brcmf_pub *drvr = ifp->drvr;
2116
+ struct brcmf_fws_info *fws = drvr_to_fws(drvr);
21042117 struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
21052118 struct ethhdr *eh = (struct ethhdr *)(skb->data);
21062119 int fifo = BRCMF_FWS_FIFO_BCMC;
....@@ -2113,8 +2126,10 @@
21132126 skcb->if_flags = 0;
21142127 skcb->state = BRCMF_FWS_SKBSTATE_NEW;
21152128 brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
2129
+
2130
+ /* mapping from 802.1d priority to firmware fifo index */
21162131 if (!multicast)
2117
- fifo = brcmf_fws_prio2fifo[skb->priority];
2132
+ fifo = brcmf_map_prio_to_aci(drvr->config, skb->priority);
21182133
21192134 brcmf_fws_lock(fws);
21202135 if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
....@@ -2128,8 +2143,7 @@
21282143 brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
21292144 brcmf_fws_schedule_deq(fws);
21302145 } else {
2131
- brcmf_err("drop skb: no hanger slot\n");
2132
- brcmf_txfinalize(ifp, skb, false);
2146
+ bphy_err(drvr, "no hanger slot available\n");
21332147 rc = -ENOMEM;
21342148 }
21352149 brcmf_fws_unlock(fws);
....@@ -2220,8 +2234,10 @@
22202234 }
22212235 continue;
22222236 }
2223
- while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) &&
2224
- (fifo == BRCMF_FWS_FIFO_BCMC))) {
2237
+
2238
+ while ((fws->fifo_credit[fifo]) ||
2239
+ ((!fws->bcmc_credit_check) &&
2240
+ (fifo == BRCMF_FWS_FIFO_BCMC))) {
22252241 skb = brcmf_fws_deq(fws, fifo);
22262242 if (!skb)
22272243 break;
....@@ -2231,10 +2247,14 @@
22312247 if (fws->bus_flow_blocked)
22322248 break;
22332249 }
2234
- if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
2235
- (fws->fifo_credit[fifo] == 0) &&
2236
- (!fws->bus_flow_blocked)) {
2237
- while (brcmf_fws_borrow_credit(fws) == 0) {
2250
+
2251
+ if (fifo >= BRCMF_FWS_FIFO_AC_BE &&
2252
+ fifo <= BRCMF_FWS_FIFO_AC_VO &&
2253
+ fws->fifo_credit[fifo] == 0 &&
2254
+ !fws->bus_flow_blocked) {
2255
+ while (brcmf_fws_borrow_credit(fws,
2256
+ fifo - 1, fifo,
2257
+ true) == 0) {
22382258 skb = brcmf_fws_deq(fws, fifo);
22392259 if (!skb) {
22402260 brcmf_fws_return_credits(fws, fifo, 1);
....@@ -2339,7 +2359,7 @@
23392359 fws->drvr = drvr;
23402360 fws->fcmode = drvr->settings->fcmode;
23412361
2342
- if ((drvr->bus_if->always_use_fws_queue == false) &&
2362
+ if (!drvr->bus_if->always_use_fws_queue &&
23432363 (fws->fcmode == BRCMF_FWS_FCMODE_NONE)) {
23442364 fws->avoid_queueing = true;
23452365 brcmf_dbg(INFO, "FWS queueing will be avoided\n");
....@@ -2348,7 +2368,7 @@
23482368
23492369 fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
23502370 if (fws->fws_wq == NULL) {
2351
- brcmf_err("workqueue creation failed\n");
2371
+ bphy_err(drvr, "workqueue creation failed\n");
23522372 rc = -EBADF;
23532373 goto fail;
23542374 }
....@@ -2364,13 +2384,13 @@
23642384 rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
23652385 brcmf_fws_notify_credit_map);
23662386 if (rc < 0) {
2367
- brcmf_err("register credit map handler failed\n");
2387
+ bphy_err(drvr, "register credit map handler failed\n");
23682388 goto fail;
23692389 }
23702390 rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT,
23712391 brcmf_fws_notify_bcmc_credit_support);
23722392 if (rc < 0) {
2373
- brcmf_err("register bcmc credit handler failed\n");
2393
+ bphy_err(drvr, "register bcmc credit handler failed\n");
23742394 brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
23752395 goto fail;
23762396 }
....@@ -2382,7 +2402,7 @@
23822402 fws->fw_signals = true;
23832403 ifp = brcmf_get_ifp(drvr, 0);
23842404 if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) {
2385
- brcmf_err("failed to set bdcv2 tlv signaling\n");
2405
+ bphy_err(drvr, "failed to set bdcv2 tlv signaling\n");
23862406 fws->fcmode = BRCMF_FWS_FCMODE_NONE;
23872407 fws->fw_signals = false;
23882408 }
....@@ -2414,25 +2434,17 @@
24142434 return fws;
24152435
24162436 fail:
2417
- brcmf_fws_detach_pre_delif(fws);
2418
- brcmf_fws_detach_post_delif(fws);
2437
+ brcmf_fws_detach(fws);
24192438 return ERR_PTR(rc);
24202439 }
24212440
2422
-void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws)
2441
+void brcmf_fws_detach(struct brcmf_fws_info *fws)
24232442 {
24242443 if (!fws)
24252444 return;
2426
- if (fws->fws_wq) {
2427
- destroy_workqueue(fws->fws_wq);
2428
- fws->fws_wq = NULL;
2429
- }
2430
-}
24312445
2432
-void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws)
2433
-{
2434
- if (!fws)
2435
- return;
2446
+ if (fws->fws_wq)
2447
+ destroy_workqueue(fws->fws_wq);
24362448
24372449 /* cleanup */
24382450 brcmf_fws_lock(fws);
....@@ -2473,7 +2485,8 @@
24732485 }
24742486 brcmf_fws_lock(fws);
24752487 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
2476
- brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0);
2488
+ brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0,
2489
+ 1);
24772490 brcmf_fws_unlock(fws);
24782491 }
24792492