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