xref: /wlan-driver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name /**
20*5113495bSYour Name  * DOC: wlan_serialization_internal.c
21*5113495bSYour Name  * This file defines the functions which are called
22*5113495bSYour Name  * from serialization public API's and are internal
23*5113495bSYour Name  * to serialization.
24*5113495bSYour Name  */
25*5113495bSYour Name 
26*5113495bSYour Name #include <wlan_objmgr_vdev_obj.h>
27*5113495bSYour Name #include <wlan_objmgr_pdev_obj.h>
28*5113495bSYour Name #include <wlan_objmgr_psoc_obj.h>
29*5113495bSYour Name #include <qdf_list.h>
30*5113495bSYour Name #include <qdf_status.h>
31*5113495bSYour Name #include <wlan_utility.h>
32*5113495bSYour Name #include "wlan_serialization_api.h"
33*5113495bSYour Name #include "wlan_serialization_main_i.h"
34*5113495bSYour Name #include "wlan_serialization_utils_i.h"
35*5113495bSYour Name #include "wlan_serialization_non_scan_i.h"
36*5113495bSYour Name #include "wlan_serialization_scan_i.h"
37*5113495bSYour Name #include "wlan_serialization_internal_i.h"
38*5113495bSYour Name 
wlan_serialization_is_cmd_present_queue(struct wlan_serialization_command * cmd,uint8_t is_active_queue)39*5113495bSYour Name bool wlan_serialization_is_cmd_present_queue(
40*5113495bSYour Name 			struct wlan_serialization_command *cmd,
41*5113495bSYour Name 			uint8_t is_active_queue)
42*5113495bSYour Name {
43*5113495bSYour Name 	qdf_list_t *queue;
44*5113495bSYour Name 	bool status = false;
45*5113495bSYour Name 	enum wlan_serialization_node node_type;
46*5113495bSYour Name 	struct wlan_ser_pdev_obj *ser_pdev_obj;
47*5113495bSYour Name 	struct wlan_ser_vdev_obj *ser_vdev_obj;
48*5113495bSYour Name 	enum wlan_serialization_cmd_type cmd_type;
49*5113495bSYour Name 
50*5113495bSYour Name 	if (!cmd) {
51*5113495bSYour Name 		ser_err("invalid cmd");
52*5113495bSYour Name 		goto error;
53*5113495bSYour Name 	}
54*5113495bSYour Name 
55*5113495bSYour Name 	cmd_type = cmd->cmd_type;
56*5113495bSYour Name 
57*5113495bSYour Name 	ser_pdev_obj = wlan_serialization_get_pdev_obj(
58*5113495bSYour Name 			wlan_serialization_get_pdev_from_cmd(cmd));
59*5113495bSYour Name 
60*5113495bSYour Name 	if (!ser_pdev_obj) {
61*5113495bSYour Name 		ser_err("invalid ser vdev obj");
62*5113495bSYour Name 		goto error;
63*5113495bSYour Name 	}
64*5113495bSYour Name 
65*5113495bSYour Name 	ser_vdev_obj = wlan_serialization_get_vdev_obj(
66*5113495bSYour Name 			wlan_serialization_get_vdev_from_cmd(cmd));
67*5113495bSYour Name 	if (!ser_vdev_obj) {
68*5113495bSYour Name 		ser_err("invalid ser pdev obj");
69*5113495bSYour Name 		goto error;
70*5113495bSYour Name 	}
71*5113495bSYour Name 
72*5113495bSYour Name 	if (cmd_type < WLAN_SER_CMD_NONSCAN) {
73*5113495bSYour Name 		queue = wlan_serialization_get_list_from_pdev_queue(
74*5113495bSYour Name 				ser_pdev_obj, cmd_type, is_active_queue);
75*5113495bSYour Name 		node_type = WLAN_SER_PDEV_NODE;
76*5113495bSYour Name 	} else {
77*5113495bSYour Name 		queue = wlan_serialization_get_list_from_vdev_queue(
78*5113495bSYour Name 				ser_vdev_obj, cmd_type, is_active_queue);
79*5113495bSYour Name 		node_type = WLAN_SER_VDEV_NODE;
80*5113495bSYour Name 	}
81*5113495bSYour Name 
82*5113495bSYour Name 	status = wlan_serialization_is_cmd_present_in_given_queue(queue, cmd,
83*5113495bSYour Name 								  node_type);
84*5113495bSYour Name 
85*5113495bSYour Name error:
86*5113495bSYour Name 	return status;
87*5113495bSYour Name }
88*5113495bSYour Name 
89*5113495bSYour Name enum wlan_serialization_status
wlan_serialization_enqueue_cmd(struct wlan_serialization_command * cmd,enum ser_queue_reason ser_reason)90*5113495bSYour Name wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd,
91*5113495bSYour Name 			       enum ser_queue_reason ser_reason)
92*5113495bSYour Name {
93*5113495bSYour Name 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
94*5113495bSYour Name 	struct wlan_serialization_command_list *cmd_list;
95*5113495bSYour Name 	qdf_list_node_t *nnode;
96*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
97*5113495bSYour Name 	struct wlan_ser_pdev_obj *ser_pdev_obj;
98*5113495bSYour Name 	struct wlan_serialization_pdev_queue *pdev_queue;
99*5113495bSYour Name 	struct wlan_ser_vdev_obj *ser_vdev_obj;
100*5113495bSYour Name 	struct wlan_serialization_vdev_queue *vdev_queue;
101*5113495bSYour Name 	bool active_queue;
102*5113495bSYour Name 	uint8_t vdev_id;
103*5113495bSYour Name 
104*5113495bSYour Name 	/* Enqueue process
105*5113495bSYour Name 	 * 1) peek through command structure and see what is the command type
106*5113495bSYour Name 	 * 2) two main types of commands to process
107*5113495bSYour Name 	 *    a) SCAN
108*5113495bSYour Name 	 *    b) NON-SCAN
109*5113495bSYour Name 	 * 3) for each command there are separate command queues per pdev
110*5113495bSYour Name 	 * 4) pull pdev from vdev structure and get the command queue associated
111*5113495bSYour Name 	 *    with that pdev and try to enqueue on those queue
112*5113495bSYour Name 	 * 5) Thumb rule:
113*5113495bSYour Name 	 *    a) There could be only 1 active non-scan command at a
114*5113495bSYour Name 	 *       time including all total non-scan commands of all pdevs.
115*5113495bSYour Name 	 *
116*5113495bSYour Name 	 *       example: pdev1 has 1 non-scan active command and
117*5113495bSYour Name 	 *       pdev2 got 1 non-scan command then that command should go to
118*5113495bSYour Name 	 *       pdev2's pending queue
119*5113495bSYour Name 	 *
120*5113495bSYour Name 	 *    b) There could be only N number of scan commands at a time
121*5113495bSYour Name 	 *       including all total scan commands of all pdevs
122*5113495bSYour Name 	 *
123*5113495bSYour Name 	 *       example: Let's say N=8,
124*5113495bSYour Name 	 *       pdev1's vdev1 has 5 scan command, pdev2's vdev1 has 3
125*5113495bSYour Name 	 *       scan commands, if we get scan request on vdev2 then it will go
126*5113495bSYour Name 	 *       to pending queue of vdev2 as we reached max allowed scan active
127*5113495bSYour Name 	 *       command.
128*5113495bSYour Name 	 */
129*5113495bSYour Name 
130*5113495bSYour Name 	if (!cmd) {
131*5113495bSYour Name 		ser_err("NULL command");
132*5113495bSYour Name 		goto error;
133*5113495bSYour Name 	}
134*5113495bSYour Name 
135*5113495bSYour Name 	if (!cmd->cmd_cb) {
136*5113495bSYour Name 		ser_err("no cmd_cb for cmd type:%d, id: %d",
137*5113495bSYour Name 			cmd->cmd_type,
138*5113495bSYour Name 			cmd->cmd_id);
139*5113495bSYour Name 		goto error;
140*5113495bSYour Name 	}
141*5113495bSYour Name 
142*5113495bSYour Name 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
143*5113495bSYour Name 	if (!pdev) {
144*5113495bSYour Name 		ser_err("pdev is invalid");
145*5113495bSYour Name 		goto error;
146*5113495bSYour Name 	}
147*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(cmd->vdev);
148*5113495bSYour Name 
149*5113495bSYour Name 	ser_pdev_obj =
150*5113495bSYour Name 		wlan_objmgr_pdev_get_comp_private_obj(
151*5113495bSYour Name 				pdev,
152*5113495bSYour Name 				WLAN_UMAC_COMP_SERIALIZATION);
153*5113495bSYour Name 	if (!ser_pdev_obj) {
154*5113495bSYour Name 		ser_err("Invalid ser_pdev_obj");
155*5113495bSYour Name 		goto error;
156*5113495bSYour Name 	}
157*5113495bSYour Name 
158*5113495bSYour Name 	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
159*5113495bSYour Name 							   cmd->cmd_type);
160*5113495bSYour Name 	if (!pdev_queue) {
161*5113495bSYour Name 		ser_err("pdev_queue is invalid");
162*5113495bSYour Name 		goto error;
163*5113495bSYour Name 	}
164*5113495bSYour Name 
165*5113495bSYour Name 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
166*5113495bSYour Name 
167*5113495bSYour Name 	/* Before queuing any non scan command,
168*5113495bSYour Name 	 * as part of wlan_serialization_request,
169*5113495bSYour Name 	 * we check if the vdev queues are disabled.
170*5113495bSYour Name 	 *
171*5113495bSYour Name 	 * The serialization command structure has an
172*5113495bSYour Name 	 * attribute, where after a given command is queued,
173*5113495bSYour Name 	 * we can block the vdev queues.
174*5113495bSYour Name 	 *
175*5113495bSYour Name 	 * For example, after VDEV_DOWN command is queued as
176*5113495bSYour Name 	 * part of a vdev deletion, no other commands should be queued
177*5113495bSYour Name 	 * until the deletion is complete, so with VDEV_DOWN(in case of
178*5113495bSYour Name 	 * vdev deletion) with pass the attribute to disable vdev queues
179*5113495bSYour Name 	 */
180*5113495bSYour Name 	if (cmd->cmd_type > WLAN_SER_CMD_SCAN &&
181*5113495bSYour Name 	    ser_reason == SER_REQUEST) {
182*5113495bSYour Name 		ser_vdev_obj =
183*5113495bSYour Name 			wlan_serialization_get_vdev_obj(
184*5113495bSYour Name 				wlan_serialization_get_vdev_from_cmd(cmd));
185*5113495bSYour Name 
186*5113495bSYour Name 		if (!ser_vdev_obj) {
187*5113495bSYour Name 			wlan_serialization_release_lock(
188*5113495bSYour Name 				&pdev_queue->pdev_queue_lock);
189*5113495bSYour Name 			goto error;
190*5113495bSYour Name 		}
191*5113495bSYour Name 
192*5113495bSYour Name 		vdev_queue =
193*5113495bSYour Name 			wlan_serialization_get_vdev_queue_obj(
194*5113495bSYour Name 				ser_vdev_obj,
195*5113495bSYour Name 				cmd->cmd_type);
196*5113495bSYour Name 
197*5113495bSYour Name 		if (!vdev_queue) {
198*5113495bSYour Name 			wlan_serialization_release_lock(
199*5113495bSYour Name 				&pdev_queue->pdev_queue_lock);
200*5113495bSYour Name 			goto error;
201*5113495bSYour Name 		}
202*5113495bSYour Name 
203*5113495bSYour Name 		if (vdev_queue->queue_disable) {
204*5113495bSYour Name 			wlan_serialization_release_lock(
205*5113495bSYour Name 				&pdev_queue->pdev_queue_lock);
206*5113495bSYour Name 			ser_err_rl("VDEV %d queue is disabled, reject cmd id %d type %d",
207*5113495bSYour Name 				   vdev_id, cmd->cmd_id, cmd->cmd_type);
208*5113495bSYour Name 			status = WLAN_SER_CMD_QUEUE_DISABLED;
209*5113495bSYour Name 			goto error;
210*5113495bSYour Name 		}
211*5113495bSYour Name 	}
212*5113495bSYour Name 
213*5113495bSYour Name 	active_queue = wlan_serialization_is_active_cmd_allowed(cmd);
214*5113495bSYour Name 
215*5113495bSYour Name 	if (wlan_serialization_is_cmd_present_queue(cmd, active_queue)) {
216*5113495bSYour Name 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
217*5113495bSYour Name 		ser_err("duplicate command, reject cmd id %d type %d vdev %d",
218*5113495bSYour Name 			cmd->cmd_id, cmd->cmd_type, vdev_id);
219*5113495bSYour Name 		goto error;
220*5113495bSYour Name 	}
221*5113495bSYour Name 
222*5113495bSYour Name 	if (wlan_serialization_remove_front(
223*5113495bSYour Name 				&pdev_queue->cmd_pool_list,
224*5113495bSYour Name 				&nnode) != QDF_STATUS_SUCCESS) {
225*5113495bSYour Name 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
226*5113495bSYour Name 		ser_err("Failed to get cmd buffer from global pool cmd id %d type %d vdev %d",
227*5113495bSYour Name 			cmd->cmd_id, cmd->cmd_type, vdev_id);
228*5113495bSYour Name 		status = WLAN_SER_CMD_DENIED_LIST_FULL;
229*5113495bSYour Name 		goto error;
230*5113495bSYour Name 	}
231*5113495bSYour Name 
232*5113495bSYour Name 	ser_debug("Type %d id %d vdev %d high_priority %d blocking %d timeout %d allowed %d",
233*5113495bSYour Name 		  cmd->cmd_type, cmd->cmd_id, vdev_id, cmd->is_high_priority,
234*5113495bSYour Name 		  cmd->is_blocking, cmd->cmd_timeout_duration, active_queue);
235*5113495bSYour Name 
236*5113495bSYour Name 	cmd_list =
237*5113495bSYour Name 		qdf_container_of(nnode,
238*5113495bSYour Name 				 struct wlan_serialization_command_list,
239*5113495bSYour Name 				 pdev_node);
240*5113495bSYour Name 
241*5113495bSYour Name 	qdf_mem_copy(&cmd_list->cmd, cmd,
242*5113495bSYour Name 		     sizeof(struct wlan_serialization_command));
243*5113495bSYour Name 
244*5113495bSYour Name 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) {
245*5113495bSYour Name 		status = wlan_ser_add_scan_cmd(ser_pdev_obj,
246*5113495bSYour Name 					       cmd_list,
247*5113495bSYour Name 					       active_queue);
248*5113495bSYour Name 	} else {
249*5113495bSYour Name 		status = wlan_ser_add_non_scan_cmd(ser_pdev_obj,
250*5113495bSYour Name 						   cmd_list,
251*5113495bSYour Name 						   active_queue);
252*5113495bSYour Name 	}
253*5113495bSYour Name 
254*5113495bSYour Name 	if (status != WLAN_SER_CMD_PENDING && status != WLAN_SER_CMD_ACTIVE) {
255*5113495bSYour Name 		qdf_mem_zero(&cmd_list->cmd,
256*5113495bSYour Name 			     sizeof(struct wlan_serialization_command));
257*5113495bSYour Name 		cmd_list->cmd_in_use = 0;
258*5113495bSYour Name 		wlan_serialization_insert_back(
259*5113495bSYour Name 			&pdev_queue->cmd_pool_list,
260*5113495bSYour Name 			&cmd_list->pdev_node);
261*5113495bSYour Name 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
262*5113495bSYour Name 		ser_err("Failed to add cmd id %d type %d to active/pending queue",
263*5113495bSYour Name 			cmd->cmd_id, cmd->cmd_type);
264*5113495bSYour Name 		goto error;
265*5113495bSYour Name 	}
266*5113495bSYour Name 
267*5113495bSYour Name 	if (WLAN_SER_CMD_ACTIVE == status) {
268*5113495bSYour Name 		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
269*5113495bSYour Name 				   &cmd_list->cmd_in_use);
270*5113495bSYour Name 	}
271*5113495bSYour Name 
272*5113495bSYour Name 	wlan_ser_update_cmd_history(pdev_queue, &cmd_list->cmd,
273*5113495bSYour Name 				    ser_reason, true, active_queue);
274*5113495bSYour Name 
275*5113495bSYour Name 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
276*5113495bSYour Name 
277*5113495bSYour Name 	if (WLAN_SER_CMD_ACTIVE == status)
278*5113495bSYour Name 		wlan_serialization_activate_cmd(cmd_list,
279*5113495bSYour Name 						ser_pdev_obj, ser_reason);
280*5113495bSYour Name 
281*5113495bSYour Name error:
282*5113495bSYour Name 
283*5113495bSYour Name 	return status;
284*5113495bSYour Name }
285*5113495bSYour Name 
wlan_serialization_activate_cmd(struct wlan_serialization_command_list * cmd_list,struct wlan_ser_pdev_obj * ser_pdev_obj,enum ser_queue_reason ser_reason)286*5113495bSYour Name QDF_STATUS wlan_serialization_activate_cmd(
287*5113495bSYour Name 			struct wlan_serialization_command_list *cmd_list,
288*5113495bSYour Name 			struct wlan_ser_pdev_obj *ser_pdev_obj,
289*5113495bSYour Name 			enum ser_queue_reason ser_reason)
290*5113495bSYour Name {
291*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
292*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = NULL;
293*5113495bSYour Name 	struct wlan_serialization_pdev_queue *pdev_queue;
294*5113495bSYour Name 	uint8_t vdev_id;
295*5113495bSYour Name 
296*5113495bSYour Name 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
297*5113495bSYour Name 			ser_pdev_obj, cmd_list->cmd.cmd_type);
298*5113495bSYour Name 
299*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(cmd_list->cmd.vdev);
300*5113495bSYour Name 	if (!psoc) {
301*5113495bSYour Name 		ser_err("invalid psoc");
302*5113495bSYour Name 		goto error;
303*5113495bSYour Name 	}
304*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(cmd_list->cmd.vdev);
305*5113495bSYour Name 
306*5113495bSYour Name 	/*
307*5113495bSYour Name 	 * command is already pushed to active queue above
308*5113495bSYour Name 	 * now start the timer and notify requestor
309*5113495bSYour Name 	 */
310*5113495bSYour Name 
311*5113495bSYour Name 	status = wlan_serialization_find_and_start_timer(psoc, &cmd_list->cmd,
312*5113495bSYour Name 							 ser_reason);
313*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
314*5113495bSYour Name 		ser_err("Failed to start timer cmd type %d id %d vdev %d",
315*5113495bSYour Name 			cmd_list->cmd.cmd_type,
316*5113495bSYour Name 			cmd_list->cmd.cmd_id, vdev_id);
317*5113495bSYour Name 		goto timer_failed;
318*5113495bSYour Name 	}
319*5113495bSYour Name 
320*5113495bSYour Name 	/*
321*5113495bSYour Name 	 * Remember that serialization module may send
322*5113495bSYour Name 	 * this callback in same context through which it
323*5113495bSYour Name 	 * received the serialization request. Due to which
324*5113495bSYour Name 	 * it is caller's responsibility to ensure acquiring
325*5113495bSYour Name 	 * and releasing its own lock appropriately.
326*5113495bSYour Name 	 */
327*5113495bSYour Name 
328*5113495bSYour Name 	ser_debug("Activate type %d id %d vdev %d", cmd_list->cmd.cmd_type,
329*5113495bSYour Name 		  cmd_list->cmd.cmd_id, vdev_id);
330*5113495bSYour Name 
331*5113495bSYour Name 	cmd_list->cmd.activation_reason = ser_reason;
332*5113495bSYour Name 
333*5113495bSYour Name 	status = cmd_list->cmd.cmd_cb(&cmd_list->cmd,
334*5113495bSYour Name 				WLAN_SER_CB_ACTIVATE_CMD);
335*5113495bSYour Name timer_failed:
336*5113495bSYour Name 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
337*5113495bSYour Name 
338*5113495bSYour Name 	qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION,
339*5113495bSYour Name 			     &cmd_list->cmd_in_use);
340*5113495bSYour Name 	qdf_atomic_set_bit(CMD_IS_ACTIVE,
341*5113495bSYour Name 			   &cmd_list->cmd_in_use);
342*5113495bSYour Name 
343*5113495bSYour Name 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
344*5113495bSYour Name 
345*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
346*5113495bSYour Name 		wlan_serialization_dequeue_cmd(&cmd_list->cmd,
347*5113495bSYour Name 					       SER_ACTIVATION_FAILED,
348*5113495bSYour Name 					       true);
349*5113495bSYour Name 		return status;
350*5113495bSYour Name 	}
351*5113495bSYour Name 
352*5113495bSYour Name 	/*
353*5113495bSYour Name 	 * Cmd was marked for activation and delete or cancel
354*5113495bSYour Name 	 * is received before activation completed, then the command
355*5113495bSYour Name 	 * should be immediately removed after activation
356*5113495bSYour Name 	 */
357*5113495bSYour Name 	if (qdf_atomic_test_bit(CMD_ACTIVE_MARKED_FOR_REMOVAL,
358*5113495bSYour Name 				&cmd_list->cmd_in_use)) {
359*5113495bSYour Name 		wlan_serialization_dequeue_cmd(&cmd_list->cmd,
360*5113495bSYour Name 					       SER_REMOVE,
361*5113495bSYour Name 					       true);
362*5113495bSYour Name 		return status;
363*5113495bSYour Name 	}
364*5113495bSYour Name 
365*5113495bSYour Name 	if (qdf_atomic_test_bit(CMD_ACTIVE_MARKED_FOR_CANCEL,
366*5113495bSYour Name 				&cmd_list->cmd_in_use))
367*5113495bSYour Name 		wlan_serialization_cmd_cancel_handler(
368*5113495bSYour Name 				ser_pdev_obj, &cmd_list->cmd,
369*5113495bSYour Name 				NULL, NULL, cmd_list->cmd.cmd_type,
370*5113495bSYour Name 				WLAN_SERIALIZATION_ACTIVE_QUEUE,
371*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONE);
372*5113495bSYour Name error:
373*5113495bSYour Name 	return status;
374*5113495bSYour Name }
375*5113495bSYour Name 
376*5113495bSYour Name bool
wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command * cmd)377*5113495bSYour Name wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd)
378*5113495bSYour Name {
379*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
380*5113495bSYour Name 	bool active_cmd_allowed = 0;
381*5113495bSYour Name 
382*5113495bSYour Name 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
383*5113495bSYour Name 	if (!pdev) {
384*5113495bSYour Name 		ser_err("NULL pdev");
385*5113495bSYour Name 		goto error;
386*5113495bSYour Name 	}
387*5113495bSYour Name 
388*5113495bSYour Name 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
389*5113495bSYour Name 		active_cmd_allowed =
390*5113495bSYour Name 		(wlan_serialization_is_active_scan_cmd_allowed(cmd) &&
391*5113495bSYour Name 			wlan_serialization_is_scan_pending_queue_empty(cmd));
392*5113495bSYour Name 	else
393*5113495bSYour Name 		active_cmd_allowed =
394*5113495bSYour Name 		(wlan_serialization_is_active_non_scan_cmd_allowed(cmd) &&
395*5113495bSYour Name 		 wlan_serialization_is_non_scan_pending_queue_empty(cmd));
396*5113495bSYour Name 
397*5113495bSYour Name error:
398*5113495bSYour Name 	return active_cmd_allowed;
399*5113495bSYour Name }
400*5113495bSYour Name 
401*5113495bSYour Name enum wlan_serialization_status
wlan_serialization_move_pending_to_active(enum wlan_serialization_cmd_type cmd_type,struct wlan_ser_pdev_obj * ser_pdev_obj,struct wlan_objmgr_vdev * vdev,bool blocking_cmd_removed)402*5113495bSYour Name wlan_serialization_move_pending_to_active(
403*5113495bSYour Name 		enum wlan_serialization_cmd_type cmd_type,
404*5113495bSYour Name 		struct wlan_ser_pdev_obj *ser_pdev_obj,
405*5113495bSYour Name 		struct wlan_objmgr_vdev *vdev,
406*5113495bSYour Name 		bool blocking_cmd_removed)
407*5113495bSYour Name {
408*5113495bSYour Name 	enum wlan_serialization_status status;
409*5113495bSYour Name 
410*5113495bSYour Name 	if (cmd_type < WLAN_SER_CMD_NONSCAN) {
411*5113495bSYour Name 		status =
412*5113495bSYour Name 		wlan_ser_move_scan_pending_to_active(
413*5113495bSYour Name 				ser_pdev_obj);
414*5113495bSYour Name 	} else {
415*5113495bSYour Name 		status =
416*5113495bSYour Name 		wlan_ser_move_non_scan_pending_to_active(
417*5113495bSYour Name 				ser_pdev_obj,
418*5113495bSYour Name 				vdev,
419*5113495bSYour Name 				blocking_cmd_removed);
420*5113495bSYour Name 	}
421*5113495bSYour Name 
422*5113495bSYour Name 	return status;
423*5113495bSYour Name }
424*5113495bSYour Name 
425*5113495bSYour Name enum wlan_serialization_cmd_status
wlan_serialization_dequeue_cmd(struct wlan_serialization_command * cmd,enum ser_queue_reason ser_reason,uint8_t active_cmd)426*5113495bSYour Name wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd,
427*5113495bSYour Name 			       enum ser_queue_reason ser_reason,
428*5113495bSYour Name 			       uint8_t active_cmd)
429*5113495bSYour Name {
430*5113495bSYour Name 	enum wlan_serialization_cmd_status status =
431*5113495bSYour Name 		WLAN_SER_CMD_NOT_FOUND;
432*5113495bSYour Name 	enum wlan_serialization_status ser_status =
433*5113495bSYour Name 		WLAN_SER_CMD_DENIED_UNSPECIFIED;
434*5113495bSYour Name 
435*5113495bSYour Name 	QDF_STATUS qdf_status;
436*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
437*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
438*5113495bSYour Name 	struct wlan_ser_pdev_obj *ser_pdev_obj;
439*5113495bSYour Name 	struct wlan_serialization_command cmd_bkup;
440*5113495bSYour Name 	struct wlan_serialization_command_list *cmd_list;
441*5113495bSYour Name 	struct wlan_serialization_pdev_queue *pdev_queue;
442*5113495bSYour Name 	bool blocking_cmd_removed = 0;
443*5113495bSYour Name 
444*5113495bSYour Name 	if (!cmd) {
445*5113495bSYour Name 		ser_err("NULL command");
446*5113495bSYour Name 		goto error;
447*5113495bSYour Name 	}
448*5113495bSYour Name 
449*5113495bSYour Name 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
450*5113495bSYour Name 	if (!pdev) {
451*5113495bSYour Name 		ser_err("invalid pdev");
452*5113495bSYour Name 		goto error;
453*5113495bSYour Name 	}
454*5113495bSYour Name 
455*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
456*5113495bSYour Name 	if (!psoc) {
457*5113495bSYour Name 		ser_err("invalid psoc");
458*5113495bSYour Name 		goto error;
459*5113495bSYour Name 	}
460*5113495bSYour Name 
461*5113495bSYour Name 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
462*5113495bSYour Name 	if (!ser_pdev_obj) {
463*5113495bSYour Name 		ser_err("ser_pdev_obj is empty");
464*5113495bSYour Name 		goto error;
465*5113495bSYour Name 	}
466*5113495bSYour Name 
467*5113495bSYour Name 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
468*5113495bSYour Name 			ser_pdev_obj, cmd->cmd_type);
469*5113495bSYour Name 
470*5113495bSYour Name 	ser_debug("Type %d id %d vdev %d blocking %d reason %d active %d",
471*5113495bSYour Name 		  cmd->cmd_type, cmd->cmd_id, wlan_vdev_get_id(cmd->vdev),
472*5113495bSYour Name 		  cmd->is_blocking, ser_reason, active_cmd);
473*5113495bSYour Name 
474*5113495bSYour Name 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
475*5113495bSYour Name 
476*5113495bSYour Name 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
477*5113495bSYour Name 		qdf_status = wlan_ser_remove_scan_cmd(
478*5113495bSYour Name 				ser_pdev_obj, &cmd_list, cmd, active_cmd);
479*5113495bSYour Name 	else {
480*5113495bSYour Name 		qdf_status = wlan_ser_remove_non_scan_cmd(
481*5113495bSYour Name 				ser_pdev_obj, &cmd_list, cmd, active_cmd);
482*5113495bSYour Name 	}
483*5113495bSYour Name 
484*5113495bSYour Name 	if (qdf_status == QDF_STATUS_E_PENDING) {
485*5113495bSYour Name 		status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION;
486*5113495bSYour Name 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
487*5113495bSYour Name 		goto error;
488*5113495bSYour Name 	}
489*5113495bSYour Name 
490*5113495bSYour Name 	if (qdf_status != QDF_STATUS_SUCCESS) {
491*5113495bSYour Name 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
492*5113495bSYour Name 		status = WLAN_SER_CMD_NOT_FOUND;
493*5113495bSYour Name 		goto error;
494*5113495bSYour Name 	}
495*5113495bSYour Name 
496*5113495bSYour Name 	if (active_cmd) {
497*5113495bSYour Name 		if (cmd_list->cmd.cmd_type >= WLAN_SER_CMD_NONSCAN)
498*5113495bSYour Name 			blocking_cmd_removed = cmd_list->cmd.is_blocking;
499*5113495bSYour Name 	}
500*5113495bSYour Name 
501*5113495bSYour Name 	if (active_cmd)
502*5113495bSYour Name 		wlan_serialization_find_and_stop_timer(
503*5113495bSYour Name 				psoc, &cmd_list->cmd,
504*5113495bSYour Name 				ser_reason);
505*5113495bSYour Name 
506*5113495bSYour Name 	qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
507*5113495bSYour Name 		     sizeof(struct wlan_serialization_command));
508*5113495bSYour Name 	qdf_mem_zero(&cmd_list->cmd,
509*5113495bSYour Name 		     sizeof(struct wlan_serialization_command));
510*5113495bSYour Name 	cmd_list->cmd_in_use = 0;
511*5113495bSYour Name 	qdf_status = wlan_serialization_insert_back(
512*5113495bSYour Name 			&pdev_queue->cmd_pool_list,
513*5113495bSYour Name 			&cmd_list->pdev_node);
514*5113495bSYour Name 
515*5113495bSYour Name 	wlan_ser_update_cmd_history(pdev_queue, &cmd_bkup, ser_reason,
516*5113495bSYour Name 				    false, active_cmd);
517*5113495bSYour Name 
518*5113495bSYour Name 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
519*5113495bSYour Name 
520*5113495bSYour Name 	if (active_cmd) {
521*5113495bSYour Name 		ser_status = wlan_serialization_move_pending_to_active(
522*5113495bSYour Name 			cmd_bkup.cmd_type, ser_pdev_obj,
523*5113495bSYour Name 			cmd_bkup.vdev,
524*5113495bSYour Name 			blocking_cmd_removed);
525*5113495bSYour Name 	}
526*5113495bSYour Name 
527*5113495bSYour Name 	/* Call cmd cb for remove request*/
528*5113495bSYour Name 	if (cmd_bkup.cmd_cb) {
529*5113495bSYour Name 		/* caller should release the memory */
530*5113495bSYour Name 		ser_debug("Release memory for type %d id %d vdev %d",
531*5113495bSYour Name 			  cmd_bkup.cmd_type, cmd_bkup.cmd_id,
532*5113495bSYour Name 			  wlan_vdev_get_id(cmd_bkup.vdev));
533*5113495bSYour Name 		cmd_bkup.cmd_cb(&cmd_bkup, WLAN_SER_CB_RELEASE_MEM_CMD);
534*5113495bSYour Name 	}
535*5113495bSYour Name 
536*5113495bSYour Name 	if (active_cmd)
537*5113495bSYour Name 		status = WLAN_SER_CMD_IN_ACTIVE_LIST;
538*5113495bSYour Name 	else
539*5113495bSYour Name 		status = WLAN_SER_CMD_IN_PENDING_LIST;
540*5113495bSYour Name 
541*5113495bSYour Name error:
542*5113495bSYour Name 	return status;
543*5113495bSYour Name }
544*5113495bSYour Name 
wlan_serialization_generic_timer_cb(void * arg)545*5113495bSYour Name static void wlan_serialization_generic_timer_cb(void *arg)
546*5113495bSYour Name {
547*5113495bSYour Name 	struct wlan_serialization_command *timeout_cmd = arg;
548*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
549*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
550*5113495bSYour Name 
551*5113495bSYour Name 	if (!timeout_cmd) {
552*5113495bSYour Name 		ser_err("cmd_info not found");
553*5113495bSYour Name 		return;
554*5113495bSYour Name 	}
555*5113495bSYour Name 
556*5113495bSYour Name 	vdev = timeout_cmd->vdev;
557*5113495bSYour Name 	if (!vdev) {
558*5113495bSYour Name 		ser_err("Invalid vdev");
559*5113495bSYour Name 		qdf_mem_free(timeout_cmd);
560*5113495bSYour Name 		return;
561*5113495bSYour Name 	}
562*5113495bSYour Name 
563*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
564*5113495bSYour Name 	if (!psoc) {
565*5113495bSYour Name 		ser_err("Psoc is NULL");
566*5113495bSYour Name 		goto free;
567*5113495bSYour Name 	}
568*5113495bSYour Name 	ser_err("Active cmd timeout for cmd_type[%d] vdev[%d] cmd_id[%d]",
569*5113495bSYour Name 		timeout_cmd->cmd_type, wlan_vdev_get_id(vdev),
570*5113495bSYour Name 		timeout_cmd->cmd_id);
571*5113495bSYour Name 
572*5113495bSYour Name 	/*
573*5113495bSYour Name 	 * Validate if active cmnd is still present, as actual command
574*5113495bSYour Name 	 * completion can removed it in parallel.
575*5113495bSYour Name 	 */
576*5113495bSYour Name 	if (!wlan_serialization_is_cmd_present_in_active_queue(psoc,
577*5113495bSYour Name 	    timeout_cmd)) {
578*5113495bSYour Name 		ser_err("cmd_type %d vdev %d not in active queue",
579*5113495bSYour Name 			timeout_cmd->cmd_type, wlan_vdev_get_id(vdev));
580*5113495bSYour Name 		goto free;
581*5113495bSYour Name 	}
582*5113495bSYour Name 
583*5113495bSYour Name 	if (timeout_cmd->cmd_cb)
584*5113495bSYour Name 		timeout_cmd->cmd_cb(timeout_cmd,
585*5113495bSYour Name 				     WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
586*5113495bSYour Name 	/*
587*5113495bSYour Name 	 * dequeue cmd API will cleanup and destroy the timer. If it fails to
588*5113495bSYour Name 	 * dequeue command then we have to destroy the timer.
589*5113495bSYour Name 	 */
590*5113495bSYour Name 	wlan_serialization_dequeue_cmd(timeout_cmd, SER_TIMEOUT, true);
591*5113495bSYour Name 
592*5113495bSYour Name free:
593*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(timeout_cmd->vdev, WLAN_SERIALIZATION_ID);
594*5113495bSYour Name 	qdf_mem_free(timeout_cmd);
595*5113495bSYour Name }
596*5113495bSYour Name 
wlan_serialization_mc_flush(struct scheduler_msg * msg)597*5113495bSYour Name static QDF_STATUS wlan_serialization_mc_flush(struct scheduler_msg *msg)
598*5113495bSYour Name {
599*5113495bSYour Name 	struct wlan_serialization_command *timeout_cmd =
600*5113495bSYour Name 		scheduler_qdf_mc_timer_deinit_return_data_ptr(msg->bodyptr);
601*5113495bSYour Name 
602*5113495bSYour Name 	if (!timeout_cmd) {
603*5113495bSYour Name 		ser_err("Error failed to release reference for vdev objmgr");
604*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
605*5113495bSYour Name 	}
606*5113495bSYour Name 
607*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(timeout_cmd->vdev, WLAN_SERIALIZATION_ID);
608*5113495bSYour Name 	qdf_mem_free(timeout_cmd);
609*5113495bSYour Name 
610*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
611*5113495bSYour Name }
612*5113495bSYour Name 
613*5113495bSYour Name static void
wlan_serialization_timer_cb_mc_ctx(struct wlan_serialization_command * cmd)614*5113495bSYour Name wlan_serialization_timer_cb_mc_ctx(struct wlan_serialization_command *cmd)
615*5113495bSYour Name {
616*5113495bSYour Name 	struct scheduler_msg msg = {0};
617*5113495bSYour Name 	struct wlan_serialization_command *timeout_cmd;
618*5113495bSYour Name 	struct sched_qdf_mc_timer_cb_wrapper *mc_timer_wrapper;
619*5113495bSYour Name 	QDF_STATUS status;
620*5113495bSYour Name 
621*5113495bSYour Name 	msg.type = SYS_MSG_ID_MC_TIMER;
622*5113495bSYour Name 	msg.reserved = SYS_MSG_COOKIE;
623*5113495bSYour Name 
624*5113495bSYour Name 	status = wlan_objmgr_vdev_try_get_ref(cmd->vdev, WLAN_SERIALIZATION_ID);
625*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
626*5113495bSYour Name 		ser_err("unable to get reference for vdev %d",
627*5113495bSYour Name 			 wlan_vdev_get_id(cmd->vdev));
628*5113495bSYour Name 		return;
629*5113495bSYour Name 	}
630*5113495bSYour Name 
631*5113495bSYour Name 	timeout_cmd = qdf_mem_malloc(sizeof(*timeout_cmd));
632*5113495bSYour Name 	if (!timeout_cmd) {
633*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(cmd->vdev, WLAN_SERIALIZATION_ID);
634*5113495bSYour Name 		return;
635*5113495bSYour Name 	}
636*5113495bSYour Name 
637*5113495bSYour Name 	qdf_mem_copy(timeout_cmd, cmd, sizeof(*timeout_cmd));
638*5113495bSYour Name 
639*5113495bSYour Name 	mc_timer_wrapper =
640*5113495bSYour Name 		scheduler_qdf_mc_timer_init(wlan_serialization_generic_timer_cb,
641*5113495bSYour Name 					    timeout_cmd);
642*5113495bSYour Name 
643*5113495bSYour Name 	if (!mc_timer_wrapper) {
644*5113495bSYour Name 		ser_err("failed to allocate sched_qdf_mc_timer_cb_wrapper");
645*5113495bSYour Name 		goto failed_mc_allocation;
646*5113495bSYour Name 	}
647*5113495bSYour Name 
648*5113495bSYour Name 	msg.callback = scheduler_qdf_mc_timer_callback_t_wrapper;
649*5113495bSYour Name 	msg.bodyptr = mc_timer_wrapper;
650*5113495bSYour Name 	msg.bodyval = 0;
651*5113495bSYour Name 	msg.flush_callback = wlan_serialization_mc_flush;
652*5113495bSYour Name 
653*5113495bSYour Name 	if (scheduler_post_message(QDF_MODULE_ID_SERIALIZATION,
654*5113495bSYour Name 				   QDF_MODULE_ID_SERIALIZATION,
655*5113495bSYour Name 				   QDF_MODULE_ID_SYS, &msg) ==
656*5113495bSYour Name 							QDF_STATUS_SUCCESS)
657*5113495bSYour Name 		return;
658*5113495bSYour Name 
659*5113495bSYour Name 	ser_err("Could not enqueue timer to timer queue");
660*5113495bSYour Name 	qdf_mem_free(mc_timer_wrapper);
661*5113495bSYour Name failed_mc_allocation:
662*5113495bSYour Name 	/* free mem and release ref on error */
663*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(timeout_cmd->vdev, WLAN_SERIALIZATION_ID);
664*5113495bSYour Name 	qdf_mem_free(timeout_cmd);
665*5113495bSYour Name }
666*5113495bSYour Name 
wlan_serialization_timer_handler(void * arg)667*5113495bSYour Name static void wlan_serialization_timer_handler(void *arg)
668*5113495bSYour Name {
669*5113495bSYour Name 	struct wlan_serialization_timer *timer = arg;
670*5113495bSYour Name 	struct wlan_serialization_command *cmd = timer->cmd;
671*5113495bSYour Name 
672*5113495bSYour Name 	if (!cmd) {
673*5113495bSYour Name 		ser_err("Command not found");
674*5113495bSYour Name 		return;
675*5113495bSYour Name 	}
676*5113495bSYour Name 
677*5113495bSYour Name 	ser_err("Active cmd timeout for cmd_type %d vdev %d cmd id %d",
678*5113495bSYour Name 		cmd->cmd_type, wlan_vdev_get_id(cmd->vdev),
679*5113495bSYour Name 		cmd->cmd_id);
680*5113495bSYour Name 
681*5113495bSYour Name 	wlan_serialization_timer_cb_mc_ctx(cmd);
682*5113495bSYour Name }
683*5113495bSYour Name 
684*5113495bSYour Name QDF_STATUS
wlan_serialization_find_and_update_timer(struct wlan_objmgr_psoc * psoc,struct wlan_serialization_command * cmd)685*5113495bSYour Name wlan_serialization_find_and_update_timer(
686*5113495bSYour Name 		struct wlan_objmgr_psoc *psoc,
687*5113495bSYour Name 		struct wlan_serialization_command *cmd)
688*5113495bSYour Name {
689*5113495bSYour Name 	struct wlan_ser_psoc_obj *psoc_ser_obj;
690*5113495bSYour Name 	struct wlan_serialization_timer *ser_timer;
691*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
692*5113495bSYour Name 	int i = 0;
693*5113495bSYour Name 
694*5113495bSYour Name 	if (!psoc || !cmd) {
695*5113495bSYour Name 		ser_err("invalid param");
696*5113495bSYour Name 		goto exit;
697*5113495bSYour Name 	}
698*5113495bSYour Name 
699*5113495bSYour Name 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
700*5113495bSYour Name 	/*
701*5113495bSYour Name 	 * Here cmd_id and cmd_type are used to locate the timer being
702*5113495bSYour Name 	 * associated with command.
703*5113495bSYour Name 	 */
704*5113495bSYour Name 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
705*5113495bSYour Name 
706*5113495bSYour Name 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
707*5113495bSYour Name 		ser_timer = &psoc_ser_obj->timers[i];
708*5113495bSYour Name 		if (!(ser_timer->cmd) ||
709*5113495bSYour Name 		    (ser_timer->cmd->cmd_id != cmd->cmd_id) ||
710*5113495bSYour Name 		    (ser_timer->cmd->cmd_type != cmd->cmd_type) ||
711*5113495bSYour Name 		    (ser_timer->cmd->vdev != cmd->vdev))
712*5113495bSYour Name 			continue;
713*5113495bSYour Name 
714*5113495bSYour Name 		qdf_timer_mod(&ser_timer->timer,
715*5113495bSYour Name 			      cmd->cmd_timeout_duration);
716*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
717*5113495bSYour Name 		break;
718*5113495bSYour Name 	}
719*5113495bSYour Name 
720*5113495bSYour Name 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
721*5113495bSYour Name 
722*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
723*5113495bSYour Name 		ser_debug("Can't find timer for cmd_type %d", cmd->cmd_type);
724*5113495bSYour Name 
725*5113495bSYour Name exit:
726*5113495bSYour Name 	return status;
727*5113495bSYour Name }
728*5113495bSYour Name 
729*5113495bSYour Name QDF_STATUS
wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc * psoc,struct wlan_serialization_command * cmd,enum ser_queue_reason ser_reason)730*5113495bSYour Name wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
731*5113495bSYour Name 				       struct wlan_serialization_command *cmd,
732*5113495bSYour Name 				       enum ser_queue_reason ser_reason)
733*5113495bSYour Name {
734*5113495bSYour Name 	struct wlan_ser_psoc_obj *psoc_ser_obj;
735*5113495bSYour Name 	struct wlan_serialization_timer *ser_timer;
736*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
737*5113495bSYour Name 	int i = 0;
738*5113495bSYour Name 	uint32_t phy_version;
739*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
740*5113495bSYour Name 
741*5113495bSYour Name 	if (!psoc || !cmd) {
742*5113495bSYour Name 		ser_err("invalid param");
743*5113495bSYour Name 		goto exit;
744*5113495bSYour Name 	}
745*5113495bSYour Name 
746*5113495bSYour Name 	if (cmd->cmd_timeout_duration == 0) {
747*5113495bSYour Name 		phy_version = wlan_psoc_get_nif_phy_version(psoc);
748*5113495bSYour Name 		if (wlan_is_emulation_platform(phy_version)) {
749*5113495bSYour Name 			ser_err("[SCAN-EMULATION]: Not performing timer funcs");
750*5113495bSYour Name 			status = QDF_STATUS_SUCCESS;
751*5113495bSYour Name 		goto exit;
752*5113495bSYour Name 		}
753*5113495bSYour Name 	}
754*5113495bSYour Name 
755*5113495bSYour Name 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
756*5113495bSYour Name 	/*
757*5113495bSYour Name 	 * Here cmd_id and cmd_type are used to locate the timer being
758*5113495bSYour Name 	 * associated with command.
759*5113495bSYour Name 	 */
760*5113495bSYour Name 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
761*5113495bSYour Name 
762*5113495bSYour Name 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
763*5113495bSYour Name 		ser_timer = &psoc_ser_obj->timers[i];
764*5113495bSYour Name 		if (!(ser_timer->cmd) ||
765*5113495bSYour Name 		    (ser_timer->cmd->cmd_id != cmd->cmd_id) ||
766*5113495bSYour Name 		    (ser_timer->cmd->cmd_type != cmd->cmd_type) ||
767*5113495bSYour Name 		    (ser_timer->cmd->vdev != cmd->vdev))
768*5113495bSYour Name 			continue;
769*5113495bSYour Name 
770*5113495bSYour Name 		vdev = ser_timer->cmd->vdev;
771*5113495bSYour Name 		status = wlan_serialization_stop_timer(ser_timer);
772*5113495bSYour Name 		/*
773*5113495bSYour Name 		 * Release the vdev reference when the active cmd is removed
774*5113495bSYour Name 		 * through remove/cancel request.
775*5113495bSYour Name 		 */
776*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
777*5113495bSYour Name 
778*5113495bSYour Name 		break;
779*5113495bSYour Name 
780*5113495bSYour Name 	}
781*5113495bSYour Name 
782*5113495bSYour Name 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
783*5113495bSYour Name 
784*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
785*5113495bSYour Name 		ser_err("Can't find timer for cmd_type %d cmd id %d",
786*5113495bSYour Name 			cmd->cmd_type, cmd->cmd_id);
787*5113495bSYour Name 
788*5113495bSYour Name exit:
789*5113495bSYour Name 	return status;
790*5113495bSYour Name }
791*5113495bSYour Name 
792*5113495bSYour Name QDF_STATUS
wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc * psoc,struct wlan_serialization_command * cmd,enum ser_queue_reason ser_reason)793*5113495bSYour Name wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
794*5113495bSYour Name 					struct wlan_serialization_command *cmd,
795*5113495bSYour Name 					enum ser_queue_reason ser_reason)
796*5113495bSYour Name {
797*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
798*5113495bSYour Name 	struct wlan_ser_psoc_obj *psoc_ser_obj;
799*5113495bSYour Name 	struct wlan_serialization_timer *ser_timer;
800*5113495bSYour Name 	int i = 0;
801*5113495bSYour Name 	uint32_t nif_phy_ver;
802*5113495bSYour Name 
803*5113495bSYour Name 	if (!psoc || !cmd) {
804*5113495bSYour Name 		ser_err("invalid param");
805*5113495bSYour Name 		goto error;
806*5113495bSYour Name 	}
807*5113495bSYour Name 
808*5113495bSYour Name 	nif_phy_ver = wlan_psoc_get_nif_phy_version(psoc);
809*5113495bSYour Name 	if ((cmd->cmd_timeout_duration == 0) &&
810*5113495bSYour Name 	    (wlan_is_emulation_platform(nif_phy_ver))) {
811*5113495bSYour Name 		ser_err("[SCAN-EMULATION]: Not performing timer functions\n");
812*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
813*5113495bSYour Name 		goto error;
814*5113495bSYour Name 	}
815*5113495bSYour Name 
816*5113495bSYour Name 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
817*5113495bSYour Name 
818*5113495bSYour Name 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
819*5113495bSYour Name 
820*5113495bSYour Name 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
821*5113495bSYour Name 		/* Keep trying timer */
822*5113495bSYour Name 		ser_timer = &psoc_ser_obj->timers[i];
823*5113495bSYour Name 		if (ser_timer->cmd)
824*5113495bSYour Name 			continue;
825*5113495bSYour Name 
826*5113495bSYour Name 		/* Remember timer is pointing to command */
827*5113495bSYour Name 		ser_timer->cmd = cmd;
828*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
829*5113495bSYour Name 
830*5113495bSYour Name 		/*
831*5113495bSYour Name 		 * Get vdev reference before starting the timer
832*5113495bSYour Name 		 * Remove the reference before removing the command
833*5113495bSYour Name 		 * in any one of the cases:
834*5113495bSYour Name 		 * 1. Active command is removed through remove/cancel request
835*5113495bSYour Name 		 * 2. Timer expiry handler is completed.
836*5113495bSYour Name 		 */
837*5113495bSYour Name 
838*5113495bSYour Name 		status = wlan_objmgr_vdev_try_get_ref(ser_timer->cmd->vdev,
839*5113495bSYour Name 						      WLAN_SERIALIZATION_ID);
840*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
841*5113495bSYour Name 			/*
842*5113495bSYour Name 			 * Set cmd to null so that ref release is not tried for
843*5113495bSYour Name 			 * vdev when timer is flushed.
844*5113495bSYour Name 			 */
845*5113495bSYour Name 			ser_timer->cmd = NULL;
846*5113495bSYour Name 			wlan_serialization_release_lock(
847*5113495bSYour Name 					&psoc_ser_obj->timer_lock);
848*5113495bSYour Name 			ser_err("Unbale to get vdev reference");
849*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
850*5113495bSYour Name 			goto error;
851*5113495bSYour Name 		}
852*5113495bSYour Name 		break;
853*5113495bSYour Name 	}
854*5113495bSYour Name 
855*5113495bSYour Name 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
856*5113495bSYour Name 
857*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status)) {
858*5113495bSYour Name 		qdf_timer_init(NULL, &ser_timer->timer,
859*5113495bSYour Name 			       wlan_serialization_timer_handler,
860*5113495bSYour Name 			       ser_timer, QDF_TIMER_TYPE_SW);
861*5113495bSYour Name 		qdf_timer_mod(&ser_timer->timer, cmd->cmd_timeout_duration);
862*5113495bSYour Name 	} else {
863*5113495bSYour Name 		ser_err("Failed to start timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
864*5113495bSYour Name 			cmd->cmd_type, cmd->cmd_id, cmd->is_high_priority,
865*5113495bSYour Name 			cmd->is_blocking);
866*5113495bSYour Name 	}
867*5113495bSYour Name 
868*5113495bSYour Name error:
869*5113495bSYour Name 	return status;
870*5113495bSYour Name }
871*5113495bSYour Name 
872*5113495bSYour Name enum wlan_serialization_cmd_status
wlan_serialization_cmd_cancel_handler(struct wlan_ser_pdev_obj * ser_obj,struct wlan_serialization_command * cmd,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,enum wlan_serialization_cmd_type cmd_type,uint8_t queue_type,enum wlan_ser_cmd_attr cmd_attr)873*5113495bSYour Name wlan_serialization_cmd_cancel_handler(
874*5113495bSYour Name 		struct wlan_ser_pdev_obj *ser_obj,
875*5113495bSYour Name 		struct wlan_serialization_command *cmd,
876*5113495bSYour Name 		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
877*5113495bSYour Name 		enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type,
878*5113495bSYour Name 		enum wlan_ser_cmd_attr cmd_attr)
879*5113495bSYour Name {
880*5113495bSYour Name 	enum wlan_serialization_cmd_status active_status =
881*5113495bSYour Name 		WLAN_SER_CMD_NOT_FOUND;
882*5113495bSYour Name 	enum wlan_serialization_cmd_status pending_status =
883*5113495bSYour Name 		WLAN_SER_CMD_NOT_FOUND;
884*5113495bSYour Name 	enum wlan_serialization_cmd_status status =
885*5113495bSYour Name 		WLAN_SER_CMD_NOT_FOUND;
886*5113495bSYour Name 
887*5113495bSYour Name 	if (!ser_obj) {
888*5113495bSYour Name 		ser_err("invalid serial object");
889*5113495bSYour Name 		goto error;
890*5113495bSYour Name 	}
891*5113495bSYour Name 
892*5113495bSYour Name 	if (queue_type & WLAN_SERIALIZATION_ACTIVE_QUEUE) {
893*5113495bSYour Name 		if (cmd_type < WLAN_SER_CMD_NONSCAN)
894*5113495bSYour Name 			active_status = wlan_ser_cancel_scan_cmd(
895*5113495bSYour Name 					ser_obj, pdev, vdev, cmd,
896*5113495bSYour Name 					cmd_type, true);
897*5113495bSYour Name 		else
898*5113495bSYour Name 			active_status = wlan_ser_cancel_non_scan_cmd(
899*5113495bSYour Name 					ser_obj, pdev, vdev, cmd,
900*5113495bSYour Name 					cmd_type, true, cmd_attr);
901*5113495bSYour Name 	}
902*5113495bSYour Name 
903*5113495bSYour Name 	if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) {
904*5113495bSYour Name 		if (cmd_type < WLAN_SER_CMD_NONSCAN)
905*5113495bSYour Name 			pending_status = wlan_ser_cancel_scan_cmd(
906*5113495bSYour Name 					ser_obj, pdev, vdev, cmd,
907*5113495bSYour Name 					cmd_type, false);
908*5113495bSYour Name 		else
909*5113495bSYour Name 			pending_status = wlan_ser_cancel_non_scan_cmd(
910*5113495bSYour Name 					ser_obj, pdev, vdev, cmd,
911*5113495bSYour Name 					cmd_type, false, cmd_attr);
912*5113495bSYour Name 	}
913*5113495bSYour Name 
914*5113495bSYour Name 	if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST &&
915*5113495bSYour Name 	    pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
916*5113495bSYour Name 		status = WLAN_SER_CMDS_IN_ALL_LISTS;
917*5113495bSYour Name 	else if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST)
918*5113495bSYour Name 		status = active_status;
919*5113495bSYour Name 	else if (pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
920*5113495bSYour Name 		status = pending_status;
921*5113495bSYour Name 
922*5113495bSYour Name error:
923*5113495bSYour Name 	return status;
924*5113495bSYour Name }
925*5113495bSYour Name 
926*5113495bSYour Name enum wlan_serialization_cmd_status
wlan_serialization_find_and_cancel_cmd(struct wlan_serialization_command * cmd,enum wlan_serialization_cancel_type req_type,uint8_t queue_type)927*5113495bSYour Name wlan_serialization_find_and_cancel_cmd(
928*5113495bSYour Name 		struct wlan_serialization_command *cmd,
929*5113495bSYour Name 		enum wlan_serialization_cancel_type req_type,
930*5113495bSYour Name 		uint8_t queue_type)
931*5113495bSYour Name {
932*5113495bSYour Name 	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
933*5113495bSYour Name 	struct wlan_ser_pdev_obj *ser_obj = NULL;
934*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
935*5113495bSYour Name 
936*5113495bSYour Name 	if (!cmd) {
937*5113495bSYour Name 		ser_err("Invalid cmd");
938*5113495bSYour Name 		goto error;
939*5113495bSYour Name 	}
940*5113495bSYour Name 
941*5113495bSYour Name 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
942*5113495bSYour Name 	if (!pdev) {
943*5113495bSYour Name 		ser_err("Invalid pdev");
944*5113495bSYour Name 		goto error;
945*5113495bSYour Name 	}
946*5113495bSYour Name 	ser_obj = wlan_serialization_get_pdev_obj(pdev);
947*5113495bSYour Name 	if (!ser_obj) {
948*5113495bSYour Name 		ser_err("Invalid ser_obj");
949*5113495bSYour Name 		goto error;
950*5113495bSYour Name 	}
951*5113495bSYour Name 
952*5113495bSYour Name 	switch (req_type) {
953*5113495bSYour Name 	case WLAN_SER_CANCEL_SINGLE_SCAN:
954*5113495bSYour Name 		/* remove scan cmd which matches the given cmd struct */
955*5113495bSYour Name 		status = wlan_serialization_cmd_cancel_handler(
956*5113495bSYour Name 				ser_obj, cmd, NULL, NULL,
957*5113495bSYour Name 				WLAN_SER_CMD_SCAN, queue_type,
958*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONE);
959*5113495bSYour Name 		break;
960*5113495bSYour Name 	case WLAN_SER_CANCEL_PDEV_SCANS:
961*5113495bSYour Name 		/* remove all scan cmds which matches the pdev object */
962*5113495bSYour Name 		status = wlan_serialization_cmd_cancel_handler(
963*5113495bSYour Name 				ser_obj, NULL, pdev, NULL,
964*5113495bSYour Name 				WLAN_SER_CMD_SCAN, queue_type,
965*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONE);
966*5113495bSYour Name 		break;
967*5113495bSYour Name 	case WLAN_SER_CANCEL_VDEV_SCANS:
968*5113495bSYour Name 	case WLAN_SER_CANCEL_VDEV_HOST_SCANS:
969*5113495bSYour Name 		/* remove all scan cmds which matches the vdev object */
970*5113495bSYour Name 		status = wlan_serialization_cmd_cancel_handler(
971*5113495bSYour Name 				ser_obj, NULL, NULL, cmd->vdev,
972*5113495bSYour Name 				WLAN_SER_CMD_SCAN, queue_type,
973*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONE);
974*5113495bSYour Name 		break;
975*5113495bSYour Name 	case WLAN_SER_CANCEL_NON_SCAN_CMD:
976*5113495bSYour Name 		/* remove nonscan cmd which matches the given cmd */
977*5113495bSYour Name 		status = wlan_serialization_cmd_cancel_handler(
978*5113495bSYour Name 				ser_obj, cmd, NULL, NULL,
979*5113495bSYour Name 				WLAN_SER_CMD_NONSCAN, queue_type,
980*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONE);
981*5113495bSYour Name 		break;
982*5113495bSYour Name 	case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD:
983*5113495bSYour Name 		/* remove all non scan cmds which matches the pdev object */
984*5113495bSYour Name 		status = wlan_serialization_cmd_cancel_handler(
985*5113495bSYour Name 				ser_obj, NULL, pdev, NULL,
986*5113495bSYour Name 				WLAN_SER_CMD_NONSCAN, queue_type,
987*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONE);
988*5113495bSYour Name 		break;
989*5113495bSYour Name 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD:
990*5113495bSYour Name 		/* remove all non scan cmds which matches the vdev object */
991*5113495bSYour Name 		status = wlan_serialization_cmd_cancel_handler(
992*5113495bSYour Name 				ser_obj, NULL, NULL, cmd->vdev,
993*5113495bSYour Name 				WLAN_SER_CMD_NONSCAN, queue_type,
994*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONE);
995*5113495bSYour Name 		break;
996*5113495bSYour Name 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE:
997*5113495bSYour Name 		/*
998*5113495bSYour Name 		 * remove all non scan cmds which matches the vdev
999*5113495bSYour Name 		 * and given cmd type
1000*5113495bSYour Name 		 */
1001*5113495bSYour Name 		status = wlan_serialization_cmd_cancel_handler(
1002*5113495bSYour Name 				ser_obj, NULL, NULL, cmd->vdev,
1003*5113495bSYour Name 				cmd->cmd_type, queue_type,
1004*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONE);
1005*5113495bSYour Name 		break;
1006*5113495bSYour Name 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD:
1007*5113495bSYour Name 		/*
1008*5113495bSYour Name 		 * remove all non-blocking non-scan cmds which matches the given
1009*5113495bSYour Name 		 * vdev
1010*5113495bSYour Name 		 */
1011*5113495bSYour Name 		status = wlan_serialization_cmd_cancel_handler(
1012*5113495bSYour Name 				ser_obj, NULL, NULL, cmd->vdev,
1013*5113495bSYour Name 				WLAN_SER_CMD_NONSCAN, queue_type,
1014*5113495bSYour Name 				WLAN_SER_CMD_ATTR_NONBLOCK);
1015*5113495bSYour Name 		break;
1016*5113495bSYour Name 	default:
1017*5113495bSYour Name 		ser_err("Invalid request");
1018*5113495bSYour Name 	}
1019*5113495bSYour Name 
1020*5113495bSYour Name error:
1021*5113495bSYour Name 
1022*5113495bSYour Name 	return status;
1023*5113495bSYour Name }
1024