From: John Robin <johnrobin044@gmail.com>
To: linux-wireless@vger.kernel.org
Cc: kuba@kernel.org, matthias.bgg@gmail.com,
angelogioacchino.delregno@collabora.com,
linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
John Robin <johnrobin044@gmail.com>
Subject: [PATCH v2 3/4] wifi: mt7601u: add AP operations and beacon handling
Date: Sun, 8 Nov 2026 12:47:45 +0530 [thread overview]
Message-ID: <20261108071820.35303-4-johnrobin044@gmail.com> (raw)
In-Reply-To: <20261108071820.35303-1-johnrobin044@gmail.com>
Implement the start_ap() and stop_ap() callbacks required for AP mode.
This clears the WCID tables and manages the hardware Pre-TBTT timer
for beaconing. Additionally, update mt7601u_bss_info_changed() to
handle BSS_CHANGED_BEACON and BSS_CHANGED_BEACON_ENABLED, routing
beacon frames through mt7601u_mac_set_beacon() and applying the
appropriate hardware SYNC modes for AP and ADHOC interfaces.
Signed-off-by: John Robin <johnrobin044@gmail.com>
---
drivers/net/wireless/mediatek/mt7601u/mac.c | 59 ++++++++++++++++---
drivers/net/wireless/mediatek/mt7601u/mac.h | 3 +-
drivers/net/wireless/mediatek/mt7601u/main.c | 56 +++++++++++++++++-
.../net/wireless/mediatek/mt7601u/mt7601u.h | 3 +-
4 files changed, 110 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wireless/mediatek/mt7601u/mac.c
index bf485dabca745..5e2dec131331c 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mac.c
+++ b/drivers/net/wireless/mediatek/mt7601u/mac.c
@@ -272,13 +272,13 @@ void mt7601u_mac_set_short_preamble(struct mt7601u_dev *dev, bool short_preamb)
mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
}
-void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int interval)
+void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, struct ieee80211_vif *vif,
+ bool enable, int interval)
{
u32 val = mt7601u_rr(dev, MT_BEACON_TIME_CFG);
- val &= ~(MT_BEACON_TIME_CFG_TIMER_EN |
- MT_BEACON_TIME_CFG_SYNC_MODE |
- MT_BEACON_TIME_CFG_TBTT_EN);
+ val &= ~(MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_SYNC_MODE |
+ MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_BEACON_TX);
if (!enable) {
mt7601u_wr(dev, MT_BEACON_TIME_CFG, val);
@@ -287,9 +287,22 @@ void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int interval)
val &= ~MT_BEACON_TIME_CFG_INTVAL;
val |= FIELD_PREP(MT_BEACON_TIME_CFG_INTVAL, interval << 4) |
- MT_BEACON_TIME_CFG_TIMER_EN |
- MT_BEACON_TIME_CFG_SYNC_MODE |
- MT_BEACON_TIME_CFG_TBTT_EN;
+ MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_TBTT_EN;
+
+ /* AP Mode */
+ if (vif && (vif->type == NL80211_IFTYPE_AP ||
+ vif->type == NL80211_IFTYPE_P2P_GO))
+ val |= FIELD_PREP(MT_BEACON_TIME_CFG_SYNC_MODE, 3) |
+ MT_BEACON_TIME_CFG_BEACON_TX;
+ /* IBSS / Ad-Hoc Mode */
+ else if (vif && vif->type == NL80211_IFTYPE_ADHOC)
+ val |= FIELD_PREP(MT_BEACON_TIME_CFG_SYNC_MODE, 2) |
+ MT_BEACON_TIME_CFG_BEACON_TX;
+ /* Station mode */
+ else
+ val |= FIELD_PREP(MT_BEACON_TIME_CFG_SYNC_MODE, 1);
+
+ mt7601u_wr(dev, MT_BEACON_TIME_CFG, val);
}
static void mt7601u_check_mac_err(struct mt7601u_dev *dev)
@@ -401,6 +414,38 @@ void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *dev)
FIELD_PREP(MT_MAX_LEN_CFG_AMPDU, min_factor));
}
+int mt7601u_mac_set_beacon(struct mt7601u_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info)
+{
+ struct sk_buff *skb = ieee80211_beacon_get(dev->hw, vif, 0);
+ struct mt76_txwi *txwi;
+ int err, words;
+
+ if (!skb)
+ return 0;
+
+ /* USB devices already reserve enough skb headroom */
+ err = skb_cow_head(skb, sizeof(struct mt76_txwi));
+ if (err) {
+ dev_kfree_skb(skb);
+ return err;
+ }
+
+ txwi = (struct mt76_txwi *)skb_push(skb, sizeof(struct mt76_txwi));
+ memset(txwi, 0, sizeof(*txwi));
+
+ txwi->wcid = 0;
+ txwi->len_ctl = cpu_to_le16(skb->len - sizeof(struct mt76_txwi));
+ txwi->rate_ctl = cpu_to_le16(0);
+
+ words = DIV_ROUND_UP(skb->len, 4);
+ err = mt7601u_burst_write_regs(dev, MT_BEACON_BASE,
+ (const u32 *)skb->data, words);
+ dev_kfree_skb(skb);
+
+ return err;
+}
+
static void
mt76_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
{
diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.h b/drivers/net/wireless/mediatek/mt7601u/mac.h
index 54bd4fac54d83..528756ccf4725 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mac.h
+++ b/drivers/net/wireless/mediatek/mt7601u/mac.h
@@ -167,5 +167,6 @@ struct mt76_tx_status
mt7601u_mac_fetch_tx_status(struct mt7601u_dev *dev);
void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat);
void mt7601u_set_macaddr(struct mt7601u_dev *dev, const u8 *addr);
-
+int mt7601u_mac_set_beacon(struct mt7601u_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info);
#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
index 05ba43e1985c8..4389e332dfe19 100644
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -149,7 +149,7 @@ mt7601u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
* rt2x00 doesn't seem to be bothered though.
*/
if (is_zero_ether_addr(info->bssid))
- mt7601u_mac_config_tsf(dev, false, 0);
+ mt7601u_mac_config_tsf(dev, vif, false, 0);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
@@ -161,7 +161,20 @@ mt7601u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (changed & BSS_CHANGED_BEACON_INT)
- mt7601u_mac_config_tsf(dev, true, info->beacon_int);
+ mt7601u_mac_config_tsf(dev, vif, true, info->beacon_int);
+
+ if ((changed & BSS_CHANGED_BEACON) && vif->type == NL80211_IFTYPE_AP)
+ mt7601u_mac_set_beacon(dev, vif, info);
+
+ if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
+ vif->type == NL80211_IFTYPE_AP) {
+ if (info->enable_beacon)
+ mt76_set(dev, MT_BEACON_TIME_CFG,
+ MT_BEACON_TIME_CFG_BEACON_TX);
+ else
+ mt76_clear(dev, MT_BEACON_TIME_CFG,
+ MT_BEACON_TIME_CFG_BEACON_TX);
+ }
if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
mt7601u_mac_set_protection(dev, info->use_cts_prot,
@@ -183,6 +196,43 @@ mt7601u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_unlock(&dev->mutex);
}
+static int mt7601u_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ struct mt7601u_dev *dev = hw->priv;
+ int err = 0;
+
+ mutex_lock(&dev->mutex);
+
+ /* Clear the wcid Table */
+ for (int i = 1; i < 128; i++)
+ mt7601u_mac_wcid_setup(dev, i, 0, NULL);
+
+ /* Set pre TBTT to 6ms */
+ mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, 6);
+ mt76_set(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN);
+
+ mt7601u_mac_config_tsf(dev, vif, true, link_conf->beacon_int);
+
+ mutex_unlock(&dev->mutex);
+
+ return err;
+}
+
+static void mt7601u_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ struct mt7601u_dev *dev = hw->priv;
+
+ mutex_lock(&dev->mutex);
+
+ mt7601u_mac_config_tsf(dev, vif, false, 0);
+
+ mt76_clear(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN);
+
+ mutex_unlock(&dev->mutex);
+}
+
static int
mt76_wcid_alloc(struct mt7601u_dev *dev)
{
@@ -419,6 +469,8 @@ const struct ieee80211_ops mt7601u_ops = {
.config = mt7601u_config,
.configure_filter = mt76_configure_filter,
.bss_info_changed = mt7601u_bss_info_changed,
+ .start_ap = mt7601u_start_ap,
+ .stop_ap = mt7601u_stop_ap,
.sta_add = mt7601u_sta_add,
.sta_remove = mt7601u_sta_remove,
.sta_notify = mt7601u_sta_notify,
diff --git a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
index 118d437078537..7366e1c476339 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
+++ b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
@@ -359,7 +359,8 @@ void mt7601u_mac_work(struct work_struct *work);
void mt7601u_mac_set_protection(struct mt7601u_dev *dev, bool legacy_prot,
int ht_mode);
void mt7601u_mac_set_short_preamble(struct mt7601u_dev *dev, bool short_preamb);
-void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int interval);
+void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, struct ieee80211_vif *vif,
+ bool enable, int interval);
void
mt7601u_mac_wcid_setup(struct mt7601u_dev *dev, u8 idx, u8 vif_idx, u8 *mac);
void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *dev);
--
2.56.0
next prev parent reply other threads:[~2026-11-08 7:19 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-15 12:41 [PATCH wireless-next] wifi: mt76: mt7601u: add support for AP and P2P concurrent modes John Robin
2026-10-09 13:11 ` Bitterblue Smith
2026-11-08 7:17 ` [PATCH v2 0/4] wifi: mt7601u: add AP and Wi-Fi Direct support John Robin
2026-11-08 7:17 ` [PATCH v2 1/4] wifi: mt7601u: fix out-of-bounds access in rate index John Robin
2026-11-08 7:17 ` [PATCH v2 2/4] wifi: mt7601u: enable AP and Wi-Fi Direct interface modes John Robin
2026-11-08 7:17 ` John Robin [this message]
2026-11-08 7:17 ` [PATCH v2 4/4] wifi: mt7601u: optimize management frame routing and queues John Robin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261108071820.35303-4-johnrobin044@gmail.com \
--to=johnrobin044@gmail.com \
--cc=angelogioacchino.delregno@collabora.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-wireless@vger.kernel.org \
--cc=matthias.bgg@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.