1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
8 #include <net/netlink.h>
13 #include "testmode_i.h"
15 #define ATH11K_FTM_SEGHDR_CURRENT_SEQ GENMASK(3, 0)
16 #define ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS GENMASK(7, 4)
18 static const struct nla_policy ath11k_tm_policy
[ATH11K_TM_ATTR_MAX
+ 1] = {
19 [ATH11K_TM_ATTR_CMD
] = { .type
= NLA_U32
},
20 [ATH11K_TM_ATTR_DATA
] = { .type
= NLA_BINARY
,
21 .len
= ATH11K_TM_DATA_MAX_LEN
},
22 [ATH11K_TM_ATTR_WMI_CMDID
] = { .type
= NLA_U32
},
23 [ATH11K_TM_ATTR_VERSION_MAJOR
] = { .type
= NLA_U32
},
24 [ATH11K_TM_ATTR_VERSION_MINOR
] = { .type
= NLA_U32
},
27 static struct ath11k
*ath11k_tm_get_ar(struct ath11k_base
*ab
)
29 struct ath11k_pdev
*pdev
;
30 struct ath11k
*ar
= NULL
;
33 for (i
= 0; i
< ab
->num_radios
; i
++) {
37 if (ar
&& ar
->state
== ATH11K_STATE_FTM
)
44 /* This function handles unsegmented events. Data in various events are aggregated
45 * in application layer, this event is unsegmented from host perspective.
47 static void ath11k_tm_wmi_event_unsegmented(struct ath11k_base
*ab
, u32 cmd_id
,
50 struct sk_buff
*nl_skb
;
53 ath11k_dbg(ab
, ATH11K_DBG_TESTMODE
,
54 "event wmi cmd_id %d skb length %d\n",
56 ath11k_dbg_dump(ab
, ATH11K_DBG_TESTMODE
, NULL
, "", skb
->data
, skb
->len
);
58 ar
= ath11k_tm_get_ar(ab
);
60 ath11k_warn(ab
, "testmode event not handled due to invalid pdev\n");
64 spin_lock_bh(&ar
->data_lock
);
66 nl_skb
= cfg80211_testmode_alloc_event_skb(ar
->hw
->wiphy
,
67 2 * nla_total_size(sizeof(u32
)) +
68 nla_total_size(skb
->len
),
72 "failed to allocate skb for unsegmented testmode wmi event\n");
76 if (nla_put_u32(nl_skb
, ATH11K_TM_ATTR_CMD
, ATH11K_TM_CMD_WMI
) ||
77 nla_put_u32(nl_skb
, ATH11K_TM_ATTR_WMI_CMDID
, cmd_id
) ||
78 nla_put(nl_skb
, ATH11K_TM_ATTR_DATA
, skb
->len
, skb
->data
)) {
79 ath11k_warn(ab
, "failed to populate testmode unsegmented event\n");
84 cfg80211_testmode_event(nl_skb
, GFP_ATOMIC
);
85 spin_unlock_bh(&ar
->data_lock
);
89 spin_unlock_bh(&ar
->data_lock
);
90 ath11k_warn(ab
, "Failed to send testmode event to higher layers\n");
93 /* This function handles segmented events. Data of various events received
94 * from firmware is aggregated and sent to application layer
96 static int ath11k_tm_process_event(struct ath11k_base
*ab
, u32 cmd_id
,
97 const struct wmi_ftm_event_msg
*ftm_msg
,
100 struct sk_buff
*nl_skb
;
105 u8 total_segments
, current_seq
;
109 ath11k_dbg(ab
, ATH11K_DBG_TESTMODE
,
110 "event wmi cmd_id %d ftm event msg %pK datalen %d\n",
111 cmd_id
, ftm_msg
, length
);
112 ath11k_dbg_dump(ab
, ATH11K_DBG_TESTMODE
, NULL
, "", ftm_msg
, length
);
113 pdev_id
= DP_HW2SW_MACID(ftm_msg
->seg_hdr
.pdev_id
);
115 if (pdev_id
>= ab
->num_radios
) {
116 ath11k_warn(ab
, "testmode event not handled due to invalid pdev id: %d\n",
121 ar
= ab
->pdevs
[pdev_id
].ar
;
123 ath11k_warn(ab
, "testmode event not handled due to absence of pdev\n");
127 current_seq
= FIELD_GET(ATH11K_FTM_SEGHDR_CURRENT_SEQ
,
128 ftm_msg
->seg_hdr
.segmentinfo
);
129 total_segments
= FIELD_GET(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS
,
130 ftm_msg
->seg_hdr
.segmentinfo
);
131 datalen
= length
- (sizeof(struct wmi_ftm_seg_hdr
));
132 buf_pos
= ftm_msg
->data
;
134 spin_lock_bh(&ar
->data_lock
);
136 if (current_seq
== 0) {
137 ab
->testmode
.expected_seq
= 0;
138 ab
->testmode
.data_pos
= 0;
141 data_pos
= ab
->testmode
.data_pos
;
143 if ((data_pos
+ datalen
) > ATH11K_FTM_EVENT_MAX_BUF_LENGTH
) {
144 ath11k_warn(ab
, "Invalid ftm event length at %d: %d\n",
150 memcpy(&ab
->testmode
.eventdata
[data_pos
], buf_pos
, datalen
);
153 if (++ab
->testmode
.expected_seq
!= total_segments
) {
154 ab
->testmode
.data_pos
= data_pos
;
155 ath11k_dbg(ab
, ATH11K_DBG_TESTMODE
,
156 "partial data received current_seq %d total_seg %d\n",
157 current_seq
, total_segments
);
161 ath11k_dbg(ab
, ATH11K_DBG_TESTMODE
,
162 "total data length pos %d len %d\n",
163 data_pos
, ftm_msg
->seg_hdr
.len
);
164 nl_skb
= cfg80211_testmode_alloc_event_skb(ar
->hw
->wiphy
,
165 2 * nla_total_size(sizeof(u32
)) +
166 nla_total_size(data_pos
),
170 "failed to allocate skb for segmented testmode wmi event\n");
175 if (nla_put_u32(nl_skb
, ATH11K_TM_ATTR_CMD
,
176 ATH11K_TM_CMD_WMI_FTM
) ||
177 nla_put_u32(nl_skb
, ATH11K_TM_ATTR_WMI_CMDID
, cmd_id
) ||
178 nla_put(nl_skb
, ATH11K_TM_ATTR_DATA
, data_pos
,
179 &ab
->testmode
.eventdata
[0])) {
180 ath11k_warn(ab
, "failed to populate segmented testmode event");
186 cfg80211_testmode_event(nl_skb
, GFP_ATOMIC
);
189 spin_unlock_bh(&ar
->data_lock
);
193 static void ath11k_tm_wmi_event_segmented(struct ath11k_base
*ab
, u32 cmd_id
,
197 const struct wmi_ftm_event_msg
*ev
;
201 tb
= ath11k_wmi_tlv_parse_alloc(ab
, skb
, GFP_ATOMIC
);
204 ath11k_warn(ab
, "failed to parse ftm event tlv: %d\n", ret
);
208 ev
= tb
[WMI_TAG_ARRAY_BYTE
];
210 ath11k_warn(ab
, "failed to fetch ftm msg\n");
215 length
= skb
->len
- TLV_HDR_SIZE
;
216 ret
= ath11k_tm_process_event(ab
, cmd_id
, ev
, length
);
218 ath11k_warn(ab
, "Failed to process ftm event\n");
223 void ath11k_tm_wmi_event(struct ath11k_base
*ab
, u32 cmd_id
, struct sk_buff
*skb
)
225 if (test_bit(ATH11K_FLAG_FTM_SEGMENTED
, &ab
->dev_flags
))
226 ath11k_tm_wmi_event_segmented(ab
, cmd_id
, skb
);
228 ath11k_tm_wmi_event_unsegmented(ab
, cmd_id
, skb
);
231 static int ath11k_tm_cmd_get_version(struct ath11k
*ar
, struct nlattr
*tb
[])
236 ath11k_dbg(ar
->ab
, ATH11K_DBG_TESTMODE
,
237 "cmd get version_major %d version_minor %d\n",
238 ATH11K_TESTMODE_VERSION_MAJOR
,
239 ATH11K_TESTMODE_VERSION_MINOR
);
241 skb
= cfg80211_testmode_alloc_reply_skb(ar
->hw
->wiphy
,
242 nla_total_size(sizeof(u32
)));
246 ret
= nla_put_u32(skb
, ATH11K_TM_ATTR_VERSION_MAJOR
,
247 ATH11K_TESTMODE_VERSION_MAJOR
);
253 ret
= nla_put_u32(skb
, ATH11K_TM_ATTR_VERSION_MINOR
,
254 ATH11K_TESTMODE_VERSION_MINOR
);
260 return cfg80211_testmode_reply(skb
);
263 static int ath11k_tm_cmd_testmode_start(struct ath11k
*ar
, struct nlattr
*tb
[])
267 mutex_lock(&ar
->conf_mutex
);
269 if (ar
->state
== ATH11K_STATE_FTM
) {
274 /* start utf only when the driver is not in use */
275 if (ar
->state
!= ATH11K_STATE_OFF
) {
280 ar
->ab
->testmode
.eventdata
= kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH
,
282 if (!ar
->ab
->testmode
.eventdata
) {
287 ar
->state
= ATH11K_STATE_FTM
;
290 mutex_unlock(&ar
->conf_mutex
);
292 ath11k_dbg(ar
->ab
, ATH11K_DBG_TESTMODE
, "cmd start\n");
296 mutex_unlock(&ar
->conf_mutex
);
300 static int ath11k_tm_cmd_wmi(struct ath11k
*ar
, struct nlattr
*tb
[],
301 struct ieee80211_vif
*vif
)
303 struct ath11k_pdev_wmi
*wmi
= ar
->wmi
;
305 struct ath11k_vif
*arvif
;
311 mutex_lock(&ar
->conf_mutex
);
313 if (!tb
[ATH11K_TM_ATTR_DATA
]) {
318 if (!tb
[ATH11K_TM_ATTR_WMI_CMDID
]) {
323 buf
= nla_data(tb
[ATH11K_TM_ATTR_DATA
]);
324 buf_len
= nla_len(tb
[ATH11K_TM_ATTR_DATA
]);
326 ath11k_warn(ar
->ab
, "No data present in testmode wmi command\n");
331 cmd_id
= nla_get_u32(tb
[ATH11K_TM_ATTR_WMI_CMDID
]);
333 /* Make sure that the buffer length is long enough to
334 * hold TLV and pdev/vdev id.
336 if (buf_len
< sizeof(struct wmi_tlv
) + sizeof(u32
)) {
342 tag
= FIELD_GET(WMI_TLV_TAG
, *ptr
);
344 /* pdev/vdev id start after TLV header */
347 if (tag
== WMI_TAG_PDEV_SET_PARAM_CMD
)
348 *ptr
= ar
->pdev
->pdev_id
;
350 if (ar
->ab
->fw_mode
!= ATH11K_FIRMWARE_MODE_FTM
&&
351 (tag
== WMI_TAG_VDEV_SET_PARAM_CMD
|| tag
== WMI_TAG_UNIT_TEST_CMD
)) {
353 arvif
= ath11k_vif_to_arvif(vif
);
354 *ptr
= arvif
->vdev_id
;
361 ath11k_dbg(ar
->ab
, ATH11K_DBG_TESTMODE
,
362 "cmd wmi cmd_id %d buf length %d\n",
365 ath11k_dbg_dump(ar
->ab
, ATH11K_DBG_TESTMODE
, NULL
, "", buf
, buf_len
);
367 skb
= ath11k_wmi_alloc_skb(wmi
->wmi_ab
, buf_len
);
373 memcpy(skb
->data
, buf
, buf_len
);
375 ret
= ath11k_wmi_cmd_send(wmi
, skb
, cmd_id
);
378 ath11k_warn(ar
->ab
, "failed to transmit wmi command (testmode): %d\n",
386 mutex_unlock(&ar
->conf_mutex
);
390 static int ath11k_tm_cmd_wmi_ftm(struct ath11k
*ar
, struct nlattr
*tb
[])
392 struct ath11k_pdev_wmi
*wmi
= ar
->wmi
;
393 struct ath11k_base
*ab
= ar
->ab
;
395 u32 cmd_id
, buf_len
, hdr_info
;
398 u8 segnumber
= 0, seginfo
;
399 u16 chunk_len
, total_bytes
, num_segments
;
401 struct wmi_ftm_cmd
*ftm_cmd
;
403 set_bit(ATH11K_FLAG_FTM_SEGMENTED
, &ab
->dev_flags
);
405 mutex_lock(&ar
->conf_mutex
);
407 if (ar
->state
!= ATH11K_STATE_FTM
) {
412 if (!tb
[ATH11K_TM_ATTR_DATA
]) {
417 buf
= nla_data(tb
[ATH11K_TM_ATTR_DATA
]);
418 buf_len
= nla_len(tb
[ATH11K_TM_ATTR_DATA
]);
419 cmd_id
= WMI_PDEV_UTF_CMDID
;
421 ath11k_dbg(ar
->ab
, ATH11K_DBG_TESTMODE
,
422 "cmd wmi ftm cmd_id %d buffer length %d\n",
424 ath11k_dbg_dump(ar
->ab
, ATH11K_DBG_TESTMODE
, NULL
, "", buf
, buf_len
);
427 total_bytes
= buf_len
;
428 num_segments
= total_bytes
/ MAX_WMI_UTF_LEN
;
430 if (buf_len
- (num_segments
* MAX_WMI_UTF_LEN
))
434 chunk_len
= min_t(u16
, buf_len
, MAX_WMI_UTF_LEN
);
436 skb
= ath11k_wmi_alloc_skb(wmi
->wmi_ab
, (chunk_len
+
437 sizeof(struct wmi_ftm_cmd
)));
443 ftm_cmd
= (struct wmi_ftm_cmd
*)skb
->data
;
444 hdr_info
= FIELD_PREP(WMI_TLV_TAG
, WMI_TAG_ARRAY_BYTE
) |
445 FIELD_PREP(WMI_TLV_LEN
, (chunk_len
+
446 sizeof(struct wmi_ftm_seg_hdr
)));
447 ftm_cmd
->tlv_header
= hdr_info
;
448 ftm_cmd
->seg_hdr
.len
= total_bytes
;
449 ftm_cmd
->seg_hdr
.msgref
= ar
->ftm_msgref
;
450 seginfo
= FIELD_PREP(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS
, num_segments
) |
451 FIELD_PREP(ATH11K_FTM_SEGHDR_CURRENT_SEQ
, segnumber
);
452 ftm_cmd
->seg_hdr
.segmentinfo
= seginfo
;
455 memcpy(&ftm_cmd
->data
, bufpos
, chunk_len
);
457 ret
= ath11k_wmi_cmd_send(wmi
, skb
, cmd_id
);
459 ath11k_warn(ar
->ab
, "failed to send wmi ftm command: %d\n", ret
);
463 buf_len
-= chunk_len
;
471 mutex_unlock(&ar
->conf_mutex
);
475 int ath11k_tm_cmd(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
478 struct ath11k
*ar
= hw
->priv
;
479 struct nlattr
*tb
[ATH11K_TM_ATTR_MAX
+ 1];
482 ret
= nla_parse(tb
, ATH11K_TM_ATTR_MAX
, data
, len
, ath11k_tm_policy
,
487 if (!tb
[ATH11K_TM_ATTR_CMD
])
490 switch (nla_get_u32(tb
[ATH11K_TM_ATTR_CMD
])) {
491 case ATH11K_TM_CMD_GET_VERSION
:
492 return ath11k_tm_cmd_get_version(ar
, tb
);
493 case ATH11K_TM_CMD_WMI
:
494 return ath11k_tm_cmd_wmi(ar
, tb
, vif
);
495 case ATH11K_TM_CMD_TESTMODE_START
:
496 return ath11k_tm_cmd_testmode_start(ar
, tb
);
497 case ATH11K_TM_CMD_WMI_FTM
:
498 return ath11k_tm_cmd_wmi_ftm(ar
, tb
);