f7e09ecaab52bfa39351192c202ca82f3915ca2b
[oweals/openwrt.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 +               skcb = brcmf_skbcb(skb);
81 +               entry = skcb->mac;
82 +               if (WARN_ON(!entry)) {
83 +                       brcmu_pkt_buf_free_skb(skb);
84 +                       goto cont;
85 +               }
86 +               entry->transit_count--;
87 +               if (entry->suppressed && entry->suppr_transit_count)
88 +                       entry->suppr_transit_count--;
89  
90 -       brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags,
91 -                 skcb->htod, seq);
92 +               brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name,
93 +                         flags, skcb->htod, seq);
94  
95 -       /* pick up the implicit credit from this packet */
96 -       fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
97 -       if ((fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT) ||
98 -           (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
99 -           (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) {
100 -               brcmf_fws_return_credits(fws, fifo, 1);
101 -               brcmf_fws_schedule_deq(fws);
102 -       }
103 -       brcmf_fws_macdesc_return_req_credit(skb);
104 +               /* pick up the implicit credit from this packet */
105 +               fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
106 +               if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT ||
107 +                   (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
108 +                   flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) {
109 +                       brcmf_fws_return_credits(fws, fifo, 1);
110 +                       brcmf_fws_schedule_deq(fws);
111 +               }
112 +               brcmf_fws_macdesc_return_req_credit(skb);
113  
114 -       ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
115 -       if (ret) {
116 -               brcmu_pkt_buf_free_skb(skb);
117 -               return -EINVAL;
118 +               ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
119 +               if (ret) {
120 +                       brcmu_pkt_buf_free_skb(skb);
121 +                       goto cont;
122 +               }
123 +               if (!remove_from_hanger)
124 +                       ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
125 +                                                           genbit, seq);
126 +               if (remove_from_hanger || ret)
127 +                       brcmf_txfinalize(ifp, skb, true);
128 +
129 +cont:
130 +               hslot = (hslot + 1) & (BRCMF_FWS_TXSTAT_HSLOT_MASK >>
131 +                                      BRCMF_FWS_TXSTAT_HSLOT_SHIFT);
132 +               if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
133 +                       seq = (seq + 1) & BRCMF_SKB_HTOD_SEQ_NR_MASK;
134 +
135 +               cnt++;
136         }
137 -       if (!remove_from_hanger)
138 -               ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
139 -                                                   genbit, seq);
140 -       if (remove_from_hanger || ret)
141 -               brcmf_txfinalize(ifp, skb, true);
142  
143         return 0;
144  }
145 @@ -1547,7 +1559,8 @@ static int brcmf_fws_fifocreditback_indi
146         return BRCMF_FWS_RET_OK_SCHEDULE;
147  }
148  
149 -static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
150 +static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 type,
151 +                                      u8 *data)
152  {
153         __le32 status_le;
154         __le16 seq_le;
155 @@ -1556,23 +1569,31 @@ static int brcmf_fws_txstatus_indicate(s
156         u32 genbit;
157         u8 flags;
158         u16 seq;
159 +       u8 compcnt;
160 +       u8 compcnt_offset = BRCMF_FWS_TYPE_TXSTATUS_LEN;
161  
162 -       fws->stats.txs_indicate++;
163         memcpy(&status_le, data, sizeof(status_le));
164         status = le32_to_cpu(status_le);
165         flags = brcmf_txstatus_get_field(status, FLAGS);
166         hslot = brcmf_txstatus_get_field(status, HSLOT);
167         genbit = brcmf_txstatus_get_field(status, GENERATION);
168         if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
169 -               memcpy(&seq_le, &data[BRCMF_FWS_TYPE_PKTTAG_LEN],
170 +               memcpy(&seq_le, &data[BRCMF_FWS_TYPE_TXSTATUS_LEN],
171                        sizeof(seq_le));
172                 seq = le16_to_cpu(seq_le);
173 +               compcnt_offset += BRCMF_FWS_TYPE_SEQ_LEN;
174         } else {
175                 seq = 0;
176         }
177  
178 +       if (type == BRCMF_FWS_TYPE_COMP_TXSTATUS)
179 +               compcnt = data[compcnt_offset];
180 +       else
181 +               compcnt = 1;
182 +       fws->stats.txs_indicate += compcnt;
183 +
184         brcmf_fws_lock(fws);
185 -       brcmf_fws_txs_process(fws, flags, hslot, genbit, seq);
186 +       brcmf_fws_txs_process(fws, flags, hslot, genbit, seq, compcnt);
187         brcmf_fws_unlock(fws);
188         return BRCMF_FWS_RET_OK_NOSCHEDULE;
189  }
190 @@ -1888,8 +1909,6 @@ void brcmf_fws_hdrpull(struct brcmf_if *
191  
192                 err = BRCMF_FWS_RET_OK_NOSCHEDULE;
193                 switch (type) {
194 -               case BRCMF_FWS_TYPE_COMP_TXSTATUS:
195 -                       break;
196                 case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
197                         rd = (struct brcmf_skb_reorder_data *)skb->cb;
198                         rd->reorder = data;
199 @@ -1912,7 +1931,8 @@ void brcmf_fws_hdrpull(struct brcmf_if *
200                         err = brcmf_fws_request_indicate(fws, type, data);
201                         break;
202                 case BRCMF_FWS_TYPE_TXSTATUS:
203 -                       brcmf_fws_txstatus_indicate(fws, data);
204 +               case BRCMF_FWS_TYPE_COMP_TXSTATUS:
205 +                       brcmf_fws_txstatus_indicate(fws, type, data);
206                         break;
207                 case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
208                         err = brcmf_fws_fifocreditback_indicate(fws, data);
209 @@ -2001,7 +2021,7 @@ static void brcmf_fws_rollback_toq(struc
210                 fws->stats.rollback_failed++;
211                 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
212                 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
213 -                                     hslot, 0, 0);
214 +                                     hslot, 0, 0, 1);
215         } else {
216                 fws->stats.rollback_success++;
217                 brcmf_fws_return_credits(fws, fifo, 1);
218 @@ -2462,7 +2482,8 @@ void brcmf_fws_bustxfail(struct brcmf_fw
219         }
220         brcmf_fws_lock(fws);
221         hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
222 -       brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0);
223 +       brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0,
224 +                             1);
225         brcmf_fws_unlock(fws);
226  }
227