1  /*
2   * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4   *
5   * Permission to use, copy, modify, and/or distribute this software for
6   * any purpose with or without fee is hereby granted, provided that the
7   * above copyright notice and this permission notice appear in all
8   * copies.
9   *
10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11   * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12   * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13   * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17   * PERFORMANCE OF THIS SOFTWARE.
18   */
19  
20  #if !defined(__SCHEDULER_CORE_H)
21  #define __SCHEDULER_CORE_H
22  
23  #include <qdf_threads.h>
24  #include <qdf_timer.h>
25  #include <scheduler_api.h>
26  #include <qdf_list.h>
27  
28  #ifndef SCHEDULER_CORE_MAX_MESSAGES
29  #define SCHEDULER_CORE_MAX_MESSAGES 4000
30  #endif
31  #ifndef WLAN_SCHED_REDUCTION_LIMIT
32  #define WLAN_SCHED_REDUCTION_LIMIT 32
33  #endif
34  #define SCHEDULER_NUMBER_OF_MSG_QUEUE 6
35  #define SCHEDULER_WRAPPER_MAX_FAIL_COUNT (SCHEDULER_CORE_MAX_MESSAGES * 3)
36  #define SCHEDULER_WATCHDOG_TIMEOUT (10 * 1000) /* 10s */
37  
38  #ifdef CONFIG_AP_PLATFORM
39  #define SCHED_DEBUG_PANIC(msg)
40  #else
41  #define SCHED_DEBUG_PANIC(msg) QDF_DEBUG_PANIC(msg)
42  #endif
43  
44  #define sched_fatal(params...) \
45  	QDF_TRACE_FATAL(QDF_MODULE_ID_SCHEDULER, params)
46  #define sched_err(params...) \
47  	QDF_TRACE_ERROR(QDF_MODULE_ID_SCHEDULER, params)
48  #define sched_warn(params...) \
49  	QDF_TRACE_WARN(QDF_MODULE_ID_SCHEDULER, params)
50  #define sched_info(params...) \
51  	QDF_TRACE_INFO(QDF_MODULE_ID_SCHEDULER, params)
52  #define sched_debug(params...) \
53  	QDF_TRACE_DEBUG(QDF_MODULE_ID_SCHEDULER, params)
54  
55  #define sched_nofl_fatal(params...) \
56  	QDF_TRACE_FATAL_NO_FL(QDF_MODULE_ID_SCHEDULER, params)
57  #define sched_nofl_err(params...) \
58  	QDF_TRACE_ERROR_NO_FL(QDF_MODULE_ID_SCHEDULER, params)
59  #define sched_nofl_warn(params...) \
60  	QDF_TRACE_WARN_NO_FL(QDF_MODULE_ID_SCHEDULER, params)
61  #define sched_nofl_info(params...) \
62  	QDF_TRACE_INFO_NO_FL(QDF_MODULE_ID_SCHEDULER, params)
63  #define sched_nofl_debug(params...) \
64  	QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_SCHEDULER, params)
65  
66  #define sched_enter() sched_debug("Enter")
67  #define sched_exit() sched_debug("Exit")
68  
69  /**
70   * struct scheduler_mq_type -  scheduler message queue
71   * @mq_lock: message queue lock
72   * @mq_list: message queue list
73   * @qid: queue id
74   */
75  struct scheduler_mq_type {
76  	qdf_spinlock_t mq_lock;
77  	qdf_list_t mq_list;
78  	QDF_MODULE_ID qid;
79  };
80  
81  /**
82   * struct scheduler_mq_ctx - scheduler message queue context
83   * @sch_msg_q: scheduler message queue
84   * @scheduler_msg_qid_to_qidx: message qid to qidx mapping
85   * @scheduler_msg_process_fn: array of message queue handler function pointers
86   */
87  struct scheduler_mq_ctx {
88  	struct scheduler_mq_type sch_msg_q[SCHEDULER_NUMBER_OF_MSG_QUEUE];
89  	uint8_t scheduler_msg_qid_to_qidx[QDF_MODULE_ID_MAX];
90  	QDF_STATUS (*scheduler_msg_process_fn[SCHEDULER_NUMBER_OF_MSG_QUEUE])
91  					(struct scheduler_msg *msg);
92  };
93  
94  /**
95   * struct scheduler_ctx - scheduler context
96   * @queue_ctx: message queue context
97   * @sch_start_event: scheduler thread start wait event
98   * @sch_thread: scheduler thread
99   * @sch_shutdown: scheduler thread shutdown wait event
100   * @sch_wait_queue: scheduler wait queue
101   * @sch_event_flag: scheduler events flag
102   * @resume_sch_event: scheduler resume wait event
103   * @sch_thread_lock: scheduler thread lock
104   * @sch_last_qidx: scheduler last qidx allocation
105   * @watchdog_msg_type: 'type' of the current msg being processed
106   * @hdd_callback: os if suspend callback
107   * @legacy_wma_handler: legacy wma message handler
108   * @legacy_sys_handler: legacy sys message handler
109   * @timeout: timeout value for scheduler watchdog timer
110   * @watchdog_timer: timer for triggering a scheduler watchdog bite
111   * @watchdog_callback: the callback of the current msg being processed
112   */
113  struct scheduler_ctx {
114  	struct scheduler_mq_ctx queue_ctx;
115  	qdf_event_t sch_start_event;
116  	qdf_thread_t *sch_thread;
117  	qdf_event_t sch_shutdown;
118  	qdf_wait_queue_head_t sch_wait_queue;
119  	unsigned long sch_event_flag;
120  	qdf_event_t resume_sch_event;
121  	qdf_spinlock_t sch_thread_lock;
122  	uint8_t sch_last_qidx;
123  	uint16_t watchdog_msg_type;
124  	hdd_suspend_callback hdd_callback;
125  	scheduler_msg_process_fn_t legacy_wma_handler;
126  	scheduler_msg_process_fn_t legacy_sys_handler;
127  	uint32_t timeout;
128  	qdf_timer_t watchdog_timer;
129  	void *watchdog_callback;
130  };
131  
132  /**
133   * scheduler_core_msg_dup() - duplicate the given scheduler message
134   * @msg: the message to duplicated
135   *
136   * Note: Duplicated messages must be freed using scheduler_core_msg_free().
137   *
138   * Return: pointer to the duplicated message
139   */
140  struct scheduler_msg *scheduler_core_msg_dup(struct scheduler_msg *msg);
141  
142  /**
143   * scheduler_core_msg_free() - free the given scheduler message
144   * @msg: the duplicated message to free
145   *
146   * Return: None
147   */
148  void scheduler_core_msg_free(struct scheduler_msg *msg);
149  
150  /**
151   * scheduler_get_context() - to get scheduler context
152   *
153   * This routine is used retrieve scheduler context
154   *
155   * Return: Pointer to scheduler context
156   */
157  struct scheduler_ctx *scheduler_get_context(void);
158  
159  /**
160   * scheduler_thread() - spawned thread will execute this routine
161   * @arg: pointer to scheduler context
162   *
163   * Newly created thread will use this routine to perform its duty
164   *
165   * Return: none
166   */
167  int scheduler_thread(void *arg);
168  
169  /**
170   * scheduler_create_ctx() - to create scheduler context
171   *
172   * This routine is used to create scheduler context
173   *
174   * Return: QDF_STATUS based on success or failure
175   */
176  QDF_STATUS scheduler_create_ctx(void);
177  /**
178   * scheduler_destroy_ctx() - to destroy scheduler context
179   *
180   * This routine is used to destroy scheduler context
181   *
182   * Return: QDF_STATUS based on success or failure
183   */
184  QDF_STATUS scheduler_destroy_ctx(void);
185  
186  /**
187   * scheduler_mq_put() - put message in the back of queue
188   * @msg_q: Pointer to the message queue
189   * @msg: the message to enqueue
190   *
191   * This function is used to put message in back of provided message
192   * queue
193   *
194   *  Return: none
195   */
196  void scheduler_mq_put(struct scheduler_mq_type *msg_q,
197  		      struct scheduler_msg *msg);
198  /**
199   * scheduler_mq_put_front() - put message in the front of queue
200   * @msg_q: Pointer to the message queue
201   * @msg: the message to enqueue
202   *
203   * This function is used to put message in front of provided message
204   * queue
205   *
206   *  Return: none
207   */
208  void scheduler_mq_put_front(struct scheduler_mq_type *msg_q,
209  			    struct scheduler_msg *msg);
210  /**
211   * scheduler_mq_get() - to get message from message queue
212   * @msg_q: Pointer to the message queue
213   *
214   * This function is used to get message from given message queue
215   *
216   *  Return: none
217   */
218  struct scheduler_msg *scheduler_mq_get(struct scheduler_mq_type *msg_q);
219  
220  /**
221   * scheduler_queues_init() - to initialize all the modules' queues
222   * @sched_ctx: pointer to scheduler context
223   *
224   * This function is used to initialize the queues for all the modules
225   *
226   * Return: QDF_STATUS based on success of failure
227   */
228  QDF_STATUS scheduler_queues_init(struct scheduler_ctx *sched_ctx);
229  
230  /**
231   * scheduler_queues_deinit() - to de-initialize all the modules' queues
232   * @sched_ctx: pointer to scheduler context
233   *
234   * This function is used to de-initialize the queues for all the modules
235   *
236   * Return: QDF_STATUS based on success of failure
237   */
238  QDF_STATUS scheduler_queues_deinit(struct scheduler_ctx *sched_ctx);
239  
240  /**
241   * scheduler_queues_flush() - flush all of the scheduler queues
242   * @sched_ctx: pointer to scheduler context
243   *
244   * This routine  is used to clean the module's queues
245   *
246   * Return: none
247   */
248  void scheduler_queues_flush(struct scheduler_ctx *sched_ctx);
249  #endif
250