* [PATCH v3 0/2] mac80211: extend current rate control tx status API
@ 2022-05-08 15:10 Jonas Jelonek
2022-05-08 15:10 ` [PATCH v3 1/2] " Jonas Jelonek
2022-05-08 15:10 ` [PATCH v3 2/2] mac80211: minstrel_ht: support ieee80211_rate_status Jonas Jelonek
0 siblings, 2 replies; 4+ messages in thread
From: Jonas Jelonek @ 2022-05-08 15:10 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, nbd, johannes, thomas.huehn, Jonas Jelonek
This patch series extends the current rate control tx status API.
ieee80211_tx_info has a fixed limit in size (SKB_CB) and its ieee80211_tx_rate
is not suitable to annotate e.g. the mcs rate set from IEEE 802.11ax nor
additional per packet information like tx-power.
The commit 18fb84d986b3 introduced the extended on-stack struct
ieee80211_tx_status, which makes the tx status API more extensible.
With this patch we introduce a new struct ieee80211_rate_status that extends
current rate control tx status API further, in order to achieve:
(1) receive tx power status feedback for transmit power control per
packet or packet retry
(2) dynamic mapping of wifi chip specific multi-rate retry (mrr) chains
with different lengths
(3) increase the limit of annotatable rate indices to support
IEEE802.11ax rate sets and beyond
(1) cannot be achieved with the use of struct ieee80211_tx_info because both
control and status buffer have a fixed SKB_CB size limit. E.g. the current
control buffer size would only allow tx-power annotations per packet,
not per mrr chain. The status buffer has no free space left. Struct
ieee80211_tx_status is intended to add such extensions.
(2) is motivated by the varying length of mrr chains in common wireless
hardware supported by Linux. E.g. Atheros chipsets support four mrr chain
stages, mediatek chips vary from a single mrr chain stage up to 8 stages, all
with specific restrictions in rate configuration, retry count and tx-power
control ability.
Currently the number of mrr chain stages is fixed to 4 (defined by
IEEE80211_TX_MAX_RATES). Although this value could be increased, a change
would affect all wireless drivers and probably cause additional problems.
Therefore we introduce a dynamic-sized solution that supports different
numbers of mrr chain stages hence a dynamic allocation of chain stages
supported by different wifi chipsets.
(3) The current struct ieee80211_tx_info uses a s8 integer for rate idx,
which would be to less for e.g. IEEE802.11ax rate annotations. To overcome
this limitation, we introduce struct rate_info from cfg80211.h. This struct
is not limited to annotate rates hence addressing rates up to 802.11ax and
also future rate sets are usable.
Our new struct is intended for all information related to RC and TPC that
needs to be passed from driver to mac80211 and its RC/TPC algorithms like
Minstrel_HT. Multiple instances of this struct can be included in struct
ieee80211_tx_status via a pointer and a length variable. Those can be
allocated on-stack. The former reference to a single instance of struct
rate_info is replaced with our new annotation.
Compile-Tested: current wireless-next tree with all flags on
Tested-on: Xiaomi 4A Gigabit (MediaTek MT7603E, MT7612E) with
OpenWrt Linux 5.10.113
---
v3: - Changed concept of handling different tx power level steps
- Fixed some minor incorrect changes
- Adjusted changes in mt76
v2: Fixed some typos and a missing ! in changes in status.c
---
Jonas Jelonek (2):
mac80211: extend current rate control tx status API
mac80211: minstrel_ht: support ieee80211_rate_status
drivers/net/wireless/mediatek/mt76/tx.c | 5 +-
include/net/mac80211.h | 33 +++++-
net/mac80211/rc80211_minstrel_ht.c | 138 ++++++++++++++++++++++--
net/mac80211/rc80211_minstrel_ht.h | 2 +-
net/mac80211/status.c | 91 +++++++++-------
5 files changed, 216 insertions(+), 53 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v3 1/2] mac80211: extend current rate control tx status API
2022-05-08 15:10 [PATCH v3 0/2] mac80211: extend current rate control tx status API Jonas Jelonek
@ 2022-05-08 15:10 ` Jonas Jelonek
2022-05-08 17:58 ` kernel test robot
2022-05-08 15:10 ` [PATCH v3 2/2] mac80211: minstrel_ht: support ieee80211_rate_status Jonas Jelonek
1 sibling, 1 reply; 4+ messages in thread
From: Jonas Jelonek @ 2022-05-08 15:10 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, nbd, johannes, thomas.huehn, Jonas Jelonek
This patch adds the new struct ieee80211_rate_status and replaces
'struct rate_info *rate' in ieee80211_tx_status with pointer and length
annotation.
The struct ieee80211_rate_status allows to:
(1) receive tx power status feedback for transmit power control (TPC)
per packet or packet retry
(2) dynamic mapping of wifi chip specific multi-rate retry (mrr)
chains with different lengths
(3) increase the limit of annotatable rate indices to support
IEEE802.11ac rate sets and beyond
ieee80211_tx_info, control and status buffer, and ieee80211_tx_rate
cannot be used to achieve these goals due to fixed size limitations.
Our new struct contains a struct rate_info to annotate the rate that was
used, retry count of the rate and tx power. It is intended for all
information related to RC and TPC that needs to be passed from driver to
mac80211 and its RC/TPC algorithms like Minstrel_HT. It corresponds to
one stage in an mrr. Multiple subsequent instances of this struct can be
included in struct ieee80211_tx_status via a pointer and a length variable.
Those instances can be allocated on-stack. The former reference to a single
instance of struct rate_info is replaced with our new annotation.
An extension is introduced to struct ieee80211_hw. There are two new
members called 'tx_power_levels' and 'max_txpwr_levels_idx' acting as a
tx power level table. When a wifi device is registered, the driver shall
supply all supported power levels in this list. This allows to support
several quirks like differing power steps in power level ranges or
alike. TPC can use this for algorithm and thus be designed more abstract
instead of handling all possible step widths individually.
Further mandatory changes in status.c and mt76 driver due to the
removal of 'struct rate_info *rate' are also included.
status.c already uses the information in ieee80211_tx_status->rate in
radiotap, this is now changed to use ieee80211_rate_status->rate_idx.
mt76 driver already uses struct rate_info to pass the tx rate to status
path. The new members of the ieee80211_tx_status are set to NULL and 0
because the previously passed rate is not relevant to rate control and
accurate information is passed via tx_info->status.rates.
Compile-Tested: current wireless-next tree with all flags on
Tested-on: Xiaomi 4A Gigabit (MediaTek MT7603E, MT7612E) with OpenWrt
Linux 5.10.83
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
---
drivers/net/wireless/mediatek/mt76/tx.c | 5 +-
include/net/mac80211.h | 33 ++++++++-
net/mac80211/status.c | 91 ++++++++++++++-----------
3 files changed, 85 insertions(+), 44 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 6b8c9dc80542..b49ef6619829 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -66,9 +66,8 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
wcid = rcu_dereference(dev->wcid[cb->wcid]);
if (wcid) {
status.sta = wcid_to_sta(wcid);
-
- if (status.sta)
- status.rate = &wcid->rate;
+ status.rates = NULL;
+ status.n_rates = 0;
}
hw = mt76_tx_status_get_hw(dev, skb);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c50221d7e82c..54455c8249c2 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1131,20 +1131,41 @@ ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info)
return info->tx_time_est << 2;
}
+/***
+ * struct ieee80211_rate_status - mrr stage for status path
+ *
+ * This struct is used in struct ieee80211_tx_status to provide drivers a
+ * dynamic way to report about used rates and power levels per packet.
+ *
+ * @rate_idx The actual used rate.
+ * @try_count How often the rate was tried.
+ * @tx_power_idx An idx into the ieee80211_hw->tx_power_levels list of the
+ * corresponding wifi hardware. The idx shall point to the power level
+ * that was used when sending the packet.
+ */
+struct ieee80211_rate_status {
+ struct rate_info rate_idx;
+ u8 try_count;
+ u8 tx_power_idx;
+};
+
/**
* struct ieee80211_tx_status - extended tx status info for rate control
*
* @sta: Station that the packet was transmitted for
* @info: Basic tx status information
* @skb: Packet skb (can be NULL if not provided by the driver)
- * @rate: The TX rate that was used when sending the packet
+ * @rates: Mrr stages that were used when sending the packet
+ * @n_rates: Number of mrr stages (count of instances for @rates)
* @free_list: list where processed skbs are stored to be free'd by the driver
*/
struct ieee80211_tx_status {
struct ieee80211_sta *sta;
struct ieee80211_tx_info *info;
struct sk_buff *skb;
- struct rate_info *rate;
+ struct ieee80211_rate_status *rates;
+ u8 n_rates;
+
struct list_head *free_list;
};
@@ -2601,6 +2622,12 @@ enum ieee80211_hw_flags {
* refilling deficit of each TXQ.
*
* @max_mtu: the max mtu could be set.
+ *
+ * @tx_power_levels: a list of power levels supported by the wifi hardware.
+ * The power levels can be specified either as integer or fractions.
+ * The power level at idx 0 shall be the maximum positive power level.
+ *
+ * @max_txpwr_levels_idx: the maximum valid idx of 'tx_power_levels' list.
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -2639,6 +2666,8 @@ struct ieee80211_hw {
u8 tx_sk_pacing_shift;
u8 weight_multiplier;
u32 max_mtu;
+ const s8 *tx_power_levels;
+ u8 max_txpwr_levels_idx;
};
static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index f6f63a0b1b72..fc6f88ab648b 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -246,15 +246,19 @@ static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info,
struct ieee80211_tx_status *status)
{
+ struct ieee80211_rate_status *status_rate = NULL;
int len = sizeof(struct ieee80211_radiotap_header);
+ if (status && status->n_rates)
+ status_rate = &status->rates[status->n_rates - 1];
+
/* IEEE80211_RADIOTAP_RATE rate */
- if (status && status->rate && !(status->rate->flags &
- (RATE_INFO_FLAGS_MCS |
- RATE_INFO_FLAGS_DMG |
- RATE_INFO_FLAGS_EDMG |
- RATE_INFO_FLAGS_VHT_MCS |
- RATE_INFO_FLAGS_HE_MCS)))
+ if (status_rate && !(status_rate->rate_idx.flags &
+ (RATE_INFO_FLAGS_MCS |
+ RATE_INFO_FLAGS_DMG |
+ RATE_INFO_FLAGS_EDMG |
+ RATE_INFO_FLAGS_VHT_MCS |
+ RATE_INFO_FLAGS_HE_MCS)))
len += 2;
else if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags &
@@ -269,12 +273,12 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info,
/* IEEE80211_RADIOTAP_MCS
* IEEE80211_RADIOTAP_VHT */
- if (status && status->rate) {
- if (status->rate->flags & RATE_INFO_FLAGS_MCS)
+ if (status_rate) {
+ if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_MCS)
len += 3;
- else if (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS)
+ else if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS)
len = ALIGN(len, 2) + 12;
- else if (status->rate->flags & RATE_INFO_FLAGS_HE_MCS)
+ else if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_HE_MCS)
len = ALIGN(len, 2) + 12;
} else if (info->status.rates[0].idx >= 0) {
if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
@@ -296,10 +300,14 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_radiotap_header *rthdr;
+ struct ieee80211_rate_status *status_rate = NULL;
unsigned char *pos;
u16 legacy_rate = 0;
u16 txflags;
+ if (status && status->n_rates)
+ status_rate = &status->rates[status->n_rates - 1];
+
rthdr = skb_push(skb, rtap_len);
memset(rthdr, 0, rtap_len);
@@ -317,13 +325,14 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
/* IEEE80211_RADIOTAP_RATE */
- if (status && status->rate) {
- if (!(status->rate->flags & (RATE_INFO_FLAGS_MCS |
- RATE_INFO_FLAGS_DMG |
- RATE_INFO_FLAGS_EDMG |
- RATE_INFO_FLAGS_VHT_MCS |
- RATE_INFO_FLAGS_HE_MCS)))
- legacy_rate = status->rate->legacy;
+ if (status_rate) {
+ if (!(status_rate->rate_idx.flags &
+ (RATE_INFO_FLAGS_MCS |
+ RATE_INFO_FLAGS_DMG |
+ RATE_INFO_FLAGS_EDMG |
+ RATE_INFO_FLAGS_VHT_MCS |
+ RATE_INFO_FLAGS_HE_MCS)))
+ legacy_rate = status_rate->rate_idx.legacy;
} else if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
IEEE80211_TX_RC_VHT_MCS)))
@@ -356,20 +365,21 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
*pos = retry_count;
pos++;
- if (status && status->rate &&
- (status->rate->flags & RATE_INFO_FLAGS_MCS)) {
+ if (status_rate && (status_rate->rate_idx.flags & RATE_INFO_FLAGS_MCS))
+ {
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_MCS));
pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
IEEE80211_RADIOTAP_MCS_HAVE_GI |
IEEE80211_RADIOTAP_MCS_HAVE_BW;
- if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_SHORT_GI)
pos[1] |= IEEE80211_RADIOTAP_MCS_SGI;
- if (status->rate->bw == RATE_INFO_BW_40)
+ if (status_rate->rate_idx.bw == RATE_INFO_BW_40)
pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40;
- pos[2] = status->rate->mcs;
+ pos[2] = status_rate->rate_idx.mcs;
pos += 3;
- } else if (status && status->rate &&
- (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS)) {
+ } else if (status_rate && (status_rate->rate_idx.flags &
+ RATE_INFO_FLAGS_VHT_MCS))
+ {
u16 known = local->hw.radiotap_vht_details &
(IEEE80211_RADIOTAP_VHT_KNOWN_GI |
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
@@ -384,12 +394,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
pos += 2;
/* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */
- if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_SHORT_GI)
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
pos++;
/* u8 bandwidth */
- switch (status->rate->bw) {
+ switch (status_rate->rate_idx.bw) {
case RATE_INFO_BW_160:
*pos = 11;
break;
@@ -406,7 +416,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
pos++;
/* u8 mcs_nss[4] */
- *pos = (status->rate->mcs << 4) | status->rate->nss;
+ *pos = (status_rate->rate_idx.mcs << 4) |
+ status_rate->rate_idx.nss;
pos += 4;
/* u8 coding */
@@ -415,8 +426,9 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
pos++;
/* u16 partial_aid */
pos += 2;
- } else if (status && status->rate &&
- (status->rate->flags & RATE_INFO_FLAGS_HE_MCS)) {
+ } else if (status_rate && (status_rate->rate_idx.flags &
+ RATE_INFO_FLAGS_HE_MCS))
+ {
struct ieee80211_radiotap_he *he;
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_HE));
@@ -434,7 +446,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
#define HE_PREP(f, val) le16_encode_bits(val, IEEE80211_RADIOTAP_HE_##f)
- he->data6 |= HE_PREP(DATA6_NSTS, status->rate->nss);
+ he->data6 |= HE_PREP(DATA6_NSTS, status_rate->rate_idx.nss);
#define CHECK_GI(s) \
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_GI_##s != \
@@ -444,12 +456,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
CHECK_GI(1_6);
CHECK_GI(3_2);
- he->data3 |= HE_PREP(DATA3_DATA_MCS, status->rate->mcs);
- he->data3 |= HE_PREP(DATA3_DATA_DCM, status->rate->he_dcm);
+ he->data3 |= HE_PREP(DATA3_DATA_MCS, status_rate->rate_idx.mcs);
+ he->data3 |= HE_PREP(DATA3_DATA_DCM, status_rate->rate_idx.he_dcm);
- he->data5 |= HE_PREP(DATA5_GI, status->rate->he_gi);
+ he->data5 |= HE_PREP(DATA5_GI, status_rate->rate_idx.he_gi);
- switch (status->rate->bw) {
+ switch (status_rate->rate_idx.bw) {
case RATE_INFO_BW_20:
he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ);
@@ -480,16 +492,16 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
CHECK_RU_ALLOC(2x996);
he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
- status->rate->he_ru_alloc + 4);
+ status_rate->rate_idx.he_ru_alloc + 4);
break;
default:
- WARN_ONCE(1, "Invalid SU BW %d\n", status->rate->bw);
+ WARN_ONCE(1, "Invalid SU BW %d\n", status_rate->rate_idx.bw);
}
pos += sizeof(struct ieee80211_radiotap_he);
}
- if ((status && status->rate) || info->status.rates[0].idx < 0)
+ if (status_rate || info->status.rates[0].idx < 0)
return;
/* IEEE80211_RADIOTAP_MCS
@@ -1108,8 +1120,9 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
if (pubsta) {
sta = container_of(pubsta, struct sta_info, sta);
- if (status->rate)
- sta->tx_stats.last_rate_info = *status->rate;
+ if (status->rates)
+ sta->tx_stats.last_rate_info =
+ status->rates[status->n_rates - 1].rate_idx;
}
if (skb && (tx_time_est =
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/2] mac80211: minstrel_ht: support ieee80211_rate_status
2022-05-08 15:10 [PATCH v3 0/2] mac80211: extend current rate control tx status API Jonas Jelonek
2022-05-08 15:10 ` [PATCH v3 1/2] " Jonas Jelonek
@ 2022-05-08 15:10 ` Jonas Jelonek
1 sibling, 0 replies; 4+ messages in thread
From: Jonas Jelonek @ 2022-05-08 15:10 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, nbd, johannes, thomas.huehn, Jonas Jelonek
This patch adds support for the new struct ieee80211_rate_status and its
annotation in struct ieee80211_tx_status in minstrel_ht.
In minstrel_ht_tx_status, a check for the presence of instances of the
new struct in ieee80211_tx_status is added. Based on this, minstrel_ht
then gets and updates internal rate stats with either struct
ieee80211_rate_status or ieee80211_tx_info->status.rates.
Adjusted variants of minstrel_ht_txstat_valid, minstrel_ht_get_stats,
minstrel_{ht/vht}_get_group_idx are added which use struct
ieee80211_rate_status and struct rate_info instead of the legacy structs.
struct rate_info from cfg80211.h does not provide whether short preamble
was used for the transmission. So we retrieve this information from VIF
and STA configuration and cache it in a new flag in struct minstrel_ht_sta
per rate control instance.
Compile-Tested: current wireless-next tree with all flags on
Tested-on: Xiaomi 4A Gigabit (MediaTek MT7603E, MT7612E) with OpenWrt
Linux 5.10.83
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
---
net/mac80211/rc80211_minstrel_ht.c | 138 +++++++++++++++++++++++++++--
net/mac80211/rc80211_minstrel_ht.h | 2 +-
2 files changed, 131 insertions(+), 9 deletions(-)
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 9c3b7fc377c1..e6300c80b0d0 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -333,6 +333,16 @@ minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
!!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
}
+/*
+ * Look up an MCS group index based on new cfg80211 rate_info.
+ */
+static int
+minstrel_ht_ri_get_group_idx(struct rate_info *rate) {
+ return GROUP_IDX((rate->mcs / 8) + 1,
+ !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI),
+ !!(rate->bw & RATE_INFO_BW_40));
+}
+
static int
minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
{
@@ -342,6 +352,17 @@ minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
2*!!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH));
}
+/*
+ * Look up an MCS group index based on new cfg80211 rate_info.
+ */
+static int
+minstrel_vht_ri_get_group_idx(struct rate_info *rate) {
+ return VHT_GROUP_IDX(rate->nss,
+ !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI),
+ !!(rate->bw & RATE_INFO_BW_40) +
+ 2*!!(rate->bw & RATE_INFO_BW_80));
+}
+
static struct minstrel_rate_stats *
minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
struct ieee80211_tx_rate *rate)
@@ -382,6 +403,50 @@ minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
return &mi->groups[group].rates[idx];
}
+/*
+ * Get the minstrel rate statistics for specified STA and rate info.
+ */
+static struct minstrel_rate_stats *
+minstrel_ht_ri_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ struct ieee80211_rate_status *rate_status)
+{
+ int group, idx;
+ struct rate_info *rate = &rate_status->rate_idx;
+
+ if (rate->flags & RATE_INFO_FLAGS_MCS) {
+ group = minstrel_ht_ri_get_group_idx(rate);
+ idx = rate->mcs % 8;
+ goto out;
+ }
+
+ if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) {
+ group = minstrel_vht_ri_get_group_idx(rate);
+ idx = rate->mcs;
+ goto out;
+ }
+
+ group = MINSTREL_CCK_GROUP;
+ for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) {
+ if (rate->legacy != minstrel_cck_bitrates[ mp->cck_rates[idx] ])
+ continue;
+
+ /* short preamble */
+ if ((mi->supported[group] & BIT(idx + 4)) &&
+ mi->use_short_preamble)
+ idx += 4;
+ goto out;
+ }
+
+ group = MINSTREL_OFDM_GROUP;
+ for (idx = 0; idx < ARRAY_SIZE(mp->ofdm_rates[0]); idx++)
+ if (rate->legacy == minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][idx] ])
+ goto out;
+
+ idx = 0;
+out:
+ return &mi->groups[group].rates[idx];
+}
+
static inline struct minstrel_rate_stats *
minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
{
@@ -1149,6 +1214,40 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
return false;
}
+/*
+ * Check whether rate_status contains valid information.
+ */
+static bool
+minstrel_ht_ri_txstat_valid(struct minstrel_priv *mp,
+ struct minstrel_ht_sta *mi,
+ struct ieee80211_rate_status *rate_status)
+{
+ int i;
+
+ if (!rate_status)
+ return false;
+ if (!rate_status->try_count)
+ return false;
+
+ if (rate_status->rate_idx.flags & RATE_INFO_FLAGS_MCS ||
+ rate_status->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS)
+ return true;
+
+ for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) {
+ if (rate_status->rate_idx.legacy ==
+ minstrel_cck_bitrates[ mp->cck_rates[i] ])
+ return true;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates); i++) {
+ if (rate_status->rate_idx.legacy ==
+ minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][i] ])
+ return true;
+ }
+
+ return false;
+}
+
static void
minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
{
@@ -1214,16 +1313,34 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
mi->ampdu_packets++;
mi->ampdu_len += info->status.ampdu_len;
- last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]);
- for (i = 0; !last; i++) {
- last = (i == IEEE80211_TX_MAX_RATES - 1) ||
- !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
+ if (st->rates && st->n_rates) {
+ last = !minstrel_ht_ri_txstat_valid(mp, mi, &(st->rates[0]));
+ for (i = 0; !last; i++) {
+ last = (i == st->n_rates - 1) ||
+ !minstrel_ht_ri_txstat_valid(mp, mi,
+ &(st->rates[i + 1]));
+
+ rate = minstrel_ht_ri_get_stats(mp, mi,
+ &(st->rates[i]));
+
+ if (last)
+ rate->success += info->status.ampdu_ack_len;
+
+ rate->attempts += st->rates[i].try_count *
+ info->status.ampdu_len;
+ }
+ } else {
+ last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]);
+ for (i = 0; !last; i++) {
+ last = (i == IEEE80211_TX_MAX_RATES - 1) ||
+ !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
- rate = minstrel_ht_get_stats(mp, mi, &ar[i]);
- if (last)
- rate->success += info->status.ampdu_ack_len;
+ rate = minstrel_ht_get_stats(mp, mi, &ar[i]);
+ if (last)
+ rate->success += info->status.ampdu_ack_len;
- rate->attempts += ar[i].count * info->status.ampdu_len;
+ rate->attempts += ar[i].count * info->status.ampdu_len;
+ }
}
if (mp->hw->max_rates > 1) {
@@ -1576,6 +1693,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
{
struct minstrel_priv *mp = priv;
struct minstrel_ht_sta *mi = priv_sta;
+ struct sta_info *sta_info;
struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
u16 ht_cap = sta->ht_cap.cap;
struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
@@ -1698,6 +1816,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
n_supported++;
}
+ sta_info = container_of(sta, struct sta_info, sta);
+ mi->use_short_preamble = test_sta_flag(sta_info, WLAN_STA_SHORT_PREAMBLE) &&
+ sta_info->sdata->vif.bss_conf.use_short_preamble;
+
minstrel_ht_update_cck(mp, mi, sband, sta);
minstrel_ht_update_ofdm(mp, mi, sband, sta);
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 06e7126727ad..1766ff0c78d3 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -180,7 +180,7 @@ struct minstrel_ht_sta {
/* tx flags to add for frames for this sta */
u32 tx_flags;
-
+ bool use_short_preamble;
u8 band;
u8 sample_seq;
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 1/2] mac80211: extend current rate control tx status API
2022-05-08 15:10 ` [PATCH v3 1/2] " Jonas Jelonek
@ 2022-05-08 17:58 ` kernel test robot
0 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2022-05-08 17:58 UTC (permalink / raw)
To: Jonas Jelonek, linux-wireless
Cc: kbuild-all, kvalo, nbd, johannes, thomas.huehn, Jonas Jelonek
Hi Jonas,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on wireless/main]
[also build test ERROR on v5.18-rc5]
[cannot apply to wireless-next/main next-20220506]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/intel-lab-lkp/linux/commits/Jonas-Jelonek/mac80211-extend-current-rate-control-tx-status-API/20220508-231356
base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git main
config: i386-randconfig-a005 (https://download.01.org/0day-ci/archive/20220509/202205090141.egLK4ZdI-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.2.0-20) 11.2.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/4241dcd99dd1ea39739668850806abcd249f8535
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Jonas-Jelonek/mac80211-extend-current-rate-control-tx-status-API/20220508-231356
git checkout 4241dcd99dd1ea39739668850806abcd249f8535
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/net/wireless/ath/ath11k/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
drivers/net/wireless/ath/ath11k/dp_tx.c: In function 'ath11k_dp_tx_complete_msdu':
>> drivers/net/wireless/ath/ath11k/dp_tx.c:606:16: error: 'struct ieee80211_tx_status' has no member named 'rate'; did you mean 'rates'?
606 | status.rate = &rate;
| ^~~~
| rates
vim +606 drivers/net/wireless/ath/ath11k/dp_tx.c
1b8bb94c0612cf Wen Gong 2021-12-20 517
d5c65159f28953 Kalle Valo 2019-11-23 518 static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
d5c65159f28953 Kalle Valo 2019-11-23 519 struct sk_buff *msdu,
d5c65159f28953 Kalle Valo 2019-11-23 520 struct hal_tx_status *ts)
d5c65159f28953 Kalle Valo 2019-11-23 521 {
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 522 struct ieee80211_tx_status status = { 0 };
d5c65159f28953 Kalle Valo 2019-11-23 523 struct ath11k_base *ab = ar->ab;
d5c65159f28953 Kalle Valo 2019-11-23 524 struct ieee80211_tx_info *info;
d5c65159f28953 Kalle Valo 2019-11-23 525 struct ath11k_skb_cb *skb_cb;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 526 struct ath11k_peer *peer;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 527 struct ath11k_sta *arsta;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 528 struct rate_info rate;
d5c65159f28953 Kalle Valo 2019-11-23 529
d5c65159f28953 Kalle Valo 2019-11-23 530 if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
d5c65159f28953 Kalle Valo 2019-11-23 531 /* Must not happen */
d5c65159f28953 Kalle Valo 2019-11-23 532 return;
d5c65159f28953 Kalle Valo 2019-11-23 533 }
d5c65159f28953 Kalle Valo 2019-11-23 534
d5c65159f28953 Kalle Valo 2019-11-23 535 skb_cb = ATH11K_SKB_CB(msdu);
d5c65159f28953 Kalle Valo 2019-11-23 536
d5c65159f28953 Kalle Valo 2019-11-23 537 dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
d5c65159f28953 Kalle Valo 2019-11-23 538
bcef57ea400cc2 P Praneesh 2021-11-12 539 if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) {
d5c65159f28953 Kalle Valo 2019-11-23 540 dev_kfree_skb_any(msdu);
bcef57ea400cc2 P Praneesh 2021-11-12 541 return;
d5c65159f28953 Kalle Valo 2019-11-23 542 }
d5c65159f28953 Kalle Valo 2019-11-23 543
bcef57ea400cc2 P Praneesh 2021-11-12 544 if (unlikely(!skb_cb->vif)) {
d5c65159f28953 Kalle Valo 2019-11-23 545 dev_kfree_skb_any(msdu);
bcef57ea400cc2 P Praneesh 2021-11-12 546 return;
d5c65159f28953 Kalle Valo 2019-11-23 547 }
d5c65159f28953 Kalle Valo 2019-11-23 548
d5c65159f28953 Kalle Valo 2019-11-23 549 info = IEEE80211_SKB_CB(msdu);
d5c65159f28953 Kalle Valo 2019-11-23 550 memset(&info->status, 0, sizeof(info->status));
d5c65159f28953 Kalle Valo 2019-11-23 551
d5c65159f28953 Kalle Valo 2019-11-23 552 /* skip tx rate update from ieee80211_status*/
d5c65159f28953 Kalle Valo 2019-11-23 553 info->status.rates[0].idx = -1;
d5c65159f28953 Kalle Valo 2019-11-23 554
d5c65159f28953 Kalle Valo 2019-11-23 555 if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED &&
d5c65159f28953 Kalle Valo 2019-11-23 556 !(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
d5c65159f28953 Kalle Valo 2019-11-23 557 info->flags |= IEEE80211_TX_STAT_ACK;
d5c65159f28953 Kalle Valo 2019-11-23 558 info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR +
d5c65159f28953 Kalle Valo 2019-11-23 559 ts->ack_rssi;
ea5907db2a9ccf Avraham Stern 2022-02-02 560 info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
d5c65159f28953 Kalle Valo 2019-11-23 561 }
d5c65159f28953 Kalle Valo 2019-11-23 562
d5c65159f28953 Kalle Valo 2019-11-23 563 if (ts->status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX &&
d5c65159f28953 Kalle Valo 2019-11-23 564 (info->flags & IEEE80211_TX_CTL_NO_ACK))
d5c65159f28953 Kalle Valo 2019-11-23 565 info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
d5c65159f28953 Kalle Valo 2019-11-23 566
1b8bb94c0612cf Wen Gong 2021-12-20 567 if (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar)) ||
1b8bb94c0612cf Wen Gong 2021-12-20 568 ab->hw_params.single_pdev_only) {
d5c65159f28953 Kalle Valo 2019-11-23 569 if (ts->flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) {
d5c65159f28953 Kalle Valo 2019-11-23 570 if (ar->last_ppdu_id == 0) {
d5c65159f28953 Kalle Valo 2019-11-23 571 ar->last_ppdu_id = ts->ppdu_id;
d5c65159f28953 Kalle Valo 2019-11-23 572 } else if (ar->last_ppdu_id == ts->ppdu_id ||
d5c65159f28953 Kalle Valo 2019-11-23 573 ar->cached_ppdu_id == ar->last_ppdu_id) {
d5c65159f28953 Kalle Valo 2019-11-23 574 ar->cached_ppdu_id = ar->last_ppdu_id;
d5c65159f28953 Kalle Valo 2019-11-23 575 ar->cached_stats.is_ampdu = true;
1b8bb94c0612cf Wen Gong 2021-12-20 576 ath11k_dp_tx_update_txcompl(ar, ts);
d5c65159f28953 Kalle Valo 2019-11-23 577 memset(&ar->cached_stats, 0,
d5c65159f28953 Kalle Valo 2019-11-23 578 sizeof(struct ath11k_per_peer_tx_stats));
d5c65159f28953 Kalle Valo 2019-11-23 579 } else {
d5c65159f28953 Kalle Valo 2019-11-23 580 ar->cached_stats.is_ampdu = false;
1b8bb94c0612cf Wen Gong 2021-12-20 581 ath11k_dp_tx_update_txcompl(ar, ts);
d5c65159f28953 Kalle Valo 2019-11-23 582 memset(&ar->cached_stats, 0,
d5c65159f28953 Kalle Valo 2019-11-23 583 sizeof(struct ath11k_per_peer_tx_stats));
d5c65159f28953 Kalle Valo 2019-11-23 584 }
d5c65159f28953 Kalle Valo 2019-11-23 585 ar->last_ppdu_id = ts->ppdu_id;
d5c65159f28953 Kalle Valo 2019-11-23 586 }
d5c65159f28953 Kalle Valo 2019-11-23 587
d5c65159f28953 Kalle Valo 2019-11-23 588 ath11k_dp_tx_cache_peer_stats(ar, msdu, ts);
d5c65159f28953 Kalle Valo 2019-11-23 589 }
d5c65159f28953 Kalle Valo 2019-11-23 590
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 591 spin_lock_bh(&ab->base_lock);
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 592 peer = ath11k_peer_find_by_id(ab, ts->peer_id);
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 593 if (!peer || !peer->sta) {
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 594 ath11k_dbg(ab, ATH11K_DBG_DATA,
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 595 "dp_tx: failed to find the peer with peer_id %d\n",
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 596 ts->peer_id);
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 597 spin_unlock_bh(&ab->base_lock);
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 598 dev_kfree_skb_any(msdu);
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 599 return;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 600 }
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 601 arsta = (struct ath11k_sta *)peer->sta->drv_priv;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 602 status.sta = peer->sta;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 603 status.skb = msdu;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 604 status.info = info;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 605 rate = arsta->last_txrate;
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 @606 status.rate = &rate;
d5c65159f28953 Kalle Valo 2019-11-23 607
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 608 spin_unlock_bh(&ab->base_lock);
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 609
94739d45c388c5 Pradeep Kumar Chitrapu 2022-02-16 610 ieee80211_tx_status_ext(ar->hw, &status);
d5c65159f28953 Kalle Valo 2019-11-23 611 }
d5c65159f28953 Kalle Valo 2019-11-23 612
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-05-08 19:13 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-08 15:10 [PATCH v3 0/2] mac80211: extend current rate control tx status API Jonas Jelonek
2022-05-08 15:10 ` [PATCH v3 1/2] " Jonas Jelonek
2022-05-08 17:58 ` kernel test robot
2022-05-08 15:10 ` [PATCH v3 2/2] mac80211: minstrel_ht: support ieee80211_rate_status Jonas Jelonek
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.