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