| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: ISC |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * 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. |
|---|
| 15 | 4 | */ |
|---|
| 16 | 5 | #include <linux/types.h> |
|---|
| 17 | 6 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 322 | 311 | /* How long to defer borrowing in jiffies */ |
|---|
| 323 | 312 | #define BRCMF_FWS_BORROW_DEFER_PERIOD (HZ / 10) |
|---|
| 324 | 313 | |
|---|
| 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 | | -}; |
|---|
| 347 | 314 | |
|---|
| 348 | 315 | /** |
|---|
| 349 | 316 | * enum brcmf_fws_txstatus - txstatus flag values. |
|---|
| .. | .. |
|---|
| 356 | 323 | * firmware suppress the packet as device is already in PS mode. |
|---|
| 357 | 324 | * @BRCMF_FWS_TXSTATUS_FW_TOSSED: |
|---|
| 358 | 325 | * 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. |
|---|
| 359 | 330 | * @BRCMF_FWS_TXSTATUS_HOST_TOSSED: |
|---|
| 360 | 331 | * host tossed the packet. |
|---|
| 361 | 332 | */ |
|---|
| .. | .. |
|---|
| 364 | 335 | BRCMF_FWS_TXSTATUS_CORE_SUPPRESS, |
|---|
| 365 | 336 | BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS, |
|---|
| 366 | 337 | BRCMF_FWS_TXSTATUS_FW_TOSSED, |
|---|
| 338 | + BRCMF_FWS_TXSTATUS_FW_DISCARD_NOACK, |
|---|
| 339 | + BRCMF_FWS_TXSTATUS_FW_SUPPRESS_ACKED, |
|---|
| 367 | 340 | BRCMF_FWS_TXSTATUS_HOST_TOSSED |
|---|
| 368 | 341 | }; |
|---|
| 369 | 342 | |
|---|
| .. | .. |
|---|
| 381 | 354 | /** |
|---|
| 382 | 355 | * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface |
|---|
| 383 | 356 | * |
|---|
| 357 | + * @name: name of the descriptor. |
|---|
| 384 | 358 | * @occupied: slot is in use. |
|---|
| 385 | 359 | * @mac_handle: handle for mac entry determined by firmware. |
|---|
| 386 | 360 | * @interface_id: interface index. |
|---|
| .. | .. |
|---|
| 389 | 363 | * @generation: generation bit. |
|---|
| 390 | 364 | * @ac_bitmap: ac queue bitmap. |
|---|
| 391 | 365 | * @requested_credit: credits requested by firmware. |
|---|
| 366 | + * @requested_packet: packet requested by firmware. |
|---|
| 392 | 367 | * @ea: ethernet address. |
|---|
| 393 | 368 | * @seq: per-node free-running sequence. |
|---|
| 394 | 369 | * @psq: power-save queue. |
|---|
| 395 | 370 | * @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. |
|---|
| 396 | 375 | */ |
|---|
| 397 | 376 | struct brcmf_fws_mac_descriptor { |
|---|
| 398 | 377 | char name[16]; |
|---|
| .. | .. |
|---|
| 415 | 394 | u8 traffic_lastreported_bmp; |
|---|
| 416 | 395 | }; |
|---|
| 417 | 396 | |
|---|
| 418 | | -#define BRCMF_FWS_HANGER_MAXITEMS 1024 |
|---|
| 397 | +#define BRCMF_FWS_HANGER_MAXITEMS 3072 |
|---|
| 398 | +#define BRCMF_BORROW_RATIO 3 |
|---|
| 419 | 399 | |
|---|
| 420 | 400 | /** |
|---|
| 421 | 401 | * enum brcmf_fws_hanger_item_state - state of hanger item. |
|---|
| .. | .. |
|---|
| 511 | 491 | struct work_struct fws_dequeue_work; |
|---|
| 512 | 492 | u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT]; |
|---|
| 513 | 493 | 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]; |
|---|
| 515 | 497 | int deq_node_pos[BRCMF_FWS_FIFO_COUNT]; |
|---|
| 516 | 498 | u32 fifo_credit_map; |
|---|
| 517 | 499 | u32 fifo_delay_map; |
|---|
| .. | .. |
|---|
| 520 | 502 | bool creditmap_received; |
|---|
| 521 | 503 | u8 mode; |
|---|
| 522 | 504 | 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 |
|---|
| 537 | 505 | }; |
|---|
| 538 | 506 | |
|---|
| 539 | 507 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ |
|---|
| .. | .. |
|---|
| 922 | 890 | wlh += wlh[1] + 2; |
|---|
| 923 | 891 | |
|---|
| 924 | 892 | if (entry->send_tim_signal) { |
|---|
| 925 | | - entry->send_tim_signal = 0; |
|---|
| 893 | + entry->send_tim_signal = false; |
|---|
| 926 | 894 | wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP; |
|---|
| 927 | 895 | wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; |
|---|
| 928 | 896 | wlh[2] = entry->mac_handle; |
|---|
| .. | .. |
|---|
| 1223 | 1191 | |
|---|
| 1224 | 1192 | fws->fifo_credit_map |= 1 << fifo; |
|---|
| 1225 | 1193 | |
|---|
| 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) { |
|---|
| 1228 | 1196 | for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0; |
|---|
| 1229 | 1197 | lender_ac--) { |
|---|
| 1230 | | - borrowed = &fws->credits_borrowed[lender_ac]; |
|---|
| 1198 | + borrowed = &fws->credits_borrowed[fifo][lender_ac]; |
|---|
| 1231 | 1199 | if (*borrowed) { |
|---|
| 1232 | 1200 | fws->fifo_credit_map |= (1 << lender_ac); |
|---|
| 1233 | 1201 | fifo_credit = &fws->fifo_credit[lender_ac]; |
|---|
| .. | .. |
|---|
| 1244 | 1212 | } |
|---|
| 1245 | 1213 | } |
|---|
| 1246 | 1214 | |
|---|
| 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 | + |
|---|
| 1248 | 1222 | } |
|---|
| 1249 | 1223 | |
|---|
| 1250 | 1224 | static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) |
|---|
| .. | .. |
|---|
| 1259 | 1233 | enum brcmf_fws_skb_state state, int fifo, |
|---|
| 1260 | 1234 | struct sk_buff *p) |
|---|
| 1261 | 1235 | { |
|---|
| 1236 | + struct brcmf_pub *drvr = fws->drvr; |
|---|
| 1262 | 1237 | int prec = 2 * fifo; |
|---|
| 1263 | 1238 | u32 *qfull_stat = &fws->stats.delayq_full_error; |
|---|
| 1264 | 1239 | struct brcmf_fws_mac_descriptor *entry; |
|---|
| .. | .. |
|---|
| 1271 | 1246 | |
|---|
| 1272 | 1247 | entry = brcmf_skbcb(p)->mac; |
|---|
| 1273 | 1248 | 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); |
|---|
| 1275 | 1250 | return -ENOENT; |
|---|
| 1276 | 1251 | } |
|---|
| 1277 | 1252 | |
|---|
| .. | .. |
|---|
| 1459 | 1434 | |
|---|
| 1460 | 1435 | static int |
|---|
| 1461 | 1436 | 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) |
|---|
| 1463 | 1438 | { |
|---|
| 1439 | + struct brcmf_pub *drvr = fws->drvr; |
|---|
| 1464 | 1440 | u32 fifo; |
|---|
| 1441 | + u8 cnt = 0; |
|---|
| 1465 | 1442 | int ret; |
|---|
| 1466 | 1443 | bool remove_from_hanger = true; |
|---|
| 1467 | 1444 | struct sk_buff *skb; |
|---|
| .. | .. |
|---|
| 1472 | 1449 | brcmf_dbg(DATA, "flags %d\n", flags); |
|---|
| 1473 | 1450 | |
|---|
| 1474 | 1451 | if (flags == BRCMF_FWS_TXSTATUS_DISCARD) |
|---|
| 1475 | | - fws->stats.txs_discard++; |
|---|
| 1452 | + fws->stats.txs_discard += compcnt; |
|---|
| 1476 | 1453 | else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) { |
|---|
| 1477 | | - fws->stats.txs_supp_core++; |
|---|
| 1454 | + fws->stats.txs_supp_core += compcnt; |
|---|
| 1478 | 1455 | remove_from_hanger = false; |
|---|
| 1479 | 1456 | } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) { |
|---|
| 1480 | | - fws->stats.txs_supp_ps++; |
|---|
| 1457 | + fws->stats.txs_supp_ps += compcnt; |
|---|
| 1481 | 1458 | remove_from_hanger = false; |
|---|
| 1482 | 1459 | } 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; |
|---|
| 1484 | 1465 | else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) |
|---|
| 1485 | | - fws->stats.txs_host_tossed++; |
|---|
| 1466 | + fws->stats.txs_host_tossed += compcnt; |
|---|
| 1486 | 1467 | else |
|---|
| 1487 | | - brcmf_err("unexpected txstatus\n"); |
|---|
| 1468 | + bphy_err(drvr, "unexpected txstatus\n"); |
|---|
| 1488 | 1469 | |
|---|
| 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++; |
|---|
| 1494 | 1520 | } |
|---|
| 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); |
|---|
| 1529 | 1521 | |
|---|
| 1530 | 1522 | return 0; |
|---|
| 1531 | 1523 | } |
|---|
| .. | .. |
|---|
| 1551 | 1543 | return BRCMF_FWS_RET_OK_SCHEDULE; |
|---|
| 1552 | 1544 | } |
|---|
| 1553 | 1545 | |
|---|
| 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) |
|---|
| 1555 | 1548 | { |
|---|
| 1556 | 1549 | __le32 status_le; |
|---|
| 1557 | 1550 | __le16 seq_le; |
|---|
| .. | .. |
|---|
| 1560 | 1553 | u32 genbit; |
|---|
| 1561 | 1554 | u8 flags; |
|---|
| 1562 | 1555 | u16 seq; |
|---|
| 1556 | + u8 compcnt; |
|---|
| 1557 | + u8 compcnt_offset = BRCMF_FWS_TYPE_TXSTATUS_LEN; |
|---|
| 1563 | 1558 | |
|---|
| 1564 | | - fws->stats.txs_indicate++; |
|---|
| 1565 | 1559 | memcpy(&status_le, data, sizeof(status_le)); |
|---|
| 1566 | 1560 | status = le32_to_cpu(status_le); |
|---|
| 1567 | 1561 | flags = brcmf_txstatus_get_field(status, FLAGS); |
|---|
| 1568 | 1562 | hslot = brcmf_txstatus_get_field(status, HSLOT); |
|---|
| 1569 | 1563 | genbit = brcmf_txstatus_get_field(status, GENERATION); |
|---|
| 1570 | 1564 | 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], |
|---|
| 1572 | 1566 | sizeof(seq_le)); |
|---|
| 1573 | 1567 | seq = le16_to_cpu(seq_le); |
|---|
| 1568 | + compcnt_offset += BRCMF_FWS_TYPE_SEQ_LEN; |
|---|
| 1574 | 1569 | } else { |
|---|
| 1575 | 1570 | seq = 0; |
|---|
| 1576 | 1571 | } |
|---|
| 1577 | 1572 | |
|---|
| 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 | + |
|---|
| 1578 | 1579 | 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); |
|---|
| 1580 | 1581 | brcmf_fws_unlock(fws); |
|---|
| 1581 | 1582 | return BRCMF_FWS_RET_OK_NOSCHEDULE; |
|---|
| 1582 | 1583 | } |
|---|
| .. | .. |
|---|
| 1595 | 1596 | const struct brcmf_event_msg *e, |
|---|
| 1596 | 1597 | void *data) |
|---|
| 1597 | 1598 | { |
|---|
| 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); |
|---|
| 1599 | 1601 | int i; |
|---|
| 1600 | 1602 | u8 *credits = data; |
|---|
| 1601 | 1603 | |
|---|
| 1602 | 1604 | 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); |
|---|
| 1604 | 1606 | return -EINVAL; |
|---|
| 1605 | 1607 | } |
|---|
| 1606 | | - if (fws->creditmap_received) |
|---|
| 1607 | | - return 0; |
|---|
| 1608 | 1608 | |
|---|
| 1609 | 1609 | fws->creditmap_received = true; |
|---|
| 1610 | 1610 | |
|---|
| 1611 | 1611 | brcmf_dbg(TRACE, "enter: credits %pM\n", credits); |
|---|
| 1612 | 1612 | brcmf_fws_lock(fws); |
|---|
| 1613 | 1613 | 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) |
|---|
| 1615 | 1617 | fws->fifo_credit_map |= 1 << i; |
|---|
| 1616 | 1618 | else |
|---|
| 1617 | 1619 | 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]); |
|---|
| 1619 | 1623 | } |
|---|
| 1620 | 1624 | brcmf_fws_schedule_deq(fws); |
|---|
| 1621 | 1625 | brcmf_fws_unlock(fws); |
|---|
| .. | .. |
|---|
| 1660 | 1664 | rfi->pend_pkts -= skb_queue_len(skb_list); |
|---|
| 1661 | 1665 | } |
|---|
| 1662 | 1666 | |
|---|
| 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) |
|---|
| 1664 | 1668 | { |
|---|
| 1669 | + struct brcmf_pub *drvr = ifp->drvr; |
|---|
| 1665 | 1670 | u8 *reorder_data; |
|---|
| 1666 | 1671 | u8 flow_id, max_idx, cur_idx, exp_idx, end_idx; |
|---|
| 1667 | 1672 | struct brcmf_ampdu_rx_reorder *rfi; |
|---|
| .. | .. |
|---|
| 1676 | 1681 | |
|---|
| 1677 | 1682 | /* validate flags and flow id */ |
|---|
| 1678 | 1683 | 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); |
|---|
| 1681 | 1686 | return; |
|---|
| 1682 | 1687 | } |
|---|
| 1683 | 1688 | |
|---|
| .. | .. |
|---|
| 1689 | 1694 | if (rfi == NULL) { |
|---|
| 1690 | 1695 | brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", |
|---|
| 1691 | 1696 | flow_id); |
|---|
| 1692 | | - brcmf_netif_rx(ifp, pkt); |
|---|
| 1697 | + brcmf_netif_rx(ifp, pkt, inirq); |
|---|
| 1693 | 1698 | return; |
|---|
| 1694 | 1699 | } |
|---|
| 1695 | 1700 | |
|---|
| .. | .. |
|---|
| 1713 | 1718 | flow_id, max_idx); |
|---|
| 1714 | 1719 | rfi = kzalloc(buf_size, GFP_ATOMIC); |
|---|
| 1715 | 1720 | 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); |
|---|
| 1718 | 1723 | return; |
|---|
| 1719 | 1724 | } |
|---|
| 1720 | 1725 | |
|---|
| .. | .. |
|---|
| 1828 | 1833 | netif_rx: |
|---|
| 1829 | 1834 | skb_queue_walk_safe(&reorder_list, pkt, pnext) { |
|---|
| 1830 | 1835 | __skb_unlink(pkt, &reorder_list); |
|---|
| 1831 | | - brcmf_netif_rx(ifp, pkt); |
|---|
| 1836 | + brcmf_netif_rx(ifp, pkt, inirq); |
|---|
| 1832 | 1837 | } |
|---|
| 1833 | 1838 | } |
|---|
| 1834 | 1839 | |
|---|
| .. | .. |
|---|
| 1848 | 1853 | ifp->ifidx, skb->len, siglen); |
|---|
| 1849 | 1854 | |
|---|
| 1850 | 1855 | WARN_ON(siglen > skb->len); |
|---|
| 1856 | + |
|---|
| 1857 | + if (siglen > skb->len) |
|---|
| 1858 | + siglen = skb->len; |
|---|
| 1851 | 1859 | |
|---|
| 1852 | 1860 | if (!siglen) |
|---|
| 1853 | 1861 | return; |
|---|
| .. | .. |
|---|
| 1890 | 1898 | |
|---|
| 1891 | 1899 | err = BRCMF_FWS_RET_OK_NOSCHEDULE; |
|---|
| 1892 | 1900 | switch (type) { |
|---|
| 1893 | | - case BRCMF_FWS_TYPE_COMP_TXSTATUS: |
|---|
| 1894 | | - break; |
|---|
| 1895 | 1901 | case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS: |
|---|
| 1896 | 1902 | rd = (struct brcmf_skb_reorder_data *)skb->cb; |
|---|
| 1897 | 1903 | rd->reorder = data; |
|---|
| .. | .. |
|---|
| 1914 | 1920 | err = brcmf_fws_request_indicate(fws, type, data); |
|---|
| 1915 | 1921 | break; |
|---|
| 1916 | 1922 | 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); |
|---|
| 1918 | 1925 | break; |
|---|
| 1919 | 1926 | case BRCMF_FWS_TYPE_FIFO_CREDITBACK: |
|---|
| 1920 | 1927 | err = brcmf_fws_fifocreditback_indicate(fws, data); |
|---|
| .. | .. |
|---|
| 1978 | 1985 | static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, |
|---|
| 1979 | 1986 | struct sk_buff *skb, int fifo) |
|---|
| 1980 | 1987 | { |
|---|
| 1988 | + struct brcmf_pub *drvr = fws->drvr; |
|---|
| 1981 | 1989 | struct brcmf_fws_mac_descriptor *entry; |
|---|
| 1982 | 1990 | struct sk_buff *pktout; |
|---|
| 1983 | 1991 | int qidx, hslot; |
|---|
| .. | .. |
|---|
| 1991 | 1999 | |
|---|
| 1992 | 2000 | pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb); |
|---|
| 1993 | 2001 | 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); |
|---|
| 1995 | 2003 | rc = -ENOSPC; |
|---|
| 1996 | 2004 | } |
|---|
| 1997 | 2005 | } else { |
|---|
| 1998 | | - brcmf_err("%s entry removed\n", entry->name); |
|---|
| 2006 | + bphy_err(drvr, "%s entry removed\n", entry->name); |
|---|
| 1999 | 2007 | rc = -ENOENT; |
|---|
| 2000 | 2008 | } |
|---|
| 2001 | 2009 | |
|---|
| .. | .. |
|---|
| 2003 | 2011 | fws->stats.rollback_failed++; |
|---|
| 2004 | 2012 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); |
|---|
| 2005 | 2013 | brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, |
|---|
| 2006 | | - hslot, 0, 0); |
|---|
| 2014 | + hslot, 0, 0, 1); |
|---|
| 2007 | 2015 | } else { |
|---|
| 2008 | 2016 | fws->stats.rollback_success++; |
|---|
| 2009 | 2017 | brcmf_fws_return_credits(fws, fifo, 1); |
|---|
| .. | .. |
|---|
| 2011 | 2019 | } |
|---|
| 2012 | 2020 | } |
|---|
| 2013 | 2021 | |
|---|
| 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) |
|---|
| 2015 | 2025 | { |
|---|
| 2016 | | - int lender_ac; |
|---|
| 2026 | + int lender_ac, borrow_limit = 0; |
|---|
| 2017 | 2027 | |
|---|
| 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++) { |
|---|
| 2022 | 2029 | |
|---|
| 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]++; |
|---|
| 2026 | 2038 | fws->fifo_credit[lender_ac]--; |
|---|
| 2027 | 2039 | if (fws->fifo_credit[lender_ac] == 0) |
|---|
| 2028 | 2040 | 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); |
|---|
| 2030 | 2042 | brcmf_dbg(DATA, "borrow credit from: %d\n", lender_ac); |
|---|
| 2031 | 2043 | return 0; |
|---|
| 2032 | 2044 | } |
|---|
| 2033 | 2045 | } |
|---|
| 2034 | | - fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE); |
|---|
| 2046 | + fws->fifo_credit_map &= ~(1 << borrower_ac); |
|---|
| 2035 | 2047 | return -ENAVAIL; |
|---|
| 2036 | 2048 | } |
|---|
| 2037 | 2049 | |
|---|
| .. | .. |
|---|
| 2100 | 2112 | |
|---|
| 2101 | 2113 | int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) |
|---|
| 2102 | 2114 | { |
|---|
| 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); |
|---|
| 2104 | 2117 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); |
|---|
| 2105 | 2118 | struct ethhdr *eh = (struct ethhdr *)(skb->data); |
|---|
| 2106 | 2119 | int fifo = BRCMF_FWS_FIFO_BCMC; |
|---|
| .. | .. |
|---|
| 2113 | 2126 | skcb->if_flags = 0; |
|---|
| 2114 | 2127 | skcb->state = BRCMF_FWS_SKBSTATE_NEW; |
|---|
| 2115 | 2128 | brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx); |
|---|
| 2129 | + |
|---|
| 2130 | + /* mapping from 802.1d priority to firmware fifo index */ |
|---|
| 2116 | 2131 | if (!multicast) |
|---|
| 2117 | | - fifo = brcmf_fws_prio2fifo[skb->priority]; |
|---|
| 2132 | + fifo = brcmf_map_prio_to_aci(drvr->config, skb->priority); |
|---|
| 2118 | 2133 | |
|---|
| 2119 | 2134 | brcmf_fws_lock(fws); |
|---|
| 2120 | 2135 | if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC) |
|---|
| .. | .. |
|---|
| 2128 | 2143 | brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); |
|---|
| 2129 | 2144 | brcmf_fws_schedule_deq(fws); |
|---|
| 2130 | 2145 | } 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"); |
|---|
| 2133 | 2147 | rc = -ENOMEM; |
|---|
| 2134 | 2148 | } |
|---|
| 2135 | 2149 | brcmf_fws_unlock(fws); |
|---|
| .. | .. |
|---|
| 2220 | 2234 | } |
|---|
| 2221 | 2235 | continue; |
|---|
| 2222 | 2236 | } |
|---|
| 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))) { |
|---|
| 2225 | 2241 | skb = brcmf_fws_deq(fws, fifo); |
|---|
| 2226 | 2242 | if (!skb) |
|---|
| 2227 | 2243 | break; |
|---|
| .. | .. |
|---|
| 2231 | 2247 | if (fws->bus_flow_blocked) |
|---|
| 2232 | 2248 | break; |
|---|
| 2233 | 2249 | } |
|---|
| 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) { |
|---|
| 2238 | 2258 | skb = brcmf_fws_deq(fws, fifo); |
|---|
| 2239 | 2259 | if (!skb) { |
|---|
| 2240 | 2260 | brcmf_fws_return_credits(fws, fifo, 1); |
|---|
| .. | .. |
|---|
| 2339 | 2359 | fws->drvr = drvr; |
|---|
| 2340 | 2360 | fws->fcmode = drvr->settings->fcmode; |
|---|
| 2341 | 2361 | |
|---|
| 2342 | | - if ((drvr->bus_if->always_use_fws_queue == false) && |
|---|
| 2362 | + if (!drvr->bus_if->always_use_fws_queue && |
|---|
| 2343 | 2363 | (fws->fcmode == BRCMF_FWS_FCMODE_NONE)) { |
|---|
| 2344 | 2364 | fws->avoid_queueing = true; |
|---|
| 2345 | 2365 | brcmf_dbg(INFO, "FWS queueing will be avoided\n"); |
|---|
| .. | .. |
|---|
| 2348 | 2368 | |
|---|
| 2349 | 2369 | fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq"); |
|---|
| 2350 | 2370 | if (fws->fws_wq == NULL) { |
|---|
| 2351 | | - brcmf_err("workqueue creation failed\n"); |
|---|
| 2371 | + bphy_err(drvr, "workqueue creation failed\n"); |
|---|
| 2352 | 2372 | rc = -EBADF; |
|---|
| 2353 | 2373 | goto fail; |
|---|
| 2354 | 2374 | } |
|---|
| .. | .. |
|---|
| 2364 | 2384 | rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP, |
|---|
| 2365 | 2385 | brcmf_fws_notify_credit_map); |
|---|
| 2366 | 2386 | if (rc < 0) { |
|---|
| 2367 | | - brcmf_err("register credit map handler failed\n"); |
|---|
| 2387 | + bphy_err(drvr, "register credit map handler failed\n"); |
|---|
| 2368 | 2388 | goto fail; |
|---|
| 2369 | 2389 | } |
|---|
| 2370 | 2390 | rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT, |
|---|
| 2371 | 2391 | brcmf_fws_notify_bcmc_credit_support); |
|---|
| 2372 | 2392 | if (rc < 0) { |
|---|
| 2373 | | - brcmf_err("register bcmc credit handler failed\n"); |
|---|
| 2393 | + bphy_err(drvr, "register bcmc credit handler failed\n"); |
|---|
| 2374 | 2394 | brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP); |
|---|
| 2375 | 2395 | goto fail; |
|---|
| 2376 | 2396 | } |
|---|
| .. | .. |
|---|
| 2382 | 2402 | fws->fw_signals = true; |
|---|
| 2383 | 2403 | ifp = brcmf_get_ifp(drvr, 0); |
|---|
| 2384 | 2404 | 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"); |
|---|
| 2386 | 2406 | fws->fcmode = BRCMF_FWS_FCMODE_NONE; |
|---|
| 2387 | 2407 | fws->fw_signals = false; |
|---|
| 2388 | 2408 | } |
|---|
| .. | .. |
|---|
| 2414 | 2434 | return fws; |
|---|
| 2415 | 2435 | |
|---|
| 2416 | 2436 | fail: |
|---|
| 2417 | | - brcmf_fws_detach_pre_delif(fws); |
|---|
| 2418 | | - brcmf_fws_detach_post_delif(fws); |
|---|
| 2437 | + brcmf_fws_detach(fws); |
|---|
| 2419 | 2438 | return ERR_PTR(rc); |
|---|
| 2420 | 2439 | } |
|---|
| 2421 | 2440 | |
|---|
| 2422 | | -void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws) |
|---|
| 2441 | +void brcmf_fws_detach(struct brcmf_fws_info *fws) |
|---|
| 2423 | 2442 | { |
|---|
| 2424 | 2443 | if (!fws) |
|---|
| 2425 | 2444 | return; |
|---|
| 2426 | | - if (fws->fws_wq) { |
|---|
| 2427 | | - destroy_workqueue(fws->fws_wq); |
|---|
| 2428 | | - fws->fws_wq = NULL; |
|---|
| 2429 | | - } |
|---|
| 2430 | | -} |
|---|
| 2431 | 2445 | |
|---|
| 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); |
|---|
| 2436 | 2448 | |
|---|
| 2437 | 2449 | /* cleanup */ |
|---|
| 2438 | 2450 | brcmf_fws_lock(fws); |
|---|
| .. | .. |
|---|
| 2473 | 2485 | } |
|---|
| 2474 | 2486 | brcmf_fws_lock(fws); |
|---|
| 2475 | 2487 | 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); |
|---|
| 2477 | 2490 | brcmf_fws_unlock(fws); |
|---|
| 2478 | 2491 | } |
|---|
| 2479 | 2492 | |
|---|