wifi: mac80211: support antenna control in injection
authorJohannes Berg <johannes.berg@intel.com>
Wed, 20 Sep 2023 18:25:26 +0000 (21:25 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 25 Sep 2023 07:12:34 +0000 (09:12 +0200)
Support antenna control for injection by parsing the antenna
radiotap field (which may be presented multiple times) and
telling the driver about the resulting antenna bitmap. Of
course there's no guarantee the driver will actually honour
this, just like any other injection control.

If misconfigured, i.e. the injected HT/VHT MCS needs more
chains than antennas are configured, the bitmap is reset to
zero, indicating no selection.

For now this is only set up for two anntenas so we keep more
free bits, but that can be trivially extended if any driver
implements support for it that can deal with hardware with
more antennas.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230920211508.f71001aa4da9.I00ccb762a806ea62bc3d728fa3a0d29f4f285eeb@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/linux/ieee80211.h
include/net/mac80211.h
net/mac80211/tx.c

index f2965ff3d7c156c7fb79a26453720bd9cb981792..3b02f038d5092c6788a2856d8fb8c2dd72fa4c98 100644 (file)
@@ -1705,6 +1705,8 @@ struct ieee80211_mcs_info {
 #define                IEEE80211_HT_MCS_TX_MAX_STREAMS 4
 #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10
 
+#define IEEE80211_HT_MCS_CHAINS(mcs) ((mcs) == 32 ? 1 : (1 + ((mcs) >> 3)))
+
 /*
  * 802.11n D5.0 20.3.5 / 20.6 says:
  * - indices 0 to 7 and 32 are single spatial stream
index d4ef2a605cb40ffb8e2950d90a273944707e8261..72375eceb7862a9062a4153ab5c2b7c2007abd60 100644 (file)
@@ -1178,7 +1178,11 @@ struct ieee80211_tx_info {
                                        u8 use_cts_prot:1;
                                        u8 short_preamble:1;
                                        u8 skip_table:1;
-                                       /* 2 bytes free */
+
+                                       /* for injection only (bitmap) */
+                                       u8 antennas:2;
+
+                                       /* 14 bits free */
                                };
                                /* only needed before rate control */
                                unsigned long jiffies;
index 932516f8cc13966ea011227f65091855ae9c8063..a984fc54644ef555d95a2384394979a577fb54e5 100644 (file)
@@ -2162,6 +2162,11 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
                        rate_found = true;
                        break;
 
+               case IEEE80211_RADIOTAP_ANTENNA:
+                       /* this can appear multiple times, keep a bitmap */
+                       info->control.antennas |= BIT(*iterator.this_arg);
+                       break;
+
                case IEEE80211_RADIOTAP_DATA_RETRIES:
                        rate_retries = *iterator.this_arg;
                        break;
@@ -2256,8 +2261,17 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
                }
 
                if (rate_flags & IEEE80211_TX_RC_MCS) {
+                       /* reset antennas if not enough */
+                       if (IEEE80211_HT_MCS_CHAINS(rate) >
+                                       hweight8(info->control.antennas))
+                               info->control.antennas = 0;
+
                        info->control.rates[0].idx = rate;
                } else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
+                       /* reset antennas if not enough */
+                       if (vht_nss > hweight8(info->control.antennas))
+                               info->control.antennas = 0;
+
                        ieee80211_rate_set_vht(info->control.rates, vht_mcs,
                                               vht_nss);
                } else if (sband) {