Search Linux Wireless

RE: [RFC PATCH 03/14] wifi: rtl8xxxu: Add beacon functions

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

 




> -----Original Message-----
> From: Martin Kaistra <martin.kaistra@xxxxxxxxxxxxx>
> Sent: Thursday, March 23, 2023 1:19 AM
> 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: [RFC PATCH 03/14] wifi: rtl8xxxu: Add beacon functions
> 
> Add a workqueue to update the beacon contents asynchronously and
> implement downloading the beacon to the HW and starting beacon tx like
> the vendor driver.
> 
> Signed-off-by: Martin Kaistra <martin.kaistra@xxxxxxxxxxxxx>
> ---
>  .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  3 +
>  .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 81 +++++++++++++++++++
>  2 files changed, 84 insertions(+)
> 
> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
> index 9d48c69ffece1..cac985271628c 100644
> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
> @@ -1744,6 +1744,8 @@ struct rtl8xxxu_priv {
>         bool shutdown;
>         struct work_struct rx_urb_wq;
> 
> +       bool beacon_enabled;
> +
>         u8 mac_addr[ETH_ALEN];
>         char chip_name[8];
>         char chip_vendor[8];
> @@ -1850,6 +1852,7 @@ struct rtl8xxxu_priv {
>         struct delayed_work ra_watchdog;
>         struct work_struct c2hcmd_work;
>         struct sk_buff_head c2hcmd_queue;
> +       struct work_struct update_beacon_work;
>         struct rtl8xxxu_btcoex bt_coex;
>         struct rtl8xxxu_ra_report ra_report;
>         struct rtl8xxxu_cfo_tracking cfo_tracking;
> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> index daeaa7d6864f9..404fa6e322f58 100644
> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> @@ -1104,6 +1104,24 @@ static void rtl8xxxu_stop_tx_beacon(struct rtl8xxxu_priv *priv)
>         val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2);
>         val8 &= ~BIT(0);
>         rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8);
> +
> +       priv->beacon_enabled = false;
> +}
> +
> +static void rtl8xxxu_start_tx_beacon(struct rtl8xxxu_priv *priv)
> +{
> +       u8 val8;
> +
> +       val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2);
> +       val8 |= BIT(6);

#define EN_BCNQ_DL BIT(22)

val8 |= EN_BCNQ_DL >> 16;

> +       rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val8);
> +
> +       rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, 0x80);
> +       val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2);
> +       val8 &= 0xF0;
> +       rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8);
> +
> +       priv->beacon_enabled = true;
>  }
> 
> 
> @@ -4895,6 +4913,17 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>                 dev_dbg(dev, "Changed BASIC_RATES!\n");
>                 rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates);
>         }
> +
> +       if (changed & BSS_CHANGED_BEACON ||
> +           (changed & BSS_CHANGED_BEACON_ENABLED &&
> +            bss_conf->enable_beacon)) {
> +               if (!priv->beacon_enabled) {
> +                       dev_dbg(dev, "BSS_CHANGED_BEACON_ENABLED\n");
> +                       rtl8xxxu_start_tx_beacon(priv);
> +                       schedule_work(&priv->update_beacon_work);
> +               }
> +       }
> +
>  error:
>         return;
>  }
> @@ -5476,6 +5505,57 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
>         dev_kfree_skb(skb);
>  }
> 
> +static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw,
> +                                      struct ieee80211_vif *vif)
> +{
> +       struct rtl8xxxu_priv *priv = hw->priv;
> +       struct sk_buff *skb = ieee80211_beacon_get(hw, vif, 0);
> +       struct device *dev = &priv->udev->dev;
> +       int retry;
> +       u8 val8;
> +
> +       /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2,
> +        * write 1 to clear, cleared by SW.
> +        */
> +       val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2);
> +       val8 |= BIT(0);

#define BIT_BCN_VALID BIT(16)
val8 |= BIT_BCN_VALID >> 16;

> +       rtl8xxxu_write8(priv, REG_TDECTRL + 2, val8);
> +
> +       /* SW_BCN_SEL - Port0 */
> +       val8 = rtl8xxxu_read8(priv, REG_DWBCN1_CTRL_8723B + 2);
> +       val8 &= ~BIT(4);

#define BIT_SW_BCN_SEL BIT(20)
val8 &= ~(BIT_SW_BCN_SEL >> 20);

> +       rtl8xxxu_write8(priv, REG_DWBCN1_CTRL_8723B + 2, val8);
> +
> +       if (skb)
> +               rtl8xxxu_tx(hw, NULL, skb);
> +
> +       retry = 100;
> +       do {
> +               val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2);
> +               if (val8 & BIT(0))

#define BIT_BCN_VALID BIT(16)

if (val8 & (BIT_BCN_VALID >> 16)

> +                       break;
> +               usleep_range(10, 20);
> +       } while (retry--);
> +
> +       if (!retry)
> +               dev_err(dev, "%s: Failed to read beacon valid bit\n", __func__);
> +}
> +
> +static void rtl8xxxu_update_beacon_work_callback(struct work_struct *work)
> +{
> +       struct rtl8xxxu_priv *priv =
> +               container_of(work, struct rtl8xxxu_priv, update_beacon_work);
> +       struct ieee80211_hw *hw = priv->hw;
> +       struct ieee80211_vif *vif = priv->vif;
> +
> +       if (!vif) {
> +               WARN_ONCE(true, "no vif to update beacon\n");
> +               return;
> +       }
> +
> +       rtl8xxxu_send_beacon_frame(hw, vif);
> +}
> +
>  void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv,
>                                  struct ieee80211_rx_status *rx_status,
>                                  struct rtl8723au_phy_stats *phy_stats,
> @@ -7244,6 +7324,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
>         spin_lock_init(&priv->rx_urb_lock);
>         INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work);
>         INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback);
> +       INIT_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback);
>         skb_queue_head_init(&priv->c2hcmd_queue);
> 
>         usb_set_intfdata(interface, hw);
> --
> 2.30.2




[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