2019-02-12 12:43:06 +00:00
|
|
|
From e4af3ffb43d50f070134aa1b40d5c3573f57deb1 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Chung-Hsien Hsu <stanley.hsu@cypress.com>
|
|
|
|
Date: Mon, 5 Nov 2018 05:52:05 +0000
|
|
|
|
Subject: [PATCH] brcmfmac: handle compressed tx status signal
|
|
|
|
|
|
|
|
Firmware inform the driver about tx status by normal tx status signal
|
|
|
|
or compressed tx status signal. This patch adds support to handle the
|
|
|
|
compressed tx status signal.
|
|
|
|
|
|
|
|
Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>
|
|
|
|
Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
|
|
|
|
Signed-off-by: Wright Feng <wright.feng@cypress.com>
|
|
|
|
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
|
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
|
|
|
---
|
|
|
|
.../broadcom/brcm80211/brcmfmac/fwsignal.c | 121 ++++++++++--------
|
|
|
|
1 file changed, 71 insertions(+), 50 deletions(-)
|
|
|
|
|
|
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
|
|
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
|
2019-07-06 22:08:20 +00:00
|
|
|
@@ -1459,9 +1459,10 @@ static int brcmf_fws_txstatus_suppressed
|
2019-02-12 12:43:06 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
|
|
|
|
- u32 genbit, u16 seq)
|
|
|
|
+ u32 genbit, u16 seq, u8 compcnt)
|
|
|
|
{
|
|
|
|
u32 fifo;
|
|
|
|
+ u8 cnt = 0;
|
|
|
|
int ret;
|
|
|
|
bool remove_from_hanger = true;
|
|
|
|
struct sk_buff *skb;
|
2019-07-06 22:08:20 +00:00
|
|
|
@@ -1472,60 +1473,71 @@ brcmf_fws_txs_process(struct brcmf_fws_i
|
2019-02-12 12:43:06 +00:00
|
|
|
brcmf_dbg(DATA, "flags %d\n", flags);
|
|
|
|
|
|
|
|
if (flags == BRCMF_FWS_TXSTATUS_DISCARD)
|
|
|
|
- fws->stats.txs_discard++;
|
|
|
|
+ fws->stats.txs_discard += compcnt;
|
|
|
|
else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) {
|
|
|
|
- fws->stats.txs_supp_core++;
|
|
|
|
+ fws->stats.txs_supp_core += compcnt;
|
|
|
|
remove_from_hanger = false;
|
|
|
|
} else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) {
|
|
|
|
- fws->stats.txs_supp_ps++;
|
|
|
|
+ fws->stats.txs_supp_ps += compcnt;
|
|
|
|
remove_from_hanger = false;
|
|
|
|
} else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED)
|
|
|
|
- fws->stats.txs_tossed++;
|
|
|
|
+ fws->stats.txs_tossed += compcnt;
|
|
|
|
else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)
|
|
|
|
- fws->stats.txs_host_tossed++;
|
|
|
|
+ fws->stats.txs_host_tossed += compcnt;
|
|
|
|
else
|
|
|
|
brcmf_err("unexpected txstatus\n");
|
|
|
|
|
|
|
|
- ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
|
|
|
|
- remove_from_hanger);
|
|
|
|
- if (ret != 0) {
|
|
|
|
- brcmf_err("no packet in hanger slot: hslot=%d\n", hslot);
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
+ while (cnt < compcnt) {
|
|
|
|
+ ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
|
|
|
|
+ remove_from_hanger);
|
|
|
|
+ if (ret != 0) {
|
|
|
|
+ brcmf_err("no packet in hanger slot: hslot=%d\n",
|
|
|
|
+ hslot);
|
|
|
|
+ goto cont;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- skcb = brcmf_skbcb(skb);
|
|
|
|
- entry = skcb->mac;
|
|
|
|
- if (WARN_ON(!entry)) {
|
|
|
|
- brcmu_pkt_buf_free_skb(skb);
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
- entry->transit_count--;
|
|
|
|
- if (entry->suppressed && entry->suppr_transit_count)
|
|
|
|
- entry->suppr_transit_count--;
|
2019-02-15 17:43:55 +00:00
|
|
|
-
|
|
|
|
- brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags,
|
|
|
|
- skcb->htod, seq);
|
|
|
|
-
|
|
|
|
- /* pick up the implicit credit from this packet */
|
|
|
|
- fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
|
|
|
|
- if ((fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT) ||
|
|
|
|
- (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
|
|
|
|
- (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) {
|
|
|
|
- brcmf_fws_return_credits(fws, fifo, 1);
|
|
|
|
- brcmf_fws_schedule_deq(fws);
|
|
|
|
- }
|
|
|
|
- brcmf_fws_macdesc_return_req_credit(skb);
|
2019-02-12 12:43:06 +00:00
|
|
|
+ skcb = brcmf_skbcb(skb);
|
|
|
|
+ entry = skcb->mac;
|
|
|
|
+ if (WARN_ON(!entry)) {
|
|
|
|
+ brcmu_pkt_buf_free_skb(skb);
|
|
|
|
+ goto cont;
|
|
|
|
+ }
|
|
|
|
+ entry->transit_count--;
|
|
|
|
+ if (entry->suppressed && entry->suppr_transit_count)
|
|
|
|
+ entry->suppr_transit_count--;
|
|
|
|
|
2019-02-15 17:43:55 +00:00
|
|
|
- ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
|
|
|
|
- if (ret) {
|
|
|
|
- brcmu_pkt_buf_free_skb(skb);
|
|
|
|
- return -EINVAL;
|
2019-02-12 12:43:06 +00:00
|
|
|
+ brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name,
|
|
|
|
+ flags, skcb->htod, seq);
|
2019-02-15 17:43:55 +00:00
|
|
|
+
|
2019-02-12 12:43:06 +00:00
|
|
|
+ /* pick up the implicit credit from this packet */
|
|
|
|
+ fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
|
|
|
|
+ if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT ||
|
|
|
|
+ (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
|
|
|
|
+ flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) {
|
|
|
|
+ brcmf_fws_return_credits(fws, fifo, 1);
|
|
|
|
+ brcmf_fws_schedule_deq(fws);
|
|
|
|
+ }
|
|
|
|
+ brcmf_fws_macdesc_return_req_credit(skb);
|
2019-02-15 17:43:55 +00:00
|
|
|
+
|
2019-02-12 12:43:06 +00:00
|
|
|
+ ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
|
|
|
|
+ if (ret) {
|
|
|
|
+ brcmu_pkt_buf_free_skb(skb);
|
|
|
|
+ goto cont;
|
|
|
|
+ }
|
|
|
|
+ if (!remove_from_hanger)
|
|
|
|
+ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
|
|
|
|
+ genbit, seq);
|
|
|
|
+ if (remove_from_hanger || ret)
|
|
|
|
+ brcmf_txfinalize(ifp, skb, true);
|
|
|
|
+
|
|
|
|
+cont:
|
|
|
|
+ hslot = (hslot + 1) & (BRCMF_FWS_TXSTAT_HSLOT_MASK >>
|
|
|
|
+ BRCMF_FWS_TXSTAT_HSLOT_SHIFT);
|
|
|
|
+ if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
|
|
|
|
+ seq = (seq + 1) & BRCMF_SKB_HTOD_SEQ_NR_MASK;
|
|
|
|
+
|
|
|
|
+ cnt++;
|
|
|
|
}
|
|
|
|
- if (!remove_from_hanger)
|
|
|
|
- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
|
|
|
|
- genbit, seq);
|
|
|
|
- if (remove_from_hanger || ret)
|
|
|
|
- brcmf_txfinalize(ifp, skb, true);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2019-07-06 22:08:20 +00:00
|
|
|
@@ -1551,7 +1563,8 @@ static int brcmf_fws_fifocreditback_indi
|
2019-02-12 12:43:06 +00:00
|
|
|
return BRCMF_FWS_RET_OK_SCHEDULE;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
|
|
|
|
+static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 type,
|
|
|
|
+ u8 *data)
|
|
|
|
{
|
|
|
|
__le32 status_le;
|
|
|
|
__le16 seq_le;
|
2019-07-06 22:08:20 +00:00
|
|
|
@@ -1560,23 +1573,31 @@ static int brcmf_fws_txstatus_indicate(s
|
2019-02-12 12:43:06 +00:00
|
|
|
u32 genbit;
|
|
|
|
u8 flags;
|
|
|
|
u16 seq;
|
|
|
|
+ u8 compcnt;
|
|
|
|
+ u8 compcnt_offset = BRCMF_FWS_TYPE_TXSTATUS_LEN;
|
|
|
|
|
|
|
|
- fws->stats.txs_indicate++;
|
|
|
|
memcpy(&status_le, data, sizeof(status_le));
|
|
|
|
status = le32_to_cpu(status_le);
|
|
|
|
flags = brcmf_txstatus_get_field(status, FLAGS);
|
|
|
|
hslot = brcmf_txstatus_get_field(status, HSLOT);
|
|
|
|
genbit = brcmf_txstatus_get_field(status, GENERATION);
|
|
|
|
if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
|
|
|
|
- memcpy(&seq_le, &data[BRCMF_FWS_TYPE_PKTTAG_LEN],
|
|
|
|
+ memcpy(&seq_le, &data[BRCMF_FWS_TYPE_TXSTATUS_LEN],
|
|
|
|
sizeof(seq_le));
|
|
|
|
seq = le16_to_cpu(seq_le);
|
|
|
|
+ compcnt_offset += BRCMF_FWS_TYPE_SEQ_LEN;
|
|
|
|
} else {
|
|
|
|
seq = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ if (type == BRCMF_FWS_TYPE_COMP_TXSTATUS)
|
|
|
|
+ compcnt = data[compcnt_offset];
|
|
|
|
+ else
|
|
|
|
+ compcnt = 1;
|
|
|
|
+ fws->stats.txs_indicate += compcnt;
|
|
|
|
+
|
|
|
|
brcmf_fws_lock(fws);
|
|
|
|
- brcmf_fws_txs_process(fws, flags, hslot, genbit, seq);
|
|
|
|
+ brcmf_fws_txs_process(fws, flags, hslot, genbit, seq, compcnt);
|
|
|
|
brcmf_fws_unlock(fws);
|
|
|
|
return BRCMF_FWS_RET_OK_NOSCHEDULE;
|
|
|
|
}
|
2019-07-06 22:08:20 +00:00
|
|
|
@@ -1892,8 +1913,6 @@ void brcmf_fws_hdrpull(struct brcmf_if *
|
2019-02-12 12:43:06 +00:00
|
|
|
|
|
|
|
err = BRCMF_FWS_RET_OK_NOSCHEDULE;
|
|
|
|
switch (type) {
|
|
|
|
- case BRCMF_FWS_TYPE_COMP_TXSTATUS:
|
|
|
|
- break;
|
|
|
|
case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
|
|
|
|
rd = (struct brcmf_skb_reorder_data *)skb->cb;
|
|
|
|
rd->reorder = data;
|
2019-07-06 22:08:20 +00:00
|
|
|
@@ -1916,7 +1935,8 @@ void brcmf_fws_hdrpull(struct brcmf_if *
|
2019-02-12 12:43:06 +00:00
|
|
|
err = brcmf_fws_request_indicate(fws, type, data);
|
|
|
|
break;
|
|
|
|
case BRCMF_FWS_TYPE_TXSTATUS:
|
|
|
|
- brcmf_fws_txstatus_indicate(fws, data);
|
|
|
|
+ case BRCMF_FWS_TYPE_COMP_TXSTATUS:
|
|
|
|
+ brcmf_fws_txstatus_indicate(fws, type, data);
|
|
|
|
break;
|
|
|
|
case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
|
|
|
|
err = brcmf_fws_fifocreditback_indicate(fws, data);
|
2019-07-06 22:08:20 +00:00
|
|
|
@@ -2005,7 +2025,7 @@ static void brcmf_fws_rollback_toq(struc
|
2019-02-12 12:43:06 +00:00
|
|
|
fws->stats.rollback_failed++;
|
|
|
|
hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
|
|
|
|
brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
|
|
|
|
- hslot, 0, 0);
|
|
|
|
+ hslot, 0, 0, 1);
|
|
|
|
} else {
|
|
|
|
fws->stats.rollback_success++;
|
|
|
|
brcmf_fws_return_credits(fws, fifo, 1);
|
2019-07-06 22:08:20 +00:00
|
|
|
@@ -2476,7 +2496,8 @@ void brcmf_fws_bustxfail(struct brcmf_fw
|
2019-02-12 12:43:06 +00:00
|
|
|
}
|
|
|
|
brcmf_fws_lock(fws);
|
|
|
|
hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
|
|
|
|
- brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0);
|
|
|
|
+ brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0,
|
|
|
|
+ 1);
|
|
|
|
brcmf_fws_unlock(fws);
|
|
|
|
}
|
|
|
|
|