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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®