blob: 2a24d76179852dd480382b8acc8cbd1d296b117a [file] [log] [blame]
Jing Zhou076a3092017-02-27 02:43:03 -08001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
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/slab.h>
14#include <linux/uaccess.h>
15#include "cam_context.h"
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070016#include "cam_debug_util.h"
Jing Zhou076a3092017-02-27 02:43:03 -080017
18static int cam_context_handle_hw_event(void *context, uint32_t evt_id,
19 void *evt_data)
20{
21 int rc = 0;
22 struct cam_context *ctx = (struct cam_context *)context;
23
24 if (!ctx || !ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070025 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -080026 return -EINVAL;
27 }
28
29 if (ctx->state_machine[ctx->state].irq_ops)
30 rc = ctx->state_machine[ctx->state].irq_ops(ctx, evt_id,
31 evt_data);
32 else
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070033 CAM_DBG(CAM_CORE,
34 "No function to handle event %d in dev %d, state %d",
35 evt_id, ctx->dev_hdl, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -080036 return rc;
37}
38
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -070039int cam_context_shutdown(struct cam_context *ctx)
40{
41 int rc = 0;
42
43 if (ctx->state_machine[ctx->state].ioctl_ops.stop_dev) {
44 rc = ctx->state_machine[ctx->state].ioctl_ops.stop_dev(
45 ctx, NULL);
46 if (rc < 0)
47 CAM_ERR(CAM_CORE, "Error while dev stop %d", rc);
48 }
49 if (ctx->state_machine[ctx->state].ioctl_ops.release_dev) {
50 rc = ctx->state_machine[ctx->state].ioctl_ops.release_dev(
51 ctx, NULL);
52 if (rc < 0)
53 CAM_ERR(CAM_CORE, "Error while dev release %d", rc);
54 }
55
56 return rc;
57}
58
Jing Zhoub524a852017-05-16 15:47:30 +053059int cam_context_handle_crm_get_dev_info(struct cam_context *ctx,
Jing Zhou076a3092017-02-27 02:43:03 -080060 struct cam_req_mgr_device_info *info)
61{
62 int rc;
63
64 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070065 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -080066 return -EINVAL;
67 }
68
69 if (!info) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070070 CAM_ERR(CAM_CORE, "Invalid get device info payload");
Jing Zhou076a3092017-02-27 02:43:03 -080071 return -EINVAL;
72 }
73
74 mutex_lock(&ctx->ctx_mutex);
75 if (ctx->state_machine[ctx->state].crm_ops.get_dev_info) {
76 rc = ctx->state_machine[ctx->state].crm_ops.get_dev_info(
77 ctx, info);
78 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070079 CAM_ERR(CAM_CORE, "No get device info in dev %d, state %d",
80 ctx->dev_hdl, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -080081 rc = -EPROTO;
82 }
83 mutex_unlock(&ctx->ctx_mutex);
84
85 return rc;
86}
87
Jing Zhoub524a852017-05-16 15:47:30 +053088int cam_context_handle_crm_link(struct cam_context *ctx,
Jing Zhou076a3092017-02-27 02:43:03 -080089 struct cam_req_mgr_core_dev_link_setup *link)
90{
91 int rc;
92
93 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070094 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -080095 return -EINVAL;
96 }
97
98 if (!link) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070099 CAM_ERR(CAM_CORE, "Invalid link payload");
Jing Zhou076a3092017-02-27 02:43:03 -0800100 return -EINVAL;
101 }
102
103 mutex_lock(&ctx->ctx_mutex);
104 if (ctx->state_machine[ctx->state].crm_ops.link) {
105 rc = ctx->state_machine[ctx->state].crm_ops.link(ctx, link);
106 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700107 CAM_ERR(CAM_CORE, "No crm link in dev %d, state %d",
Jing Zhou076a3092017-02-27 02:43:03 -0800108 ctx->dev_hdl, ctx->state);
109 rc = -EPROTO;
110 }
111 mutex_unlock(&ctx->ctx_mutex);
112
113 return rc;
114}
115
Jing Zhoub524a852017-05-16 15:47:30 +0530116int cam_context_handle_crm_unlink(struct cam_context *ctx,
Jing Zhou076a3092017-02-27 02:43:03 -0800117 struct cam_req_mgr_core_dev_link_setup *unlink)
118{
119 int rc;
120
121 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700122 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -0800123 return -EINVAL;
124 }
125
126 if (!unlink) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700127 CAM_ERR(CAM_CORE, "Invalid unlink payload");
Jing Zhou076a3092017-02-27 02:43:03 -0800128 return -EINVAL;
129 }
130
131 mutex_lock(&ctx->ctx_mutex);
132 if (ctx->state_machine[ctx->state].crm_ops.unlink) {
133 rc = ctx->state_machine[ctx->state].crm_ops.unlink(
134 ctx, unlink);
135 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700136 CAM_ERR(CAM_CORE, "No crm unlink in dev %d, state %d",
137 ctx->dev_hdl, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -0800138 rc = -EPROTO;
139 }
140 mutex_unlock(&ctx->ctx_mutex);
141
142 return rc;
143}
144
Jing Zhoub524a852017-05-16 15:47:30 +0530145int cam_context_handle_crm_apply_req(struct cam_context *ctx,
Jing Zhou076a3092017-02-27 02:43:03 -0800146 struct cam_req_mgr_apply_request *apply)
147{
148 int rc;
149
150 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700151 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -0800152 return -EINVAL;
153 }
154
155 if (!apply) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700156 CAM_ERR(CAM_CORE, "Invalid apply request payload");
Jing Zhou076a3092017-02-27 02:43:03 -0800157 return -EINVAL;
158 }
159
160 mutex_lock(&ctx->ctx_mutex);
161 if (ctx->state_machine[ctx->state].crm_ops.apply_req) {
162 rc = ctx->state_machine[ctx->state].crm_ops.apply_req(ctx,
163 apply);
164 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700165 CAM_ERR(CAM_CORE, "No crm apply req in dev %d, state %d",
166 ctx->dev_hdl, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -0800167 rc = -EPROTO;
168 }
169 mutex_unlock(&ctx->ctx_mutex);
170
171 return rc;
172}
173
Jing Zhoub524a852017-05-16 15:47:30 +0530174int cam_context_handle_crm_flush_req(struct cam_context *ctx,
175 struct cam_req_mgr_flush_request *flush)
176{
177 int rc;
178
179 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700180 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhoub524a852017-05-16 15:47:30 +0530181 return -EINVAL;
182 }
183
184 mutex_lock(&ctx->ctx_mutex);
185 if (ctx->state_machine[ctx->state].crm_ops.flush_req) {
186 rc = ctx->state_machine[ctx->state].crm_ops.flush_req(ctx,
187 flush);
188 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700189 CAM_ERR(CAM_CORE, "No crm flush req in dev %d, state %d",
190 ctx->dev_hdl, ctx->state);
Jing Zhoub524a852017-05-16 15:47:30 +0530191 rc = -EPROTO;
192 }
193 mutex_unlock(&ctx->ctx_mutex);
194
195 return rc;
196}
Jing Zhou076a3092017-02-27 02:43:03 -0800197
198int cam_context_handle_acquire_dev(struct cam_context *ctx,
199 struct cam_acquire_dev_cmd *cmd)
200{
201 int rc;
202
203 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700204 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -0800205 return -EINVAL;
206 }
207
208 if (!cmd) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700209 CAM_ERR(CAM_CORE, "Invalid acquire device command payload");
Jing Zhou076a3092017-02-27 02:43:03 -0800210 return -EINVAL;
211 }
212
213 mutex_lock(&ctx->ctx_mutex);
214 if (ctx->state_machine[ctx->state].ioctl_ops.acquire_dev) {
215 rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_dev(
216 ctx, cmd);
217 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700218 CAM_ERR(CAM_CORE, "No acquire device in dev %d, state %d",
219 cmd->dev_handle, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -0800220 rc = -EPROTO;
221 }
222 mutex_unlock(&ctx->ctx_mutex);
223
224 return rc;
225}
226
227int cam_context_handle_release_dev(struct cam_context *ctx,
228 struct cam_release_dev_cmd *cmd)
229{
230 int rc;
231
232 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700233 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -0800234 return -EINVAL;
235 }
236
237 if (!cmd) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700238 CAM_ERR(CAM_CORE, "Invalid release device command payload");
Jing Zhou076a3092017-02-27 02:43:03 -0800239 return -EINVAL;
240 }
241
242 mutex_lock(&ctx->ctx_mutex);
243 if (ctx->state_machine[ctx->state].ioctl_ops.release_dev) {
244 rc = ctx->state_machine[ctx->state].ioctl_ops.release_dev(
245 ctx, cmd);
246 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700247 CAM_ERR(CAM_CORE, "No release device in dev %d, state %d",
248 ctx->dev_hdl, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -0800249 rc = -EPROTO;
250 }
251 mutex_unlock(&ctx->ctx_mutex);
252
253 return rc;
254}
255
256int cam_context_handle_config_dev(struct cam_context *ctx,
257 struct cam_config_dev_cmd *cmd)
258{
259 int rc;
260
261 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700262 CAM_ERR(CAM_CORE, "context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -0800263 return -EINVAL;
264 }
265
266 if (!cmd) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700267 CAM_ERR(CAM_CORE, "Invalid config device command payload");
Jing Zhou076a3092017-02-27 02:43:03 -0800268 return -EINVAL;
269 }
270
271 mutex_lock(&ctx->ctx_mutex);
272 if (ctx->state_machine[ctx->state].ioctl_ops.config_dev) {
273 rc = ctx->state_machine[ctx->state].ioctl_ops.config_dev(
274 ctx, cmd);
275 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700276 CAM_ERR(CAM_CORE, "No config device in dev %d, state %d",
277 ctx->dev_hdl, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -0800278 rc = -EPROTO;
279 }
280 mutex_unlock(&ctx->ctx_mutex);
281
282 return rc;
283}
284
285int cam_context_handle_start_dev(struct cam_context *ctx,
286 struct cam_start_stop_dev_cmd *cmd)
287{
288 int rc = 0;
289
290 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700291 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -0800292 return -EINVAL;
293 }
294
295 if (!cmd) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700296 CAM_ERR(CAM_CORE, "Invalid start device command payload");
Jing Zhou076a3092017-02-27 02:43:03 -0800297 return -EINVAL;
298 }
299
300 mutex_lock(&ctx->ctx_mutex);
301 if (ctx->state_machine[ctx->state].ioctl_ops.start_dev)
302 rc = ctx->state_machine[ctx->state].ioctl_ops.start_dev(
303 ctx, cmd);
304 else
305 /* start device can be optional for some driver */
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700306 CAM_DBG(CAM_CORE, "No start device in dev %d, state %d",
307 ctx->dev_hdl, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -0800308
309 mutex_unlock(&ctx->ctx_mutex);
310
311 return rc;
312}
313
314int cam_context_handle_stop_dev(struct cam_context *ctx,
315 struct cam_start_stop_dev_cmd *cmd)
316{
317 int rc = 0;
318
319 if (!ctx->state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700320 CAM_ERR(CAM_CORE, "Context is not ready");
Jing Zhou076a3092017-02-27 02:43:03 -0800321 return -EINVAL;
322 }
323
324 if (!cmd) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700325 CAM_ERR(CAM_CORE, "Invalid stop device command payload");
Jing Zhou076a3092017-02-27 02:43:03 -0800326 return -EINVAL;
327 }
328
329 mutex_lock(&ctx->ctx_mutex);
330 if (ctx->state_machine[ctx->state].ioctl_ops.stop_dev)
331 rc = ctx->state_machine[ctx->state].ioctl_ops.stop_dev(
332 ctx, cmd);
333 else
334 /* stop device can be optional for some driver */
Harsh Shahe9a8a9c2017-11-01 04:07:38 -0700335 CAM_WARN(CAM_CORE, "No stop device in dev %d, name %s state %d",
336 ctx->dev_hdl, ctx->dev_name, ctx->state);
Jing Zhou076a3092017-02-27 02:43:03 -0800337 mutex_unlock(&ctx->ctx_mutex);
338
339 return rc;
340}
341
342int cam_context_init(struct cam_context *ctx,
Harsh Shahe9a8a9c2017-11-01 04:07:38 -0700343 const char *dev_name,
Jing Zhou076a3092017-02-27 02:43:03 -0800344 struct cam_req_mgr_kmd_ops *crm_node_intf,
345 struct cam_hw_mgr_intf *hw_mgr_intf,
346 struct cam_ctx_request *req_list,
347 uint32_t req_size)
348{
349 int i;
350
351 /* crm_node_intf is optinal */
352 if (!ctx || !hw_mgr_intf || !req_list) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700353 CAM_ERR(CAM_CORE, "Invalid input parameters");
Jing Zhou076a3092017-02-27 02:43:03 -0800354 return -EINVAL;
355 }
356
357 memset(ctx, 0, sizeof(*ctx));
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700358 ctx->dev_hdl = -1;
Karthik Anantha Ram34dc2652017-10-20 15:49:54 -0700359 ctx->link_hdl = -1;
360 ctx->session_hdl = -1;
Jing Zhou076a3092017-02-27 02:43:03 -0800361 INIT_LIST_HEAD(&ctx->list);
362 mutex_init(&ctx->ctx_mutex);
363 spin_lock_init(&ctx->lock);
364
Harsh Shahe9a8a9c2017-11-01 04:07:38 -0700365 ctx->dev_name = dev_name;
Jing Zhou076a3092017-02-27 02:43:03 -0800366 ctx->ctx_crm_intf = NULL;
367 ctx->crm_ctx_intf = crm_node_intf;
368 ctx->hw_mgr_intf = hw_mgr_intf;
369 ctx->irq_cb_intf = cam_context_handle_hw_event;
370
371 INIT_LIST_HEAD(&ctx->active_req_list);
372 INIT_LIST_HEAD(&ctx->wait_req_list);
373 INIT_LIST_HEAD(&ctx->pending_req_list);
374 INIT_LIST_HEAD(&ctx->free_req_list);
375 ctx->req_list = req_list;
376 ctx->req_size = req_size;
377 for (i = 0; i < req_size; i++) {
378 INIT_LIST_HEAD(&ctx->req_list[i].list);
379 list_add_tail(&ctx->req_list[i].list, &ctx->free_req_list);
380 }
381 ctx->state = CAM_CTX_AVAILABLE;
382 ctx->state_machine = NULL;
383 ctx->ctx_priv = NULL;
384
385 return 0;
386}
387
388int cam_context_deinit(struct cam_context *ctx)
389{
390 if (!ctx)
391 return -EINVAL;
392
393 /**
394 * This is called from platform device remove.
395 * Everyting should be released at this moment.
396 * so we just free the memory for the context
397 */
398 if (ctx->state != CAM_CTX_AVAILABLE)
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700399 CAM_ERR(CAM_CORE, "Device did not shutdown cleanly");
Jing Zhou076a3092017-02-27 02:43:03 -0800400
401 memset(ctx, 0, sizeof(*ctx));
402
403 return 0;
404}