106 lines
2.5 KiB
C
106 lines
2.5 KiB
C
/**
|
|
******************************************************************************
|
|
*
|
|
* @file rwnx_bfmer.c
|
|
*
|
|
* @brief VHT Beamformer function definitions
|
|
*
|
|
* Copyright (C) RivieraWaves 2016-2019
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/**
|
|
* INCLUDE FILES
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include <linux/slab.h>
|
|
#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 */
|