blob: e7146ca6df8a062ca2b0c7be5ea536639dc485d9 [file] [log] [blame]
developerd0c89452024-10-11 16:53:27 +08001From c16fd657d9955992ab12c22ac068c7f9d0035ed3 Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: mtk20656 <chank.chen@mediatek.com>
3Date: Sat, 20 Jan 2024 12:03:24 +0800
developerd0c89452024-10-11 16:53:27 +08004Subject: [PATCH 106/223] mtk: mt76: mt7996: Add connac3 csi feature.
developer66e89bc2024-04-23 14:50:01 +08005
61. format align to wifi6.
72. add bw320 support.
83. add active mode.
9
developer05f3b2b2024-08-19 19:17:34 +080010Fix csi bug with single wiphy design.
11
developerd0c89452024-10-11 16:53:27 +080012Change-Id: If37ac6de4781c3673671707ee3ee243dda8163f8
13Change-Id: I7761e2883bb08939917432df075062fb78de3bee
developer66e89bc2024-04-23 14:50:01 +080014Signed-off-by: mtk20656 <chank.chen@mediatek.com>
15---
16 mt76_connac_mcu.h | 2 +
17 mt7996/init.c | 22 +++
18 mt7996/main.c | 3 +
19 mt7996/mcu.c | 465 ++++++++++++++++++++++++++++++++++++++++++++++
20 mt7996/mcu.h | 105 +++++++++++
21 mt7996/mt7996.h | 55 ++++++
developer05f3b2b2024-08-19 19:17:34 +080022 mt7996/vendor.c | 247 ++++++++++++++++++++++++
23 mt7996/vendor.h | 52 ++++++
24 8 files changed, 951 insertions(+)
developer66e89bc2024-04-23 14:50:01 +080025
26diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
developerd0c89452024-10-11 16:53:27 +080027index f6b472ef..11c147cd 100644
developer66e89bc2024-04-23 14:50:01 +080028--- a/mt76_connac_mcu.h
29+++ b/mt76_connac_mcu.h
developerd0c89452024-10-11 16:53:27 +080030@@ -1066,6 +1066,7 @@ enum {
developer66e89bc2024-04-23 14:50:01 +080031 MCU_UNI_EVENT_THERMAL = 0x35,
32 MCU_UNI_EVENT_NIC_CAPAB = 0x43,
33 MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
34+ MCU_UNI_EVENT_CSI_REPORT = 0x4A,
35 MCU_UNI_EVENT_WED_RRO = 0x57,
36 MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
37 MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
developerd0c89452024-10-11 16:53:27 +080038@@ -1303,6 +1304,7 @@ enum {
developer66e89bc2024-04-23 14:50:01 +080039 MCU_UNI_CMD_TESTMODE_TRX_PARAM = 0x42,
40 MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
41 MCU_UNI_CMD_PRECAL_RESULT = 0x47,
42+ MCU_UNI_CMD_CSI_CTRL = 0x4A,
43 MCU_UNI_CMD_THERMAL_CAL = 0x4c,
44 MCU_UNI_CMD_RRO = 0x57,
45 MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
46diff --git a/mt7996/init.c b/mt7996/init.c
developerd0c89452024-10-11 16:53:27 +080047index f26687df..211ad40c 100644
developer66e89bc2024-04-23 14:50:01 +080048--- a/mt7996/init.c
49+++ b/mt7996/init.c
developer05f3b2b2024-08-19 19:17:34 +080050@@ -807,6 +807,24 @@ error:
developer66e89bc2024-04-23 14:50:01 +080051 return ret;
52 }
53
54+#ifdef CONFIG_MTK_VENDOR
55+static int mt7996_unregister_csi(struct mt7996_phy *phy)
56+{
57+ struct csi_data *c, *tmp_c;
58+
59+ spin_lock_bh(&phy->csi.lock);
60+ phy->csi.enable = 0;
61+
62+ list_for_each_entry_safe(c, tmp_c, &phy->csi.list, node) {
63+ list_del(&c->node);
64+ kfree(c);
65+ }
66+ spin_unlock_bh(&phy->csi.lock);
67+
68+ return 0;
69+}
70+#endif
71+
72 static void
73 mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
74 {
developer05f3b2b2024-08-19 19:17:34 +080075@@ -818,6 +836,10 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
developer66e89bc2024-04-23 14:50:01 +080076 /* TODO: FIXME: temp for single wiphy support */
77 phy->mt76->hw = phy->mt76->ori_hw;
78
79+#ifdef CONFIG_MTK_VENDOR
80+ mt7996_unregister_csi(phy);
81+#endif
82+
83 mt7996_unregister_thermal(phy);
84
85 mphy = phy->dev->mt76.phys[band];
86diff --git a/mt7996/main.c b/mt7996/main.c
developerd0c89452024-10-11 16:53:27 +080087index b7096901..32a37936 100644
developer66e89bc2024-04-23 14:50:01 +080088--- a/mt7996/main.c
89+++ b/mt7996/main.c
developerd0c89452024-10-11 16:53:27 +080090@@ -1306,6 +1306,9 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +080091 struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
92 unsigned long rem = sta->valid_links ?: BIT(0);
93
94+#ifdef CONFIG_MTK_VENDOR
95+ mt7996_mcu_set_csi(&dev->phy, 2, 8, 1, 0, sta->addr);
96+#endif
97 mt7996_mac_sta_remove_links(dev, vif, sta, rem);
98 }
99
100diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +0800101index 8034c8ab..56bb32a0 100644
developer66e89bc2024-04-23 14:50:01 +0800102--- a/mt7996/mcu.c
103+++ b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +0800104@@ -658,6 +658,263 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
developer66e89bc2024-04-23 14:50:01 +0800105 }
106 }
107
108+static int
109+csi_integrate_segment_data(struct mt7996_phy *phy, struct csi_data *csi)
110+{
111+ struct csi_data *csi_temp = NULL;
112+
113+ if (csi->segment_num == 0 && csi->remain_last == 0)
114+ return CSI_CHAIN_COMPLETE;
115+ else if (csi->segment_num == 0 && csi->remain_last == 1) {
116+ memcpy(&phy->csi.buffered_csi,
117+ csi, sizeof(struct csi_data));
118+
119+ return CSI_CHAIN_SEGMENT_FIRST;
120+ } else if (csi->segment_num != 0) {
121+ csi_temp = &phy->csi.buffered_csi;
122+ if (csi->chain_info != csi_temp->chain_info ||
123+ csi->segment_num != (csi_temp->segment_num + 1))
124+ return CSI_CHAIN_SEGMENT_ERR;
125+
126+ memcpy(&csi_temp->data_i[csi_temp->data_num],
127+ csi->data_i, csi->data_num * sizeof(s16));
128+
129+ memcpy(&csi_temp->data_q[csi_temp->data_num],
130+ csi->data_q, csi->data_num * sizeof(s16));
131+
132+ csi_temp->data_num += csi->data_num;
133+ csi_temp->segment_num = csi->segment_num;
134+ csi_temp->remain_last = csi->remain_last;
135+
136+ if (csi->remain_last == 0)
137+ return CSI_CHAIN_SEGMENT_LAST;
138+ else if (csi->remain_last == 1)
139+ return CSI_CHAIN_SEGMENT_MIDDLE;
140+ }
141+
142+ return CSI_CHAIN_ERR;
143+}
144+
145+static int
146+mt7996_mcu_csi_report_data(struct mt7996_phy *phy, u8 *tlv_buf, u32 len)
147+{
148+ int ret, i;
149+ struct csi_data *current_csi;
150+ struct csi_data *target_csi;
151+ struct csi_tlv *tlv_data;
152+ u8 *buf_tmp;
153+ u32 rx_info, tx_rx_idx;
154+ u32 buf_len_last, offset;
155+
156+ buf_tmp = tlv_buf;
157+ buf_len_last = len;
158+ offset = sizeof(((struct csi_tlv *)0)->basic);
159+
160+ current_csi = kzalloc(sizeof(*current_csi), GFP_KERNEL);
161+ if (!current_csi)
162+ return -ENOMEM;
163+
164+ while (buf_len_last >= offset) {
165+ u32 tag, len;
166+ s16 *data_tmp = NULL;
167+
168+ tlv_data = (struct csi_tlv *)buf_tmp;
169+ tag = le32_to_cpu(tlv_data->basic.tag);
170+ len = le32_to_cpu(tlv_data->basic.len);
171+
172+ switch (tag) {
173+ case CSI_EVENT_FW_VER:
174+ current_csi->fw_ver = le32_to_cpu(tlv_data->info);
175+ break;
176+ case CSI_EVENT_CBW:
177+ current_csi->ch_bw = le32_to_cpu(tlv_data->info);
178+ break;
179+ case CSI_EVENT_RSSI:
180+ current_csi->rssi = le32_to_cpu(tlv_data->info);
181+ break;
182+ case CSI_EVENT_SNR:
183+ current_csi->snr = le32_to_cpu(tlv_data->info);
184+ break;
185+ case CSI_EVENT_BAND:
186+ current_csi->band = le32_to_cpu(tlv_data->info);
187+
188+ if (current_csi->band != phy->mt76->band_idx) {
189+ kfree(current_csi);
190+ return -EINVAL;
191+ }
192+
193+ break;
194+ case CSI_EVENT_CSI_NUM:
195+ current_csi->data_num = le32_to_cpu(tlv_data->info);
196+
197+ if (current_csi->data_num > CSI_BW80_DATA_COUNT) {
198+ kfree(current_csi);
199+ return -EINVAL;
200+ }
201+
202+ break;
203+ case CSI_EVENT_CSI_I_DATA:
204+ if (len != sizeof(s16) * current_csi->data_num) {
205+ kfree(current_csi);
206+ return -EINVAL;
207+ }
208+
209+ data_tmp = tlv_data->data;
210+ for (i = 0; i < current_csi->data_num; i++)
211+ current_csi->data_i[i] = le16_to_cpu(*(data_tmp + i));
212+ break;
213+ case CSI_EVENT_CSI_Q_DATA:
214+ if (len != sizeof(s16) * current_csi->data_num) {
215+ kfree(current_csi);
216+ return -EINVAL;
217+ }
218+
219+ data_tmp = tlv_data->data;
220+ for (i = 0; i < current_csi->data_num; i++)
221+ current_csi->data_q[i] = le16_to_cpu(*(data_tmp + i));
222+ break;
223+ case CSI_EVENT_DBW:
224+ current_csi->data_bw = le32_to_cpu(tlv_data->info);
225+ break;
226+ case CSI_EVENT_CH_IDX:
227+ current_csi->pri_ch_idx = le32_to_cpu(tlv_data->info);
228+ break;
229+ case CSI_EVENT_TA:
230+ memcpy(current_csi->ta, tlv_data->mac, ETH_ALEN);
231+ break;
232+ case CSI_EVENT_EXTRA_INFO:
233+ current_csi->ext_info = le32_to_cpu(tlv_data->info);
234+ break;
235+ case CSI_EVENT_RX_MODE:
236+ rx_info = le32_to_cpu(tlv_data->info);
237+ current_csi->rx_mode = u32_get_bits(rx_info, GENMASK(15, 0));
238+ current_csi->rx_rate = u32_get_bits(rx_info, GENMASK(31, 16));
239+ break;
240+ case CSI_EVENT_H_IDX:
241+ current_csi->chain_info = le32_to_cpu(tlv_data->info);
242+ break;
243+ case CSI_EVENT_TX_RX_IDX:
244+ tx_rx_idx = le32_to_cpu(tlv_data->info);
245+ current_csi->tx_idx = u32_get_bits(tx_rx_idx, GENMASK(31, 16));
246+ current_csi->rx_idx = u32_get_bits(tx_rx_idx, GENMASK(15, 0));
247+ break;
248+ case CSI_EVENT_TS:
249+ current_csi->ts = le32_to_cpu(tlv_data->info);
250+
251+ if (phy->csi.interval &&
252+ current_csi->ts < phy->csi.last_record + phy->csi.interval) {
253+ kfree(current_csi);
254+ return 0;
255+ }
256+
257+ break;
258+ case CSI_EVENT_PKT_SN:
259+ current_csi->pkt_sn = le32_to_cpu(tlv_data->info);
260+ break;
261+ case CSI_EVENT_BW_SEG:
262+ current_csi->segment_num = le32_to_cpu(tlv_data->info);
263+ break;
264+ case CSI_EVENT_REMAIN_LAST:
265+ current_csi->remain_last = le32_to_cpu(tlv_data->info);
266+ break;
267+ case CSI_EVENT_TR_STREAM:
268+ current_csi->tr_stream = le32_to_cpu(tlv_data->info);
269+ break;
270+ default:
271+ break;
272+ };
273+
274+ buf_len_last -= (offset + len);
275+
276+ if (buf_len_last >= offset)
277+ buf_tmp += (offset + len);
278+ }
279+
280+ /* integret the bw80 segment */
281+ if (current_csi->ch_bw >= CSI_BW80) {
282+ ret = csi_integrate_segment_data(phy, current_csi);
283+
284+ switch (ret) {
285+ case CSI_CHAIN_ERR:
286+ case CSI_CHAIN_SEGMENT_ERR:
287+ kfree(current_csi);
288+ return -EINVAL;
289+ break;
290+ case CSI_CHAIN_SEGMENT_FIRST:
291+ case CSI_CHAIN_SEGMENT_MIDDLE:
292+ kfree(current_csi);
293+ return 0;
294+ break;
295+ case CSI_CHAIN_COMPLETE:
296+ target_csi = current_csi;
297+ break;
298+ case CSI_CHAIN_SEGMENT_LAST:
299+ target_csi = current_csi;
300+ memcpy(target_csi, &phy->csi.buffered_csi, sizeof(struct csi_data));
301+ memset(&phy->csi.buffered_csi, 0, sizeof(struct csi_data));
302+ break;
303+ default:
304+ break;
305+ }
306+ } else {
307+ target_csi = current_csi;
308+ }
309+
310+ /* put the csi data into list */
311+ INIT_LIST_HEAD(&target_csi->node);
312+ spin_lock_bh(&phy->csi.lock);
313+
314+ if (!phy->csi.enable) {
315+ kfree(target_csi);
316+ goto out;
317+ }
318+
319+ list_add_tail(&target_csi->node, &phy->csi.list);
320+ phy->csi.count++;
321+
322+ if (phy->csi.count > CSI_MAX_BUF_NUM) {
323+ struct csi_data *old;
324+
325+ old = list_first_entry(&phy->csi.list,
326+ struct csi_data, node);
327+
328+ list_del(&old->node);
329+ kfree(old);
330+ phy->csi.count--;
331+ }
332+
333+ if (target_csi->chain_info & BIT(15)) /* last chain */
334+ phy->csi.last_record = target_csi->ts;
335+
336+out:
337+ spin_unlock_bh(&phy->csi.lock);
338+ return 0;
339+}
340+
341+void
342+mt7996_mcu_csi_report_event(struct mt7996_dev *dev, struct sk_buff *skb)
343+{
344+ struct mt7996_mcu_csi_event *event;
345+ struct mt76_phy *mphy;
346+ struct mt7996_phy *phy;
347+
348+ event = (struct mt7996_mcu_csi_event *)skb->data;
349+
350+ mphy = dev->mt76.phys[event->band_idx];
351+ if (!mphy)
352+ return;
353+
354+ phy = mphy->priv;
355+
356+ switch (le16_to_cpu(event->tag)) {
357+ case UNI_EVENT_CSI_DATA:
358+ mt7996_mcu_csi_report_data(phy, event->tlv_buf, le16_to_cpu(event->len) - 4);
359+ break;
360+ default:
361+ break;
362+ }
363+}
364+
365 static void
366 mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
367 {
developerd0c89452024-10-11 16:53:27 +0800368@@ -901,6 +1158,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
developer66e89bc2024-04-23 14:50:01 +0800369 case MCU_UNI_EVENT_BF:
370 mt7996_mcu_rx_bf_event(dev, skb);
371 break;
372+#endif
373+#ifdef CONFIG_MTK_VENDOR
374+ case MCU_UNI_EVENT_CSI_REPORT:
375+ mt7996_mcu_csi_report_event(dev, skb);
376+ break;
377 #endif
378 default:
379 break;
developerd0c89452024-10-11 16:53:27 +0800380@@ -6006,4 +6268,207 @@ void mt7996_set_beacon_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
developer66e89bc2024-04-23 14:50:01 +0800381
382 mt7996_mcu_add_beacon(hw, &vif->bss_conf, &mvif->deflink, val);
383 }
384+
385+static int mt7996_mcu_set_csi_enable(struct mt7996_phy *phy, u16 tag)
386+{
387+ struct {
388+ u8 band;
389+ u8 rsv1[3];
390+
391+ __le16 tag;
392+ __le16 len;
393+ } __packed req = {
394+ .band = phy->mt76->band_idx,
395+ .tag = cpu_to_le16(tag),
396+ .len = cpu_to_le16(sizeof(req) - 4),
397+ };
398+
399+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(CSI_CTRL), &req,
400+ sizeof(req), false);
401+}
402+
403+static int mt7996_mcu_set_csi_frame_type(struct mt7996_phy *phy, u16 tag, u8 type_idx, u32 type)
404+{
405+ struct {
406+ u8 band;
407+ u8 rsv1[3];
408+
409+ __le16 tag;
410+ __le16 len;
411+ u8 frame_type_idx;
412+ u8 frame_type;
413+ u8 rsv2[2];
414+ } __packed req = {
415+ .band = phy->mt76->band_idx,
416+ .tag = cpu_to_le16(tag),
417+ .len = cpu_to_le16(sizeof(req) - 4),
418+ .frame_type_idx = type_idx,
419+ .frame_type = type,
420+ };
421+
422+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(CSI_CTRL), &req,
423+ sizeof(req), false);
424+}
425+
426+static int mt7996_mcu_set_csi_chain_filter(struct mt7996_phy *phy, u16 tag, u8 func, u32 value)
427+{
428+ struct {
429+ u8 band;
430+ u8 rsv1[3];
431+
432+ __le16 tag;
433+ __le16 len;
434+ u8 function;
435+ u8 chain_value;
436+ u8 rsv2[2];
437+ } __packed req = {
438+ .band = phy->mt76->band_idx,
439+ .tag = cpu_to_le16(tag),
440+ .len = cpu_to_le16(sizeof(req) - 4),
441+ .function = func,
442+ .chain_value = value,
443+ };
444+
445+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(CSI_CTRL), &req,
446+ sizeof(req), false);
447+}
448+
449+static int mt7996_mcu_set_csi_sta_filter(struct mt7996_phy *phy, u16 tag, u32 op, u8 *sta_mac)
450+{
451+ struct {
452+ u8 band;
453+ u8 rsv1[3];
454+
455+ __le16 tag;
456+ __le16 len;
457+ u8 operation;
458+ u8 rsv2[1];
459+ u8 mac[6];
460+ } __packed req = {
461+ .band = phy->mt76->band_idx,
462+ .tag = cpu_to_le16(tag),
463+ .len = cpu_to_le16(sizeof(req) - 4),
464+ .operation = op,
465+ };
466+
467+ memcpy(req.mac, sta_mac, ETH_ALEN);
468+
469+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(CSI_CTRL), &req,
470+ sizeof(req), false);
471+}
472+
473+static int mt7996_mcu_set_csi_active_mode(struct mt7996_phy *phy, u16 tag,
474+ u32 interval, u8 frame_idx, u8 subframe_idx, u32 bitmap)
475+{
476+ struct {
477+ u8 band;
478+ u8 rsv1[3];
479+
480+ __le16 tag;
481+ __le16 len;
482+ __le16 interval; /* uint: ms */
483+ u8 frame_type_idx;
484+ u8 subframe_type_idx;
485+ __le32 bitmap; /* sta wcid bitmap */
486+ u8 rsv2[4];
487+ } __packed req = {
488+ .band = phy->mt76->band_idx,
489+ .tag = cpu_to_le16(tag),
490+ .len = cpu_to_le16(sizeof(req) - 4),
491+ .interval = cpu_to_le16(interval),
492+ .frame_type_idx = frame_idx,
493+ .subframe_type_idx = subframe_idx,
494+ .bitmap = cpu_to_le32(bitmap),
495+ };
496+
497+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(CSI_CTRL), &req,
498+ sizeof(req), false);
499+}
500+
501+void mt7996_csi_wcid_bitmap_update(void *data, struct ieee80211_sta *sta)
502+{
503+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
504+ struct mt7996_phy *phy = msta->vif->deflink.phy;
505+ struct csi_bitmap_info_update *sta_info = (struct csi_bitmap_info_update *)data;
506+ u16 wcid = 0;
507+
508+#define CSI_ACTIVE_MODE_ADD 1
509+#define CSI_ACTIVE_MODE_REMOVE 0
510+
511+ if (!memcmp(sta_info->addr, sta->addr, ETH_ALEN)) {
512+ wcid = msta->deflink.wcid.idx;
513+
514+ /* active mode: only support station with wcid less than 32 */
515+ if (wcid > 32)
516+ return;
517+
518+ if (sta_info->action == CSI_ACTIVE_MODE_ADD)
519+ phy->csi.active_bitmap |= BIT(wcid);
520+ else if (sta_info->action == CSI_ACTIVE_MODE_REMOVE)
521+ phy->csi.active_bitmap &= ~(BIT(wcid));
522+ }
523+}
524+
525+int mt7996_mcu_set_csi(struct mt7996_phy *phy, u8 mode,
526+ u8 cfg, u8 v1, u32 v2, u8 *mac_addr)
527+{
528+ switch (mode) {
529+ case CSI_CONTROL_MODE_STOP:
530+ return mt7996_mcu_set_csi_enable(phy, UNI_CMD_CSI_STOP);
531+ case CSI_CONTROL_MODE_START:
532+ return mt7996_mcu_set_csi_enable(phy, UNI_CMD_CSI_START);
533+ case CSI_CONTROL_MODE_SET:
534+ switch (cfg) {
535+ case CSI_CONFIG_FRAME_TYPE:
536+ if (v2 > 255)
537+ return -EINVAL;
538+
539+ return mt7996_mcu_set_csi_frame_type(phy,
540+ UNI_CMD_CSI_SET_FRAME_TYPE, v1, v2);
541+ case CSI_CONFIG_CHAIN_FILTER:
542+ if (v2 > 255)
543+ return -EINVAL;
544+
545+ return mt7996_mcu_set_csi_chain_filter(phy,
546+ UNI_CMD_CSI_SET_CHAIN_FILTER, v1, v2);
547+ case CSI_CONFIG_STA_FILTER:
548+ if (!is_valid_ether_addr(mac_addr))
549+ return -EINVAL;
550+
551+ if (v2 > 255)
552+ return -EINVAL;
553+
554+ return mt7996_mcu_set_csi_sta_filter(phy,
555+ UNI_CMD_CSI_SET_STA_FILTER, v2, mac_addr);
556+ case CSI_CONFIG_ACTIVE_MODE:
557+ if (is_valid_ether_addr(mac_addr)) {
558+ struct csi_bitmap_info_update sta_info;
559+
560+ if (v2 > 255)
561+ return -EINVAL;
562+
563+ memcpy(sta_info.addr, mac_addr, ETH_ALEN);
564+ sta_info.action = v2;
565+
566+ ieee80211_iterate_stations_atomic(phy->mt76->hw,
567+ mt7996_csi_wcid_bitmap_update, &sta_info);
568+ return 0;
569+ } else {
570+ u8 frame_type = v1 & 0x3;
571+ u8 frame_subtype = (v1 & 0x3c) >> 2;
572+
573+ /* active mode: max interval is 3000ms */
574+ if (v2 > 3000)
575+ return -EINVAL;
576+
577+ return mt7996_mcu_set_csi_active_mode(phy, UNI_CMD_CSI_SET_ACTIVE_MODE,
578+ v2, frame_type, frame_subtype, phy->csi.active_bitmap);
579+ }
580+ default:
581+ return -EINVAL;
582+ }
583+ default:
584+ return -EINVAL;
585+ }
586+}
587 #endif
588diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer05f3b2b2024-08-19 19:17:34 +0800589index f9f04680..42e9f525 100644
developer66e89bc2024-04-23 14:50:01 +0800590--- a/mt7996/mcu.h
591+++ b/mt7996/mcu.h
developer05f3b2b2024-08-19 19:17:34 +0800592@@ -1153,4 +1153,109 @@ struct fixed_rate_table_ctrl {
developer66e89bc2024-04-23 14:50:01 +0800593 u8 _rsv2;
594 } __packed;
595
596+#ifdef CONFIG_MTK_VENDOR
597+struct mt7996_mcu_csi_event {
598+ struct mt7996_mcu_rxd rxd;
599+
600+ u8 band_idx;
601+ u8 _rsv[3];
602+
603+ __le16 tag;
604+ __le16 len;
605+ u8 tlv_buf[0];
606+};
607+
608+enum UNI_EVENT_CSI_TAG_T {
609+ UNI_EVENT_CSI_DATA = 0,
610+ UNI_EVENT_CSI_MAX_NUM
611+};
612+
613+struct csi_tlv {
614+ struct {
615+ __le32 tag;
616+ __le32 len;
617+ } basic;
618+ union {
619+ u8 mac[ETH_ALEN];
620+ __le32 info;
621+ s16 data[0];
622+ };
623+} __packed;
624+
625+struct csi_bitmap_info_update {
626+ u8 action;
627+ u8 addr[ETH_ALEN];
628+};
629+
630+#define CSI_MAX_BUF_NUM 3000
631+
632+enum CSI_EVENT_TLV_TAG {
633+ CSI_EVENT_FW_VER,
634+ CSI_EVENT_CBW,
635+ CSI_EVENT_RSSI,
636+ CSI_EVENT_SNR,
637+ CSI_EVENT_BAND,
638+ CSI_EVENT_CSI_NUM,
639+ CSI_EVENT_CSI_I_DATA,
640+ CSI_EVENT_CSI_Q_DATA,
641+ CSI_EVENT_DBW,
642+ CSI_EVENT_CH_IDX,
643+ CSI_EVENT_TA,
644+ CSI_EVENT_EXTRA_INFO,
645+ CSI_EVENT_RX_MODE,
646+ CSI_EVENT_RSVD1,
647+ CSI_EVENT_RSVD2,
648+ CSI_EVENT_RSVD3,
649+ CSI_EVENT_RSVD4,
650+ CSI_EVENT_H_IDX,
651+ CSI_EVENT_TX_RX_IDX,
652+ CSI_EVENT_TS,
653+ CSI_EVENT_PKT_SN,
654+ CSI_EVENT_BW_SEG,
655+ CSI_EVENT_REMAIN_LAST,
656+ CSI_EVENT_TR_STREAM,
657+ CSI_EVENT_TLV_TAG_NUM,
658+};
659+
660+enum CSI_CHAIN_TYPE {
661+ CSI_CHAIN_ERR,
662+ CSI_CHAIN_COMPLETE,
663+ CSI_CHAIN_SEGMENT_FIRST,
664+ CSI_CHAIN_SEGMENT_MIDDLE,
665+ CSI_CHAIN_SEGMENT_LAST,
666+ CSI_CHAIN_SEGMENT_ERR,
667+};
668+
669+enum CSI_CONTROL_MODE_T {
670+ CSI_CONTROL_MODE_STOP,
671+ CSI_CONTROL_MODE_START,
672+ CSI_CONTROL_MODE_SET,
673+ CSI_CONTROL_MODE_NUM
674+};
675+
676+enum CSI_CONFIG_ITEM_T {
677+ CSI_CONFIG_RSVD1,
678+ CSI_CONFIG_WF,
679+ CSI_CONFIG_RSVD2,
680+ CSI_CONFIG_FRAME_TYPE,
681+ CSI_CONFIG_TX_PATH,
682+ CSI_CONFIG_OUTPUT_FORMAT,
683+ CSI_CONFIG_INFO,
684+ CSI_CONFIG_CHAIN_FILTER,
685+ CSI_CONFIG_STA_FILTER,
686+ CSI_CONFIG_ACTIVE_MODE,
687+ CSI_CONFIG_ITEM_NUM
688+};
689+
690+/* CSI config Tag */
691+enum UNI_CMD_CSI_TAG_T {
692+ UNI_CMD_CSI_STOP = 0,
693+ UNI_CMD_CSI_START = 1,
694+ UNI_CMD_CSI_SET_FRAME_TYPE = 2,
695+ UNI_CMD_CSI_SET_CHAIN_FILTER = 3,
696+ UNI_CMD_CSI_SET_STA_FILTER = 4,
697+ UNI_CMD_CSI_SET_ACTIVE_MODE = 5,
698+};
699+#endif
700+
701 #endif
702diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800703index 2a638a4a..eb38427b 100644
developer66e89bc2024-04-23 14:50:01 +0800704--- a/mt7996/mt7996.h
705+++ b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800706@@ -446,6 +446,47 @@ struct mt7996_air_monitor_ctrl {
developer66e89bc2024-04-23 14:50:01 +0800707 struct mt7996_air_monitor_group group[MT7996_AIR_MONITOR_MAX_GROUP];
708 struct mt7996_air_monitor_entry entry[MT7996_AIR_MONITOR_MAX_ENTRY];
709 };
710+
711+enum {
712+ CSI_BW20,
713+ CSI_BW40,
714+ CSI_BW80,
715+ CSI_BW160,
716+ CSI_BW320
717+};
718+
719+#define CSI_BW20_DATA_COUNT 64
720+#define CSI_BW40_DATA_COUNT 128
721+#define CSI_BW80_DATA_COUNT 256
722+#define CSI_BW160_DATA_COUNT 512
723+#define CSI_BW320_DATA_COUNT 1024
724+
725+struct csi_data {
726+ u8 fw_ver;
727+ u8 ch_bw;
728+ u16 data_num;
729+ s16 data_i[CSI_BW320_DATA_COUNT];
730+ s16 data_q[CSI_BW320_DATA_COUNT];
731+ u8 band;
732+ s8 rssi;
733+ u8 snr;
734+ u32 ts;
735+ u8 data_bw;
736+ u8 pri_ch_idx;
737+ u8 ta[ETH_ALEN];
738+ u32 ext_info;
739+ u16 rx_mode;
740+ u16 rx_rate;
741+ u32 chain_info;
742+ u16 tx_idx;
743+ u16 rx_idx;
744+ u32 segment_num;
745+ u8 remain_last;
746+ u16 pkt_sn;
747+ u8 tr_stream;
748+
749+ struct list_head node;
750+};
751 #endif
752
753 struct mt7996_rro_ba_session {
developerd0c89452024-10-11 16:53:27 +0800754@@ -542,6 +583,18 @@ struct mt7996_phy {
developer66e89bc2024-04-23 14:50:01 +0800755 u8 rts_bw_sig;
756 spinlock_t amnt_lock;
757 struct mt7996_air_monitor_ctrl amnt_ctrl;
758+
759+ struct {
760+ struct list_head list;
761+ spinlock_t lock;
762+ u32 count;
763+ bool enable;
764+
765+ struct csi_data buffered_csi;
766+ u32 active_bitmap;
767+ u32 interval;
768+ u32 last_record;
769+ } csi;
770 #endif
771 #ifdef CONFIG_MTK_DEBUG
772 bool sr_enable:1;
developerd0c89452024-10-11 16:53:27 +0800773@@ -1180,6 +1233,8 @@ void mt7996_mcu_set_mimo(struct mt7996_phy *phy);
developer66e89bc2024-04-23 14:50:01 +0800774 int mt7996_set_muru_cfg(struct mt7996_phy *phy, u8 action, u8 val);
775 int mt7996_mcu_set_muru_cfg(struct mt7996_phy *phy, void *data);
776 void mt7996_set_beacon_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
777+int mt7996_mcu_set_csi(struct mt7996_phy *phy, u8 mode,
778+ u8 cfg, u8 v1, u32 v2, u8 *mac_addr);
779 #endif
780
781 int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable);
782diff --git a/mt7996/vendor.c b/mt7996/vendor.c
developer05f3b2b2024-08-19 19:17:34 +0800783index 64ef5515..84b50ab2 100644
developer66e89bc2024-04-23 14:50:01 +0800784--- a/mt7996/vendor.c
785+++ b/mt7996/vendor.c
developer05f3b2b2024-08-19 19:17:34 +0800786@@ -119,6 +119,19 @@ beacon_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BEACON_CTRL] = {
developer66e89bc2024-04-23 14:50:01 +0800787 [MTK_VENDOR_ATTR_BEACON_CTRL_MODE] = { .type = NLA_U8 },
788 };
789
790+static const struct nla_policy
791+csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {
developer05f3b2b2024-08-19 19:17:34 +0800792+ [MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX] = { .type = NLA_U8 },
developer66e89bc2024-04-23 14:50:01 +0800793+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG] = {.type = NLA_NESTED },
794+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE] = { .type = NLA_U8 },
795+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE] = { .type = NLA_U8 },
796+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1] = { .type = NLA_U8 },
797+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2] = { .type = NLA_U32 },
798+ [MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR] = { .type = NLA_NESTED },
799+ [MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM] = { .type = NLA_U16 },
800+ [MTK_VENDOR_ATTR_CSI_CTRL_DATA] = { .type = NLA_NESTED },
801+};
802+
803 struct mt7996_amnt_data {
804 u8 idx;
805 u8 addr[ETH_ALEN];
developer05f3b2b2024-08-19 19:17:34 +0800806@@ -1000,7 +1013,226 @@ static int mt7996_vendor_beacon_ctrl(struct wiphy *wiphy,
developer66e89bc2024-04-23 14:50:01 +0800807
808 return 0;
809 }
810+static int mt7996_vendor_csi_ctrl(struct wiphy *wiphy,
811+ struct wireless_dev *wdev,
812+ const void *data,
813+ int data_len)
814+{
815+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
developer05f3b2b2024-08-19 19:17:34 +0800816+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
817+ struct mt7996_phy *phy;
818+ struct mt76_phy *mphy;
developer66e89bc2024-04-23 14:50:01 +0800819+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_CSI_CTRL];
developer05f3b2b2024-08-19 19:17:34 +0800820+ u8 band_idx = 0;
developer66e89bc2024-04-23 14:50:01 +0800821+ int err;
822+
823+ err = nla_parse(tb, MTK_VENDOR_ATTR_CSI_CTRL_MAX, data, data_len,
824+ csi_ctrl_policy, NULL);
825+ if (err)
826+ return err;
827+
developer05f3b2b2024-08-19 19:17:34 +0800828+ if (tb[MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX])
829+ band_idx = nla_get_u8(tb[MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX]);
830+
831+ if (!mt7996_band_valid(dev, band_idx))
832+ goto error;
833+
834+ mphy = dev->mt76.phys[band_idx];
835+ if (!mphy)
836+ goto error;
837+
838+ phy = (struct mt7996_phy *)mphy->priv;
839+ if (!phy)
840+ goto error;
841+
developer66e89bc2024-04-23 14:50:01 +0800842+ if (tb[MTK_VENDOR_ATTR_CSI_CTRL_CFG]) {
843+ u8 mode = 0, type = 0, v1 = 0;
844+ u32 v2 = 0;
845+ u8 mac_addr[ETH_ALEN] = {};
846+ struct nlattr *cur;
847+ int rem;
848+
849+ nla_for_each_nested(cur, tb[MTK_VENDOR_ATTR_CSI_CTRL_CFG], rem) {
850+ switch (nla_type(cur)) {
851+ case MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE:
852+ mode = nla_get_u8(cur);
853+ break;
854+ case MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE:
855+ type = nla_get_u8(cur);
856+ break;
857+ case MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1:
858+ v1 = nla_get_u8(cur);
859+ break;
860+ case MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2:
861+ v2 = nla_get_u32(cur);
862+ break;
863+ default:
864+ return -EINVAL;
865+ };
866+ }
867+
868+ if (tb[MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR]) {
869+ u8 idx = 0;
870+
871+ nla_for_each_nested(cur, tb[MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR], rem) {
872+ mac_addr[idx++] = nla_get_u8(cur);
873+ }
874+ }
875+
876+ err = mt7996_mcu_set_csi(phy, mode, type, v1, v2, mac_addr);
877+ if (err < 0)
878+ return err;
879+
880+ spin_lock_bh(&phy->csi.lock);
developer05f3b2b2024-08-19 19:17:34 +0800881+
developer66e89bc2024-04-23 14:50:01 +0800882+ phy->csi.enable = !!mode;
883+
884+ /* clean up old csi stats */
885+ if ((mode == CSI_CONTROL_MODE_STOP || mode == CSI_CONTROL_MODE_SET)
886+ && !list_empty(&phy->csi.list)) {
887+ struct csi_data *c, *tmp_c;
888+
889+ list_for_each_entry_safe(c, tmp_c, &phy->csi.list, node) {
890+ list_del(&c->node);
891+ kfree(c);
892+ phy->csi.count--;
893+ }
894+ } else if (mode == CSI_CONTROL_MODE_START) {
895+ phy->csi.last_record = 0;
896+ }
897+
898+ spin_unlock_bh(&phy->csi.lock);
899+
900+ if (mode == CSI_CONTROL_MODE_SET && type == CSI_CONFIG_STA_FILTER && v1 == 2)
901+ phy->csi.interval = v2;
902+ }
903+
904+ return 0;
developer05f3b2b2024-08-19 19:17:34 +0800905+
906+error:
907+ dev_err(dev->mt76.dev, "Invalid band idx: %d\n", band_idx);
908+ return -EINVAL;
developer66e89bc2024-04-23 14:50:01 +0800909+}
910+
911+static int
912+mt7996_vendor_csi_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
913+ struct sk_buff *skb, const void *data, int data_len,
914+ unsigned long *storage)
915+{
916+#define RESERVED_SET BIT(31)
917+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
developer05f3b2b2024-08-19 19:17:34 +0800918+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
919+ struct mt7996_phy *phy;
920+ struct mt76_phy *mphy;
developer66e89bc2024-04-23 14:50:01 +0800921+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {0};
developer05f3b2b2024-08-19 19:17:34 +0800922+ u8 band_idx = 0;
developer66e89bc2024-04-23 14:50:01 +0800923+ int err = 0;
924+
925+ if (*storage & RESERVED_SET) {
926+ if ((*storage & GENMASK(15, 0)) == 0)
927+ return -ENOENT;
928+ (*storage)--;
929+ }
930+
931+ if (data) {
932+ err = nla_parse(tb, MTK_VENDOR_ATTR_CSI_CTRL_MAX, data, data_len,
933+ csi_ctrl_policy, NULL);
934+ if (err)
935+ return err;
936+ }
937+
developer05f3b2b2024-08-19 19:17:34 +0800938+ if (tb[MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX])
939+ band_idx = nla_get_u8(tb[MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX]);
940+
941+ if (!mt7996_band_valid(dev, band_idx))
942+ return -EINVAL;
943
944+ mphy = dev->mt76.phys[band_idx];
945+ if (!mphy)
946+ return -EINVAL;
947+
948+ phy = (struct mt7996_phy *)mphy->priv;
949+ if (!phy)
950+ return -EINVAL;
951+
developer66e89bc2024-04-23 14:50:01 +0800952+ if (!(*storage & RESERVED_SET) && tb[MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM]) {
953+ *storage = nla_get_u16(tb[MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM]);
954+ *storage |= RESERVED_SET;
955+ }
956+
957+ spin_lock_bh(&phy->csi.lock);
958+
959+ if (!list_empty(&phy->csi.list)) {
960+ struct csi_data *csi;
961+ void *a, *b;
962+ int i;
963+
964+ csi = list_first_entry(&phy->csi.list, struct csi_data, node);
965+
966+ a = nla_nest_start(skb, MTK_VENDOR_ATTR_CSI_CTRL_DATA);
967+ if (!a)
968+ goto out;
969+
970+ if (nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_VER, 1) ||
971+ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_RSSI, csi->rssi) ||
972+ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_SNR, csi->snr) ||
973+ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_BW, csi->data_bw) ||
974+ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_CH_IDX, csi->pri_ch_idx) ||
975+ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_MODE, csi->rx_mode))
976+ goto out;
977+
978+ if (nla_put_u16(skb, MTK_VENDOR_ATTR_CSI_DATA_TX_ANT, csi->tx_idx) ||
979+ nla_put_u16(skb, MTK_VENDOR_ATTR_CSI_DATA_RX_ANT, csi->rx_idx))
980+ goto out;
981+
982+ if (nla_put_u32(skb, MTK_VENDOR_ATTR_CSI_DATA_INFO, csi->ext_info) ||
983+ nla_put_u32(skb, MTK_VENDOR_ATTR_CSI_DATA_CHAIN_INFO, csi->chain_info) ||
984+ nla_put_u32(skb, MTK_VENDOR_ATTR_CSI_DATA_TS, csi->ts))
985+ goto out;
986+
987+ b = nla_nest_start(skb, MTK_VENDOR_ATTR_CSI_DATA_TA);
988+ if (!b)
989+ goto out;
990+
991+ for (i = 0; i < ARRAY_SIZE(csi->ta); i++)
992+ if (nla_put_u8(skb, i, csi->ta[i]))
993+ goto out;
994+ nla_nest_end(skb, b);
995+
996+ if (nla_put_u32(skb, MTK_VENDOR_ATTR_CSI_DATA_NUM, csi->data_num))
997+ goto out;
998+
999+ b = nla_nest_start(skb, MTK_VENDOR_ATTR_CSI_DATA_I);
1000+ if (!b)
1001+ goto out;
1002+
1003+ for (i = 0; i < csi->data_num; i++)
1004+ if (nla_put_u16(skb, i, csi->data_i[i]))
1005+ goto out;
1006+ nla_nest_end(skb, b);
1007+
1008+ b = nla_nest_start(skb, MTK_VENDOR_ATTR_CSI_DATA_Q);
1009+ if (!b)
1010+ goto out;
1011+
1012+ for (i = 0; i < csi->data_num; i++)
1013+ if (nla_put_u16(skb, i, csi->data_q[i]))
1014+ goto out;
1015+ nla_nest_end(skb, b);
1016+
1017+ nla_nest_end(skb, a);
1018+
1019+ list_del(&csi->node);
1020+ kfree(csi);
1021+ phy->csi.count--;
1022+
1023+ err = phy->csi.count;
1024+ }
1025+out:
1026+ spin_unlock_bh(&phy->csi.lock);
1027+
1028+ return err;
1029+}
1030
1031 static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
1032 {
developer05f3b2b2024-08-19 19:17:34 +08001033@@ -1129,6 +1361,18 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
developer66e89bc2024-04-23 14:50:01 +08001034 .policy = beacon_ctrl_policy,
1035 .maxattr = MTK_VENDOR_ATTR_BEACON_CTRL_MAX,
1036 },
1037+ {
1038+ .info = {
1039+ .vendor_id = MTK_NL80211_VENDOR_ID,
1040+ .subcmd = MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL,
1041+ },
1042+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
1043+ WIPHY_VENDOR_CMD_NEED_RUNNING,
1044+ .doit = mt7996_vendor_csi_ctrl,
1045+ .dumpit = mt7996_vendor_csi_ctrl_dump,
1046+ .policy = csi_ctrl_policy,
1047+ .maxattr = MTK_VENDOR_ATTR_CSI_CTRL_MAX,
1048+ },
1049 };
1050
1051 void mt7996_vendor_register(struct mt7996_phy *phy)
developer05f3b2b2024-08-19 19:17:34 +08001052@@ -1136,6 +1380,9 @@ void mt7996_vendor_register(struct mt7996_phy *phy)
developer66e89bc2024-04-23 14:50:01 +08001053 phy->mt76->hw->wiphy->vendor_commands = mt7996_vendor_commands;
1054 phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
1055
1056+ INIT_LIST_HEAD(&phy->csi.list);
1057+ spin_lock_init(&phy->csi.lock);
1058+
1059 spin_lock_init(&phy->amnt_lock);
1060 }
1061 #endif
1062diff --git a/mt7996/vendor.h b/mt7996/vendor.h
developer05f3b2b2024-08-19 19:17:34 +08001063index 32346775..834b3d08 100644
developer66e89bc2024-04-23 14:50:01 +08001064--- a/mt7996/vendor.h
1065+++ b/mt7996/vendor.h
1066@@ -7,6 +7,7 @@
1067
1068 enum mtk_nl80211_vendor_subcmds {
1069 MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
1070+ MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL = 0xc2,
1071 MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL = 0xc3,
1072 MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4,
1073 MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
developer05f3b2b2024-08-19 19:17:34 +08001074@@ -240,6 +241,57 @@ enum mtk_vendor_attr_beacon_ctrl {
developer66e89bc2024-04-23 14:50:01 +08001075 NUM_MTK_VENDOR_ATTRS_BEACON_CTRL - 1
1076 };
1077
1078+enum mtk_vendor_attr_csi_ctrl {
1079+ MTK_VENDOR_ATTR_CSI_CTRL_UNSPEC,
1080+
1081+ MTK_VENDOR_ATTR_CSI_CTRL_CFG,
1082+ MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE,
1083+ MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE,
1084+ MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1,
1085+ MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2,
1086+ MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR,
1087+
1088+ MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM,
1089+
1090+ MTK_VENDOR_ATTR_CSI_CTRL_DATA,
1091+
developer05f3b2b2024-08-19 19:17:34 +08001092+ MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX,
1093+
developer66e89bc2024-04-23 14:50:01 +08001094+ /* keep last */
1095+ NUM_MTK_VENDOR_ATTRS_CSI_CTRL,
1096+ MTK_VENDOR_ATTR_CSI_CTRL_MAX =
1097+ NUM_MTK_VENDOR_ATTRS_CSI_CTRL - 1
1098+};
1099+
1100+enum mtk_vendor_attr_csi_data {
1101+ MTK_VENDOR_ATTR_CSI_DATA_UNSPEC,
1102+ MTK_VENDOR_ATTR_CSI_DATA_PAD,
1103+
1104+ MTK_VENDOR_ATTR_CSI_DATA_VER,
1105+ MTK_VENDOR_ATTR_CSI_DATA_TS,
1106+ MTK_VENDOR_ATTR_CSI_DATA_RSSI,
1107+ MTK_VENDOR_ATTR_CSI_DATA_SNR,
1108+ MTK_VENDOR_ATTR_CSI_DATA_BW,
1109+ MTK_VENDOR_ATTR_CSI_DATA_CH_IDX,
1110+ MTK_VENDOR_ATTR_CSI_DATA_TA,
1111+ MTK_VENDOR_ATTR_CSI_DATA_NUM,
1112+ MTK_VENDOR_ATTR_CSI_DATA_I,
1113+ MTK_VENDOR_ATTR_CSI_DATA_Q,
1114+ MTK_VENDOR_ATTR_CSI_DATA_INFO,
1115+ MTK_VENDOR_ATTR_CSI_DATA_RSVD1,
1116+ MTK_VENDOR_ATTR_CSI_DATA_RSVD2,
1117+ MTK_VENDOR_ATTR_CSI_DATA_RSVD3,
1118+ MTK_VENDOR_ATTR_CSI_DATA_RSVD4,
1119+ MTK_VENDOR_ATTR_CSI_DATA_TX_ANT,
1120+ MTK_VENDOR_ATTR_CSI_DATA_RX_ANT,
1121+ MTK_VENDOR_ATTR_CSI_DATA_MODE,
1122+ MTK_VENDOR_ATTR_CSI_DATA_CHAIN_INFO,
1123+
1124+ /* keep last */
1125+ NUM_MTK_VENDOR_ATTRS_CSI_DATA,
1126+ MTK_VENDOR_ATTR_CSI_DATA_MAX =
1127+ NUM_MTK_VENDOR_ATTRS_CSI_DATA - 1
1128+};
1129 #endif
1130
1131 #endif
1132--
developerd0c89452024-10-11 16:53:27 +080011332.45.2
developer66e89bc2024-04-23 14:50:01 +08001134