| .. | .. |
|---|
| 1 | | -/* SPDX-License-Identifier: GPL-2.0 */ |
|---|
| 2 | 1 | /* |
|---|
| 3 | 2 | * DHD PROP_TXSTATUS Module. |
|---|
| 4 | 3 | * |
|---|
| 5 | | - * Copyright (C) 1999-2019, Broadcom Corporation |
|---|
| 6 | | - * |
|---|
| 4 | + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation |
|---|
| 5 | + * |
|---|
| 6 | + * Copyright (C) 1999-2017, Broadcom Corporation |
|---|
| 7 | + * |
|---|
| 7 | 8 | * Unless you and Broadcom execute a separate written software license |
|---|
| 8 | 9 | * agreement governing use of this software, this software is licensed to you |
|---|
| 9 | 10 | * under the terms of the GNU General Public License version 2 (the "GPL"), |
|---|
| 10 | 11 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the |
|---|
| 11 | 12 | * following added to such license: |
|---|
| 12 | | - * |
|---|
| 13 | + * |
|---|
| 13 | 14 | * As a special exception, the copyright holders of this software give you |
|---|
| 14 | 15 | * permission to link this software with independent modules, and to copy and |
|---|
| 15 | 16 | * distribute the resulting executable under terms of your choice, provided that |
|---|
| .. | .. |
|---|
| 17 | 18 | * the license of that module. An independent module is a module which is not |
|---|
| 18 | 19 | * derived from this software. The special exception does not apply to any |
|---|
| 19 | 20 | * modifications of the software. |
|---|
| 20 | | - * |
|---|
| 21 | + * |
|---|
| 21 | 22 | * Notwithstanding the above, under no circumstances may you combine this |
|---|
| 22 | 23 | * software in any way with any other Broadcom software provided under a license |
|---|
| 23 | 24 | * other than the GPL, without Broadcom's express prior written consent. |
|---|
| .. | .. |
|---|
| 25 | 26 | * |
|---|
| 26 | 27 | * <<Broadcom-WL-IPTag/Open:>> |
|---|
| 27 | 28 | * |
|---|
| 28 | | - * $Id: dhd_wlfc.c 606400 2015-12-15 09:59:42Z $ |
|---|
| 29 | + * $Id: dhd_wlfc.c 700323 2017-05-18 16:12:11Z $ |
|---|
| 29 | 30 | * |
|---|
| 30 | 31 | */ |
|---|
| 31 | | - |
|---|
| 32 | 32 | |
|---|
| 33 | 33 | #include <typedefs.h> |
|---|
| 34 | 34 | #include <osl.h> |
|---|
| .. | .. |
|---|
| 39 | 39 | #include <dngl_stats.h> |
|---|
| 40 | 40 | #include <dhd.h> |
|---|
| 41 | 41 | |
|---|
| 42 | | -#ifdef BCMDBUS /* an abstraction layer that hides details of the underlying bus, eg \ |
|---|
| 43 | | - Linux USB */ |
|---|
| 44 | | -#include <dbus.h> |
|---|
| 45 | | -#else |
|---|
| 46 | 42 | #include <dhd_bus.h> |
|---|
| 47 | | -#endif /* BCMDBUS */ |
|---|
| 48 | 43 | |
|---|
| 49 | 44 | #include <dhd_dbg.h> |
|---|
| 50 | 45 | |
|---|
| 51 | 46 | #ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */ |
|---|
| 52 | 47 | #include <wlfc_proto.h> |
|---|
| 53 | 48 | #include <dhd_wlfc.h> |
|---|
| 54 | | -#endif |
|---|
| 49 | +#endif // endif |
|---|
| 55 | 50 | |
|---|
| 56 | 51 | #ifdef DHDTCPACK_SUPPRESS |
|---|
| 57 | 52 | #include <dhd_ip.h> |
|---|
| 58 | 53 | #endif /* DHDTCPACK_SUPPRESS */ |
|---|
| 59 | | - |
|---|
| 60 | 54 | |
|---|
| 61 | 55 | /* |
|---|
| 62 | 56 | * wlfc naming and lock rules: |
|---|
| .. | .. |
|---|
| 72 | 66 | #define WLFC_THREAD_RETRY_WAIT_MS 10000 /* 10 sec */ |
|---|
| 73 | 67 | #endif /* defined (DHD_WLFC_THREAD) */ |
|---|
| 74 | 68 | |
|---|
| 75 | | -#if defined(BCMDBUS) |
|---|
| 76 | | -extern int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf); |
|---|
| 77 | | -#endif |
|---|
| 78 | | - |
|---|
| 79 | 69 | #ifdef PROP_TXSTATUS |
|---|
| 80 | 70 | |
|---|
| 81 | 71 | #define DHD_WLFC_QMON_COMPLETE(entry) |
|---|
| 82 | | - |
|---|
| 83 | 72 | |
|---|
| 84 | 73 | /** reordering related */ |
|---|
| 85 | 74 | |
|---|
| .. | .. |
|---|
| 132 | 121 | return; |
|---|
| 133 | 122 | |
|---|
| 134 | 123 | ASSERT(prec >= 0 && prec < pq->num_prec); |
|---|
| 135 | | - /* queueing chains not allowed and no segmented SKB (Kernel-3.18.y) */ |
|---|
| 136 | | - ASSERT(!((PKTLINK(p) != NULL) && (PKTLINK(p) != p))); |
|---|
| 124 | + ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ |
|---|
| 137 | 125 | |
|---|
| 138 | 126 | ASSERT(!pktq_full(pq)); |
|---|
| 139 | | - ASSERT(!pktq_pfull(pq, prec)); |
|---|
| 127 | + ASSERT(!pktqprec_full(pq, prec)); |
|---|
| 140 | 128 | |
|---|
| 141 | 129 | q = &pq->q[prec]; |
|---|
| 142 | 130 | |
|---|
| 143 | | - PKTSETLINK(p, NULL); |
|---|
| 144 | 131 | if (q->head == NULL) { |
|---|
| 145 | 132 | /* empty queue */ |
|---|
| 146 | 133 | q->head = p; |
|---|
| .. | .. |
|---|
| 194 | 181 | |
|---|
| 195 | 182 | exit: |
|---|
| 196 | 183 | |
|---|
| 197 | | - q->len++; |
|---|
| 198 | | - pq->len++; |
|---|
| 184 | + q->n_pkts++; |
|---|
| 185 | + pq->n_pkts_tot++; |
|---|
| 199 | 186 | |
|---|
| 200 | 187 | if (pq->hi_prec < prec) |
|---|
| 201 | 188 | pq->hi_prec = (uint8)prec; |
|---|
| .. | .. |
|---|
| 504 | 491 | } |
|---|
| 505 | 492 | } |
|---|
| 506 | 493 | |
|---|
| 507 | | - q->len--; |
|---|
| 508 | | - pq->len--; |
|---|
| 494 | + q->n_pkts--; |
|---|
| 495 | + pq->n_pkts_tot--; |
|---|
| 496 | + |
|---|
| 497 | +#ifdef WL_TXQ_STALL |
|---|
| 498 | + q->dequeue_count++; |
|---|
| 499 | +#endif // endif |
|---|
| 509 | 500 | |
|---|
| 510 | 501 | PKTSETLINK(p, NULL); |
|---|
| 511 | 502 | |
|---|
| .. | .. |
|---|
| 593 | 584 | h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); |
|---|
| 594 | 585 | if (PKTSUMNEEDED(p)) |
|---|
| 595 | 586 | h->flags |= BDC_FLAG_SUM_NEEDED; |
|---|
| 596 | | - |
|---|
| 597 | 587 | |
|---|
| 598 | 588 | h->priority = (PKTPRIO(p) & BDC_PRIORITY_MASK); |
|---|
| 599 | 589 | h->flags2 = 0; |
|---|
| .. | .. |
|---|
| 699 | 689 | void *pout = NULL; |
|---|
| 700 | 690 | |
|---|
| 701 | 691 | ASSERT(dhdp && p); |
|---|
| 702 | | - ASSERT(prec >= 0 && prec <= WLFC_PSQ_PREC_COUNT); |
|---|
| 692 | + if (prec < 0 || prec >= WLFC_PSQ_PREC_COUNT) { |
|---|
| 693 | + ASSERT(0); |
|---|
| 694 | + return BCME_BADARG; |
|---|
| 695 | + } |
|---|
| 703 | 696 | |
|---|
| 704 | 697 | ctx = (athost_wl_status_info_t*)dhdp->wlfc_state; |
|---|
| 705 | 698 | |
|---|
| .. | .. |
|---|
| 774 | 767 | /* Fast case, precedence queue is not full and we are also not |
|---|
| 775 | 768 | * exceeding total queue length |
|---|
| 776 | 769 | */ |
|---|
| 777 | | - if (!pktq_pfull(pq, prec) && !pktq_full(pq)) { |
|---|
| 770 | + if (!pktqprec_full(pq, prec) && !pktq_full(pq)) { |
|---|
| 778 | 771 | goto exit; |
|---|
| 779 | 772 | } |
|---|
| 780 | 773 | |
|---|
| 781 | 774 | /* Determine precedence from which to evict packet, if any */ |
|---|
| 782 | | - if (pktq_pfull(pq, prec)) { |
|---|
| 775 | + if (pktqprec_full(pq, prec)) { |
|---|
| 783 | 776 | eprec = prec; |
|---|
| 784 | 777 | } else if (pktq_full(pq)) { |
|---|
| 785 | 778 | p = pktq_peek_tail(pq, &eprec); |
|---|
| .. | .. |
|---|
| 788 | 781 | return FALSE; |
|---|
| 789 | 782 | } |
|---|
| 790 | 783 | if ((eprec > prec) || (eprec < 0)) { |
|---|
| 791 | | - if (!pktq_pempty(pq, prec)) { |
|---|
| 784 | + if (!pktqprec_empty(pq, prec)) { |
|---|
| 792 | 785 | eprec = prec; |
|---|
| 793 | 786 | } else { |
|---|
| 794 | 787 | return FALSE; |
|---|
| .. | .. |
|---|
| 799 | 792 | /* Evict if needed */ |
|---|
| 800 | 793 | if (eprec >= 0) { |
|---|
| 801 | 794 | /* Detect queueing to unconfigured precedence */ |
|---|
| 802 | | - ASSERT(!pktq_pempty(pq, eprec)); |
|---|
| 795 | + ASSERT(!pktqprec_empty(pq, eprec)); |
|---|
| 803 | 796 | /* Evict all fragmented frames */ |
|---|
| 804 | 797 | dhd_prec_drop_pkts(dhdp, pq, eprec, _dhd_wlfc_prec_drop); |
|---|
| 805 | 798 | } |
|---|
| .. | .. |
|---|
| 940 | 933 | dhdp = (dhd_pub_t *)ctx->dhdp; |
|---|
| 941 | 934 | ASSERT(dhdp); |
|---|
| 942 | 935 | |
|---|
| 943 | | - if (dhdp->skip_fc && dhdp->skip_fc()) |
|---|
| 936 | + if (if_id >= 255) |
|---|
| 937 | + return; |
|---|
| 938 | + |
|---|
| 939 | + if (dhdp->skip_fc && dhdp->skip_fc((void *)dhdp, if_id)) |
|---|
| 944 | 940 | return; |
|---|
| 945 | 941 | |
|---|
| 946 | 942 | if ((ctx->hostif_flow_state[if_id] == OFF) && !_dhd_wlfc_allow_fc(ctx, if_id)) |
|---|
| 947 | 943 | return; |
|---|
| 948 | 944 | |
|---|
| 949 | | - if ((pq->len <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) { |
|---|
| 945 | + if ((pq->n_pkts_tot <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) { |
|---|
| 950 | 946 | /* start traffic */ |
|---|
| 951 | 947 | ctx->hostif_flow_state[if_id] = OFF; |
|---|
| 952 | 948 | /* |
|---|
| 953 | 949 | WLFC_DBGMESG(("qlen:%02d, if:%02d, ->OFF, start traffic %s()\n", |
|---|
| 954 | | - pq->len, if_id, __FUNCTION__)); |
|---|
| 950 | + pq->n_pkts_tot, if_id, __FUNCTION__)); |
|---|
| 955 | 951 | */ |
|---|
| 956 | 952 | WLFC_DBGMESG(("F")); |
|---|
| 957 | 953 | |
|---|
| .. | .. |
|---|
| 960 | 956 | ctx->toggle_host_if = 0; |
|---|
| 961 | 957 | } |
|---|
| 962 | 958 | |
|---|
| 963 | | - if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) { |
|---|
| 959 | + if (pq->n_pkts_tot >= WLFC_FLOWCONTROL_HIWATER && ctx->hostif_flow_state[if_id] == OFF) { |
|---|
| 964 | 960 | /* stop traffic */ |
|---|
| 965 | 961 | ctx->hostif_flow_state[if_id] = ON; |
|---|
| 966 | 962 | /* |
|---|
| 967 | 963 | WLFC_DBGMESG(("qlen:%02d, if:%02d, ->ON, stop traffic %s()\n", |
|---|
| 968 | | - pq->len, if_id, __FUNCTION__)); |
|---|
| 964 | + pq->n_pkts_tot, if_id, __FUNCTION__)); |
|---|
| 969 | 965 | */ |
|---|
| 970 | 966 | WLFC_DBGMESG(("N")); |
|---|
| 971 | 967 | |
|---|
| .. | .. |
|---|
| 1002 | 998 | DHD_PKTTAG_WLFCPKT_SET(PKTTAG(p), 1); |
|---|
| 1003 | 999 | #ifdef PROP_TXSTATUS_DEBUG |
|---|
| 1004 | 1000 | ctx->stats.signal_only_pkts_sent++; |
|---|
| 1005 | | -#endif |
|---|
| 1001 | +#endif // endif |
|---|
| 1006 | 1002 | |
|---|
| 1007 | 1003 | #if defined(BCMPCIE) |
|---|
| 1008 | 1004 | rc = dhd_bus_txdata(dhdp->bus, p, ctx->host_ifidx); |
|---|
| 1009 | | -#elif defined(BCMDBUS) |
|---|
| 1010 | | - rc = dhd_dbus_txdata(dhdp, p); |
|---|
| 1011 | 1005 | #else |
|---|
| 1012 | 1006 | rc = dhd_bus_txdata(dhdp->bus, p); |
|---|
| 1013 | | -#endif |
|---|
| 1007 | +#endif // endif |
|---|
| 1014 | 1008 | if (rc != BCME_OK) { |
|---|
| 1015 | 1009 | _dhd_wlfc_pullheader(ctx, p); |
|---|
| 1016 | 1010 | PKTFREE(ctx->osh, p, TRUE); |
|---|
| .. | .. |
|---|
| 1041 | 1035 | bool rc = FALSE; |
|---|
| 1042 | 1036 | |
|---|
| 1043 | 1037 | if (entry->state == WLFC_STATE_CLOSE) { |
|---|
| 1044 | | - if ((pktq_plen(&entry->psq, (prec << 1)) == 0) && |
|---|
| 1045 | | - (pktq_plen(&entry->psq, ((prec << 1) + 1)) == 0)) { |
|---|
| 1038 | + if ((pktqprec_n_pkts(&entry->psq, (prec << 1)) == 0) && |
|---|
| 1039 | + (pktqprec_n_pkts(&entry->psq, ((prec << 1) + 1)) == 0)) { |
|---|
| 1046 | 1040 | /* no packets in both 'normal' and 'suspended' queues */ |
|---|
| 1047 | 1041 | if (entry->traffic_pending_bmp & NBITVAL(prec)) { |
|---|
| 1048 | 1042 | rc = TRUE; |
|---|
| .. | .. |
|---|
| 1218 | 1212 | #ifdef PROP_TXSTATUS_DEBUG |
|---|
| 1219 | 1213 | h->items[hslot].push_time = |
|---|
| 1220 | 1214 | OSL_SYSUPTIME(); |
|---|
| 1221 | | -#endif |
|---|
| 1215 | +#endif // endif |
|---|
| 1222 | 1216 | } else { |
|---|
| 1223 | 1217 | DHD_ERROR(("%s() hanger_pushpkt() failed, rc: %d\n", |
|---|
| 1224 | 1218 | __FUNCTION__, rc)); |
|---|
| .. | .. |
|---|
| 1235 | 1229 | h->items[hslot].pkt_txstatus = 0; |
|---|
| 1236 | 1230 | h->items[hslot].state = WLFC_HANGER_ITEM_STATE_INUSE; |
|---|
| 1237 | 1231 | } |
|---|
| 1238 | | - } else if (!WLFC_GET_AFQ(dhdp->wlfc_mode)) { |
|---|
| 1239 | | - /* clear hanger state */ |
|---|
| 1240 | | - ((wlfc_hanger_t*)(ctx->hanger))->items[hslot].pkt_state = 0; |
|---|
| 1241 | | - ((wlfc_hanger_t*)(ctx->hanger))->items[hslot].pkt_txstatus = 0; |
|---|
| 1242 | 1232 | } |
|---|
| 1243 | 1233 | |
|---|
| 1244 | 1234 | if ((rc == BCME_OK) && header_needed) { |
|---|
| .. | .. |
|---|
| 1259 | 1249 | _dhd_wlfc_is_destination_open(athost_wl_status_info_t* ctx, |
|---|
| 1260 | 1250 | wlfc_mac_descriptor_t* entry, int prec) |
|---|
| 1261 | 1251 | { |
|---|
| 1252 | + wlfc_mac_descriptor_t* interfaces = ctx->destination_entries.interfaces; |
|---|
| 1253 | + |
|---|
| 1262 | 1254 | if (entry->interface_id >= WLFC_MAX_IFNUM) { |
|---|
| 1263 | 1255 | ASSERT(&ctx->destination_entries.other == entry); |
|---|
| 1264 | 1256 | return 1; |
|---|
| 1265 | 1257 | } |
|---|
| 1266 | 1258 | |
|---|
| 1267 | | - if (ctx->destination_entries.interfaces[entry->interface_id].iftype == |
|---|
| 1259 | + if (interfaces[entry->interface_id].iftype == |
|---|
| 1268 | 1260 | WLC_E_IF_ROLE_P2P_GO) { |
|---|
| 1269 | 1261 | /* - destination interface is of type p2p GO. |
|---|
| 1270 | 1262 | For a p2pGO interface, if the destination is OPEN but the interface is |
|---|
| .. | .. |
|---|
| 1279 | 1271 | } |
|---|
| 1280 | 1272 | |
|---|
| 1281 | 1273 | /* AP, p2p_go -> unicast desc entry, STA/p2p_cl -> interface desc. entry */ |
|---|
| 1282 | | - if (((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && |
|---|
| 1274 | + if ((((entry->state == WLFC_STATE_CLOSE) || |
|---|
| 1275 | + (interfaces[entry->interface_id].state == WLFC_STATE_CLOSE)) && |
|---|
| 1276 | + (entry->requested_credit == 0) && |
|---|
| 1283 | 1277 | (entry->requested_packet == 0)) || |
|---|
| 1284 | 1278 | (!(entry->ac_bitmap & (1 << prec)))) { |
|---|
| 1285 | 1279 | return 0; |
|---|
| .. | .. |
|---|
| 1357 | 1351 | entry->requested_credit--; |
|---|
| 1358 | 1352 | #ifdef PROP_TXSTATUS_DEBUG |
|---|
| 1359 | 1353 | entry->dstncredit_sent_packets++; |
|---|
| 1360 | | -#endif |
|---|
| 1354 | +#endif // endif |
|---|
| 1361 | 1355 | } else if (entry->requested_packet > 0) { |
|---|
| 1362 | 1356 | entry->requested_packet--; |
|---|
| 1363 | 1357 | DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p)); |
|---|
| .. | .. |
|---|
| 1406 | 1400 | ctx->stats.delayq_full_error++; |
|---|
| 1407 | 1401 | return BCME_ERROR; |
|---|
| 1408 | 1402 | } |
|---|
| 1409 | | - |
|---|
| 1410 | 1403 | |
|---|
| 1411 | 1404 | /* A packet has been pushed, update traffic availability bitmap, if applicable */ |
|---|
| 1412 | 1405 | _dhd_wlfc_traffic_pending_check(ctx, entry, prec); |
|---|
| .. | .. |
|---|
| 1543 | 1536 | /* Optimize flush, if pktq len = 0, just return. |
|---|
| 1544 | 1537 | * pktq len of 0 means pktq's prec q's are all empty. |
|---|
| 1545 | 1538 | */ |
|---|
| 1546 | | - if (pq->len == 0) { |
|---|
| 1539 | + if (pq->n_pkts_tot == 0) { |
|---|
| 1547 | 1540 | return; |
|---|
| 1548 | 1541 | } |
|---|
| 1549 | 1542 | |
|---|
| .. | .. |
|---|
| 1608 | 1601 | } |
|---|
| 1609 | 1602 | PKTFREE(ctx->osh, p, dir); |
|---|
| 1610 | 1603 | |
|---|
| 1611 | | - q->len--; |
|---|
| 1612 | | - pq->len--; |
|---|
| 1604 | + q->n_pkts--; |
|---|
| 1605 | + pq->n_pkts_tot--; |
|---|
| 1606 | +#ifdef WL_TXQ_STALL |
|---|
| 1607 | + q->dequeue_count++; |
|---|
| 1608 | +#endif // endif |
|---|
| 1609 | + |
|---|
| 1613 | 1610 | p = (head ? q->head : PKTLINK(prev)); |
|---|
| 1614 | 1611 | } else { |
|---|
| 1615 | 1612 | prev = p; |
|---|
| .. | .. |
|---|
| 1618 | 1615 | } |
|---|
| 1619 | 1616 | |
|---|
| 1620 | 1617 | if (q->head == NULL) { |
|---|
| 1621 | | - ASSERT(q->len == 0); |
|---|
| 1618 | + ASSERT(q->n_pkts == 0); |
|---|
| 1622 | 1619 | q->tail = NULL; |
|---|
| 1623 | 1620 | } |
|---|
| 1624 | 1621 | |
|---|
| 1625 | 1622 | } |
|---|
| 1626 | 1623 | |
|---|
| 1627 | 1624 | if (fn == NULL) |
|---|
| 1628 | | - ASSERT(pq->len == 0); |
|---|
| 1625 | + ASSERT(pq->n_pkts_tot == 0); |
|---|
| 1629 | 1626 | } /* _dhd_wlfc_pktq_flush */ |
|---|
| 1630 | | - |
|---|
| 1631 | | -#ifndef BCMDBUS |
|---|
| 1632 | 1627 | |
|---|
| 1633 | 1628 | /** !BCMDBUS specific function. Dequeues a packet from the caller supplied queue. */ |
|---|
| 1634 | 1629 | static void* |
|---|
| .. | .. |
|---|
| 1666 | 1661 | } |
|---|
| 1667 | 1662 | } |
|---|
| 1668 | 1663 | |
|---|
| 1669 | | - q->len--; |
|---|
| 1664 | + q->n_pkts--; |
|---|
| 1670 | 1665 | |
|---|
| 1671 | | - pq->len--; |
|---|
| 1666 | + pq->n_pkts_tot--; |
|---|
| 1667 | + |
|---|
| 1668 | +#ifdef WL_TXQ_STALL |
|---|
| 1669 | + q->dequeue_count++; |
|---|
| 1670 | +#endif // endif |
|---|
| 1672 | 1671 | |
|---|
| 1673 | 1672 | PKTSETLINK(p, NULL); |
|---|
| 1674 | 1673 | |
|---|
| .. | .. |
|---|
| 1707 | 1706 | } |
|---|
| 1708 | 1707 | dhd_os_sdunlock_txq(dhd); |
|---|
| 1709 | 1708 | |
|---|
| 1710 | | - |
|---|
| 1711 | 1709 | while ((pkt = head)) { |
|---|
| 1712 | 1710 | head = PKTLINK(pkt); |
|---|
| 1713 | 1711 | PKTSETLINK(pkt, NULL); |
|---|
| .. | .. |
|---|
| 1736 | 1734 | } |
|---|
| 1737 | 1735 | } /* _dhd_wlfc_cleanup_txq */ |
|---|
| 1738 | 1736 | |
|---|
| 1739 | | -#endif /* !BCMDBUS */ |
|---|
| 1740 | | - |
|---|
| 1741 | 1737 | /** called during eg detach */ |
|---|
| 1742 | 1738 | void |
|---|
| 1743 | 1739 | _dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void *arg) |
|---|
| .. | .. |
|---|
| 1755 | 1751 | /* |
|---|
| 1756 | 1752 | * flush sequence should be txq -> psq -> hanger/afq, hanger has to be last one |
|---|
| 1757 | 1753 | */ |
|---|
| 1758 | | -#ifndef BCMDBUS |
|---|
| 1759 | 1754 | /* flush bus->txq */ |
|---|
| 1760 | 1755 | _dhd_wlfc_cleanup_txq(dhd, fn, arg); |
|---|
| 1761 | | -#endif /* BCMDBUS */ |
|---|
| 1762 | 1756 | |
|---|
| 1763 | 1757 | /* flush psq, search all entries, include nodes as well as interfaces */ |
|---|
| 1764 | 1758 | total_entries = sizeof(wlfc->destination_entries)/sizeof(wlfc_mac_descriptor_t); |
|---|
| .. | .. |
|---|
| 1767 | 1761 | for (i = 0; i < total_entries; i++) { |
|---|
| 1768 | 1762 | if (table[i].occupied) { |
|---|
| 1769 | 1763 | /* release packets held in PSQ (both delayed and suppressed) */ |
|---|
| 1770 | | - if (table[i].psq.len) { |
|---|
| 1764 | + if (table[i].psq.n_pkts_tot) { |
|---|
| 1771 | 1765 | WLFC_DBGMESG(("%s(): PSQ[%d].len = %d\n", |
|---|
| 1772 | | - __FUNCTION__, i, table[i].psq.len)); |
|---|
| 1766 | + __FUNCTION__, i, table[i].psq.n_pkts_tot)); |
|---|
| 1773 | 1767 | _dhd_wlfc_pktq_flush(wlfc, &table[i].psq, TRUE, |
|---|
| 1774 | 1768 | fn, arg, Q_TYPE_PSQ); |
|---|
| 1775 | 1769 | } |
|---|
| 1776 | 1770 | |
|---|
| 1777 | 1771 | /* free packets held in AFQ */ |
|---|
| 1778 | | - if (WLFC_GET_AFQ(dhd->wlfc_mode) && (table[i].afq.len)) { |
|---|
| 1772 | + if (WLFC_GET_AFQ(dhd->wlfc_mode) && (table[i].afq.n_pkts_tot)) { |
|---|
| 1779 | 1773 | _dhd_wlfc_pktq_flush(wlfc, &table[i].afq, TRUE, |
|---|
| 1780 | 1774 | fn, arg, Q_TYPE_AFQ); |
|---|
| 1781 | 1775 | } |
|---|
| .. | .. |
|---|
| 1819 | 1813 | { |
|---|
| 1820 | 1814 | int rc = BCME_OK; |
|---|
| 1821 | 1815 | |
|---|
| 1822 | | - |
|---|
| 1823 | 1816 | if ((action == eWLFC_MAC_ENTRY_ACTION_ADD) || (action == eWLFC_MAC_ENTRY_ACTION_UPDATE)) { |
|---|
| 1824 | 1817 | entry->occupied = 1; |
|---|
| 1825 | 1818 | entry->state = WLFC_STATE_OPEN; |
|---|
| .. | .. |
|---|
| 1843 | 1836 | dhd_pub_t *dhdp = (dhd_pub_t *)(ctx->dhdp); |
|---|
| 1844 | 1837 | |
|---|
| 1845 | 1838 | pktq_init(&entry->psq, WLFC_PSQ_PREC_COUNT, WLFC_PSQ_LEN); |
|---|
| 1839 | + _dhd_wlfc_flow_control_check(ctx, &entry->psq, ifid); |
|---|
| 1846 | 1840 | |
|---|
| 1847 | 1841 | if (WLFC_GET_AFQ(dhdp->wlfc_mode)) { |
|---|
| 1848 | 1842 | pktq_init(&entry->afq, WLFC_AFQ_PREC_COUNT, WLFC_PSQ_LEN); |
|---|
| .. | .. |
|---|
| 1898 | 1892 | } |
|---|
| 1899 | 1893 | return rc; |
|---|
| 1900 | 1894 | } /* _dhd_wlfc_mac_entry_update */ |
|---|
| 1901 | | - |
|---|
| 1902 | 1895 | |
|---|
| 1903 | 1896 | #ifdef LIMIT_BORROW |
|---|
| 1904 | 1897 | |
|---|
| .. | .. |
|---|
| 2189 | 2182 | } |
|---|
| 2190 | 2183 | } |
|---|
| 2191 | 2184 | |
|---|
| 2192 | | - q->len--; |
|---|
| 2193 | | - pq->len--; |
|---|
| 2185 | + q->n_pkts--; |
|---|
| 2186 | + pq->n_pkts_tot--; |
|---|
| 2187 | + |
|---|
| 2188 | +#ifdef WL_TXQ_STALL |
|---|
| 2189 | + q->dequeue_count++; |
|---|
| 2190 | +#endif // endif |
|---|
| 2191 | + |
|---|
| 2194 | 2192 | ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec]--; |
|---|
| 2195 | 2193 | ctx->pkt_cnt_per_ac[prec]--; |
|---|
| 2196 | 2194 | |
|---|
| .. | .. |
|---|
| 2232 | 2230 | if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) { |
|---|
| 2233 | 2231 | memcpy(&seq, pkt_info + WLFC_CTL_VALUE_LEN_TXSTATUS, WLFC_CTL_VALUE_LEN_SEQ); |
|---|
| 2234 | 2232 | seq = ltoh16(seq); |
|---|
| 2235 | | - seq_fromfw = WL_SEQ_GET_FROMFW(seq); |
|---|
| 2233 | + seq_fromfw = GET_WL_HAS_ASSIGNED_SEQ(seq); |
|---|
| 2236 | 2234 | seq_num = WL_SEQ_GET_NUM(seq); |
|---|
| 2237 | 2235 | } |
|---|
| 2238 | 2236 | |
|---|
| .. | .. |
|---|
| 2250 | 2248 | remove_from_hanger = 0; |
|---|
| 2251 | 2249 | } else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { |
|---|
| 2252 | 2250 | wlfc->stats.wlc_tossed_pkts += len; |
|---|
| 2253 | | - } |
|---|
| 2254 | | - |
|---|
| 2255 | | - else if (status_flag == WLFC_CTL_PKTFLAG_SUPPRESS_ACKED) { |
|---|
| 2251 | + } else if (status_flag == WLFC_CTL_PKTFLAG_SUPPRESS_ACKED) { |
|---|
| 2256 | 2252 | wlfc->stats.pkt_freed += len; |
|---|
| 2253 | + } else if (status_flag == WLFC_CTL_PKTFLAG_EXPIRED) { |
|---|
| 2254 | + wlfc->stats.pkt_exptime += len; |
|---|
| 2255 | + } else if (status_flag == WLFC_CTL_PKTFLAG_DROPPED) { |
|---|
| 2256 | + wlfc->stats.pkt_dropped += len; |
|---|
| 2257 | 2257 | } |
|---|
| 2258 | 2258 | |
|---|
| 2259 | 2259 | if (dhd->proptxstatus_txstatus_ignore) { |
|---|
| .. | .. |
|---|
| 2326 | 2326 | uint32 delta; |
|---|
| 2327 | 2327 | old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[hslot].push_time; |
|---|
| 2328 | 2328 | |
|---|
| 2329 | | - |
|---|
| 2330 | 2329 | wlfc->stats.latency_sample_count++; |
|---|
| 2331 | 2330 | if (new_t > old_t) |
|---|
| 2332 | 2331 | delta = new_t - old_t; |
|---|
| .. | .. |
|---|
| 2357 | 2356 | } |
|---|
| 2358 | 2357 | #ifdef PROP_TXSTATUS_DEBUG |
|---|
| 2359 | 2358 | entry->dstncredit_acks++; |
|---|
| 2360 | | -#endif |
|---|
| 2359 | +#endif // endif |
|---|
| 2361 | 2360 | } |
|---|
| 2362 | 2361 | |
|---|
| 2363 | 2362 | if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || |
|---|
| .. | .. |
|---|
| 2366 | 2365 | WL_TXSTATUS_SET_GENERATION(DHD_PKTTAG_H2DTAG(PKTTAG(pktbuf)), gen); |
|---|
| 2367 | 2366 | |
|---|
| 2368 | 2367 | if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) { |
|---|
| 2369 | | - WL_SEQ_SET_FROMDRV(DHD_PKTTAG_H2DSEQ(PKTTAG(pktbuf)), seq_fromfw); |
|---|
| 2368 | + WL_SEQ_SET_REUSE(DHD_PKTTAG_H2DSEQ(PKTTAG(pktbuf)), seq_fromfw); |
|---|
| 2370 | 2369 | WL_SEQ_SET_NUM(DHD_PKTTAG_H2DSEQ(PKTTAG(pktbuf)), seq_num); |
|---|
| 2371 | 2370 | } |
|---|
| 2372 | 2371 | |
|---|
| .. | .. |
|---|
| 2438 | 2437 | for (i = 0; i < WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK; i++) { |
|---|
| 2439 | 2438 | #ifdef PROP_TXSTATUS_DEBUG |
|---|
| 2440 | 2439 | wlfc->stats.fifo_credits_back[i] += credits[i]; |
|---|
| 2441 | | -#endif |
|---|
| 2440 | +#endif // endif |
|---|
| 2442 | 2441 | |
|---|
| 2443 | 2442 | /* update FIFO credits */ |
|---|
| 2444 | 2443 | if (dhd->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT) |
|---|
| .. | .. |
|---|
| 2480 | 2479 | return BCME_OK; |
|---|
| 2481 | 2480 | } /* _dhd_wlfc_fifocreditback_indicate */ |
|---|
| 2482 | 2481 | |
|---|
| 2483 | | -#ifndef BCMDBUS |
|---|
| 2484 | | - |
|---|
| 2485 | 2482 | /** !BCMDBUS specific function */ |
|---|
| 2486 | 2483 | static void |
|---|
| 2487 | 2484 | _dhd_wlfc_suppress_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg) |
|---|
| .. | .. |
|---|
| 2516 | 2513 | PKTSETLINK(pkt, NULL); |
|---|
| 2517 | 2514 | |
|---|
| 2518 | 2515 | entry = _dhd_wlfc_find_table_entry(wlfc, pkt); |
|---|
| 2519 | | - if (entry) { |
|---|
| 2520 | | - if (entry->onbus_pkts_count > 0) |
|---|
| 2521 | | - entry->onbus_pkts_count--; |
|---|
| 2522 | | - if (entry->suppressed && |
|---|
| 2523 | | - (!entry->onbus_pkts_count) && |
|---|
| 2524 | | - (!entry->suppr_transit_count)) |
|---|
| 2525 | | - entry->suppressed = FALSE; |
|---|
| 2516 | + if (!entry) { |
|---|
| 2517 | + PKTFREE(dhd->osh, pkt, TRUE); |
|---|
| 2518 | + continue; |
|---|
| 2526 | 2519 | } |
|---|
| 2527 | | - |
|---|
| 2520 | + if (entry->onbus_pkts_count > 0) { |
|---|
| 2521 | + entry->onbus_pkts_count--; |
|---|
| 2522 | + } |
|---|
| 2523 | + if (entry->suppressed && |
|---|
| 2524 | + (!entry->onbus_pkts_count) && |
|---|
| 2525 | + (!entry->suppr_transit_count)) { |
|---|
| 2526 | + entry->suppressed = FALSE; |
|---|
| 2527 | + } |
|---|
| 2528 | 2528 | /* fake a suppression txstatus */ |
|---|
| 2529 | 2529 | htod = DHD_PKTTAG_H2DTAG(PKTTAG(pkt)); |
|---|
| 2530 | 2530 | WL_TXSTATUS_SET_FLAGS(htod, WLFC_CTL_PKTFLAG_WLSUPPRESS); |
|---|
| .. | .. |
|---|
| 2533 | 2533 | memcpy(results, &htod, WLFC_CTL_VALUE_LEN_TXSTATUS); |
|---|
| 2534 | 2534 | if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) { |
|---|
| 2535 | 2535 | htodseq = DHD_PKTTAG_H2DSEQ(PKTTAG(pkt)); |
|---|
| 2536 | | - if (WL_SEQ_GET_FROMDRV(htodseq)) { |
|---|
| 2537 | | - WL_SEQ_SET_FROMFW(htodseq, 1); |
|---|
| 2538 | | - WL_SEQ_SET_FROMDRV(htodseq, 0); |
|---|
| 2536 | + if (IS_WL_TO_REUSE_SEQ(htodseq)) { |
|---|
| 2537 | + SET_WL_HAS_ASSIGNED_SEQ(htodseq); |
|---|
| 2538 | + RESET_WL_TO_REUSE_SEQ(htodseq); |
|---|
| 2539 | 2539 | } |
|---|
| 2540 | 2540 | htodseq = htol16(htodseq); |
|---|
| 2541 | 2541 | memcpy(results + WLFC_CTL_VALUE_LEN_TXSTATUS, &htodseq, |
|---|
| .. | .. |
|---|
| 2557 | 2557 | _dhd_wlfc_fifocreditback_indicate(dhd, credits); |
|---|
| 2558 | 2558 | } |
|---|
| 2559 | 2559 | } /* _dhd_wlfc_suppress_txq */ |
|---|
| 2560 | | - |
|---|
| 2561 | | -#endif /* !BCMDBUS */ |
|---|
| 2562 | 2560 | |
|---|
| 2563 | 2561 | static int |
|---|
| 2564 | 2562 | _dhd_wlfc_dbg_senum_check(dhd_pub_t *dhd, uint8 *value) |
|---|
| .. | .. |
|---|
| 2643 | 2641 | uint8 ifid; |
|---|
| 2644 | 2642 | uint8* ea; |
|---|
| 2645 | 2643 | |
|---|
| 2646 | | - WLFC_DBGMESG(("%s(), mac [%02x:%02x:%02x:%02x:%02x:%02x],%s,idx:%d,id:0x%02x\n", |
|---|
| 2647 | | - __FUNCTION__, value[2], value[3], value[4], value[5], value[6], value[7], |
|---|
| 2644 | + WLFC_DBGMESG(("%s(), mac ["MACDBG"],%s,idx:%d,id:0x%02x\n", |
|---|
| 2645 | + __FUNCTION__, MAC2STRDBG(&value[2]), |
|---|
| 2648 | 2646 | ((type == WLFC_CTL_TYPE_MACDESC_ADD) ? "ADD":"DEL"), |
|---|
| 2649 | 2647 | WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]), value[0])); |
|---|
| 2650 | 2648 | |
|---|
| .. | .. |
|---|
| 2828 | 2826 | _dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len) |
|---|
| 2829 | 2827 | { |
|---|
| 2830 | 2828 | if (info_len) { |
|---|
| 2831 | | - if (info_buf) { |
|---|
| 2829 | + /* Check copy length to avoid buffer overrun. In case of length exceeding |
|---|
| 2830 | + * WLHOST_REORDERDATA_TOTLEN, return failure instead sending incomplete result |
|---|
| 2831 | + * of length WLHOST_REORDERDATA_TOTLEN |
|---|
| 2832 | + */ |
|---|
| 2833 | + if ((info_buf) && (len <= WLHOST_REORDERDATA_TOTLEN)) { |
|---|
| 2832 | 2834 | bcopy(val, info_buf, len); |
|---|
| 2833 | 2835 | *info_len = len; |
|---|
| 2834 | 2836 | } else { |
|---|
| .. | .. |
|---|
| 2923 | 2925 | wlfc->allow_credit_borrow = 0; |
|---|
| 2924 | 2926 | wlfc->single_ac = 0; |
|---|
| 2925 | 2927 | wlfc->single_ac_timestamp = 0; |
|---|
| 2926 | | - |
|---|
| 2927 | 2928 | |
|---|
| 2928 | 2929 | exit: |
|---|
| 2929 | 2930 | dhd_os_wlfc_unblock(dhd); |
|---|
| .. | .. |
|---|
| 3082 | 3083 | _dhd_wlfc_interface_update(dhd, value, type); |
|---|
| 3083 | 3084 | } |
|---|
| 3084 | 3085 | |
|---|
| 3085 | | -#ifndef BCMDBUS |
|---|
| 3086 | 3086 | if (entry && WLFC_GET_REORDERSUPP(dhd->wlfc_mode)) { |
|---|
| 3087 | 3087 | /* suppress all packets for this mac entry from bus->txq */ |
|---|
| 3088 | 3088 | _dhd_wlfc_suppress_txq(dhd, _dhd_wlfc_entrypkt_fn, entry); |
|---|
| 3089 | 3089 | } |
|---|
| 3090 | | -#endif /* !BCMDBUS */ |
|---|
| 3091 | 3090 | } /* while */ |
|---|
| 3092 | 3091 | |
|---|
| 3093 | 3092 | if (remainder != 0 && wlfc) { |
|---|
| .. | .. |
|---|
| 3101 | 3100 | |
|---|
| 3102 | 3101 | dhd_os_wlfc_unblock(dhd); |
|---|
| 3103 | 3102 | return BCME_OK; |
|---|
| 3104 | | -} /* dhd_wlfc_parse_header_info */ |
|---|
| 3103 | +} |
|---|
| 3105 | 3104 | |
|---|
| 3106 | 3105 | KERNEL_THREAD_RETURN_TYPE |
|---|
| 3107 | 3106 | dhd_wlfc_transfer_packets(void *data) |
|---|
| .. | .. |
|---|
| 3112 | 3111 | athost_wl_status_info_t* ctx; |
|---|
| 3113 | 3112 | int bus_retry_count = 0; |
|---|
| 3114 | 3113 | int pkt_send = 0; |
|---|
| 3114 | + int pkt_send_per_ac = 0; |
|---|
| 3115 | 3115 | |
|---|
| 3116 | 3116 | uint8 tx_map = 0; /* packets (send + in queue), Bitmask for 4 ACs + BC/MC */ |
|---|
| 3117 | 3117 | uint8 rx_map = 0; /* received packets, Bitmask for 4 ACs + BC/MC */ |
|---|
| .. | .. |
|---|
| 3179 | 3179 | |
|---|
| 3180 | 3180 | tx_map |= (1 << ac); |
|---|
| 3181 | 3181 | single_ac = ac + 1; |
|---|
| 3182 | | - while (FALSE == dhdp->proptxstatus_txoff) { |
|---|
| 3182 | + pkt_send_per_ac = 0; |
|---|
| 3183 | + while ((FALSE == dhdp->proptxstatus_txoff) && |
|---|
| 3184 | + (pkt_send_per_ac < WLFC_PACKET_BOUND)) { |
|---|
| 3183 | 3185 | /* packets from delayQ with less priority are fresh and |
|---|
| 3184 | 3186 | * they'd need header and have no MAC entry |
|---|
| 3185 | 3187 | */ |
|---|
| .. | .. |
|---|
| 3199 | 3201 | no_credit = FALSE; |
|---|
| 3200 | 3202 | } |
|---|
| 3201 | 3203 | } |
|---|
| 3202 | | -#endif |
|---|
| 3204 | +#endif // endif |
|---|
| 3203 | 3205 | commit_info.needs_hdr = 1; |
|---|
| 3204 | 3206 | commit_info.mac_entry = NULL; |
|---|
| 3205 | 3207 | commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, |
|---|
| .. | .. |
|---|
| 3215 | 3217 | if (lender != -1 && dhdp->wlfc_borrow_allowed) { |
|---|
| 3216 | 3218 | _dhd_wlfc_return_credit(ctx, lender, ac); |
|---|
| 3217 | 3219 | } |
|---|
| 3218 | | -#endif |
|---|
| 3220 | +#endif // endif |
|---|
| 3219 | 3221 | break; |
|---|
| 3220 | 3222 | } |
|---|
| 3221 | 3223 | |
|---|
| .. | .. |
|---|
| 3229 | 3231 | /* Bus commits may fail (e.g. flow control); abort after retries */ |
|---|
| 3230 | 3232 | if (rc == BCME_OK) { |
|---|
| 3231 | 3233 | pkt_send++; |
|---|
| 3234 | + pkt_send_per_ac++; |
|---|
| 3232 | 3235 | if (commit_info.ac_fifo_credit_spent && (lender == -1)) { |
|---|
| 3233 | 3236 | ctx->FIFO_credit[ac]--; |
|---|
| 3234 | 3237 | } |
|---|
| .. | .. |
|---|
| 3237 | 3240 | dhdp->wlfc_borrow_allowed) { |
|---|
| 3238 | 3241 | _dhd_wlfc_return_credit(ctx, lender, ac); |
|---|
| 3239 | 3242 | } |
|---|
| 3240 | | -#endif |
|---|
| 3243 | +#endif // endif |
|---|
| 3241 | 3244 | } else { |
|---|
| 3242 | 3245 | #ifdef LIMIT_BORROW |
|---|
| 3243 | 3246 | if (lender != -1 && dhdp->wlfc_borrow_allowed) { |
|---|
| 3244 | 3247 | _dhd_wlfc_return_credit(ctx, lender, ac); |
|---|
| 3245 | 3248 | } |
|---|
| 3246 | | -#endif |
|---|
| 3249 | +#endif // endif |
|---|
| 3247 | 3250 | bus_retry_count++; |
|---|
| 3248 | 3251 | if (bus_retry_count >= BUS_RETRIES) { |
|---|
| 3249 | 3252 | DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc)); |
|---|
| .. | .. |
|---|
| 3316 | 3319 | } |
|---|
| 3317 | 3320 | else |
|---|
| 3318 | 3321 | break; |
|---|
| 3319 | | -#endif |
|---|
| 3322 | +#endif // endif |
|---|
| 3320 | 3323 | commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, |
|---|
| 3321 | 3324 | &(commit_info.ac_fifo_credit_spent), |
|---|
| 3322 | 3325 | &(commit_info.needs_hdr), |
|---|
| .. | .. |
|---|
| 3326 | 3329 | /* before borrow only one ac exists and now this only ac is empty */ |
|---|
| 3327 | 3330 | #ifdef LIMIT_BORROW |
|---|
| 3328 | 3331 | _dhd_wlfc_return_credit(ctx, lender, ac); |
|---|
| 3329 | | -#endif |
|---|
| 3332 | +#endif // endif |
|---|
| 3330 | 3333 | break; |
|---|
| 3331 | 3334 | } |
|---|
| 3332 | 3335 | |
|---|
| .. | .. |
|---|
| 3342 | 3345 | if (commit_info.ac_fifo_credit_spent) { |
|---|
| 3343 | 3346 | #ifndef LIMIT_BORROW |
|---|
| 3344 | 3347 | ctx->FIFO_credit[ac]--; |
|---|
| 3345 | | -#endif |
|---|
| 3348 | +#endif // endif |
|---|
| 3346 | 3349 | } else { |
|---|
| 3347 | 3350 | #ifdef LIMIT_BORROW |
|---|
| 3348 | 3351 | _dhd_wlfc_return_credit(ctx, lender, ac); |
|---|
| 3349 | | -#endif |
|---|
| 3352 | +#endif // endif |
|---|
| 3350 | 3353 | } |
|---|
| 3351 | 3354 | } else { |
|---|
| 3352 | 3355 | #ifdef LIMIT_BORROW |
|---|
| 3353 | 3356 | _dhd_wlfc_return_credit(ctx, lender, ac); |
|---|
| 3354 | | -#endif |
|---|
| 3357 | +#endif // endif |
|---|
| 3355 | 3358 | bus_retry_count++; |
|---|
| 3356 | 3359 | if (bus_retry_count >= BUS_RETRIES) { |
|---|
| 3357 | 3360 | DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc)); |
|---|
| .. | .. |
|---|
| 3414 | 3417 | } |
|---|
| 3415 | 3418 | |
|---|
| 3416 | 3419 | ctx = (athost_wl_status_info_t*)dhdp->wlfc_state; |
|---|
| 3417 | | - |
|---|
| 3418 | | -#ifdef BCMDBUS |
|---|
| 3419 | | - if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) { |
|---|
| 3420 | | - if (pktbuf) { |
|---|
| 3421 | | - PKTFREE(ctx->osh, pktbuf, TRUE); |
|---|
| 3422 | | - rc = BCME_OK; |
|---|
| 3423 | | - } |
|---|
| 3424 | | - goto exit; |
|---|
| 3425 | | - } |
|---|
| 3426 | | -#endif |
|---|
| 3427 | 3420 | |
|---|
| 3428 | 3421 | if (dhdp->proptxstatus_module_ignore) { |
|---|
| 3429 | 3422 | if (pktbuf) { |
|---|
| .. | .. |
|---|
| 3503 | 3496 | if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { |
|---|
| 3504 | 3497 | #ifdef PROP_TXSTATUS_DEBUG |
|---|
| 3505 | 3498 | wlfc->stats.signal_only_pkts_freed++; |
|---|
| 3506 | | -#endif |
|---|
| 3499 | +#endif // endif |
|---|
| 3507 | 3500 | /* is this a signal-only packet? */ |
|---|
| 3508 | 3501 | _dhd_wlfc_pullheader(wlfc, txp); |
|---|
| 3509 | 3502 | PKTFREE(wlfc->osh, txp, TRUE); |
|---|
| .. | .. |
|---|
| 3546 | 3539 | } |
|---|
| 3547 | 3540 | } |
|---|
| 3548 | 3541 | |
|---|
| 3549 | | - ASSERT(entry->onbus_pkts_count > 0); |
|---|
| 3550 | 3542 | if (entry->onbus_pkts_count > 0) |
|---|
| 3551 | 3543 | entry->onbus_pkts_count--; |
|---|
| 3552 | 3544 | if (entry->suppressed && |
|---|
| .. | .. |
|---|
| 3585 | 3577 | WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | |
|---|
| 3586 | 3578 | WLFC_FLAGS_HOST_RXRERODER_ACTIVE; |
|---|
| 3587 | 3579 | |
|---|
| 3588 | | - |
|---|
| 3589 | 3580 | /* |
|---|
| 3590 | 3581 | try to enable/disable signaling by sending "tlv" iovar. if that fails, |
|---|
| 3591 | 3582 | fallback to no flow control? Print a message for now. |
|---|
| .. | .. |
|---|
| 3610 | 3601 | DHD_INFO(("%s: query wlfc_mode succeed, fw_caps=0x%x\n", __FUNCTION__, fw_caps)); |
|---|
| 3611 | 3602 | |
|---|
| 3612 | 3603 | if (WLFC_IS_OLD_DEF(fw_caps)) { |
|---|
| 3613 | | -#ifdef BCMDBUS |
|---|
| 3614 | | - mode = WLFC_MODE_HANGER; |
|---|
| 3615 | | -#else |
|---|
| 3616 | 3604 | /* enable proptxtstatus v2 by default */ |
|---|
| 3617 | 3605 | mode = WLFC_MODE_AFQ; |
|---|
| 3618 | | -#endif /* BCMDBUS */ |
|---|
| 3619 | 3606 | } else { |
|---|
| 3620 | 3607 | WLFC_SET_AFQ(mode, WLFC_GET_AFQ(fw_caps)); |
|---|
| 3621 | | -#ifdef BCMDBUS |
|---|
| 3622 | | - WLFC_SET_AFQ(mode, 0); |
|---|
| 3623 | | -#endif /* BCMDBUS */ |
|---|
| 3624 | | - WLFC_SET_REUSESEQ(mode, WLFC_GET_REUSESEQ(fw_caps)); |
|---|
| 3625 | 3608 | WLFC_SET_REORDERSUPP(mode, WLFC_GET_REORDERSUPP(fw_caps)); |
|---|
| 3626 | 3609 | } |
|---|
| 3627 | 3610 | ret = dhd_wl_ioctl_set_intiovar(dhd, "wlfc_mode", mode, WLC_SET_VAR, TRUE, 0); |
|---|
| .. | .. |
|---|
| 3641 | 3624 | DHD_INFO(("dhd_wlfc_init(): wlfc_mode=0x%x, ret=%d\n", dhd->wlfc_mode, ret)); |
|---|
| 3642 | 3625 | #ifdef LIMIT_BORROW |
|---|
| 3643 | 3626 | dhd->wlfc_borrow_allowed = TRUE; |
|---|
| 3644 | | -#endif |
|---|
| 3627 | +#endif // endif |
|---|
| 3645 | 3628 | dhd_os_wlfc_unblock(dhd); |
|---|
| 3646 | 3629 | |
|---|
| 3647 | 3630 | if (dhd->plat_init) |
|---|
| .. | .. |
|---|
| 3701 | 3684 | return WLFC_UNSUPPORTED; |
|---|
| 3702 | 3685 | } |
|---|
| 3703 | 3686 | |
|---|
| 3704 | | -#ifndef BCMDBUS |
|---|
| 3705 | 3687 | _dhd_wlfc_cleanup_txq(dhd, fn, arg); |
|---|
| 3706 | | -#endif /* !BCMDBUS */ |
|---|
| 3707 | 3688 | |
|---|
| 3708 | 3689 | dhd_os_wlfc_unblock(dhd); |
|---|
| 3709 | 3690 | |
|---|
| .. | .. |
|---|
| 3794 | 3775 | _dhd_wlfc_hanger_delete(dhd, h); |
|---|
| 3795 | 3776 | } |
|---|
| 3796 | 3777 | |
|---|
| 3797 | | - |
|---|
| 3798 | 3778 | /* free top structure */ |
|---|
| 3799 | 3779 | DHD_OS_PREFREE(dhd, dhd->wlfc_state, |
|---|
| 3800 | 3780 | sizeof(athost_wl_status_info_t)); |
|---|
| .. | .. |
|---|
| 3862 | 3842 | #ifdef LIMIT_BORROW |
|---|
| 3863 | 3843 | int dhd_wlfc_disable_credit_borrow_event(dhd_pub_t *dhdp, uint8* event_data) |
|---|
| 3864 | 3844 | { |
|---|
| 3865 | | - int rc; |
|---|
| 3866 | | - if (dhdp == NULL) { |
|---|
| 3845 | + if (dhdp == NULL || event_data == NULL) { |
|---|
| 3867 | 3846 | DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__)); |
|---|
| 3868 | 3847 | return BCME_BADARG; |
|---|
| 3869 | 3848 | } |
|---|
| .. | .. |
|---|
| 3871 | 3850 | dhdp->wlfc_borrow_allowed = (bool)(*(uint32 *)event_data); |
|---|
| 3872 | 3851 | dhd_os_wlfc_unblock(dhdp); |
|---|
| 3873 | 3852 | |
|---|
| 3874 | | - return rc; |
|---|
| 3853 | + return BCME_OK; |
|---|
| 3875 | 3854 | } |
|---|
| 3876 | 3855 | #endif /* LIMIT_BORROW */ |
|---|
| 3877 | 3856 | |
|---|
| .. | .. |
|---|
| 3987 | 3966 | |
|---|
| 3988 | 3967 | ea = interfaces[i].ea; |
|---|
| 3989 | 3968 | bcm_bprintf(strbuf, "INTERFACE[%d].ea = " |
|---|
| 3990 | | - "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d, type: %s " |
|---|
| 3969 | + "["MACDBG"], if:%d, type: %s " |
|---|
| 3991 | 3970 | "netif_flow_control:%s\n", i, |
|---|
| 3992 | | - ea[0], ea[1], ea[2], ea[3], ea[4], ea[5], |
|---|
| 3993 | | - interfaces[i].interface_id, |
|---|
| 3971 | + MAC2STRDBG(ea), interfaces[i].interface_id, |
|---|
| 3994 | 3972 | iftype_desc, ((wlfc->hostif_flow_state[i] == OFF) |
|---|
| 3995 | 3973 | ? " OFF":" ON")); |
|---|
| 3996 | 3974 | |
|---|
| .. | .. |
|---|
| 3998 | 3976 | "(trans,supp_trans,onbus)" |
|---|
| 3999 | 3977 | "= (%d,%s,%d),(%d,%d,%d)\n", |
|---|
| 4000 | 3978 | i, |
|---|
| 4001 | | - interfaces[i].psq.len, |
|---|
| 3979 | + interfaces[i].psq.n_pkts_tot, |
|---|
| 4002 | 3980 | ((interfaces[i].state == |
|---|
| 4003 | 3981 | WLFC_STATE_OPEN) ? "OPEN":"CLOSE"), |
|---|
| 4004 | 3982 | interfaces[i].requested_credit, |
|---|
| .. | .. |
|---|
| 4011 | 3989 | "(delay3,sup3,afq3),(delay4,sup4,afq4) = (%d,%d,%d)," |
|---|
| 4012 | 3990 | "(%d,%d,%d),(%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n", |
|---|
| 4013 | 3991 | i, |
|---|
| 4014 | | - interfaces[i].psq.q[0].len, |
|---|
| 4015 | | - interfaces[i].psq.q[1].len, |
|---|
| 4016 | | - interfaces[i].afq.q[0].len, |
|---|
| 4017 | | - interfaces[i].psq.q[2].len, |
|---|
| 4018 | | - interfaces[i].psq.q[3].len, |
|---|
| 4019 | | - interfaces[i].afq.q[1].len, |
|---|
| 4020 | | - interfaces[i].psq.q[4].len, |
|---|
| 4021 | | - interfaces[i].psq.q[5].len, |
|---|
| 4022 | | - interfaces[i].afq.q[2].len, |
|---|
| 4023 | | - interfaces[i].psq.q[6].len, |
|---|
| 4024 | | - interfaces[i].psq.q[7].len, |
|---|
| 4025 | | - interfaces[i].afq.q[3].len, |
|---|
| 4026 | | - interfaces[i].psq.q[8].len, |
|---|
| 4027 | | - interfaces[i].psq.q[9].len, |
|---|
| 4028 | | - interfaces[i].afq.q[4].len); |
|---|
| 3992 | + interfaces[i].psq.q[0].n_pkts, |
|---|
| 3993 | + interfaces[i].psq.q[1].n_pkts, |
|---|
| 3994 | + interfaces[i].afq.q[0].n_pkts, |
|---|
| 3995 | + interfaces[i].psq.q[2].n_pkts, |
|---|
| 3996 | + interfaces[i].psq.q[3].n_pkts, |
|---|
| 3997 | + interfaces[i].afq.q[1].n_pkts, |
|---|
| 3998 | + interfaces[i].psq.q[4].n_pkts, |
|---|
| 3999 | + interfaces[i].psq.q[5].n_pkts, |
|---|
| 4000 | + interfaces[i].afq.q[2].n_pkts, |
|---|
| 4001 | + interfaces[i].psq.q[6].n_pkts, |
|---|
| 4002 | + interfaces[i].psq.q[7].n_pkts, |
|---|
| 4003 | + interfaces[i].afq.q[3].n_pkts, |
|---|
| 4004 | + interfaces[i].psq.q[8].n_pkts, |
|---|
| 4005 | + interfaces[i].psq.q[9].n_pkts, |
|---|
| 4006 | + interfaces[i].afq.q[4].n_pkts); |
|---|
| 4029 | 4007 | } |
|---|
| 4030 | 4008 | } |
|---|
| 4031 | 4009 | |
|---|
| .. | .. |
|---|
| 4034 | 4012 | if (mac_table[i].occupied) { |
|---|
| 4035 | 4013 | ea = mac_table[i].ea; |
|---|
| 4036 | 4014 | bcm_bprintf(strbuf, "MAC_table[%d].ea = " |
|---|
| 4037 | | - "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d \n", i, |
|---|
| 4038 | | - ea[0], ea[1], ea[2], ea[3], ea[4], ea[5], |
|---|
| 4039 | | - mac_table[i].interface_id); |
|---|
| 4015 | + "["MACDBG"], if:%d \n", i, |
|---|
| 4016 | + MAC2STRDBG(ea), mac_table[i].interface_id); |
|---|
| 4040 | 4017 | |
|---|
| 4041 | 4018 | bcm_bprintf(strbuf, "MAC_table[%d].PSQ(len,state,credit)," |
|---|
| 4042 | 4019 | "(trans,supp_trans,onbus)" |
|---|
| 4043 | 4020 | "= (%d,%s,%d),(%d,%d,%d)\n", |
|---|
| 4044 | 4021 | i, |
|---|
| 4045 | | - mac_table[i].psq.len, |
|---|
| 4022 | + mac_table[i].psq.n_pkts_tot, |
|---|
| 4046 | 4023 | ((mac_table[i].state == |
|---|
| 4047 | 4024 | WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), |
|---|
| 4048 | 4025 | mac_table[i].requested_credit, |
|---|
| .. | .. |
|---|
| 4052 | 4029 | #ifdef PROP_TXSTATUS_DEBUG |
|---|
| 4053 | 4030 | bcm_bprintf(strbuf, "MAC_table[%d]: (opened, closed) = (%d, %d)\n", |
|---|
| 4054 | 4031 | i, mac_table[i].opened_ct, mac_table[i].closed_ct); |
|---|
| 4055 | | -#endif |
|---|
| 4032 | +#endif // endif |
|---|
| 4056 | 4033 | bcm_bprintf(strbuf, "MAC_table[%d].PSQ" |
|---|
| 4057 | 4034 | "(delay0,sup0,afq0),(delay1,sup1,afq1),(delay2,sup2,afq2)," |
|---|
| 4058 | 4035 | "(delay3,sup3,afq3),(delay4,sup4,afq4) =(%d,%d,%d)," |
|---|
| 4059 | 4036 | "(%d,%d,%d),(%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n", |
|---|
| 4060 | 4037 | i, |
|---|
| 4061 | | - mac_table[i].psq.q[0].len, |
|---|
| 4062 | | - mac_table[i].psq.q[1].len, |
|---|
| 4063 | | - mac_table[i].afq.q[0].len, |
|---|
| 4064 | | - mac_table[i].psq.q[2].len, |
|---|
| 4065 | | - mac_table[i].psq.q[3].len, |
|---|
| 4066 | | - mac_table[i].afq.q[1].len, |
|---|
| 4067 | | - mac_table[i].psq.q[4].len, |
|---|
| 4068 | | - mac_table[i].psq.q[5].len, |
|---|
| 4069 | | - mac_table[i].afq.q[2].len, |
|---|
| 4070 | | - mac_table[i].psq.q[6].len, |
|---|
| 4071 | | - mac_table[i].psq.q[7].len, |
|---|
| 4072 | | - mac_table[i].afq.q[3].len, |
|---|
| 4073 | | - mac_table[i].psq.q[8].len, |
|---|
| 4074 | | - mac_table[i].psq.q[9].len, |
|---|
| 4075 | | - mac_table[i].afq.q[4].len); |
|---|
| 4038 | + mac_table[i].psq.q[0].n_pkts, |
|---|
| 4039 | + mac_table[i].psq.q[1].n_pkts, |
|---|
| 4040 | + mac_table[i].afq.q[0].n_pkts, |
|---|
| 4041 | + mac_table[i].psq.q[2].n_pkts, |
|---|
| 4042 | + mac_table[i].psq.q[3].n_pkts, |
|---|
| 4043 | + mac_table[i].afq.q[1].n_pkts, |
|---|
| 4044 | + mac_table[i].psq.q[4].n_pkts, |
|---|
| 4045 | + mac_table[i].psq.q[5].n_pkts, |
|---|
| 4046 | + mac_table[i].afq.q[2].n_pkts, |
|---|
| 4047 | + mac_table[i].psq.q[6].n_pkts, |
|---|
| 4048 | + mac_table[i].psq.q[7].n_pkts, |
|---|
| 4049 | + mac_table[i].afq.q[3].n_pkts, |
|---|
| 4050 | + mac_table[i].psq.q[8].n_pkts, |
|---|
| 4051 | + mac_table[i].psq.q[9].n_pkts, |
|---|
| 4052 | + mac_table[i].afq.q[4].n_pkts); |
|---|
| 4076 | 4053 | |
|---|
| 4077 | 4054 | } |
|---|
| 4078 | 4055 | } |
|---|
| .. | .. |
|---|
| 4164 | 4141 | } |
|---|
| 4165 | 4142 | #endif /* PROP_TXSTATUS_DEBUG */ |
|---|
| 4166 | 4143 | bcm_bprintf(strbuf, "\n"); |
|---|
| 4167 | | - bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull,out),(dropped,hdr_only,wlc_tossed)" |
|---|
| 4144 | + bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull,out)," |
|---|
| 4145 | + "(dropped,hdr_only,wlc_tossed,wlc_dropped,wlc_exptime)" |
|---|
| 4168 | 4146 | "(freed,free_err,rollback)) = " |
|---|
| 4169 | | - "((%d,%d,%d,%d,%d),(%d,%d,%d),(%d,%d,%d))\n", |
|---|
| 4147 | + "((%d,%d,%d,%d,%d),(%d,%d,%d,%d,%d),(%d,%d,%d))\n", |
|---|
| 4170 | 4148 | wlfc->stats.pktin, |
|---|
| 4171 | 4149 | wlfc->stats.pkt2bus, |
|---|
| 4172 | 4150 | wlfc->stats.txstatus_in, |
|---|
| .. | .. |
|---|
| 4176 | 4154 | wlfc->stats.pktdropped, |
|---|
| 4177 | 4155 | wlfc->stats.wlfc_header_only_pkt, |
|---|
| 4178 | 4156 | wlfc->stats.wlc_tossed_pkts, |
|---|
| 4157 | + wlfc->stats.pkt_dropped, |
|---|
| 4158 | + wlfc->stats.pkt_exptime, |
|---|
| 4179 | 4159 | |
|---|
| 4180 | 4160 | wlfc->stats.pkt_freed, |
|---|
| 4181 | 4161 | wlfc->stats.pkt_free_err, wlfc->stats.rollback); |
|---|
| .. | .. |
|---|
| 4362 | 4342 | dhd_os_wlfc_unblock(dhdp); |
|---|
| 4363 | 4343 | } |
|---|
| 4364 | 4344 | |
|---|
| 4365 | | -#if defined(DHD_WLFC_THREAD) |
|---|
| 4366 | | - _dhd_wlfc_thread_wakeup(dhd); |
|---|
| 4367 | | -#endif /* defined(DHD_WLFC_THREAD) */ |
|---|
| 4368 | | - |
|---|
| 4369 | 4345 | return BCME_OK; |
|---|
| 4370 | 4346 | } |
|---|
| 4371 | 4347 | |
|---|
| .. | .. |
|---|
| 4459 | 4435 | __FUNCTION__, tlv)); |
|---|
| 4460 | 4436 | } |
|---|
| 4461 | 4437 | } |
|---|
| 4438 | + |
|---|
| 4439 | +#if defined(DHD_WLFC_THREAD) |
|---|
| 4440 | + _dhd_wlfc_thread_wakeup(dhd); |
|---|
| 4441 | +#endif /* defined(DHD_WLFC_THREAD) */ |
|---|
| 4442 | + |
|---|
| 4462 | 4443 | return BCME_OK; |
|---|
| 4463 | 4444 | } |
|---|
| 4464 | 4445 | |
|---|