d44c8737ad55553b4e00a8fb004b97f98c74463a
[openwrt/staging/xback.git] /
1 From e4af3ffb43d50f070134aa1b40d5c3573f57deb1 Mon Sep 17 00:00:00 2001
2 From: Chung-Hsien Hsu <stanley.hsu@cypress.com>
3 Date: Mon, 5 Nov 2018 05:52:05 +0000
4 Subject: [PATCH] brcmfmac: handle compressed tx status signal
5
6 Firmware inform the driver about tx status by normal tx status signal
7 or compressed tx status signal. This patch adds support to handle the
8 compressed tx status signal.
9
10 Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>
11 Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
12 Signed-off-by: Wright Feng <wright.feng@cypress.com>
13 Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
14 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
15 ---
16 .../broadcom/brcm80211/brcmfmac/fwsignal.c | 121 ++++++++++--------
17 1 file changed, 71 insertions(+), 50 deletions(-)
18
19 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
20 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
21 @@ -1455,9 +1455,10 @@ static int brcmf_fws_txstatus_suppressed
22
23 static int
24 brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
25 - u32 genbit, u16 seq)
26 + u32 genbit, u16 seq, u8 compcnt)
27 {
28 u32 fifo;
29 + u8 cnt = 0;
30 int ret;
31 bool remove_from_hanger = true;
32 struct sk_buff *skb;
33 @@ -1468,60 +1469,71 @@ brcmf_fws_txs_process(struct brcmf_fws_i
34 brcmf_dbg(DATA, "flags %d\n", flags);
35
36 if (flags == BRCMF_FWS_TXSTATUS_DISCARD)
37 - fws->stats.txs_discard++;
38 + fws->stats.txs_discard += compcnt;
39 else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) {
40 - fws->stats.txs_supp_core++;
41 + fws->stats.txs_supp_core += compcnt;
42 remove_from_hanger = false;
43 } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) {
44 - fws->stats.txs_supp_ps++;
45 + fws->stats.txs_supp_ps += compcnt;
46 remove_from_hanger = false;
47 } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED)
48 - fws->stats.txs_tossed++;
49 + fws->stats.txs_tossed += compcnt;
50 else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)
51 - fws->stats.txs_host_tossed++;
52 + fws->stats.txs_host_tossed += compcnt;
53 else
54 brcmf_err("unexpected txstatus\n");
55
56 - ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
57 - remove_from_hanger);
58 - if (ret != 0) {
59 - brcmf_err("no packet in hanger slot: hslot=%d\n", hslot);
60 - return ret;
61 - }
62 + while (cnt < compcnt) {
63 + ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
64 + remove_from_hanger);
65 + if (ret != 0) {
66 + brcmf_err("no packet in hanger slot: hslot=%d\n",
67 + hslot);
68 + goto cont;
69 + }
70
71 - skcb = brcmf_skbcb(skb);
72 - entry = skcb->mac;
73 - if (WARN_ON(!entry)) {
74 - brcmu_pkt_buf_free_skb(skb);
75 - return -EINVAL;
76 - }
77 - entry->transit_count--;
78 - if (entry->suppressed && entry->suppr_transit_count)
79 - entry->suppr_transit_count--;
80 -
81 - brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags,
82 - skcb->htod, seq);
83 -
84 - /* pick up the implicit credit from this packet */
85 - fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
86 - if ((fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT) ||
87 - (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
88 - (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) {
89 - brcmf_fws_return_credits(fws, fifo, 1);
90 - brcmf_fws_schedule_deq(fws);
91 - }
92 - brcmf_fws_macdesc_return_req_credit(skb);
93 + skcb = brcmf_skbcb(skb);
94 + entry = skcb->mac;
95 + if (WARN_ON(!entry)) {
96 + brcmu_pkt_buf_free_skb(skb);
97 + goto cont;
98 + }
99 + entry->transit_count--;
100 + if (entry->suppressed && entry->suppr_transit_count)
101 + entry->suppr_transit_count--;
102
103 - ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
104 - if (ret) {
105 - brcmu_pkt_buf_free_skb(skb);
106 - return -EINVAL;
107 + brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name,
108 + flags, skcb->htod, seq);
109 +
110 + /* pick up the implicit credit from this packet */
111 + fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
112 + if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT ||
113 + (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
114 + flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) {
115 + brcmf_fws_return_credits(fws, fifo, 1);
116 + brcmf_fws_schedule_deq(fws);
117 + }
118 + brcmf_fws_macdesc_return_req_credit(skb);
119 +
120 + ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
121 + if (ret) {
122 + brcmu_pkt_buf_free_skb(skb);
123 + goto cont;
124 + }
125 + if (!remove_from_hanger)
126 + ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
127 + genbit, seq);
128 + if (remove_from_hanger || ret)
129 + brcmf_txfinalize(ifp, skb, true);
130 +
131 +cont:
132 + hslot = (hslot + 1) & (BRCMF_FWS_TXSTAT_HSLOT_MASK >>
133 + BRCMF_FWS_TXSTAT_HSLOT_SHIFT);
134 + if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
135 + seq = (seq + 1) & BRCMF_SKB_HTOD_SEQ_NR_MASK;
136 +
137 + cnt++;
138 }
139 - if (!remove_from_hanger)
140 - ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
141 - genbit, seq);
142 - if (remove_from_hanger || ret)
143 - brcmf_txfinalize(ifp, skb, true);
144
145 return 0;
146 }
147 @@ -1547,7 +1559,8 @@ static int brcmf_fws_fifocreditback_indi
148 return BRCMF_FWS_RET_OK_SCHEDULE;
149 }
150
151 -static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
152 +static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 type,
153 + u8 *data)
154 {
155 __le32 status_le;
156 __le16 seq_le;
157 @@ -1556,23 +1569,31 @@ static int brcmf_fws_txstatus_indicate(s
158 u32 genbit;
159 u8 flags;
160 u16 seq;
161 + u8 compcnt;
162 + u8 compcnt_offset = BRCMF_FWS_TYPE_TXSTATUS_LEN;
163
164 - fws->stats.txs_indicate++;
165 memcpy(&status_le, data, sizeof(status_le));
166 status = le32_to_cpu(status_le);
167 flags = brcmf_txstatus_get_field(status, FLAGS);
168 hslot = brcmf_txstatus_get_field(status, HSLOT);
169 genbit = brcmf_txstatus_get_field(status, GENERATION);
170 if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
171 - memcpy(&seq_le, &data[BRCMF_FWS_TYPE_PKTTAG_LEN],
172 + memcpy(&seq_le, &data[BRCMF_FWS_TYPE_TXSTATUS_LEN],
173 sizeof(seq_le));
174 seq = le16_to_cpu(seq_le);
175 + compcnt_offset += BRCMF_FWS_TYPE_SEQ_LEN;
176 } else {
177 seq = 0;
178 }
179
180 + if (type == BRCMF_FWS_TYPE_COMP_TXSTATUS)
181 + compcnt = data[compcnt_offset];
182 + else
183 + compcnt = 1;
184 + fws->stats.txs_indicate += compcnt;
185 +
186 brcmf_fws_lock(fws);
187 - brcmf_fws_txs_process(fws, flags, hslot, genbit, seq);
188 + brcmf_fws_txs_process(fws, flags, hslot, genbit, seq, compcnt);
189 brcmf_fws_unlock(fws);
190 return BRCMF_FWS_RET_OK_NOSCHEDULE;
191 }
192 @@ -1888,8 +1909,6 @@ void brcmf_fws_hdrpull(struct brcmf_if *
193
194 err = BRCMF_FWS_RET_OK_NOSCHEDULE;
195 switch (type) {
196 - case BRCMF_FWS_TYPE_COMP_TXSTATUS:
197 - break;
198 case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
199 rd = (struct brcmf_skb_reorder_data *)skb->cb;
200 rd->reorder = data;
201 @@ -1912,7 +1931,8 @@ void brcmf_fws_hdrpull(struct brcmf_if *
202 err = brcmf_fws_request_indicate(fws, type, data);
203 break;
204 case BRCMF_FWS_TYPE_TXSTATUS:
205 - brcmf_fws_txstatus_indicate(fws, data);
206 + case BRCMF_FWS_TYPE_COMP_TXSTATUS:
207 + brcmf_fws_txstatus_indicate(fws, type, data);
208 break;
209 case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
210 err = brcmf_fws_fifocreditback_indicate(fws, data);
211 @@ -2001,7 +2021,7 @@ static void brcmf_fws_rollback_toq(struc
212 fws->stats.rollback_failed++;
213 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
214 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
215 - hslot, 0, 0);
216 + hslot, 0, 0, 1);
217 } else {
218 fws->stats.rollback_success++;
219 brcmf_fws_return_credits(fws, fifo, 1);
220 @@ -2462,7 +2482,8 @@ void brcmf_fws_bustxfail(struct brcmf_fw
221 }
222 brcmf_fws_lock(fws);
223 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
224 - brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0);
225 + brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0,
226 + 1);
227 brcmf_fws_unlock(fws);
228 }
229