xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_manager.c (revision 1f55ed1a9f5050d8da228aa8dd3fff7c0242aa71)
1 /*
2  * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * DOC: contains scan manager functionality
21  */
22 
23 #include <wlan_serialization_api.h>
24 #include <wlan_scan_ucfg_api.h>
25 #include <wlan_scan_tgt_api.h>
26 #include "wlan_scan_main.h"
27 #include "wlan_scan_manager.h"
28 #include "wlan_utility.h"
29 #ifdef FEATURE_WLAN_SCAN_PNO
30 #include <host_diag_core_event.h>
31 #endif
32 
33 QDF_STATUS
34 scm_scan_free_scan_request_mem(struct scan_start_request *req)
35 {
36 	void *ie;
37 
38 	if (!req) {
39 		scm_err("null request");
40 		QDF_ASSERT(0);
41 		return QDF_STATUS_E_FAILURE;
42 	}
43 	scm_debug("freed scan request: 0x%pK, scan_id: %d, requester: %d",
44 		  req, req->scan_req.scan_id, req->scan_req.scan_req_id);
45 	/* Free vendor(extra) ie */
46 	ie = req->scan_req.extraie.ptr;
47 	if (ie) {
48 		req->scan_req.extraie.ptr = NULL;
49 		req->scan_req.extraie.len = 0;
50 		qdf_mem_free(ie);
51 	}
52 
53 	/* Free htcap ie */
54 	ie = req->scan_req.htcap.ptr;
55 	if (ie) {
56 		req->scan_req.htcap.len = 0;
57 		req->scan_req.htcap.ptr = NULL;
58 		qdf_mem_free(ie);
59 	}
60 
61 	/* Free vhtcap ie */
62 	ie = req->scan_req.vhtcap.ptr;
63 	if (ie) {
64 		req->scan_req.vhtcap.len = 0;
65 		req->scan_req.vhtcap.ptr = NULL;
66 		qdf_mem_free(ie);
67 	}
68 	/* free scan_start_request memory */
69 	qdf_mem_free(req);
70 
71 	return QDF_STATUS_SUCCESS;
72 }
73 
74 static QDF_STATUS
75 scm_scan_get_pdev_global_event_handlers(struct scan_event_listeners *listeners,
76 		struct pdev_scan_ev_handler *pdev_ev_handler)
77 {
78 	uint32_t i;
79 	struct cb_handler *cb_handlers  = &(pdev_ev_handler->cb_handlers[0]);
80 
81 	for (i = 0; i < MAX_SCAN_EVENT_HANDLERS_PER_PDEV; i++, cb_handlers++) {
82 		if ((cb_handlers->func) &&
83 		    (listeners->count < MAX_SCAN_EVENT_LISTENERS)) {
84 			listeners->cb[listeners->count].func =
85 				cb_handlers->func;
86 			listeners->cb[listeners->count].arg =
87 				cb_handlers->arg;
88 			listeners->count++;
89 		}
90 	}
91 
92 	return QDF_STATUS_SUCCESS;
93 }
94 
95 static QDF_STATUS
96 scm_scan_get_requester_event_handler(struct scan_event_listeners *listeners,
97 		struct scan_requester_info *requesters,
98 		wlan_scan_requester requester_id)
99 {
100 	uint32_t idx;
101 	struct cb_handler *ev_handler;
102 
103 	idx = requester_id & WLAN_SCAN_REQUESTER_ID_PREFIX;
104 	if (idx != WLAN_SCAN_REQUESTER_ID_PREFIX)
105 		return QDF_STATUS_SUCCESS;
106 
107 	idx = requester_id & WLAN_SCAN_REQUESTER_ID_MASK;
108 	if (idx < WLAN_MAX_REQUESTORS) {
109 		ev_handler = &(requesters[idx].ev_handler);
110 		if (ev_handler->func) {
111 			if (listeners->count < MAX_SCAN_EVENT_LISTENERS) {
112 				listeners->cb[listeners->count].func =
113 							     ev_handler->func;
114 				listeners->cb[listeners->count].arg =
115 							     ev_handler->arg;
116 				listeners->count++;
117 			}
118 		}
119 		return QDF_STATUS_SUCCESS;
120 	} else {
121 		scm_err("invalid requester id");
122 		return QDF_STATUS_E_INVAL;
123 	}
124 
125 }
126 
127 static void scm_scan_post_event(struct wlan_objmgr_vdev *vdev,
128 		struct scan_event *event)
129 {
130 	uint32_t i = 0;
131 	struct wlan_scan_obj *scan;
132 	struct pdev_scan_ev_handler *pdev_ev_handler;
133 	struct cb_handler *cb_handlers;
134 	struct scan_requester_info *requesters;
135 	struct scan_event_listeners *listeners;
136 
137 	if (!vdev || !event) {
138 		scm_err("vdev: 0x%pK, event: 0x%pK", vdev, event);
139 		return;
140 	}
141 	if (!event->requester) {
142 		scm_err("invalid requester id");
143 		QDF_ASSERT(0);
144 	}
145 	scan = wlan_vdev_get_scan_obj(vdev);
146 	pdev_ev_handler = wlan_vdev_get_pdev_scan_ev_handlers(vdev);
147 	cb_handlers = &(pdev_ev_handler->cb_handlers[0]);
148 	requesters = scan->requesters;
149 
150 	scm_debug("vdev: %d, type: %d, reason: %d, freq: %d, req: %d, scanid: %d",
151 		  event->vdev_id, event->type, event->reason, event->chan_freq,
152 		  event->requester, event->scan_id);
153 
154 	listeners = qdf_mem_malloc_atomic(sizeof(*listeners));
155 	if (!listeners) {
156 		scm_warn("couldn't allocate listeners list");
157 		return;
158 	}
159 
160 	/* initialize number of listeners */
161 	listeners->count = 0;
162 
163 	/*
164 	 * Initiator of scan request decides which all scan events
165 	 * he is interested in and FW will send only those scan events
166 	 * to host driver.
167 	 * All the events received by scan module will be notified
168 	 * to all registered handlers.
169 	 */
170 
171 	qdf_spin_lock_bh(&scan->lock);
172 	/* find all global scan event handlers on this pdev */
173 	scm_scan_get_pdev_global_event_handlers(listeners, pdev_ev_handler);
174 	/* find owner who triggered this scan request */
175 	scm_scan_get_requester_event_handler(listeners, requesters,
176 			event->requester);
177 	qdf_spin_unlock_bh(&scan->lock);
178 
179 	/* notify all interested handlers */
180 	for (i = 0; i < listeners->count; i++) {
181 		scm_debug("func: 0x%pK, arg: 0x%pK",
182 			listeners->cb[i].func, listeners->cb[i].arg);
183 		listeners->cb[i].func(vdev, event, listeners->cb[i].arg);
184 	}
185 	qdf_mem_free(listeners);
186 }
187 
188 static QDF_STATUS
189 scm_release_serialization_command(struct wlan_objmgr_vdev *vdev,
190 		uint32_t scan_id)
191 {
192 	struct wlan_serialization_queued_cmd_info cmd = {0};
193 
194 	cmd.requestor = WLAN_UMAC_COMP_SCAN;
195 	cmd.cmd_type = WLAN_SER_CMD_SCAN;
196 	cmd.cmd_id = scan_id;
197 	cmd.req_type = WLAN_SER_CANCEL_SINGLE_SCAN;
198 	cmd.vdev = vdev;
199 	cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
200 
201 	/* Inform serialization for command completion */
202 	wlan_serialization_remove_cmd(&cmd);
203 
204 	return QDF_STATUS_SUCCESS;
205 }
206 
207 static QDF_STATUS
208 scm_post_internal_scan_complete_event(struct scan_start_request *req,
209 		enum scan_completion_reason reason)
210 {
211 	struct scan_event event = {0, };
212 
213 	/* prepare internal scan complete event */
214 	event.type = SCAN_EVENT_TYPE_COMPLETED;
215 	event.reason = reason;
216 	event.chan_freq = 0; /* Invalid frequency */
217 	event.vdev_id =  req->scan_req.vdev_id;
218 	event.requester = req->scan_req.scan_req_id;
219 	event.scan_id = req->scan_req.scan_id;
220 	/* Fill scan_start_request used to trigger this scan */
221 	event.scan_start_req = req;
222 	/* post scan event to registered handlers */
223 	scm_scan_post_event(req->vdev, &event);
224 
225 	return QDF_STATUS_SUCCESS;
226 }
227 
228 static inline struct pdev_scan_info *
229 scm_scan_get_pdev_priv_info(uint8_t pdev_id, struct wlan_scan_obj *scan_obj)
230 {
231 	return &scan_obj->pdev_info[pdev_id];
232 }
233 
234 static QDF_STATUS
235 scm_update_last_scan_time(struct scan_start_request *req)
236 {
237 	uint8_t pdev_id;
238 	struct wlan_scan_obj *scan_obj;
239 	struct pdev_scan_info *pdev_scan_info;
240 
241 	scan_obj = wlan_vdev_get_scan_obj(req->vdev);
242 	pdev_id = wlan_scan_vdev_get_pdev_id(req->vdev);
243 	pdev_scan_info = scm_scan_get_pdev_priv_info(pdev_id, scan_obj);
244 	/* update last scan start time */
245 	pdev_scan_info->last_scan_time = qdf_system_ticks();
246 
247 	return QDF_STATUS_SUCCESS;
248 }
249 
250 static QDF_STATUS
251 scm_activate_scan_request(struct scan_start_request *req)
252 {
253 	QDF_STATUS status;
254 
255 	status = tgt_scan_start(req);
256 	if (status != QDF_STATUS_SUCCESS) {
257 		scm_err("tgt_scan_start failed, status: %d", status);
258 		/* scan could not be started and hence
259 		 * we will not receive any completions.
260 		 * post scan cancelled
261 		 */
262 		scm_post_internal_scan_complete_event(req,
263 				SCAN_REASON_CANCELLED);
264 		return status;
265 	}
266 	/* save last scan start time */
267 	status = scm_update_last_scan_time(req);
268 
269 	return status;
270 }
271 
272 static QDF_STATUS
273 scm_cancel_scan_request(struct scan_start_request *req)
274 {
275 	struct scan_cancel_request cancel_req = {0, };
276 	QDF_STATUS status;
277 
278 	cancel_req.vdev = req->vdev;
279 	cancel_req.cancel_req.scan_id = req->scan_req.scan_id;
280 	cancel_req.cancel_req.requester = req->scan_req.scan_req_id;
281 	cancel_req.cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE;
282 	cancel_req.cancel_req.vdev_id = req->scan_req.vdev_id;
283 	/* send scan cancel to fw */
284 	status = tgt_scan_cancel(&cancel_req);
285 	if (status != QDF_STATUS_SUCCESS)
286 		scm_err("tgt_scan_cancel failed: status: %d, scanid: %d",
287 			status, req->scan_req.scan_id);
288 	/* notify event handler about scan cancellation */
289 	scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED);
290 
291 	return status;
292 }
293 
294 static QDF_STATUS
295 scm_scan_serialize_callback(struct wlan_serialization_command *cmd,
296 	enum wlan_serialization_cb_reason reason)
297 {
298 	struct scan_start_request *req;
299 	QDF_STATUS status;
300 
301 	if (!cmd) {
302 		scm_err("cmd is NULL, reason: %d", reason);
303 		QDF_ASSERT(0);
304 		return QDF_STATUS_E_NULL_VALUE;
305 	}
306 
307 	if (!cmd->umac_cmd) {
308 		scm_err("cmd->umac_cmd is NULL , reason: %d", reason);
309 		QDF_ASSERT(0);
310 		return QDF_STATUS_E_NULL_VALUE;
311 	}
312 
313 	req = cmd->umac_cmd;
314 	scm_debug("reason:%d, reqid:%d, scanid:%d, vdevid:%d, vdev:0x%pK",
315 		reason, req->scan_req.scan_req_id, req->scan_req.scan_id,
316 		req->scan_req.vdev_id, req->vdev);
317 
318 	if (!req->vdev) {
319 		scm_err("NULL vdev. req:0x%pK, reason:%d\n", req, reason);
320 		QDF_ASSERT(0);
321 		return QDF_STATUS_E_NULL_VALUE;
322 	}
323 
324 	qdf_mtrace(QDF_MODULE_ID_SERIALIZATION, QDF_MODULE_ID_SCAN, reason,
325 		   req->scan_req.vdev_id, req->scan_req.scan_id);
326 
327 	switch (reason) {
328 	case WLAN_SER_CB_ACTIVATE_CMD:
329 		/* command moved to active list
330 		 * modify the params if required for concurency case.
331 		 */
332 		status = scm_activate_scan_request(req);
333 		break;
334 
335 	case WLAN_SER_CB_CANCEL_CMD:
336 		/* command removed from pending list.
337 		 * notify registered scan event handlers with
338 		 * status completed and reason cancelled.
339 		 */
340 		status = scm_post_internal_scan_complete_event(req,
341 				SCAN_REASON_CANCELLED);
342 		break;
343 
344 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
345 		/* active command timed out.
346 		 * prepare internal scan cancel request
347 		 */
348 		status = scm_cancel_scan_request(req);
349 		break;
350 
351 	case WLAN_SER_CB_RELEASE_MEM_CMD:
352 		/* command successfully completed.
353 		 * Release vdev reference and free scan_start_request memory
354 		 */
355 		cmd->umac_cmd = NULL;
356 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
357 		status = scm_scan_free_scan_request_mem(req);
358 		break;
359 
360 	default:
361 		/* Do nothing but logging */
362 		QDF_ASSERT(0);
363 		status = QDF_STATUS_E_INVAL;
364 		break;
365 	}
366 
367 	return status;
368 }
369 
370 bool scm_is_scan_allowed(struct wlan_objmgr_vdev *vdev)
371 {
372 	struct wlan_scan_obj *scan_psoc_obj;
373 	struct scan_vdev_obj *scan_vdev_obj;
374 
375 	if (!vdev) {
376 		scm_err("vdev is NULL");
377 		return false;
378 	}
379 
380 	scan_psoc_obj = wlan_vdev_get_scan_obj(vdev);
381 	if (!scan_psoc_obj) {
382 		scm_err("Couldn't find scan psoc object");
383 		return false;
384 	}
385 
386 	if (scan_psoc_obj->scan_disabled) {
387 		scm_err_rl("scan disabled %x, for psoc",
388 			   scan_psoc_obj->scan_disabled);
389 		return false;
390 	}
391 
392 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
393 	if (!scan_vdev_obj) {
394 		scm_err("Couldn't find scan vdev object");
395 		return false;
396 	}
397 
398 	if (scan_vdev_obj->scan_disabled) {
399 		scm_err_rl("scan disabled %x on vdev_id:%d",
400 			   scan_vdev_obj->scan_disabled,
401 			   wlan_vdev_get_id(vdev));
402 		return false;
403 	}
404 
405 	return true;
406 }
407 
408 QDF_STATUS
409 scm_scan_start_req(struct scheduler_msg *msg)
410 {
411 	struct wlan_serialization_command cmd = {0, };
412 	enum wlan_serialization_status ser_cmd_status;
413 	struct scan_start_request *req = NULL;
414 	struct wlan_scan_obj *scan_obj;
415 	QDF_STATUS status = QDF_STATUS_SUCCESS;
416 
417 	if (!msg) {
418 		scm_err("msg received is NULL");
419 		QDF_ASSERT(0);
420 		return QDF_STATUS_E_NULL_VALUE;
421 	}
422 	if (!msg->bodyptr) {
423 		scm_err("bodyptr is NULL");
424 		QDF_ASSERT(0);
425 		return QDF_STATUS_E_NULL_VALUE;
426 	}
427 
428 	req = msg->bodyptr;
429 
430 	if (!scm_is_scan_allowed(req->vdev)) {
431 		scm_err("scan disabled, rejecting the scan req");
432 		status = QDF_STATUS_E_NULL_VALUE;
433 		goto err;
434 	}
435 
436 	scan_obj = wlan_vdev_get_scan_obj(req->vdev);
437 	if (!scan_obj) {
438 		scm_debug("Couldn't find scan object");
439 		status = QDF_STATUS_E_NULL_VALUE;
440 		goto err;
441 	}
442 
443 	cmd.cmd_type = WLAN_SER_CMD_SCAN;
444 	cmd.cmd_id = req->scan_req.scan_id;
445 	cmd.cmd_cb = (wlan_serialization_cmd_callback)
446 		scm_scan_serialize_callback;
447 	cmd.umac_cmd = req;
448 	cmd.source = WLAN_UMAC_COMP_SCAN;
449 	cmd.is_high_priority = false;
450 	cmd.cmd_timeout_duration = req->scan_req.max_scan_time +
451 		SCAN_TIMEOUT_GRACE_PERIOD;
452 	cmd.vdev = req->vdev;
453 
454 	if (scan_obj->disable_timeout)
455 		cmd.cmd_timeout_duration = 0;
456 
457 	scm_debug("req: 0x%pK, reqid: %d, scanid: %d, vdevid: %d",
458 		  req, req->scan_req.scan_req_id, req->scan_req.scan_id,
459 		  req->scan_req.vdev_id);
460 
461 	qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SERIALIZATION,
462 		   WLAN_SER_CMD_SCAN, req->vdev->vdev_objmgr.vdev_id,
463 		   req->scan_req.scan_id);
464 
465 	ser_cmd_status = wlan_serialization_request(&cmd);
466 	scm_debug("wlan_serialization_request status:%d", ser_cmd_status);
467 
468 	switch (ser_cmd_status) {
469 	case WLAN_SER_CMD_PENDING:
470 		/* command moved to pending list.Do nothing */
471 		break;
472 	case WLAN_SER_CMD_ACTIVE:
473 		/* command moved to active list. Do nothing */
474 		break;
475 	case WLAN_SER_CMD_DENIED_LIST_FULL:
476 	case WLAN_SER_CMD_DENIED_RULES_FAILED:
477 	case WLAN_SER_CMD_DENIED_UNSPECIFIED:
478 		goto err;
479 	default:
480 		QDF_ASSERT(0);
481 		status = QDF_STATUS_E_INVAL;
482 		goto err;
483 	}
484 
485 	return status;
486 err:
487 	/*
488 	 * notify registered scan event handlers
489 	 * about internal error
490 	 */
491 	scm_post_internal_scan_complete_event(req,
492 					      SCAN_REASON_INTERNAL_FAILURE);
493 	/*
494 	 * cmd can't be serviced.
495 	 * release vdev reference and free scan_start_request memory
496 	 */
497 	if (req) {
498 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
499 		scm_scan_free_scan_request_mem(req);
500 	}
501 
502 	return status;
503 }
504 
505 static inline enum wlan_serialization_cancel_type
506 get_serialization_cancel_type(enum scan_cancel_req_type type)
507 {
508 	enum wlan_serialization_cancel_type serialization_type;
509 
510 	switch (type) {
511 	case WLAN_SCAN_CANCEL_SINGLE:
512 		serialization_type = WLAN_SER_CANCEL_SINGLE_SCAN;
513 		break;
514 	case WLAN_SCAN_CANCEL_VDEV_ALL:
515 		serialization_type = WLAN_SER_CANCEL_VDEV_SCANS;
516 		break;
517 	case WLAN_SCAN_CANCEL_PDEV_ALL:
518 		serialization_type = WLAN_SER_CANCEL_PDEV_SCANS;
519 		break;
520 	default:
521 		QDF_ASSERT(0);
522 		scm_warn("invalid scan_cancel_req_type: %d", type);
523 		serialization_type = WLAN_SER_CANCEL_PDEV_SCANS;
524 		break;
525 	}
526 
527 	return serialization_type;
528 }
529 
530 QDF_STATUS
531 scm_scan_cancel_req(struct scheduler_msg *msg)
532 {
533 	struct wlan_serialization_queued_cmd_info cmd = {0,};
534 	struct wlan_serialization_command ser_cmd = {0,};
535 	enum wlan_serialization_cmd_status ser_cmd_status;
536 	struct scan_cancel_request *req;
537 	QDF_STATUS status = QDF_STATUS_SUCCESS;
538 
539 	if (!msg) {
540 		scm_err("msg received is NULL");
541 		QDF_ASSERT(0);
542 		return QDF_STATUS_E_NULL_VALUE;
543 	}
544 	if (!msg->bodyptr) {
545 		scm_err("Bodyptr is NULL");
546 		QDF_ASSERT(0);
547 		return QDF_STATUS_E_NULL_VALUE;
548 	}
549 
550 	req = msg->bodyptr;
551 	/*
552 	 * If requester wants to wait for target scan cancel event
553 	 * instead of internally generated cancel event, just check
554 	 * which queue this scan request belongs to and send scan
555 	 * cancel request to FW accordingly.
556 	 * Else generate internal scan cancel event and notify
557 	 * handlers and free scan request resources.
558 	 */
559 	if (req->wait_tgt_cancel &&
560 			(req->cancel_req.req_type == WLAN_SCAN_CANCEL_SINGLE)) {
561 		ser_cmd.cmd_type = WLAN_SER_CMD_SCAN;
562 		ser_cmd.cmd_id = req->cancel_req.scan_id;
563 		ser_cmd.cmd_cb = NULL;
564 		ser_cmd.umac_cmd = NULL;
565 		ser_cmd.source = WLAN_UMAC_COMP_SCAN;
566 		ser_cmd.is_high_priority = false;
567 		ser_cmd.vdev = req->vdev;
568 		if (wlan_serialization_is_cmd_present_in_active_queue(NULL, &ser_cmd))
569 			ser_cmd_status = WLAN_SER_CMD_IN_ACTIVE_LIST;
570 		else if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, &ser_cmd))
571 			ser_cmd_status = WLAN_SER_CMD_IN_PENDING_LIST;
572 		else
573 			ser_cmd_status = WLAN_SER_CMD_NOT_FOUND;
574 	} else {
575 		cmd.requestor = 0;
576 		cmd.cmd_type = WLAN_SER_CMD_SCAN;
577 		cmd.cmd_id = req->cancel_req.scan_id;
578 		cmd.vdev = req->vdev;
579 		cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE |
580 			WLAN_SERIALIZATION_PENDING_QUEUE;
581 		cmd.req_type = get_serialization_cancel_type(req->cancel_req.req_type);
582 
583 		ser_cmd_status = wlan_serialization_cancel_request(&cmd);
584 	}
585 
586 	scm_debug("status: %d, reqid: %d, scanid: %d, vdevid: %d, type: %d",
587 		ser_cmd_status, req->cancel_req.requester,
588 		req->cancel_req.scan_id, req->cancel_req.vdev_id,
589 		req->cancel_req.req_type);
590 
591 	switch (ser_cmd_status) {
592 	case WLAN_SER_CMD_IN_PENDING_LIST:
593 		/* do nothing */
594 		break;
595 	case WLAN_SER_CMD_IN_ACTIVE_LIST:
596 	case WLAN_SER_CMDS_IN_ALL_LISTS:
597 		/* send wmi scan cancel to fw */
598 		status = tgt_scan_cancel(req);
599 		break;
600 	case WLAN_SER_CMD_NOT_FOUND:
601 		/* do nothing */
602 		break;
603 	default:
604 		QDF_ASSERT(0);
605 		status = QDF_STATUS_E_INVAL;
606 		break;
607 	}
608 
609 	/* Release vdev reference and scan cancel request
610 	 * processing is complete
611 	 */
612 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
613 	/* Free cancel request memory */
614 	qdf_mem_free(req);
615 
616 	return status;
617 }
618 
619 #ifdef FEATURE_WLAN_SCAN_PNO
620 static QDF_STATUS
621 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev,
622 	struct scan_event *event)
623 {
624 	struct scan_vdev_obj *scan_vdev_obj;
625 	struct wlan_scan_obj *scan_psoc_obj;
626 	scan_event_handler pno_cb;
627 	void *cb_arg;
628 
629 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
630 	scan_psoc_obj = wlan_vdev_get_scan_obj(vdev);
631 	if (!scan_vdev_obj || !scan_psoc_obj) {
632 		scm_err("null scan_vdev_obj %pK scan_obj %pK",
633 			scan_vdev_obj, scan_psoc_obj);
634 		return QDF_STATUS_E_INVAL;
635 	}
636 
637 	switch (event->type) {
638 	case SCAN_EVENT_TYPE_NLO_COMPLETE:
639 		if (!scan_vdev_obj->pno_match_evt_received)
640 			return QDF_STATUS_SUCCESS;
641 		qdf_wake_lock_release(&scan_psoc_obj->pno_cfg.pno_wake_lock,
642 			WIFI_POWER_EVENT_WAKELOCK_PNO);
643 		qdf_wake_lock_timeout_acquire(
644 			&scan_psoc_obj->pno_cfg.pno_wake_lock,
645 			SCAN_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT);
646 		scan_vdev_obj->pno_match_evt_received = false;
647 		break;
648 	case SCAN_EVENT_TYPE_NLO_MATCH:
649 		scan_vdev_obj->pno_match_evt_received = true;
650 		qdf_wake_lock_timeout_acquire(
651 			&scan_psoc_obj->pno_cfg.pno_wake_lock,
652 			SCAN_PNO_MATCH_WAKE_LOCK_TIMEOUT);
653 		return QDF_STATUS_SUCCESS;
654 	default:
655 		return QDF_STATUS_E_INVAL;
656 	}
657 	qdf_spin_lock_bh(&scan_psoc_obj->lock);
658 	pno_cb = scan_psoc_obj->pno_cfg.pno_cb.func;
659 	cb_arg = scan_psoc_obj->pno_cfg.pno_cb.arg;
660 	qdf_spin_unlock_bh(&scan_psoc_obj->lock);
661 
662 	if (pno_cb)
663 		pno_cb(vdev, event, cb_arg);
664 
665 	return QDF_STATUS_SUCCESS;
666 }
667 #else
668 
669 static QDF_STATUS
670 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev,
671 	struct scan_event *event)
672 {
673 	return QDF_STATUS_SUCCESS;
674 }
675 #endif
676 
677 /**
678  * scm_scan_update_scan_event() - update scan event
679  * @scan: scan object
680  * @event: scan event
681  * @scan_start_req: scan_start_req used for triggering scan
682  *
683  * update scan params in scan event
684  *
685  * Return: QDF_STATUS
686  */
687 static QDF_STATUS
688 scm_scan_update_scan_event(struct wlan_scan_obj *scan,
689 		struct scan_event *event,
690 		struct scan_start_request *scan_start_req)
691 {
692 	if (!event)
693 		return QDF_STATUS_E_NULL_VALUE;
694 
695 	if (!scan || !scan_start_req) {
696 		event->scan_start_req = NULL;
697 		return QDF_STATUS_E_NULL_VALUE;
698 	}
699 	/* copy scan start request to pass back buffer */
700 	qdf_mem_copy(&scan->scan_start_request_buff, scan_start_req,
701 			sizeof(struct scan_start_request));
702 	/* reset all pointers */
703 	scan->scan_start_request_buff.scan_req.extraie.ptr = NULL;
704 	scan->scan_start_request_buff.scan_req.extraie.len = 0;
705 	scan->scan_start_request_buff.scan_req.htcap.ptr = NULL;
706 	scan->scan_start_request_buff.scan_req.htcap.len = 0;
707 	scan->scan_start_request_buff.scan_req.vhtcap.ptr = NULL;
708 	scan->scan_start_request_buff.scan_req.vhtcap.len = 0;
709 
710 	event->scan_start_req = &scan->scan_start_request_buff;
711 
712 	return QDF_STATUS_SUCCESS;
713 }
714 
715 QDF_STATUS
716 scm_scan_event_handler(struct scheduler_msg *msg)
717 {
718 	struct wlan_objmgr_vdev *vdev;
719 	struct scan_event *event;
720 	struct scan_event_info *event_info;
721 	struct wlan_serialization_command cmd = {0,};
722 	struct wlan_serialization_command *queued_cmd;
723 	struct scan_start_request *scan_start_req;
724 	struct wlan_scan_obj *scan;
725 
726 	if (!msg) {
727 		scm_err("NULL msg received ");
728 		QDF_ASSERT(0);
729 		return QDF_STATUS_E_NULL_VALUE;
730 	}
731 	if (!msg->bodyptr) {
732 		scm_err("NULL scan event received");
733 		QDF_ASSERT(0);
734 		return QDF_STATUS_E_NULL_VALUE;
735 	}
736 
737 	event_info = msg->bodyptr;
738 	vdev = event_info->vdev;
739 	event = &(event_info->event);
740 
741 	scm_debug("vdevid:%d, type:%d, reason:%d, freq:%d, reqstr:%d, scanid:%d",
742 		  event->vdev_id, event->type, event->reason, event->chan_freq,
743 		  event->requester, event->scan_id);
744 	/*
745 	 * NLO requests are never queued, so post NLO events
746 	 * without checking for their presence in active queue.
747 	 */
748 	switch (event->type) {
749 	case SCAN_EVENT_TYPE_NLO_COMPLETE:
750 	case SCAN_EVENT_TYPE_NLO_MATCH:
751 		scm_pno_event_handler(vdev, event);
752 		goto exit;
753 	default:
754 		break;
755 	}
756 
757 	cmd.cmd_type = WLAN_SER_CMD_SCAN;
758 	cmd.cmd_id = event->scan_id;
759 	cmd.cmd_cb = NULL;
760 	cmd.umac_cmd = NULL;
761 	cmd.source = WLAN_UMAC_COMP_SCAN;
762 	cmd.is_high_priority = false;
763 	cmd.vdev = vdev;
764 	if (!wlan_serialization_is_cmd_present_in_active_queue(NULL, &cmd)) {
765 		/*
766 		 * We received scan event for an already completed/cancelled
767 		 * scan request. Drop this event.
768 		 */
769 		scm_debug("Received scan event while request not in active queue");
770 		goto exit;
771 	}
772 
773 	/* Fill scan_start_request used to trigger this scan */
774 	queued_cmd = wlan_serialization_get_scan_cmd_using_scan_id(
775 			wlan_vdev_get_psoc(vdev), wlan_vdev_get_id(vdev),
776 			event->scan_id, true);
777 
778 	if (!queued_cmd) {
779 		scm_err("NULL queued_cmd");
780 		goto exit;
781 	}
782 	if (!queued_cmd->umac_cmd) {
783 		scm_err("NULL umac_cmd");
784 		goto exit;
785 	}
786 	scan_start_req = queued_cmd->umac_cmd;
787 
788 	if (scan_start_req->scan_req.scan_req_id != event->requester) {
789 		scm_err("req ID mismatch, scan_req_id:%d, event_req_id:%d",
790 				scan_start_req->scan_req.scan_req_id,
791 				event->requester);
792 		goto exit;
793 	}
794 
795 	scan = wlan_vdev_get_scan_obj(vdev);
796 	if (scan)
797 		scm_scan_update_scan_event(scan, event, scan_start_req);
798 
799 	switch (event->type) {
800 	case SCAN_EVENT_TYPE_COMPLETED:
801 		if (event->reason == SCAN_REASON_COMPLETED)
802 			scm_11d_decide_country_code(vdev);
803 		/* fall through to release the command */
804 	case SCAN_EVENT_TYPE_START_FAILED:
805 	case SCAN_EVENT_TYPE_DEQUEUED:
806 		scm_release_serialization_command(vdev, event->scan_id);
807 		break;
808 	default:
809 		break;
810 	}
811 
812 	/* Notify all interested parties */
813 	scm_scan_post_event(vdev, event);
814 
815 exit:
816 	/* free event info memory */
817 	qdf_mem_free(event_info);
818 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID);
819 
820 	return QDF_STATUS_SUCCESS;
821 }
822 
823 QDF_STATUS scm_scan_event_flush_callback(struct scheduler_msg *msg)
824 {
825 	struct wlan_objmgr_vdev *vdev;
826 	struct scan_event_info *event_info;
827 
828 	if (!msg || !msg->bodyptr) {
829 		scm_err("msg or msg->bodyptr is NULL");
830 		return QDF_STATUS_E_NULL_VALUE;
831 	}
832 
833 	event_info = msg->bodyptr;
834 	vdev = event_info->vdev;
835 
836 	/* free event info memory */
837 	qdf_mem_free(event_info);
838 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID);
839 
840 	return QDF_STATUS_SUCCESS;
841 }
842 
843 QDF_STATUS scm_bcn_probe_flush_callback(struct scheduler_msg *msg)
844 {
845 	struct scan_bcn_probe_event *bcn;
846 
847 	bcn = msg->bodyptr;
848 
849 	if (!bcn) {
850 		scm_err("bcn is NULL");
851 		return QDF_STATUS_E_NULL_VALUE;
852 	}
853 	if (bcn->psoc)
854 		wlan_objmgr_psoc_release_ref(bcn->psoc, WLAN_SCAN_ID);
855 	if (bcn->rx_data)
856 		qdf_mem_free(bcn->rx_data);
857 	if (bcn->buf)
858 		qdf_nbuf_free(bcn->buf);
859 	qdf_mem_free(bcn);
860 
861 	return QDF_STATUS_SUCCESS;
862 }
863 
864 QDF_STATUS scm_scan_start_flush_callback(struct scheduler_msg *msg)
865 {
866 	struct scan_start_request *req;
867 
868 	if (!msg || !msg->bodyptr) {
869 		scm_err("msg or msg->bodyptr is NULL");
870 		return QDF_STATUS_E_NULL_VALUE;
871 	}
872 
873 	req = msg->bodyptr;
874 	scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED);
875 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
876 	scm_scan_free_scan_request_mem(req);
877 
878 	return QDF_STATUS_SUCCESS;
879 }
880 
881 QDF_STATUS scm_scan_cancel_flush_callback(struct scheduler_msg *msg)
882 {
883 	struct scan_cancel_request *req;
884 
885 	if (!msg || !msg->bodyptr) {
886 		scm_err("msg or msg->bodyptr is NULL");
887 		return QDF_STATUS_E_NULL_VALUE;
888 	}
889 
890 	req = msg->bodyptr;
891 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
892 	/* Free cancel request memory */
893 	qdf_mem_free(req);
894 
895 	return QDF_STATUS_SUCCESS;
896 }
897