76f26e3c4381ca87438e6f1d26d99e25f45fad1d
[linux-2.6-microblaze.git] / drivers / staging / wfx / data_tx.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Datapath implementation.
4  *
5  * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
6  * Copyright (c) 2010, ST-Ericsson
7  */
8 #include <net/mac80211.h>
9
10 #include "wfx.h"
11 #include "sta.h"
12 #include "traces.h"
13 #include "hif_tx_mib.h"
14
15 static int wfx_get_hw_rate(struct wfx_dev *wdev,
16                            const struct ieee80211_tx_rate *rate)
17 {
18         struct ieee80211_supported_band *band;
19
20         if (rate->idx < 0)
21                 return -1;
22         if (rate->flags & IEEE80211_TX_RC_MCS) {
23                 if (rate->idx > 7) {
24                         WARN(1, "wrong rate->idx value: %d", rate->idx);
25                         return -1;
26                 }
27                 return rate->idx + 14;
28         }
29         // WFx only support 2GHz, else band information should be retrieved
30         // from ieee80211_tx_info
31         band = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
32         if (rate->idx >= band->n_bitrates) {
33                 WARN(1, "wrong rate->idx value: %d", rate->idx);
34                 return -1;
35         }
36         return band->bitrates[rate->idx].hw_value;
37 }
38
39 /* TX policy cache implementation */
40
41 static void wfx_tx_policy_build(struct wfx_vif *wvif, struct tx_policy *policy,
42                                 struct ieee80211_tx_rate *rates)
43 {
44         struct wfx_dev *wdev = wvif->wdev;
45         int i, rateid;
46         u8 count;
47
48         WARN(rates[0].idx < 0, "invalid rate policy");
49         memset(policy, 0, sizeof(*policy));
50         for (i = 0; i < IEEE80211_TX_MAX_RATES; ++i) {
51                 if (rates[i].idx < 0)
52                         break;
53                 WARN_ON(rates[i].count > 15);
54                 rateid = wfx_get_hw_rate(wdev, &rates[i]);
55                 // Pack two values in each byte of policy->rates
56                 count = rates[i].count;
57                 if (rateid % 2)
58                         count <<= 4;
59                 policy->rates[rateid / 2] |= count;
60         }
61 }
62
63 static bool tx_policy_is_equal(const struct tx_policy *a,
64                                const struct tx_policy *b)
65 {
66         return !memcmp(a->rates, b->rates, sizeof(a->rates));
67 }
68
69 static int wfx_tx_policy_find(struct tx_policy_cache *cache,
70                               struct tx_policy *wanted)
71 {
72         struct tx_policy *it;
73
74         list_for_each_entry(it, &cache->used, link)
75                 if (tx_policy_is_equal(wanted, it))
76                         return it - cache->cache;
77         list_for_each_entry(it, &cache->free, link)
78                 if (tx_policy_is_equal(wanted, it))
79                         return it - cache->cache;
80         return -1;
81 }
82
83 static void wfx_tx_policy_use(struct tx_policy_cache *cache,
84                               struct tx_policy *entry)
85 {
86         ++entry->usage_count;
87         list_move(&entry->link, &cache->used);
88 }
89
90 static int wfx_tx_policy_release(struct tx_policy_cache *cache,
91                                  struct tx_policy *entry)
92 {
93         int ret = --entry->usage_count;
94
95         if (!ret)
96                 list_move(&entry->link, &cache->free);
97         return ret;
98 }
99
100 static int wfx_tx_policy_get(struct wfx_vif *wvif,
101                              struct ieee80211_tx_rate *rates, bool *renew)
102 {
103         int idx;
104         struct tx_policy_cache *cache = &wvif->tx_policy_cache;
105         struct tx_policy wanted;
106
107         wfx_tx_policy_build(wvif, &wanted, rates);
108
109         spin_lock_bh(&cache->lock);
110         if (list_empty(&cache->free)) {
111                 WARN(1, "unable to get a valid Tx policy");
112                 spin_unlock_bh(&cache->lock);
113                 return HIF_TX_RETRY_POLICY_INVALID;
114         }
115         idx = wfx_tx_policy_find(cache, &wanted);
116         if (idx >= 0) {
117                 *renew = false;
118         } else {
119                 struct tx_policy *entry;
120                 *renew = true;
121                 /* If policy is not found create a new one
122                  * using the oldest entry in "free" list
123                  */
124                 entry = list_entry(cache->free.prev, struct tx_policy, link);
125                 memcpy(entry->rates, wanted.rates, sizeof(entry->rates));
126                 entry->uploaded = false;
127                 entry->usage_count = 0;
128                 idx = entry - cache->cache;
129         }
130         wfx_tx_policy_use(cache, &cache->cache[idx]);
131         if (list_empty(&cache->free))
132                 ieee80211_stop_queues(wvif->wdev->hw);
133         spin_unlock_bh(&cache->lock);
134         return idx;
135 }
136
137 static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx)
138 {
139         int usage, locked;
140         struct tx_policy_cache *cache = &wvif->tx_policy_cache;
141
142         if (idx == HIF_TX_RETRY_POLICY_INVALID)
143                 return;
144         spin_lock_bh(&cache->lock);
145         locked = list_empty(&cache->free);
146         usage = wfx_tx_policy_release(cache, &cache->cache[idx]);
147         if (locked && !usage)
148                 ieee80211_wake_queues(wvif->wdev->hw);
149         spin_unlock_bh(&cache->lock);
150 }
151
152 static int wfx_tx_policy_upload(struct wfx_vif *wvif)
153 {
154         struct tx_policy *policies = wvif->tx_policy_cache.cache;
155         u8 tmp_rates[12];
156         int i, is_used;
157
158         do {
159                 spin_lock_bh(&wvif->tx_policy_cache.lock);
160                 for (i = 0; i < ARRAY_SIZE(wvif->tx_policy_cache.cache); ++i) {
161                         is_used = memzcmp(policies[i].rates,
162                                           sizeof(policies[i].rates));
163                         if (!policies[i].uploaded && is_used)
164                                 break;
165                 }
166                 if (i < ARRAY_SIZE(wvif->tx_policy_cache.cache)) {
167                         policies[i].uploaded = true;
168                         memcpy(tmp_rates, policies[i].rates, sizeof(tmp_rates));
169                         spin_unlock_bh(&wvif->tx_policy_cache.lock);
170                         hif_set_tx_rate_retry_policy(wvif, i, tmp_rates);
171                 } else {
172                         spin_unlock_bh(&wvif->tx_policy_cache.lock);
173                 }
174         } while (i < ARRAY_SIZE(wvif->tx_policy_cache.cache));
175         return 0;
176 }
177
178 void wfx_tx_policy_upload_work(struct work_struct *work)
179 {
180         struct wfx_vif *wvif =
181                 container_of(work, struct wfx_vif, tx_policy_upload_work);
182
183         wfx_tx_policy_upload(wvif);
184         wfx_tx_unlock(wvif->wdev);
185 }
186
187 void wfx_tx_policy_init(struct wfx_vif *wvif)
188 {
189         struct tx_policy_cache *cache = &wvif->tx_policy_cache;
190         int i;
191
192         memset(cache, 0, sizeof(*cache));
193
194         spin_lock_init(&cache->lock);
195         INIT_LIST_HEAD(&cache->used);
196         INIT_LIST_HEAD(&cache->free);
197
198         for (i = 0; i < ARRAY_SIZE(cache->cache); ++i)
199                 list_add(&cache->cache[i].link, &cache->free);
200 }
201
202 /* Tx implementation */
203
204 static bool ieee80211_is_action_back(struct ieee80211_hdr *hdr)
205 {
206         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr;
207
208         if (!ieee80211_is_action(mgmt->frame_control))
209                 return false;
210         if (mgmt->u.action.category != WLAN_CATEGORY_BACK)
211                 return false;
212         return true;
213 }
214
215 static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta,
216                              struct ieee80211_hdr *hdr)
217 {
218         struct wfx_sta_priv *sta_priv =
219                 sta ? (struct wfx_sta_priv *)&sta->drv_priv : NULL;
220         const u8 *da = ieee80211_get_DA(hdr);
221
222         if (sta_priv && sta_priv->link_id)
223                 return sta_priv->link_id;
224         if (wvif->vif->type != NL80211_IFTYPE_AP)
225                 return 0;
226         if (is_multicast_ether_addr(da))
227                 return 0;
228         return HIF_LINK_ID_NOT_ASSOCIATED;
229 }
230
231 static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates)
232 {
233         int i;
234         bool finished;
235
236         // Firmware is not able to mix rates with different flags
237         for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
238                 if (rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
239                         rates[i].flags |= IEEE80211_TX_RC_SHORT_GI;
240                 if (!(rates[0].flags & IEEE80211_TX_RC_SHORT_GI))
241                         rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI;
242                 if (!(rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS))
243                         rates[i].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS;
244         }
245
246         // Sort rates and remove duplicates
247         do {
248                 finished = true;
249                 for (i = 0; i < IEEE80211_TX_MAX_RATES - 1; i++) {
250                         if (rates[i + 1].idx == rates[i].idx &&
251                             rates[i].idx != -1) {
252                                 rates[i].count += rates[i + 1].count;
253                                 if (rates[i].count > 15)
254                                         rates[i].count = 15;
255                                 rates[i + 1].idx = -1;
256                                 rates[i + 1].count = 0;
257
258                                 finished = false;
259                         }
260                         if (rates[i + 1].idx > rates[i].idx) {
261                                 swap(rates[i + 1], rates[i]);
262                                 finished = false;
263                         }
264                 }
265         } while (!finished);
266         // Ensure that MCS0 or 1Mbps is present at the end of the retry list
267         for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
268                 if (rates[i].idx == 0)
269                         break;
270                 if (rates[i].idx == -1) {
271                         rates[i].idx = 0;
272                         rates[i].count = 8; // == hw->max_rate_tries
273                         rates[i].flags = rates[i - 1].flags &
274                                          IEEE80211_TX_RC_MCS;
275                         break;
276                 }
277         }
278         // All retries use long GI
279         for (i = 1; i < IEEE80211_TX_MAX_RATES; i++)
280                 rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI;
281 }
282
283 static u8 wfx_tx_get_rate_id(struct wfx_vif *wvif,
284                              struct ieee80211_tx_info *tx_info)
285 {
286         bool tx_policy_renew = false;
287         u8 rate_id;
288
289         rate_id = wfx_tx_policy_get(wvif,
290                                     tx_info->driver_rates, &tx_policy_renew);
291         if (rate_id == HIF_TX_RETRY_POLICY_INVALID)
292                 dev_warn(wvif->wdev->dev, "unable to get a valid Tx policy");
293
294         if (tx_policy_renew) {
295                 wfx_tx_lock(wvif->wdev);
296                 if (!schedule_work(&wvif->tx_policy_upload_work))
297                         wfx_tx_unlock(wvif->wdev);
298         }
299         return rate_id;
300 }
301
302 static int wfx_tx_get_frame_format(struct ieee80211_tx_info *tx_info)
303 {
304         if (!(tx_info->driver_rates[0].flags & IEEE80211_TX_RC_MCS))
305                 return HIF_FRAME_FORMAT_NON_HT;
306         else if (!(tx_info->driver_rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD))
307                 return HIF_FRAME_FORMAT_MIXED_FORMAT_HT;
308         else
309                 return HIF_FRAME_FORMAT_GF_HT_11N;
310 }
311
312 static int wfx_tx_get_icv_len(struct ieee80211_key_conf *hw_key)
313 {
314         int mic_space;
315
316         if (!hw_key)
317                 return 0;
318         if (hw_key->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
319                 return 0;
320         mic_space = (hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) ? 8 : 0;
321         return hw_key->icv_len + mic_space;
322 }
323
324 static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta,
325                         struct sk_buff *skb)
326 {
327         struct hif_msg *hif_msg;
328         struct hif_req_tx *req;
329         struct wfx_tx_priv *tx_priv;
330         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
331         struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
332         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
333         int queue_id = skb_get_queue_mapping(skb);
334         size_t offset = (size_t)skb->data & 3;
335         int wmsg_len = sizeof(struct hif_msg) +
336                         sizeof(struct hif_req_tx) + offset;
337
338         WARN(queue_id >= IEEE80211_NUM_ACS, "unsupported queue_id");
339         wfx_tx_fixup_rates(tx_info->driver_rates);
340
341         // From now tx_info->control is unusable
342         memset(tx_info->rate_driver_data, 0, sizeof(struct wfx_tx_priv));
343         // Fill tx_priv
344         tx_priv = (struct wfx_tx_priv *)tx_info->rate_driver_data;
345         tx_priv->icv_size = wfx_tx_get_icv_len(hw_key);
346
347         // Fill hif_msg
348         WARN(skb_headroom(skb) < wmsg_len, "not enough space in skb");
349         WARN(offset & 1, "attempt to transmit an unaligned frame");
350         skb_put(skb, tx_priv->icv_size);
351         skb_push(skb, wmsg_len);
352         memset(skb->data, 0, wmsg_len);
353         hif_msg = (struct hif_msg *)skb->data;
354         hif_msg->len = cpu_to_le16(skb->len);
355         hif_msg->id = HIF_REQ_ID_TX;
356         hif_msg->interface = wvif->id;
357         if (skb->len > wvif->wdev->hw_caps.size_inp_ch_buf) {
358                 dev_warn(wvif->wdev->dev,
359                          "requested frame size (%d) is larger than maximum supported (%d)\n",
360                          skb->len, wvif->wdev->hw_caps.size_inp_ch_buf);
361                 skb_pull(skb, wmsg_len);
362                 return -EIO;
363         }
364
365         // Fill tx request
366         req = (struct hif_req_tx *)hif_msg->body;
367         // packet_id just need to be unique on device. 32bits are more than
368         // necessary for that task, so we tae advantage of it to add some extra
369         // data for debug.
370         req->packet_id = atomic_add_return(1, &wvif->wdev->packet_id) & 0xFFFF;
371         req->packet_id |= IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)) << 16;
372         req->packet_id |= queue_id << 28;
373
374         req->fc_offset = offset;
375         if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)
376                 req->after_dtim = 1;
377         req->peer_sta_id = wfx_tx_get_link_id(wvif, sta, hdr);
378         // Queue index are inverted between firmware and Linux
379         req->queue_id = 3 - queue_id;
380         req->retry_policy_index = wfx_tx_get_rate_id(wvif, tx_info);
381         req->frame_format = wfx_tx_get_frame_format(tx_info);
382         if (tx_info->driver_rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
383                 req->short_gi = 1;
384
385         // Auxiliary operations
386         wfx_tx_queues_put(wvif, skb);
387         if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)
388                 schedule_work(&wvif->update_tim_work);
389         wfx_bh_request_tx(wvif->wdev);
390         return 0;
391 }
392
393 void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
394             struct sk_buff *skb)
395 {
396         struct wfx_dev *wdev = hw->priv;
397         struct wfx_vif *wvif;
398         struct ieee80211_sta *sta = control ? control->sta : NULL;
399         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
400         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
401         size_t driver_data_room = sizeof_field(struct ieee80211_tx_info,
402                                                rate_driver_data);
403
404         compiletime_assert(sizeof(struct wfx_tx_priv) <= driver_data_room,
405                            "struct tx_priv is too large");
406         WARN(skb->next || skb->prev, "skb is already member of a list");
407         // control.vif can be NULL for injected frames
408         if (tx_info->control.vif)
409                 wvif = (struct wfx_vif *)tx_info->control.vif->drv_priv;
410         else
411                 wvif = wvif_iterate(wdev, NULL);
412         if (WARN_ON(!wvif))
413                 goto drop;
414         // Because of TX_AMPDU_SETUP_IN_HW, mac80211 does not try to send any
415         // BlockAck session management frame. The check below exist just in case.
416         if (ieee80211_is_action_back(hdr)) {
417                 dev_info(wdev->dev, "drop BA action\n");
418                 goto drop;
419         }
420         if (wfx_tx_inner(wvif, sta, skb))
421                 goto drop;
422
423         return;
424
425 drop:
426         ieee80211_tx_status_irqsafe(wdev->hw, skb);
427 }
428
429 static void wfx_skb_dtor(struct wfx_vif *wvif, struct sk_buff *skb)
430 {
431         struct hif_msg *hif = (struct hif_msg *)skb->data;
432         struct hif_req_tx *req = (struct hif_req_tx *)hif->body;
433         unsigned int offset = sizeof(struct hif_msg) +
434                               sizeof(struct hif_req_tx) +
435                               req->fc_offset;
436
437         if (!wvif) {
438                 pr_warn("%s: vif associated with the skb does not exist anymore\n", __func__);
439                 return;
440         }
441         wfx_tx_policy_put(wvif, req->retry_policy_index);
442         skb_pull(skb, offset);
443         ieee80211_tx_status_irqsafe(wvif->wdev->hw, skb);
444 }
445
446 static void wfx_tx_fill_rates(struct wfx_dev *wdev,
447                               struct ieee80211_tx_info *tx_info,
448                               const struct hif_cnf_tx *arg)
449 {
450         struct ieee80211_tx_rate *rate;
451         int tx_count;
452         int i;
453
454         tx_count = arg->ack_failures;
455         if (!arg->status || arg->ack_failures)
456                 tx_count += 1; // Also report success
457         for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
458                 rate = &tx_info->status.rates[i];
459                 if (rate->idx < 0)
460                         break;
461                 if (tx_count < rate->count &&
462                     arg->status == HIF_STATUS_TX_FAIL_RETRIES &&
463                     arg->ack_failures)
464                         dev_dbg(wdev->dev, "all retries were not consumed: %d != %d\n",
465                                 rate->count, tx_count);
466                 if (tx_count <= rate->count && tx_count &&
467                     arg->txed_rate != wfx_get_hw_rate(wdev, rate))
468                         dev_dbg(wdev->dev, "inconsistent tx_info rates: %d != %d\n",
469                                 arg->txed_rate, wfx_get_hw_rate(wdev, rate));
470                 if (tx_count > rate->count) {
471                         tx_count -= rate->count;
472                 } else if (!tx_count) {
473                         rate->count = 0;
474                         rate->idx = -1;
475                 } else {
476                         rate->count = tx_count;
477                         tx_count = 0;
478                 }
479         }
480         if (tx_count)
481                 dev_dbg(wdev->dev, "%d more retries than expected\n", tx_count);
482 }
483
484 void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg)
485 {
486         const struct wfx_tx_priv *tx_priv;
487         struct ieee80211_tx_info *tx_info;
488         struct wfx_vif *wvif;
489         struct sk_buff *skb;
490
491         skb = wfx_pending_get(wdev, arg->packet_id);
492         if (!skb) {
493                 dev_warn(wdev->dev, "received unknown packet_id (%#.8x) from chip\n",
494                          arg->packet_id);
495                 return;
496         }
497         tx_info = IEEE80211_SKB_CB(skb);
498         tx_priv = wfx_skb_tx_priv(skb);
499         wvif = wdev_to_wvif(wdev, ((struct hif_msg *)skb->data)->interface);
500         WARN_ON(!wvif);
501         if (!wvif)
502                 return;
503
504         // Note that wfx_pending_get_pkt_us_delay() get data from tx_info
505         _trace_tx_stats(arg, skb, wfx_pending_get_pkt_us_delay(wdev, skb));
506         wfx_tx_fill_rates(wdev, tx_info, arg);
507         skb_trim(skb, skb->len - tx_priv->icv_size);
508
509         // From now, you can touch to tx_info->status, but do not touch to
510         // tx_priv anymore
511         // FIXME: use ieee80211_tx_info_clear_status()
512         memset(tx_info->rate_driver_data, 0, sizeof(tx_info->rate_driver_data));
513         memset(tx_info->pad, 0, sizeof(tx_info->pad));
514
515         if (!arg->status) {
516                 tx_info->status.tx_time =
517                         le32_to_cpu(arg->media_delay) -
518                         le32_to_cpu(arg->tx_queue_delay);
519                 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
520                         tx_info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
521                 else
522                         tx_info->flags |= IEEE80211_TX_STAT_ACK;
523         } else if (arg->status == HIF_STATUS_TX_FAIL_REQUEUE) {
524                 WARN(!arg->requeue, "incoherent status and result_flags");
525                 if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
526                         wvif->after_dtim_tx_allowed = false; // DTIM period elapsed
527                         schedule_work(&wvif->update_tim_work);
528                 }
529                 tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
530         }
531         wfx_skb_dtor(wvif, skb);
532 }
533
534 static void wfx_flush_vif(struct wfx_vif *wvif, u32 queues,
535                           struct sk_buff_head *dropped)
536 {
537         struct wfx_queue *queue;
538         int i;
539
540         for (i = 0; i < IEEE80211_NUM_ACS; i++) {
541                 if (!(BIT(i) & queues))
542                         continue;
543                 queue = &wvif->tx_queue[i];
544                 if (dropped)
545                         wfx_tx_queue_drop(wvif, queue, dropped);
546         }
547         if (wvif->wdev->chip_frozen)
548                 return;
549         for (i = 0; i < IEEE80211_NUM_ACS; i++) {
550                 if (!(BIT(i) & queues))
551                         continue;
552                 queue = &wvif->tx_queue[i];
553                 if (wait_event_timeout(wvif->wdev->tx_dequeue,
554                                        wfx_tx_queue_empty(wvif, queue),
555                                        msecs_to_jiffies(1000)) <= 0)
556                         dev_warn(wvif->wdev->dev,
557                                  "frames queued while flushing tx queues?");
558         }
559 }
560
561 void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
562                u32 queues, bool drop)
563 {
564         struct wfx_dev *wdev = hw->priv;
565         struct sk_buff_head dropped;
566         struct wfx_vif *wvif;
567         struct hif_msg *hif;
568         struct sk_buff *skb;
569
570         skb_queue_head_init(&dropped);
571         if (vif) {
572                 wvif = (struct wfx_vif *)vif->drv_priv;
573                 wfx_flush_vif(wvif, queues, drop ? &dropped : NULL);
574         } else {
575                 wvif = NULL;
576                 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
577                         wfx_flush_vif(wvif, queues, drop ? &dropped : NULL);
578         }
579         wfx_tx_flush(wdev);
580         if (wdev->chip_frozen)
581                 wfx_pending_drop(wdev, &dropped);
582         while ((skb = skb_dequeue(&dropped)) != NULL) {
583                 hif = (struct hif_msg *)skb->data;
584                 wvif = wdev_to_wvif(wdev, hif->interface);
585                 ieee80211_tx_info_clear_status(IEEE80211_SKB_CB(skb));
586                 wfx_skb_dtor(wvif, skb);
587         }
588 }