xref: /wlan-driver/qca-wifi-host-cmn/os_if/linux/afc/src/wlan_cfg80211_afc.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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