1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Data receiving implementation. 4 * 5 * Copyright (c) 2017-2020, Silicon Laboratories, Inc. 6 * Copyright (c) 2010, ST-Ericsson 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 16 static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt) 17 { 18 struct ieee80211_vif *vif = wvif_to_vif(wvif); 19 int params, tid; 20 21 if (wfx_api_older_than(wvif->wdev, 3, 6)) 22 return; 23 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); 29 break; 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); 34 break; 35 } 36 } 37 38 void wfx_rx_cb(struct wfx_vif *wvif, const struct wfx_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, hdr->band); 58 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; 64 } else { 65 hdr->rate_idx = arg->rxed_rate; 66 } 67 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"); 71 } 72 hdr->signal = arg->rcpi_rssi / 2 - 110; 73 hdr->antenna = 0; 74 75 if (arg->encryp) 76 hdr->flag |= RX_FLAG_DECRYPTED; 77 78 /* Block ack negotiation is offloaded by the firmware. However, re-ordering must be done by 79 * the mac80211. 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 91 drop: 92 dev_kfree_skb(skb); 93 } 94