Search Linux Wireless

RE: [PATCH v2] wifi: rtl8xxxu: update rate mask per sta

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> -----Original Message-----
> From: Martin Kaistra <martin.kaistra@xxxxxxxxxxxxx>
> Sent: Wednesday, January 24, 2024 4:27 PM
> To: linux-wireless@xxxxxxxxxxxxxxx
> Cc: Jes Sorensen <Jes.Sorensen@xxxxxxxxx>; Kalle Valo <kvalo@xxxxxxxxxx>; Ping-Ke Shih
> <pkshih@xxxxxxxxxxx>; Bitterblue Smith <rtl8821cerfe2@xxxxxxxxx>; Sebastian Andrzej Siewior
> <bigeasy@xxxxxxxxxxxxx>
> Subject: [PATCH v2] wifi: rtl8xxxu: update rate mask per sta
> 
> Until now, rtl8xxxu_watchdog_callback() only fetches RSSI and updates
> the rate mask in station mode. This means, in AP mode only the default
> rate mask is used.
> 
> In order to have the rate mask reflect the actual connection quality,
> extend rtl8xxxu_watchdog_callback() to iterate over every sta. Like in
> the rtw88 driver, add a function to collect all currently present stas
> and then iterate over a list of copies to ensure no RCU lock problems
> for register access via USB. Remove the existing RCU lock in
> rtl8xxxu_refresh_rate_mask().
> 
> Since the currently used ieee80211_ave_rssi() is only for 'vif', add
> driver-level tracking of RSSI per sta.
> 
> Signed-off-by: Martin Kaistra <martin.kaistra@xxxxxxxxxxxxx>
> ---
> changes v1->v2: move 'rssi_level' into struct rtl8xxxu_sta_info
> v1: https://lore.kernel.org/linux-wireless/20240117145516.497966-1-martin.kaistra@xxxxxxxxxxxxx/

[...]

> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> index 3b954c2fe448f..3820d3c308759 100644
> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> @@ -4993,8 +4993,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>         struct device *dev = &priv->udev->dev;
>         struct ieee80211_sta *sta;
>         struct rtl8xxxu_ra_report *rarpt;
> +       u8 val8, macid;
>         u32 val32;
> -       u8 val8;
> 
>         rarpt = &priv->ra_report;
> 
> @@ -5004,6 +5004,7 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>                 rtl8xxxu_set_linktype(priv, vif->type, rtlvif->port_num);
> 
>                 if (vif->cfg.assoc) {
> +                       struct rtl8xxxu_sta_info *sta_info;

nit: I remember that declaration at beginning of function is preferred. 

>                         u32 ramask;
>                         int sgi = 0;
>                         u8 highest_rate;
> @@ -5017,6 +5018,7 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>                                 rcu_read_unlock();
>                                 goto error;
>                         }
> +                       macid = rtl8xxxu_get_macid(priv, sta);
> 
>                         if (sta->deflink.ht_cap.ht_supported)
>                                 dev_info(dev, "%s: HT supported\n", __func__);
> @@ -5037,14 +5039,15 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>                                 bw = RATE_INFO_BW_40;
>                         else
>                                 bw = RATE_INFO_BW_20;
> +
> +                       sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
> +                       sta_info->rssi_level = RTL8XXXU_RATR_STA_INIT;

For AP mode, we should do this as well at rtl8xxxu_sta_add() before calling
rtl8xxxu_refresh_rate_mask()?

>                         rcu_read_unlock();
> 
>                         rtl8xxxu_update_ra_report(rarpt, highest_rate, sgi, bw);
> 
> -                       priv->rssi_level = RTL8XXXU_RATR_STA_INIT;
> -
>                         priv->fops->update_rate_mask(priv, ramask, 0, sgi,
> -                                                    bw == RATE_INFO_BW_40, 0);
> +                                                    bw == RATE_INFO_BW_40, macid);
> 
>                         rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
> 
> @@ -6317,6 +6320,76 @@ static void rtl8188e_c2hcmd_callback(struct work_struct *work)
>         }
>  }
> 
> +#define rtl8xxxu_iterate_vifs_atomic(priv, iterator, data)                     \
> +       ieee80211_iterate_active_interfaces_atomic((priv)->hw,                  \
> +                       IEEE80211_IFACE_ITER_NORMAL, iterator, data)
> +
> +struct rtl8xxxu_rx_addr_match_data {
> +       struct rtl8xxxu_priv *priv;
> +       struct ieee80211_hdr *hdr;
> +       struct ieee80211_rx_status *rx_status;
> +       u8 *bssid;
> +};
> +
> +static void rtl8xxxu_rx_addr_match_iter(void *data, u8 *mac,
> +                                       struct ieee80211_vif *vif)
> +{
> +       struct rtl8xxxu_rx_addr_match_data *iter_data = data;
> +       struct ieee80211_sta *sta;
> +       struct ieee80211_hdr *hdr = iter_data->hdr;
> +       struct rtl8xxxu_priv *priv = iter_data->priv;
> +       struct rtl8xxxu_sta_info *sta_info;
> +       struct ieee80211_rx_status *rx_status = iter_data->rx_status;
> +       u8 *bssid = iter_data->bssid;
> +
> +       if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
> +               return;
> +
> +       if (!(ether_addr_equal(vif->addr, hdr->addr1) ||
> +             ieee80211_is_beacon(hdr->frame_control)))
> +               return;

nit: Here checks bssid, addr1 and beacon frame. For me, if you want to combine
some of them, would it be reasonable to combine bssid and add1? 

> +
> +       sta = ieee80211_find_sta_by_ifaddr(priv->hw, hdr->addr2,
> +                                          vif->addr);
> +       if (!sta)
> +               return;
> +
> +       sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
> +       ewma_rssi_add(&sta_info->avg_rssi, -rx_status->signal);
> +}
> +
> +static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)

Would you like to add a ieee80211_get_BSSID() to ieee80211.h in separated 
patch? But I wonder if it is enough to check addr1 only?

> +{
> +       __le16 fc = hdr->frame_control;
> +       u8 *bssid;
> +
> +       if (ieee80211_has_tods(fc))
> +               bssid = hdr->addr1;
> +       else if (ieee80211_has_fromds(fc))
> +               bssid = hdr->addr2;
> +       else
> +               bssid = hdr->addr3;
> +
> +       return bssid;
> +}
> +
> +static void rtl8xxxu_rx_addr_match(struct rtl8xxxu_priv *priv,
> +                                  struct ieee80211_rx_status *rx_status,
> +                                  struct ieee80211_hdr *hdr)
> +{
> +       struct rtl8xxxu_rx_addr_match_data data = {};
> +
> +       if (ieee80211_is_ctl(hdr->frame_control))
> +               return;
> +
> +       data.priv = priv;
> +       data.hdr = hdr;
> +       data.rx_status = rx_status;
> +       data.bssid = get_hdr_bssid(hdr);
> +
> +       rtl8xxxu_iterate_vifs_atomic(priv, rtl8xxxu_rx_addr_match_iter, &data);
> +}
> +
>  int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
>  {
>         struct ieee80211_hw *hw = priv->hw;
> @@ -6376,18 +6449,26 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
>                         skb_queue_tail(&priv->c2hcmd_queue, skb);
>                         schedule_work(&priv->c2hcmd_work);
>                 } else {
> +                       struct ieee80211_hdr *hdr;
> +
>                         phy_stats = (struct rtl8723au_phy_stats *)skb->data;
> 
>                         skb_pull(skb, drvinfo_sz + desc_shift);
> 
>                         skb_trim(skb, pkt_len);
> 
> -                       if (rx_desc->phy_stats)
> +                       hdr = (struct ieee80211_hdr *)skb->data;
> +                       if (rx_desc->phy_stats) {
>                                 priv->fops->parse_phystats(
>                                         priv, rx_status, phy_stats,
>                                         rx_desc->rxmcs,
> -                                       (struct ieee80211_hdr *)skb->data,
> +                                       hdr,
>                                         rx_desc->crc32 || rx_desc->icverr);
> +                               if (!rx_desc->crc32 && !rx_desc->icverr)
> +                                       rtl8xxxu_rx_addr_match(priv,
> +                                                              rx_status,
> +                                                              hdr);

This function name isn't clear, because it doesn't just match rx addr,
but it is to update RSSI by rx_status for corresponding station. 

> +                       }
> 
>                         rx_status->mactime = rx_desc->tsfl;
>                         rx_status->flag |= RX_FLAG_MACTIME_START;

[...]






[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux