/** ****************************************************************************** * * @file rwnx_bfmer.c * * @brief VHT Beamformer function definitions * * Copyright (C) RivieraWaves 2016-2019 * ****************************************************************************** */ /** * INCLUDE FILES ****************************************************************************** */ #include #include "rwnx_bfmer.h" /** * FUNCTION DEFINITIONS ****************************************************************************** */ int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, unsigned int length) { gfp_t flags; struct rwnx_bfmer_report *bfm_report ; if (in_softirq()) flags = GFP_ATOMIC; else flags = GFP_KERNEL; /* Allocate a structure that will contain the beamforming report */ bfm_report = kmalloc(sizeof(*bfm_report) + length, flags); /* Check report allocation */ if (!bfm_report) { /* Do not use beamforming */ return -1; } /* Store report length */ bfm_report->length = length; /* * Need to provide a Virtual Address to the MAC so that it can * upload the received Beamforming Report in driver memory */ bfm_report->dma_addr = dma_map_single(rwnx_hw->dev, &bfm_report->report[0], length, DMA_FROM_DEVICE); /* Check DMA mapping result */ if (dma_mapping_error(rwnx_hw->dev, bfm_report->dma_addr)) { /* Free allocated report */ kfree(bfm_report); /* And leave */ return -1; } /* Store report structure */ rwnx_sta->bfm_report = bfm_report; return 0; } void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) { /* Verify if a report has been allocated */ if (rwnx_sta->bfm_report) { struct rwnx_bfmer_report *bfm_report = rwnx_sta->bfm_report; /* Unmap DMA region */ dma_unmap_single(rwnx_hw->dev, bfm_report->dma_addr, bfm_report->length, DMA_BIDIRECTIONAL); /* Free allocated report structure and clean the pointer */ kfree(bfm_report); rwnx_sta->bfm_report = NULL; } } #ifdef CONFIG_RWNX_FULLMAC u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa) { int i; u8 rx_nss = 0; u16 rx_mcs_map = le16_to_cpu(vht_capa->supp_mcs.rx_mcs_map); for (i = 7; i >= 0; i--) { u8 mcs = (rx_mcs_map >> (2 * i)) & 3; if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) { rx_nss = i + 1; break; } } return rx_nss; } #endif /* CONFIG_RWNX_FULLMAC */