blob: 3e6b856bfc556aef388a912ae600ab0bb20e9710 [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) &&
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800203 (traverse_data->self_link == true)) {
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;
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800447 CAM_DBG(CAM_CRM, "SEND: link_hdl: %x pd %d req_id %lld",
448 link->link_hdl, pd, apply_req.request_id);
Sagar Gored79f95e2017-03-14 18:32:17 -0700449 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
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800482 * @self_link : To indicate whether the validation is for the given link or
483 * other sync link
Sagar Gored79f95e2017-03-14 18:32:17 -0700484 *
485 * @return : 0 for success, negative for failure
486 *
487 */
488static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800489 int32_t idx, bool validate_only, bool self_link)
Sagar Gored79f95e2017-03-14 18:32:17 -0700490{
491 int rc;
492 struct cam_req_mgr_traverse traverse_data;
493 struct cam_req_mgr_req_queue *in_q;
494 struct cam_req_mgr_apply *apply_data;
495
496 in_q = link->req.in_q;
497
498 apply_data = link->req.apply_data;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800499
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800500 if (validate_only == false) {
501 memset(apply_data, 0,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800502 sizeof(struct cam_req_mgr_apply) * CAM_PIPELINE_DELAY_MAX);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800503 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700504
505 traverse_data.apply_data = apply_data;
506 traverse_data.idx = idx;
507 traverse_data.tbl = link->req.l_tbl;
508 traverse_data.in_q = in_q;
509 traverse_data.result = 0;
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800510 traverse_data.validate_only = validate_only;
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800511 traverse_data.self_link = self_link;
Sagar Gored79f95e2017-03-14 18:32:17 -0700512 /*
513 * Traverse through all pd tables, if result is success,
514 * apply the settings
515 */
516
517 rc = __cam_req_mgr_traverse(&traverse_data);
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800518 CAM_DBG(CAM_CRM,
519 "SOF: idx %d self_link %d validate %d result %x pd_mask %x rc %d",
520 idx, traverse_data.self_link, traverse_data.validate_only,
521 traverse_data.result, link->pd_mask, rc);
Sagar Gored79f95e2017-03-14 18:32:17 -0700522
Venkat Chintaddbe5132018-01-30 12:00:29 -0800523 if (!rc && traverse_data.result == link->pd_mask) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700524 CAM_DBG(CAM_CRM,
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800525 "APPLY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
Sagar Gored79f95e2017-03-14 18:32:17 -0700526 link->link_hdl, idx,
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800527 apply_data[2].req_id,
528 apply_data[1].req_id,
Sagar Gored79f95e2017-03-14 18:32:17 -0700529 apply_data[0].req_id);
Venkat Chintaddbe5132018-01-30 12:00:29 -0800530 } else
531 rc = -EAGAIN;
Sagar Gored79f95e2017-03-14 18:32:17 -0700532
533 return rc;
534}
535
536/**
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800537 * __cam_req_mgr_find_slot_for_req()
538 *
539 * @brief : Find idx from input queue at which req id is enqueued
540 * @in_q : input request queue pointer
541 * @req_id : request id which needs to be searched in input queue
542 *
543 * @return : slot index where passed request id is stored, -1 for failure
544 *
545 */
546static int32_t __cam_req_mgr_find_slot_for_req(
547 struct cam_req_mgr_req_queue *in_q, int64_t req_id)
548{
549 int32_t idx, i;
550 struct cam_req_mgr_slot *slot;
551
552 idx = in_q->rd_idx;
553 for (i = 0; i < in_q->num_slots; i++) {
554 slot = &in_q->slot[idx];
555 if (slot->req_id == req_id) {
556 CAM_DBG(CAM_CRM,
557 "req: %lld found at idx: %d status: %d sync_mode: %d",
558 req_id, idx, slot->status, slot->sync_mode);
559 break;
560 }
561 __cam_req_mgr_dec_idx(&idx, 1, in_q->num_slots);
562 }
563 if (i >= in_q->num_slots)
564 idx = -1;
565
566 return idx;
567}
568
569/**
570 * __cam_req_mgr_reset_sof_cnt()
571 *
572 * @brief : the sof_count for both the links are reset
573 * @link : pointer to link whose input queue and req tbl are
574 * traversed through
575 *
576 */
577static void __cam_req_mgr_reset_sof_cnt(
578 struct cam_req_mgr_core_link *link)
579{
580 link->sof_counter = -1;
581 link->sync_link->sof_counter = -1;
582 link->frame_skip_flag = false;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800583
584 CAM_DBG(CAM_CRM,
585 "link_hdl %x self_counter %lld other_counter %lld frame_skip_lag %d",
586 link->link_hdl, link->sof_counter,
587 link->sync_link->sof_counter, link->frame_skip_flag);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800588}
589
590/**
591 * __cam_req_mgr_sof_cnt_initialize()
592 *
593 * @brief : when the sof count is intially -1 it increments count
594 * and computes the sync_self_ref for this link
595 * the count needs to be wrapped back starting from 0
596 * @link : pointer to link whose input queue and req tbl are
597 * traversed through
598 *
599 */
600static void __cam_req_mgr_sof_cnt_initialize(
601 struct cam_req_mgr_core_link *link)
602{
603 link->sof_counter++;
604 link->sync_self_ref = link->sof_counter -
605 link->sync_link->sof_counter;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800606
607 CAM_DBG(CAM_CRM,
608 "link_hdl %x self_counter %lld other_counter %lld",
609 link->link_hdl, link->sof_counter,
610 link->sync_link->sof_counter);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800611}
612
613/**
614 * __cam_req_mgr_wrap_sof_cnt()
615 *
616 * @brief : once the sof count reaches a predefined maximum
617 * the count needs to be wrapped back starting from 0
618 * @link : pointer to link whose input queue and req tbl are
619 * traversed through
620 *
621 */
622static void __cam_req_mgr_wrap_sof_cnt(
623 struct cam_req_mgr_core_link *link)
624{
625 link->sof_counter = (MAX_SYNC_COUNT -
626 (link->sync_link->sof_counter));
627 link->sync_link->sof_counter = 0;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800628
629 CAM_DBG(CAM_CRM,
630 "link_hdl %x self_counter %lld sync_link_hdl %x other_counter %lld",
631 link->link_hdl, link->sof_counter,
632 link->sync_link->link_hdl, link->sync_link->sof_counter);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800633}
634
635/**
636 * __cam_req_mgr_validate_sof_cnt()
637 *
638 * @brief : validates sof count difference for a given link
639 * @link : pointer to link whose input queue and req tbl are
640 * traversed through
641 * @sync_link : pointer to the sync link
642 * @return : 0 for success, negative for failure
643 *
644 */
645static int __cam_req_mgr_validate_sof_cnt(
646 struct cam_req_mgr_core_link *link,
647 struct cam_req_mgr_core_link *sync_link)
648{
649 int64_t sync_diff = 0;
650 int rc = 0;
651
652 if (link->sof_counter == MAX_SYNC_COUNT)
653 __cam_req_mgr_wrap_sof_cnt(link);
654
655 sync_diff = link->sof_counter - sync_link->sof_counter;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800656
657 CAM_DBG(CAM_CRM,
658 "link[%x] self_counter=%lld other_counter=%lld diff=%lld sync_self_ref=%lld",
659 link->link_hdl, link->sof_counter,
660 sync_link->sof_counter, sync_diff, link->sync_self_ref);
661
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800662 if (sync_diff != link->sync_self_ref) {
663 link->sync_link->frame_skip_flag = true;
664 CAM_WARN(CAM_CRM,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800665 "Detected anomaly, skip link_hdl %x self_counter=%lld other_counter=%lld sync_self_ref=%lld",
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800666 link->link_hdl, link->sof_counter,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800667 sync_link->sof_counter, link->sync_self_ref);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800668 rc = -EPERM;
669 }
670
671 return rc;
672}
673
674
675/**
676 * __cam_req_mgr_process_sync_req()
677 *
678 * @brief : processes requests during sync mode
679 * @link : pointer to link whose input queue and req tbl are
680 * traversed through
681 * @slot : pointer to the current slot being processed
682 * @return : 0 for success, negative for failure
683 *
684 */
685static int __cam_req_mgr_process_sync_req(
686 struct cam_req_mgr_core_link *link,
Venkat Chintaddbe5132018-01-30 12:00:29 -0800687 struct cam_req_mgr_slot *slot)
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800688{
689 struct cam_req_mgr_core_link *sync_link = NULL;
690 int64_t req_id = 0;
691 int sync_slot_idx = 0, rc = 0;
692
693 if (!link->sync_link) {
694 CAM_ERR(CAM_CRM, "Sync link null");
695 return -EINVAL;
696 }
697
698 sync_link = link->sync_link;
699 req_id = slot->req_id;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800700
701 CAM_DBG(CAM_CRM,
702 "link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld",
703 link->link_hdl, req_id, link->sync_self_ref, link->sof_counter,
704 link->frame_skip_flag, link->sync_link->sync_self_ref);
705
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800706 if (link->sof_counter == -1) {
707 __cam_req_mgr_sof_cnt_initialize(link);
Venkat Chinta686c9e52018-01-20 14:33:25 -0800708 } else if ((link->frame_skip_flag) &&
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800709 (sync_link->sync_self_ref != -1)) {
Venkat Chinta686c9e52018-01-20 14:33:25 -0800710 CAM_DBG(CAM_CRM, "Link[%x] Req[%lld] Resetting values ",
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800711 link->link_hdl, req_id);
712 __cam_req_mgr_reset_sof_cnt(link);
713 __cam_req_mgr_sof_cnt_initialize(link);
714 } else {
715 link->sof_counter++;
716 }
717
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800718 rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800719 if (rc) {
720 CAM_DBG(CAM_CRM,
721 "Req: %lld [My link]not available link: %x, rc=%d",
722 req_id, link->link_hdl, rc);
723 goto failure;
724 }
725
726 sync_slot_idx = __cam_req_mgr_find_slot_for_req(
727 sync_link->req.in_q, req_id);
Venkat Chinta686c9e52018-01-20 14:33:25 -0800728
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800729 if (sync_slot_idx != -1) {
730 rc = __cam_req_mgr_check_link_is_ready(
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800731 sync_link, sync_slot_idx, true, false);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800732 CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d",
733 sync_slot_idx,
734 sync_link->req.in_q->slot[sync_slot_idx].status,
735 rc);
736 } else {
737 CAM_DBG(CAM_CRM, "sync_slot_idx=%d, rc=%d",
738 sync_slot_idx, rc);
739 }
740
741 if ((sync_slot_idx != -1) &&
Venkat Chintaddbe5132018-01-30 12:00:29 -0800742 ((sync_link->req.in_q->slot[sync_slot_idx].status ==
743 CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800744 rc = __cam_req_mgr_validate_sof_cnt(link, sync_link);
745 if (rc) {
746 CAM_DBG(CAM_CRM,
747 "Req: %lld validate failed: %x",
748 req_id, sync_link->link_hdl);
749 goto failure;
750 }
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800751
752 CAM_DBG(CAM_CRM,
753 "Req: %lld ready to apply on link: %x [validation successful]",
754 req_id, link->link_hdl);
755 /*
756 * At this point all validation is successfully done
757 * and we can proceed to apply the given request.
758 * Ideally the next call should return success.
759 */
760 rc = __cam_req_mgr_check_link_is_ready(link,
761 slot->idx, false, true);
762
763 if (rc) {
764 CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
765 }
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800766 } else {
767 CAM_DBG(CAM_CRM,
768 "Req: %lld [Other link] not ready to apply on link: %x",
769 req_id, sync_link->link_hdl);
770 rc = -EPERM;
771 goto failure;
772 }
773
774 return rc;
775
776failure:
777 link->sof_counter--;
778 return rc;
779}
780
781/**
Sagar Gored79f95e2017-03-14 18:32:17 -0700782 * __cam_req_mgr_process_req()
783 *
784 * @brief : processes read index in request queue and traverse through table
785 * @link : pointer to link whose input queue and req tbl are
786 * traversed through
787 *
788 * @return : 0 for success, negative for failure
789 *
790 */
Junzhe Zou2df84502017-05-26 13:20:23 -0700791static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
792 uint32_t trigger)
Sagar Gored79f95e2017-03-14 18:32:17 -0700793{
Venkat Chintaddbe5132018-01-30 12:00:29 -0800794 int rc = 0, idx;
Sagar Gored79f95e2017-03-14 18:32:17 -0700795 struct cam_req_mgr_slot *slot = NULL;
796 struct cam_req_mgr_req_queue *in_q;
797 struct cam_req_mgr_core_session *session;
798
799 in_q = link->req.in_q;
800 session = (struct cam_req_mgr_core_session *)link->parent;
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800801 mutex_lock(&session->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -0700802 /*
Junzhe Zou2df84502017-05-26 13:20:23 -0700803 * Check if new read index,
Sagar Gored79f95e2017-03-14 18:32:17 -0700804 * - if in pending state, traverse again to complete
805 * transaction of this read index.
806 * - if in applied_state, somthign wrong.
807 * - if in no_req state, no new req
808 */
Venkat Chinta686c9e52018-01-20 14:33:25 -0800809 CAM_DBG(CAM_CRM, "SOF Req[%lld] idx %d req_status %d link_hdl %x",
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800810 in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx,
Venkat Chinta686c9e52018-01-20 14:33:25 -0800811 in_q->slot[in_q->rd_idx].status, link->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -0700812
813 slot = &in_q->slot[in_q->rd_idx];
814 if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700815 CAM_DBG(CAM_CRM, "No Pending req");
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800816 rc = 0;
817 goto error;
Sagar Gored79f95e2017-03-14 18:32:17 -0700818 }
819
Venkat Chinta686c9e52018-01-20 14:33:25 -0800820 if ((trigger != CAM_TRIGGER_POINT_SOF) &&
821 (trigger != CAM_TRIGGER_POINT_EOF))
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800822 goto error;
823
824 if ((trigger == CAM_TRIGGER_POINT_EOF) &&
825 (!(link->trigger_mask & CAM_TRIGGER_POINT_SOF))) {
826 CAM_DBG(CAM_CRM, "Applying for last SOF fails");
827 rc = -EINVAL;
828 goto error;
829 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700830
Junzhe Zou2df84502017-05-26 13:20:23 -0700831 if (trigger == CAM_TRIGGER_POINT_SOF) {
Junzhe Zou3f77d832017-08-25 14:55:23 -0700832 if (link->trigger_mask) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700833 CAM_ERR_RATE_LIMIT(CAM_CRM,
834 "Applying for last EOF fails");
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800835 rc = -EINVAL;
836 goto error;
Junzhe Zou2df84502017-05-26 13:20:23 -0700837 }
Junzhe Zou2df84502017-05-26 13:20:23 -0700838
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800839 if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)
Venkat Chintaddbe5132018-01-30 12:00:29 -0800840 rc = __cam_req_mgr_process_sync_req(link, slot);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800841 else
842 rc = __cam_req_mgr_check_link_is_ready(link,
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -0800843 slot->idx, false, true);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800844
845 if (rc < 0) {
846 /*
847 * If traverse result is not success, then some devices
848 * are not ready with packet for the asked request id,
849 * hence try again in next sof
850 */
Junzhe Zou2df84502017-05-26 13:20:23 -0700851 slot->status = CRM_SLOT_STATUS_REQ_PENDING;
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +0530852 spin_lock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -0700853 if (link->state == CAM_CRM_LINK_STATE_ERR) {
Junzhe Zou2df84502017-05-26 13:20:23 -0700854 /*
855 * During error recovery all tables should be
856 * ready, don't expect to enter here.
857 * @TODO: gracefully handle if recovery fails.
858 */
Harsh Shahcb0072c2017-09-26 19:22:10 -0700859 CAM_ERR_RATE_LIMIT(CAM_CRM,
Junzhe Zou2df84502017-05-26 13:20:23 -0700860 "FATAL recovery cant finish idx %d status %d",
Sagar Gored79f95e2017-03-14 18:32:17 -0700861 in_q->rd_idx,
862 in_q->slot[in_q->rd_idx].status);
Junzhe Zou2df84502017-05-26 13:20:23 -0700863 rc = -EPERM;
Sagar Gored79f95e2017-03-14 18:32:17 -0700864 }
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +0530865 spin_unlock_bh(&link->link_state_spin_lock);
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800866 goto error;
Junzhe Zou2df84502017-05-26 13:20:23 -0700867 }
868 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700869
Junzhe Zou2df84502017-05-26 13:20:23 -0700870 rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger);
871 if (rc < 0) {
872 /* Apply req failed retry at next sof */
873 slot->status = CRM_SLOT_STATUS_REQ_PENDING;
874 } else {
875 link->trigger_mask |= trigger;
876
Venkat Chinta686c9e52018-01-20 14:33:25 -0800877 CAM_DBG(CAM_CRM, "Applied req[%lld] on link[%x] success",
878 slot->req_id, link->link_hdl);
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +0530879 spin_lock_bh(&link->link_state_spin_lock);
Junzhe Zou2df84502017-05-26 13:20:23 -0700880 if (link->state == CAM_CRM_LINK_STATE_ERR) {
881 CAM_WARN(CAM_CRM, "Err recovery done idx %d",
882 in_q->rd_idx);
Junzhe Zou2df84502017-05-26 13:20:23 -0700883 link->state = CAM_CRM_LINK_STATE_READY;
Junzhe Zou2df84502017-05-26 13:20:23 -0700884 }
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +0530885 spin_unlock_bh(&link->link_state_spin_lock);
886
Junzhe Zou2df84502017-05-26 13:20:23 -0700887 if (link->trigger_mask == link->subscribe_event) {
Venkat Chintaddbe5132018-01-30 12:00:29 -0800888 slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
Junzhe Zou2df84502017-05-26 13:20:23 -0700889 link->trigger_mask = 0;
Venkat Chinta686c9e52018-01-20 14:33:25 -0800890 CAM_DBG(CAM_CRM, "req %d is applied on link %x",
Venkat Chintaddbe5132018-01-30 12:00:29 -0800891 slot->req_id,
892 link->link_hdl);
893 idx = in_q->rd_idx;
894 __cam_req_mgr_dec_idx(
895 &idx, link->max_delay + 1,
896 in_q->num_slots);
897 __cam_req_mgr_reset_req_slot(link, idx);
Sagar Gored79f95e2017-03-14 18:32:17 -0700898 }
Sagar Gored79f95e2017-03-14 18:32:17 -0700899 }
Venkat Chinta686c9e52018-01-20 14:33:25 -0800900
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800901 mutex_unlock(&session->lock);
902 return rc;
Karthik Anantha Ramfa643332017-11-06 13:49:31 -0800903error:
904 mutex_unlock(&session->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -0700905 return rc;
906}
907
908/**
909 * __cam_req_mgr_add_tbl_to_link()
910 *
911 * @brief : Add table to list under link sorted by pd decremeting order
912 * @l_tbl : list of pipeline delay tables.
Junzhe Zou2df84502017-05-26 13:20:23 -0700913 * @new_tbl : new tbl which will be appended to above list as per its pd value
Sagar Gored79f95e2017-03-14 18:32:17 -0700914 *
915 */
916static void __cam_req_mgr_add_tbl_to_link(struct cam_req_mgr_req_tbl **l_tbl,
917 struct cam_req_mgr_req_tbl *new_tbl)
918{
919 struct cam_req_mgr_req_tbl *tbl;
920
921 if (!(*l_tbl) || (*l_tbl)->pd < new_tbl->pd) {
922 new_tbl->next = *l_tbl;
923 if (*l_tbl) {
924 new_tbl->pd_delta =
925 new_tbl->pd - (*l_tbl)->pd;
926 }
927 *l_tbl = new_tbl;
928 } else {
929 tbl = *l_tbl;
930
931 /* Reach existing tbl which has less pd value */
932 while (tbl->next != NULL &&
933 new_tbl->pd < tbl->next->pd) {
934 tbl = tbl->next;
935 }
936 if (tbl->next != NULL) {
937 new_tbl->pd_delta =
938 new_tbl->pd - tbl->next->pd;
939 } else {
940 /* This is last table in linked list*/
941 new_tbl->pd_delta = 0;
942 }
943 new_tbl->next = tbl->next;
944 tbl->next = new_tbl;
945 tbl->pd_delta = tbl->pd - new_tbl->pd;
946 }
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700947 CAM_DBG(CAM_CRM, "added pd %d tbl to link delta %d", new_tbl->pd,
Sagar Gored79f95e2017-03-14 18:32:17 -0700948 new_tbl->pd_delta);
949}
950
951/**
952 * __cam_req_mgr_create_pd_tbl()
953 *
954 * @brief : Creates new request table for new delay value
955 * @delay : New pd table allocated will have this delay value
956 *
957 * @return : pointer to newly allocated table, NULL for failure
958 *
959 */
960static struct cam_req_mgr_req_tbl *__cam_req_mgr_create_pd_tbl(int32_t delay)
961{
962 struct cam_req_mgr_req_tbl *tbl =
963 kzalloc(sizeof(struct cam_req_mgr_req_tbl), GFP_KERNEL);
964 if (tbl != NULL) {
965 tbl->num_slots = MAX_REQ_SLOTS;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700966 CAM_DBG(CAM_CRM, "pd= %d slots= %d", delay, tbl->num_slots);
Sagar Gored79f95e2017-03-14 18:32:17 -0700967 }
968
969 return tbl;
970}
971
972/**
973 * __cam_req_mgr_destroy_all_tbl()
974 *
975 * @brief : This func will destroy all pipeline delay based req table structs
976 * @l_tbl : pointer to first table in list and it has max pd .
977 *
978 */
979static void __cam_req_mgr_destroy_all_tbl(struct cam_req_mgr_req_tbl **l_tbl)
980{
981 struct cam_req_mgr_req_tbl *tbl = *l_tbl, *temp;
982
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700983 CAM_DBG(CAM_CRM, "*l_tbl %pK", tbl);
Sagar Gored79f95e2017-03-14 18:32:17 -0700984 while (tbl != NULL) {
985 temp = tbl->next;
986 kfree(tbl);
987 tbl = temp;
988 }
989 *l_tbl = NULL;
990}
991
992/**
Sagar Gored79f95e2017-03-14 18:32:17 -0700993 * __cam_req_mgr_setup_in_q()
994 *
995 * @brief : Initialize req table data
996 * @req : request data pointer
997 *
998 * @return: 0 for success, negative for failure
999 *
1000 */
1001static int __cam_req_mgr_setup_in_q(struct cam_req_mgr_req_data *req)
1002{
1003 int i;
1004 struct cam_req_mgr_req_queue *in_q = req->in_q;
1005
1006 if (!in_q) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001007 CAM_ERR(CAM_CRM, "NULL in_q");
Sagar Gored79f95e2017-03-14 18:32:17 -07001008 return -EINVAL;
1009 }
1010
1011 mutex_lock(&req->lock);
1012 in_q->num_slots = MAX_REQ_SLOTS;
1013
1014 for (i = 0; i < in_q->num_slots; i++) {
1015 in_q->slot[i].idx = i;
1016 in_q->slot[i].req_id = -1;
1017 in_q->slot[i].skip_idx = 0;
1018 in_q->slot[i].status = CRM_SLOT_STATUS_NO_REQ;
1019 }
1020
1021 in_q->wr_idx = 0;
1022 in_q->rd_idx = 0;
1023 mutex_unlock(&req->lock);
1024
1025 return 0;
1026}
1027
1028/**
1029 * __cam_req_mgr_reset_req_tbl()
1030 *
1031 * @brief : Initialize req table data
1032 * @req : request queue pointer
1033 *
1034 * @return: 0 for success, negative for failure
1035 *
1036 */
1037static int __cam_req_mgr_reset_in_q(struct cam_req_mgr_req_data *req)
1038{
1039 struct cam_req_mgr_req_queue *in_q = req->in_q;
1040
1041 if (!in_q) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001042 CAM_ERR(CAM_CRM, "NULL in_q");
Sagar Gored79f95e2017-03-14 18:32:17 -07001043 return -EINVAL;
1044 }
1045
1046 mutex_lock(&req->lock);
1047 memset(in_q->slot, 0,
1048 sizeof(struct cam_req_mgr_slot) * in_q->num_slots);
1049 in_q->num_slots = 0;
1050
1051 in_q->wr_idx = 0;
1052 in_q->rd_idx = 0;
1053 mutex_unlock(&req->lock);
1054
1055 return 0;
1056}
1057
1058/**
1059 * __cam_req_mgr_sof_freeze()
1060 *
1061 * @brief : Apoptosis - Handles case when connected devices are not responding
1062 * @data : timer pointer
1063 *
1064 */
1065static void __cam_req_mgr_sof_freeze(unsigned long data)
1066{
Harsh Shah67fa2312017-10-30 04:03:07 -07001067 struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
1068 struct cam_req_mgr_core_link *link = NULL;
1069 struct cam_req_mgr_core_session *session = NULL;
1070 struct cam_req_mgr_message msg;
Sagar Gore8d91a622017-02-23 14:57:18 -08001071
Sagar Gored79f95e2017-03-14 18:32:17 -07001072 if (!timer) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001073 CAM_ERR(CAM_CRM, "NULL timer");
Sagar Gored79f95e2017-03-14 18:32:17 -07001074 return;
1075 }
1076 link = (struct cam_req_mgr_core_link *)timer->parent;
Harsh Shah67fa2312017-10-30 04:03:07 -07001077 session = (struct cam_req_mgr_core_session *)link->parent;
1078
1079 CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x",
1080 session->session_hdl, link->link_hdl);
1081
1082 memset(&msg, 0, sizeof(msg));
1083
1084 msg.session_hdl = session->session_hdl;
1085 msg.u.err_msg.error_type = CAM_REQ_MGR_ERROR_TYPE_DEVICE;
1086 msg.u.err_msg.request_id = 0;
1087 msg.u.err_msg.link_hdl = link->link_hdl;
1088
1089
1090 if (cam_req_mgr_notify_message(&msg,
1091 V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT))
1092 CAM_ERR(CAM_CRM,
1093 "Error notifying SOF freeze for session %d link 0x%x",
1094 session->session_hdl, link->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07001095}
1096
1097/**
1098 * __cam_req_mgr_create_subdevs()
1099 *
1100 * @brief : Create new crm subdev to link with realtime devices
1101 * @l_dev : list of subdevs internal to crm
1102 * @num_dev : num of subdevs to be created for link
1103 *
1104 * @return : pointer to allocated list of devices
1105 */
1106static int __cam_req_mgr_create_subdevs(
1107 struct cam_req_mgr_connected_device **l_dev, int32_t num_dev)
1108{
1109 int rc = 0;
1110 *l_dev = (struct cam_req_mgr_connected_device *)
1111 kzalloc(sizeof(struct cam_req_mgr_connected_device) * num_dev,
1112 GFP_KERNEL);
1113 if (!*l_dev)
1114 rc = -ENOMEM;
1115
1116 return rc;
1117}
1118
1119/**
1120 * __cam_req_mgr_destroy_subdev()
1121 *
1122 * @brief : Cleans up the subdevs allocated by crm for link
1123 * @l_device : pointer to list of subdevs crm created
1124 *
1125 */
1126static void __cam_req_mgr_destroy_subdev(
1127 struct cam_req_mgr_connected_device *l_device)
1128{
1129 kfree(l_device);
1130 l_device = NULL;
1131}
1132
1133/**
1134 * __cam_req_mgr_destroy_link_info()
1135 *
1136 * @brief : Cleans up the mem allocated while linking
1137 * @link : pointer to link, mem associated with this link is freed
1138 *
Venkat Chinta686c9e52018-01-20 14:33:25 -08001139 * @return : returns if unlink for any device was success or failure
Sagar Gored79f95e2017-03-14 18:32:17 -07001140 */
Venkat Chinta686c9e52018-01-20 14:33:25 -08001141static int __cam_req_mgr_destroy_link_info(struct cam_req_mgr_core_link *link)
Sagar Gored79f95e2017-03-14 18:32:17 -07001142{
1143 int32_t i = 0;
1144 struct cam_req_mgr_connected_device *dev;
1145 struct cam_req_mgr_core_dev_link_setup link_data;
Harsh Shaha606d182017-11-10 00:15:58 -08001146 int rc = 0;
Sagar Gored79f95e2017-03-14 18:32:17 -07001147
Sagar Gored79f95e2017-03-14 18:32:17 -07001148 link_data.link_enable = 0;
1149 link_data.link_hdl = link->link_hdl;
1150 link_data.crm_cb = NULL;
Junzhe Zou2df84502017-05-26 13:20:23 -07001151 link_data.subscribe_event = 0;
Sagar Gored79f95e2017-03-14 18:32:17 -07001152
1153 /* Using device ops unlink devices */
1154 for (i = 0; i < link->num_devs; i++) {
1155 dev = &link->l_dev[i];
1156 if (dev != NULL) {
Soundrapandian Jeyaprakash74946262017-08-11 18:23:47 -07001157 link_data.dev_hdl = dev->dev_hdl;
Lynus Vaz345e6a02017-12-04 17:02:12 +05301158 if (dev->ops && dev->ops->link_setup) {
Harsh Shaha606d182017-11-10 00:15:58 -08001159 rc = dev->ops->link_setup(&link_data);
1160 if (rc)
1161 CAM_ERR(CAM_CRM,
Venkat Chinta686c9e52018-01-20 14:33:25 -08001162 "Unlink failed dev_hdl %d",
1163 dev->dev_hdl);
Lynus Vaz345e6a02017-12-04 17:02:12 +05301164 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001165 dev->dev_hdl = 0;
1166 dev->parent = NULL;
1167 dev->ops = NULL;
1168 }
1169 }
1170 __cam_req_mgr_destroy_all_tbl(&link->req.l_tbl);
1171 __cam_req_mgr_reset_in_q(&link->req);
1172 link->req.num_tbl = 0;
1173 mutex_destroy(&link->req.lock);
1174
1175 link->pd_mask = 0;
1176 link->num_devs = 0;
1177 link->max_delay = 0;
Venkat Chinta686c9e52018-01-20 14:33:25 -08001178
1179 return rc;
Sagar Gored79f95e2017-03-14 18:32:17 -07001180}
1181
1182/**
1183 * __cam_req_mgr_reserve_link()
1184 *
1185 * @brief: Reserves one link data struct within session
1186 * @session: session identifier
1187 *
1188 * @return: pointer to link reserved
1189 *
1190 */
1191static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
1192 struct cam_req_mgr_core_session *session)
1193{
1194 struct cam_req_mgr_core_link *link;
1195 struct cam_req_mgr_req_queue *in_q;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001196 int i;
Sagar Gored79f95e2017-03-14 18:32:17 -07001197
1198 if (!session || !g_crm_core_dev) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001199 CAM_ERR(CAM_CRM, "NULL session/core_dev ptr");
Sagar Gore8d91a622017-02-23 14:57:18 -08001200 return NULL;
1201 }
1202
Sagar Gored79f95e2017-03-14 18:32:17 -07001203 if (session->num_links >= MAX_LINKS_PER_SESSION) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001204 CAM_ERR(CAM_CRM, "Reached max links %d per session limit %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001205 session->num_links, MAX_LINKS_PER_SESSION);
1206 return NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001207 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001208
1209 link = (struct cam_req_mgr_core_link *)
1210 kzalloc(sizeof(struct cam_req_mgr_core_link), GFP_KERNEL);
1211 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001212 CAM_ERR(CAM_CRM, "failed to create link, no mem");
Sagar Gored79f95e2017-03-14 18:32:17 -07001213 return NULL;
1214 }
Sagar Gored46e67d2017-08-31 17:05:46 -07001215 in_q = (struct cam_req_mgr_req_queue *)
1216 kzalloc(sizeof(struct cam_req_mgr_req_queue), GFP_KERNEL);
1217 if (!in_q) {
1218 CAM_ERR(CAM_CRM, "failed to create input queue, no mem");
1219 kfree(link);
1220 return NULL;
1221 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001222 mutex_init(&link->lock);
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301223 spin_lock_init(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001224
1225 mutex_lock(&link->lock);
1226 link->state = CAM_CRM_LINK_STATE_AVAILABLE;
1227 link->num_devs = 0;
1228 link->max_delay = 0;
1229 memset(in_q->slot, 0,
1230 sizeof(struct cam_req_mgr_slot) * MAX_REQ_SLOTS);
1231 link->req.in_q = in_q;
1232 in_q->num_slots = 0;
1233 link->state = CAM_CRM_LINK_STATE_IDLE;
1234 link->parent = (void *)session;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001235 link->sync_link = NULL;
Sagar Gored79f95e2017-03-14 18:32:17 -07001236 mutex_unlock(&link->lock);
1237
1238 mutex_lock(&session->lock);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001239 /* Loop through and find a free index */
1240 for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
1241 if (!session->links[i]) {
Venkat Chinta686c9e52018-01-20 14:33:25 -08001242 CAM_DBG(CAM_CRM,
1243 "Free link index %d found, num_links=%d",
1244 i, session->num_links);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001245 session->links[i] = link;
1246 break;
1247 }
1248 }
1249
1250 if (i == MAX_LINKS_PER_SESSION) {
1251 CAM_ERR(CAM_CRM, "Free link index not found");
1252 goto error;
1253 }
1254
Sagar Gored79f95e2017-03-14 18:32:17 -07001255 session->num_links++;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001256 CAM_DBG(CAM_CRM, "Active session links (%d)",
Sagar Gored79f95e2017-03-14 18:32:17 -07001257 session->num_links);
1258 mutex_unlock(&session->lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08001259
1260 return link;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001261error:
1262 mutex_unlock(&session->lock);
1263 kfree(link);
1264 kfree(in_q);
1265 return NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001266}
1267
Sunil Khatribc029f72017-11-28 18:54:24 +05301268/*
1269 * __cam_req_mgr_free_link()
1270 *
1271 * @brief: Frees the link and its request queue
1272 *
1273 * @link: link identifier
1274 *
1275 */
1276static void __cam_req_mgr_free_link(struct cam_req_mgr_core_link *link)
1277{
1278 kfree(link->req.in_q);
1279 link->req.in_q = NULL;
1280 kfree(link);
1281}
1282
Sagar Gore8d91a622017-02-23 14:57:18 -08001283/**
Sagar Gored46e67d2017-08-31 17:05:46 -07001284 * __cam_req_mgr_unreserve_link()
Sagar Gored79f95e2017-03-14 18:32:17 -07001285 *
Sunil Khatribc029f72017-11-28 18:54:24 +05301286 * @brief : Removes the link data struct from the session and frees it
Sagar Gored79f95e2017-03-14 18:32:17 -07001287 * @session: session identifier
1288 * @link : link identifier
1289 *
1290 */
1291static void __cam_req_mgr_unreserve_link(
1292 struct cam_req_mgr_core_session *session,
Sunil Khatribc029f72017-11-28 18:54:24 +05301293 struct cam_req_mgr_core_link *link)
Sagar Gored79f95e2017-03-14 18:32:17 -07001294{
Sunil Khatribc029f72017-11-28 18:54:24 +05301295 int i;
Sagar Gored79f95e2017-03-14 18:32:17 -07001296
Sunil Khatribc029f72017-11-28 18:54:24 +05301297 if (!session || !link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001298 CAM_ERR(CAM_CRM, "NULL session/link ptr %pK %pK",
Sunil Khatribc029f72017-11-28 18:54:24 +05301299 session, link);
Sagar Gored79f95e2017-03-14 18:32:17 -07001300 return;
1301 }
1302
1303 mutex_lock(&session->lock);
Sunil Khatribc029f72017-11-28 18:54:24 +05301304 if (!session->num_links) {
1305 CAM_WARN(CAM_CRM, "No active link or invalid state: hdl %x",
1306 link->link_hdl);
1307 mutex_unlock(&session->lock);
1308 return;
Sagar Gored79f95e2017-03-14 18:32:17 -07001309 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001310
Sunil Khatribc029f72017-11-28 18:54:24 +05301311 for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
1312 if (session->links[i] == link)
1313 session->links[i] = NULL;
1314 }
1315
1316 if ((session->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC) &&
1317 (link->sync_link)) {
1318 /*
1319 * make sure to unlink sync setup under the assumption
1320 * of only having 2 links in a given session
1321 */
1322 session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
1323 for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
1324 if (session->links[i])
1325 session->links[i]->sync_link = NULL;
1326 }
1327 }
1328
1329 session->num_links--;
1330 CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links);
1331 mutex_unlock(&session->lock);
1332 __cam_req_mgr_free_link(link);
Sagar Gored79f95e2017-03-14 18:32:17 -07001333}
1334
1335/* Workqueue context processing section */
1336
1337/**
1338 * cam_req_mgr_process_send_req()
1339 *
1340 * @brief: This runs in workque thread context. Call core funcs to send
1341 * apply request id to drivers.
1342 * @priv : link information.
1343 * @data : contains information about frame_id, link etc.
1344 *
1345 * @return: 0 on success.
1346 */
1347int cam_req_mgr_process_send_req(void *priv, void *data)
1348{
1349 int rc = 0;
1350 struct cam_req_mgr_core_link *link = NULL;
1351 struct cam_req_mgr_send_request *send_req = NULL;
1352 struct cam_req_mgr_req_queue *in_q = NULL;
1353
1354 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001355 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001356 rc = -EINVAL;
1357 goto end;
1358 }
1359 link = (struct cam_req_mgr_core_link *)priv;
1360 send_req = (struct cam_req_mgr_send_request *)data;
1361 in_q = send_req->in_q;
1362
Junzhe Zou2df84502017-05-26 13:20:23 -07001363 rc = __cam_req_mgr_send_req(link, in_q, CAM_TRIGGER_POINT_SOF);
Sagar Gored79f95e2017-03-14 18:32:17 -07001364end:
1365 return rc;
1366}
1367
1368/**
1369 * cam_req_mgr_process_flush_req()
1370 *
1371 * @brief: This runs in workque thread context. Call core funcs to check
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001372 * which requests need to be removed/cancelled.
Sagar Gored79f95e2017-03-14 18:32:17 -07001373 * @priv : link information.
1374 * @data : contains information about frame_id, link etc.
1375 *
1376 * @return: 0 on success.
1377 */
1378int cam_req_mgr_process_flush_req(void *priv, void *data)
1379{
1380 int rc = 0, i = 0, idx = -1;
1381 struct cam_req_mgr_flush_info *flush_info = NULL;
1382 struct cam_req_mgr_core_link *link = NULL;
1383 struct cam_req_mgr_req_queue *in_q = NULL;
1384 struct cam_req_mgr_slot *slot = NULL;
1385 struct cam_req_mgr_connected_device *device = NULL;
1386 struct cam_req_mgr_flush_request flush_req;
1387 struct crm_task_payload *task_data = NULL;
1388
1389 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001390 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001391 rc = -EINVAL;
1392 goto end;
1393 }
1394 link = (struct cam_req_mgr_core_link *)priv;
1395 task_data = (struct crm_task_payload *)data;
1396 flush_info = (struct cam_req_mgr_flush_info *)&task_data->u;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001397 CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld type %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001398 flush_info->link_hdl,
1399 flush_info->req_id,
1400 flush_info->flush_type);
1401
1402 in_q = link->req.in_q;
1403
Gregory Bergschneider60679932017-07-19 15:27:16 -06001404 trace_cam_flush_req(link, flush_info);
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001405
Sagar Gored79f95e2017-03-14 18:32:17 -07001406 mutex_lock(&link->req.lock);
1407 if (flush_info->flush_type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
1408 for (i = 0; i < in_q->num_slots; i++) {
1409 slot = &in_q->slot[i];
1410 slot->req_id = -1;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001411 slot->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
Sagar Gored79f95e2017-03-14 18:32:17 -07001412 slot->skip_idx = 1;
1413 slot->status = CRM_SLOT_STATUS_NO_REQ;
1414 }
1415 in_q->wr_idx = 0;
1416 in_q->rd_idx = 0;
1417 } else if (flush_info->flush_type ==
1418 CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
1419 idx = __cam_req_mgr_find_slot_for_req(in_q, flush_info->req_id);
1420 if (idx < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001421 CAM_ERR(CAM_CRM, "req_id %lld not found in input queue",
Sagar Gored79f95e2017-03-14 18:32:17 -07001422 flush_info->req_id);
1423 } else {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001424 CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001425 flush_info->req_id, idx);
1426 slot = &in_q->slot[idx];
1427 if (slot->status == CRM_SLOT_STATUS_REQ_PENDING ||
1428 slot->status == CRM_SLOT_STATUS_REQ_APPLIED) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001429 CAM_WARN(CAM_CRM,
1430 "req_id %lld can not be cancelled",
Sagar Gored79f95e2017-03-14 18:32:17 -07001431 flush_info->req_id);
1432 mutex_unlock(&link->req.lock);
1433 return -EINVAL;
1434 }
1435 __cam_req_mgr_in_q_skip_idx(in_q, idx);
1436 }
1437 }
1438
1439 for (i = 0; i < link->num_devs; i++) {
1440 device = &link->l_dev[i];
1441 flush_req.link_hdl = flush_info->link_hdl;
1442 flush_req.dev_hdl = device->dev_hdl;
1443 flush_req.req_id = flush_info->req_id;
1444 flush_req.type = flush_info->flush_type;
1445 /* @TODO: error return handling from drivers */
1446 if (device->ops && device->ops->flush_req)
1447 rc = device->ops->flush_req(&flush_req);
1448 }
Alok Pandeya6bde9e2018-02-02 10:14:19 +05301449 complete(&link->workq_comp);
Sagar Gored79f95e2017-03-14 18:32:17 -07001450 mutex_unlock(&link->req.lock);
1451
Sagar Gored79f95e2017-03-14 18:32:17 -07001452end:
1453 return rc;
1454}
1455
1456/**
1457 * cam_req_mgr_process_sched_req()
1458 *
1459 * @brief: This runs in workque thread context. Call core funcs to check
1460 * which peding requests can be processed.
1461 * @priv : link information.
1462 * @data : contains information about frame_id, link etc.
1463 *
1464 * @return: 0 on success.
1465 */
1466int cam_req_mgr_process_sched_req(void *priv, void *data)
1467{
1468 int rc = 0;
1469 struct cam_req_mgr_sched_request *sched_req = NULL;
1470 struct cam_req_mgr_core_link *link = NULL;
1471 struct cam_req_mgr_req_queue *in_q = NULL;
1472 struct cam_req_mgr_slot *slot = NULL;
1473 struct crm_task_payload *task_data = NULL;
1474
1475 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001476 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001477 rc = -EINVAL;
1478 goto end;
1479 }
1480 link = (struct cam_req_mgr_core_link *)priv;
1481 task_data = (struct crm_task_payload *)data;
1482 sched_req = (struct cam_req_mgr_sched_request *)&task_data->u;
Sagar Gored79f95e2017-03-14 18:32:17 -07001483 in_q = link->req.in_q;
1484
Venkat Chinta686c9e52018-01-20 14:33:25 -08001485 CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld at slot %d sync_mode %d",
1486 sched_req->link_hdl, sched_req->req_id,
1487 in_q->wr_idx, sched_req->sync_mode);
1488
Sagar Gored79f95e2017-03-14 18:32:17 -07001489 mutex_lock(&link->req.lock);
1490 slot = &in_q->slot[in_q->wr_idx];
1491
1492 if (slot->status != CRM_SLOT_STATUS_NO_REQ &&
Sagar Goreb56c81e2017-05-08 17:15:47 -07001493 slot->status != CRM_SLOT_STATUS_REQ_APPLIED)
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001494 CAM_WARN(CAM_CRM, "in_q overwrite %d", slot->status);
Sagar Goreb56c81e2017-05-08 17:15:47 -07001495
Sagar Gored79f95e2017-03-14 18:32:17 -07001496 slot->status = CRM_SLOT_STATUS_REQ_ADDED;
1497 slot->req_id = sched_req->req_id;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08001498 slot->sync_mode = sched_req->sync_mode;
Sagar Gored79f95e2017-03-14 18:32:17 -07001499 slot->skip_idx = 0;
1500 slot->recover = sched_req->bubble_enable;
1501 __cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
1502 mutex_unlock(&link->req.lock);
1503
Sagar Gored79f95e2017-03-14 18:32:17 -07001504end:
1505 return rc;
1506}
1507
1508/**
1509 * cam_req_mgr_process_add_req()
1510 *
1511 * @brief: This runs in workque thread context. Call core funcs to check
1512 * which peding requests can be processed.
1513 * @priv : link information.
1514 * @data : contains information about frame_id, link etc.
1515 *
1516 * @return: 0 on success.
1517 */
1518int cam_req_mgr_process_add_req(void *priv, void *data)
1519{
1520 int rc = 0, i = 0, idx;
1521 struct cam_req_mgr_add_request *add_req = NULL;
1522 struct cam_req_mgr_core_link *link = NULL;
1523 struct cam_req_mgr_connected_device *device = NULL;
1524 struct cam_req_mgr_req_tbl *tbl = NULL;
1525 struct cam_req_mgr_tbl_slot *slot = NULL;
1526 struct crm_task_payload *task_data = NULL;
1527
1528 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001529 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001530 rc = -EINVAL;
1531 goto end;
1532 }
1533
1534 link = (struct cam_req_mgr_core_link *)priv;
1535 task_data = (struct crm_task_payload *)data;
1536 add_req = (struct cam_req_mgr_add_request *)&task_data->u;
1537
1538 for (i = 0; i < link->num_devs; i++) {
1539 device = &link->l_dev[i];
1540 if (device->dev_hdl == add_req->dev_hdl) {
1541 tbl = device->pd_tbl;
1542 break;
1543 }
1544 }
1545 if (!tbl) {
Harsh Shahcb0072c2017-09-26 19:22:10 -07001546 CAM_ERR_RATE_LIMIT(CAM_CRM, "dev_hdl not found %x, %x %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07001547 add_req->dev_hdl,
1548 link->l_dev[0].dev_hdl,
1549 link->l_dev[1].dev_hdl);
1550 rc = -EINVAL;
1551 goto end;
1552 }
1553 /*
1554 * Go through request table and add
1555 * request id to proper table
1556 * 1. find req slot in in_q matching req_id.sent by dev
1557 * 2. goto table of this device based on p_delay
1558 * 3. mark req_ready_map with this dev_bit.
1559 */
1560
1561 mutex_lock(&link->req.lock);
1562 idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id);
1563 if (idx < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001564 CAM_ERR(CAM_CRM, "req %lld not found in in_q", add_req->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001565 rc = -EBADSLT;
1566 mutex_unlock(&link->req.lock);
1567 goto end;
1568 }
Sagar Gorea4d7dfd2017-09-13 19:56:24 -07001569
1570 if (add_req->skip_before_applying > tbl->inject_delay)
1571 tbl->inject_delay = add_req->skip_before_applying;
1572
Sagar Gored79f95e2017-03-14 18:32:17 -07001573 slot = &tbl->slot[idx];
1574 if (slot->state != CRM_REQ_STATE_PENDING &&
1575 slot->state != CRM_REQ_STATE_EMPTY) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001576 CAM_WARN(CAM_CRM, "Unexpected state %d for slot %d map %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07001577 slot->state, idx, slot->req_ready_map);
1578 }
1579
1580 slot->state = CRM_REQ_STATE_PENDING;
1581 slot->req_ready_map |= (1 << device->dev_bit);
1582
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001583 CAM_DBG(CAM_CRM, "idx %d dev_hdl %x req_id %lld pd %d ready_map %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07001584 idx, add_req->dev_hdl, add_req->req_id, tbl->pd,
1585 slot->req_ready_map);
1586
Gregory Bergschneider60679932017-07-19 15:27:16 -06001587 trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device);
1588
Sagar Gored79f95e2017-03-14 18:32:17 -07001589 if (slot->req_ready_map == tbl->dev_mask) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001590 CAM_DBG(CAM_CRM, "idx %d req_id %lld pd %d SLOT READY",
Sagar Gored79f95e2017-03-14 18:32:17 -07001591 idx, add_req->req_id, tbl->pd);
1592 slot->state = CRM_REQ_STATE_READY;
1593 }
1594 mutex_unlock(&link->req.lock);
1595
1596end:
1597 return rc;
1598}
1599
1600/**
1601 * cam_req_mgr_process_error()
1602 *
1603 * @brief: This runs in workque thread context. bubble /err recovery.
1604 * @priv : link information.
1605 * @data : contains information about frame_id, link etc.
1606 *
1607 * @return: 0 on success.
1608 */
1609int cam_req_mgr_process_error(void *priv, void *data)
1610{
1611 int rc = 0, idx = -1, i;
1612 struct cam_req_mgr_error_notify *err_info = NULL;
1613 struct cam_req_mgr_core_link *link = NULL;
1614 struct cam_req_mgr_req_queue *in_q = NULL;
1615 struct cam_req_mgr_slot *slot = NULL;
1616 struct cam_req_mgr_connected_device *device = NULL;
1617 struct cam_req_mgr_link_evt_data evt_data;
1618 struct crm_task_payload *task_data = NULL;
1619
1620 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001621 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001622 rc = -EINVAL;
1623 goto end;
1624 }
1625 link = (struct cam_req_mgr_core_link *)priv;
1626 task_data = (struct crm_task_payload *)data;
1627 err_info = (struct cam_req_mgr_error_notify *)&task_data->u;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001628 CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld error %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001629 err_info->link_hdl,
1630 err_info->req_id,
1631 err_info->error);
1632
1633 in_q = link->req.in_q;
1634
1635 mutex_lock(&link->req.lock);
1636 if (err_info->error == CRM_KMD_ERR_BUBBLE) {
1637 idx = __cam_req_mgr_find_slot_for_req(in_q, err_info->req_id);
1638 if (idx < 0) {
Harsh Shahcb0072c2017-09-26 19:22:10 -07001639 CAM_ERR_RATE_LIMIT(CAM_CRM,
1640 "req_id %lld not found in input queue",
1641 err_info->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001642 } else {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001643 CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001644 err_info->req_id, idx);
1645 slot = &in_q->slot[idx];
1646 if (!slot->recover) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001647 CAM_WARN(CAM_CRM,
1648 "err recovery disabled req_id %lld",
Sagar Gored79f95e2017-03-14 18:32:17 -07001649 err_info->req_id);
1650 mutex_unlock(&link->req.lock);
1651 return 0;
1652 } else if (slot->status != CRM_SLOT_STATUS_REQ_PENDING
1653 && slot->status != CRM_SLOT_STATUS_REQ_APPLIED) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001654 CAM_WARN(CAM_CRM,
1655 "req_id %lld can not be recovered %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001656 err_info->req_id, slot->status);
1657 mutex_unlock(&link->req.lock);
1658 return -EINVAL;
1659 }
1660 /* Notify all devices in the link about error */
1661 for (i = 0; i < link->num_devs; i++) {
1662 device = &link->l_dev[i];
1663 if (device != NULL) {
1664 evt_data.dev_hdl = device->dev_hdl;
1665 evt_data.evt_type =
1666 CAM_REQ_MGR_LINK_EVT_ERR;
1667 evt_data.link_hdl = link->link_hdl;
1668 evt_data.req_id = err_info->req_id;
1669 evt_data.u.error = err_info->error;
1670 if (device->ops &&
1671 device->ops->process_evt)
1672 rc = device->ops->
1673 process_evt(&evt_data);
1674 }
1675 }
1676 /* Bring processing pointer to bubbled req id */
1677 __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl);
1678 in_q->rd_idx = idx;
1679 in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED;
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301680 spin_lock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001681 link->state = CAM_CRM_LINK_STATE_ERR;
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301682 spin_unlock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001683 }
1684 }
1685 mutex_unlock(&link->req.lock);
1686
1687end:
1688 return rc;
1689}
1690
1691/**
Junzhe Zou2df84502017-05-26 13:20:23 -07001692 * cam_req_mgr_process_trigger()
Sagar Gore8d91a622017-02-23 14:57:18 -08001693 *
1694 * @brief: This runs in workque thread context. Call core funcs to check
Sagar Gored79f95e2017-03-14 18:32:17 -07001695 * which peding requests can be processed.
1696 * @priv : link information.
1697 * @data : contains information about frame_id, link etc.
Sagar Gore8d91a622017-02-23 14:57:18 -08001698 *
Sagar Gored79f95e2017-03-14 18:32:17 -07001699 * @return: 0 on success.
Sagar Gore8d91a622017-02-23 14:57:18 -08001700 */
Junzhe Zou2df84502017-05-26 13:20:23 -07001701static int cam_req_mgr_process_trigger(void *priv, void *data)
Sagar Gore8d91a622017-02-23 14:57:18 -08001702{
Sagar Gored79f95e2017-03-14 18:32:17 -07001703 int rc = 0;
Junzhe Zou2df84502017-05-26 13:20:23 -07001704 struct cam_req_mgr_trigger_notify *trigger_data = NULL;
Sagar Gored79f95e2017-03-14 18:32:17 -07001705 struct cam_req_mgr_core_link *link = NULL;
1706 struct cam_req_mgr_req_queue *in_q = NULL;
1707 struct crm_task_payload *task_data = NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001708
1709 if (!data || !priv) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001710 CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
Sagar Gored79f95e2017-03-14 18:32:17 -07001711 rc = -EINVAL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001712 goto end;
1713 }
1714 link = (struct cam_req_mgr_core_link *)priv;
Sagar Gored79f95e2017-03-14 18:32:17 -07001715 task_data = (struct crm_task_payload *)data;
Junzhe Zou2df84502017-05-26 13:20:23 -07001716 trigger_data = (struct cam_req_mgr_trigger_notify *)&task_data->u;
Sagar Gore8d91a622017-02-23 14:57:18 -08001717
Junzhe Zou2df84502017-05-26 13:20:23 -07001718 CAM_DBG(CAM_CRM, "link_hdl %x frame_id %lld, trigger %x\n",
1719 trigger_data->link_hdl,
1720 trigger_data->frame_id,
1721 trigger_data->trigger);
Sagar Gore8d91a622017-02-23 14:57:18 -08001722
Sagar Gored79f95e2017-03-14 18:32:17 -07001723 in_q = link->req.in_q;
1724
1725 mutex_lock(&link->req.lock);
1726 /*
1727 * Check if current read index is in applied state, if yes make it free
1728 * and increment read index to next slot.
Sagar Gore8d91a622017-02-23 14:57:18 -08001729 */
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001730 CAM_DBG(CAM_CRM, "link_hdl %x curent idx %d req_status %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001731 link->link_hdl, in_q->rd_idx, in_q->slot[in_q->rd_idx].status);
Sagar Gore8d91a622017-02-23 14:57:18 -08001732
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301733 spin_lock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001734 if (link->state == CAM_CRM_LINK_STATE_ERR)
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001735 CAM_WARN(CAM_CRM, "Error recovery idx %d status %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07001736 in_q->rd_idx,
1737 in_q->slot[in_q->rd_idx].status);
Sagar Gore8d91a622017-02-23 14:57:18 -08001738
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301739 spin_unlock_bh(&link->link_state_spin_lock);
1740
Sagar Gored79f95e2017-03-14 18:32:17 -07001741 if (in_q->slot[in_q->rd_idx].status == CRM_SLOT_STATUS_REQ_APPLIED) {
1742 /*
1743 * Do NOT reset req q slot data here, it can not be done
1744 * here because we need to preserve the data to handle bubble.
Junzhe Zou2b342222017-08-28 18:15:54 -07001745 *
1746 * Check if any new req is pending in slot, if not finish the
1747 * lower pipeline delay device with available req ids.
Sagar Gored79f95e2017-03-14 18:32:17 -07001748 */
Karthik Anantha Ramfa643332017-11-06 13:49:31 -08001749 CAM_DBG(CAM_CRM, "link[%x] Req[%lld] invalidating slot",
1750 link->link_hdl, in_q->slot[in_q->rd_idx].req_id);
Junzhe Zou2b342222017-08-28 18:15:54 -07001751 __cam_req_mgr_check_next_req_slot(in_q);
Sagar Gored79f95e2017-03-14 18:32:17 -07001752 __cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots);
Sagar Gore8d91a622017-02-23 14:57:18 -08001753 }
Junzhe Zou2df84502017-05-26 13:20:23 -07001754 rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
Sagar Gored79f95e2017-03-14 18:32:17 -07001755 mutex_unlock(&link->req.lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08001756
1757end:
Sagar Gored79f95e2017-03-14 18:32:17 -07001758 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08001759}
1760
Sagar Gore8d91a622017-02-23 14:57:18 -08001761
Sagar Gored79f95e2017-03-14 18:32:17 -07001762/* Linked devices' Callback section */
1763
1764/**
1765 * cam_req_mgr_cb_add_req()
1766 *
1767 * @brief : Drivers call this function to notify new packet is available.
1768 * @add_req : Information about new request available at a device.
1769 *
1770 * @return : 0 on success, negative in case of failure
1771 *
1772 */
1773static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req)
1774{
1775 int rc = 0, idx;
1776 struct crm_workq_task *task = NULL;
1777 struct cam_req_mgr_core_link *link = NULL;
1778 struct cam_req_mgr_add_request *dev_req;
1779 struct crm_task_payload *task_data;
1780
1781 if (!add_req) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001782 CAM_ERR(CAM_CRM, "sof_data is NULL");
Suresh Vankadara10a8e492017-11-09 01:11:31 +05301783 return -EINVAL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001784 }
1785
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001786 CAM_DBG(CAM_CRM, "E: dev %x dev req %lld",
1787 add_req->dev_hdl, add_req->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001788 link = (struct cam_req_mgr_core_link *)
1789 cam_get_device_priv(add_req->link_hdl);
1790
1791 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001792 CAM_DBG(CAM_CRM, "link ptr NULL %x", add_req->link_hdl);
Suresh Vankadara10a8e492017-11-09 01:11:31 +05301793 return -EINVAL;
Sagar Gored79f95e2017-03-14 18:32:17 -07001794 }
1795
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301796 mutex_lock(&link->lock);
1797 spin_lock_bh(&link->link_state_spin_lock);
1798 if (link->state != CAM_CRM_LINK_STATE_READY) {
1799 CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
1800 rc = -EPERM;
1801 spin_unlock_bh(&link->link_state_spin_lock);
1802 goto end;
1803 }
1804 spin_unlock_bh(&link->link_state_spin_lock);
1805
Sagar Gored79f95e2017-03-14 18:32:17 -07001806 /* Validate if req id is present in input queue */
1807 idx = __cam_req_mgr_find_slot_for_req(link->req.in_q, add_req->req_id);
1808 if (idx < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001809 CAM_ERR(CAM_CRM, "req %lld not found in in_q", add_req->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001810 rc = -ENOENT;
1811 goto end;
1812 }
1813
1814 task = cam_req_mgr_workq_get_task(link->workq);
1815 if (!task) {
Harsh Shahcb0072c2017-09-26 19:22:10 -07001816 CAM_ERR_RATE_LIMIT(CAM_CRM, "no empty task dev %x req %lld",
Sagar Gored79f95e2017-03-14 18:32:17 -07001817 add_req->dev_hdl, add_req->req_id);
1818 rc = -EBUSY;
1819 goto end;
1820 }
1821
1822 task_data = (struct crm_task_payload *)task->payload;
1823 task_data->type = CRM_WORKQ_TASK_DEV_ADD_REQ;
1824 dev_req = (struct cam_req_mgr_add_request *)&task_data->u;
1825 dev_req->req_id = add_req->req_id;
1826 dev_req->link_hdl = add_req->link_hdl;
1827 dev_req->dev_hdl = add_req->dev_hdl;
Sagar Gorea4d7dfd2017-09-13 19:56:24 -07001828 dev_req->skip_before_applying = add_req->skip_before_applying;
Sagar Gored79f95e2017-03-14 18:32:17 -07001829 task->process_cb = &cam_req_mgr_process_add_req;
1830 rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001831 CAM_DBG(CAM_CRM, "X: dev %x dev req %lld",
1832 add_req->dev_hdl, add_req->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001833
1834end:
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301835 mutex_unlock(&link->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001836 return rc;
1837}
1838
1839/**
1840 * cam_req_mgr_cb_notify_err()
1841 *
1842 * @brief : Error received from device, sends bubble recovery
1843 * @err_info : contains information about error occurred like bubble/overflow
1844 *
1845 * @return : 0 on success, negative in case of failure
1846 *
1847 */
1848static int cam_req_mgr_cb_notify_err(
1849 struct cam_req_mgr_error_notify *err_info)
1850{
1851 int rc = 0;
1852 struct crm_workq_task *task = NULL;
1853 struct cam_req_mgr_core_link *link = NULL;
1854 struct cam_req_mgr_error_notify *notify_err;
1855 struct crm_task_payload *task_data;
1856
1857 if (!err_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001858 CAM_ERR(CAM_CRM, "err_info is NULL");
Sagar Gored79f95e2017-03-14 18:32:17 -07001859 rc = -EINVAL;
1860 goto end;
1861 }
1862
1863 link = (struct cam_req_mgr_core_link *)
1864 cam_get_device_priv(err_info->link_hdl);
1865 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001866 CAM_DBG(CAM_CRM, "link ptr NULL %x", err_info->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07001867 rc = -EINVAL;
1868 goto end;
1869 }
1870
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301871 spin_lock_bh(&link->link_state_spin_lock);
1872 if (link->state != CAM_CRM_LINK_STATE_READY) {
1873 CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
1874 spin_unlock_bh(&link->link_state_spin_lock);
1875 rc = -EPERM;
1876 goto end;
1877 }
Venkat Chinta686c9e52018-01-20 14:33:25 -08001878 crm_timer_reset(link->watchdog);
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301879 spin_unlock_bh(&link->link_state_spin_lock);
1880
Sagar Gored79f95e2017-03-14 18:32:17 -07001881 task = cam_req_mgr_workq_get_task(link->workq);
1882 if (!task) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001883 CAM_ERR(CAM_CRM, "no empty task req_id %lld", err_info->req_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001884 rc = -EBUSY;
1885 goto end;
1886 }
1887
1888 task_data = (struct crm_task_payload *)task->payload;
1889 task_data->type = CRM_WORKQ_TASK_NOTIFY_ERR;
1890 notify_err = (struct cam_req_mgr_error_notify *)&task_data->u;
1891 notify_err->req_id = err_info->req_id;
1892 notify_err->link_hdl = err_info->link_hdl;
1893 notify_err->dev_hdl = err_info->dev_hdl;
1894 notify_err->error = err_info->error;
1895 task->process_cb = &cam_req_mgr_process_error;
1896 rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
1897
1898end:
1899 return rc;
1900}
1901
1902/**
Junzhe Zou2df84502017-05-26 13:20:23 -07001903 * cam_req_mgr_cb_notify_trigger()
Sagar Gored79f95e2017-03-14 18:32:17 -07001904 *
1905 * @brief : SOF received from device, sends trigger through workqueue
1906 * @sof_data: contains information about frame_id, link etc.
1907 *
1908 * @return : 0 on success
1909 *
1910 */
Junzhe Zou2df84502017-05-26 13:20:23 -07001911static int cam_req_mgr_cb_notify_trigger(
1912 struct cam_req_mgr_trigger_notify *trigger_data)
Sagar Gored79f95e2017-03-14 18:32:17 -07001913{
1914 int rc = 0;
1915 struct crm_workq_task *task = NULL;
1916 struct cam_req_mgr_core_link *link = NULL;
Junzhe Zou2df84502017-05-26 13:20:23 -07001917 struct cam_req_mgr_trigger_notify *notify_trigger;
Sagar Gored79f95e2017-03-14 18:32:17 -07001918 struct crm_task_payload *task_data;
1919
Junzhe Zou2df84502017-05-26 13:20:23 -07001920 if (!trigger_data) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001921 CAM_ERR(CAM_CRM, "sof_data is NULL");
Sagar Gored79f95e2017-03-14 18:32:17 -07001922 rc = -EINVAL;
1923 goto end;
1924 }
Sagar Gore8d91a622017-02-23 14:57:18 -08001925
1926 link = (struct cam_req_mgr_core_link *)
Junzhe Zou2df84502017-05-26 13:20:23 -07001927 cam_get_device_priv(trigger_data->link_hdl);
Sagar Gore8d91a622017-02-23 14:57:18 -08001928 if (!link) {
Junzhe Zou2df84502017-05-26 13:20:23 -07001929 CAM_DBG(CAM_CRM, "link ptr NULL %x", trigger_data->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07001930 rc = -EINVAL;
Sagar Gore8d91a622017-02-23 14:57:18 -08001931 goto end;
Sagar Gore8d91a622017-02-23 14:57:18 -08001932 }
1933
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301934 spin_lock_bh(&link->link_state_spin_lock);
1935 if (link->state != CAM_CRM_LINK_STATE_READY) {
1936 CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
1937 spin_unlock_bh(&link->link_state_spin_lock);
1938 rc = -EPERM;
1939 goto end;
1940 }
Venkat Chinta686c9e52018-01-20 14:33:25 -08001941 crm_timer_reset(link->watchdog);
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05301942 spin_unlock_bh(&link->link_state_spin_lock);
1943
Sagar Gore8d91a622017-02-23 14:57:18 -08001944 task = cam_req_mgr_workq_get_task(link->workq);
1945 if (!task) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001946 CAM_ERR(CAM_CRM, "no empty task frame %lld",
Junzhe Zou2df84502017-05-26 13:20:23 -07001947 trigger_data->frame_id);
Sagar Gored79f95e2017-03-14 18:32:17 -07001948 rc = -EBUSY;
Sagar Gore8d91a622017-02-23 14:57:18 -08001949 goto end;
1950 }
Sagar Gored79f95e2017-03-14 18:32:17 -07001951 task_data = (struct crm_task_payload *)task->payload;
1952 task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF;
Junzhe Zou2df84502017-05-26 13:20:23 -07001953 notify_trigger = (struct cam_req_mgr_trigger_notify *)&task_data->u;
1954 notify_trigger->frame_id = trigger_data->frame_id;
1955 notify_trigger->link_hdl = trigger_data->link_hdl;
1956 notify_trigger->dev_hdl = trigger_data->dev_hdl;
1957 notify_trigger->trigger = trigger_data->trigger;
1958 task->process_cb = &cam_req_mgr_process_trigger;
Sagar Gored79f95e2017-03-14 18:32:17 -07001959 rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
Sagar Gore8d91a622017-02-23 14:57:18 -08001960
1961end:
Sagar Gored79f95e2017-03-14 18:32:17 -07001962 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08001963}
1964
Sagar Gored79f95e2017-03-14 18:32:17 -07001965static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
Junzhe Zou2df84502017-05-26 13:20:23 -07001966 .notify_trigger = cam_req_mgr_cb_notify_trigger,
1967 .notify_err = cam_req_mgr_cb_notify_err,
1968 .add_req = cam_req_mgr_cb_add_req,
Sagar Gored79f95e2017-03-14 18:32:17 -07001969};
1970
Sagar Gore8d91a622017-02-23 14:57:18 -08001971/**
Sagar Gored79f95e2017-03-14 18:32:17 -07001972 * __cam_req_mgr_setup_link_info()
Sagar Gore8d91a622017-02-23 14:57:18 -08001973 *
Sagar Gored79f95e2017-03-14 18:32:17 -07001974 * @brief : Sets up input queue, create pd based tables, communicate with
1975 * devs connected on this link and setup communication.
1976 * @link : pointer to link to setup
1977 * @link_info : link_info coming from CSL to prepare link
Sagar Gore8d91a622017-02-23 14:57:18 -08001978 *
Sagar Gored79f95e2017-03-14 18:32:17 -07001979 * @return : 0 on success, negative in case of failure
1980 *
Sagar Gore8d91a622017-02-23 14:57:18 -08001981 */
Sagar Gored79f95e2017-03-14 18:32:17 -07001982static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
1983 struct cam_req_mgr_link_info *link_info)
Sagar Gore8d91a622017-02-23 14:57:18 -08001984{
Sagar Gored79f95e2017-03-14 18:32:17 -07001985 int rc = 0, i = 0;
1986 struct cam_req_mgr_core_dev_link_setup link_data;
1987 struct cam_req_mgr_connected_device *dev;
1988 struct cam_req_mgr_req_tbl *pd_tbl;
1989 enum cam_pipeline_delay max_delay;
Junzhe Zou2df84502017-05-26 13:20:23 -07001990 uint32_t subscribe_event = 0;
Sagar Gore8d91a622017-02-23 14:57:18 -08001991
Sagar Gored79f95e2017-03-14 18:32:17 -07001992 if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES)
1993 return -EPERM;
Sagar Gore8d91a622017-02-23 14:57:18 -08001994
Sagar Gored79f95e2017-03-14 18:32:17 -07001995 mutex_init(&link->req.lock);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07001996 CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07001997 link->req.num_tbl = 0;
1998
1999 rc = __cam_req_mgr_setup_in_q(&link->req);
2000 if (rc < 0)
2001 return rc;
2002
Sagar Gored79f95e2017-03-14 18:32:17 -07002003 max_delay = CAM_PIPELINE_DELAY_0;
2004 for (i = 0; i < link_info->num_devices; i++) {
2005 dev = &link->l_dev[i];
2006 /* Using dev hdl, get ops ptr to communicate with device */
2007 dev->ops = (struct cam_req_mgr_kmd_ops *)
2008 cam_get_device_ops(link_info->dev_hdls[i]);
2009 if (!dev->ops ||
2010 !dev->ops->get_dev_info ||
2011 !dev->ops->link_setup) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002012 CAM_ERR(CAM_CRM, "FATAL: device ops NULL");
Sagar Gored79f95e2017-03-14 18:32:17 -07002013 rc = -ENXIO;
2014 goto error;
Sagar Gore8d91a622017-02-23 14:57:18 -08002015 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002016 dev->dev_hdl = link_info->dev_hdls[i];
2017 dev->parent = (void *)link;
2018 dev->dev_info.dev_hdl = dev->dev_hdl;
2019 rc = dev->ops->get_dev_info(&dev->dev_info);
Gregory Bergschneider60679932017-07-19 15:27:16 -06002020
2021 trace_cam_req_mgr_connect_device(link, &dev->dev_info);
2022
Junzhe Zou2df84502017-05-26 13:20:23 -07002023 CAM_DBG(CAM_CRM,
2024 "%x: connected: %s, id %d, delay %d, trigger %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07002025 link_info->session_hdl, dev->dev_info.name,
Junzhe Zou2df84502017-05-26 13:20:23 -07002026 dev->dev_info.dev_id, dev->dev_info.p_delay,
2027 dev->dev_info.trigger);
Sagar Gored79f95e2017-03-14 18:32:17 -07002028 if (rc < 0 ||
2029 dev->dev_info.p_delay >=
2030 CAM_PIPELINE_DELAY_MAX ||
2031 dev->dev_info.p_delay <
2032 CAM_PIPELINE_DELAY_0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002033 CAM_ERR(CAM_CRM, "get device info failed");
Sagar Gored79f95e2017-03-14 18:32:17 -07002034 goto error;
2035 } else {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002036 CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07002037 link_info->session_hdl,
2038 dev->dev_info.name,
2039 dev->dev_info.p_delay);
Junzhe Zou2df84502017-05-26 13:20:23 -07002040 if (dev->dev_info.p_delay > max_delay)
2041 max_delay = dev->dev_info.p_delay;
2042
2043 subscribe_event |= (uint32_t)dev->dev_info.trigger;
Sagar Gored79f95e2017-03-14 18:32:17 -07002044 }
Sagar Gore8d91a622017-02-23 14:57:18 -08002045 }
2046
Junzhe Zou2df84502017-05-26 13:20:23 -07002047 link->subscribe_event = subscribe_event;
Sagar Gored79f95e2017-03-14 18:32:17 -07002048 link_data.link_enable = 1;
2049 link_data.link_hdl = link->link_hdl;
2050 link_data.crm_cb = &cam_req_mgr_ops;
2051 link_data.max_delay = max_delay;
Junzhe Zou2df84502017-05-26 13:20:23 -07002052 link_data.subscribe_event = subscribe_event;
Sagar Gored79f95e2017-03-14 18:32:17 -07002053
2054 for (i = 0; i < link_info->num_devices; i++) {
2055 dev = &link->l_dev[i];
2056
2057 link_data.dev_hdl = dev->dev_hdl;
2058 /*
2059 * For unique pipeline delay table create request
2060 * tracking table
2061 */
2062 if (link->pd_mask & (1 << dev->dev_info.p_delay)) {
2063 pd_tbl = __cam_req_mgr_find_pd_tbl(link->req.l_tbl,
2064 dev->dev_info.p_delay);
2065 if (!pd_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002066 CAM_ERR(CAM_CRM, "pd %d tbl not found",
Sagar Gored79f95e2017-03-14 18:32:17 -07002067 dev->dev_info.p_delay);
2068 rc = -ENXIO;
2069 goto error;
2070 }
2071 } else {
2072 pd_tbl = __cam_req_mgr_create_pd_tbl(
2073 dev->dev_info.p_delay);
2074 if (pd_tbl == NULL) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002075 CAM_ERR(CAM_CRM, "create new pd tbl failed");
Sagar Gored79f95e2017-03-14 18:32:17 -07002076 rc = -ENXIO;
2077 goto error;
2078 }
2079 pd_tbl->pd = dev->dev_info.p_delay;
2080 link->pd_mask |= (1 << pd_tbl->pd);
2081 /*
2082 * Add table to list and also sort list
2083 * from max pd to lowest
2084 */
2085 __cam_req_mgr_add_tbl_to_link(&link->req.l_tbl, pd_tbl);
2086 }
2087 dev->dev_bit = pd_tbl->dev_count++;
2088 dev->pd_tbl = pd_tbl;
2089 pd_tbl->dev_mask |= (1 << dev->dev_bit);
2090
2091 /* Communicate with dev to establish the link */
2092 dev->ops->link_setup(&link_data);
2093
2094 if (link->max_delay < dev->dev_info.p_delay)
2095 link->max_delay = dev->dev_info.p_delay;
2096 }
2097 link->num_devs = link_info->num_devices;
2098
2099 /* Assign id for pd tables */
2100 __cam_req_mgr_tbl_set_id(link->req.l_tbl, &link->req);
2101
2102 /* At start, expect max pd devices, all are in skip state */
2103 __cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl);
2104
Sagar Gored79f95e2017-03-14 18:32:17 -07002105 return 0;
2106
2107error:
2108 __cam_req_mgr_destroy_link_info(link);
2109 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002110}
2111
Sagar Gored79f95e2017-03-14 18:32:17 -07002112/* IOCTLs handling section */
Sagar Gore8d91a622017-02-23 14:57:18 -08002113int cam_req_mgr_create_session(
2114 struct cam_req_mgr_session_info *ses_info)
2115{
Sagar Gored79f95e2017-03-14 18:32:17 -07002116 int rc = 0;
2117 int32_t session_hdl;
2118 struct cam_req_mgr_core_session *cam_session = NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -08002119
2120 if (!ses_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002121 CAM_DBG(CAM_CRM, "NULL session info pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002122 return -EINVAL;
2123 }
2124 mutex_lock(&g_crm_core_dev->crm_lock);
2125 cam_session = (struct cam_req_mgr_core_session *)
2126 kzalloc(sizeof(*cam_session), GFP_KERNEL);
2127 if (!cam_session) {
Sagar Gored79f95e2017-03-14 18:32:17 -07002128 rc = -ENOMEM;
Sagar Gore8d91a622017-02-23 14:57:18 -08002129 goto end;
2130 }
2131
2132 session_hdl = cam_create_session_hdl((void *)cam_session);
2133 if (session_hdl < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002134 CAM_ERR(CAM_CRM, "unable to create session_hdl = %x",
2135 session_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002136 rc = session_hdl;
2137 kfree(cam_session);
2138 goto end;
Sagar Gore8d91a622017-02-23 14:57:18 -08002139 }
2140 ses_info->session_hdl = session_hdl;
Sagar Gored79f95e2017-03-14 18:32:17 -07002141
2142 mutex_init(&cam_session->lock);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002143 CAM_DBG(CAM_CRM, "LOCK_DBG session lock %pK", &cam_session->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002144
2145 mutex_lock(&cam_session->lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002146 cam_session->session_hdl = session_hdl;
Sagar Gored79f95e2017-03-14 18:32:17 -07002147 cam_session->num_links = 0;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002148 cam_session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
Sagar Gore8d91a622017-02-23 14:57:18 -08002149 list_add(&cam_session->entry, &g_crm_core_dev->session_head);
Sagar Gored79f95e2017-03-14 18:32:17 -07002150 mutex_unlock(&cam_session->lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002151end:
2152 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002153 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002154}
2155
Sunil Khatribc029f72017-11-28 18:54:24 +05302156/**
2157 * __cam_req_mgr_unlink()
2158 *
2159 * @brief : Unlink devices on a link structure from the session
2160 * @link : Pointer to the link structure
2161 *
2162 * @return: 0 for success, negative for failure
2163 *
2164 */
2165static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
2166{
2167 int rc;
2168
2169 mutex_lock(&link->lock);
2170 spin_lock_bh(&link->link_state_spin_lock);
2171 link->state = CAM_CRM_LINK_STATE_IDLE;
Venkat Chinta686c9e52018-01-20 14:33:25 -08002172
2173 /* Destroy timer of link */
2174 crm_timer_exit(&link->watchdog);
Sunil Khatribc029f72017-11-28 18:54:24 +05302175 spin_unlock_bh(&link->link_state_spin_lock);
2176 __cam_req_mgr_print_req_tbl(&link->req);
2177
2178 /* Destroy workq payload data */
2179 kfree(link->workq->task.pool[0].payload);
2180 link->workq->task.pool[0].payload = NULL;
2181
Venkat Chinta686c9e52018-01-20 14:33:25 -08002182 /* Destroy workq of link */
Sunil Khatribc029f72017-11-28 18:54:24 +05302183 cam_req_mgr_workq_destroy(&link->workq);
2184
2185 /* Cleanup request tables and unlink devices */
Venkat Chinta686c9e52018-01-20 14:33:25 -08002186 rc = __cam_req_mgr_destroy_link_info(link);
Vishalsingh Hajeri87c3131b2018-02-09 17:36:35 -08002187 if (rc)
2188 CAM_ERR(CAM_CORE,
2189 "Unlink for all devices was not successful");
Sunil Khatribc029f72017-11-28 18:54:24 +05302190
2191 /* Free memory holding data of linked devs */
2192 __cam_req_mgr_destroy_subdev(link->l_dev);
2193
2194 /* Destroy the link handle */
2195 rc = cam_destroy_device_hdl(link->link_hdl);
2196 if (rc < 0) {
2197 CAM_ERR(CAM_CRM, "error while destroying dev handle %d %x",
2198 rc, link->link_hdl);
2199 }
2200
Sunil Khatribc029f72017-11-28 18:54:24 +05302201 mutex_unlock(&link->lock);
2202 return rc;
2203}
2204
Sagar Gore8d91a622017-02-23 14:57:18 -08002205int cam_req_mgr_destroy_session(
2206 struct cam_req_mgr_session_info *ses_info)
2207{
Sagar Gored79f95e2017-03-14 18:32:17 -07002208 int rc;
Sunil Khatribc029f72017-11-28 18:54:24 +05302209 int i;
Sagar Gored79f95e2017-03-14 18:32:17 -07002210 struct cam_req_mgr_core_session *cam_session = NULL;
Sunil Khatribc029f72017-11-28 18:54:24 +05302211 struct cam_req_mgr_core_link *link;
Sagar Gore8d91a622017-02-23 14:57:18 -08002212
2213 if (!ses_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002214 CAM_DBG(CAM_CRM, "NULL session info pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002215 return -EINVAL;
2216 }
2217
2218 mutex_lock(&g_crm_core_dev->crm_lock);
2219 cam_session = (struct cam_req_mgr_core_session *)
2220 cam_get_device_priv(ses_info->session_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002221 if (!cam_session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002222 CAM_ERR(CAM_CRM, "failed to get session priv");
Sagar Gored79f95e2017-03-14 18:32:17 -07002223 rc = -ENOENT;
Sagar Gore8d91a622017-02-23 14:57:18 -08002224 goto end;
2225
2226 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002227 mutex_lock(&cam_session->lock);
2228 if (cam_session->num_links) {
Sunil Khatribc029f72017-11-28 18:54:24 +05302229 CAM_DBG(CAM_CRM, "destroy session %x num_active_links %d",
Sagar Gore8d91a622017-02-23 14:57:18 -08002230 ses_info->session_hdl,
Sagar Gored79f95e2017-03-14 18:32:17 -07002231 cam_session->num_links);
Sunil Khatribc029f72017-11-28 18:54:24 +05302232
2233 for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
2234 link = cam_session->links[i];
2235
2236 if (!link)
2237 continue;
2238
2239 /* Ignore return value since session is going away */
2240 __cam_req_mgr_unlink(link);
2241 __cam_req_mgr_free_link(link);
2242 }
Sagar Gore8d91a622017-02-23 14:57:18 -08002243 }
2244 list_del(&cam_session->entry);
Sagar Gored79f95e2017-03-14 18:32:17 -07002245 mutex_unlock(&cam_session->lock);
2246 mutex_destroy(&cam_session->lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002247 kfree(cam_session);
2248
Sagar Gored79f95e2017-03-14 18:32:17 -07002249 rc = cam_destroy_session_hdl(ses_info->session_hdl);
2250 if (rc < 0)
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002251 CAM_ERR(CAM_CRM, "unable to destroy session_hdl = %x rc %d",
Sagar Gored79f95e2017-03-14 18:32:17 -07002252 ses_info->session_hdl, rc);
Sagar Gore8d91a622017-02-23 14:57:18 -08002253
2254end:
2255 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002256 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002257}
2258
2259int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
2260{
Sagar Gored79f95e2017-03-14 18:32:17 -07002261 int rc = 0;
2262 char buf[128];
2263 struct cam_create_dev_hdl root_dev;
2264 struct cam_req_mgr_core_session *cam_session;
2265 struct cam_req_mgr_core_link *link;
Sagar Gore8d91a622017-02-23 14:57:18 -08002266
2267 if (!link_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002268 CAM_DBG(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002269 return -EINVAL;
2270 }
Sagar Gore8d91a622017-02-23 14:57:18 -08002271 if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002272 CAM_ERR(CAM_CRM, "Invalid num devices %d",
2273 link_info->num_devices);
Sagar Gore8d91a622017-02-23 14:57:18 -08002274 return -EINVAL;
2275 }
2276
Sagar Gored79f95e2017-03-14 18:32:17 -07002277 /* session hdl's priv data is cam session struct */
Sagar Gore8d91a622017-02-23 14:57:18 -08002278 cam_session = (struct cam_req_mgr_core_session *)
2279 cam_get_device_priv(link_info->session_hdl);
2280 if (!cam_session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002281 CAM_DBG(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002282 return -EINVAL;
2283 }
2284
Sagar Gored79f95e2017-03-14 18:32:17 -07002285 mutex_lock(&g_crm_core_dev->crm_lock);
2286
2287 /* Allocate link struct and map it with session's request queue */
2288 link = __cam_req_mgr_reserve_link(cam_session);
Sagar Gore8d91a622017-02-23 14:57:18 -08002289 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002290 CAM_ERR(CAM_CRM, "failed to reserve new link");
Sagar Gored79f95e2017-03-14 18:32:17 -07002291 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002292 return -EINVAL;
2293 }
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002294 CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl);
Sagar Gore8d91a622017-02-23 14:57:18 -08002295
2296 memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl));
2297 root_dev.session_hdl = link_info->session_hdl;
2298 root_dev.priv = (void *)link;
2299
Sagar Gored79f95e2017-03-14 18:32:17 -07002300 mutex_lock(&link->lock);
2301 /* Create unique dev handle for link */
2302 link->link_hdl = cam_create_device_hdl(&root_dev);
2303 if (link->link_hdl < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002304 CAM_ERR(CAM_CRM,
2305 "Insufficient memory to create new device handle");
Sagar Gored79f95e2017-03-14 18:32:17 -07002306 rc = link->link_hdl;
Sagar Gore8d91a622017-02-23 14:57:18 -08002307 goto link_hdl_fail;
2308 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002309 link_info->link_hdl = link->link_hdl;
Sagar Gore8d91a622017-02-23 14:57:18 -08002310
Sagar Gored79f95e2017-03-14 18:32:17 -07002311 /* Allocate memory to hold data of all linked devs */
2312 rc = __cam_req_mgr_create_subdevs(&link->l_dev,
2313 link_info->num_devices);
2314 if (rc < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002315 CAM_ERR(CAM_CRM,
2316 "Insufficient memory to create new crm subdevs");
Sagar Gore8d91a622017-02-23 14:57:18 -08002317 goto create_subdev_failed;
2318 }
2319
Sagar Gored79f95e2017-03-14 18:32:17 -07002320 /* Using device ops query connected devs, prepare request tables */
2321 rc = __cam_req_mgr_setup_link_info(link, link_info);
2322 if (rc < 0)
2323 goto setup_failed;
Sagar Gore8d91a622017-02-23 14:57:18 -08002324
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302325 spin_lock_bh(&link->link_state_spin_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002326 link->state = CAM_CRM_LINK_STATE_READY;
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302327 spin_unlock_bh(&link->link_state_spin_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002328
2329 /* Create worker for current link */
Sagar Gored79f95e2017-03-14 18:32:17 -07002330 snprintf(buf, sizeof(buf), "%x-%x",
2331 link_info->session_hdl, link->link_hdl);
Sagar Gore9f404712017-05-22 16:57:25 -07002332 rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
2333 &link->workq, CRM_WORKQ_USAGE_NON_IRQ);
Sagar Gored79f95e2017-03-14 18:32:17 -07002334 if (rc < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002335 CAM_ERR(CAM_CRM, "FATAL: unable to create worker");
Sagar Gored79f95e2017-03-14 18:32:17 -07002336 __cam_req_mgr_destroy_link_info(link);
2337 goto setup_failed;
Sagar Gore8d91a622017-02-23 14:57:18 -08002338 }
2339
Sagar Gored79f95e2017-03-14 18:32:17 -07002340 /* Assign payload to workqueue tasks */
2341 rc = __cam_req_mgr_setup_payload(link->workq);
2342 if (rc < 0) {
2343 __cam_req_mgr_destroy_link_info(link);
2344 cam_req_mgr_workq_destroy(&link->workq);
2345 goto setup_failed;
2346 }
Sagar Gore8d91a622017-02-23 14:57:18 -08002347
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302348 mutex_unlock(&link->lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002349 mutex_unlock(&g_crm_core_dev->crm_lock);
2350 return rc;
2351setup_failed:
2352 __cam_req_mgr_destroy_subdev(link->l_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002353create_subdev_failed:
Sagar Gored79f95e2017-03-14 18:32:17 -07002354 cam_destroy_device_hdl(link->link_hdl);
2355 link_info->link_hdl = 0;
Sagar Gore8d91a622017-02-23 14:57:18 -08002356link_hdl_fail:
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302357 mutex_unlock(&link->lock);
Sunil Khatribc029f72017-11-28 18:54:24 +05302358 __cam_req_mgr_unreserve_link(cam_session, link);
Sagar Gored79f95e2017-03-14 18:32:17 -07002359 mutex_unlock(&g_crm_core_dev->crm_lock);
2360 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002361}
2362
2363int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info)
2364{
Sagar Gored79f95e2017-03-14 18:32:17 -07002365 int rc = 0;
Sagar Gore8d91a622017-02-23 14:57:18 -08002366 struct cam_req_mgr_core_session *cam_session;
Sagar Gored79f95e2017-03-14 18:32:17 -07002367 struct cam_req_mgr_core_link *link;
Sagar Gore8d91a622017-02-23 14:57:18 -08002368
2369 if (!unlink_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002370 CAM_ERR(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002371 return -EINVAL;
2372 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002373
2374 mutex_lock(&g_crm_core_dev->crm_lock);
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002375 CAM_DBG(CAM_CRM, "link_hdl %x", unlink_info->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002376
2377 /* session hdl's priv data is cam session struct */
Sagar Gore8d91a622017-02-23 14:57:18 -08002378 cam_session = (struct cam_req_mgr_core_session *)
Sagar Gored79f95e2017-03-14 18:32:17 -07002379 cam_get_device_priv(unlink_info->session_hdl);
Sagar Gore8d91a622017-02-23 14:57:18 -08002380 if (!cam_session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002381 CAM_ERR(CAM_CRM, "NULL pointer");
Sagar Gored79f95e2017-03-14 18:32:17 -07002382 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -08002383 return -EINVAL;
2384 }
2385
Sagar Gored79f95e2017-03-14 18:32:17 -07002386 /* link hdl's priv data is core_link struct */
2387 link = cam_get_device_priv(unlink_info->link_hdl);
Sagar Gore8d91a622017-02-23 14:57:18 -08002388 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002389 CAM_ERR(CAM_CRM, "NULL pointer");
Sunil Khatribc029f72017-11-28 18:54:24 +05302390 rc = -EINVAL;
2391 goto done;
Sagar Gore8d91a622017-02-23 14:57:18 -08002392 }
Ravikishore Pampana6c2e1c12017-10-16 18:46:15 +05302393
Sunil Khatribc029f72017-11-28 18:54:24 +05302394 rc = __cam_req_mgr_unlink(link);
Sagar Gore8d91a622017-02-23 14:57:18 -08002395
Sagar Gored79f95e2017-03-14 18:32:17 -07002396 /* Free curent link and put back into session's free pool of links */
Sunil Khatribc029f72017-11-28 18:54:24 +05302397 if (!rc)
2398 __cam_req_mgr_unreserve_link(cam_session, link);
Sagar Gored79f95e2017-03-14 18:32:17 -07002399
Sunil Khatribc029f72017-11-28 18:54:24 +05302400done:
2401 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002402 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002403}
2404
2405int cam_req_mgr_schedule_request(
2406 struct cam_req_mgr_sched_request *sched_req)
2407{
Sagar Gored79f95e2017-03-14 18:32:17 -07002408 int rc = 0;
Sagar Gored79f95e2017-03-14 18:32:17 -07002409 struct cam_req_mgr_core_link *link = NULL;
2410 struct cam_req_mgr_core_session *session = NULL;
2411 struct cam_req_mgr_sched_request *sched;
Sagar Goreb56c81e2017-05-08 17:15:47 -07002412 struct crm_task_payload task_data;
Sagar Gored79f95e2017-03-14 18:32:17 -07002413
Sagar Gore8d91a622017-02-23 14:57:18 -08002414 if (!sched_req) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002415 CAM_ERR(CAM_CRM, "csl_req is NULL");
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002416 return -EINVAL;
Sagar Gored79f95e2017-03-14 18:32:17 -07002417 }
2418
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002419 mutex_lock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002420 link = (struct cam_req_mgr_core_link *)
2421 cam_get_device_priv(sched_req->link_hdl);
2422 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002423 CAM_DBG(CAM_CRM, "link ptr NULL %x", sched_req->link_hdl);
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002424 rc = -EINVAL;
2425 goto end;
Sagar Gored79f95e2017-03-14 18:32:17 -07002426 }
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002427
Sagar Gored79f95e2017-03-14 18:32:17 -07002428 session = (struct cam_req_mgr_core_session *)link->parent;
2429 if (!session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002430 CAM_WARN(CAM_CRM, "session ptr NULL %x", sched_req->link_hdl);
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002431 rc = -EINVAL;
2432 goto end;
Sagar Gore8d91a622017-02-23 14:57:18 -08002433 }
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002434
2435 CAM_DBG(CAM_CRM, "link %x req %lld, sync_mode %d",
2436 sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
Sagar Gore8d91a622017-02-23 14:57:18 -08002437
Sagar Goreb56c81e2017-05-08 17:15:47 -07002438 task_data.type = CRM_WORKQ_TASK_SCHED_REQ;
2439 sched = (struct cam_req_mgr_sched_request *)&task_data.u;
Sagar Gored79f95e2017-03-14 18:32:17 -07002440 sched->req_id = sched_req->req_id;
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002441 sched->sync_mode = sched_req->sync_mode;
Sagar Gored79f95e2017-03-14 18:32:17 -07002442 sched->link_hdl = sched_req->link_hdl;
2443 if (session->force_err_recovery == AUTO_RECOVERY) {
2444 sched->bubble_enable = sched_req->bubble_enable;
2445 } else {
2446 sched->bubble_enable =
2447 (session->force_err_recovery == FORCE_ENABLE_RECOVERY) ? 1 : 0;
2448 }
Sagar Gored79f95e2017-03-14 18:32:17 -07002449
Sagar Goreb56c81e2017-05-08 17:15:47 -07002450 rc = cam_req_mgr_process_sched_req(link, &task_data);
2451
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002452 CAM_DBG(CAM_CRM, "DONE dev %x req %lld sync_mode %d",
2453 sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
Sagar Gored79f95e2017-03-14 18:32:17 -07002454end:
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002455 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002456 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002457}
2458
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002459int cam_req_mgr_sync_config(
2460 struct cam_req_mgr_sync_mode *sync_info)
Sagar Gore8d91a622017-02-23 14:57:18 -08002461{
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002462 int rc = 0;
2463 struct cam_req_mgr_core_session *cam_session;
2464 struct cam_req_mgr_core_link *link1 = NULL;
2465 struct cam_req_mgr_core_link *link2 = NULL;
2466
2467 if (!sync_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002468 CAM_ERR(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002469 return -EINVAL;
2470 }
2471
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002472 if ((sync_info->num_links < 0) ||
2473 (sync_info->num_links > MAX_LINKS_PER_SESSION)) {
2474 CAM_ERR(CAM_CRM, "Invalid num links %d", sync_info->num_links);
2475 return -EINVAL;
2476 }
2477
Pavan Kumar Chilamkurthibd699432018-01-24 12:53:01 -08002478 if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) {
2479 CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x",
2480 sync_info->link_hdls[0], sync_info->link_hdls[1]);
2481 return -EINVAL;
2482 }
2483
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002484 mutex_lock(&g_crm_core_dev->crm_lock);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002485 /* session hdl's priv data is cam session struct */
2486 cam_session = (struct cam_req_mgr_core_session *)
2487 cam_get_device_priv(sync_info->session_hdl);
2488 if (!cam_session) {
2489 CAM_ERR(CAM_CRM, "NULL pointer");
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002490 mutex_unlock(&g_crm_core_dev->crm_lock);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002491 return -EINVAL;
2492 }
2493
2494 mutex_lock(&cam_session->lock);
Venkat Chinta686c9e52018-01-20 14:33:25 -08002495
Karthik Anantha Ramfa643332017-11-06 13:49:31 -08002496 CAM_DBG(CAM_CRM, "link handles %x %x",
2497 sync_info->link_hdls[0], sync_info->link_hdls[1]);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002498
2499 /* only two links existing per session in dual cam use case*/
2500 link1 = cam_get_device_priv(sync_info->link_hdls[0]);
2501 if (!link1) {
Karthik Anantha Ramfa643332017-11-06 13:49:31 -08002502 CAM_ERR(CAM_CRM, "link1 NULL pointer");
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002503 rc = -EINVAL;
2504 goto done;
2505 }
2506
2507 link2 = cam_get_device_priv(sync_info->link_hdls[1]);
2508 if (!link2) {
Karthik Anantha Ramfa643332017-11-06 13:49:31 -08002509 CAM_ERR(CAM_CRM, "link2 NULL pointer");
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002510 rc = -EINVAL;
2511 goto done;
2512 }
2513
2514 link1->sof_counter = -1;
2515 link1->sync_self_ref = -1;
2516 link1->frame_skip_flag = false;
2517 link1->sync_link = link2;
2518
2519 link2->sof_counter = -1;
2520 link2->sync_self_ref = -1;
2521 link2->frame_skip_flag = false;
2522 link2->sync_link = link1;
2523
2524 cam_session->sync_mode = sync_info->sync_mode;
2525
2526done:
2527 mutex_unlock(&cam_session->lock);
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002528 mutex_unlock(&g_crm_core_dev->crm_lock);
Pavan Kumar Chilamkurthi1fd03442017-11-07 17:07:21 -08002529 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002530}
2531
2532int cam_req_mgr_flush_requests(
Sagar Gored79f95e2017-03-14 18:32:17 -07002533 struct cam_req_mgr_flush_info *flush_info)
Sagar Gore8d91a622017-02-23 14:57:18 -08002534{
Sagar Gored79f95e2017-03-14 18:32:17 -07002535 int rc = 0;
2536 struct crm_workq_task *task = NULL;
2537 struct cam_req_mgr_core_link *link = NULL;
2538 struct cam_req_mgr_flush_info *flush;
2539 struct crm_task_payload *task_data;
2540 struct cam_req_mgr_core_session *session = NULL;
2541
Sagar Gore8d91a622017-02-23 14:57:18 -08002542 if (!flush_info) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002543 CAM_ERR(CAM_CRM, "flush req is NULL");
Sagar Gored79f95e2017-03-14 18:32:17 -07002544 rc = -EFAULT;
2545 goto end;
2546 }
2547 if (flush_info->flush_type >= CAM_REQ_MGR_FLUSH_TYPE_MAX) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002548 CAM_ERR(CAM_CRM, "incorrect flush type %x",
2549 flush_info->flush_type);
Sagar Gored79f95e2017-03-14 18:32:17 -07002550 rc = -EINVAL;
2551 goto end;
Sagar Gore8d91a622017-02-23 14:57:18 -08002552 }
2553
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002554 mutex_lock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002555 /* session hdl's priv data is cam session struct */
2556 session = (struct cam_req_mgr_core_session *)
2557 cam_get_device_priv(flush_info->session_hdl);
2558 if (!session) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002559 CAM_ERR(CAM_CRM, "Invalid session %x", flush_info->session_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002560 rc = -EINVAL;
2561 goto end;
2562 }
2563 if (session->num_links <= 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002564 CAM_WARN(CAM_CRM, "No active links in session %x",
Sagar Gored79f95e2017-03-14 18:32:17 -07002565 flush_info->session_hdl);
2566 goto end;
2567 }
2568
2569 link = (struct cam_req_mgr_core_link *)
2570 cam_get_device_priv(flush_info->link_hdl);
2571 if (!link) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002572 CAM_DBG(CAM_CRM, "link ptr NULL %x", flush_info->link_hdl);
Sagar Gored79f95e2017-03-14 18:32:17 -07002573 rc = -EINVAL;
2574 goto end;
2575 }
2576
2577 task = cam_req_mgr_workq_get_task(link->workq);
2578 if (!task) {
2579 rc = -ENOMEM;
2580 goto end;
2581 }
2582
2583 task_data = (struct crm_task_payload *)task->payload;
2584 task_data->type = CRM_WORKQ_TASK_FLUSH_REQ;
2585 flush = (struct cam_req_mgr_flush_info *)&task_data->u;
2586 flush->req_id = flush_info->req_id;
2587 flush->link_hdl = flush_info->link_hdl;
2588 flush->flush_type = flush_info->flush_type;
2589 task->process_cb = &cam_req_mgr_process_flush_req;
Junzhe Zou158da722017-10-25 19:14:32 -07002590 init_completion(&link->workq_comp);
Sagar Gored79f95e2017-03-14 18:32:17 -07002591 rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
2592
2593 /* Blocking call */
Sagar Gored79f95e2017-03-14 18:32:17 -07002594 rc = wait_for_completion_timeout(
2595 &link->workq_comp,
2596 msecs_to_jiffies(CAM_REQ_MGR_SCHED_REQ_TIMEOUT));
2597end:
Vishalsingh Hajeri41ac1672017-12-01 14:36:00 -08002598 mutex_unlock(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002599 return rc;
Sagar Gore8d91a622017-02-23 14:57:18 -08002600}
2601
Jing Zhou0f645332017-11-17 12:16:40 -08002602int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
2603{
2604 int rc = 0;
Jing Zhou30504bd2017-11-21 11:36:07 -08002605 int i, j;
Jing Zhou0f645332017-11-17 12:16:40 -08002606 struct cam_req_mgr_core_link *link = NULL;
2607
Jing Zhou30504bd2017-11-21 11:36:07 -08002608 struct cam_req_mgr_connected_device *dev = NULL;
2609 struct cam_req_mgr_link_evt_data evt_data;
2610
Jing Zhou0f645332017-11-17 12:16:40 -08002611 if (!control) {
2612 CAM_ERR(CAM_CRM, "Control command is NULL");
2613 rc = -EINVAL;
2614 goto end;
2615 }
2616
2617 mutex_lock(&g_crm_core_dev->crm_lock);
2618 for (i = 0; i < control->num_links; i++) {
2619 link = (struct cam_req_mgr_core_link *)
2620 cam_get_device_priv(control->link_hdls[i]);
2621 if (!link) {
2622 CAM_ERR(CAM_CRM, "Link(%d) is NULL on session 0x%x",
2623 i, control->session_hdl);
2624 rc = -EINVAL;
2625 break;
2626 }
2627
2628 mutex_lock(&link->lock);
2629 if (control->ops == CAM_REQ_MGR_LINK_ACTIVATE) {
2630 /* Start SOF watchdog timer */
2631 rc = crm_timer_init(&link->watchdog,
2632 CAM_REQ_MGR_WATCHDOG_TIMEOUT, link,
2633 &__cam_req_mgr_sof_freeze);
2634 if (rc < 0) {
2635 CAM_ERR(CAM_CRM,
2636 "SOF timer start fails: link=0x%x",
2637 link->link_hdl);
2638 rc = -EFAULT;
2639 }
Jing Zhou30504bd2017-11-21 11:36:07 -08002640 /* notify nodes */
2641 for (j = 0; j < link->num_devs; j++) {
2642 dev = &link->l_dev[j];
2643 evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_RESUME;
2644 evt_data.link_hdl = link->link_hdl;
2645 evt_data.dev_hdl = dev->dev_hdl;
2646 evt_data.req_id = 0;
2647 if (dev->ops && dev->ops->process_evt)
2648 dev->ops->process_evt(&evt_data);
2649 }
Jing Zhou0f645332017-11-17 12:16:40 -08002650 } else if (control->ops == CAM_REQ_MGR_LINK_DEACTIVATE) {
2651 /* Destroy SOF watchdog timer */
Venkat Chinta686c9e52018-01-20 14:33:25 -08002652 spin_lock_bh(&link->link_state_spin_lock);
Jing Zhou0f645332017-11-17 12:16:40 -08002653 crm_timer_exit(&link->watchdog);
Venkat Chinta686c9e52018-01-20 14:33:25 -08002654 spin_unlock_bh(&link->link_state_spin_lock);
Jing Zhou30504bd2017-11-21 11:36:07 -08002655 /* notify nodes */
2656 for (j = 0; j < link->num_devs; j++) {
2657 dev = &link->l_dev[j];
2658 evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_PAUSE;
2659 evt_data.link_hdl = link->link_hdl;
2660 evt_data.dev_hdl = dev->dev_hdl;
2661 evt_data.req_id = 0;
2662 if (dev->ops && dev->ops->process_evt)
2663 dev->ops->process_evt(&evt_data);
2664 }
Jing Zhou0f645332017-11-17 12:16:40 -08002665 } else {
2666 CAM_ERR(CAM_CRM, "Invalid link control command");
2667 rc = -EINVAL;
2668 }
2669 mutex_unlock(&link->lock);
2670 }
2671 mutex_unlock(&g_crm_core_dev->crm_lock);
2672end:
2673 return rc;
2674}
2675
Sagar Gore8d91a622017-02-23 14:57:18 -08002676
2677int cam_req_mgr_core_device_init(void)
2678{
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002679 CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002680
2681 if (g_crm_core_dev) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002682 CAM_WARN(CAM_CRM, "core device is already initialized");
Sagar Gore8d91a622017-02-23 14:57:18 -08002683 return 0;
2684 }
2685 g_crm_core_dev = (struct cam_req_mgr_core_device *)
2686 kzalloc(sizeof(*g_crm_core_dev), GFP_KERNEL);
2687 if (!g_crm_core_dev)
2688 return -ENOMEM;
2689
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002690 CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002691 INIT_LIST_HEAD(&g_crm_core_dev->session_head);
2692 mutex_init(&g_crm_core_dev->crm_lock);
Sagar Gored79f95e2017-03-14 18:32:17 -07002693 cam_req_mgr_debug_register(g_crm_core_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002694
2695 return 0;
2696}
2697
2698int cam_req_mgr_core_device_deinit(void)
2699{
2700 if (!g_crm_core_dev) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002701 CAM_ERR(CAM_CRM, "NULL pointer");
Sagar Gore8d91a622017-02-23 14:57:18 -08002702 return -EINVAL;
2703 }
2704
Jigarkumar Zala36ad7172017-07-18 19:52:14 -07002705 CAM_DBG(CAM_CRM, "g_crm_core_dev %pK", g_crm_core_dev);
Sagar Gore8d91a622017-02-23 14:57:18 -08002706 mutex_destroy(&g_crm_core_dev->crm_lock);
2707 kfree(g_crm_core_dev);
2708 g_crm_core_dev = NULL;
2709
2710 return 0;
2711}