hc
2024-03-22 a0752693d998599af469473b8dc239ef973a012f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**
 ******************************************************************************
 *
 * @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 */