1 // SPDX-License-Identifier: GPL-2.0-only
3 * Data receiving implementation.
5 * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
6 * Copyright (c) 2010, ST-Ericsson
8 #include <linux/etherdevice.h>
9 #include <net/mac80211.h>
16 static void wfx_rx_handle_ba(struct wfx_vif
*wvif
, struct ieee80211_mgmt
*mgmt
)
18 struct ieee80211_vif
*vif
= wvif_to_vif(wvif
);
21 if (wfx_api_older_than(wvif
->wdev
, 3, 6))
24 switch (mgmt
->u
.action
.u
.addba_req
.action_code
) {
25 case WLAN_ACTION_ADDBA_REQ
:
26 params
= le16_to_cpu(mgmt
->u
.action
.u
.addba_req
.capab
);
27 tid
= (params
& IEEE80211_ADDBA_PARAM_TID_MASK
) >> 2;
28 ieee80211_start_rx_ba_session_offl(vif
, mgmt
->sa
, tid
);
30 case WLAN_ACTION_DELBA
:
31 params
= le16_to_cpu(mgmt
->u
.action
.u
.delba
.params
);
32 tid
= (params
& IEEE80211_DELBA_PARAM_TID_MASK
) >> 12;
33 ieee80211_stop_rx_ba_session_offl(vif
, mgmt
->sa
, tid
);
38 void wfx_rx_cb(struct wfx_vif
*wvif
, const struct wfx_hif_ind_rx
*arg
, struct sk_buff
*skb
)
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
;
44 memset(hdr
, 0, sizeof(*hdr
));
46 if (arg
->status
== HIF_STATUS_RX_FAIL_MIC
)
47 hdr
->flag
|= RX_FLAG_MMIC_ERROR
| RX_FLAG_IV_STRIPPED
;
51 if (skb
->len
< sizeof(struct ieee80211_pspoll
)) {
52 dev_warn(wvif
->wdev
->dev
, "malformed SDU received\n");
56 hdr
->band
= NL80211_BAND_2GHZ
;
57 hdr
->freq
= ieee80211_channel_to_frequency(arg
->channel_number
, hdr
->band
);
59 if (arg
->rxed_rate
>= 14) {
60 hdr
->encoding
= RX_ENC_HT
;
61 hdr
->rate_idx
= arg
->rxed_rate
- 14;
62 } else if (arg
->rxed_rate
>= 4) {
63 hdr
->rate_idx
= arg
->rxed_rate
- 2;
65 hdr
->rate_idx
= arg
->rxed_rate
;
68 if (!arg
->rcpi_rssi
) {
69 hdr
->flag
|= RX_FLAG_NO_SIGNAL_VAL
;
70 dev_info(wvif
->wdev
->dev
, "received frame without RSSI data\n");
72 hdr
->signal
= arg
->rcpi_rssi
/ 2 - 110;
76 hdr
->flag
|= RX_FLAG_DECRYPTED
;
78 /* Block ack negotiation is offloaded by the firmware. However, re-ordering must be done by
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
);
88 ieee80211_rx_irqsafe(wvif
->wdev
->hw
, skb
);