diff mbox series

[v3,4/5] rtw88: add set_bitrate_mask support

Message ID 20191022100420.25116-5-yhchuang@realtek.com (mailing list archive)
State Accepted
Commit f39e9bd49a3d612a2489b774265107f61ffd82fa
Delegated to: Kalle Valo
Headers show
Series rtw88: minor throughput improvement | expand

Commit Message

Tony Chuang Oct. 22, 2019, 10:04 a.m. UTC
From: Tzu-En Huang <tehuang@realtek.com>

Support setting bit rate from upper layer.
After configuring the original rate control result in the driver, the
result is then masked by the bit rate mask received from the ops
set_bitrate_mask. Lastly, the masked result will be sent to firmware.

Signed-off-by: Tzu-En Huang <tehuang@realtek.com>
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---

v1 -> v2
  * No change

v2 -> v3
  * use u64_encode_bits

 drivers/net/wireless/realtek/rtw88/mac80211.c | 53 +++++++++++++
 drivers/net/wireless/realtek/rtw88/main.c     | 78 +++++++++++++++----
 drivers/net/wireless/realtek/rtw88/main.h     |  3 +
 3 files changed, 118 insertions(+), 16 deletions(-)

Comments

Chris Chiu Oct. 22, 2019, 12:49 p.m. UTC | #1
On Tue, Oct 22, 2019 at 6:04 PM <yhchuang@realtek.com> wrote:
>
> From: Tzu-En Huang <tehuang@realtek.com>
>
> Support setting bit rate from upper layer.
> After configuring the original rate control result in the driver, the
> result is then masked by the bit rate mask received from the ops
> set_bitrate_mask. Lastly, the masked result will be sent to firmware.
>
> Signed-off-by: Tzu-En Huang <tehuang@realtek.com>
> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
> ---
>
> v1 -> v2
>   * No change
>
> v2 -> v3
>   * use u64_encode_bits
>
>  drivers/net/wireless/realtek/rtw88/mac80211.c | 53 +++++++++++++
>  drivers/net/wireless/realtek/rtw88/main.c     | 78 +++++++++++++++----
>  drivers/net/wireless/realtek/rtw88/main.h     |  3 +
>  3 files changed, 118 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
> index bc04cc280a96..2247bd61e716 100644
> --- a/drivers/net/wireless/realtek/rtw88/mac80211.c
> +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
> @@ -684,6 +686,56 @@ static void rtw_ops_flush(struct ieee80211_hw *hw,
>         mutex_unlock(&rtwdev->mutex);
>  }
>
> +struct rtw_iter_bitrate_mask_data {
> +       struct rtw_dev *rtwdev;
> +       struct ieee80211_vif *vif;
> +       const struct cfg80211_bitrate_mask *mask;
> +};
> +
> +static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
> +{
> +       struct rtw_iter_bitrate_mask_data *br_data = data;
> +       struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
> +
> +       if (si->vif != br_data->vif)
> +               return;
> +
> +       /* free previous mask setting */
> +       kfree(si->mask);

You may want to do NULL check for si->mask before kfree.

> +       si->mask = kmemdup(br_data->mask, sizeof(struct cfg80211_bitrate_mask),
> +                          GFP_ATOMIC);
> +       if (!si->mask) {
> +               si->use_cfg_mask = false;
> +               return;
> +       }
> +
> +       si->use_cfg_mask = true;
> +       rtw_update_sta_info(br_data->rtwdev, si);
> +}
> +
> diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
> index 47e74f0aec06..e53143132a9b 100644
> --- a/drivers/net/wireless/realtek/rtw88/main.c
> +++ b/drivers/net/wireless/realtek/rtw88/main.c
> @@ -612,12 +612,71 @@ static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num)
>  #define RA_MASK_OFDM_IN_HT_2G  0x00010
>  #define RA_MASK_OFDM_IN_HT_5G  0x00030
>
> +static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev,
> +                               struct rtw_sta_info *si,
> +                               u64 ra_mask, bool is_vht_enable,
> +                               u8 wireless_set)
> +{
> +       struct rtw_hal *hal = &rtwdev->hal;
> +       const struct cfg80211_bitrate_mask *mask = si->mask;
> +       u64 cfg_mask = GENMASK(63, 0);
> +       u8 rssi_level, band;
> +
> +       if (wireless_set != WIRELESS_CCK) {
> +               rssi_level = si->rssi_level;
> +               if (rssi_level == 0)
> +                       ra_mask &= 0xffffffffffffffffULL;
> +               else if (rssi_level == 1)
> +                       ra_mask &= 0xfffffffffffffff0ULL;
> +               else if (rssi_level == 2)
> +                       ra_mask &= 0xffffffffffffefe0ULL;
> +               else if (rssi_level == 3)
> +                       ra_mask &= 0xffffffffffffcfc0ULL;
> +               else if (rssi_level == 4)
> +                       ra_mask &= 0xffffffffffff8f80ULL;
> +               else if (rssi_level >= 5)
> +                       ra_mask &= 0xffffffffffff0f00ULL;
> +       }

Would be better to enumerate rssi_level instead of 0 to 5. Does level
0 means bad rssi or good?

> --
> 2.17.1
>
Ping-Ke Shih Oct. 23, 2019, 12:47 a.m. UTC | #2
> -----Original Message-----
> From: linux-wireless-owner@vger.kernel.org [mailto:linux-wireless-owner@vger.kernel.org] On Behalf
> Of Chris Chiu
> Sent: Tuesday, October 22, 2019 8:49 PM
> To: Tony Chuang
> Cc: Kalle Valo; linux-wireless; Brian Norris
> Subject: Re: [PATCH v3 4/5] rtw88: add set_bitrate_mask support
> 
> On Tue, Oct 22, 2019 at 6:04 PM <yhchuang@realtek.com> wrote:
> >
> > From: Tzu-En Huang <tehuang@realtek.com>
> >
> > Support setting bit rate from upper layer.
> > After configuring the original rate control result in the driver, the
> > result is then masked by the bit rate mask received from the ops
> > set_bitrate_mask. Lastly, the masked result will be sent to firmware.
> >
> > Signed-off-by: Tzu-En Huang <tehuang@realtek.com>
> > Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
> > ---
> >
> > v1 -> v2
> >   * No change
> >
> > v2 -> v3
> >   * use u64_encode_bits
> >
> >  drivers/net/wireless/realtek/rtw88/mac80211.c | 53 +++++++++++++
> >  drivers/net/wireless/realtek/rtw88/main.c     | 78 +++++++++++++++----
> >  drivers/net/wireless/realtek/rtw88/main.h     |  3 +
> >  3 files changed, 118 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c
> b/drivers/net/wireless/realtek/rtw88/mac80211.c
> > index bc04cc280a96..2247bd61e716 100644
> > --- a/drivers/net/wireless/realtek/rtw88/mac80211.c
> > +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
> > @@ -684,6 +686,56 @@ static void rtw_ops_flush(struct ieee80211_hw *hw,
> >         mutex_unlock(&rtwdev->mutex);
> >  }
> >
> > +struct rtw_iter_bitrate_mask_data {
> > +       struct rtw_dev *rtwdev;
> > +       struct ieee80211_vif *vif;
> > +       const struct cfg80211_bitrate_mask *mask;
> > +};
> > +
> > +static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
> > +{
> > +       struct rtw_iter_bitrate_mask_data *br_data = data;
> > +       struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
> > +
> > +       if (si->vif != br_data->vif)
> > +               return;
> > +
> > +       /* free previous mask setting */
> > +       kfree(si->mask);
> 
> You may want to do NULL check for si->mask before kfree.

kfree checks NULL by itself, and checkpatch also warns this kind of needless checking.

> 
> > +       si->mask = kmemdup(br_data->mask, sizeof(struct cfg80211_bitrate_mask),
> > +                          GFP_ATOMIC);
> > +       if (!si->mask) {
> > +               si->use_cfg_mask = false;
> > +               return;
> > +       }
> > +
> > +       si->use_cfg_mask = true;
> > +       rtw_update_sta_info(br_data->rtwdev, si);
> > +}
> > +
> > diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
> > index 47e74f0aec06..e53143132a9b 100644
> > --- a/drivers/net/wireless/realtek/rtw88/main.c
> > +++ b/drivers/net/wireless/realtek/rtw88/main.c
> > @@ -612,12 +612,71 @@ static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num)
> >  #define RA_MASK_OFDM_IN_HT_2G  0x00010
> >  #define RA_MASK_OFDM_IN_HT_5G  0x00030
> >
> > +static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev,
> > +                               struct rtw_sta_info *si,
> > +                               u64 ra_mask, bool is_vht_enable,
> > +                               u8 wireless_set)
> > +{
> > +       struct rtw_hal *hal = &rtwdev->hal;
> > +       const struct cfg80211_bitrate_mask *mask = si->mask;
> > +       u64 cfg_mask = GENMASK(63, 0);
> > +       u8 rssi_level, band;
> > +
> > +       if (wireless_set != WIRELESS_CCK) {
> > +               rssi_level = si->rssi_level;
> > +               if (rssi_level == 0)
> > +                       ra_mask &= 0xffffffffffffffffULL;
> > +               else if (rssi_level == 1)
> > +                       ra_mask &= 0xfffffffffffffff0ULL;
> > +               else if (rssi_level == 2)
> > +                       ra_mask &= 0xffffffffffffefe0ULL;
> > +               else if (rssi_level == 3)
> > +                       ra_mask &= 0xffffffffffffcfc0ULL;
> > +               else if (rssi_level == 4)
> > +                       ra_mask &= 0xffffffffffff8f80ULL;
> > +               else if (rssi_level >= 5)
> > +                       ra_mask &= 0xffffffffffff0f00ULL;
> > +       }
> 
> Would be better to enumerate rssi_level instead of 0 to 5. Does level
> 0 means bad rssi or good?
> 
> > --
> > 2.17.1
> >
> 
> ------Please consider the environment before printing this e-mail.
Tony Chuang Oct. 23, 2019, 2:37 a.m. UTC | #3
> [mailto:linux-wireless-owner@vger.kernel.org] On Behalf
> > Of Chris Chiu
> > Sent: Tuesday, October 22, 2019 8:49 PM
> > To: Tony Chuang
> > Cc: Kalle Valo; linux-wireless; Brian Norris
> > Subject: Re: [PATCH v3 4/5] rtw88: add set_bitrate_mask support
> >
> > On Tue, Oct 22, 2019 at 6:04 PM <yhchuang@realtek.com> wrote:
> > >
> > > From: Tzu-En Huang <tehuang@realtek.com>
> > >
> > > Support setting bit rate from upper layer.
> > > After configuring the original rate control result in the driver, the
> > > result is then masked by the bit rate mask received from the ops
> > > set_bitrate_mask. Lastly, the masked result will be sent to firmware.
> > >
> > > Signed-off-by: Tzu-En Huang <tehuang@realtek.com>
> > > Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
> > > ---
> > >
> > > v1 -> v2
> > >   * No change
> > >
> > > v2 -> v3
> > >   * use u64_encode_bits
> > >
> > >  drivers/net/wireless/realtek/rtw88/mac80211.c | 53 +++++++++++++
> > >  drivers/net/wireless/realtek/rtw88/main.c     | 78
> +++++++++++++++----
> > >  drivers/net/wireless/realtek/rtw88/main.h     |  3 +
> > >  3 files changed, 118 insertions(+), 16 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c
> > b/drivers/net/wireless/realtek/rtw88/mac80211.c
> > > index bc04cc280a96..2247bd61e716 100644
> > > --- a/drivers/net/wireless/realtek/rtw88/mac80211.c
> > > +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
> > > @@ -684,6 +686,56 @@ static void rtw_ops_flush(struct ieee80211_hw
> *hw,
> > >         mutex_unlock(&rtwdev->mutex);
> > >  }
> > >
> > > +struct rtw_iter_bitrate_mask_data {
> > > +       struct rtw_dev *rtwdev;
> > > +       struct ieee80211_vif *vif;
> > > +       const struct cfg80211_bitrate_mask *mask;
> > > +};
> > > +
> > > +static void rtw_ra_mask_info_update_iter(void *data, struct
> ieee80211_sta *sta)
> > > +{
> > > +       struct rtw_iter_bitrate_mask_data *br_data = data;
> > > +       struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
> > > +
> > > +       if (si->vif != br_data->vif)
> > > +               return;
> > > +
> > > +       /* free previous mask setting */
> > > +       kfree(si->mask);
> >
> > You may want to do NULL check for si->mask before kfree.
> 
> kfree checks NULL by itself, and checkpatch also warns this kind of needless
> checking.
> 
> >
> > > +       si->mask = kmemdup(br_data->mask, sizeof(struct
> cfg80211_bitrate_mask),
> > > +                          GFP_ATOMIC);
> > > +       if (!si->mask) {
> > > +               si->use_cfg_mask = false;
> > > +               return;
> > > +       }
> > > +
> > > +       si->use_cfg_mask = true;
> > > +       rtw_update_sta_info(br_data->rtwdev, si);
> > > +}
> > > +
> > > diff --git a/drivers/net/wireless/realtek/rtw88/main.c
> b/drivers/net/wireless/realtek/rtw88/main.c
> > > index 47e74f0aec06..e53143132a9b 100644
> > > --- a/drivers/net/wireless/realtek/rtw88/main.c
> > > +++ b/drivers/net/wireless/realtek/rtw88/main.c
> > > @@ -612,12 +612,71 @@ static u8 get_rate_id(u8 wireless_set, enum
> rtw_bandwidth bw_mode, u8 tx_num)
> > >  #define RA_MASK_OFDM_IN_HT_2G  0x00010
> > >  #define RA_MASK_OFDM_IN_HT_5G  0x00030
> > >
> > > +static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev,
> > > +                               struct rtw_sta_info *si,
> > > +                               u64 ra_mask, bool is_vht_enable,
> > > +                               u8 wireless_set)
> > > +{
> > > +       struct rtw_hal *hal = &rtwdev->hal;
> > > +       const struct cfg80211_bitrate_mask *mask = si->mask;
> > > +       u64 cfg_mask = GENMASK(63, 0);
> > > +       u8 rssi_level, band;
> > > +
> > > +       if (wireless_set != WIRELESS_CCK) {
> > > +               rssi_level = si->rssi_level;
> > > +               if (rssi_level == 0)
> > > +                       ra_mask &= 0xffffffffffffffffULL;
> > > +               else if (rssi_level == 1)
> > > +                       ra_mask &= 0xfffffffffffffff0ULL;
> > > +               else if (rssi_level == 2)
> > > +                       ra_mask &= 0xffffffffffffefe0ULL;
> > > +               else if (rssi_level == 3)
> > > +                       ra_mask &= 0xffffffffffffcfc0ULL;
> > > +               else if (rssi_level == 4)
> > > +                       ra_mask &= 0xffffffffffff8f80ULL;
> > > +               else if (rssi_level >= 5)
> > > +                       ra_mask &= 0xffffffffffff0f00ULL;
> > > +       }
> >
> > Would be better to enumerate rssi_level instead of 0 to 5. Does level
> > 0 means bad rssi or good?
> >

I think 0 is the lowest level. And I think we don't need to add an enum for
this kind of levels, as the number just presents the meaning of it.

Yan-Hsuan
Chris Chiu Oct. 23, 2019, 3:15 a.m. UTC | #4
Tony Chuang <yhchuang@realtek.com> 於 2019年10月23日 上午10:37 寫道:

>> [mailto:linux-wireless-owner@vger.kernel.org] On Behalf
>>> Of Chris Chiu
>>> Sent: Tuesday, October 22, 2019 8:49 PM
>>> To: Tony Chuang
>>> Cc: Kalle Valo; linux-wireless; Brian Norris
>>> Subject: Re: [PATCH v3 4/5] rtw88: add set_bitrate_mask support
>>> 
>>>> On Tue, Oct 22, 2019 at 6:04 PM <yhchuang@realtek.com> wrote:
>>>> 
>>>> From: Tzu-En Huang <tehuang@realtek.com>
>>>> 
>>>> Support setting bit rate from upper layer.
>>>> After configuring the original rate control result in the driver, the
>>>> result is then masked by the bit rate mask received from the ops
>>>> set_bitrate_mask. Lastly, the masked result will be sent to firmware.
>>>> 
>>>> Signed-off-by: Tzu-En Huang <tehuang@realtek.com>
>>>> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
Reviewed-by: Chris Chiu <chiu@endlessm.com>

>>>> ---
>>>> 
>>>> v1 -> v2
>>>>  * No change
>>>> 
>>>> v2 -> v3
>>>>  * use u64_encode_bits
>>>> 
>>>> +static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev,
>>>> +                               struct rtw_sta_info *si,
>>>> +                               u64 ra_mask, bool is_vht_enable,
>>>> +                               u8 wireless_set)
>>>> +{
>>>> +       struct rtw_hal *hal = &rtwdev->hal;
>>>> +       const struct cfg80211_bitrate_mask *mask = si->mask;
>>>> +       u64 cfg_mask = GENMASK(63, 0);
>>>> +       u8 rssi_level, band;
>>>> +
>>>> +       if (wireless_set != WIRELESS_CCK) {
>>>> +               rssi_level = si->rssi_level;
>>>> +               if (rssi_level == 0)
>>>> +                       ra_mask &= 0xffffffffffffffffULL;
>>>> +               else if (rssi_level == 1)
>>>> +                       ra_mask &= 0xfffffffffffffff0ULL;
>>>> +               else if (rssi_level == 2)
>>>> +                       ra_mask &= 0xffffffffffffefe0ULL;
>>>> +               else if (rssi_level == 3)
>>>> +                       ra_mask &= 0xffffffffffffcfc0ULL;
>>>> +               else if (rssi_level == 4)
>>>> +                       ra_mask &= 0xffffffffffff8f80ULL;
>>>> +               else if (rssi_level >= 5)
>>>> +                       ra_mask &= 0xffffffffffff0f00ULL;
>>>> +       }
>>> 
>>> Would be better to enumerate rssi_level instead of 0 to 5. Does level
>>> 0 means bad rssi or good?
>>> 
> 
> I think 0 is the lowest level. And I think we don't need to add an enum for
> this kind of levels, as the number just presents the meaning of it.
> 
> Yan-Hsuan

OK. I think it also makes sense to me.

Chris
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index bc04cc280a96..2247bd61e716 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -475,6 +475,8 @@  static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
 	for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
 		rtw_txq_cleanup(rtwdev, sta->txq[i]);
 
+	kfree(si->mask);
+
 	rtwdev->sta_cnt--;
 
 	rtw_info(rtwdev, "sta %pM with macid %d left\n",
@@ -684,6 +686,56 @@  static void rtw_ops_flush(struct ieee80211_hw *hw,
 	mutex_unlock(&rtwdev->mutex);
 }
 
+struct rtw_iter_bitrate_mask_data {
+	struct rtw_dev *rtwdev;
+	struct ieee80211_vif *vif;
+	const struct cfg80211_bitrate_mask *mask;
+};
+
+static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw_iter_bitrate_mask_data *br_data = data;
+	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+
+	if (si->vif != br_data->vif)
+		return;
+
+	/* free previous mask setting */
+	kfree(si->mask);
+	si->mask = kmemdup(br_data->mask, sizeof(struct cfg80211_bitrate_mask),
+			   GFP_ATOMIC);
+	if (!si->mask) {
+		si->use_cfg_mask = false;
+		return;
+	}
+
+	si->use_cfg_mask = true;
+	rtw_update_sta_info(br_data->rtwdev, si);
+}
+
+static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev,
+				    struct ieee80211_vif *vif,
+				    const struct cfg80211_bitrate_mask *mask)
+{
+	struct rtw_iter_bitrate_mask_data br_data;
+
+	br_data.rtwdev = rtwdev;
+	br_data.vif = vif;
+	br_data.mask = mask;
+	rtw_iterate_stas_atomic(rtwdev, rtw_ra_mask_info_update_iter, &br_data);
+}
+
+static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    const struct cfg80211_bitrate_mask *mask)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+
+	rtw_ra_mask_info_update(rtwdev, vif, mask);
+
+	return 0;
+}
+
 const struct ieee80211_ops rtw_ops = {
 	.tx			= rtw_ops_tx,
 	.wake_tx_queue		= rtw_ops_wake_tx_queue,
@@ -705,5 +757,6 @@  const struct ieee80211_ops rtw_ops = {
 	.set_rts_threshold	= rtw_ops_set_rts_threshold,
 	.sta_statistics		= rtw_ops_sta_statistics,
 	.flush			= rtw_ops_flush,
+	.set_bitrate_mask	= rtw_ops_set_bitrate_mask,
 };
 EXPORT_SYMBOL(rtw_ops);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 47e74f0aec06..e53143132a9b 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -612,12 +612,71 @@  static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num)
 #define RA_MASK_OFDM_IN_HT_2G	0x00010
 #define RA_MASK_OFDM_IN_HT_5G	0x00030
 
+static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev,
+				struct rtw_sta_info *si,
+				u64 ra_mask, bool is_vht_enable,
+				u8 wireless_set)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	const struct cfg80211_bitrate_mask *mask = si->mask;
+	u64 cfg_mask = GENMASK(63, 0);
+	u8 rssi_level, band;
+
+	if (wireless_set != WIRELESS_CCK) {
+		rssi_level = si->rssi_level;
+		if (rssi_level == 0)
+			ra_mask &= 0xffffffffffffffffULL;
+		else if (rssi_level == 1)
+			ra_mask &= 0xfffffffffffffff0ULL;
+		else if (rssi_level == 2)
+			ra_mask &= 0xffffffffffffefe0ULL;
+		else if (rssi_level == 3)
+			ra_mask &= 0xffffffffffffcfc0ULL;
+		else if (rssi_level == 4)
+			ra_mask &= 0xffffffffffff8f80ULL;
+		else if (rssi_level >= 5)
+			ra_mask &= 0xffffffffffff0f00ULL;
+	}
+
+	if (!si->use_cfg_mask)
+		return ra_mask;
+
+	band = hal->current_band_type;
+	if (band == RTW_BAND_2G) {
+		band = NL80211_BAND_2GHZ;
+		cfg_mask = mask->control[band].legacy;
+	} else if (band == RTW_BAND_5G) {
+		band = NL80211_BAND_5GHZ;
+		cfg_mask = u64_encode_bits(mask->control[band].legacy,
+					   RA_MASK_OFDM_RATES);
+	}
+
+	if (!is_vht_enable) {
+		if (ra_mask & RA_MASK_HT_RATES_1SS)
+			cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0],
+						    RA_MASK_HT_RATES_1SS);
+		if (ra_mask & RA_MASK_HT_RATES_2SS)
+			cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1],
+						    RA_MASK_HT_RATES_2SS);
+	} else {
+		if (ra_mask & RA_MASK_VHT_RATES_1SS)
+			cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0],
+						    RA_MASK_VHT_RATES_1SS);
+		if (ra_mask & RA_MASK_VHT_RATES_2SS)
+			cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1],
+						    RA_MASK_VHT_RATES_2SS);
+	}
+
+	ra_mask &= cfg_mask;
+
+	return ra_mask;
+}
+
 void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
 {
 	struct ieee80211_sta *sta = si->sta;
 	struct rtw_efuse *efuse = &rtwdev->efuse;
 	struct rtw_hal *hal = &rtwdev->hal;
-	u8 rssi_level;
 	u8 wireless_set;
 	u8 bw_mode;
 	u8 rate_id;
@@ -710,21 +769,8 @@  void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
 
 	rate_id = get_rate_id(wireless_set, bw_mode, tx_num);
 
-	if (wireless_set != WIRELESS_CCK) {
-		rssi_level = si->rssi_level;
-		if (rssi_level == 0)
-			ra_mask &= 0xffffffffffffffffULL;
-		else if (rssi_level == 1)
-			ra_mask &= 0xfffffffffffffff0ULL;
-		else if (rssi_level == 2)
-			ra_mask &= 0xffffffffffffefe0ULL;
-		else if (rssi_level == 3)
-			ra_mask &= 0xffffffffffffcfc0ULL;
-		else if (rssi_level == 4)
-			ra_mask &= 0xffffffffffff8f80ULL;
-		else if (rssi_level >= 5)
-			ra_mask &= 0xffffffffffff0f00ULL;
-	}
+	ra_mask = rtw_update_rate_mask(rtwdev, si, ra_mask, is_vht_enable,
+				       wireless_set);
 
 	si->bw_mode = bw_mode;
 	si->stbc_en = stbc_en;
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 14b35152fe9f..5e33b7e47a9d 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -646,6 +646,9 @@  struct rtw_sta_info {
 	DECLARE_BITMAP(tid_ba, IEEE80211_NUM_TIDS);
 
 	struct rtw_ra_report ra_report;
+
+	bool use_cfg_mask;
+	struct cfg80211_bitrate_mask *mask;
 };
 
 enum rtw_bfee_role {