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]

 



On 22/03/2023 19:18, Martin Kaistra wrote:
> 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);
> +	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);
> +		}

Is it not necessary to stop transmitting the beacons when
bss_conf->enable_beacon is false?

> +	}
> +
>  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);
> +	rtl8xxxu_write8(priv, REG_TDECTRL + 2, val8);
> +
> +	/* SW_BCN_SEL - Port0 */
> +	val8 = rtl8xxxu_read8(priv, REG_DWBCN1_CTRL_8723B + 2);
> +	val8 &= ~BIT(4);
> +	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))
> +			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);




[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