hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Datapath implementation.
 *
 * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
 * Copyright (c) 2010, ST-Ericsson
 */
#include <linux/etherdevice.h>
#include <net/mac80211.h>
 
#include "data_rx.h"
#include "wfx.h"
#include "bh.h"
#include "sta.h"
 
static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt)
{
   int params, tid;
 
   if (wfx_api_older_than(wvif->wdev, 3, 6))
       return;
 
   switch (mgmt->u.action.u.addba_req.action_code) {
   case WLAN_ACTION_ADDBA_REQ:
       params = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
       tid = (params & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
       ieee80211_start_rx_ba_session_offl(wvif->vif, mgmt->sa, tid);
       break;
   case WLAN_ACTION_DELBA:
       params = le16_to_cpu(mgmt->u.action.u.delba.params);
       tid = (params &  IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
       ieee80211_stop_rx_ba_session_offl(wvif->vif, mgmt->sa, tid);
       break;
   }
}
 
void wfx_rx_cb(struct wfx_vif *wvif,
          const struct hif_ind_rx *arg, struct sk_buff *skb)
{
   struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb);
   struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
   struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
 
   memset(hdr, 0, sizeof(*hdr));
 
   if (arg->status == HIF_STATUS_RX_FAIL_MIC)
       hdr->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_IV_STRIPPED;
   else if (arg->status)
       goto drop;
 
   if (skb->len < sizeof(struct ieee80211_pspoll)) {
       dev_warn(wvif->wdev->dev, "malformed SDU received\n");
       goto drop;
   }
 
   hdr->band = NL80211_BAND_2GHZ;
   hdr->freq = ieee80211_channel_to_frequency(arg->channel_number,
                          hdr->band);
 
   if (arg->rxed_rate >= 14) {
       hdr->encoding = RX_ENC_HT;
       hdr->rate_idx = arg->rxed_rate - 14;
   } else if (arg->rxed_rate >= 4) {
       hdr->rate_idx = arg->rxed_rate - 2;
   } else {
       hdr->rate_idx = arg->rxed_rate;
   }
 
   if (!arg->rcpi_rssi) {
       hdr->flag |= RX_FLAG_NO_SIGNAL_VAL;
       dev_info(wvif->wdev->dev, "received frame without RSSI data\n");
   }
   hdr->signal = arg->rcpi_rssi / 2 - 110;
   hdr->antenna = 0;
 
   if (arg->encryp)
       hdr->flag |= RX_FLAG_DECRYPTED;
 
   // Block ack negotiation is offloaded by the firmware. However,
   // re-ordering must be done by the mac80211.
   if (ieee80211_is_action(frame->frame_control) &&
       mgmt->u.action.category == WLAN_CATEGORY_BACK &&
       skb->len > IEEE80211_MIN_ACTION_SIZE) {
       wfx_rx_handle_ba(wvif, mgmt);
       goto drop;
   }
 
   ieee80211_rx_irqsafe(wvif->wdev->hw, skb);
   return;
 
drop:
   dev_kfree_skb(skb);
}