linux/drivers/staging/wfx/data_rx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Datapath 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
  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        // Block ack negotiation is offloaded by the firmware. However,
  80        // re-ordering must be done by the mac80211.
  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