blob: 4c3becbc7cdc1332f92834475fe70e271598ee55 [file] [log] [blame]
Pavan Kumar Chilamkurthibd699432018-01-24 12:53:01 -08001/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
Sagar Gore8d91a622017-02-23 14:57:18 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
14#include <linux/of_platform.h>
15#include <linux/slab.h>
16#include <linux/mutex.h>
17#include "cam_req_mgr_interface.h"
18#include "cam_req_mgr_util.h"
19#include "cam_req_mgr_core.h"
20#include "cam_req_mgr_workq.h"
Sagar Gored79f95e2017-03-14 18:32:17 -070021#include "cam_req_mgr_debug.h"
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -060022#include "cam_trace.h"
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070023#include "cam_debug_util.h"
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -070024#include "cam_req_mgr_dev.h"
Sagar Gore8d91a622017-02-23 14:57:18 -080025
26static struct cam_req_mgr_core_device *g_crm_core_dev;
27
Venkat Chintaddbe5132018-01-30 12:00:29 -080028void cam_req_mgr_handle_core_shutdown(void)
29{
30 struct cam_req_mgr_core_session *session;
31 struct cam_req_mgr_core_session *tsession;
32 struct cam_req_mgr_session_info ses_info;
33
34 if (!list_empty(&g_crm_core_dev->session_head)) {
35 list_for_each_entry_safe(session, tsession,
36 &g_crm_core_dev->session_head, entry) {
37 ses_info.session_hdl =
38 session->session_hdl;
39 cam_req_mgr_destroy_session(&ses_info);
40 }
41 }
42}
43
Sagar Gored79f95e2017-03-14 18:32:17 -070044static int __cam_req_mgr_setup_payload(struct cam_req_mgr_core_workq *workq)
45{
46 int32_t i = 0;
47 int rc = 0;
48 struct crm_task_payload *task_data = NULL;
49
50 task_data = kcalloc(
51 workq->task.num_task, sizeof(*task_data),
52 GFP_KERNEL);
53 if (!task_data) {
54 rc = -ENOMEM;
55 } else {
56 for (i = 0; i < workq->task.num_task; i++)
57 workq->task.pool[i].payload = &task_data[i];
58 }
59
60 return rc;
61}
Sagar Gore8d91a622017-02-23 14:57:18 -080062
63/**
Sagar Gored79f95e2017-03-14 18:32:17 -070064 * __cam_req_mgr_reset_req_tbl()
Sagar Gore8d91a622017-02-23 14:57:18 -080065 *
Sagar Gored79f95e2017-03-14 18:32:17 -070066 * @brief : Initialize req table data
67 * @in_q : request queue pointer
Sagar Gore8d91a622017-02-23 14:57:18 -080068 *
Sagar Gored79f95e2017-03-14 18:32:17 -070069 * @return: 0 for success, negative for failure
70 *
Sagar Gore8d91a622017-02-23 14:57:18 -080071 */
Sagar Gored79f95e2017-03-14 18:32:17 -070072static int __cam_req_mgr_print_req_tbl(struct cam_req_mgr_req_data *req)
Sagar Gore8d91a622017-02-23 14:57:18 -080073{
Sagar Gored79f95e2017-03-14 18:32:17 -070074 int rc = 0;
75 int32_t i = 0;
76 struct cam_req_mgr_req_queue *in_q = req->in_q;
77 struct cam_req_mgr_req_tbl *req_tbl = req->l_tbl;
78
79 if (!in_q || !req_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070080 CAM_WARN(CAM_CRM, "NULL pointer %pK %pK", in_q, req_tbl);
Sagar Gored79f95e2017-03-14 18:32:17 -070081 return -EINVAL;
82 }
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070083 CAM_DBG(CAM_CRM, "in_q %pK %pK %d", in_q, req_tbl, req_tbl->num_slots);
Sagar Gored79f95e2017-03-14 18:32:17 -070084 mutex_lock(&req->lock);
85 for (i = 0; i < in_q->num_slots; i++) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070086 CAM_DBG(CAM_CRM, "IN_Q %d: idx %d, red_id %lld", i,
Sagar Gored79f95e2017-03-14 18:32:17 -070087 in_q->slot[i].idx, CRM_GET_REQ_ID(in_q, i));
88 }
89
90 while (req_tbl != NULL) {
91 for (i = 0; i < req_tbl->num_slots; i++) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070092 CAM_DBG(CAM_CRM, "idx= %d, map= %x, state= %d",
Sagar Gored79f95e2017-03-14 18:32:17 -070093 req_tbl->slot[i].idx,
94 req_tbl->slot[i].req_ready_map,
95 req_tbl->slot[i].state);
96 }
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070097 CAM_DBG(CAM_CRM,
98 "TBL:id= %d, pd=%d cnt=%d mask=%x skip=%d num_slt= %d",
Sagar Gored79f95e2017-03-14 18:32:17 -070099 req_tbl->id, req_tbl->pd, req_tbl->dev_count,
100 req_tbl->dev_mask, req_tbl->skip_traverse,
101 req_tbl->num_slots);
102 req_tbl = req_tbl->next;
103 }
104 mutex_unlock(&req->lock);
105
106 return rc;
107}
108
109/**
110 * __cam_req_mgr_find_pd_tbl()
111 *
112 * @brief : Find pipeline delay based table pointer which matches delay
113 * @tbl : Pointer to list of request table
114 * @delay : Pipeline delay value to be searched for comparison
115 *
116 * @return : pointer to request table for matching pipeline delay table.
117 *
118 */
119static struct cam_req_mgr_req_tbl *__cam_req_mgr_find_pd_tbl(
120 struct cam_req_mgr_req_tbl *tbl, int32_t delay)
121{
122 if (!tbl)
123 return NULL;
124
125 do {
126 if (delay != tbl->pd)
127 tbl = tbl->next;
128 else
129 return tbl;
130 } while (tbl != NULL);
131
132 return NULL;
133}
134
135/**
136 * __cam_req_mgr_inc_idx()
137 *
138 * @brief : Increment val passed by step size and rollover after max_val
139 * @val : value to be incremented
140 * @step : amount/step by which val is incremented
141 * @max_val : max val after which idx will roll over
142 *
143 */
144static void __cam_req_mgr_inc_idx(int32_t *val, int32_t step, int32_t max_val)
145{
146 *val = (*val + step) % max_val;
147}
148
149/**
150 * __cam_req_mgr_dec_idx()
151 *
152 * @brief : Decrement val passed by step size and rollover after max_val
153 * @val : value to be decremented
154 * @step : amount/step by which val is decremented
155 * @max_val : after zero value will roll over to max val
156 *
157 */
158static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val)
159{
160 *val = *val - step;
161 if (*val < 0)
162 *val = max_val + (*val);
163}
164
165/**
166 * __cam_req_mgr_traverse()
167 *
168 * @brief : Traverse through pd tables, it will internally cover all linked
169 * pd tables. Each pd table visited will check if idx passed to its
170 * in ready state. If ready means all devices linked to the pd table
171 * have this request id packet ready. Then it calls subsequent pd
172 * tbl with new idx. New idx value takes into account the delta
173 * between current pd table and next one.
174 * @traverse_data: contains all the info to traverse through pd tables
175 *
176 * @return: 0 for success, negative for failure
177 *
178 */
179static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data)
180{
181 int rc = 0;
182 int32_t next_idx = traverse_data->idx;
183 int32_t curr_idx = traverse_data->idx;
184 struct cam_req_mgr_req_tbl *tbl;
185 struct cam_req_mgr_apply *apply_data;
186
187 if (!traverse_data->tbl || !traverse_data->apply_data) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700188 CAM_ERR(CAM_CRM, "NULL pointer %pK %pK",
Sagar Gored79f95e2017-03-14 18:32:17 -0700189 traverse_data->tbl, traverse_data->apply_data);
190 traverse_data->result = 0;
191 return -EINVAL;
192 }
193
194 tbl = traverse_data->tbl;
195 apply_data = traverse_data->apply_data;
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800196 CAM_DBG(CAM_CRM,
197 "Enter pd %d idx %d state %d skip %d status %d skip_idx %d",
Sagar Gored79f95e2017-03-14 18:32:17 -0700198 tbl->pd, curr_idx, tbl->slot[curr_idx].state,
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800199 tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status,
200 traverse_data->in_q->slot[curr_idx].skip_idx);
Sagar Gored79f95e2017-03-14 18:32:17 -0700201
Venkat Chinta686c9e52018-01-20 14:33:25 -0800202 if ((tbl->inject_delay > 0) &&
203 (traverse_data->validate_only == false)) {
Sagar Gorea4d7dfd2017-09-13 19:56:24 -0700204 CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
Venkat Chintaddbe5132018-01-30 12:00:29 -0800205 apply_data[tbl->pd].req_id = -1;
Sagar Gorea4d7dfd2017-09-13 19:56:24 -0700206 tbl->inject_delay--;
207 /* This pd table is not ready to proceed with asked idx */
208 SET_FAILURE_BIT(traverse_data->result, tbl->pd);
Venkat Chintaddbe5132018-01-30 12:00:29 -0800209 return -EAGAIN;
Sagar Gorea4d7dfd2017-09-13 19:56:24 -0700210 }
211
Sagar Gored79f95e2017-03-14 18:32:17 -0700212 /* Check if req is ready or in skip mode or pd tbl is in skip mode */
213 if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY ||
214 traverse_data->in_q->slot[curr_idx].skip_idx == 1 ||
215 tbl->skip_traverse > 0) {
216 if (tbl->next) {
217 __cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta,
218 tbl->num_slots);
219 traverse_data->idx = next_idx;
220 traverse_data->tbl = tbl->next;
221 rc = __cam_req_mgr_traverse(traverse_data);
222 }
223 if (rc >= 0) {
224 SET_SUCCESS_BIT(traverse_data->result, tbl->pd);
Venkat Chinta686c9e52018-01-20 14:33:25 -0800225
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800226 if (traverse_data->validate_only == false) {
227 apply_data[tbl->pd].pd = tbl->pd;
228 apply_data[tbl->pd].req_id =
Venkat Chinta686c9e52018-01-20 14:33:25 -0800229 CRM_GET_REQ_ID(
230 traverse_data->in_q, curr_idx);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800231 apply_data[tbl->pd].idx = curr_idx;
Sagar Gored79f95e2017-03-14 18:32:17 -0700232
Venkat Chinta686c9e52018-01-20 14:33:25 -0800233 CAM_DBG(CAM_CRM, "req_id: %d with pd of %d",
234 apply_data[tbl->pd].req_id,
235 apply_data[tbl->pd].pd);
236 /*
237 * If traverse is successful decrement
238 * traverse skip
239 */
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800240 if (tbl->skip_traverse > 0) {
241 apply_data[tbl->pd].req_id = -1;
242 tbl->skip_traverse--;
243 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700244 }
245 } else {
246 /* linked pd table is not ready for this traverse yet */
247 return rc;
248 }
249 } else {
250 /* This pd table is not ready to proceed with asked idx */
Venkat Chintaddbe5132018-01-30 12:00:29 -0800251 SET_FAILURE_BIT(traverse_data->result, tbl->pd);
252 return -EAGAIN;
Sagar Gored79f95e2017-03-14 18:32:17 -0700253 }
254 return 0;
255}
256
257/**
258 * __cam_req_mgr_in_q_skip_idx()
259 *
260 * @brief : Decrement val passed by step size and rollover after max_val
261 * @in_q : input queue pointer
262 * @idx : Sets skip_idx bit of the particular slot to true so when traverse
263 * happens for this idx, no req will be submitted for devices
264 * handling this idx.
265 *
266 */
267static void __cam_req_mgr_in_q_skip_idx(struct cam_req_mgr_req_queue *in_q,
268 int32_t idx)
269{
270 in_q->slot[idx].req_id = -1;
271 in_q->slot[idx].skip_idx = 1;
272 in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700273 CAM_DBG(CAM_CRM, "SET IDX SKIP on slot= %d", idx);
Sagar Gored79f95e2017-03-14 18:32:17 -0700274}
275
276/**
277 * __cam_req_mgr_tbl_set_id()
278 *
279 * @brief : Set unique id to table
280 * @tbl : pipeline based table which requires new id
281 * @req : pointer to request data wihch contains num_tables counter
282 *
283 */
284static void __cam_req_mgr_tbl_set_id(struct cam_req_mgr_req_tbl *tbl,
285 struct cam_req_mgr_req_data *req)
286{
287 if (!tbl)
288 return;
289 do {
290 tbl->id = req->num_tbl++;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700291 CAM_DBG(CAM_CRM, "%d: pd %d skip_traverse %d delta %d",
Sagar Gored79f95e2017-03-14 18:32:17 -0700292 tbl->id, tbl->pd, tbl->skip_traverse,
293 tbl->pd_delta);
294 tbl = tbl->next;
295 } while (tbl != NULL);
296}
297
298/**
299 * __cam_req_mgr_tbl_set_all_skip_cnt()
300 *
301 * @brief : Each pd table sets skip value based on delta between itself and
302 * max pd value. During initial streamon or bubble case this is
303 * used. That way each pd table skips required num of traverse and
304 * align themselve with req mgr connected devs.
305 * @l_tbl : iterates through list of pd tables and sets skip traverse
306 *
307 */
308static void __cam_req_mgr_tbl_set_all_skip_cnt(
309 struct cam_req_mgr_req_tbl **l_tbl)
310{
311 struct cam_req_mgr_req_tbl *tbl = *l_tbl;
312 int32_t max_pd;
313
314 if (!tbl)
315 return;
316
317 max_pd = tbl->pd;
318 do {
319 tbl->skip_traverse = max_pd - tbl->pd;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700320 CAM_DBG(CAM_CRM, "%d: pd %d skip_traverse %d delta %d",
Sagar Gored79f95e2017-03-14 18:32:17 -0700321 tbl->id, tbl->pd, tbl->skip_traverse,
322 tbl->pd_delta);
323 tbl = tbl->next;
324 } while (tbl != NULL);
325}
326
327/**
328 * __cam_req_mgr_reset_req_slot()
329 *
330 * @brief : reset specified idx/slot in input queue as well as all pd tables
331 * @link : link pointer
332 * @idx : slot index which will be reset
333 *
334 */
335static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
336 int32_t idx)
337{
338 struct cam_req_mgr_slot *slot;
339 struct cam_req_mgr_req_tbl *tbl = link->req.l_tbl;
340 struct cam_req_mgr_req_queue *in_q = link->req.in_q;
341
342 slot = &in_q->slot[idx];
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700343 CAM_DBG(CAM_CRM, "RESET: idx: %d: slot->status %d", idx, slot->status);
Sagar Gored79f95e2017-03-14 18:32:17 -0700344
345 /* Check if CSL has already pushed new request*/
346 if (slot->status == CRM_SLOT_STATUS_REQ_ADDED)
347 return;
348
349 /* Reset input queue slot */
350 slot->req_id = -1;
351 slot->skip_idx = 0;
352 slot->recover = 0;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -0800353 slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
Sagar Gored79f95e2017-03-14 18:32:17 -0700354 slot->status = CRM_SLOT_STATUS_NO_REQ;
355
356 /* Reset all pd table slot */
357 while (tbl != NULL) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700358 CAM_DBG(CAM_CRM, "pd: %d: idx %d state %d",
Sagar Gored79f95e2017-03-14 18:32:17 -0700359 tbl->pd, idx, tbl->slot[idx].state);
360 tbl->slot[idx].req_ready_map = 0;
361 tbl->slot[idx].state = CRM_REQ_STATE_EMPTY;
362 tbl = tbl->next;
363 }
364}
365
366/**
367 * __cam_req_mgr_check_next_req_slot()
368 *
369 * @brief : While streaming if input queue does not contain any pending
370 * request, req mgr still needs to submit pending request ids to
371 * devices with lower pipeline delay value.
372 * @in_q : Pointer to input queue where req mgr wil peep into
373 *
374 */
375static void __cam_req_mgr_check_next_req_slot(
376 struct cam_req_mgr_req_queue *in_q)
377{
378 int32_t idx = in_q->rd_idx;
379 struct cam_req_mgr_slot *slot;
380
381 __cam_req_mgr_inc_idx(&idx, 1, in_q->num_slots);
382 slot = &in_q->slot[idx];
383
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700384 CAM_DBG(CAM_CRM, "idx: %d: slot->status %d", idx, slot->status);
Sagar Gored79f95e2017-03-14 18:32:17 -0700385
386 /* Check if there is new req from CSL, if not complete req */
387 if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
388 __cam_req_mgr_in_q_skip_idx(in_q, idx);
389 if (in_q->wr_idx != idx)
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700390 CAM_WARN(CAM_CRM,
391 "CHECK here wr %d, rd %d", in_q->wr_idx, idx);
Sagar Gored79f95e2017-03-14 18:32:17 -0700392 __cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
393 }
394}
395
396/**
397 * __cam_req_mgr_send_req()
398 *
399 * @brief : send request id to be applied to each device connected on link
400 * @link : pointer to link whose input queue and req tbl are
401 * traversed through
402 * @in_q : pointer to input request queue
403 *
404 * @return : 0 for success, negative for failure
405 *
406 */
407static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
Junzhe Zou2df84502017-05-26 13:20:23 -0700408 struct cam_req_mgr_req_queue *in_q, uint32_t trigger)
Sagar Gored79f95e2017-03-14 18:32:17 -0700409{
410 int rc = 0, pd, i, idx;
411 struct cam_req_mgr_connected_device *dev = NULL;
412 struct cam_req_mgr_apply_request apply_req;
413 struct cam_req_mgr_link_evt_data evt_data;
414
415 apply_req.link_hdl = link->link_hdl;
416 apply_req.report_if_bubble = 0;
417
418 for (i = 0; i < link->num_devs; i++) {
419 dev = &link->l_dev[i];
420 if (dev) {
421 pd = dev->dev_info.p_delay;
422 if (pd >= CAM_PIPELINE_DELAY_MAX) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700423 CAM_WARN(CAM_CRM, "pd %d greater than max",
Sagar Gored79f95e2017-03-14 18:32:17 -0700424 pd);
425 continue;
426 }
427 if (link->req.apply_data[pd].skip_idx ||
428 link->req.apply_data[pd].req_id < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700429 CAM_DBG(CAM_CRM, "skip %d req_id %lld",
Sagar Gored79f95e2017-03-14 18:32:17 -0700430 link->req.apply_data[pd].skip_idx,
431 link->req.apply_data[pd].req_id);
432 continue;
433 }
Junzhe Zou2df84502017-05-26 13:20:23 -0700434 if (!(dev->dev_info.trigger & trigger))
435 continue;
436
Sagar Gored79f95e2017-03-14 18:32:17 -0700437 apply_req.dev_hdl = dev->dev_hdl;
438 apply_req.request_id =
439 link->req.apply_data[pd].req_id;
440 idx = link->req.apply_data[pd].idx;
441 apply_req.report_if_bubble =
442 in_q->slot[idx].recover;
Gregory Bergschneider60679932017-07-19 15:27:16 -0600443
444 trace_cam_req_mgr_apply_request(link, &apply_req, dev);
445
Junzhe Zou2df84502017-05-26 13:20:23 -0700446 apply_req.trigger_point = trigger;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700447 CAM_DBG(CAM_CRM, "SEND: pd %d req_id %lld",
Sagar Gored79f95e2017-03-14 18:32:17 -0700448 pd, apply_req.request_id);
449 if (dev->ops && dev->ops->apply_req) {
450 rc = dev->ops->apply_req(&apply_req);
451 if (rc < 0)
452 break;
453 }
454 }
455 }
456 if (rc < 0) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700457 CAM_ERR_RATE_LIMIT(CAM_CRM, "APPLY FAILED pd %d req_id %lld",
Sagar Gored79f95e2017-03-14 18:32:17 -0700458 dev->dev_info.p_delay, apply_req.request_id);
459 /* Apply req failed notify already applied devs */
460 for (; i >= 0; i--) {
461 dev = &link->l_dev[i];
462 evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_ERR;
463 evt_data.link_hdl = link->link_hdl;
464 evt_data.req_id = apply_req.request_id;
465 evt_data.u.error = CRM_KMD_ERR_BUBBLE;
466 if (dev->ops && dev->ops->process_evt)
467 dev->ops->process_evt(&evt_data);
468 }
469 }
470 return rc;
471}
472
473/**
474 * __cam_req_mgr_check_link_is_ready()
475 *
Venkat Chinta686c9e52018-01-20 14:33:25 -0800476 * @brief : traverse through all request tables and see if all devices are
477 * ready to apply request settings.
478 * @link : pointer to link whose input queue and req tbl are
479 * traversed through
480 * @idx : index within input request queue
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800481 * @validate_only : Whether to validate only and/or update settings
Sagar Gored79f95e2017-03-14 18:32:17 -0700482 *
483 * @return : 0 for success, negative for failure
484 *
485 */
486static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
Venkat Chintaddbe5132018-01-30 12:00:29 -0800487 int32_t idx, bool validate_only)
Sagar Gored79f95e2017-03-14 18:32:17 -0700488{
489 int rc;
490 struct cam_req_mgr_traverse traverse_data;
491 struct cam_req_mgr_req_queue *in_q;
492 struct cam_req_mgr_apply *apply_data;
493
494 in_q = link->req.in_q;
495
496 apply_data = link->req.apply_data;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800497
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800498 if (validate_only == false) {
499 memset(apply_data, 0,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800500 sizeof(struct cam_req_mgr_apply) * CAM_PIPELINE_DELAY_MAX);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800501 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700502
503 traverse_data.apply_data = apply_data;
504 traverse_data.idx = idx;
505 traverse_data.tbl = link->req.l_tbl;
506 traverse_data.in_q = in_q;
507 traverse_data.result = 0;
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800508 traverse_data.validate_only = validate_only;
Sagar Gored79f95e2017-03-14 18:32:17 -0700509 /*
510 * Traverse through all pd tables, if result is success,
511 * apply the settings
512 */
513
514 rc = __cam_req_mgr_traverse(&traverse_data);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700515 CAM_DBG(CAM_CRM, "SOF: idx %d result %x pd_mask %x rc %d",
Sagar Gored79f95e2017-03-14 18:32:17 -0700516 idx, traverse_data.result, link->pd_mask, rc);
517
Venkat Chintaddbe5132018-01-30 12:00:29 -0800518 if (!rc && traverse_data.result == link->pd_mask) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700519 CAM_DBG(CAM_CRM,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800520 "APPLY: link_hdl= %x idx= %d, validate_only=%d, req_id= %lld :%lld :%lld",
Sagar Gored79f95e2017-03-14 18:32:17 -0700521 link->link_hdl, idx,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800522 traverse_data.validate_only,
Sagar Gored79f95e2017-03-14 18:32:17 -0700523 apply_data[2].req_id, apply_data[1].req_id,
524 apply_data[0].req_id);
Venkat Chintaddbe5132018-01-30 12:00:29 -0800525 } else
526 rc = -EAGAIN;
Sagar Gored79f95e2017-03-14 18:32:17 -0700527
528 return rc;
529}
530
531/**
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800532 * __cam_req_mgr_find_slot_for_req()
533 *
534 * @brief : Find idx from input queue at which req id is enqueued
535 * @in_q : input request queue pointer
536 * @req_id : request id which needs to be searched in input queue
537 *
538 * @return : slot index where passed request id is stored, -1 for failure
539 *
540 */
541static int32_t __cam_req_mgr_find_slot_for_req(
542 struct cam_req_mgr_req_queue *in_q, int64_t req_id)
543{
544 int32_t idx, i;
545 struct cam_req_mgr_slot *slot;
546
547 idx = in_q->rd_idx;
548 for (i = 0; i < in_q->num_slots; i++) {
549 slot = &in_q->slot[idx];
550 if (slot->req_id == req_id) {
551 CAM_DBG(CAM_CRM,
552 "req: %lld found at idx: %d status: %d sync_mode: %d",
553 req_id, idx, slot->status, slot->sync_mode);
554 break;
555 }
556 __cam_req_mgr_dec_idx(&idx, 1, in_q->num_slots);
557 }
558 if (i >= in_q->num_slots)
559 idx = -1;
560
561 return idx;
562}
563
564/**
565 * __cam_req_mgr_reset_sof_cnt()
566 *
567 * @brief : the sof_count for both the links are reset
568 * @link : pointer to link whose input queue and req tbl are
569 * traversed through
570 *
571 */
572static void __cam_req_mgr_reset_sof_cnt(
573 struct cam_req_mgr_core_link *link)
574{
575 link->sof_counter = -1;
576 link->sync_link->sof_counter = -1;
577 link->frame_skip_flag = false;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800578
579 CAM_DBG(CAM_CRM,
580 "link_hdl %x self_counter %lld other_counter %lld frame_skip_lag %d",
581 link->link_hdl, link->sof_counter,
582 link->sync_link->sof_counter, link->frame_skip_flag);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800583}
584
585/**
586 * __cam_req_mgr_sof_cnt_initialize()
587 *
588 * @brief : when the sof count is intially -1 it increments count
589 * and computes the sync_self_ref for this link
590 * the count needs to be wrapped back starting from 0
591 * @link : pointer to link whose input queue and req tbl are
592 * traversed through
593 *
594 */
595static void __cam_req_mgr_sof_cnt_initialize(
596 struct cam_req_mgr_core_link *link)
597{
598 link->sof_counter++;
599 link->sync_self_ref = link->sof_counter -
600 link->sync_link->sof_counter;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800601
602 CAM_DBG(CAM_CRM,
603 "link_hdl %x self_counter %lld other_counter %lld",
604 link->link_hdl, link->sof_counter,
605 link->sync_link->sof_counter);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800606}
607
608/**
609 * __cam_req_mgr_wrap_sof_cnt()
610 *
611 * @brief : once the sof count reaches a predefined maximum
612 * the count needs to be wrapped back starting from 0
613 * @link : pointer to link whose input queue and req tbl are
614 * traversed through
615 *
616 */
617static void __cam_req_mgr_wrap_sof_cnt(
618 struct cam_req_mgr_core_link *link)
619{
620 link->sof_counter = (MAX_SYNC_COUNT -
621 (link->sync_link->sof_counter));
622 link->sync_link->sof_counter = 0;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800623
624 CAM_DBG(CAM_CRM,
625 "link_hdl %x self_counter %lld sync_link_hdl %x other_counter %lld",
626 link->link_hdl, link->sof_counter,
627 link->sync_link->link_hdl, link->sync_link->sof_counter);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800628}
629
630/**
631 * __cam_req_mgr_validate_sof_cnt()
632 *
633 * @brief : validates sof count difference for a given link
634 * @link : pointer to link whose input queue and req tbl are
635 * traversed through
636 * @sync_link : pointer to the sync link
637 * @return : 0 for success, negative for failure
638 *
639 */
640static int __cam_req_mgr_validate_sof_cnt(
641 struct cam_req_mgr_core_link *link,
642 struct cam_req_mgr_core_link *sync_link)
643{
644 int64_t sync_diff = 0;
645 int rc = 0;
646
647 if (link->sof_counter == MAX_SYNC_COUNT)
648 __cam_req_mgr_wrap_sof_cnt(link);
649
650 sync_diff = link->sof_counter - sync_link->sof_counter;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800651
652 CAM_DBG(CAM_CRM,
653 "link[%x] self_counter=%lld other_counter=%lld diff=%lld sync_self_ref=%lld",
654 link->link_hdl, link->sof_counter,
655 sync_link->sof_counter, sync_diff, link->sync_self_ref);
656
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800657 if (sync_diff != link->sync_self_ref) {
658 link->sync_link->frame_skip_flag = true;
659 CAM_WARN(CAM_CRM,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800660 "Detected anomaly, skip link_hdl %x self_counter=%lld other_counter=%lld sync_self_ref=%lld",
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800661 link->link_hdl, link->sof_counter,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800662 sync_link->sof_counter, link->sync_self_ref);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800663 rc = -EPERM;
664 }
665
666 return rc;
667}
668
669
670/**
671 * __cam_req_mgr_process_sync_req()
672 *
673 * @brief : processes requests during sync mode
674 * @link : pointer to link whose input queue and req tbl are
675 * traversed through
676 * @slot : pointer to the current slot being processed
677 * @return : 0 for success, negative for failure
678 *
679 */
680static int __cam_req_mgr_process_sync_req(
681 struct cam_req_mgr_core_link *link,
Venkat Chintaddbe5132018-01-30 12:00:29 -0800682 struct cam_req_mgr_slot *slot)
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800683{
684 struct cam_req_mgr_core_link *sync_link = NULL;
685 int64_t req_id = 0;
686 int sync_slot_idx = 0, rc = 0;
687
688 if (!link->sync_link) {
689 CAM_ERR(CAM_CRM, "Sync link null");
690 return -EINVAL;
691 }
692
693 sync_link = link->sync_link;
694 req_id = slot->req_id;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800695
696 CAM_DBG(CAM_CRM,
697 "link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld",
698 link->link_hdl, req_id, link->sync_self_ref, link->sof_counter,
699 link->frame_skip_flag, link->sync_link->sync_self_ref);
700
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800701 if (link->sof_counter == -1) {
702 __cam_req_mgr_sof_cnt_initialize(link);
Venkat Chinta686c9e52018-01-20 14:33:25 -0800703 } else if ((link->frame_skip_flag) &&
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800704 (sync_link->sync_self_ref != -1)) {
Venkat Chinta686c9e52018-01-20 14:33:25 -0800705 CAM_DBG(CAM_CRM, "Link[%x] Req[%lld] Resetting values ",
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800706 link->link_hdl, req_id);
707 __cam_req_mgr_reset_sof_cnt(link);
708 __cam_req_mgr_sof_cnt_initialize(link);
709 } else {
710 link->sof_counter++;
711 }
712
Venkat Chintaddbe5132018-01-30 12:00:29 -0800713 rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800714 if (rc) {
715 CAM_DBG(CAM_CRM,
716 "Req: %lld [My link]not available link: %x, rc=%d",
717 req_id, link->link_hdl, rc);
718 goto failure;
719 }
720
721 sync_slot_idx = __cam_req_mgr_find_slot_for_req(
722 sync_link->req.in_q, req_id);
Venkat Chinta686c9e52018-01-20 14:33:25 -0800723
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800724 if (sync_slot_idx != -1) {
725 rc = __cam_req_mgr_check_link_is_ready(
Venkat Chintaddbe5132018-01-30 12:00:29 -0800726 sync_link, sync_slot_idx, true);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800727 CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d",
728 sync_slot_idx,
729 sync_link->req.in_q->slot[sync_slot_idx].status,
730 rc);
731 } else {
732 CAM_DBG(CAM_CRM, "sync_slot_idx=%d, rc=%d",
733 sync_slot_idx, rc);
734 }
735
736 if ((sync_slot_idx != -1) &&
Venkat Chintaddbe5132018-01-30 12:00:29 -0800737 ((sync_link->req.in_q->slot[sync_slot_idx].status ==
738 CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800739 rc = __cam_req_mgr_validate_sof_cnt(link, sync_link);
740 if (rc) {
741 CAM_DBG(CAM_CRM,
742 "Req: %lld validate failed: %x",
743 req_id, sync_link->link_hdl);
744 goto failure;
745 }
Venkat Chintaddbe5132018-01-30 12:00:29 -0800746 __cam_req_mgr_check_link_is_ready(link, slot->idx, false);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800747 } else {
748 CAM_DBG(CAM_CRM,
749 "Req: %lld [Other link] not ready to apply on link: %x",
750 req_id, sync_link->link_hdl);
751 rc = -EPERM;
752 goto failure;
753 }
754
755 return rc;
756
757failure:
758 link->sof_counter--;
759 return rc;
760}
761
762/**
Sagar Gored79f95e2017-03-14 18:32:17 -0700763 * __cam_req_mgr_process_req()
764 *
765 * @brief : processes read index in request queue and traverse through table
766 * @link : pointer to link whose input queue and req tbl are
767 * traversed through
768 *
769 * @return : 0 for success, negative for failure
770 *
771 */
Junzhe Zou2df84502017-05-26 13:20:23 -0700772static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
773 uint32_t trigger)
Sagar Gored79f95e2017-03-14 18:32:17 -0700774{
Venkat Chintaddbe5132018-01-30 12:00:29 -0800775 int rc = 0, idx;
Sagar Gored79f95e2017-03-14 18:32:17 -0700776 struct cam_req_mgr_slot *slot = NULL;
777 struct cam_req_mgr_req_queue *in_q;
778 struct cam_req_mgr_core_session *session;
779
780 in_q = link->req.in_q;
781 session = (struct cam_req_mgr_core_session *)link->parent;
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800782 mutex_lock(&session->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -0700783 /*
Junzhe Zou2df84502017-05-26 13:20:23 -0700784 * Check if new read index,
Sagar Gored79f95e2017-03-14 18:32:17 -0700785 * - if in pending state, traverse again to complete
786 * transaction of this read index.
787 * - if in applied_state, somthign wrong.
788 * - if in no_req state, no new req
789 */
Venkat Chinta686c9e52018-01-20 14:33:25 -0800790 CAM_DBG(CAM_CRM, "SOF Req[%lld] idx %d req_status %d link_hdl %x",
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800791 in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800792 in_q->slot[in_q->rd_idx].status, link->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -0700793
794 slot = &in_q->slot[in_q->rd_idx];
795 if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700796 CAM_DBG(CAM_CRM, "No Pending req");
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800797 rc = 0;
798 goto error;
Sagar Gored79f95e2017-03-14 18:32:17 -0700799 }
800
Venkat Chinta686c9e52018-01-20 14:33:25 -0800801 if ((trigger != CAM_TRIGGER_POINT_SOF) &&
802 (trigger != CAM_TRIGGER_POINT_EOF))
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800803 goto error;
804
805 if ((trigger == CAM_TRIGGER_POINT_EOF) &&
806 (!(link->trigger_mask & CAM_TRIGGER_POINT_SOF))) {
807 CAM_DBG(CAM_CRM, "Applying for last SOF fails");
808 rc = -EINVAL;
809 goto error;
810 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700811
Junzhe Zou2df84502017-05-26 13:20:23 -0700812 if (trigger == CAM_TRIGGER_POINT_SOF) {
Junzhe Zou3f77d832017-08-25 14:55:23 -0700813 if (link->trigger_mask) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700814 CAM_ERR_RATE_LIMIT(CAM_CRM,
815 "Applying for last EOF fails");
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800816 rc = -EINVAL;
817 goto error;
Junzhe Zou2df84502017-05-26 13:20:23 -0700818 }
Junzhe Zou2df84502017-05-26 13:20:23 -0700819
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800820 if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)
Venkat Chintaddbe5132018-01-30 12:00:29 -0800821 rc = __cam_req_mgr_process_sync_req(link, slot);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800822 else
823 rc = __cam_req_mgr_check_link_is_ready(link,
Venkat Chintaddbe5132018-01-30 12:00:29 -0800824 slot->idx, false);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800825
826 if (rc < 0) {
827 /*
828 * If traverse result is not success, then some devices
829 * are not ready with packet for the asked request id,
830 * hence try again in next sof
831 */
Junzhe Zou2df84502017-05-26 13:20:23 -0700832 slot->status = CRM_SLOT_STATUS_REQ_PENDING;
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +0530833 spin_lock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -0700834 if (link->state == CAM_CRM_LINK_STATE_ERR) {
Junzhe Zou2df84502017-05-26 13:20:23 -0700835 /*
836 * During error recovery all tables should be
837 * ready, don't expect to enter here.
838 * @TODO: gracefully handle if recovery fails.
839 */
Harsh Shahcb0072c2017-09-26 19:22:10 -0700840 CAM_ERR_RATE_LIMIT(CAM_CRM,
Junzhe Zou2df84502017-05-26 13:20:23 -0700841 "FATAL recovery cant finish idx %d status %d",
Sagar Gored79f95e2017-03-14 18:32:17 -0700842 in_q->rd_idx,
843 in_q->slot[in_q->rd_idx].status);
Junzhe Zou2df84502017-05-26 13:20:23 -0700844 rc = -EPERM;
Sagar Gored79f95e2017-03-14 18:32:17 -0700845 }
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +0530846 spin_unlock_bh(&link->link_state_spin_lock);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800847 goto error;
Junzhe Zou2df84502017-05-26 13:20:23 -0700848 }
849 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700850
Junzhe Zou2df84502017-05-26 13:20:23 -0700851 rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger);
852 if (rc < 0) {
853 /* Apply req failed retry at next sof */
854 slot->status = CRM_SLOT_STATUS_REQ_PENDING;
855 } else {
856 link->trigger_mask |= trigger;
857
Venkat Chinta686c9e52018-01-20 14:33:25 -0800858 CAM_DBG(CAM_CRM, "Applied req[%lld] on link[%x] success",
859 slot->req_id, link->link_hdl);
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +0530860 spin_lock_bh(&link->link_state_spin_lock);
Junzhe Zou2df84502017-05-26 13:20:23 -0700861 if (link->state == CAM_CRM_LINK_STATE_ERR) {
862 CAM_WARN(CAM_CRM, "Err recovery done idx %d",
863 in_q->rd_idx);
Junzhe Zou2df84502017-05-26 13:20:23 -0700864 link->state = CAM_CRM_LINK_STATE_READY;
Junzhe Zou2df84502017-05-26 13:20:23 -0700865 }
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +0530866 spin_unlock_bh(&link->link_state_spin_lock);
867
Junzhe Zou2df84502017-05-26 13:20:23 -0700868 if (link->trigger_mask == link->subscribe_event) {
Venkat Chintaddbe5132018-01-30 12:00:29 -0800869 slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
Junzhe Zou2df84502017-05-26 13:20:23 -0700870 link->trigger_mask = 0;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800871 CAM_DBG(CAM_CRM, "req %d is applied on link %x",
Venkat Chintaddbe5132018-01-30 12:00:29 -0800872 slot->req_id,
873 link->link_hdl);
874 idx = in_q->rd_idx;
875 __cam_req_mgr_dec_idx(
876 &idx, link->max_delay + 1,
877 in_q->num_slots);
878 __cam_req_mgr_reset_req_slot(link, idx);
Sagar Gored79f95e2017-03-14 18:32:17 -0700879 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700880 }
Venkat Chinta686c9e52018-01-20 14:33:25 -0800881
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800882 mutex_unlock(&session->lock);
883 return rc;
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800884error:
885 mutex_unlock(&session->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -0700886 return rc;
887}
888
889/**
890 * __cam_req_mgr_add_tbl_to_link()
891 *
892 * @brief : Add table to list under link sorted by pd decremeting order
893 * @l_tbl : list of pipeline delay tables.
Junzhe Zou2df84502017-05-26 13:20:23 -0700894 * @new_tbl : new tbl which will be appended to above list as per its pd value
Sagar Gored79f95e2017-03-14 18:32:17 -0700895 *
896 */
897static void __cam_req_mgr_add_tbl_to_link(struct cam_req_mgr_req_tbl **l_tbl,
898 struct cam_req_mgr_req_tbl *new_tbl)
899{
900 struct cam_req_mgr_req_tbl *tbl;
901
902 if (!(*l_tbl) || (*l_tbl)->pd < new_tbl->pd) {
903 new_tbl->next = *l_tbl;
904 if (*l_tbl) {
905 new_tbl->pd_delta =
906 new_tbl->pd - (*l_tbl)->pd;
907 }
908 *l_tbl = new_tbl;
909 } else {
910 tbl = *l_tbl;
911
912 /* Reach existing tbl which has less pd value */
913 while (tbl->next != NULL &&
914 new_tbl->pd < tbl->next->pd) {
915 tbl = tbl->next;
916 }
917 if (tbl->next != NULL) {
918 new_tbl->pd_delta =
919 new_tbl->pd - tbl->next->pd;
920 } else {
921 /* This is last table in linked list*/
922 new_tbl->pd_delta = 0;
923 }
924 new_tbl->next = tbl->next;
925 tbl->next = new_tbl;
926 tbl->pd_delta = tbl->pd - new_tbl->pd;
927 }
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700928 CAM_DBG(CAM_CRM, "added pd %d tbl to link delta %d", new_tbl->pd,
Sagar Gored79f95e2017-03-14 18:32:17 -0700929 new_tbl->pd_delta);
930}
931
932/**
933 * __cam_req_mgr_create_pd_tbl()
934 *
935 * @brief : Creates new request table for new delay value
936 * @delay : New pd table allocated will have this delay value
937 *
938 * @return : pointer to newly allocated table, NULL for failure
939 *
940 */
941static struct cam_req_mgr_req_tbl *__cam_req_mgr_create_pd_tbl(int32_t delay)
942{
943 struct cam_req_mgr_req_tbl *tbl =
944 kzalloc(sizeof(struct cam_req_mgr_req_tbl), GFP_KERNEL);
945 if (tbl != NULL) {
946 tbl->num_slots = MAX_REQ_SLOTS;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700947 CAM_DBG(CAM_CRM, "pd= %d slots= %d", delay, tbl->num_slots);
Sagar Gored79f95e2017-03-14 18:32:17 -0700948 }
949
950 return tbl;
951}
952
953/**
954 * __cam_req_mgr_destroy_all_tbl()
955 *
956 * @brief : This func will destroy all pipeline delay based req table structs
957 * @l_tbl : pointer to first table in list and it has max pd .
958 *
959 */
960static void __cam_req_mgr_destroy_all_tbl(struct cam_req_mgr_req_tbl **l_tbl)
961{
962 struct cam_req_mgr_req_tbl *tbl = *l_tbl, *temp;
963
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700964 CAM_DBG(CAM_CRM, "*l_tbl %pK", tbl);
Sagar Gored79f95e2017-03-14 18:32:17 -0700965 while (tbl != NULL) {
966 temp = tbl->next;
967 kfree(tbl);
968 tbl = temp;
969 }
970 *l_tbl = NULL;
971}
972
973/**
Sagar Gored79f95e2017-03-14 18:32:17 -0700974 * __cam_req_mgr_setup_in_q()
975 *
976 * @brief : Initialize req table data
977 * @req : request data pointer
978 *
979 * @return: 0 for success, negative for failure
980 *
981 */
982static int __cam_req_mgr_setup_in_q(struct cam_req_mgr_req_data *req)
983{
984 int i;
985 struct cam_req_mgr_req_queue *in_q = req->in_q;
986
987 if (!in_q) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700988 CAM_ERR(CAM_CRM, "NULL in_q");
Sagar Gored79f95e2017-03-14 18:32:17 -0700989 return -EINVAL;
990 }
991
992 mutex_lock(&req->lock);
993 in_q->num_slots = MAX_REQ_SLOTS;
994
995 for (i = 0; i < in_q->num_slots; i++) {
996 in_q->slot[i].idx = i;
997 in_q->slot[i].req_id = -1;
998 in_q->slot[i].skip_idx = 0;
999 in_q->slot[i].status = CRM_SLOT_STATUS_NO_REQ;
1000 }
1001
1002 in_q->wr_idx = 0;
1003 in_q->rd_idx = 0;
1004 mutex_unlock(&req->lock);
1005
1006 return 0;
1007}
1008
1009/**
1010 * __cam_req_mgr_reset_req_tbl()
1011 *
1012 * @brief : Initialize req table data
1013 * @req : request queue pointer
1014 *
1015 * @return: 0 for success, negative for failure
1016 *
1017 */
1018static int __cam_req_mgr_reset_in_q(struct cam_req_mgr_req_data *req)
1019{
1020 struct cam_req_mgr_req_queue *in_q = req->in_q;
1021
1022 if (!in_q) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001023 CAM_ERR(CAM_CRM, "NULL in_q");
Sagar Gored79f95e2017-03-14 18:32:17 -07001024 return -EINVAL;
1025 }
1026
1027 mutex_lock(&req->lock);
1028 memset(in_q->slot, 0,
1029 sizeof(struct cam_req_mgr_slot) * in_q->num_slots);
1030 in_q->num_slots = 0;
1031
1032 in_q->wr_idx = 0;
1033 in_q->rd_idx = 0;
1034 mutex_unlock(&req->lock);
1035
1036 return 0;
1037}
1038
1039/**
1040 * __cam_req_mgr_sof_freeze()
1041 *
1042 * @brief : Apoptosis - Handles case when connected devices are not responding
1043 * @data : timer pointer
1044 *
1045 */
1046static void __cam_req_mgr_sof_freeze(unsigned long data)
1047{
Harsh Shah67fa2312017-10-30 04:03:07 -07001048 struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
1049 struct cam_req_mgr_core_link *link = NULL;
1050 struct cam_req_mgr_core_session *session = NULL;
1051 struct cam_req_mgr_message msg;
Sagar Gore8d91a622017-02-23 14:57:18 -08001052
Sagar Gored79f95e2017-03-14 18:32:17 -07001053 if (!timer) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001054 CAM_ERR(CAM_CRM, "NULL timer");
Sagar Gored79f95e2017-03-14 18:32:17 -07001055 return;
1056 }
1057 link = (struct cam_req_mgr_core_link *)timer->parent;
Harsh Shah67fa2312017-10-30 04:03:07 -07001058 session = (struct cam_req_mgr_core_session *)link->parent;
1059
1060 CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x",
1061 session->session_hdl, link->link_hdl);
1062
1063 memset(&msg, 0, sizeof(msg));
1064
1065 msg.session_hdl = session->session_hdl;
1066 msg.u.err_msg.error_type = CAM_REQ_MGR_ERROR_TYPE_DEVICE;
1067 msg.u.err_msg.request_id = 0;
1068 msg.u.err_msg.link_hdl = link->link_hdl;
1069
1070
1071 if (cam_req_mgr_notify_message(&msg,
1072 V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT))
1073 CAM_ERR(CAM_CRM,
1074 "Error notifying SOF freeze for session %d link 0x%x",
1075 session->session_hdl, link->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07001076}
1077
1078/**
1079 * __cam_req_mgr_create_subdevs()
1080 *
1081 * @brief : Create new crm subdev to link with realtime devices
1082 * @l_dev : list of subdevs internal to crm
1083 * @num_dev : num of subdevs to be created for link
1084 *
1085 * @return : pointer to allocated list of devices
1086 */
1087static int __cam_req_mgr_create_subdevs(
1088 struct cam_req_mgr_connected_device **l_dev, int32_t num_dev)
1089{
1090 int rc = 0;
1091 *l_dev = (struct cam_req_mgr_connected_device *)
1092 kzalloc(sizeof(struct cam_req_mgr_connected_device) * num_dev,
1093 GFP_KERNEL);
1094 if (!*l_dev)
1095 rc = -ENOMEM;
1096
1097 return rc;
1098}
1099
1100/**
1101 * __cam_req_mgr_destroy_subdev()
1102 *
1103 * @brief : Cleans up the subdevs allocated by crm for link
1104 * @l_device : pointer to list of subdevs crm created
1105 *
1106 */
1107static void __cam_req_mgr_destroy_subdev(
1108 struct cam_req_mgr_connected_device *l_device)
1109{
1110 kfree(l_device);
1111 l_device = NULL;
1112}
1113
1114/**
1115 * __cam_req_mgr_destroy_link_info()
1116 *
1117 * @brief : Cleans up the mem allocated while linking
1118 * @link : pointer to link, mem associated with this link is freed
1119 *
Venkat Chinta686c9e52018-01-20 14:33:25 -08001120 * @return : returns if unlink for any device was success or failure
Sagar Gored79f95e2017-03-14 18:32:17 -07001121 */
Venkat Chinta686c9e52018-01-20 14:33:25 -08001122static int __cam_req_mgr_destroy_link_info(struct cam_req_mgr_core_link *link)
Sagar Gored79f95e2017-03-14 18:32:17 -07001123{
1124 int32_t i = 0;
1125 struct cam_req_mgr_connected_device *dev;
1126 struct cam_req_mgr_core_dev_link_setup link_data;
Harsh Shaha606d182017-11-10 00:15:58 -08001127 int rc = 0;
Sagar Gored79f95e2017-03-14 18:32:17 -07001128
Sagar Gored79f95e2017-03-14 18:32:17 -07001129 link_data.link_enable = 0;
1130 link_data.link_hdl = link->link_hdl;
1131 link_data.crm_cb = NULL;
Junzhe Zou2df84502017-05-26 13:20:23 -07001132 link_data.subscribe_event = 0;
Sagar Gored79f95e2017-03-14 18:32:17 -07001133
1134 /* Using device ops unlink devices */
1135 for (i = 0; i < link->num_devs; i++) {
1136 dev = &link->l_dev[i];
1137 if (dev != NULL) {
Soundrapandian Jeyaprakash74946262017-08-11 18:23:47 -07001138 link_data.dev_hdl = dev->dev_hdl;
Lynus Vaz345e6a02017-12-04 17:02:12 +05301139 if (dev->ops && dev->ops->link_setup) {
Harsh Shaha606d182017-11-10 00:15:58 -08001140 rc = dev->ops->link_setup(&link_data);
1141 if (rc)
1142 CAM_ERR(CAM_CRM,
Venkat Chinta686c9e52018-01-20 14:33:25 -08001143 "Unlink failed dev_hdl %d",
1144 dev->dev_hdl);
Lynus Vaz345e6a02017-12-04 17:02:12 +05301145 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001146 dev->dev_hdl = 0;
1147 dev->parent = NULL;
1148 dev->ops = NULL;
1149 }
1150 }
1151 __cam_req_mgr_destroy_all_tbl(&link->req.l_tbl);
1152 __cam_req_mgr_reset_in_q(&link->req);
1153 link->req.num_tbl = 0;
1154 mutex_destroy(&link->req.lock);
1155
1156 link->pd_mask = 0;
1157 link->num_devs = 0;
1158 link->max_delay = 0;
Venkat Chinta686c9e52018-01-20 14:33:25 -08001159
1160 return rc;
Sagar Gored79f95e2017-03-14 18:32:17 -07001161}
1162
1163/**
1164 * __cam_req_mgr_reserve_link()
1165 *
1166 * @brief: Reserves one link data struct within session
1167 * @session: session identifier
1168 *
1169 * @return: pointer to link reserved
1170 *
1171 */
1172static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
1173 struct cam_req_mgr_core_session *session)
1174{
1175 struct cam_req_mgr_core_link *link;
1176 struct cam_req_mgr_req_queue *in_q;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001177 int i;
Sagar Gored79f95e2017-03-14 18:32:17 -07001178
1179 if (!session || !g_crm_core_dev) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001180 CAM_ERR(CAM_CRM, "NULL session/core_dev ptr");
Sagar Gore8d91a622017-02-23 14:57:18 -08001181 return NULL;
1182 }
1183
Sagar Gored79f95e2017-03-14 18:32:17 -07001184 if (session->num_links >= MAX_LINKS_PER_SESSION) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001185 CAM_ERR(CAM_CRM, "Reached max links %d per session limit %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001186 session->num_links, MAX_LINKS_PER_SESSION);
1187 return NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001188 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001189
1190 link = (struct cam_req_mgr_core_link *)
1191 kzalloc(sizeof(struct cam_req_mgr_core_link), GFP_KERNEL);
1192 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001193 CAM_ERR(CAM_CRM, "failed to create link, no mem");
Sagar Gored79f95e2017-03-14 18:32:17 -07001194 return NULL;
1195 }
Sagar Gored46e67d2017-08-31 17:05:46 -07001196 in_q = (struct cam_req_mgr_req_queue *)
1197 kzalloc(sizeof(struct cam_req_mgr_req_queue), GFP_KERNEL);
1198 if (!in_q) {
1199 CAM_ERR(CAM_CRM, "failed to create input queue, no mem");
1200 kfree(link);
1201 return NULL;
1202 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001203 mutex_init(&link->lock);
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301204 spin_lock_init(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001205
1206 mutex_lock(&link->lock);
1207 link->state = CAM_CRM_LINK_STATE_AVAILABLE;
1208 link->num_devs = 0;
1209 link->max_delay = 0;
1210 memset(in_q->slot, 0,
1211 sizeof(struct cam_req_mgr_slot) * MAX_REQ_SLOTS);
1212 link->req.in_q = in_q;
1213 in_q->num_slots = 0;
1214 link->state = CAM_CRM_LINK_STATE_IDLE;
1215 link->parent = (void *)session;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001216 link->sync_link = NULL;
Sagar Gored79f95e2017-03-14 18:32:17 -07001217 mutex_unlock(&link->lock);
1218
1219 mutex_lock(&session->lock);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001220 /* Loop through and find a free index */
1221 for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
1222 if (!session->links[i]) {
Venkat Chinta686c9e52018-01-20 14:33:25 -08001223 CAM_DBG(CAM_CRM,
1224 "Free link index %d found, num_links=%d",
1225 i, session->num_links);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001226 session->links[i] = link;
1227 break;
1228 }
1229 }
1230
1231 if (i == MAX_LINKS_PER_SESSION) {
1232 CAM_ERR(CAM_CRM, "Free link index not found");
1233 goto error;
1234 }
1235
Sagar Gored79f95e2017-03-14 18:32:17 -07001236 session->num_links++;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001237 CAM_DBG(CAM_CRM, "Active session links (%d)",
Sagar Gored79f95e2017-03-14 18:32:17 -07001238 session->num_links);
1239 mutex_unlock(&session->lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08001240
1241 return link;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001242error:
1243 mutex_unlock(&session->lock);
1244 kfree(link);
1245 kfree(in_q);
1246 return NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001247}
1248
Sunil Khatribc029f72017-11-28 18:54:24 +05301249/*
1250 * __cam_req_mgr_free_link()
1251 *
1252 * @brief: Frees the link and its request queue
1253 *
1254 * @link: link identifier
1255 *
1256 */
1257static void __cam_req_mgr_free_link(struct cam_req_mgr_core_link *link)
1258{
1259 kfree(link->req.in_q);
1260 link->req.in_q = NULL;
1261 kfree(link);
1262}
1263
Sagar Gore8d91a622017-02-23 14:57:18 -08001264/**
Sagar Gored46e67d2017-08-31 17:05:46 -07001265 * __cam_req_mgr_unreserve_link()
Sagar Gored79f95e2017-03-14 18:32:17 -07001266 *
Sunil Khatribc029f72017-11-28 18:54:24 +05301267 * @brief : Removes the link data struct from the session and frees it
Sagar Gored79f95e2017-03-14 18:32:17 -07001268 * @session: session identifier
1269 * @link : link identifier
1270 *
1271 */
1272static void __cam_req_mgr_unreserve_link(
1273 struct cam_req_mgr_core_session *session,
Sunil Khatribc029f72017-11-28 18:54:24 +05301274 struct cam_req_mgr_core_link *link)
Sagar Gored79f95e2017-03-14 18:32:17 -07001275{
Sunil Khatribc029f72017-11-28 18:54:24 +05301276 int i;
Sagar Gored79f95e2017-03-14 18:32:17 -07001277
Sunil Khatribc029f72017-11-28 18:54:24 +05301278 if (!session || !link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001279 CAM_ERR(CAM_CRM, "NULL session/link ptr %pK %pK",
Sunil Khatribc029f72017-11-28 18:54:24 +05301280 session, link);
Sagar Gored79f95e2017-03-14 18:32:17 -07001281 return;
1282 }
1283
1284 mutex_lock(&session->lock);
Sunil Khatribc029f72017-11-28 18:54:24 +05301285 if (!session->num_links) {
1286 CAM_WARN(CAM_CRM, "No active link or invalid state: hdl %x",
1287 link->link_hdl);
1288 mutex_unlock(&session->lock);
1289 return;
Sagar Gored79f95e2017-03-14 18:32:17 -07001290 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001291
Sunil Khatribc029f72017-11-28 18:54:24 +05301292 for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
1293 if (session->links[i] == link)
1294 session->links[i] = NULL;
1295 }
1296
1297 if ((session->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC) &&
1298 (link->sync_link)) {
1299 /*
1300 * make sure to unlink sync setup under the assumption
1301 * of only having 2 links in a given session
1302 */
1303 session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
1304 for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
1305 if (session->links[i])
1306 session->links[i]->sync_link = NULL;
1307 }
1308 }
1309
1310 session->num_links--;
1311 CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links);
1312 mutex_unlock(&session->lock);
1313 __cam_req_mgr_free_link(link);
Sagar Gored79f95e2017-03-14 18:32:17 -07001314}
1315
1316/* Workqueue context processing section */
1317
1318/**
1319 * cam_req_mgr_process_send_req()
1320 *
1321 * @brief: This runs in workque thread context. Call core funcs to send
1322 * apply request id to drivers.
1323 * @priv : link information.
1324 * @data : contains information about frame_id, link etc.
1325 *
1326 * @return: 0 on success.
1327 */
1328int cam_req_mgr_process_send_req(void *priv, void *data)
1329{
1330 int rc = 0;
1331 struct cam_req_mgr_core_link *link = NULL;
1332 struct cam_req_mgr_send_request *send_req = NULL;
1333 struct cam_req_mgr_req_queue *in_q = NULL;
1334
1335 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001336 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001337 rc = -EINVAL;
1338 goto end;
1339 }
1340 link = (struct cam_req_mgr_core_link *)priv;
1341 send_req = (struct cam_req_mgr_send_request *)data;
1342 in_q = send_req->in_q;
1343
Junzhe Zou2df84502017-05-26 13:20:23 -07001344 rc = __cam_req_mgr_send_req(link, in_q, CAM_TRIGGER_POINT_SOF);
Sagar Gored79f95e2017-03-14 18:32:17 -07001345end:
1346 return rc;
1347}
1348
1349/**
1350 * cam_req_mgr_process_flush_req()
1351 *
1352 * @brief: This runs in workque thread context. Call core funcs to check
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001353 * which requests need to be removed/cancelled.
Sagar Gored79f95e2017-03-14 18:32:17 -07001354 * @priv : link information.
1355 * @data : contains information about frame_id, link etc.
1356 *
1357 * @return: 0 on success.
1358 */
1359int cam_req_mgr_process_flush_req(void *priv, void *data)
1360{
1361 int rc = 0, i = 0, idx = -1;
1362 struct cam_req_mgr_flush_info *flush_info = NULL;
1363 struct cam_req_mgr_core_link *link = NULL;
1364 struct cam_req_mgr_req_queue *in_q = NULL;
1365 struct cam_req_mgr_slot *slot = NULL;
1366 struct cam_req_mgr_connected_device *device = NULL;
1367 struct cam_req_mgr_flush_request flush_req;
1368 struct crm_task_payload *task_data = NULL;
1369
1370 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001371 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001372 rc = -EINVAL;
1373 goto end;
1374 }
1375 link = (struct cam_req_mgr_core_link *)priv;
1376 task_data = (struct crm_task_payload *)data;
1377 flush_info = (struct cam_req_mgr_flush_info *)&task_data->u;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001378 CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld type %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001379 flush_info->link_hdl,
1380 flush_info->req_id,
1381 flush_info->flush_type);
1382
1383 in_q = link->req.in_q;
1384
Gregory Bergschneider60679932017-07-19 15:27:16 -06001385 trace_cam_flush_req(link, flush_info);
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001386
Sagar Gored79f95e2017-03-14 18:32:17 -07001387 mutex_lock(&link->req.lock);
1388 if (flush_info->flush_type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
1389 for (i = 0; i < in_q->num_slots; i++) {
1390 slot = &in_q->slot[i];
1391 slot->req_id = -1;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001392 slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
Sagar Gored79f95e2017-03-14 18:32:17 -07001393 slot->skip_idx = 1;
1394 slot->status = CRM_SLOT_STATUS_NO_REQ;
1395 }
1396 in_q->wr_idx = 0;
1397 in_q->rd_idx = 0;
1398 } else if (flush_info->flush_type ==
1399 CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
1400 idx = __cam_req_mgr_find_slot_for_req(in_q, flush_info->req_id);
1401 if (idx < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001402 CAM_ERR(CAM_CRM, "req_id %lld not found in input queue",
Sagar Gored79f95e2017-03-14 18:32:17 -07001403 flush_info->req_id);
1404 } else {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001405 CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001406 flush_info->req_id, idx);
1407 slot = &in_q->slot[idx];
1408 if (slot->status == CRM_SLOT_STATUS_REQ_PENDING ||
1409 slot->status == CRM_SLOT_STATUS_REQ_APPLIED) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001410 CAM_WARN(CAM_CRM,
1411 "req_id %lld can not be cancelled",
Sagar Gored79f95e2017-03-14 18:32:17 -07001412 flush_info->req_id);
1413 mutex_unlock(&link->req.lock);
1414 return -EINVAL;
1415 }
1416 __cam_req_mgr_in_q_skip_idx(in_q, idx);
1417 }
1418 }
1419
1420 for (i = 0; i < link->num_devs; i++) {
1421 device = &link->l_dev[i];
1422 flush_req.link_hdl = flush_info->link_hdl;
1423 flush_req.dev_hdl = device->dev_hdl;
1424 flush_req.req_id = flush_info->req_id;
1425 flush_req.type = flush_info->flush_type;
1426 /* @TODO: error return handling from drivers */
1427 if (device->ops && device->ops->flush_req)
1428 rc = device->ops->flush_req(&flush_req);
1429 }
Alok Pandeya6bde9e2018-02-02 10:14:19 +05301430 complete(&link->workq_comp);
Sagar Gored79f95e2017-03-14 18:32:17 -07001431 mutex_unlock(&link->req.lock);
1432
Sagar Gored79f95e2017-03-14 18:32:17 -07001433end:
1434 return rc;
1435}
1436
1437/**
1438 * cam_req_mgr_process_sched_req()
1439 *
1440 * @brief: This runs in workque thread context. Call core funcs to check
1441 * which peding requests can be processed.
1442 * @priv : link information.
1443 * @data : contains information about frame_id, link etc.
1444 *
1445 * @return: 0 on success.
1446 */
1447int cam_req_mgr_process_sched_req(void *priv, void *data)
1448{
1449 int rc = 0;
1450 struct cam_req_mgr_sched_request *sched_req = NULL;
1451 struct cam_req_mgr_core_link *link = NULL;
1452 struct cam_req_mgr_req_queue *in_q = NULL;
1453 struct cam_req_mgr_slot *slot = NULL;
1454 struct crm_task_payload *task_data = NULL;
1455
1456 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001457 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001458 rc = -EINVAL;
1459 goto end;
1460 }
1461 link = (struct cam_req_mgr_core_link *)priv;
1462 task_data = (struct crm_task_payload *)data;
1463 sched_req = (struct cam_req_mgr_sched_request *)&task_data->u;
Sagar Gored79f95e2017-03-14 18:32:17 -07001464 in_q = link->req.in_q;
1465
Venkat Chinta686c9e52018-01-20 14:33:25 -08001466 CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld at slot %d sync_mode %d",
1467 sched_req->link_hdl, sched_req->req_id,
1468 in_q->wr_idx, sched_req->sync_mode);
1469
Sagar Gored79f95e2017-03-14 18:32:17 -07001470 mutex_lock(&link->req.lock);
1471 slot = &in_q->slot[in_q->wr_idx];
1472
1473 if (slot->status != CRM_SLOT_STATUS_NO_REQ &&
Sagar Goreb56c81e2017-05-08 17:15:47 -07001474 slot->status != CRM_SLOT_STATUS_REQ_APPLIED)
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001475 CAM_WARN(CAM_CRM, "in_q overwrite %d", slot->status);
Sagar Goreb56c81e2017-05-08 17:15:47 -07001476
Sagar Gored79f95e2017-03-14 18:32:17 -07001477 slot->status = CRM_SLOT_STATUS_REQ_ADDED;
1478 slot->req_id = sched_req->req_id;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001479 slot->sync_mode = sched_req->sync_mode;
Sagar Gored79f95e2017-03-14 18:32:17 -07001480 slot->skip_idx = 0;
1481 slot->recover = sched_req->bubble_enable;
1482 __cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
1483 mutex_unlock(&link->req.lock);
1484
Sagar Gored79f95e2017-03-14 18:32:17 -07001485end:
1486 return rc;
1487}
1488
1489/**
1490 * cam_req_mgr_process_add_req()
1491 *
1492 * @brief: This runs in workque thread context. Call core funcs to check
1493 * which peding requests can be processed.
1494 * @priv : link information.
1495 * @data : contains information about frame_id, link etc.
1496 *
1497 * @return: 0 on success.
1498 */
1499int cam_req_mgr_process_add_req(void *priv, void *data)
1500{
1501 int rc = 0, i = 0, idx;
1502 struct cam_req_mgr_add_request *add_req = NULL;
1503 struct cam_req_mgr_core_link *link = NULL;
1504 struct cam_req_mgr_connected_device *device = NULL;
1505 struct cam_req_mgr_req_tbl *tbl = NULL;
1506 struct cam_req_mgr_tbl_slot *slot = NULL;
1507 struct crm_task_payload *task_data = NULL;
1508
1509 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001510 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001511 rc = -EINVAL;
1512 goto end;
1513 }
1514
1515 link = (struct cam_req_mgr_core_link *)priv;
1516 task_data = (struct crm_task_payload *)data;
1517 add_req = (struct cam_req_mgr_add_request *)&task_data->u;
1518
1519 for (i = 0; i < link->num_devs; i++) {
1520 device = &link->l_dev[i];
1521 if (device->dev_hdl == add_req->dev_hdl) {
1522 tbl = device->pd_tbl;
1523 break;
1524 }
1525 }
1526 if (!tbl) {
Harsh Shahcb0072c2017-09-26 19:22:10 -07001527 CAM_ERR_RATE_LIMIT(CAM_CRM, "dev_hdl not found %x, %x %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07001528 add_req->dev_hdl,
1529 link->l_dev[0].dev_hdl,
1530 link->l_dev[1].dev_hdl);
1531 rc = -EINVAL;
1532 goto end;
1533 }
1534 /*
1535 * Go through request table and add
1536 * request id to proper table
1537 * 1. find req slot in in_q matching req_id.sent by dev
1538 * 2. goto table of this device based on p_delay
1539 * 3. mark req_ready_map with this dev_bit.
1540 */
1541
1542 mutex_lock(&link->req.lock);
1543 idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id);
1544 if (idx < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001545 CAM_ERR(CAM_CRM, "req %lld not found in in_q", add_req->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001546 rc = -EBADSLT;
1547 mutex_unlock(&link->req.lock);
1548 goto end;
1549 }
Sagar Gorea4d7dfd2017-09-13 19:56:24 -07001550
1551 if (add_req->skip_before_applying > tbl->inject_delay)
1552 tbl->inject_delay = add_req->skip_before_applying;
1553
Sagar Gored79f95e2017-03-14 18:32:17 -07001554 slot = &tbl->slot[idx];
1555 if (slot->state != CRM_REQ_STATE_PENDING &&
1556 slot->state != CRM_REQ_STATE_EMPTY) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001557 CAM_WARN(CAM_CRM, "Unexpected state %d for slot %d map %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07001558 slot->state, idx, slot->req_ready_map);
1559 }
1560
1561 slot->state = CRM_REQ_STATE_PENDING;
1562 slot->req_ready_map |= (1 << device->dev_bit);
1563
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001564 CAM_DBG(CAM_CRM, "idx %d dev_hdl %x req_id %lld pd %d ready_map %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07001565 idx, add_req->dev_hdl, add_req->req_id, tbl->pd,
1566 slot->req_ready_map);
1567
Gregory Bergschneider60679932017-07-19 15:27:16 -06001568 trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device);
1569
Sagar Gored79f95e2017-03-14 18:32:17 -07001570 if (slot->req_ready_map == tbl->dev_mask) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001571 CAM_DBG(CAM_CRM, "idx %d req_id %lld pd %d SLOT READY",
Sagar Gored79f95e2017-03-14 18:32:17 -07001572 idx, add_req->req_id, tbl->pd);
1573 slot->state = CRM_REQ_STATE_READY;
1574 }
1575 mutex_unlock(&link->req.lock);
1576
1577end:
1578 return rc;
1579}
1580
1581/**
1582 * cam_req_mgr_process_error()
1583 *
1584 * @brief: This runs in workque thread context. bubble /err recovery.
1585 * @priv : link information.
1586 * @data : contains information about frame_id, link etc.
1587 *
1588 * @return: 0 on success.
1589 */
1590int cam_req_mgr_process_error(void *priv, void *data)
1591{
1592 int rc = 0, idx = -1, i;
1593 struct cam_req_mgr_error_notify *err_info = NULL;
1594 struct cam_req_mgr_core_link *link = NULL;
1595 struct cam_req_mgr_req_queue *in_q = NULL;
1596 struct cam_req_mgr_slot *slot = NULL;
1597 struct cam_req_mgr_connected_device *device = NULL;
1598 struct cam_req_mgr_link_evt_data evt_data;
1599 struct crm_task_payload *task_data = NULL;
1600
1601 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001602 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001603 rc = -EINVAL;
1604 goto end;
1605 }
1606 link = (struct cam_req_mgr_core_link *)priv;
1607 task_data = (struct crm_task_payload *)data;
1608 err_info = (struct cam_req_mgr_error_notify *)&task_data->u;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001609 CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld error %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001610 err_info->link_hdl,
1611 err_info->req_id,
1612 err_info->error);
1613
1614 in_q = link->req.in_q;
1615
1616 mutex_lock(&link->req.lock);
1617 if (err_info->error == CRM_KMD_ERR_BUBBLE) {
1618 idx = __cam_req_mgr_find_slot_for_req(in_q, err_info->req_id);
1619 if (idx < 0) {
Harsh Shahcb0072c2017-09-26 19:22:10 -07001620 CAM_ERR_RATE_LIMIT(CAM_CRM,
1621 "req_id %lld not found in input queue",
1622 err_info->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001623 } else {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001624 CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001625 err_info->req_id, idx);
1626 slot = &in_q->slot[idx];
1627 if (!slot->recover) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001628 CAM_WARN(CAM_CRM,
1629 "err recovery disabled req_id %lld",
Sagar Gored79f95e2017-03-14 18:32:17 -07001630 err_info->req_id);
1631 mutex_unlock(&link->req.lock);
1632 return 0;
1633 } else if (slot->status != CRM_SLOT_STATUS_REQ_PENDING
1634 && slot->status != CRM_SLOT_STATUS_REQ_APPLIED) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001635 CAM_WARN(CAM_CRM,
1636 "req_id %lld can not be recovered %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001637 err_info->req_id, slot->status);
1638 mutex_unlock(&link->req.lock);
1639 return -EINVAL;
1640 }
1641 /* Notify all devices in the link about error */
1642 for (i = 0; i < link->num_devs; i++) {
1643 device = &link->l_dev[i];
1644 if (device != NULL) {
1645 evt_data.dev_hdl = device->dev_hdl;
1646 evt_data.evt_type =
1647 CAM_REQ_MGR_LINK_EVT_ERR;
1648 evt_data.link_hdl = link->link_hdl;
1649 evt_data.req_id = err_info->req_id;
1650 evt_data.u.error = err_info->error;
1651 if (device->ops &&
1652 device->ops->process_evt)
1653 rc = device->ops->
1654 process_evt(&evt_data);
1655 }
1656 }
1657 /* Bring processing pointer to bubbled req id */
1658 __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl);
1659 in_q->rd_idx = idx;
1660 in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED;
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301661 spin_lock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001662 link->state = CAM_CRM_LINK_STATE_ERR;
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301663 spin_unlock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001664 }
1665 }
1666 mutex_unlock(&link->req.lock);
1667
1668end:
1669 return rc;
1670}
1671
1672/**
Junzhe Zou2df84502017-05-26 13:20:23 -07001673 * cam_req_mgr_process_trigger()
Sagar Gore8d91a622017-02-23 14:57:18 -08001674 *
1675 * @brief: This runs in workque thread context. Call core funcs to check
Sagar Gored79f95e2017-03-14 18:32:17 -07001676 * which peding requests can be processed.
1677 * @priv : link information.
1678 * @data : contains information about frame_id, link etc.
Sagar Gore8d91a622017-02-23 14:57:18 -08001679 *
Sagar Gored79f95e2017-03-14 18:32:17 -07001680 * @return: 0 on success.
Sagar Gore8d91a622017-02-23 14:57:18 -08001681 */
Junzhe Zou2df84502017-05-26 13:20:23 -07001682static int cam_req_mgr_process_trigger(void *priv, void *data)
Sagar Gore8d91a622017-02-23 14:57:18 -08001683{
Sagar Gored79f95e2017-03-14 18:32:17 -07001684 int rc = 0;
Junzhe Zou2df84502017-05-26 13:20:23 -07001685 struct cam_req_mgr_trigger_notify *trigger_data = NULL;
Sagar Gored79f95e2017-03-14 18:32:17 -07001686 struct cam_req_mgr_core_link *link = NULL;
1687 struct cam_req_mgr_req_queue *in_q = NULL;
1688 struct crm_task_payload *task_data = NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001689
1690 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001691 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001692 rc = -EINVAL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001693 goto end;
1694 }
1695 link = (struct cam_req_mgr_core_link *)priv;
Sagar Gored79f95e2017-03-14 18:32:17 -07001696 task_data = (struct crm_task_payload *)data;
Junzhe Zou2df84502017-05-26 13:20:23 -07001697 trigger_data = (struct cam_req_mgr_trigger_notify *)&task_data->u;
Sagar Gore8d91a622017-02-23 14:57:18 -08001698
Junzhe Zou2df84502017-05-26 13:20:23 -07001699 CAM_DBG(CAM_CRM, "link_hdl %x frame_id %lld, trigger %x\n",
1700 trigger_data->link_hdl,
1701 trigger_data->frame_id,
1702 trigger_data->trigger);
Sagar Gore8d91a622017-02-23 14:57:18 -08001703
Sagar Gored79f95e2017-03-14 18:32:17 -07001704 in_q = link->req.in_q;
1705
1706 mutex_lock(&link->req.lock);
1707 /*
1708 * Check if current read index is in applied state, if yes make it free
1709 * and increment read index to next slot.
Sagar Gore8d91a622017-02-23 14:57:18 -08001710 */
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001711 CAM_DBG(CAM_CRM, "link_hdl %x curent idx %d req_status %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001712 link->link_hdl, in_q->rd_idx, in_q->slot[in_q->rd_idx].status);
Sagar Gore8d91a622017-02-23 14:57:18 -08001713
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301714 spin_lock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001715 if (link->state == CAM_CRM_LINK_STATE_ERR)
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001716 CAM_WARN(CAM_CRM, "Error recovery idx %d status %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001717 in_q->rd_idx,
1718 in_q->slot[in_q->rd_idx].status);
Sagar Gore8d91a622017-02-23 14:57:18 -08001719
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301720 spin_unlock_bh(&link->link_state_spin_lock);
1721
Sagar Gored79f95e2017-03-14 18:32:17 -07001722 if (in_q->slot[in_q->rd_idx].status == CRM_SLOT_STATUS_REQ_APPLIED) {
1723 /*
1724 * Do NOT reset req q slot data here, it can not be done
1725 * here because we need to preserve the data to handle bubble.
Junzhe Zou2b342222017-08-28 18:15:54 -07001726 *
1727 * Check if any new req is pending in slot, if not finish the
1728 * lower pipeline delay device with available req ids.
Sagar Gored79f95e2017-03-14 18:32:17 -07001729 */
Karthik Anantha Ramfa643332017-11-06 13:49:31 -08001730 CAM_DBG(CAM_CRM, "link[%x] Req[%lld] invalidating slot",
1731 link->link_hdl, in_q->slot[in_q->rd_idx].req_id);
Junzhe Zou2b342222017-08-28 18:15:54 -07001732 __cam_req_mgr_check_next_req_slot(in_q);
Sagar Gored79f95e2017-03-14 18:32:17 -07001733 __cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots);
Sagar Gore8d91a622017-02-23 14:57:18 -08001734 }
Junzhe Zou2df84502017-05-26 13:20:23 -07001735 rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
Sagar Gored79f95e2017-03-14 18:32:17 -07001736 mutex_unlock(&link->req.lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08001737
1738end:
Sagar Gored79f95e2017-03-14 18:32:17 -07001739 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08001740}
1741
Sagar Gore8d91a622017-02-23 14:57:18 -08001742
Sagar Gored79f95e2017-03-14 18:32:17 -07001743/* Linked devices' Callback section */
1744
1745/**
1746 * cam_req_mgr_cb_add_req()
1747 *
1748 * @brief : Drivers call this function to notify new packet is available.
1749 * @add_req : Information about new request available at a device.
1750 *
1751 * @return : 0 on success, negative in case of failure
1752 *
1753 */
1754static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req)
1755{
1756 int rc = 0, idx;
1757 struct crm_workq_task *task = NULL;
1758 struct cam_req_mgr_core_link *link = NULL;
1759 struct cam_req_mgr_add_request *dev_req;
1760 struct crm_task_payload *task_data;
1761
1762 if (!add_req) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001763 CAM_ERR(CAM_CRM, "sof_data is NULL");
Suresh Vankadara10a8e492017-11-09 01:11:31 +05301764 return -EINVAL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001765 }
1766
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001767 CAM_DBG(CAM_CRM, "E: dev %x dev req %lld",
1768 add_req->dev_hdl, add_req->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001769 link = (struct cam_req_mgr_core_link *)
1770 cam_get_device_priv(add_req->link_hdl);
1771
1772 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001773 CAM_DBG(CAM_CRM, "link ptr NULL %x", add_req->link_hdl);
Suresh Vankadara10a8e492017-11-09 01:11:31 +05301774 return -EINVAL;
Sagar Gored79f95e2017-03-14 18:32:17 -07001775 }
1776
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301777 mutex_lock(&link->lock);
1778 spin_lock_bh(&link->link_state_spin_lock);
1779 if (link->state != CAM_CRM_LINK_STATE_READY) {
1780 CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
1781 rc = -EPERM;
1782 spin_unlock_bh(&link->link_state_spin_lock);
1783 goto end;
1784 }
1785 spin_unlock_bh(&link->link_state_spin_lock);
1786
Sagar Gored79f95e2017-03-14 18:32:17 -07001787 /* Validate if req id is present in input queue */
1788 idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id);
1789 if (idx < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001790 CAM_ERR(CAM_CRM, "req %lld not found in in_q", add_req->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001791 rc = -ENOENT;
1792 goto end;
1793 }
1794
1795 task = cam_req_mgr_workq_get_task(link->workq);
1796 if (!task) {
Harsh Shahcb0072c2017-09-26 19:22:10 -07001797 CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task dev %x req %lld",
Sagar Gored79f95e2017-03-14 18:32:17 -07001798 add_req->dev_hdl, add_req->req_id);
1799 rc = -EBUSY;
1800 goto end;
1801 }
1802
1803 task_data = (struct crm_task_payload *)task->payload;
1804 task_data->type = CRM_WORKQ_TASK_DEV_ADD_REQ;
1805 dev_req = (struct cam_req_mgr_add_request *)&task_data->u;
1806 dev_req->req_id = add_req->req_id;
1807 dev_req->link_hdl = add_req->link_hdl;
1808 dev_req->dev_hdl = add_req->dev_hdl;
Sagar Gorea4d7dfd2017-09-13 19:56:24 -07001809 dev_req->skip_before_applying = add_req->skip_before_applying;
Sagar Gored79f95e2017-03-14 18:32:17 -07001810 task->process_cb = &cam_req_mgr_process_add_req;
1811 rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001812 CAM_DBG(CAM_CRM, "X: dev %x dev req %lld",
1813 add_req->dev_hdl, add_req->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001814
1815end:
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301816 mutex_unlock(&link->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001817 return rc;
1818}
1819
1820/**
1821 * cam_req_mgr_cb_notify_err()
1822 *
1823 * @brief : Error received from device, sends bubble recovery
1824 * @err_info : contains information about error occurred like bubble/overflow
1825 *
1826 * @return : 0 on success, negative in case of failure
1827 *
1828 */
1829static int cam_req_mgr_cb_notify_err(
1830 struct cam_req_mgr_error_notify *err_info)
1831{
1832 int rc = 0;
1833 struct crm_workq_task *task = NULL;
1834 struct cam_req_mgr_core_link *link = NULL;
1835 struct cam_req_mgr_error_notify *notify_err;
1836 struct crm_task_payload *task_data;
1837
1838 if (!err_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001839 CAM_ERR(CAM_CRM, "err_info is NULL");
Sagar Gored79f95e2017-03-14 18:32:17 -07001840 rc = -EINVAL;
1841 goto end;
1842 }
1843
1844 link = (struct cam_req_mgr_core_link *)
1845 cam_get_device_priv(err_info->link_hdl);
1846 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001847 CAM_DBG(CAM_CRM, "link ptr NULL %x", err_info->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07001848 rc = -EINVAL;
1849 goto end;
1850 }
1851
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301852 spin_lock_bh(&link->link_state_spin_lock);
1853 if (link->state != CAM_CRM_LINK_STATE_READY) {
1854 CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
1855 spin_unlock_bh(&link->link_state_spin_lock);
1856 rc = -EPERM;
1857 goto end;
1858 }
Venkat Chinta686c9e52018-01-20 14:33:25 -08001859 crm_timer_reset(link->watchdog);
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301860 spin_unlock_bh(&link->link_state_spin_lock);
1861
Sagar Gored79f95e2017-03-14 18:32:17 -07001862 task = cam_req_mgr_workq_get_task(link->workq);
1863 if (!task) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001864 CAM_ERR(CAM_CRM, "no empty task req_id %lld", err_info->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001865 rc = -EBUSY;
1866 goto end;
1867 }
1868
1869 task_data = (struct crm_task_payload *)task->payload;
1870 task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR;
1871 notify_err = (struct cam_req_mgr_error_notify *)&task_data->u;
1872 notify_err->req_id = err_info->req_id;
1873 notify_err->link_hdl = err_info->link_hdl;
1874 notify_err->dev_hdl = err_info->dev_hdl;
1875 notify_err->error = err_info->error;
1876 task->process_cb = &cam_req_mgr_process_error;
1877 rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
1878
1879end:
1880 return rc;
1881}
1882
1883/**
Junzhe Zou2df84502017-05-26 13:20:23 -07001884 * cam_req_mgr_cb_notify_trigger()
Sagar Gored79f95e2017-03-14 18:32:17 -07001885 *
1886 * @brief : SOF received from device, sends trigger through workqueue
1887 * @sof_data: contains information about frame_id, link etc.
1888 *
1889 * @return : 0 on success
1890 *
1891 */
Junzhe Zou2df84502017-05-26 13:20:23 -07001892static int cam_req_mgr_cb_notify_trigger(
1893 struct cam_req_mgr_trigger_notify *trigger_data)
Sagar Gored79f95e2017-03-14 18:32:17 -07001894{
1895 int rc = 0;
1896 struct crm_workq_task *task = NULL;
1897 struct cam_req_mgr_core_link *link = NULL;
Junzhe Zou2df84502017-05-26 13:20:23 -07001898 struct cam_req_mgr_trigger_notify *notify_trigger;
Sagar Gored79f95e2017-03-14 18:32:17 -07001899 struct crm_task_payload *task_data;
1900
Junzhe Zou2df84502017-05-26 13:20:23 -07001901 if (!trigger_data) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001902 CAM_ERR(CAM_CRM, "sof_data is NULL");
Sagar Gored79f95e2017-03-14 18:32:17 -07001903 rc = -EINVAL;
1904 goto end;
1905 }
Sagar Gore8d91a622017-02-23 14:57:18 -08001906
1907 link = (struct cam_req_mgr_core_link *)
Junzhe Zou2df84502017-05-26 13:20:23 -07001908 cam_get_device_priv(trigger_data->link_hdl);
Sagar Gore8d91a622017-02-23 14:57:18 -08001909 if (!link) {
Junzhe Zou2df84502017-05-26 13:20:23 -07001910 CAM_DBG(CAM_CRM, "link ptr NULL %x", trigger_data->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07001911 rc = -EINVAL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001912 goto end;
Sagar Gore8d91a622017-02-23 14:57:18 -08001913 }
1914
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301915 spin_lock_bh(&link->link_state_spin_lock);
1916 if (link->state != CAM_CRM_LINK_STATE_READY) {
1917 CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
1918 spin_unlock_bh(&link->link_state_spin_lock);
1919 rc = -EPERM;
1920 goto end;
1921 }
Venkat Chinta686c9e52018-01-20 14:33:25 -08001922 crm_timer_reset(link->watchdog);
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301923 spin_unlock_bh(&link->link_state_spin_lock);
1924
Sagar Gore8d91a622017-02-23 14:57:18 -08001925 task = cam_req_mgr_workq_get_task(link->workq);
1926 if (!task) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001927 CAM_ERR(CAM_CRM, "no empty task frame %lld",
Junzhe Zou2df84502017-05-26 13:20:23 -07001928 trigger_data->frame_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001929 rc = -EBUSY;
Sagar Gore8d91a622017-02-23 14:57:18 -08001930 goto end;
1931 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001932 task_data = (struct crm_task_payload *)task->payload;
1933 task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF;
Junzhe Zou2df84502017-05-26 13:20:23 -07001934 notify_trigger = (struct cam_req_mgr_trigger_notify *)&task_data->u;
1935 notify_trigger->frame_id = trigger_data->frame_id;
1936 notify_trigger->link_hdl = trigger_data->link_hdl;
1937 notify_trigger->dev_hdl = trigger_data->dev_hdl;
1938 notify_trigger->trigger = trigger_data->trigger;
1939 task->process_cb = &cam_req_mgr_process_trigger;
Sagar Gored79f95e2017-03-14 18:32:17 -07001940 rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
Sagar Gore8d91a622017-02-23 14:57:18 -08001941
1942end:
Sagar Gored79f95e2017-03-14 18:32:17 -07001943 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08001944}
1945
Sagar Gored79f95e2017-03-14 18:32:17 -07001946static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
Junzhe Zou2df84502017-05-26 13:20:23 -07001947 .notify_trigger = cam_req_mgr_cb_notify_trigger,
1948 .notify_err = cam_req_mgr_cb_notify_err,
1949 .add_req = cam_req_mgr_cb_add_req,
Sagar Gored79f95e2017-03-14 18:32:17 -07001950};
1951
Sagar Gore8d91a622017-02-23 14:57:18 -08001952/**
Sagar Gored79f95e2017-03-14 18:32:17 -07001953 * __cam_req_mgr_setup_link_info()
Sagar Gore8d91a622017-02-23 14:57:18 -08001954 *
Sagar Gored79f95e2017-03-14 18:32:17 -07001955 * @brief : Sets up input queue, create pd based tables, communicate with
1956 * devs connected on this link and setup communication.
1957 * @link : pointer to link to setup
1958 * @link_info : link_info coming from CSL to prepare link
Sagar Gore8d91a622017-02-23 14:57:18 -08001959 *
Sagar Gored79f95e2017-03-14 18:32:17 -07001960 * @return : 0 on success, negative in case of failure
1961 *
Sagar Gore8d91a622017-02-23 14:57:18 -08001962 */
Sagar Gored79f95e2017-03-14 18:32:17 -07001963static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
1964 struct cam_req_mgr_link_info *link_info)
Sagar Gore8d91a622017-02-23 14:57:18 -08001965{
Sagar Gored79f95e2017-03-14 18:32:17 -07001966 int rc = 0, i = 0;
1967 struct cam_req_mgr_core_dev_link_setup link_data;
1968 struct cam_req_mgr_connected_device *dev;
1969 struct cam_req_mgr_req_tbl *pd_tbl;
1970 enum cam_pipeline_delay max_delay;
Junzhe Zou2df84502017-05-26 13:20:23 -07001971 uint32_t subscribe_event = 0;
Sagar Gore8d91a622017-02-23 14:57:18 -08001972
Sagar Gored79f95e2017-03-14 18:32:17 -07001973 if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES)
1974 return -EPERM;
Sagar Gore8d91a622017-02-23 14:57:18 -08001975
Sagar Gored79f95e2017-03-14 18:32:17 -07001976 mutex_init(&link->req.lock);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001977 CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001978 link->req.num_tbl = 0;
1979
1980 rc = __cam_req_mgr_setup_in_q(&link->req);
1981 if (rc < 0)
1982 return rc;
1983
Sagar Gored79f95e2017-03-14 18:32:17 -07001984 max_delay = CAM_PIPELINE_DELAY_0;
1985 for (i = 0; i < link_info->num_devices; i++) {
1986 dev = &link->l_dev[i];
1987 /* Using dev hdl, get ops ptr to communicate with device */
1988 dev->ops = (struct cam_req_mgr_kmd_ops *)
1989 cam_get_device_ops(link_info->dev_hdls[i]);
1990 if (!dev->ops ||
1991 !dev->ops->get_dev_info ||
1992 !dev->ops->link_setup) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001993 CAM_ERR(CAM_CRM, "FATAL: device ops NULL");
Sagar Gored79f95e2017-03-14 18:32:17 -07001994 rc = -ENXIO;
1995 goto error;
Sagar Gore8d91a622017-02-23 14:57:18 -08001996 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001997 dev->dev_hdl = link_info->dev_hdls[i];
1998 dev->parent = (void *)link;
1999 dev->dev_info.dev_hdl = dev->dev_hdl;
2000 rc = dev->ops->get_dev_info(&dev->dev_info);
Gregory Bergschneider60679932017-07-19 15:27:16 -06002001
2002 trace_cam_req_mgr_connect_device(link, &dev->dev_info);
2003
Junzhe Zou2df84502017-05-26 13:20:23 -07002004 CAM_DBG(CAM_CRM,
2005 "%x: connected: %s, id %d, delay %d, trigger %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07002006 link_info->session_hdl, dev->dev_info.name,
Junzhe Zou2df84502017-05-26 13:20:23 -07002007 dev->dev_info.dev_id, dev->dev_info.p_delay,
2008 dev->dev_info.trigger);
Sagar Gored79f95e2017-03-14 18:32:17 -07002009 if (rc < 0 ||
2010 dev->dev_info.p_delay >=
2011 CAM_PIPELINE_DELAY_MAX ||
2012 dev->dev_info.p_delay <
2013 CAM_PIPELINE_DELAY_0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002014 CAM_ERR(CAM_CRM, "get device info failed");
Sagar Gored79f95e2017-03-14 18:32:17 -07002015 goto error;
2016 } else {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002017 CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07002018 link_info->session_hdl,
2019 dev->dev_info.name,
2020 dev->dev_info.p_delay);
Junzhe Zou2df84502017-05-26 13:20:23 -07002021 if (dev->dev_info.p_delay > max_delay)
2022 max_delay = dev->dev_info.p_delay;
2023
2024 subscribe_event |= (uint32_t)dev->dev_info.trigger;
Sagar Gored79f95e2017-03-14 18:32:17 -07002025 }
Sagar Gore8d91a622017-02-23 14:57:18 -08002026 }
2027
Junzhe Zou2df84502017-05-26 13:20:23 -07002028 link->subscribe_event = subscribe_event;
Sagar Gored79f95e2017-03-14 18:32:17 -07002029 link_data.link_enable = 1;
2030 link_data.link_hdl = link->link_hdl;
2031 link_data.crm_cb = &cam_req_mgr_ops;
2032 link_data.max_delay = max_delay;
Junzhe Zou2df84502017-05-26 13:20:23 -07002033 link_data.subscribe_event = subscribe_event;
Sagar Gored79f95e2017-03-14 18:32:17 -07002034
2035 for (i = 0; i < link_info->num_devices; i++) {
2036 dev = &link->l_dev[i];
2037
2038 link_data.dev_hdl = dev->dev_hdl;
2039 /*
2040 * For unique pipeline delay table create request
2041 * tracking table
2042 */
2043 if (link->pd_mask & (1 << dev->dev_info.p_delay)) {
2044 pd_tbl = __cam_req_mgr_find_pd_tbl(link->req.l_tbl,
2045 dev->dev_info.p_delay);
2046 if (!pd_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002047 CAM_ERR(CAM_CRM, "pd %d tbl not found",
Sagar Gored79f95e2017-03-14 18:32:17 -07002048 dev->dev_info.p_delay);
2049 rc = -ENXIO;
2050 goto error;
2051 }
2052 } else {
2053 pd_tbl = __cam_req_mgr_create_pd_tbl(
2054 dev->dev_info.p_delay);
2055 if (pd_tbl == NULL) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002056 CAM_ERR(CAM_CRM, "create new pd tbl failed");
Sagar Gored79f95e2017-03-14 18:32:17 -07002057 rc = -ENXIO;
2058 goto error;
2059 }
2060 pd_tbl->pd = dev->dev_info.p_delay;
2061 link->pd_mask |= (1 << pd_tbl->pd);
2062 /*
2063 * Add table to list and also sort list
2064 * from max pd to lowest
2065 */
2066 __cam_req_mgr_add_tbl_to_link(&link->req.l_tbl, pd_tbl);
2067 }
2068 dev->dev_bit = pd_tbl->dev_count++;
2069 dev->pd_tbl = pd_tbl;
2070 pd_tbl->dev_mask |= (1 << dev->dev_bit);
2071
2072 /* Communicate with dev to establish the link */
2073 dev->ops->link_setup(&link_data);
2074
2075 if (link->max_delay < dev->dev_info.p_delay)
2076 link->max_delay = dev->dev_info.p_delay;
2077 }
2078 link->num_devs = link_info->num_devices;
2079
2080 /* Assign id for pd tables */
2081 __cam_req_mgr_tbl_set_id(link->req.l_tbl, &link->req);
2082
2083 /* At start, expect max pd devices, all are in skip state */
2084 __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl);
2085
Sagar Gored79f95e2017-03-14 18:32:17 -07002086 return 0;
2087
2088error:
2089 __cam_req_mgr_destroy_link_info(link);
2090 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002091}
2092
Sagar Gored79f95e2017-03-14 18:32:17 -07002093/* IOCTLs handling section */
Sagar Gore8d91a622017-02-23 14:57:18 -08002094int cam_req_mgr_create_session(
2095 struct cam_req_mgr_session_info *ses_info)
2096{
Sagar Gored79f95e2017-03-14 18:32:17 -07002097 int rc = 0;
2098 int32_t session_hdl;
2099 struct cam_req_mgr_core_session *cam_session = NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -08002100
2101 if (!ses_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002102 CAM_DBG(CAM_CRM, "NULL session info pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002103 return -EINVAL;
2104 }
2105 mutex_lock(&g_crm_core_dev->crm_lock);
2106 cam_session = (struct cam_req_mgr_core_session *)
2107 kzalloc(sizeof(*cam_session), GFP_KERNEL);
2108 if (!cam_session) {
Sagar Gored79f95e2017-03-14 18:32:17 -07002109 rc = -ENOMEM;
Sagar Gore8d91a622017-02-23 14:57:18 -08002110 goto end;
2111 }
2112
2113 session_hdl = cam_create_session_hdl((void *)cam_session);
2114 if (session_hdl < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002115 CAM_ERR(CAM_CRM, "unable to create session_hdl = %x",
2116 session_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002117 rc = session_hdl;
2118 kfree(cam_session);
2119 goto end;
Sagar Gore8d91a622017-02-23 14:57:18 -08002120 }
2121 ses_info->session_hdl = session_hdl;
Sagar Gored79f95e2017-03-14 18:32:17 -07002122
2123 mutex_init(&cam_session->lock);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002124 CAM_DBG(CAM_CRM, "LOCK_DBG session lock %pK", &cam_session->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002125
2126 mutex_lock(&cam_session->lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002127 cam_session->session_hdl = session_hdl;
Sagar Gored79f95e2017-03-14 18:32:17 -07002128 cam_session->num_links = 0;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002129 cam_session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
Sagar Gore8d91a622017-02-23 14:57:18 -08002130 list_add(&cam_session->entry, &g_crm_core_dev->session_head);
Sagar Gored79f95e2017-03-14 18:32:17 -07002131 mutex_unlock(&cam_session->lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002132end:
2133 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002134 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002135}
2136
Sunil Khatribc029f72017-11-28 18:54:24 +05302137/**
2138 * __cam_req_mgr_unlink()
2139 *
2140 * @brief : Unlink devices on a link structure from the session
2141 * @link : Pointer to the link structure
2142 *
2143 * @return: 0 for success, negative for failure
2144 *
2145 */
2146static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
2147{
2148 int rc;
2149
2150 mutex_lock(&link->lock);
2151 spin_lock_bh(&link->link_state_spin_lock);
2152 link->state = CAM_CRM_LINK_STATE_IDLE;
Venkat Chinta686c9e52018-01-20 14:33:25 -08002153
2154 /* Destroy timer of link */
2155 crm_timer_exit(&link->watchdog);
Sunil Khatribc029f72017-11-28 18:54:24 +05302156 spin_unlock_bh(&link->link_state_spin_lock);
2157 __cam_req_mgr_print_req_tbl(&link->req);
2158
2159 /* Destroy workq payload data */
2160 kfree(link->workq->task.pool[0].payload);
2161 link->workq->task.pool[0].payload = NULL;
2162
Venkat Chinta686c9e52018-01-20 14:33:25 -08002163 /* Destroy workq of link */
Sunil Khatribc029f72017-11-28 18:54:24 +05302164 cam_req_mgr_workq_destroy(&link->workq);
2165
2166 /* Cleanup request tables and unlink devices */
Venkat Chinta686c9e52018-01-20 14:33:25 -08002167 rc = __cam_req_mgr_destroy_link_info(link);
2168 if (rc) {
2169 CAM_ERR(CAM_CORE, "Unlink failed. Cannot proceed");
2170 goto done;
2171 }
Sunil Khatribc029f72017-11-28 18:54:24 +05302172
2173 /* Free memory holding data of linked devs */
2174 __cam_req_mgr_destroy_subdev(link->l_dev);
2175
2176 /* Destroy the link handle */
2177 rc = cam_destroy_device_hdl(link->link_hdl);
2178 if (rc < 0) {
2179 CAM_ERR(CAM_CRM, "error while destroying dev handle %d %x",
2180 rc, link->link_hdl);
2181 }
2182
Venkat Chinta686c9e52018-01-20 14:33:25 -08002183done:
Sunil Khatribc029f72017-11-28 18:54:24 +05302184 mutex_unlock(&link->lock);
2185 return rc;
2186}
2187
Sagar Gore8d91a622017-02-23 14:57:18 -08002188int cam_req_mgr_destroy_session(
2189 struct cam_req_mgr_session_info *ses_info)
2190{
Sagar Gored79f95e2017-03-14 18:32:17 -07002191 int rc;
Sunil Khatribc029f72017-11-28 18:54:24 +05302192 int i;
Sagar Gored79f95e2017-03-14 18:32:17 -07002193 struct cam_req_mgr_core_session *cam_session = NULL;
Sunil Khatribc029f72017-11-28 18:54:24 +05302194 struct cam_req_mgr_core_link *link;
Sagar Gore8d91a622017-02-23 14:57:18 -08002195
2196 if (!ses_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002197 CAM_DBG(CAM_CRM, "NULL session info pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002198 return -EINVAL;
2199 }
2200
2201 mutex_lock(&g_crm_core_dev->crm_lock);
2202 cam_session = (struct cam_req_mgr_core_session *)
2203 cam_get_device_priv(ses_info->session_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002204 if (!cam_session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002205 CAM_ERR(CAM_CRM, "failed to get session priv");
Sagar Gored79f95e2017-03-14 18:32:17 -07002206 rc = -ENOENT;
Sagar Gore8d91a622017-02-23 14:57:18 -08002207 goto end;
2208
2209 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002210 mutex_lock(&cam_session->lock);
2211 if (cam_session->num_links) {
Sunil Khatribc029f72017-11-28 18:54:24 +05302212 CAM_DBG(CAM_CRM, "destroy session %x num_active_links %d",
Sagar Gore8d91a622017-02-23 14:57:18 -08002213 ses_info->session_hdl,
Sagar Gored79f95e2017-03-14 18:32:17 -07002214 cam_session->num_links);
Sunil Khatribc029f72017-11-28 18:54:24 +05302215
2216 for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
2217 link = cam_session->links[i];
2218
2219 if (!link)
2220 continue;
2221
2222 /* Ignore return value since session is going away */
2223 __cam_req_mgr_unlink(link);
2224 __cam_req_mgr_free_link(link);
2225 }
Sagar Gore8d91a622017-02-23 14:57:18 -08002226 }
2227 list_del(&cam_session->entry);
Sagar Gored79f95e2017-03-14 18:32:17 -07002228 mutex_unlock(&cam_session->lock);
2229 mutex_destroy(&cam_session->lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002230 kfree(cam_session);
2231
Sagar Gored79f95e2017-03-14 18:32:17 -07002232 rc = cam_destroy_session_hdl(ses_info->session_hdl);
2233 if (rc < 0)
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002234 CAM_ERR(CAM_CRM, "unable to destroy session_hdl = %x rc %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07002235 ses_info->session_hdl, rc);
Sagar Gore8d91a622017-02-23 14:57:18 -08002236
2237end:
2238 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002239 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002240}
2241
2242int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
2243{
Sagar Gored79f95e2017-03-14 18:32:17 -07002244 int rc = 0;
2245 char buf[128];
2246 struct cam_create_dev_hdl root_dev;
2247 struct cam_req_mgr_core_session *cam_session;
2248 struct cam_req_mgr_core_link *link;
Sagar Gore8d91a622017-02-23 14:57:18 -08002249
2250 if (!link_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002251 CAM_DBG(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002252 return -EINVAL;
2253 }
Sagar Gore8d91a622017-02-23 14:57:18 -08002254 if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002255 CAM_ERR(CAM_CRM, "Invalid num devices %d",
2256 link_info->num_devices);
Sagar Gore8d91a622017-02-23 14:57:18 -08002257 return -EINVAL;
2258 }
2259
Sagar Gored79f95e2017-03-14 18:32:17 -07002260 /* session hdl's priv data is cam session struct */
Sagar Gore8d91a622017-02-23 14:57:18 -08002261 cam_session = (struct cam_req_mgr_core_session *)
2262 cam_get_device_priv(link_info->session_hdl);
2263 if (!cam_session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002264 CAM_DBG(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002265 return -EINVAL;
2266 }
2267
Sagar Gored79f95e2017-03-14 18:32:17 -07002268 mutex_lock(&g_crm_core_dev->crm_lock);
2269
2270 /* Allocate link struct and map it with session's request queue */
2271 link = __cam_req_mgr_reserve_link(cam_session);
Sagar Gore8d91a622017-02-23 14:57:18 -08002272 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002273 CAM_ERR(CAM_CRM, "failed to reserve new link");
Sagar Gored79f95e2017-03-14 18:32:17 -07002274 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002275 return -EINVAL;
2276 }
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002277 CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl);
Sagar Gore8d91a622017-02-23 14:57:18 -08002278
2279 memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl));
2280 root_dev.session_hdl = link_info->session_hdl;
2281 root_dev.priv = (void *)link;
2282
Sagar Gored79f95e2017-03-14 18:32:17 -07002283 mutex_lock(&link->lock);
2284 /* Create unique dev handle for link */
2285 link->link_hdl = cam_create_device_hdl(&root_dev);
2286 if (link->link_hdl < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002287 CAM_ERR(CAM_CRM,
2288 "Insufficient memory to create new device handle");
Sagar Gored79f95e2017-03-14 18:32:17 -07002289 rc = link->link_hdl;
Sagar Gore8d91a622017-02-23 14:57:18 -08002290 goto link_hdl_fail;
2291 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002292 link_info->link_hdl = link->link_hdl;
Sagar Gore8d91a622017-02-23 14:57:18 -08002293
Sagar Gored79f95e2017-03-14 18:32:17 -07002294 /* Allocate memory to hold data of all linked devs */
2295 rc = __cam_req_mgr_create_subdevs(&link->l_dev,
2296 link_info->num_devices);
2297 if (rc < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002298 CAM_ERR(CAM_CRM,
2299 "Insufficient memory to create new crm subdevs");
Sagar Gore8d91a622017-02-23 14:57:18 -08002300 goto create_subdev_failed;
2301 }
2302
Sagar Gored79f95e2017-03-14 18:32:17 -07002303 /* Using device ops query connected devs, prepare request tables */
2304 rc = __cam_req_mgr_setup_link_info(link, link_info);
2305 if (rc < 0)
2306 goto setup_failed;
Sagar Gore8d91a622017-02-23 14:57:18 -08002307
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302308 spin_lock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002309 link->state = CAM_CRM_LINK_STATE_READY;
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302310 spin_unlock_bh(&link->link_state_spin_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002311
2312 /* Create worker for current link */
Sagar Gored79f95e2017-03-14 18:32:17 -07002313 snprintf(buf, sizeof(buf), "%x-%x",
2314 link_info->session_hdl, link->link_hdl);
Sagar Gore9f404712017-05-22 16:57:25 -07002315 rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
2316 &link->workq, CRM_WORKQ_USAGE_NON_IRQ);
Sagar Gored79f95e2017-03-14 18:32:17 -07002317 if (rc < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002318 CAM_ERR(CAM_CRM, "FATAL: unable to create worker");
Sagar Gored79f95e2017-03-14 18:32:17 -07002319 __cam_req_mgr_destroy_link_info(link);
2320 goto setup_failed;
Sagar Gore8d91a622017-02-23 14:57:18 -08002321 }
2322
Sagar Gored79f95e2017-03-14 18:32:17 -07002323 /* Assign payload to workqueue tasks */
2324 rc = __cam_req_mgr_setup_payload(link->workq);
2325 if (rc < 0) {
2326 __cam_req_mgr_destroy_link_info(link);
2327 cam_req_mgr_workq_destroy(&link->workq);
2328 goto setup_failed;
2329 }
Sagar Gore8d91a622017-02-23 14:57:18 -08002330
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302331 mutex_unlock(&link->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002332 mutex_unlock(&g_crm_core_dev->crm_lock);
2333 return rc;
2334setup_failed:
2335 __cam_req_mgr_destroy_subdev(link->l_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002336create_subdev_failed:
Sagar Gored79f95e2017-03-14 18:32:17 -07002337 cam_destroy_device_hdl(link->link_hdl);
2338 link_info->link_hdl = 0;
Sagar Gore8d91a622017-02-23 14:57:18 -08002339link_hdl_fail:
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302340 mutex_unlock(&link->lock);
Sunil Khatribc029f72017-11-28 18:54:24 +05302341 __cam_req_mgr_unreserve_link(cam_session, link);
Sagar Gored79f95e2017-03-14 18:32:17 -07002342 mutex_unlock(&g_crm_core_dev->crm_lock);
2343 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002344}
2345
2346int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info)
2347{
Sagar Gored79f95e2017-03-14 18:32:17 -07002348 int rc = 0;
Sagar Gore8d91a622017-02-23 14:57:18 -08002349 struct cam_req_mgr_core_session *cam_session;
Sagar Gored79f95e2017-03-14 18:32:17 -07002350 struct cam_req_mgr_core_link *link;
Sagar Gore8d91a622017-02-23 14:57:18 -08002351
2352 if (!unlink_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002353 CAM_ERR(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002354 return -EINVAL;
2355 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002356
2357 mutex_lock(&g_crm_core_dev->crm_lock);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002358 CAM_DBG(CAM_CRM, "link_hdl %x", unlink_info->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002359
2360 /* session hdl's priv data is cam session struct */
Sagar Gore8d91a622017-02-23 14:57:18 -08002361 cam_session = (struct cam_req_mgr_core_session *)
Sagar Gored79f95e2017-03-14 18:32:17 -07002362 cam_get_device_priv(unlink_info->session_hdl);
Sagar Gore8d91a622017-02-23 14:57:18 -08002363 if (!cam_session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002364 CAM_ERR(CAM_CRM, "NULL pointer");
Sagar Gored79f95e2017-03-14 18:32:17 -07002365 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002366 return -EINVAL;
2367 }
2368
Sagar Gored79f95e2017-03-14 18:32:17 -07002369 /* link hdl's priv data is core_link struct */
2370 link = cam_get_device_priv(unlink_info->link_hdl);
Sagar Gore8d91a622017-02-23 14:57:18 -08002371 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002372 CAM_ERR(CAM_CRM, "NULL pointer");
Sunil Khatribc029f72017-11-28 18:54:24 +05302373 rc = -EINVAL;
2374 goto done;
Sagar Gore8d91a622017-02-23 14:57:18 -08002375 }
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302376
Sunil Khatribc029f72017-11-28 18:54:24 +05302377 rc = __cam_req_mgr_unlink(link);
Sagar Gore8d91a622017-02-23 14:57:18 -08002378
Sagar Gored79f95e2017-03-14 18:32:17 -07002379 /* Free curent link and put back into session's free pool of links */
Sunil Khatribc029f72017-11-28 18:54:24 +05302380 if (!rc)
2381 __cam_req_mgr_unreserve_link(cam_session, link);
Sagar Gored79f95e2017-03-14 18:32:17 -07002382
Sunil Khatribc029f72017-11-28 18:54:24 +05302383done:
2384 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002385 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002386}
2387
2388int cam_req_mgr_schedule_request(
2389 struct cam_req_mgr_sched_request *sched_req)
2390{
Sagar Gored79f95e2017-03-14 18:32:17 -07002391 int rc = 0;
Sagar Gored79f95e2017-03-14 18:32:17 -07002392 struct cam_req_mgr_core_link *link = NULL;
2393 struct cam_req_mgr_core_session *session = NULL;
2394 struct cam_req_mgr_sched_request *sched;
Sagar Goreb56c81e2017-05-08 17:15:47 -07002395 struct crm_task_payload task_data;
Sagar Gored79f95e2017-03-14 18:32:17 -07002396
Sagar Gore8d91a622017-02-23 14:57:18 -08002397 if (!sched_req) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002398 CAM_ERR(CAM_CRM, "csl_req is NULL");
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002399 return -EINVAL;
Sagar Gored79f95e2017-03-14 18:32:17 -07002400 }
2401
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002402 mutex_lock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002403 link = (struct cam_req_mgr_core_link *)
2404 cam_get_device_priv(sched_req->link_hdl);
2405 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002406 CAM_DBG(CAM_CRM, "link ptr NULL %x", sched_req->link_hdl);
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002407 rc = -EINVAL;
2408 goto end;
Sagar Gored79f95e2017-03-14 18:32:17 -07002409 }
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002410
Sagar Gored79f95e2017-03-14 18:32:17 -07002411 session = (struct cam_req_mgr_core_session *)link->parent;
2412 if (!session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002413 CAM_WARN(CAM_CRM, "session ptr NULL %x", sched_req->link_hdl);
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002414 rc = -EINVAL;
2415 goto end;
Sagar Gore8d91a622017-02-23 14:57:18 -08002416 }
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002417
2418 CAM_DBG(CAM_CRM, "link %x req %lld, sync_mode %d",
2419 sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
Sagar Gore8d91a622017-02-23 14:57:18 -08002420
Sagar Goreb56c81e2017-05-08 17:15:47 -07002421 task_data.type = CRM_WORKQ_TASK_SCHED_REQ;
2422 sched = (struct cam_req_mgr_sched_request *)&task_data.u;
Sagar Gored79f95e2017-03-14 18:32:17 -07002423 sched->req_id = sched_req->req_id;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002424 sched->sync_mode = sched_req->sync_mode;
Sagar Gored79f95e2017-03-14 18:32:17 -07002425 sched->link_hdl = sched_req->link_hdl;
2426 if (session->force_err_recovery == AUTO_RECOVERY) {
2427 sched->bubble_enable = sched_req->bubble_enable;
2428 } else {
2429 sched->bubble_enable =
2430 (session->force_err_recovery == FORCE_ENABLE_RECOVERY) ? 1 : 0;
2431 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002432
Sagar Goreb56c81e2017-05-08 17:15:47 -07002433 rc = cam_req_mgr_process_sched_req(link, &task_data);
2434
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002435 CAM_DBG(CAM_CRM, "DONE dev %x req %lld sync_mode %d",
2436 sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
Sagar Gored79f95e2017-03-14 18:32:17 -07002437end:
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002438 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002439 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002440}
2441
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002442int cam_req_mgr_sync_config(
2443 struct cam_req_mgr_sync_mode *sync_info)
Sagar Gore8d91a622017-02-23 14:57:18 -08002444{
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002445 int rc = 0;
2446 struct cam_req_mgr_core_session *cam_session;
2447 struct cam_req_mgr_core_link *link1 = NULL;
2448 struct cam_req_mgr_core_link *link2 = NULL;
2449
2450 if (!sync_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002451 CAM_ERR(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002452 return -EINVAL;
2453 }
2454
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002455 if ((sync_info->num_links < 0) ||
2456 (sync_info->num_links > MAX_LINKS_PER_SESSION)) {
2457 CAM_ERR(CAM_CRM, "Invalid num links %d", sync_info->num_links);
2458 return -EINVAL;
2459 }
2460
Pavan Kumar Chilamkurthibd699432018-01-24 12:53:01 -08002461 if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) {
2462 CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x",
2463 sync_info->link_hdls[0], sync_info->link_hdls[1]);
2464 return -EINVAL;
2465 }
2466
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002467 mutex_lock(&g_crm_core_dev->crm_lock);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002468 /* session hdl's priv data is cam session struct */
2469 cam_session = (struct cam_req_mgr_core_session *)
2470 cam_get_device_priv(sync_info->session_hdl);
2471 if (!cam_session) {
2472 CAM_ERR(CAM_CRM, "NULL pointer");
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002473 mutex_unlock(&g_crm_core_dev->crm_lock);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002474 return -EINVAL;
2475 }
2476
2477 mutex_lock(&cam_session->lock);
Venkat Chinta686c9e52018-01-20 14:33:25 -08002478
Karthik Anantha Ramfa643332017-11-06 13:49:31 -08002479 CAM_DBG(CAM_CRM, "link handles %x %x",
2480 sync_info->link_hdls[0], sync_info->link_hdls[1]);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002481
2482 /* only two links existing per session in dual cam use case*/
2483 link1 = cam_get_device_priv(sync_info->link_hdls[0]);
2484 if (!link1) {
Karthik Anantha Ramfa643332017-11-06 13:49:31 -08002485 CAM_ERR(CAM_CRM, "link1 NULL pointer");
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002486 rc = -EINVAL;
2487 goto done;
2488 }
2489
2490 link2 = cam_get_device_priv(sync_info->link_hdls[1]);
2491 if (!link2) {
Karthik Anantha Ramfa643332017-11-06 13:49:31 -08002492 CAM_ERR(CAM_CRM, "link2 NULL pointer");
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002493 rc = -EINVAL;
2494 goto done;
2495 }
2496
2497 link1->sof_counter = -1;
2498 link1->sync_self_ref = -1;
2499 link1->frame_skip_flag = false;
2500 link1->sync_link = link2;
2501
2502 link2->sof_counter = -1;
2503 link2->sync_self_ref = -1;
2504 link2->frame_skip_flag = false;
2505 link2->sync_link = link1;
2506
2507 cam_session->sync_mode = sync_info->sync_mode;
2508
2509done:
2510 mutex_unlock(&cam_session->lock);
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002511 mutex_unlock(&g_crm_core_dev->crm_lock);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002512 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002513}
2514
2515int cam_req_mgr_flush_requests(
Sagar Gored79f95e2017-03-14 18:32:17 -07002516 struct cam_req_mgr_flush_info *flush_info)
Sagar Gore8d91a622017-02-23 14:57:18 -08002517{
Sagar Gored79f95e2017-03-14 18:32:17 -07002518 int rc = 0;
2519 struct crm_workq_task *task = NULL;
2520 struct cam_req_mgr_core_link *link = NULL;
2521 struct cam_req_mgr_flush_info *flush;
2522 struct crm_task_payload *task_data;
2523 struct cam_req_mgr_core_session *session = NULL;
2524
Sagar Gore8d91a622017-02-23 14:57:18 -08002525 if (!flush_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002526 CAM_ERR(CAM_CRM, "flush req is NULL");
Sagar Gored79f95e2017-03-14 18:32:17 -07002527 rc = -EFAULT;
2528 goto end;
2529 }
2530 if (flush_info->flush_type >= CAM_REQ_MGR_FLUSH_TYPE_MAX) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002531 CAM_ERR(CAM_CRM, "incorrect flush type %x",
2532 flush_info->flush_type);
Sagar Gored79f95e2017-03-14 18:32:17 -07002533 rc = -EINVAL;
2534 goto end;
Sagar Gore8d91a622017-02-23 14:57:18 -08002535 }
2536
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002537 mutex_lock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002538 /* session hdl's priv data is cam session struct */
2539 session = (struct cam_req_mgr_core_session *)
2540 cam_get_device_priv(flush_info->session_hdl);
2541 if (!session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002542 CAM_ERR(CAM_CRM, "Invalid session %x", flush_info->session_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002543 rc = -EINVAL;
2544 goto end;
2545 }
2546 if (session->num_links <= 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002547 CAM_WARN(CAM_CRM, "No active links in session %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07002548 flush_info->session_hdl);
2549 goto end;
2550 }
2551
2552 link = (struct cam_req_mgr_core_link *)
2553 cam_get_device_priv(flush_info->link_hdl);
2554 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002555 CAM_DBG(CAM_CRM, "link ptr NULL %x", flush_info->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002556 rc = -EINVAL;
2557 goto end;
2558 }
2559
2560 task = cam_req_mgr_workq_get_task(link->workq);
2561 if (!task) {
2562 rc = -ENOMEM;
2563 goto end;
2564 }
2565
2566 task_data = (struct crm_task_payload *)task->payload;
2567 task_data->type = CRM_WORKQ_TASK_FLUSH_REQ;
2568 flush = (struct cam_req_mgr_flush_info *)&task_data->u;
2569 flush->req_id = flush_info->req_id;
2570 flush->link_hdl = flush_info->link_hdl;
2571 flush->flush_type = flush_info->flush_type;
2572 task->process_cb = &cam_req_mgr_process_flush_req;
Junzhe Zou158da722017-10-25 19:14:32 -07002573 init_completion(&link->workq_comp);
Sagar Gored79f95e2017-03-14 18:32:17 -07002574 rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
2575
2576 /* Blocking call */
Sagar Gored79f95e2017-03-14 18:32:17 -07002577 rc = wait_for_completion_timeout(
2578 &link->workq_comp,
2579 msecs_to_jiffies(CAM_REQ_MGR_SCHED_REQ_TIMEOUT));
2580end:
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002581 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002582 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002583}
2584
Jing Zhou0f645332017-11-17 12:16:40 -08002585int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
2586{
2587 int rc = 0;
Jing Zhou30504bd2017-11-21 11:36:07 -08002588 int i, j;
Jing Zhou0f645332017-11-17 12:16:40 -08002589 struct cam_req_mgr_core_link *link = NULL;
2590
Jing Zhou30504bd2017-11-21 11:36:07 -08002591 struct cam_req_mgr_connected_device *dev = NULL;
2592 struct cam_req_mgr_link_evt_data evt_data;
2593
Jing Zhou0f645332017-11-17 12:16:40 -08002594 if (!control) {
2595 CAM_ERR(CAM_CRM, "Control command is NULL");
2596 rc = -EINVAL;
2597 goto end;
2598 }
2599
2600 mutex_lock(&g_crm_core_dev->crm_lock);
2601 for (i = 0; i < control->num_links; i++) {
2602 link = (struct cam_req_mgr_core_link *)
2603 cam_get_device_priv(control->link_hdls[i]);
2604 if (!link) {
2605 CAM_ERR(CAM_CRM, "Link(%d) is NULL on session 0x%x",
2606 i, control->session_hdl);
2607 rc = -EINVAL;
2608 break;
2609 }
2610
2611 mutex_lock(&link->lock);
2612 if (control->ops == CAM_REQ_MGR_LINK_ACTIVATE) {
2613 /* Start SOF watchdog timer */
2614 rc = crm_timer_init(&link->watchdog,
2615 CAM_REQ_MGR_WATCHDOG_TIMEOUT, link,
2616 &__cam_req_mgr_sof_freeze);
2617 if (rc < 0) {
2618 CAM_ERR(CAM_CRM,
2619 "SOF timer start fails: link=0x%x",
2620 link->link_hdl);
2621 rc = -EFAULT;
2622 }
Jing Zhou30504bd2017-11-21 11:36:07 -08002623 /* notify nodes */
2624 for (j = 0; j < link->num_devs; j++) {
2625 dev = &link->l_dev[j];
2626 evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_RESUME;
2627 evt_data.link_hdl = link->link_hdl;
2628 evt_data.dev_hdl = dev->dev_hdl;
2629 evt_data.req_id = 0;
2630 if (dev->ops && dev->ops->process_evt)
2631 dev->ops->process_evt(&evt_data);
2632 }
Jing Zhou0f645332017-11-17 12:16:40 -08002633 } else if (control->ops == CAM_REQ_MGR_LINK_DEACTIVATE) {
2634 /* Destroy SOF watchdog timer */
Venkat Chinta686c9e52018-01-20 14:33:25 -08002635 spin_lock_bh(&link->link_state_spin_lock);
Jing Zhou0f645332017-11-17 12:16:40 -08002636 crm_timer_exit(&link->watchdog);
Venkat Chinta686c9e52018-01-20 14:33:25 -08002637 spin_unlock_bh(&link->link_state_spin_lock);
Jing Zhou30504bd2017-11-21 11:36:07 -08002638 /* notify nodes */
2639 for (j = 0; j < link->num_devs; j++) {
2640 dev = &link->l_dev[j];
2641 evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_PAUSE;
2642 evt_data.link_hdl = link->link_hdl;
2643 evt_data.dev_hdl = dev->dev_hdl;
2644 evt_data.req_id = 0;
2645 if (dev->ops && dev->ops->process_evt)
2646 dev->ops->process_evt(&evt_data);
2647 }
Jing Zhou0f645332017-11-17 12:16:40 -08002648 } else {
2649 CAM_ERR(CAM_CRM, "Invalid link control command");
2650 rc = -EINVAL;
2651 }
2652 mutex_unlock(&link->lock);
2653 }
2654 mutex_unlock(&g_crm_core_dev->crm_lock);
2655end:
2656 return rc;
2657}
2658
Sagar Gore8d91a622017-02-23 14:57:18 -08002659
2660int cam_req_mgr_core_device_init(void)
2661{
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002662 CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002663
2664 if (g_crm_core_dev) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002665 CAM_WARN(CAM_CRM, "core device is already initialized");
Sagar Gore8d91a622017-02-23 14:57:18 -08002666 return 0;
2667 }
2668 g_crm_core_dev = (struct cam_req_mgr_core_device *)
2669 kzalloc(sizeof(*g_crm_core_dev), GFP_KERNEL);
2670 if (!g_crm_core_dev)
2671 return -ENOMEM;
2672
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002673 CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002674 INIT_LIST_HEAD(&g_crm_core_dev->session_head);
2675 mutex_init(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002676 cam_req_mgr_debug_register(g_crm_core_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002677
2678 return 0;
2679}
2680
2681int cam_req_mgr_core_device_deinit(void)
2682{
2683 if (!g_crm_core_dev) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002684 CAM_ERR(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002685 return -EINVAL;
2686 }
2687
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002688 CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002689 mutex_destroy(&g_crm_core_dev->crm_lock);
2690 kfree(g_crm_core_dev);
2691 g_crm_core_dev = NULL;
2692
2693 return 0;
2694}