1 /*
2 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /**
18 * DOC: wlan_cfg80211_afc.c
19 *
20 * Defines AFC cfg80211 vendor command interface handles
21 */
22
23 #include <wlan_cfg80211.h>
24 #include <wlan_cfg80211_afc.h>
25 #include <wlan_reg_ucfg_api.h>
26 #include <wlan_objmgr_pdev_obj.h>
27 #include <wlan_osif_priv.h>
28 #include <wlan_afc_ucfg_api.h>
29
30 /* Maximum AFC data length can pass to target limited by platform driver */
31 #define IF_AFC_RESPONSE_MAX_LEN 4096
32
33 /*
34 * JSON format AFC response data maximum length, limited by interface,
35 * struct wlan_afc_host_resp is AFC response format pass to target.
36 */
37 #define QCA_NL80211_AFC_RESP_DATA_MAX_SIZE \
38 (IF_AFC_RESPONSE_MAX_LEN - sizeof(struct wlan_afc_host_resp))
39
40 /**
41 * struct frange_obj - Structure of channel frequency range with psd
42 * @freq_start: Frequency range start in MHz
43 * @freq_end: Frequency range end in MHz
44 * @psd: The PSD power info (dBm/MHz) multiplied by a factor of 100 to
45 * preserve granularity up to 2 decimal places
46 */
47 struct frange_obj {
48 qdf_freq_t freq_start;
49 qdf_freq_t freq_end;
50 uint32_t psd;
51 };
52
53 /**
54 * struct channel_eirp - Structure of channel with eirp
55 * @channel_cfi: Channel center frequency index
56 * @eirp: The EIRP power info (dBm) multiplied by a factor of 100 to
57 * preserve granularity up to 2 decimal places
58 */
59 struct channel_eirp {
60 uint8_t channel_cfi;
61 uint32_t eirp;
62 };
63
64 /**
65 * struct opclass_eirp_obj - Structure of operation class eirp object
66 * @opclass: Operation class number
67 * @num_channel: Number of channels belongs to this opclass
68 * @chan_eirp: Channel eirp structure list
69 */
70 struct opclass_eirp_obj {
71 uint8_t opclass;
72 uint8_t num_channel;
73 struct channel_eirp chan_eirp[REG_MAX_CHANNELS_PER_OPERATING_CLASS];
74 };
75
76 /**
77 * struct afc_resp_extracted - Structure of AFC response extracted from
78 * AFC vendor response
79 * @json_data: Pointer to JSON data buffer
80 * @json_len: JSON data length
81 * @time_to_live: Time to live of AFC response in seconds
82 * @request_id: Request ID
83 * @avail_exp_date: Expire date
84 * Date format: bits 7:0 - DD (Day 1-31)
85 * bits 15:8 - MM (Month 1-12)
86 * bits 31:16 - YYYY (Year)
87 * @avail_exp_time: Expire time
88 * Time format: bits 7:0 - SS (Seconds 0-59)
89 * bits 15:8 - MM (Minutes 0-59)
90 * bits 23:16 - HH (Hours 0-23)
91 * bits 31:24 - Reserved
92 * @afc_serv_resp_code: AFC server respond code
93 * -1: General Failure.
94 * 0: Success.
95 * 100 - 199: General errors related to protocol.
96 * 300 - 399: Error events specific to message exchange
97 * for the Available Spectrum Inquiry.
98 * @num_frange_obj: Number of frequency range objects
99 * @frange: Array of frequency range object
100 * @num_opclass: Number of operation class channel eirp objects
101 * @op_obj: Array of operation class channel eirp objects
102 */
103 struct afc_resp_extracted {
104 uint8_t *json_data;
105 uint32_t json_len;
106 uint32_t time_to_live;
107 uint32_t request_id;
108 uint32_t avail_exp_date;
109 uint32_t avail_exp_time;
110 int32_t afc_serv_resp_code;
111 uint32_t num_frange_obj;
112 struct frange_obj frange[NUM_6GHZ_CHANNELS];
113 uint32_t num_opclass;
114 struct opclass_eirp_obj op_obj[REG_MAX_SUPP_OPER_CLASSES];
115 };
116
117 const struct nla_policy
118 wlan_cfg80211_afc_response_policy[QCA_WLAN_VENDOR_ATTR_AFC_RESP_MAX + 1] = {
119 [QCA_WLAN_VENDOR_ATTR_AFC_RESP_DATA] = { .type = NLA_STRING,
120 .len = QCA_NL80211_AFC_RESP_DATA_MAX_SIZE },
121 [QCA_WLAN_VENDOR_ATTR_AFC_RESP_TIME_TO_LIVE] = { .type = NLA_U32 },
122 [QCA_WLAN_VENDOR_ATTR_AFC_RESP_REQ_ID] = { .type = NLA_U32 },
123 [QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_DATE] = { .type = NLA_U32 },
124 [QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_TIME] = { .type = NLA_U32 },
125 [QCA_WLAN_VENDOR_ATTR_AFC_RESP_AFC_SERVER_RESP_CODE] = {
126 .type = NLA_S32 },
127 [QCA_WLAN_VENDOR_ATTR_AFC_RESP_FREQ_PSD_INFO] = { .type = NLA_NESTED },
128 [QCA_WLAN_VENDOR_ATTR_AFC_RESP_OPCLASS_CHAN_EIRP_INFO] = {
129 .type = NLA_NESTED },
130 };
131
132 #define nla_nest_end_checked(skb, start) do { \
133 if ((skb) && (start)) \
134 nla_nest_end(skb, start); \
135 } while (0)
136
137 /**
138 * afc_expiry_event_update_or_get_len() - Function to fill vendor event buffer
139 * with info extracted from AFC request, or get required vendor buffer length.
140 * @vendor_event: Pointer to vendor event SK buffer structure
141 * @afc_req: Pointer to AFC request from regulatory component
142 *
143 * If vendor_event is NULL, to get vendor buffer length, otherwise
144 * to fill vendor event buffer with info
145 *
146 * Return: If get vendor buffer length, return positive value as length,
147 * If fill vendor event 0 if success, otherwise negative error code
148 */
149 static int
afc_expiry_event_update_or_get_len(struct sk_buff * vendor_event,struct wlan_afc_host_request * afc_req)150 afc_expiry_event_update_or_get_len(struct sk_buff *vendor_event,
151 struct wlan_afc_host_request *afc_req)
152 {
153 struct nlattr *nla_attr;
154 struct nlattr *freq_info;
155 struct nlattr *opclass_info = NULL;
156 struct nlattr *chan_list = NULL;
157 struct nlattr *chan_info = NULL;
158 int i, j, len = NLMSG_HDRLEN;
159 struct wlan_afc_opclass_obj *afc_opclass_obj;
160
161 if (vendor_event &&
162 nla_put_u8(vendor_event,
163 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE,
164 QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY)) {
165 osif_err("QCA_WLAN_VENDOR_AFC_EVENT_TYPE_EXPIRY put fail");
166 goto fail;
167 } else {
168 len += nla_total_size(sizeof(u8));
169 }
170
171 if (vendor_event &&
172 nla_put_u32(vendor_event,
173 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_REQ_ID,
174 afc_req->req_id)) {
175 osif_err("QCA_WLAN_VENDOR_ATTR_AFC_REQ_ID put fail");
176 goto fail;
177 } else {
178 len += nla_total_size(sizeof(u32));
179 }
180
181 if (vendor_event &&
182 nla_put_u32(vendor_event,
183 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AFC_WFA_VERSION,
184 (afc_req->version_major << 16) |
185 afc_req->version_minor)) {
186 osif_err("AFC EVENT WFA version put fail");
187 goto fail;
188 } else {
189 len += nla_total_size(sizeof(u32));
190 }
191
192 if (vendor_event &&
193 nla_put_u16(vendor_event,
194 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_MIN_DES_POWER,
195 afc_req->min_des_power)) {
196 osif_err("QCA_WLAN_VENDOR_ATTR_AFC_REQ_MIN_DES_PWR put fail");
197 goto fail;
198 } else {
199 len += nla_total_size(sizeof(u16));
200 }
201
202 if (vendor_event &&
203 nla_put_u8(vendor_event,
204 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_AP_DEPLOYMENT,
205 afc_req->afc_location->deployment_type)) {
206 osif_err("AFC EVENT AP deployment put fail");
207 goto fail;
208 } else {
209 len += nla_total_size(sizeof(u8));
210 }
211
212 if (vendor_event) {
213 /* Update the frequency range list from the Expiry event */
214 nla_attr = nla_nest_start(vendor_event,
215 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_FREQ_RANGE_LIST);
216 if (!nla_attr) {
217 osif_err("AFC FREQ RANGE LIST start put fail");
218 goto fail;
219 }
220 } else {
221 len += nla_total_size(0);
222 }
223
224 for (i = 0; i < afc_req->freq_lst->num_ranges; i++) {
225 if (vendor_event) {
226 freq_info = nla_nest_start(vendor_event, i);
227 if (!freq_info) {
228 osif_err("Fail to put freq list nest %d", i);
229 goto fail;
230 }
231 } else {
232 len += nla_total_size(0);
233 }
234
235 if (vendor_event &&
236 (nla_put_u32(vendor_event,
237 QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_START,
238 afc_req->freq_lst->range_objs[i].lowfreq) ||
239 nla_put_u32(vendor_event,
240 QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_END,
241 afc_req->freq_lst->range_objs[i].highfreq))) {
242 osif_err("AFC REQ FREQ RANGE LIST put fail, num %d",
243 afc_req->freq_lst->num_ranges);
244 goto fail;
245 } else {
246 len += nla_total_size(sizeof(u32)) * 2;
247 }
248 nla_nest_end_checked(vendor_event, freq_info);
249 }
250 nla_nest_end_checked(vendor_event, nla_attr);
251
252 if (vendor_event) {
253 /* Update the Operating class and channel list */
254 nla_attr = nla_nest_start(vendor_event,
255 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_OPCLASS_CHAN_LIST);
256 if (!nla_attr) {
257 osif_err("AFC OPCLASS CHAN LIST start put fail");
258 goto fail;
259 }
260 } else {
261 len += nla_total_size(0);
262 }
263
264 for (i = 0; i < afc_req->opclass_obj_lst->num_opclass_objs; i++) {
265 if (vendor_event) {
266 opclass_info = nla_nest_start(vendor_event, i);
267 if (!opclass_info) {
268 osif_err("Fail to put opclass nest %d", i);
269 goto fail;
270 }
271 } else {
272 len += nla_total_size(0);
273 }
274
275 afc_opclass_obj = &afc_req->opclass_obj_lst->opclass_objs[i];
276
277 if (vendor_event &&
278 nla_put_u8(vendor_event,
279 QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS,
280 afc_opclass_obj->opclass)) {
281 osif_err("AFC OPCLASS INFO OPCLASS put fail, num %d",
282 afc_req->opclass_obj_lst->num_opclass_objs);
283 goto fail;
284 } else {
285 len += nla_total_size(sizeof(u8));
286 }
287
288 if (vendor_event) {
289 chan_list = nla_nest_start(vendor_event,
290 QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST);
291 if (!chan_list) {
292 osif_err("AFC OPCLASS INFO CHAN LIST start put fail");
293 goto fail;
294 }
295 } else {
296 len += nla_total_size(0);
297 }
298
299 for (j = 0; j < afc_opclass_obj->opclass_num_cfis; j++) {
300 if (vendor_event) {
301 chan_info = nla_nest_start(vendor_event, j);
302 if (!chan_info) {
303 osif_err("Fail to put opclass cfis nest %d", j);
304 goto fail;
305 }
306 } else {
307 len += nla_total_size(0);
308 }
309
310 if (vendor_event &&
311 nla_put_u8(vendor_event,
312 QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM,
313 afc_opclass_obj->cfis[j])) {
314 osif_err("AFC EIRP INFO CHAN NUM put fail, num %d",
315 afc_opclass_obj->opclass_num_cfis);
316 goto fail;
317 } else {
318 len += nla_total_size(sizeof(u8));
319 }
320 nla_nest_end_checked(vendor_event, chan_info);
321 }
322 nla_nest_end_checked(vendor_event, chan_list);
323 nla_nest_end_checked(vendor_event, opclass_info);
324 }
325 nla_nest_end_checked(vendor_event, nla_attr);
326
327 return vendor_event ? 0 : len;
328
329 fail:
330 return -EINVAL;
331 }
332
333 /**
334 * afc_power_event_update_or_get_len() - Function to fill vendor event buffer
335 * with AFC power update event or get required vendor buffer length
336 * @vendor_event: Pointer to vendor event SK buffer
337 * @pwr_evt: Pointer to AFC power event
338 *
339 * If vendor_event is NULL, to get vendor buffer length, otherwise
340 * to fill vendor event buffer with info
341 *
342 * Return: If get vendor buffer length, return positive value as length,
343 * If fill vendor event, 0 if success, otherwise negative error code
344 */
345 static int
afc_power_event_update_or_get_len(struct sk_buff * vendor_event,struct reg_fw_afc_power_event * pwr_evt)346 afc_power_event_update_or_get_len(struct sk_buff *vendor_event,
347 struct reg_fw_afc_power_event *pwr_evt)
348 {
349 struct afc_chan_obj *pow_evt_chan_info = NULL;
350 struct chan_eirp_obj *pow_evt_eirp_info = NULL;
351 struct nlattr *nla_attr;
352 struct nlattr *freq_info;
353 struct nlattr *opclass_info;
354 struct nlattr *chan_list;
355 struct nlattr *chan_info = NULL;
356 int i, j, len = NLMSG_HDRLEN;
357
358 if (vendor_event &&
359 nla_put_u8(vendor_event,
360 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_TYPE,
361 QCA_WLAN_VENDOR_AFC_EVENT_TYPE_POWER_UPDATE_COMPLETE)) {
362 osif_err("AFC power update complete event type put fail");
363 goto fail;
364 } else {
365 len += nla_total_size(sizeof(u8));
366 }
367
368 if (vendor_event &&
369 nla_put_u32(vendor_event,
370 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_REQ_ID,
371 pwr_evt->resp_id)) {
372 osif_err("QCA_WLAN_VENDOR_ATTR_AFC_EVENT_REQ_ID put fail");
373 goto fail;
374 } else {
375 len += nla_total_size(sizeof(u32));
376 }
377
378 if (vendor_event &&
379 nla_put_u8(vendor_event,
380 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_STATUS_CODE,
381 pwr_evt->fw_status_code)) {
382 osif_err("AFC EVENT STATUS CODE put fail");
383 goto fail;
384 } else {
385 len += nla_total_size(sizeof(u8));
386 }
387
388 if (vendor_event &&
389 nla_put_s32(vendor_event,
390 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_SERVER_RESP_CODE,
391 pwr_evt->serv_resp_code)) {
392 osif_err("AFC EVENT SERVER RESP CODE put fail");
393 goto fail;
394 } else {
395 len += nla_total_size(sizeof(s32));
396 }
397
398 if (vendor_event &&
399 nla_put_u32(vendor_event,
400 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_EXP_DATE,
401 pwr_evt->avail_exp_time_d)) {
402 osif_err("AFC EVENT EXPIRE DATE put fail");
403 goto fail;
404 } else {
405 len += nla_total_size(sizeof(u32));
406 }
407
408 if (vendor_event &&
409 nla_put_u32(vendor_event,
410 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_EXP_TIME,
411 pwr_evt->avail_exp_time_t)) {
412 osif_err("AFC EVENT EXPIRE TIME put fail");
413 goto fail;
414 } else {
415 len += nla_total_size(sizeof(u32));
416 }
417
418 if (vendor_event) {
419 /* Update the Frequency and corresponding PSD info */
420 nla_attr = nla_nest_start(vendor_event,
421 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_FREQ_RANGE_LIST);
422 if (!nla_attr)
423 goto fail;
424 } else {
425 len += nla_total_size(0);
426 }
427
428 for (i = 0; i < pwr_evt->num_freq_objs; i++) {
429 if (vendor_event) {
430 freq_info = nla_nest_start(vendor_event, i);
431 if (!freq_info)
432 goto fail;
433 } else {
434 len += nla_total_size(0);
435 }
436
437 if (vendor_event &&
438 (nla_put_u32(vendor_event,
439 QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_START,
440 pwr_evt->afc_freq_info[i].low_freq) ||
441 nla_put_u32(vendor_event,
442 QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_END,
443 pwr_evt->afc_freq_info[i].high_freq) ||
444 nla_put_u32(vendor_event,
445 QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_PSD,
446 pwr_evt->afc_freq_info[i].max_psd))) {
447 osif_err("AFC FREQUENCY PSD INFO put failed, num %d",
448 pwr_evt->num_freq_objs);
449 goto fail;
450 } else {
451 len += nla_total_size(sizeof(u32)) * 3;
452 }
453 nla_nest_end_checked(vendor_event, freq_info);
454 }
455 nla_nest_end_checked(vendor_event, nla_attr);
456
457 if (vendor_event) {
458 /* Update the Operating class, channel list and EIRP info */
459 nla_attr = nla_nest_start(vendor_event,
460 QCA_WLAN_VENDOR_ATTR_AFC_EVENT_OPCLASS_CHAN_LIST);
461 if (!nla_attr)
462 goto fail;
463 } else {
464 len += nla_total_size(0);
465 }
466
467 pow_evt_chan_info = pwr_evt->afc_chan_info;
468
469 for (i = 0; i < pwr_evt->num_chan_objs; i++) {
470 if (vendor_event) {
471 opclass_info = nla_nest_start(vendor_event, i);
472 if (!opclass_info)
473 goto fail;
474 } else {
475 len += nla_total_size(0);
476 }
477
478 if (vendor_event &&
479 nla_put_u8(vendor_event,
480 QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS,
481 pow_evt_chan_info[i].global_opclass)) {
482 osif_err("AFC OPCLASS INFO put fail, num %d",
483 pwr_evt->num_chan_objs);
484 goto fail;
485 } else {
486 len += nla_total_size(sizeof(u8));
487 }
488
489 if (vendor_event) {
490 chan_list = nla_nest_start(vendor_event,
491 QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST);
492 if (!chan_list)
493 goto fail;
494 } else {
495 len += nla_total_size(0);
496 }
497
498 pow_evt_eirp_info = pow_evt_chan_info[i].chan_eirp_info;
499
500 for (j = 0; j < pow_evt_chan_info[i].num_chans; j++) {
501 if (vendor_event) {
502 chan_info = nla_nest_start(vendor_event, j);
503 if (!chan_info)
504 goto fail;
505 } else {
506 len += nla_total_size(0);
507 }
508
509 if (vendor_event &&
510 (nla_put_u8(vendor_event,
511 QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM,
512 pow_evt_eirp_info[j].cfi) ||
513 nla_put_u32(vendor_event,
514 QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_EIRP,
515 pow_evt_eirp_info[j].eirp_power))) {
516 osif_err("AFC CHAN EIRP_INFO put fail, num %d",
517 pow_evt_chan_info[i].num_chans);
518 goto fail;
519 } else {
520 len += nla_total_size(sizeof(u8));
521 len += nla_total_size(sizeof(u32));
522 }
523 nla_nest_end_checked(vendor_event, chan_info);
524 }
525 nla_nest_end_checked(vendor_event, chan_list);
526 nla_nest_end_checked(vendor_event, opclass_info);
527 }
528
529 nla_nest_end_checked(vendor_event, nla_attr);
530
531 return vendor_event ? 0 : len;
532
533 fail:
534 return -EINVAL;
535 }
536
wlan_cfg80211_afc_send_request(struct wlan_objmgr_pdev * pdev,struct wlan_afc_host_request * afc_req)537 int wlan_cfg80211_afc_send_request(struct wlan_objmgr_pdev *pdev,
538 struct wlan_afc_host_request *afc_req)
539 {
540 struct sk_buff *vendor_event;
541 struct pdev_osif_priv *osif_priv;
542 int ret, vendor_buffer_len;
543
544 osif_priv = wlan_pdev_get_ospriv(pdev);
545 if (!osif_priv) {
546 osif_err("PDEV OS private structure is NULL");
547 return -EINVAL;
548 }
549
550 if (!afc_req) {
551 osif_err("afc host request is NULL");
552 return -EINVAL;
553 }
554
555 vendor_buffer_len = afc_expiry_event_update_or_get_len(NULL, afc_req);
556
557 vendor_event = wlan_cfg80211_vendor_event_alloc(osif_priv->wiphy,
558 NULL,
559 vendor_buffer_len,
560 QCA_NL80211_VENDOR_SUBCMD_AFC_EVENT_INDEX,
561 GFP_ATOMIC);
562 if (!vendor_event) {
563 osif_err("cfg80211 vendor event alloc failed");
564 return -ENOMEM;
565 }
566
567 ret = afc_expiry_event_update_or_get_len(vendor_event, afc_req);
568
569 if (ret) {
570 osif_err("Failed to update AFC request vendor event");
571 goto fail;
572 }
573
574 osif_debug("Sending AFC expiry event to user application");
575 wlan_cfg80211_vendor_event(vendor_event, GFP_ATOMIC);
576
577 return 0;
578
579 fail:
580 wlan_cfg80211_vendor_free_skb(vendor_event);
581 return -EINVAL;
582 }
583
584 int
wlan_cfg80211_afc_send_update_complete(struct wlan_objmgr_pdev * pdev,struct reg_fw_afc_power_event * afc_evt)585 wlan_cfg80211_afc_send_update_complete(struct wlan_objmgr_pdev *pdev,
586 struct reg_fw_afc_power_event *afc_evt)
587 {
588 struct sk_buff *vendor_event;
589 struct pdev_osif_priv *osif_priv;
590 int vendor_buffer_len;
591
592 osif_priv = wlan_pdev_get_ospriv(pdev);
593 if (!osif_priv) {
594 osif_err("PDEV OS private structure is NULL");
595 return -EINVAL;
596 }
597
598 if (!afc_evt) {
599 osif_err("afc power event is NULL");
600 return -EINVAL;
601 }
602
603 vendor_buffer_len = afc_power_event_update_or_get_len(NULL, afc_evt);
604
605 vendor_event = wlan_cfg80211_vendor_event_alloc(osif_priv->wiphy,
606 NULL,
607 vendor_buffer_len,
608 QCA_NL80211_VENDOR_SUBCMD_AFC_EVENT_INDEX,
609 GFP_ATOMIC);
610 if (!vendor_event) {
611 osif_err("cfg80211 vendor event alloc failed");
612 return -ENOMEM;
613 }
614
615 if (afc_power_event_update_or_get_len(vendor_event, afc_evt)) {
616 osif_err("Failed to update AFC power vendor event");
617 goto fail;
618 }
619
620 osif_debug("Sending AFC update complete event to user application");
621 wlan_cfg80211_vendor_event(vendor_event, GFP_ATOMIC);
622
623 return 0;
624
625 fail:
626 wlan_cfg80211_vendor_free_skb(vendor_event);
627 return -EINVAL;
628 }
629
630 /**
631 * afc_response_display() - Function to display AFC response information
632 * @rsp: Pointer to AFC response structure which is extracted from vendor
633 * command
634 *
635 * Return: None
636 */
afc_response_display(struct afc_resp_extracted * rsp)637 static void afc_response_display(struct afc_resp_extracted *rsp)
638 {
639 int iter, j;
640
641 if (rsp->json_data)
642 return;
643
644 osif_debug("Req ID: %u TTL: %u Date: 0x%x Time: 0x%x Resp code: %u Freq objs: %u Opclass objs: %u",
645 rsp->request_id,
646 rsp->time_to_live,
647 rsp->avail_exp_date,
648 rsp->avail_exp_time,
649 rsp->afc_serv_resp_code,
650 rsp->num_frange_obj,
651 rsp->num_opclass);
652
653 for (iter = 0; iter < rsp->num_frange_obj; iter++)
654 osif_debug("Freq Info[%d]: start %u end %u PSD %u",
655 iter,
656 rsp->frange[iter].freq_start,
657 rsp->frange[iter].freq_end,
658 rsp->frange[iter].psd);
659
660 for (iter = 0; iter < rsp->num_opclass; iter++) {
661 osif_debug("Opclass[%d]: %u Num channels: %u",
662 iter,
663 rsp->op_obj[iter].opclass,
664 rsp->op_obj[iter].num_channel);
665
666 for (j = 0; j < rsp->op_obj[iter].num_channel; j++)
667 osif_debug("Channel Info[%d]:CFI: %u EIRP: %u",
668 j,
669 rsp->op_obj[iter].chan_eirp[j].channel_cfi,
670 rsp->op_obj[iter].chan_eirp[j].eirp);
671 }
672 }
673
674 /**
675 * wlan_parse_afc_rsp_freq_psd() - Function to parse AFC response channel
676 * frequency range PSD information from NL attribute.
677 * @attr: Pointer to NL AFC frequency PSD attributes
678 * @rsp: Pointer to AFC extracted response
679 *
680 * Return: Negative error number if failed, otherwise success
681 */
682 static int
wlan_parse_afc_rsp_freq_psd(struct nlattr * attr,struct afc_resp_extracted * rsp)683 wlan_parse_afc_rsp_freq_psd(struct nlattr *attr, struct afc_resp_extracted *rsp)
684 {
685 int ret = -EINVAL;
686 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_MAX + 1];
687 struct nlattr *cur_attr = NULL, *tb2;
688 uint32_t rem;
689 qdf_size_t i = 0;
690
691 nla_for_each_nested(cur_attr, attr, rem) {
692 if (i >= NUM_6GHZ_CHANNELS) {
693 osif_err("Ignore exceed");
694 break;
695 }
696 if (wlan_cfg80211_nla_parse(tb,
697 QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_MAX,
698 nla_data(cur_attr),
699 nla_len(cur_attr),
700 NULL)) {
701 osif_err("Invalid ATTR");
702 return ret;
703 }
704
705 tb2 = tb[QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_START];
706 if (tb2)
707 rsp->frange[i].freq_start = nla_get_u32(tb2);
708
709 tb2 = tb[QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_RANGE_END];
710 if (tb2)
711 rsp->frange[i].freq_end = nla_get_u32(tb2);
712
713 tb2 = tb[QCA_WLAN_VENDOR_ATTR_AFC_FREQ_PSD_INFO_PSD];
714 if (tb2)
715 rsp->frange[i].psd = nla_get_u32(tb2);
716
717 i++;
718 }
719
720 rsp->num_frange_obj = i;
721 return i;
722 }
723
724 /**
725 * wlan_parse_afc_rsp_opclass_eirp() - Function to parse AFC response operation
726 * class EIRP information from NL attributes.
727 * @attr: Pointer to NL AFC operation class EIRP attributes
728 * @rsp: Pointer to AFC extracted response
729 *
730 * Return: Negative error number if failed, otherwise success
731 */
732 static int
wlan_parse_afc_rsp_opclass_eirp(struct nlattr * attr,struct afc_resp_extracted * rsp)733 wlan_parse_afc_rsp_opclass_eirp(struct nlattr *attr,
734 struct afc_resp_extracted *rsp)
735 {
736 int ret = -EINVAL;
737 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_MAX + 1];
738 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_MAX + 1];
739 struct nlattr *cur_attr = NULL, *sub_attr = NULL, *tb;
740 uint32_t rem, sub_rem;
741 int i = 0, ch_idx;
742
743 nla_for_each_nested(cur_attr, attr, rem) {
744 if (i >= REG_MAX_SUPP_OPER_CLASSES) {
745 osif_err("Ignore opclass list exceed");
746 break;
747 }
748 if (wlan_cfg80211_nla_parse(tb1,
749 QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_MAX,
750 nla_data(cur_attr),
751 nla_len(cur_attr),
752 NULL)) {
753 osif_err("Invalid ATTR");
754 return ret;
755 }
756 tb = tb1[QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_OPCLASS];
757 if (tb)
758 rsp->op_obj[i].opclass = nla_get_u8(tb);
759
760 tb = tb1[QCA_WLAN_VENDOR_ATTR_AFC_OPCLASS_INFO_CHAN_LIST];
761 if (!tb) {
762 osif_err("No opclass channel list");
763 return ret;
764 }
765
766 ch_idx = 0;
767
768 nla_for_each_nested(sub_attr, tb, sub_rem) {
769 if (ch_idx >= NUM_6GHZ_CHANNELS) {
770 osif_err("Ignore eirp list exceed");
771 break;
772 }
773 if (wlan_cfg80211_nla_parse(tb2,
774 QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_MAX,
775 nla_data(sub_attr),
776 nla_len(sub_attr),
777 NULL)) {
778 osif_err("Invalid ATTR");
779 return ret;
780 }
781 tb = tb2[QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_CHAN_NUM];
782 if (tb)
783 rsp->op_obj[i].chan_eirp[ch_idx].channel_cfi =
784 nla_get_u8(tb);
785 tb = tb2[QCA_WLAN_VENDOR_ATTR_AFC_CHAN_EIRP_INFO_EIRP];
786 if (tb)
787 rsp->op_obj[i].chan_eirp[ch_idx].eirp =
788 nla_get_u32(tb);
789 ch_idx++;
790 }
791 rsp->op_obj[i].num_channel = ch_idx;
792
793 i++;
794 }
795 rsp->num_opclass = i;
796 return i;
797 }
798
799 /**
800 * free_extract_afc_rsp() - Function to free AFC extracted response
801 * @rsp: Pointer to AFC extracted response
802 *
803 * Return: None
804 */
free_extract_afc_rsp(struct afc_resp_extracted * rsp)805 static inline void free_extract_afc_rsp(struct afc_resp_extracted *rsp)
806 {
807 if (!rsp)
808 return;
809
810 qdf_mem_free(rsp->json_data);
811 qdf_mem_free(rsp);
812 }
813
814 /**
815 * extract_afc_resp() - Function to extract AFC response
816 * @attr: Pointer to NL attribute array
817 *
818 * Return: Pointer to AFC response axtracted
819 */
extract_afc_resp(struct nlattr ** attr)820 static struct afc_resp_extracted *extract_afc_resp(struct nlattr **attr)
821 {
822 struct afc_resp_extracted *afc_rsp;
823 struct nlattr *nl;
824
825 if (!attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_TIME_TO_LIVE]) {
826 osif_err("ATTR AFC RESP TIME TO LIVE is required");
827 return NULL;
828 }
829
830 if (!attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_REQ_ID]) {
831 osif_err("ATTR AFC RESP REQ ID is required");
832 return NULL;
833 }
834
835 if (!attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_DATE]) {
836 osif_err("ATTR AFC RESP EXP DATE is required");
837 return NULL;
838 }
839
840 if (!attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_TIME]) {
841 osif_err("ATTR AFC RESP EXP TIME is required");
842 return NULL;
843 }
844
845 if (!attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_AFC_SERVER_RESP_CODE]) {
846 osif_err("ATTR AFC RESP SERVER RESP CODE is required");
847 return NULL;
848 }
849
850 if (!attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_FREQ_PSD_INFO]) {
851 osif_err("ATTR AFC RESP FREQ PSD INFO is required");
852 return NULL;
853 }
854
855 if (!attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_OPCLASS_CHAN_EIRP_INFO]) {
856 osif_err("ATTR AFC RESP OPCLASS CHAN EIRP INFO is required");
857 return NULL;
858 }
859
860 afc_rsp = qdf_mem_malloc(sizeof(*afc_rsp));
861 if (!afc_rsp)
862 return NULL;
863
864 if (attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_DATA]) {
865 nl = attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_DATA];
866 afc_rsp->json_data = qdf_mem_malloc(nla_len(nl));
867 if (!afc_rsp->json_data)
868 goto fail;
869
870 afc_rsp->json_len = nla_len(nl);
871 nla_memcpy(afc_rsp->json_data, nl, afc_rsp->json_len);
872 }
873
874 afc_rsp->time_to_live =
875 nla_get_u32(attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_TIME_TO_LIVE]);
876
877 afc_rsp->request_id =
878 nla_get_u32(attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_REQ_ID]);
879
880 afc_rsp->avail_exp_date =
881 nla_get_u32(attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_DATE]);
882
883 afc_rsp->avail_exp_time =
884 nla_get_u32(attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_EXP_TIME]);
885
886 afc_rsp->afc_serv_resp_code =
887 nla_get_s32(attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_AFC_SERVER_RESP_CODE]);
888
889 if (wlan_parse_afc_rsp_freq_psd(attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_FREQ_PSD_INFO],
890 afc_rsp) <= 0) {
891 osif_err("parse freq psd err");
892 goto fail;
893 }
894
895 if (wlan_parse_afc_rsp_opclass_eirp(attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_OPCLASS_CHAN_EIRP_INFO],
896 afc_rsp) <= 0) {
897 osif_err("parse opclass eirp err");
898 goto fail;
899 }
900
901 return afc_rsp;
902 fail:
903 osif_err("Error parsing the AFC response from application");
904 free_extract_afc_rsp(afc_rsp);
905 return NULL;
906 }
907
908 /**
909 * is_target_support_json_format() - API to get whether target support JSON
910 * format AFC response.
911 * @psoc: Pointer to PSOC object
912 *
913 * Return: Boolean
914 */
915
is_target_support_json_format(struct wlan_objmgr_psoc * psoc)916 static inline bool is_target_support_json_format(struct wlan_objmgr_psoc *psoc)
917 {
918 return false;
919 }
920
921 /**
922 * fill_host_afc_response_buffer() - Function to fill AFC response buffer which
923 * pass to target.
924 * @psoc: Pointer to PSOC object
925 * @afc_rsp: Pointer to AFC extracted response
926 * @host_afc: Pointer to interface AFC response buffer with target
927 *
928 * Return: Negative error number if failed, otherwise success
929 */
930 static int
fill_host_afc_response_buffer(struct wlan_objmgr_psoc * psoc,struct afc_resp_extracted * afc_rsp,struct wlan_afc_host_resp * host_afc)931 fill_host_afc_response_buffer(struct wlan_objmgr_psoc *psoc,
932 struct afc_resp_extracted *afc_rsp,
933 struct wlan_afc_host_resp *host_afc)
934 {
935 int ret = -EINVAL;
936 uint32_t bin_len, tmp_len;
937 struct wlan_afc_bin_resp_data *afc_bin;
938 struct wlan_afc_resp_freq_psd_info *freq_psd;
939 struct wlan_afc_resp_opclass_info *op;
940 struct wlan_afc_resp_eirp_info *chan_eirp;
941 int i, j;
942
943 if (!afc_rsp || !host_afc)
944 return ret;
945
946 host_afc->time_to_live = afc_rsp->time_to_live;
947 if (is_target_support_json_format(psoc)) {
948 if (!afc_rsp->json_data) {
949 osif_err("No JSON data");
950 return ret;
951 }
952 if (afc_rsp->json_len >
953 IF_AFC_RESPONSE_MAX_LEN - sizeof(*host_afc)) {
954 osif_err("Invalid JSON data len %d", afc_rsp->json_len);
955 return ret;
956 }
957 host_afc->resp_format = REG_AFC_SERV_RESP_FORMAT_JSON;
958 host_afc->length = sizeof(*host_afc) + afc_rsp->json_len;
959 qdf_mem_copy(host_afc->afc_resp,
960 afc_rsp->json_data,
961 afc_rsp->json_len);
962 return host_afc->length;
963 }
964 host_afc->resp_format = REG_AFC_SERV_RESP_FORMAT_BINARY;
965 afc_bin = (struct wlan_afc_bin_resp_data *)host_afc->afc_resp;
966 afc_bin->request_id = afc_rsp->request_id;
967 afc_bin->avail_exp_time_d = afc_rsp->avail_exp_date;
968 afc_bin->avail_exp_time_t = afc_rsp->avail_exp_time;
969 afc_bin->afc_serv_resp_code = afc_rsp->afc_serv_resp_code;
970 afc_bin->num_frequency_obj = afc_rsp->num_frange_obj;
971 afc_bin->num_channel_obj = afc_rsp->num_opclass;
972 bin_len = sizeof(*host_afc) + sizeof(*afc_bin);
973
974 if (bin_len + sizeof(*freq_psd) * afc_bin->num_frequency_obj >
975 IF_AFC_RESPONSE_MAX_LEN) {
976 osif_err("Invalid number frequency obj %d",
977 afc_bin->num_frequency_obj);
978 return ret;
979 }
980 freq_psd = (struct wlan_afc_resp_freq_psd_info *)
981 ((uint8_t *)host_afc + bin_len);
982 for (i = 0; i < afc_bin->num_frequency_obj; i++) {
983 freq_psd->freq_info =
984 (afc_rsp->frange[i].freq_start & 0x0000FFFF) |
985 (afc_rsp->frange[i].freq_end << 16);
986 freq_psd->max_psd = afc_rsp->frange[i].psd;
987 freq_psd++;
988 }
989 bin_len += sizeof(*freq_psd) * afc_bin->num_frequency_obj;
990
991 tmp_len = bin_len;
992 for (i = 0; i < afc_rsp->num_opclass; i++) {
993 tmp_len += sizeof(*op) +
994 sizeof(*chan_eirp) * afc_rsp->op_obj[i].num_channel;
995 }
996 if (tmp_len > IF_AFC_RESPONSE_MAX_LEN) {
997 osif_err("Invalid opclass channel eirp info");
998 return ret;
999 }
1000
1001 op = (struct wlan_afc_resp_opclass_info *)
1002 ((uint8_t *)host_afc + bin_len);
1003 for (i = 0; i < afc_rsp->num_opclass; i++) {
1004 op->opclass = afc_rsp->op_obj[i].opclass;
1005 op->num_channels = afc_rsp->op_obj[i].num_channel;
1006 chan_eirp = (struct wlan_afc_resp_eirp_info *)
1007 ((uint8_t *)op + sizeof(*op));
1008 for (j = 0; j < afc_rsp->op_obj[i].num_channel; j++) {
1009 chan_eirp->channel_cfi =
1010 afc_rsp->op_obj[i].chan_eirp[j].channel_cfi;
1011 chan_eirp->max_eirp_pwr =
1012 afc_rsp->op_obj[i].chan_eirp[j].eirp;
1013 chan_eirp++;
1014 }
1015 op = (struct wlan_afc_resp_opclass_info *)chan_eirp;
1016 }
1017
1018 host_afc->length = tmp_len;
1019
1020 return tmp_len;
1021 }
1022
wlan_cfg80211_vendor_afc_response(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev,const void * data,int data_len)1023 int wlan_cfg80211_vendor_afc_response(struct wlan_objmgr_psoc *psoc,
1024 struct wlan_objmgr_pdev *pdev,
1025 const void *data,
1026 int data_len)
1027 {
1028 int ret = -EINVAL;
1029 struct nlattr *attr[QCA_WLAN_VENDOR_ATTR_AFC_RESP_MAX + 1];
1030 struct afc_resp_extracted *afc_rsp;
1031 struct wlan_afc_host_resp *host_afc;
1032 struct reg_afc_resp_rx_ind_info afc_ind_obj;
1033 bool is_json = is_target_support_json_format(psoc);
1034
1035 if (wlan_cfg80211_nla_parse(attr, QCA_WLAN_VENDOR_ATTR_AFC_RESP_MAX,
1036 data, data_len,
1037 wlan_cfg80211_afc_response_policy)) {
1038 osif_err("Invalid AFC RESP ATTR");
1039 return ret;
1040 }
1041
1042 afc_rsp = extract_afc_resp(attr);
1043 if (!afc_rsp)
1044 return ret;
1045
1046 afc_response_display(afc_rsp);
1047
1048 host_afc = qdf_mem_malloc(IF_AFC_RESPONSE_MAX_LEN);
1049 if (!host_afc)
1050 goto fail;
1051
1052 ret = fill_host_afc_response_buffer(psoc, afc_rsp, host_afc);
1053 if (ret <= 0)
1054 goto fail;
1055
1056 ret = ucfg_afc_data_send(psoc, pdev, host_afc, ret);
1057 if (ret) {
1058 osif_err("Failed to send afc data");
1059 goto fail;
1060 }
1061
1062 afc_ind_obj.cmd_type = REG_AFC_CMD_SERV_RESP_READY;
1063 afc_ind_obj.serv_resp_format =
1064 is_json ? REG_AFC_SERV_RESP_FORMAT_JSON :
1065 REG_AFC_SERV_RESP_FORMAT_BINARY;
1066 if (ucfg_reg_send_afc_resp_rx_ind(pdev, &afc_ind_obj) !=
1067 QDF_STATUS_SUCCESS) {
1068 osif_err("Failed to send afc rx indication");
1069 ret = -EINVAL;
1070 }
1071
1072 fail:
1073 free_extract_afc_rsp(afc_rsp);
1074 qdf_mem_free(host_afc);
1075 return ret;
1076 }
1077