0a2b315e2ac34a63d504647b7279fccf2845b672
[librecmc/librecmc.git] /
1 From f66c48af7a110c0d694c4ac4a1257affb272a2ea Mon Sep 17 00:00:00 2001
2 From: Johannes Berg <johannes.berg@intel.com>
3 Date: Mon, 9 Jan 2023 13:07:21 +0200
4 Subject: [PATCH] mac80211: support minimal EHT rate reporting on RX
5
6 Add minimal support for RX EHT rate reporting, not yet
7 adding (modifying) any radiotap headers, just statistics
8 for cfg80211.
9
10 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
11 ---
12  include/net/mac80211.h  | 19 ++++++++++++++++---
13  net/mac80211/rx.c       |  9 +++++++++
14  net/mac80211/sta_info.c |  9 ++++++++-
15  net/mac80211/sta_info.h | 24 ++++++++++++++++++------
16  net/mac80211/util.c     | 13 +++++++++++++
17  5 files changed, 64 insertions(+), 10 deletions(-)
18
19 --- a/include/net/mac80211.h
20 +++ b/include/net/mac80211.h
21 @@ -1477,6 +1477,7 @@ enum mac80211_rx_encoding {
22         RX_ENC_HT,
23         RX_ENC_VHT,
24         RX_ENC_HE,
25 +       RX_ENC_EHT,
26  };
27  
28  /**
29 @@ -1510,7 +1511,7 @@ enum mac80211_rx_encoding {
30   * @antenna: antenna used
31   * @rate_idx: index of data rate into band's supported rates or MCS index if
32   *     HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
33 - * @nss: number of streams (VHT and HE only)
34 + * @nss: number of streams (VHT, HE and EHT only)
35   * @flag: %RX_FLAG_\*
36   * @encoding: &enum mac80211_rx_encoding
37   * @bw: &enum rate_info_bw
38 @@ -1518,6 +1519,8 @@ enum mac80211_rx_encoding {
39   * @he_ru: HE RU, from &enum nl80211_he_ru_alloc
40   * @he_gi: HE GI, from &enum nl80211_he_gi
41   * @he_dcm: HE DCM value
42 + * @eht.ru: EHT RU, from &enum nl80211_eht_ru_alloc
43 + * @eht.gi: EHT GI, from &enum nl80211_eht_gi
44   * @rx_flags: internal RX flags for mac80211
45   * @ampdu_reference: A-MPDU reference number, must be a different value for
46   *     each A-MPDU but the same for each subframe within one A-MPDU
47 @@ -1539,8 +1542,18 @@ struct ieee80211_rx_status {
48         u32 flag;
49         u16 freq: 13, freq_offset: 1;
50         u8 enc_flags;
51 -       u8 encoding:2, bw:3, he_ru:3;
52 -       u8 he_gi:2, he_dcm:1;
53 +       u8 encoding:3, bw:4;
54 +       union {
55 +               struct {
56 +                       u8 he_ru:3;
57 +                       u8 he_gi:2;
58 +                       u8 he_dcm:1;
59 +               };
60 +               struct {
61 +                       u8 ru:4;
62 +                       u8 gi:2;
63 +               } eht;
64 +       };
65         u8 rate_idx;
66         u8 nss;
67         u8 rx_flags;
68 --- a/net/mac80211/rx.c
69 +++ b/net/mac80211/rx.c
70 @@ -5358,6 +5358,15 @@ void ieee80211_rx_list(struct ieee80211_
71                                       status->rate_idx, status->nss))
72                                 goto drop;
73                         break;
74 +               case RX_ENC_EHT:
75 +                       if (WARN_ONCE(status->rate_idx > 15 ||
76 +                                     !status->nss ||
77 +                                     status->nss > 8 ||
78 +                                     status->eht.gi > NL80211_RATE_INFO_EHT_GI_3_2,
79 +                                     "Rate marked as an EHT rate but data is invalid: MCS:%d, NSS:%d, GI:%d\n",
80 +                                     status->rate_idx, status->nss, status->eht.gi))
81 +                               goto drop;
82 +                       break;
83                 default:
84                         WARN_ON_ONCE(1);
85                         fallthrough;
86 --- a/net/mac80211/sta_info.c
87 +++ b/net/mac80211/sta_info.c
88 @@ -4,7 +4,7 @@
89   * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
90   * Copyright 2013-2014  Intel Mobile Communications GmbH
91   * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
92 - * Copyright (C) 2018-2021 Intel Corporation
93 + * Copyright (C) 2018-2022 Intel Corporation
94   */
95  
96  #include <linux/module.h>
97 @@ -2389,6 +2389,13 @@ static void sta_stats_decode_rate(struct
98                 rinfo->he_ru_alloc = STA_STATS_GET(HE_RU, rate);
99                 rinfo->he_dcm = STA_STATS_GET(HE_DCM, rate);
100                 break;
101 +       case STA_STATS_RATE_TYPE_EHT:
102 +               rinfo->flags = RATE_INFO_FLAGS_EHT_MCS;
103 +               rinfo->mcs = STA_STATS_GET(EHT_MCS, rate);
104 +               rinfo->nss = STA_STATS_GET(EHT_NSS, rate);
105 +               rinfo->eht_gi = STA_STATS_GET(EHT_GI, rate);
106 +               rinfo->eht_ru_alloc = STA_STATS_GET(EHT_RU, rate);
107 +               break;
108         }
109  }
110  
111 --- a/net/mac80211/sta_info.h
112 +++ b/net/mac80211/sta_info.h
113 @@ -930,6 +930,7 @@ enum sta_stats_type {
114         STA_STATS_RATE_TYPE_VHT,
115         STA_STATS_RATE_TYPE_HE,
116         STA_STATS_RATE_TYPE_S1G,
117 +       STA_STATS_RATE_TYPE_EHT,
118  };
119  
120  #define STA_STATS_FIELD_HT_MCS         GENMASK( 7,  0)
121 @@ -939,12 +940,16 @@ enum sta_stats_type {
122  #define STA_STATS_FIELD_VHT_NSS                GENMASK( 7,  4)
123  #define STA_STATS_FIELD_HE_MCS         GENMASK( 3,  0)
124  #define STA_STATS_FIELD_HE_NSS         GENMASK( 7,  4)
125 -#define STA_STATS_FIELD_BW             GENMASK(11,  8)
126 -#define STA_STATS_FIELD_SGI            GENMASK(12, 12)
127 -#define STA_STATS_FIELD_TYPE           GENMASK(15, 13)
128 -#define STA_STATS_FIELD_HE_RU          GENMASK(18, 16)
129 -#define STA_STATS_FIELD_HE_GI          GENMASK(20, 19)
130 -#define STA_STATS_FIELD_HE_DCM         GENMASK(21, 21)
131 +#define STA_STATS_FIELD_EHT_MCS                GENMASK( 3,  0)
132 +#define STA_STATS_FIELD_EHT_NSS                GENMASK( 7,  4)
133 +#define STA_STATS_FIELD_BW             GENMASK(12,  8)
134 +#define STA_STATS_FIELD_SGI            GENMASK(13, 13)
135 +#define STA_STATS_FIELD_TYPE           GENMASK(16, 14)
136 +#define STA_STATS_FIELD_HE_RU          GENMASK(19, 17)
137 +#define STA_STATS_FIELD_HE_GI          GENMASK(21, 20)
138 +#define STA_STATS_FIELD_HE_DCM         GENMASK(22, 22)
139 +#define STA_STATS_FIELD_EHT_RU         GENMASK(20, 17)
140 +#define STA_STATS_FIELD_EHT_GI         GENMASK(22, 21)
141  
142  #define STA_STATS_FIELD(_n, _v)                FIELD_PREP(STA_STATS_FIELD_ ## _n, _v)
143  #define STA_STATS_GET(_n, _v)          FIELD_GET(STA_STATS_FIELD_ ## _n, _v)
144 @@ -983,6 +988,13 @@ static inline u32 sta_stats_encode_rate(
145                 r |= STA_STATS_FIELD(HE_RU, s->he_ru);
146                 r |= STA_STATS_FIELD(HE_DCM, s->he_dcm);
147                 break;
148 +       case RX_ENC_EHT:
149 +               r |= STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_EHT);
150 +               r |= STA_STATS_FIELD(EHT_NSS, s->nss);
151 +               r |= STA_STATS_FIELD(EHT_MCS, s->rate_idx);
152 +               r |= STA_STATS_FIELD(EHT_GI, s->eht.gi);
153 +               r |= STA_STATS_FIELD(EHT_RU, s->eht.ru);
154 +               break;
155         default:
156                 WARN_ON(1);
157                 return STA_STATS_RATE_INVALID;
158 --- a/net/mac80211/util.c
159 +++ b/net/mac80211/util.c
160 @@ -3898,6 +3898,19 @@ u64 ieee80211_calculate_rx_timestamp(str
161  
162         /* Fill cfg80211 rate info */
163         switch (status->encoding) {
164 +       case RX_ENC_EHT:
165 +               ri.flags |= RATE_INFO_FLAGS_EHT_MCS;
166 +               ri.mcs = status->rate_idx;
167 +               ri.nss = status->nss;
168 +               ri.eht_ru_alloc = status->eht.ru;
169 +               if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
170 +                       ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
171 +               /* TODO/FIXME: is this right? handle other PPDUs */
172 +               if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
173 +                       mpdu_offset += 2;
174 +                       ts += 36;
175 +               }
176 +               break;
177         case RX_ENC_HE:
178                 ri.flags |= RATE_INFO_FLAGS_HE_MCS;
179                 ri.mcs = status->rate_idx;