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@linutronix.de> Reviewed-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/20230428150833.218605-4-martin.kaistra@linutronix.de
This commit is contained in:
committed by
Kalle Valo
parent
25ed009cc0
commit
cde8848cad
@@ -1851,6 +1851,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;
|
||||
|
||||
@@ -1185,6 +1185,20 @@ static void rtl8xxxu_stop_tx_beacon(struct rtl8xxxu_priv *priv)
|
||||
rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8);
|
||||
}
|
||||
|
||||
static void rtl8xxxu_start_tx_beacon(struct rtl8xxxu_priv *priv)
|
||||
{
|
||||
u8 val8;
|
||||
|
||||
val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The rtl8723a has 3 channel groups for it's efuse settings. It only
|
||||
@@ -4964,6 +4978,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_ENABLED) {
|
||||
if (bss_conf->enable_beacon)
|
||||
rtl8xxxu_start_tx_beacon(priv);
|
||||
else
|
||||
rtl8xxxu_stop_tx_beacon(priv);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON)
|
||||
schedule_work(&priv->update_beacon_work);
|
||||
|
||||
error:
|
||||
return;
|
||||
}
|
||||
@@ -5545,6 +5570,55 @@ error:
|
||||
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, write 1 to clear, cleared by SW */
|
||||
val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2);
|
||||
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_SW_BCN_SEL >> 16);
|
||||
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_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,
|
||||
@@ -7311,6 +7385,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);
|
||||
|
||||
@@ -456,6 +456,7 @@
|
||||
|
||||
#define REG_FIFOPAGE 0x0204
|
||||
#define REG_TDECTRL 0x0208
|
||||
#define BIT_BCN_VALID BIT(16)
|
||||
|
||||
#define REG_DWBCN0_CTRL_8188F REG_TDECTRL
|
||||
|
||||
@@ -470,6 +471,7 @@
|
||||
#define AUTO_LLT_INIT_LLT BIT(16)
|
||||
|
||||
#define REG_DWBCN1_CTRL_8723B 0x0228
|
||||
#define BIT_SW_BCN_SEL BIT(20)
|
||||
|
||||
/* 0x0280 ~ 0x02FF RXDMA Configuration */
|
||||
#define REG_RXDMA_AGG_PG_TH 0x0280 /* 0-7 : USB DMA size bits
|
||||
@@ -516,6 +518,7 @@
|
||||
#define REG_FWHW_TXQ_CTRL 0x0420
|
||||
#define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7)
|
||||
#define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12)
|
||||
#define EN_BCNQ_DL BIT(22)
|
||||
|
||||
#define REG_HWSEQ_CTRL 0x0423
|
||||
#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
|
||||
|
||||
Reference in New Issue
Block a user