Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Data receiving implementation.
0004  *
0005  * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
0006  * Copyright (c) 2010, ST-Ericsson
0007  */
0008 #include <linux/etherdevice.h>
0009 #include <net/mac80211.h>
0010 
0011 #include "data_rx.h"
0012 #include "wfx.h"
0013 #include "bh.h"
0014 #include "sta.h"
0015 
0016 static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt)
0017 {
0018     struct ieee80211_vif *vif = wvif_to_vif(wvif);
0019     int params, tid;
0020 
0021     if (wfx_api_older_than(wvif->wdev, 3, 6))
0022         return;
0023 
0024     switch (mgmt->u.action.u.addba_req.action_code) {
0025     case WLAN_ACTION_ADDBA_REQ:
0026         params = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
0027         tid = (params & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
0028         ieee80211_start_rx_ba_session_offl(vif, mgmt->sa, tid);
0029         break;
0030     case WLAN_ACTION_DELBA:
0031         params = le16_to_cpu(mgmt->u.action.u.delba.params);
0032         tid = (params &  IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
0033         ieee80211_stop_rx_ba_session_offl(vif, mgmt->sa, tid);
0034         break;
0035     }
0036 }
0037 
0038 void wfx_rx_cb(struct wfx_vif *wvif, const struct wfx_hif_ind_rx *arg, struct sk_buff *skb)
0039 {
0040     struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb);
0041     struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
0042     struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
0043 
0044     memset(hdr, 0, sizeof(*hdr));
0045 
0046     if (arg->status == HIF_STATUS_RX_FAIL_MIC)
0047         hdr->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_IV_STRIPPED;
0048     else if (arg->status)
0049         goto drop;
0050 
0051     if (skb->len < sizeof(struct ieee80211_pspoll)) {
0052         dev_warn(wvif->wdev->dev, "malformed SDU received\n");
0053         goto drop;
0054     }
0055 
0056     hdr->band = NL80211_BAND_2GHZ;
0057     hdr->freq = ieee80211_channel_to_frequency(arg->channel_number, hdr->band);
0058 
0059     if (arg->rxed_rate >= 14) {
0060         hdr->encoding = RX_ENC_HT;
0061         hdr->rate_idx = arg->rxed_rate - 14;
0062     } else if (arg->rxed_rate >= 4) {
0063         hdr->rate_idx = arg->rxed_rate - 2;
0064     } else {
0065         hdr->rate_idx = arg->rxed_rate;
0066     }
0067 
0068     if (!arg->rcpi_rssi) {
0069         hdr->flag |= RX_FLAG_NO_SIGNAL_VAL;
0070         dev_info(wvif->wdev->dev, "received frame without RSSI data\n");
0071     }
0072     hdr->signal = arg->rcpi_rssi / 2 - 110;
0073     hdr->antenna = 0;
0074 
0075     if (arg->encryp)
0076         hdr->flag |= RX_FLAG_DECRYPTED;
0077 
0078     /* Block ack negotiation is offloaded by the firmware. However, re-ordering must be done by
0079      * the mac80211.
0080      */
0081     if (ieee80211_is_action(frame->frame_control) &&
0082         mgmt->u.action.category == WLAN_CATEGORY_BACK &&
0083         skb->len > IEEE80211_MIN_ACTION_SIZE) {
0084         wfx_rx_handle_ba(wvif, mgmt);
0085         goto drop;
0086     }
0087 
0088     ieee80211_rx_irqsafe(wvif->wdev->hw, skb);
0089     return;
0090 
0091 drop:
0092     dev_kfree_skb(skb);
0093 }