From nobody Mon Sep 28 23:11:32 2026 Received: from mail-pg1-f172.google.com (mail-pg1-f172.google.com [209.85.215.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F5FD17B50A for ; Sat, 15 Aug 2026 12:47:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786798028; cv=none; b=PIepcfSrPQ++oBFgg57QtdoyA7HnrDyCiAQ+MwTgnr62i1FQzGSvwlG0WUgRAO94dq578j/4M3mYSIV5o2XNeNgGXpvaczwVOrSZJBFWJy3BGzCMRK8GcS0iUCqyscFN2Li2GKPeQzvWMlyvg+E0vH0Vp/SZuFRW6mgIcfxtd/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786798028; c=relaxed/simple; bh=xqoxQQ7WZ2nnphgzHgGNzJH7tixpgDPJzhzltuchHQ4=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=ISG68w7RcQ8iX4HSE4FtD/FxWg1wVNbmzaAClBEeFOB4KJaK1y2r9WB5RpRW6wo2IZZNFP2zzFY8lt0D5dyem+9FG90xdx9JDnHrRM08ZZsm7Ps8jD9jwp3AXxVjVLVbQTc5NvgCZ8MTRHFoWoXQOb6jAhaLfz5OxnvGWTa6amM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BcdRrtsI; arc=none smtp.client-ip=209.85.215.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BcdRrtsI" Received: by mail-pg1-f172.google.com with SMTP id 41be03b00d2f7-c9eefcf9175so1748810a12.3 for ; Sat, 15 Aug 2026 05:47:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786798026; x=1787402826; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=UovdtwbKOZJYgbPU5yoW/I+C9znrZRaPv34XykRkKzU=; b=BcdRrtsIZSqaAmpjlXoe/hQzcK4WGUOCrgn3+LOh3EX9AYuQGZVTG7iJPOXuX7SrtJ 8HRGcQ3xEB1duPnfwK3Cc7kedBN7z33wQl6jw2WZTYZjYmFOcNWIV8nnNPR+sd0rv/45 NTOrwdnRLdAFm4d4itFCcQC71sjhJC/hIQ9mv1u/pFwlwFZ2HVTgOYZc7BZ4oQH6ZFup GfRKeNp2pomK4Wc6I3WghFpAbdWU/cYTpcWrhYXlWvPUteYGLJBFjAS1utT+qbs+Wglv 3hEEg6IFz1klVG1ixlTEF6SRNqS82yZEKupPDBY0W9cloEDCvrDmoUsqQrM/O9RdYHPU URoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786798026; x=1787402826; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=UovdtwbKOZJYgbPU5yoW/I+C9znrZRaPv34XykRkKzU=; b=IrYpH2H5eeQvnU+J1jRRIcaDjzaqrbrqF4lpGWmngOUHXrNPtGyWd4ITEOko9nhRiy 9rGYWj7z6DN5X45vlucqxL+WvwYKSZHftdmpPq+JdJT36y7gmv/eQi8darzdZcBa5NW+ qR3prej7v0stWW5Vhm2xl7jZ0tkmCfthHoyXPek2YJVzKlQkgTJwMs9txSpw3JriOJpG BPmCMZC3eyV6zzx0QvHJs8GryPhsrHHo5GRTJNmZfj8CsvegefYimRDZJ4J7/B6wvTvd dxgUEd/vVmjKe0T20PbnM1R6TmvsEwON78PHlKZjsfKNQPCgGCsXR6fai+t/hcCvalao Id7w== X-Forwarded-Encrypted: i=1; AHgh+Rp8cGBZVLAeVzht9ZXXGT8C/odePAw9LQZfXl0nzv5MRq8imlCzqedT3696JT4UCrHgAR6p8qGPQPEYGMg=@vger.kernel.org X-Gm-Message-State: AOJu0YwZu4Ik72wxeRsjsEHkEIB4iyN/+c7/7Sh9dY0nKoLjot+3hPim 1B44eEJ6K4S14/UNdwj2ltMatLns7++2Oi6rt7l3ceJGtlK4INh5hYUB X-Gm-Gg: AR+sD13FqoSxnR6EG7ikRi7qziVJ6omAVVVkucFmw5QzjqpwqtIz7LOE7gC85Y0QENq UOi0XWNgpj38Efd34MqeYOhIans0pQD/gQG/rN2tjA5IIsp8Le7VxtJ7rzWrTppcUfPlsyOmi09 id7gLqz0/HTmQJePcRMwlBhVenHIAV4v/S/P9s9I8WwAQnhqyzKRAt5a0ZhDpsG/YMusWE6X337 C9t52PDfGgVje9HTfu9IyysYXrbmZLxZqwco5uPwAffyO5NPsO0L+rqVlQKR8yn1YqjWmGDDzRr fQ4wZk/hel2e3bfMmBFXBP1BqO7+FhOmhFknYXogMXm7CHPq1hJRlj6JAaXj/b+KsJjZvN2DJNj TdOVIWqRp8UioPoulNmBk386W6FAQs8n9fadhrz0KtadfjfSJKZAHjOa4j+LBJAoDfHxWB4CT4H kueJ+3U1GXqoc/FO0bwmDVEk/uWHacvPTtY4PzLfTpLrfKjguN2h0pPF7RgHS1I1MAe59uR7iBE 9bk2b51OfY= X-Received: by 2002:a05:6a20:7290:b0:3cc:54a6:8a44 with SMTP id adf61e73a8af0-3cc71cd9e2amr13949926637.29.1786798026370; Sat, 15 Aug 2026 05:47:06 -0700 (PDT) Received: from cachyos-x8664.nitc.ac.in ([117.250.237.105]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-320ea302649sm13943893eec.24.2026.08.15.05.47.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 15 Aug 2026 05:47:05 -0700 (PDT) From: John Robin To: linux-wireless@vger.kernel.org Cc: John Robin , Jakub Kicinski , Matthias Brugger , AngeloGioacchino Del Regno , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org Subject: [PATCH wireless-next] wifi: mt76: mt7601u: add support for AP and P2P concurrent modes Date: Sat, 15 Aug 2026 18:11:48 +0530 Message-ID: <20260815124547.329654-1-johnrobin044@gmail.com> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Enable Access Point (AP) and Wi-Fi Direct (P2P_GO/P2P_CLIENT) interface modes on MT7601U device, allowing concurrent Station and AP. Register AP, P2P_GO, P2P_CLIENT, and ADHOC modes and defined an interface combination to support 2 concurrent modes. Set NEEDS_UNIQUE_STA_ADDR to allow mac80211 to generate MACs for virtual interfaces. Implement start_ap() and stop_ap() to clear WCID tables and manage the hardware Pre-TBTT timer. Update mt7601u_bss_info_changed() to handle BSS_CHANGED_BEACON and BSS_CHANGED_BEACON_ENABLED. Add beacon frame handling through mt7601u_mac_set_beacon() and set appropriate SYNC Modes for AP and ADHOC interfaces. Add bounds checking to rate->idx to prevent out of bounds access and safely fall back to CCK rates. Route management and injected frames to the Voice (VO) queue to bypass firmware queue suspension also avoid requesting ACKs for multicast frames and skip data rate fallbacks for management frames All implemented modes were verified to be working. Tested AP mode and simultaneous STA+AP with iperf3 to verify stability. Signed-off-by: John Robin --- drivers/net/wireless/mediatek/mt7601u/init.c | 31 ++++++- drivers/net/wireless/mediatek/mt7601u/mac.c | 91 +++++++++++++++---- drivers/net/wireless/mediatek/mt7601u/mac.h | 3 +- drivers/net/wireless/mediatek/mt7601u/main.c | 56 +++++++++++- .../net/wireless/mediatek/mt7601u/mt7601u.h | 3 +- drivers/net/wireless/mediatek/mt7601u/tx.c | 19 +++- 6 files changed, 175 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wir= eless/mediatek/mt7601u/init.c index 5d9e952b29664..e871f7b63cb35 100644 --- a/drivers/net/wireless/mediatek/mt7601u/init.c +++ b/drivers/net/wireless/mediatek/mt7601u/init.c @@ -12,6 +12,25 @@ =20 #include "initvals.h" =20 +static const struct ieee80211_iface_limit if_limits[] =3D { + { .max =3D 1, .types =3D BIT(NL80211_IFTYPE_ADHOC) }, + { .max =3D 8, + .types =3D BIT(NL80211_IFTYPE_STATION) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_AP) }, +}; + +static const struct ieee80211_iface_combination if_comb[] =3D { { + .limits =3D if_limits, + .n_limits =3D ARRAY_SIZE(if_limits), + .max_interfaces =3D 2, + .num_different_channels =3D 1, + .beacon_int_infra_match =3D true, +} }; + static void mt7601u_set_wlan_state(struct mt7601u_dev *dev, u32 val, bool enable) { @@ -599,6 +618,7 @@ int mt7601u_register_device(struct mt7601u_dev *dev) ieee80211_hw_set(hw, AMPDU_AGGREGATION); ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); ieee80211_hw_set(hw, MFP_CAPABLE); + ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); hw->max_rates =3D 1; hw->max_report_rates =3D 7; hw->max_rate_tries =3D 1; @@ -607,9 +627,16 @@ int mt7601u_register_device(struct mt7601u_dev *dev) hw->vif_data_size =3D sizeof(struct mt76_vif); =20 SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); - + wiphy->interface_modes =3D + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_ADHOC); + wiphy->iface_combinations =3D if_comb; + wiphy->n_iface_combinations =3D ARRAY_SIZE(if_comb); wiphy->features |=3D NL80211_FEATURE_ACTIVE_MONITOR; - wiphy->interface_modes =3D BIT(NL80211_IFTYPE_STATION); wiphy->flags |=3D WIPHY_FLAG_SUPPORTS_TDLS; =20 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wire= less/mediatek/mt7601u/mac.c index ca9cf628eb10d..5e2dec131331c 100644 --- a/drivers/net/wireless/mediatek/mt7601u/mac.c +++ b/drivers/net/wireless/mediatek/mt7601u/mac.c @@ -118,19 +118,27 @@ u16 mt76_mac_tx_rate_val(struct mt7601u_dev *dev, if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) bw =3D 1; } else { - const struct ieee80211_rate *r; - int band =3D dev->chandef.chan->band; - u16 val; - - r =3D &dev->hw->wiphy->bands[band]->bitrates[rate->idx]; - if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - val =3D r->hw_value_short; - else - val =3D r->hw_value; =20 - phy =3D val >> 8; - rate_idx =3D val & 0xff; - bw =3D 0; + int band =3D dev->chandef.chan->band; + struct ieee80211_supported_band *sband =3D + dev->hw->wiphy->bands[band]; + + if (rate->idx < 0 || rate->idx >=3D sband->n_bitrates) { + phy =3D MT_PHY_TYPE_CCK; + rate_idx =3D 0; + } else { + const struct ieee80211_rate *r =3D + &sband->bitrates[rate->idx]; + u16 val; + + if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + val =3D r->hw_value_short; + else + val =3D r->hw_value; + + phy =3D val >> 8; + rate_idx =3D val & 0xff; + } } =20 rateval =3D FIELD_PREP(MT_RXWI_RATE_MCS, rate_idx); @@ -264,13 +272,13 @@ void mt7601u_mac_set_short_preamble(struct mt7601u_de= v *dev, bool short_preamb) mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT); } =20 -void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int inte= rval) +void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, struct ieee80211_vif = *vif, + bool enable, int interval) { u32 val =3D mt7601u_rr(dev, MT_BEACON_TIME_CFG); =20 - val &=3D ~(MT_BEACON_TIME_CFG_TIMER_EN | - MT_BEACON_TIME_CFG_SYNC_MODE | - MT_BEACON_TIME_CFG_TBTT_EN); + val &=3D ~(MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_SYNC_MODE | + MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_BEACON_TX); =20 if (!enable) { mt7601u_wr(dev, MT_BEACON_TIME_CFG, val); @@ -279,9 +287,22 @@ void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, b= ool enable, int interval) =20 val &=3D ~MT_BEACON_TIME_CFG_INTVAL; val |=3D 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 =3D=3D NL80211_IFTYPE_AP || + vif->type =3D=3D NL80211_IFTYPE_P2P_GO)) + val |=3D FIELD_PREP(MT_BEACON_TIME_CFG_SYNC_MODE, 3) | + MT_BEACON_TIME_CFG_BEACON_TX; + /* IBSS / Ad-Hoc Mode */ + else if (vif && vif->type =3D=3D NL80211_IFTYPE_ADHOC) + val |=3D FIELD_PREP(MT_BEACON_TIME_CFG_SYNC_MODE, 2) | + MT_BEACON_TIME_CFG_BEACON_TX; + /* Station mode */ + else + val |=3D FIELD_PREP(MT_BEACON_TIME_CFG_SYNC_MODE, 1); + + mt7601u_wr(dev, MT_BEACON_TIME_CFG, val); } =20 static void mt7601u_check_mac_err(struct mt7601u_dev *dev) @@ -393,6 +414,38 @@ void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *= dev) FIELD_PREP(MT_MAX_LEN_CFG_AMPDU, min_factor)); } =20 +int mt7601u_mac_set_beacon(struct mt7601u_dev *dev, struct ieee80211_vif *= vif, + struct ieee80211_bss_conf *info) +{ + struct sk_buff *skb =3D 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 =3D skb_cow_head(skb, sizeof(struct mt76_txwi)); + if (err) { + dev_kfree_skb(skb); + return err; + } + + txwi =3D (struct mt76_txwi *)skb_push(skb, sizeof(struct mt76_txwi)); + memset(txwi, 0, sizeof(*txwi)); + + txwi->wcid =3D 0; + txwi->len_ctl =3D cpu_to_le16(skb->len - sizeof(struct mt76_txwi)); + txwi->rate_ctl =3D cpu_to_le16(0); + + words =3D DIV_ROUND_UP(skb->len, 4); + err =3D 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/wire= less/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 *s= tat); 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/wir= eless/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, struc= t 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); } =20 if (changed & BSS_CHANGED_BASIC_RATES) { @@ -161,7 +161,20 @@ mt7601u_bss_info_changed(struct ieee80211_hw *hw, stru= ct ieee80211_vif *vif, } =20 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 =3D=3D NL80211_IFTYPE_AP) + mt7601u_mac_set_beacon(dev, vif, info); + + if ((changed & BSS_CHANGED_BEACON_ENABLED) && + vif->type =3D=3D 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); + } =20 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, stru= ct ieee80211_vif *vif, mutex_unlock(&dev->mutex); } =20 +static int mt7601u_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif = *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt7601u_dev *dev =3D hw->priv; + int err =3D 0; + + mutex_lock(&dev->mutex); + + /* Clear the wcid Table */ + for (int i =3D 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 =3D 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 =3D { .config =3D mt7601u_config, .configure_filter =3D mt76_configure_filter, .bss_info_changed =3D mt7601u_bss_info_changed, + .start_ap =3D mt7601u_start_ap, + .stop_ap =3D mt7601u_stop_ap, .sta_add =3D mt7601u_sta_add, .sta_remove =3D mt7601u_sta_remove, .sta_notify =3D 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_pr= eamb); -void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int inte= rval); +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 *ma= c); void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt7601u/tx.c b/drivers/net/wirel= ess/mediatek/mt7601u/tx.c index 5aeeac0dd9fe7..47c78c4ff5144 100644 --- a/drivers/net/wireless/mediatek/mt7601u/tx.c +++ b/drivers/net/wireless/mediatek/mt7601u/tx.c @@ -27,6 +27,14 @@ static u8 q2hwq(u8 q) static u8 skb2q(struct sk_buff *skb) { int qid =3D skb_get_queue_mapping(skb); + struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr =3D (struct ieee80211_hdr *)skb->data; + + if (ieee80211_is_mgmt(hdr->frame_control) || + (info->flags & IEEE80211_TX_CTL_INJECTED)) { + skb_set_queue_mapping(skb, MT_TXQ_VO); + return q2hwq(MT_TXQ_VO); + } =20 if (WARN_ON(qid >=3D MT_TXQ_PSD)) { qid =3D MT_TXQ_BE; @@ -134,6 +142,9 @@ mt7601u_push_txwi(struct mt7601u_dev *dev, struct sk_bu= ff *skb, struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rate =3D &info->control.rates[0]; struct mt76_txwi *txwi; + struct ieee80211_hdr *hdr =3D (struct ieee80211_hdr *)skb->data; + bool is_mgmt =3D ieee80211_is_mgmt(hdr->frame_control); + bool is_mcast =3D is_multicast_ether_addr(hdr->addr1); unsigned long flags; bool is_probe; u32 pkt_id; @@ -148,14 +159,14 @@ mt7601u_push_txwi(struct mt7601u_dev *dev, struct sk_= buff *skb, info->control.rates, 1); =20 spin_lock_irqsave(&dev->lock, flags); - if (rate->idx < 0 || !rate->count) + if (!is_mgmt && (rate->idx < 0 || !rate->count)) rate_ctl =3D wcid->tx_rate; else rate_ctl =3D mt76_mac_tx_rate_val(dev, rate, &nss); spin_unlock_irqrestore(&dev->lock, flags); txwi->rate_ctl =3D cpu_to_le16(rate_ctl); =20 - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && sta && !is_mcast) txwi->ack_ctl |=3D MT_TXWI_ACK_CTL_REQ; if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) txwi->ack_ctl |=3D MT_TXWI_ACK_CTL_NSEQ; @@ -197,6 +208,8 @@ void mt7601u_tx(struct ieee80211_hw *hw, struct ieee802= 11_tx_control *control, struct mt76_sta *msta =3D NULL; struct mt76_wcid *wcid =3D dev->mon_wcid; struct mt76_txwi *txwi; + struct ieee80211_hdr *hdr =3D (struct ieee80211_hdr *)skb->data; + bool is_mcast =3D is_multicast_ether_addr(hdr->addr1); int pkt_len =3D skb->len; int hw_q =3D skb2q(skb); =20 @@ -211,7 +224,7 @@ void mt7601u_tx(struct ieee80211_hw *hw, struct ieee802= 11_tx_control *control, if (sta) { msta =3D (struct mt76_sta *) sta->drv_priv; wcid =3D &msta->wcid; - } else if (vif) { + } else if (vif && is_mcast) { struct mt76_vif *mvif =3D (struct mt76_vif *)vif->drv_priv; =20 wcid =3D &mvif->group_wcid; --=20 2.55.0