xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_manager.c (revision 302a1d9701784af5f4797b1a9fe07ae820b51907)
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 	switch (reason) {
325 	case WLAN_SER_CB_ACTIVATE_CMD:
326 		/* command moved to active list
327 		 * modify the params if required for concurency case.
328 		 */
329 		status = scm_activate_scan_request(req);
330 		break;
331 
332 	case WLAN_SER_CB_CANCEL_CMD:
333 		/* command removed from pending list.
334 		 * notify registered scan event handlers with
335 		 * status completed and reason cancelled.
336 		 */
337 		status = scm_post_internal_scan_complete_event(req,
338 				SCAN_REASON_CANCELLED);
339 		break;
340 
341 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
342 		/* active command timed out.
343 		 * prepare internal scan cancel request
344 		 */
345 		status = scm_cancel_scan_request(req);
346 		break;
347 
348 	case WLAN_SER_CB_RELEASE_MEM_CMD:
349 		/* command successfully completed.
350 		 * Release vdev reference and free scan_start_request memory
351 		 */
352 		cmd->umac_cmd = NULL;
353 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
354 		status = scm_scan_free_scan_request_mem(req);
355 		break;
356 
357 	default:
358 		/* Do nothing but logging */
359 		QDF_ASSERT(0);
360 		status = QDF_STATUS_E_INVAL;
361 		break;
362 	}
363 
364 	return status;
365 }
366 
367 QDF_STATUS
368 scm_scan_start_req(struct scheduler_msg *msg)
369 {
370 	struct wlan_serialization_command cmd = {0, };
371 	enum wlan_serialization_status ser_cmd_status;
372 	struct scan_start_request *req = NULL;
373 	struct wlan_scan_obj *scan_obj;
374 	struct scan_vdev_obj *scan_vdev_priv_obj;
375 	QDF_STATUS status = QDF_STATUS_SUCCESS;
376 
377 	if (!msg) {
378 		scm_err("msg received is NULL");
379 		QDF_ASSERT(0);
380 		return QDF_STATUS_E_NULL_VALUE;
381 	}
382 	if (!msg->bodyptr) {
383 		scm_err("bodyptr is NULL");
384 		QDF_ASSERT(0);
385 		return QDF_STATUS_E_NULL_VALUE;
386 	}
387 
388 	req = msg->bodyptr;
389 	scan_obj = wlan_vdev_get_scan_obj(req->vdev);
390 	if (!scan_obj) {
391 		scm_debug("Couldn't find scan object");
392 		status = QDF_STATUS_E_NULL_VALUE;
393 		goto err;
394 	}
395 
396 	cmd.cmd_type = WLAN_SER_CMD_SCAN;
397 	cmd.cmd_id = req->scan_req.scan_id;
398 	cmd.cmd_cb = (wlan_serialization_cmd_callback)
399 		scm_scan_serialize_callback;
400 	cmd.umac_cmd = req;
401 	cmd.source = WLAN_UMAC_COMP_SCAN;
402 	cmd.is_high_priority = false;
403 	cmd.cmd_timeout_duration = req->scan_req.max_scan_time +
404 		SCAN_TIMEOUT_GRACE_PERIOD;
405 	cmd.vdev = req->vdev;
406 
407 	if (scan_obj->disable_timeout)
408 		cmd.cmd_timeout_duration = 0;
409 
410 	scm_debug("req: 0x%pK, reqid: %d, scanid: %d, vdevid: %d",
411 		  req, req->scan_req.scan_req_id, req->scan_req.scan_id,
412 		  req->scan_req.vdev_id);
413 
414 	scan_vdev_priv_obj = wlan_get_vdev_scan_obj(req->vdev);
415 	if (!scan_vdev_priv_obj) {
416 		scm_debug("Couldn't find scan priv object");
417 		status = QDF_STATUS_E_NULL_VALUE;
418 		goto err;
419 	}
420 	if (scan_vdev_priv_obj->is_vdev_delete_in_progress) {
421 		scm_err("Can't allow scan on vdev_id:%d",
422 			wlan_vdev_get_id(req->vdev));
423 		status = QDF_STATUS_E_NULL_VALUE;
424 		goto err;
425 	}
426 	ser_cmd_status = wlan_serialization_request(&cmd);
427 	scm_debug("wlan_serialization_request status:%d", ser_cmd_status);
428 
429 	switch (ser_cmd_status) {
430 	case WLAN_SER_CMD_PENDING:
431 		/* command moved to pending list.Do nothing */
432 		break;
433 	case WLAN_SER_CMD_ACTIVE:
434 		/* command moved to active list. Do nothing */
435 		break;
436 	case WLAN_SER_CMD_DENIED_LIST_FULL:
437 	case WLAN_SER_CMD_DENIED_RULES_FAILED:
438 	case WLAN_SER_CMD_DENIED_UNSPECIFIED:
439 		/* notify registered scan event handlers
440 		 * about internal error
441 		 */
442 		scm_post_internal_scan_complete_event(req,
443 				SCAN_REASON_INTERNAL_FAILURE);
444 		goto err;
445 	default:
446 		QDF_ASSERT(0);
447 		status = QDF_STATUS_E_INVAL;
448 		goto err;
449 	}
450 
451 	return status;
452 err:
453 	/*
454 	 * cmd can't be serviced.
455 	 * release vdev reference and free scan_start_request memory
456 	 */
457 	if (req) {
458 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
459 		scm_scan_free_scan_request_mem(req);
460 	}
461 
462 	return status;
463 }
464 
465 static inline enum wlan_serialization_cancel_type
466 get_serialization_cancel_type(enum scan_cancel_req_type type)
467 {
468 	enum wlan_serialization_cancel_type serialization_type;
469 
470 	switch (type) {
471 	case WLAN_SCAN_CANCEL_SINGLE:
472 		serialization_type = WLAN_SER_CANCEL_SINGLE_SCAN;
473 		break;
474 	case WLAN_SCAN_CANCEL_VDEV_ALL:
475 		serialization_type = WLAN_SER_CANCEL_VDEV_SCANS;
476 		break;
477 	case WLAN_SCAN_CANCEL_PDEV_ALL:
478 		serialization_type = WLAN_SER_CANCEL_PDEV_SCANS;
479 		break;
480 	default:
481 		QDF_ASSERT(0);
482 		scm_warn("invalid scan_cancel_req_type: %d", type);
483 		serialization_type = WLAN_SER_CANCEL_PDEV_SCANS;
484 		break;
485 	}
486 
487 	return serialization_type;
488 }
489 
490 QDF_STATUS
491 scm_scan_cancel_req(struct scheduler_msg *msg)
492 {
493 	struct wlan_serialization_queued_cmd_info cmd = {0,};
494 	struct wlan_serialization_command ser_cmd = {0,};
495 	enum wlan_serialization_cmd_status ser_cmd_status;
496 	struct scan_cancel_request *req;
497 	QDF_STATUS status = QDF_STATUS_SUCCESS;
498 
499 	if (!msg) {
500 		scm_err("msg received is NULL");
501 		QDF_ASSERT(0);
502 		return QDF_STATUS_E_NULL_VALUE;
503 	}
504 	if (!msg->bodyptr) {
505 		scm_err("Bodyptr is NULL");
506 		QDF_ASSERT(0);
507 		return QDF_STATUS_E_NULL_VALUE;
508 	}
509 
510 	req = msg->bodyptr;
511 	/*
512 	 * If requester wants to wait for target scan cancel event
513 	 * instead of internally generated cancel event, just check
514 	 * which queue this scan request belongs to and send scan
515 	 * cancel request to FW accordingly.
516 	 * Else generate internal scan cancel event and notify
517 	 * handlers and free scan request resources.
518 	 */
519 	if (req->wait_tgt_cancel &&
520 			(req->cancel_req.req_type == WLAN_SCAN_CANCEL_SINGLE)) {
521 		ser_cmd.cmd_type = WLAN_SER_CMD_SCAN;
522 		ser_cmd.cmd_id = req->cancel_req.scan_id;
523 		ser_cmd.cmd_cb = NULL;
524 		ser_cmd.umac_cmd = NULL;
525 		ser_cmd.source = WLAN_UMAC_COMP_SCAN;
526 		ser_cmd.is_high_priority = false;
527 		ser_cmd.vdev = req->vdev;
528 		if (wlan_serialization_is_cmd_present_in_active_queue(NULL, &ser_cmd))
529 			ser_cmd_status = WLAN_SER_CMD_IN_ACTIVE_LIST;
530 		else if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, &ser_cmd))
531 			ser_cmd_status = WLAN_SER_CMD_IN_PENDING_LIST;
532 		else
533 			ser_cmd_status = WLAN_SER_CMD_NOT_FOUND;
534 	} else {
535 		cmd.requestor = 0;
536 		cmd.cmd_type = WLAN_SER_CMD_SCAN;
537 		cmd.cmd_id = req->cancel_req.scan_id;
538 		cmd.vdev = req->vdev;
539 		cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE |
540 			WLAN_SERIALIZATION_PENDING_QUEUE;
541 		cmd.req_type = get_serialization_cancel_type(req->cancel_req.req_type);
542 
543 		ser_cmd_status = wlan_serialization_cancel_request(&cmd);
544 	}
545 
546 	scm_debug("status: %d, reqid: %d, scanid: %d, vdevid: %d, type: %d",
547 		ser_cmd_status, req->cancel_req.requester,
548 		req->cancel_req.scan_id, req->cancel_req.vdev_id,
549 		req->cancel_req.req_type);
550 
551 	switch (ser_cmd_status) {
552 	case WLAN_SER_CMD_IN_PENDING_LIST:
553 		/* do nothing */
554 		break;
555 	case WLAN_SER_CMD_IN_ACTIVE_LIST:
556 	case WLAN_SER_CMDS_IN_ALL_LISTS:
557 		/* send wmi scan cancel to fw */
558 		status = tgt_scan_cancel(req);
559 		break;
560 	case WLAN_SER_CMD_NOT_FOUND:
561 		/* do nothing */
562 		break;
563 	default:
564 		QDF_ASSERT(0);
565 		status = QDF_STATUS_E_INVAL;
566 		break;
567 	}
568 
569 	/* Release vdev reference and scan cancel request
570 	 * processing is complete
571 	 */
572 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
573 	/* Free cancel request memory */
574 	qdf_mem_free(req);
575 
576 	return status;
577 }
578 
579 #ifdef FEATURE_WLAN_SCAN_PNO
580 static QDF_STATUS
581 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev,
582 	struct scan_event *event)
583 {
584 	struct scan_vdev_obj *scan_vdev_obj;
585 	struct wlan_scan_obj *scan_psoc_obj;
586 	scan_event_handler pno_cb;
587 	void *cb_arg;
588 
589 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
590 	scan_psoc_obj = wlan_vdev_get_scan_obj(vdev);
591 	if (!scan_vdev_obj || !scan_psoc_obj) {
592 		scm_err("null scan_vdev_obj %pK scan_obj %pK",
593 			scan_vdev_obj, scan_psoc_obj);
594 		return QDF_STATUS_E_INVAL;
595 	}
596 
597 	switch (event->type) {
598 	case SCAN_EVENT_TYPE_NLO_COMPLETE:
599 		if (!scan_vdev_obj->pno_match_evt_received)
600 			return QDF_STATUS_SUCCESS;
601 		qdf_wake_lock_release(&scan_psoc_obj->pno_cfg.pno_wake_lock,
602 			WIFI_POWER_EVENT_WAKELOCK_PNO);
603 		qdf_wake_lock_timeout_acquire(
604 			&scan_psoc_obj->pno_cfg.pno_wake_lock,
605 			SCAN_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT);
606 		scan_vdev_obj->pno_match_evt_received = false;
607 		break;
608 	case SCAN_EVENT_TYPE_NLO_MATCH:
609 		scan_vdev_obj->pno_match_evt_received = true;
610 		qdf_wake_lock_timeout_acquire(
611 			&scan_psoc_obj->pno_cfg.pno_wake_lock,
612 			SCAN_PNO_MATCH_WAKE_LOCK_TIMEOUT);
613 		return QDF_STATUS_SUCCESS;
614 	default:
615 		return QDF_STATUS_E_INVAL;
616 	}
617 	qdf_spin_lock_bh(&scan_psoc_obj->lock);
618 	pno_cb = scan_psoc_obj->pno_cfg.pno_cb.func;
619 	cb_arg = scan_psoc_obj->pno_cfg.pno_cb.arg;
620 	qdf_spin_unlock_bh(&scan_psoc_obj->lock);
621 
622 	if (pno_cb)
623 		pno_cb(vdev, event, cb_arg);
624 
625 	return QDF_STATUS_SUCCESS;
626 }
627 #else
628 
629 static QDF_STATUS
630 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev,
631 	struct scan_event *event)
632 {
633 	return QDF_STATUS_SUCCESS;
634 }
635 #endif
636 
637 /**
638  * scm_scan_update_scan_event() - update scan event
639  * @scan: scan object
640  * @event: scan event
641  * @scan_start_req: scan_start_req used for triggering scan
642  *
643  * update scan params in scan event
644  *
645  * Return: QDF_STATUS
646  */
647 static QDF_STATUS
648 scm_scan_update_scan_event(struct wlan_scan_obj *scan,
649 		struct scan_event *event,
650 		struct scan_start_request *scan_start_req)
651 {
652 	if (!event)
653 		return QDF_STATUS_E_NULL_VALUE;
654 
655 	if (!scan || !scan_start_req) {
656 		event->scan_start_req = NULL;
657 		return QDF_STATUS_E_NULL_VALUE;
658 	}
659 	/* copy scan start request to pass back buffer */
660 	qdf_mem_copy(&scan->scan_start_request_buff, scan_start_req,
661 			sizeof(struct scan_start_request));
662 	/* reset all pointers */
663 	scan->scan_start_request_buff.scan_req.extraie.ptr = NULL;
664 	scan->scan_start_request_buff.scan_req.extraie.len = 0;
665 	scan->scan_start_request_buff.scan_req.htcap.ptr = NULL;
666 	scan->scan_start_request_buff.scan_req.htcap.len = 0;
667 	scan->scan_start_request_buff.scan_req.vhtcap.ptr = NULL;
668 	scan->scan_start_request_buff.scan_req.vhtcap.len = 0;
669 
670 	event->scan_start_req = &scan->scan_start_request_buff;
671 
672 	return QDF_STATUS_SUCCESS;
673 }
674 
675 QDF_STATUS
676 scm_scan_event_handler(struct scheduler_msg *msg)
677 {
678 	struct wlan_objmgr_vdev *vdev;
679 	struct scan_event *event;
680 	struct scan_event_info *event_info;
681 	struct wlan_serialization_command cmd = {0,};
682 	struct wlan_serialization_command *queued_cmd;
683 	struct scan_start_request *scan_start_req;
684 	struct wlan_scan_obj *scan;
685 
686 	if (!msg) {
687 		scm_err("NULL msg received ");
688 		QDF_ASSERT(0);
689 		return QDF_STATUS_E_NULL_VALUE;
690 	}
691 	if (!msg->bodyptr) {
692 		scm_err("NULL scan event received");
693 		QDF_ASSERT(0);
694 		return QDF_STATUS_E_NULL_VALUE;
695 	}
696 
697 	event_info = msg->bodyptr;
698 	vdev = event_info->vdev;
699 	event = &(event_info->event);
700 
701 	scm_debug("vdevid:%d, type:%d, reason:%d, freq:%d, reqstr:%d, scanid:%d",
702 		  event->vdev_id, event->type, event->reason, event->chan_freq,
703 		  event->requester, event->scan_id);
704 	/*
705 	 * NLO requests are never queued, so post NLO events
706 	 * without checking for their presence in active queue.
707 	 */
708 	switch (event->type) {
709 	case SCAN_EVENT_TYPE_NLO_COMPLETE:
710 	case SCAN_EVENT_TYPE_NLO_MATCH:
711 		scm_pno_event_handler(vdev, event);
712 		goto exit;
713 	default:
714 		break;
715 	}
716 
717 	cmd.cmd_type = WLAN_SER_CMD_SCAN;
718 	cmd.cmd_id = event->scan_id;
719 	cmd.cmd_cb = NULL;
720 	cmd.umac_cmd = NULL;
721 	cmd.source = WLAN_UMAC_COMP_SCAN;
722 	cmd.is_high_priority = false;
723 	cmd.vdev = vdev;
724 	if (!wlan_serialization_is_cmd_present_in_active_queue(NULL, &cmd)) {
725 		/*
726 		 * We received scan event for an already completed/cancelled
727 		 * scan request. Drop this event.
728 		 */
729 		scm_debug("Received scan event while request not in active queue");
730 		goto exit;
731 	}
732 
733 	/* Fill scan_start_request used to trigger this scan */
734 	queued_cmd = wlan_serialization_get_scan_cmd_using_scan_id(
735 			wlan_vdev_get_psoc(vdev), wlan_vdev_get_id(vdev),
736 			event->scan_id, true);
737 
738 	if (!queued_cmd) {
739 		scm_err("NULL queued_cmd");
740 		goto exit;
741 	}
742 	if (!queued_cmd->umac_cmd) {
743 		scm_err("NULL umac_cmd");
744 		goto exit;
745 	}
746 	scan_start_req = queued_cmd->umac_cmd;
747 
748 	if (scan_start_req->scan_req.scan_req_id != event->requester) {
749 		scm_err("req ID mismatch, scan_req_id:%d, event_req_id:%d",
750 				scan_start_req->scan_req.scan_req_id,
751 				event->requester);
752 		goto exit;
753 	}
754 
755 	scan = wlan_vdev_get_scan_obj(vdev);
756 	if (scan)
757 		scm_scan_update_scan_event(scan, event, scan_start_req);
758 
759 	switch (event->type) {
760 	case SCAN_EVENT_TYPE_COMPLETED:
761 		if (event->reason == SCAN_REASON_COMPLETED)
762 			scm_11d_decide_country_code(vdev);
763 		/* fall through to release the command */
764 	case SCAN_EVENT_TYPE_START_FAILED:
765 	case SCAN_EVENT_TYPE_DEQUEUED:
766 		scm_release_serialization_command(vdev, event->scan_id);
767 		break;
768 	default:
769 		break;
770 	}
771 
772 	/* Notify all interested parties */
773 	scm_scan_post_event(vdev, event);
774 
775 exit:
776 	/* free event info memory */
777 	qdf_mem_free(event_info);
778 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID);
779 
780 	return QDF_STATUS_SUCCESS;
781 }
782 
783 QDF_STATUS scm_scan_event_flush_callback(struct scheduler_msg *msg)
784 {
785 	struct wlan_objmgr_vdev *vdev;
786 	struct scan_event_info *event_info;
787 
788 	if (!msg || !msg->bodyptr) {
789 		scm_err("msg or msg->bodyptr is NULL");
790 		return QDF_STATUS_E_NULL_VALUE;
791 	}
792 
793 	event_info = msg->bodyptr;
794 	vdev = event_info->vdev;
795 
796 	/* free event info memory */
797 	qdf_mem_free(event_info);
798 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID);
799 
800 	return QDF_STATUS_SUCCESS;
801 }
802 
803 QDF_STATUS scm_bcn_probe_flush_callback(struct scheduler_msg *msg)
804 {
805 	struct scan_bcn_probe_event *bcn;
806 
807 	bcn = msg->bodyptr;
808 
809 	if (!bcn) {
810 		scm_err("bcn is NULL");
811 		return QDF_STATUS_E_NULL_VALUE;
812 	}
813 	if (bcn->psoc)
814 		wlan_objmgr_psoc_release_ref(bcn->psoc, WLAN_SCAN_ID);
815 	if (bcn->rx_data)
816 		qdf_mem_free(bcn->rx_data);
817 	if (bcn->buf)
818 		qdf_nbuf_free(bcn->buf);
819 	qdf_mem_free(bcn);
820 
821 	return QDF_STATUS_SUCCESS;
822 }
823 
824 QDF_STATUS scm_scan_start_flush_callback(struct scheduler_msg *msg)
825 {
826 	struct scan_start_request *req;
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 	req = msg->bodyptr;
834 	scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED);
835 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
836 	scm_scan_free_scan_request_mem(req);
837 
838 	return QDF_STATUS_SUCCESS;
839 }
840 
841 QDF_STATUS scm_scan_cancel_flush_callback(struct scheduler_msg *msg)
842 {
843 	struct scan_cancel_request *req;
844 
845 	if (!msg || !msg->bodyptr) {
846 		scm_err("msg or msg->bodyptr is NULL");
847 		return QDF_STATUS_E_NULL_VALUE;
848 	}
849 
850 	req = msg->bodyptr;
851 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
852 	/* Free cancel request memory */
853 	qdf_mem_free(req);
854 
855 	return QDF_STATUS_SUCCESS;
856 }
857