Commit cde8848c authored by Martin Kaistra's avatar Martin Kaistra Committed by Kalle Valo

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: default avatarMartin Kaistra <martin.kaistra@linutronix.de>
Reviewed-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230428150833.218605-4-martin.kaistra@linutronix.de
parent 25ed009c
...@@ -1851,6 +1851,7 @@ struct rtl8xxxu_priv { ...@@ -1851,6 +1851,7 @@ struct rtl8xxxu_priv {
struct delayed_work ra_watchdog; struct delayed_work ra_watchdog;
struct work_struct c2hcmd_work; struct work_struct c2hcmd_work;
struct sk_buff_head c2hcmd_queue; struct sk_buff_head c2hcmd_queue;
struct work_struct update_beacon_work;
struct rtl8xxxu_btcoex bt_coex; struct rtl8xxxu_btcoex bt_coex;
struct rtl8xxxu_ra_report ra_report; struct rtl8xxxu_ra_report ra_report;
struct rtl8xxxu_cfo_tracking cfo_tracking; struct rtl8xxxu_cfo_tracking cfo_tracking;
......
...@@ -1185,6 +1185,20 @@ static void rtl8xxxu_stop_tx_beacon(struct rtl8xxxu_priv *priv) ...@@ -1185,6 +1185,20 @@ static void rtl8xxxu_stop_tx_beacon(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8); 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 * 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, ...@@ -4964,6 +4978,17 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
dev_dbg(dev, "Changed BASIC_RATES!\n"); dev_dbg(dev, "Changed BASIC_RATES!\n");
rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates); 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: error:
return; return;
} }
...@@ -5545,6 +5570,55 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, ...@@ -5545,6 +5570,55 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
dev_kfree_skb(skb); 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, void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status, struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats, struct rtl8723au_phy_stats *phy_stats,
...@@ -7311,6 +7385,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, ...@@ -7311,6 +7385,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
spin_lock_init(&priv->rx_urb_lock); spin_lock_init(&priv->rx_urb_lock);
INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work);
INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback); 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); skb_queue_head_init(&priv->c2hcmd_queue);
usb_set_intfdata(interface, hw); usb_set_intfdata(interface, hw);
......
...@@ -456,6 +456,7 @@ ...@@ -456,6 +456,7 @@
#define REG_FIFOPAGE 0x0204 #define REG_FIFOPAGE 0x0204
#define REG_TDECTRL 0x0208 #define REG_TDECTRL 0x0208
#define BIT_BCN_VALID BIT(16)
#define REG_DWBCN0_CTRL_8188F REG_TDECTRL #define REG_DWBCN0_CTRL_8188F REG_TDECTRL
...@@ -470,6 +471,7 @@ ...@@ -470,6 +471,7 @@
#define AUTO_LLT_INIT_LLT BIT(16) #define AUTO_LLT_INIT_LLT BIT(16)
#define REG_DWBCN1_CTRL_8723B 0x0228 #define REG_DWBCN1_CTRL_8723B 0x0228
#define BIT_SW_BCN_SEL BIT(20)
/* 0x0280 ~ 0x02FF RXDMA Configuration */ /* 0x0280 ~ 0x02FF RXDMA Configuration */
#define REG_RXDMA_AGG_PG_TH 0x0280 /* 0-7 : USB DMA size bits #define REG_RXDMA_AGG_PG_TH 0x0280 /* 0-7 : USB DMA size bits
...@@ -516,6 +518,7 @@ ...@@ -516,6 +518,7 @@
#define REG_FWHW_TXQ_CTRL 0x0420 #define REG_FWHW_TXQ_CTRL 0x0420
#define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7) #define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7)
#define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12) #define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12)
#define EN_BCNQ_DL BIT(22)
#define REG_HWSEQ_CTRL 0x0423 #define REG_HWSEQ_CTRL 0x0423
#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 #define REG_TXPKTBUF_BCNQ_BDNY 0x0424
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment