[PATCH 12/15] wifi: mt76: mt7925: add ULW event handling and peer ULW update
Sean Wang
sean.wang at kernel.org
Mon Aug 24 12:52:24 PDT 2026
From: Stella Liu <yu-ching.liu at mediatek.com>
Forward NAN Unaligned Window attributes between FW and mac80211:
report ULW updates from FW via cfg80211_nan_ulw_update() and push
peer ULW attributes to FW with NAN_UNI_CMD_UPDATE_ULW.
Co-developed-by: Sean Wang <sean.wang at mediatek.com>
Signed-off-by: Sean Wang <sean.wang at mediatek.com>
Signed-off-by: Stella Liu <yu-ching.liu at mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/nan.c | 84 +++++++++++++++++++
.../net/wireless/mediatek/mt76/mt7925/nan.h | 40 ++++++++-
2 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/nan.c b/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
index 16fb196e1bf5..53736b156f69 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
@@ -397,6 +397,52 @@ mt7925_nan_mcu_handle_de_event(struct mt792x_dev *dev, struct tlv *tlv)
ieee80211_nan_cluster_joined(dev->nan_vif, cluster_id, true, GFP_KERNEL);
}
+static void
+mt7925_nan_handle_ulw_update(struct mt792x_dev *dev, struct tlv *tlv)
+{
+ struct mt7925_nan_ulw_event *evt;
+ struct mt7925_nan_ulw_attr attr;
+ struct wireless_dev *wdev;
+ u16 len;
+
+ if (!dev || !tlv)
+ return;
+
+ if (!dev->nan_vif || !ieee80211_vif_nan_started(dev->nan_vif))
+ return;
+
+ len = le16_to_cpu(tlv->len);
+ if (len < sizeof(*tlv) + sizeof(*evt)) {
+ dev_warn(dev->mt76.dev,
+ "nan: short ulw event tlv len=%u\n", len);
+ return;
+ }
+
+ evt = (struct mt7925_nan_ulw_event *)tlv->data;
+ wdev = ieee80211_vif_to_wdev(dev->nan_vif);
+ if (!wdev)
+ return;
+
+ dev_dbg(dev->mt76.dev,
+ "nan: ulw_update wdev=%p owner_nlportid=%u sched_id=%u seq=%u dur=%u\n",
+ wdev, wdev->owner_nlportid,
+ evt->sched_id, evt->seq_id, le32_to_cpu(evt->duration));
+
+ /* Reorder the FW fields into NAN spec Table 109 attribute layout */
+ attr.attr_id = NAN_ULW_ATTR_ID;
+ attr.length = cpu_to_le16(NAN_ULW_FIXED_PAYLOAD);
+ attr.sched_id = evt->sched_id;
+ attr.seq_id = evt->seq_id;
+ attr.start_time = evt->start_time;
+ attr.duration = evt->duration;
+ attr.period = evt->period;
+ attr.count_down = evt->count_down;
+ attr.ulw_overwrite = evt->ulw_overwrite;
+
+ cfg80211_nan_ulw_update(wdev, (const u8 *)&attr, sizeof(attr),
+ GFP_KERNEL);
+}
+
void mt7925_nan_mcu_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct tlv *tlv;
@@ -425,6 +471,9 @@ void mt7925_nan_mcu_event(struct mt792x_dev *dev, struct sk_buff *skb)
case NAN_UNI_EVENT_REPORT_DW_START:
mt7925_nan_handle_dw_ind(dev, tlv);
break;
+ case NAN_UNI_EVENT_ID_ULW_UPDATE:
+ mt7925_nan_handle_ulw_update(dev, tlv);
+ break;
default:
break;
}
@@ -736,6 +785,37 @@ static int mt7925_nan_update_crb_tlv(struct sk_buff *skb,
return 0;
}
+static int
+mt7925_nan_peer_ulw_tlv(struct sk_buff *skb,
+ struct ieee80211_sta *sta,
+ struct mt792x_sta *msta)
+{
+ struct mt7925_nan_update_ulw_tlv *ulw_tlv = NULL;
+ struct ieee80211_nan_peer_sched *sched = NULL;
+ struct tlv *tlv = NULL;
+
+ if (!skb || !sta || !msta)
+ return -EINVAL;
+
+ sched = sta->nan_sched;
+ if (!sched || !sched->init_ulw || !sched->ulw_size)
+ return 0; /* No ULW to send, not an error */
+
+ if (sched->ulw_size > NAN_ULW_MAX_SIZE)
+ return -EINVAL;
+
+ tlv = mt76_connac_mcu_add_tlv(skb, NAN_UNI_CMD_UPDATE_ULW,
+ sizeof(struct mt7925_nan_update_ulw_tlv));
+ if (!tlv)
+ return -ENOMEM;
+
+ ulw_tlv = (struct mt7925_nan_update_ulw_tlv *)tlv;
+ ether_addr_copy(ulw_tlv->nmi_addr, sta->addr);
+ memcpy(ulw_tlv->ulw_attr, sched->init_ulw, sched->ulw_size);
+
+ return 0;
+}
+
int mt792x_nan_set_peer_schedule(struct mt792x_dev *dev,
struct ieee80211_sta *sta)
{
@@ -788,6 +868,10 @@ int mt792x_nan_set_peer_schedule(struct mt792x_dev *dev,
goto free_skb;
}
+ ret = mt7925_nan_peer_ulw_tlv(skb, sta, msta);
+ if (ret)
+ goto free_skb;
+
ret = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(NAN), true);
if (ret && idx_allocated)
goto clear_idx;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/nan.h b/drivers/net/wireless/mediatek/mt76/mt7925/nan.h
index 32e2e9cfffc7..c9207b5c899e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/nan.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/nan.h
@@ -50,7 +50,8 @@
(sizeof(struct mt7925_nan_common_hdr) + \
sizeof(struct mt7925_nan_sched_manage_peer_rec_tlv) + \
sizeof(struct mt7925_nan_sched_update_peer_cap_tlv) + \
- sizeof(struct mt7925_nan_sched_update_crb_tlv))
+ sizeof(struct mt7925_nan_sched_update_crb_tlv) + \
+ sizeof(struct mt7925_nan_update_ulw_tlv))
/* NAN Availability Attribute */
#define NAN_AVAIL_ATTR_ID_OFFSET 0
@@ -81,6 +82,7 @@ enum nan_uni_cmd_tag {
NAN_UNI_CMD_UPDATE_CRB = 10,
NAN_UNI_CMD_MANAGE_PEER_SCH_RECORD = 12,
NAN_UNI_CMD_MAP_STA_RECORD = 13,
+ NAN_UNI_CMD_UPDATE_ULW = 16,
NAN_UNI_CMD_UPDATE_AVAILABILITY_CTRL = 20,
NAN_UNI_CMD_UPDATE_PEER_CAPABILITY = 21,
NAN_UNI_CMD_CHANGE_NMI_ADDRESS = 24,
@@ -92,6 +94,7 @@ enum nan_uni_cmd_tag {
enum nan_uni_event_tag {
NAN_UNI_EVENT_ID_DE_EVENT_IND = 19,
+ NAN_UNI_EVENT_ID_ULW_UPDATE = 39,
NAN_UNI_EVENT_REPORT_DW_START = 59,
NAN_UNI_EVENT_REPORT_DW_END = 60,
};
@@ -165,6 +168,32 @@ struct nan_rpt_dw_evt {
__le16 dw_num;
};
+#define NAN_ULW_ATTR_ID 0x17
+#define NAN_ULW_FIXED_PAYLOAD 16 /* Table 109 fixed fields */
+
+struct mt7925_nan_ulw_event {
+ u8 sched_id;
+ u8 seq_id;
+ u8 count_down;
+ u8 ulw_overwrite;
+ __le32 start_time;
+ __le32 duration;
+ __le32 period;
+} __packed;
+
+/* ULW attribute laid out in NAN spec Table 109 field order */
+struct mt7925_nan_ulw_attr {
+ u8 attr_id;
+ __le16 length;
+ u8 sched_id;
+ u8 seq_id;
+ __le32 start_time;
+ __le32 duration;
+ __le32 period;
+ u8 count_down;
+ u8 ulw_overwrite;
+} __packed;
+
struct mt7925_nan_conf_dw {
u8 config_2dot4g_dw_band;
__le32 dw_2dot4g_interval_val;
@@ -389,6 +418,15 @@ struct mt7925_nan_sched_update_crb_tlv {
struct mt7925_nan_sched_faw_ndc_timeline faw_ndc_timeline[NAN_TIMELINE_MGMT_SIZE];
} __packed __aligned(4);
+#define NAN_ULW_MAX_SIZE 256
+
+struct mt7925_nan_update_ulw_tlv {
+ __le16 tag;
+ __le16 len;
+ u8 nmi_addr[ETH_ALEN];
+ u8 ulw_attr[NAN_ULW_MAX_SIZE];
+} __packed __aligned(4);
+
struct mt7925_nan_sched_map_sta_rec_tlv {
__le16 tag;
__le16 len;
--
2.43.0
More information about the Linux-mediatek
mailing list