Lines Matching refs:fws

514  * @fws: firmware-signalling information.
519 static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws,
525 fws->stats.tlv_invalid_type++;
532 static void brcmf_fws_lock(struct brcmf_fws_info *fws)
533 __acquires(&fws->spinlock)
535 spin_lock_irqsave(&fws->spinlock, fws->flags);
538 static void brcmf_fws_unlock(struct brcmf_fws_info *fws)
539 __releases(&fws->spinlock)
541 spin_unlock_irqrestore(&fws->spinlock, fws->flags);
621 static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
636 hi = &fws->hanger.items[hslot];
639 brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
662 static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws,
666 struct brcmf_fws_hanger *h = &fws->hanger;
687 static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws,
690 if (desc == &fws->desc.other)
728 brcmf_fws_macdesc_lookup(struct brcmf_fws_info *fws, u8 *ea)
736 entry = &fws->desc.nodes[0];
737 for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) {
747 brcmf_fws_macdesc_find(struct brcmf_fws_info *fws, struct brcmf_if *ifp, u8 *da)
763 entry = brcmf_fws_macdesc_lookup(fws, da);
771 static bool brcmf_fws_macdesc_closed(struct brcmf_fws_info *fws,
782 if_entry = &fws->desc.iface[entry->interface_id];
796 static void brcmf_fws_macdesc_cleanup(struct brcmf_fws_info *fws,
801 brcmf_fws_psq_flush(fws, &entry->psq, ifidx);
806 static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws,
816 txq = brcmf_bus_gettxq(fws->drvr->bus_if);
826 hi = &fws->hanger.items[hslot];
835 static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
841 if (fws == NULL)
848 table = &fws->desc.nodes[0];
849 for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++)
850 brcmf_fws_macdesc_cleanup(fws, &table[i], ifidx);
852 brcmf_fws_macdesc_cleanup(fws, &fws->desc.other, ifidx);
853 brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx);
854 brcmf_fws_hanger_cleanup(fws, matchfn, ifidx);
857 static u8 brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
872 if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
885 if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
909 static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
936 4 + fws->drvr->hdrlen;
946 data_offset = brcmf_fws_hdrpush(fws, skb);
948 brcmf_fws_unlock(fws);
949 err = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
950 brcmf_fws_lock(fws);
959 brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
962 struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id);
973 fws->stats.fws_flow_block++;
979 static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
986 int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
997 entry = &fws->desc.nodes[mac_handle & 0x1F];
1002 brcmf_fws_lock(fws);
1003 brcmf_fws_macdesc_cleanup(fws, entry, -1);
1005 brcmf_fws_unlock(fws);
1007 fws->stats.mac_update_failed++;
1011 existing = brcmf_fws_macdesc_lookup(fws, addr);
1014 brcmf_fws_lock(fws);
1017 brcmf_fws_macdesc_set_name(fws, entry);
1020 brcmf_fws_unlock(fws);
1023 fws->stats.mac_update_failed++;
1028 brcmf_fws_lock(fws);
1033 brcmf_fws_macdesc_set_name(fws, entry);
1034 brcmf_fws_unlock(fws);
1046 static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
1054 entry = &fws->desc.nodes[mac_handle & 0x1F];
1056 fws->stats.mac_ps_update_failed++;
1059 brcmf_fws_lock(fws);
1068 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false);
1069 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false);
1070 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false);
1071 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
1074 brcmf_fws_unlock(fws);
1078 static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
1092 entry = &fws->desc.iface[ifidx];
1100 brcmf_fws_lock(fws);
1112 brcmf_fws_unlock(fws);
1115 brcmf_fws_unlock(fws);
1119 fws->stats.if_update_failed++;
1123 static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
1128 entry = &fws->desc.nodes[data[1] & 0x1F];
1131 fws->stats.credit_request_failed++;
1133 fws->stats.packet_request_failed++;
1140 brcmf_fws_lock(fws);
1147 brcmf_fws_unlock(fws);
1182 static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
1192 fws->fifo_credit_map |= 1 << fifo;
1198 borrowed = &fws->credits_borrowed[fifo][lender_ac];
1200 fws->fifo_credit_map |= (1 << lender_ac);
1201 fifo_credit = &fws->fifo_credit[lender_ac];
1216 fws->fifo_credit[fifo] += credits;
1219 if (fws->fifo_credit[fifo] > fws->init_fifo_credit[fifo])
1220 fws->fifo_credit[fifo] = fws->init_fifo_credit[fifo];
1224 static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws)
1227 if ((fws->fifo_credit_map & fws->fifo_delay_map) ||
1228 (!brcmf_fws_fc_active(fws) && fws->fifo_delay_map))
1229 queue_work(fws->fws_wq, &fws->fws_dequeue_work);
1232 static int brcmf_fws_enq(struct brcmf_fws_info *fws,
1236 struct brcmf_pub *drvr = fws->drvr;
1238 u32 *qfull_stat = &fws->stats.delayq_full_error;
1256 qfull_stat = &fws->stats.supprq_full_error;
1311 fws->fifo_delay_map |= 1 << fifo;
1312 fws->fifo_enqpkt[fifo]++;
1321 brcmf_fws_tim_update(fws, entry, fifo, true);
1322 brcmf_fws_flow_control_check(fws, &entry->psq,
1327 static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
1338 table = (struct brcmf_fws_mac_descriptor *)&fws->desc;
1339 num_nodes = sizeof(fws->desc) / sizeof(struct brcmf_fws_mac_descriptor);
1340 node_pos = fws->deq_node_pos[fifo];
1345 brcmf_fws_macdesc_closed(fws, entry, fifo))
1368 fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes;
1369 brcmf_fws_flow_control_check(fws, &entry->psq,
1377 brcmf_fws_tim_update(fws, entry, fifo, false);
1383 fws->fifo_enqpkt[fifo]--;
1384 if (fws->fifo_enqpkt[fifo] == 0)
1385 fws->fifo_delay_map &= ~(1 << fifo);
1394 static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
1422 ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb);
1426 brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true);
1429 brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
1436 brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
1439 struct brcmf_pub *drvr = fws->drvr;
1452 fws->stats.txs_discard += compcnt;
1454 fws->stats.txs_supp_core += compcnt;
1457 fws->stats.txs_supp_ps += compcnt;
1460 fws->stats.txs_tossed += compcnt;
1462 fws->stats.txs_discard += compcnt;
1464 fws->stats.txs_discard += compcnt;
1466 fws->stats.txs_host_tossed += compcnt;
1471 ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
1494 if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT ||
1497 brcmf_fws_return_credits(fws, fifo, 1);
1498 brcmf_fws_schedule_deq(fws);
1502 ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
1508 ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
1516 if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
1525 static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
1530 if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
1536 brcmf_fws_lock(fws);
1538 brcmf_fws_return_credits(fws, i, data[i]);
1540 brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
1541 fws->fifo_delay_map);
1542 brcmf_fws_unlock(fws);
1546 static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 type,
1564 if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
1577 fws->stats.txs_indicate += compcnt;
1579 brcmf_fws_lock(fws);
1580 brcmf_fws_txs_process(fws, flags, hslot, genbit, seq, compcnt);
1581 brcmf_fws_unlock(fws);
1585 static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
1600 struct brcmf_fws_info *fws = drvr_to_fws(drvr);
1609 fws->creditmap_received = true;
1612 brcmf_fws_lock(fws);
1613 for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) {
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)
1617 fws->fifo_credit_map |= 1 << i;
1619 fws->fifo_credit_map &= ~(1 << i);
1620 WARN_ONCE(fws->fifo_credit[i] < 0,
1622 fws->fifo_credit[i]);
1624 brcmf_fws_schedule_deq(fws);
1625 brcmf_fws_unlock(fws);
1633 struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
1635 if (fws) {
1636 brcmf_fws_lock(fws);
1637 fws->bcmc_credit_check = true;
1638 brcmf_fws_unlock(fws);
1843 struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
1863 if ((!fws) || (!fws->fw_signals)) {
1868 fws->stats.header_pulls++;
1890 brcmf_fws_get_tlv_len(fws, type));
1896 if (len < brcmf_fws_get_tlv_len(fws, type))
1907 brcmf_fws_macdesc_indicate(fws, type, data);
1911 err = brcmf_fws_macdesc_state_indicate(fws, type, data);
1915 err = brcmf_fws_interface_state_indicate(fws, type,
1920 err = brcmf_fws_request_indicate(fws, type, data);
1924 brcmf_fws_txstatus_indicate(fws, type, data);
1927 err = brcmf_fws_fifocreditback_indicate(fws, data);
1930 brcmf_fws_rssi_indicate(fws, *data);
1933 brcmf_fws_dbg_seqnum_check(fws, data);
1938 fws->stats.tlv_invalid_type++;
1948 fws->stats.tlv_parse_failed++;
1951 brcmf_fws_schedule_deq(fws);
1961 fws->stats.header_only_pkt++;
1964 static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
1982 return brcmf_fws_hdrpush(fws, p);
1985 static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
1988 struct brcmf_pub *drvr = fws->drvr;
2011 fws->stats.rollback_failed++;
2013 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
2016 fws->stats.rollback_success++;
2017 brcmf_fws_return_credits(fws, fifo, 1);
2022 static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws,
2032 fws->init_fifo_credit[lender_ac] / BRCMF_BORROW_RATIO;
2036 if (fws->fifo_credit[lender_ac] > borrow_limit) {
2037 fws->credits_borrowed[borrower_ac][lender_ac]++;
2038 fws->fifo_credit[lender_ac]--;
2039 if (fws->fifo_credit[lender_ac] == 0)
2040 fws->fifo_credit_map &= ~(1 << lender_ac);
2041 fws->fifo_credit_map |= (1 << borrower_ac);
2046 fws->fifo_credit_map &= ~(1 << borrower_ac);
2050 static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
2063 data_offset = brcmf_fws_precommit_skb(fws, fifo, skb);
2068 brcmf_fws_unlock(fws);
2069 rc = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
2070 brcmf_fws_lock(fws);
2077 (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL);
2081 fws->stats.pkt2bus++;
2082 fws->stats.send_pkts[fifo]++;
2084 fws->stats.requested_sent[fifo]++;
2089 brcmf_fws_rollback_toq(fws, skb, fifo);
2093 static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
2101 hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
2105 rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
2109 fws->stats.generic_error++;
2116 struct brcmf_fws_info *fws = drvr_to_fws(drvr);
2134 brcmf_fws_lock(fws);
2136 fws->borrow_defer_timestamp = jiffies +
2139 skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
2142 if (!brcmf_fws_assign_htod(fws, skb, fifo)) {
2143 brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
2144 brcmf_fws_schedule_deq(fws);
2149 brcmf_fws_unlock(fws);
2167 struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
2170 if (!ifp->ndev || !brcmf_fws_queue_skbs(fws))
2173 entry = &fws->desc.iface[ifp->ifidx];
2176 brcmf_fws_macdesc_set_name(fws, entry);
2185 struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
2190 brcmf_fws_lock(fws);
2193 brcmf_fws_macdesc_cleanup(fws, &fws->desc.iface[ifp->ifidx],
2196 brcmf_fws_cleanup(fws, ifp->ifidx);
2197 brcmf_fws_unlock(fws);
2202 struct brcmf_fws_info *fws;
2210 fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
2211 drvr = fws->drvr;
2213 brcmf_fws_lock(fws);
2214 for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
2216 if (!brcmf_fws_fc_active(fws)) {
2217 while ((skb = brcmf_fws_deq(fws, fifo)) != NULL) {
2220 brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
2225 brcmf_fws_unlock(fws);
2227 brcmf_fws_lock(fws);
2232 if (fws->bus_flow_blocked)
2238 while ((fws->fifo_credit[fifo]) ||
2239 ((!fws->bcmc_credit_check) &&
2241 skb = brcmf_fws_deq(fws, fifo);
2244 fws->fifo_credit[fifo]--;
2245 if (brcmf_fws_commit_skb(fws, fifo, skb))
2247 if (fws->bus_flow_blocked)
2253 fws->fifo_credit[fifo] == 0 &&
2254 !fws->bus_flow_blocked) {
2255 while (brcmf_fws_borrow_credit(fws,
2258 skb = brcmf_fws_deq(fws, fifo);
2260 brcmf_fws_return_credits(fws, fifo, 1);
2263 if (brcmf_fws_commit_skb(fws, fifo, skb))
2265 if (fws->bus_flow_blocked)
2270 brcmf_fws_unlock(fws);
2344 struct brcmf_fws_info *fws;
2350 fws = kzalloc(sizeof(*fws), GFP_KERNEL);
2351 if (!fws) {
2356 spin_lock_init(&fws->spinlock);
2359 fws->drvr = drvr;
2360 fws->fcmode = drvr->settings->fcmode;
2363 (fws->fcmode == BRCMF_FWS_FCMODE_NONE)) {
2364 fws->avoid_queueing = true;
2366 return fws;
2369 fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
2370 if (fws->fws_wq == NULL) {
2375 INIT_WORK(&fws->fws_dequeue_work, brcmf_fws_dequeue_worker);
2378 if (fws->fcmode != BRCMF_FWS_FCMODE_NONE)
2402 fws->fw_signals = true;
2406 fws->fcmode = BRCMF_FWS_FCMODE_NONE;
2407 fws->fw_signals = false;
2420 BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1);
2425 brcmf_fws_hanger_init(&fws->hanger);
2426 brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0);
2427 brcmf_fws_macdesc_set_name(fws, &fws->desc.other);
2428 brcmf_dbg(INFO, "added %s\n", fws->desc.other.name);
2429 brcmu_pktq_init(&fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
2433 fws->fw_signals ? "enabled" : "disabled", tlv);
2434 return fws;
2437 brcmf_fws_detach(fws);
2441 void brcmf_fws_detach(struct brcmf_fws_info *fws)
2443 if (!fws)
2446 if (fws->fws_wq)
2447 destroy_workqueue(fws->fws_wq);
2450 brcmf_fws_lock(fws);
2451 brcmf_fws_cleanup(fws, -1);
2452 brcmf_fws_unlock(fws);
2455 kfree(fws);
2465 bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws)
2467 return !fws->avoid_queueing;
2470 bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
2472 if (!fws->creditmap_received)
2475 return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
2478 void brcmf_fws_bustxcomplete(struct brcmf_fws_info *fws, struct sk_buff *skb,
2489 brcmf_fws_lock(fws);
2491 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot,
2493 brcmf_fws_unlock(fws);
2499 struct brcmf_fws_info *fws = drvr_to_fws(drvr);
2503 if (fws->avoid_queueing) {
2512 fws->bus_flow_blocked = flow_blocked;
2514 brcmf_fws_schedule_deq(fws);
2516 fws->stats.bus_flow_block++;