blob: dda04f8e516417eb4bc8dafef6e13a4d597ce34f [file] [log] [blame]
Venkat Chinta686c9e52018-01-20 14:33:25 -08001/* Copyright (c) 2017-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#define pr_fmt(fmt) "CAM-REQ-MGR_UTIL %s:%d " fmt, __func__, __LINE__
14
15#include <linux/module.h>
16#include <linux/of_platform.h>
17#include <linux/slab.h>
18#include <linux/mutex.h>
19#include <linux/spinlock.h>
20#include <linux/random.h>
21#include <media/cam_req_mgr.h>
22#include "cam_req_mgr_util.h"
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070023#include "cam_debug_util.h"
Sagar Gore8d91a622017-02-23 14:57:18 -080024
25static struct cam_req_mgr_util_hdl_tbl *hdl_tbl;
Jing Zhouefe94f52017-04-26 12:04:14 -070026static DEFINE_SPINLOCK(hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -080027
28int cam_req_mgr_util_init(void)
29{
30 int rc = 0;
31 int bitmap_size;
Jing Zhouefe94f52017-04-26 12:04:14 -070032 static struct cam_req_mgr_util_hdl_tbl *hdl_tbl_local;
Sagar Gore8d91a622017-02-23 14:57:18 -080033
Sagar Gore8d91a622017-02-23 14:57:18 -080034 if (hdl_tbl) {
35 rc = -EINVAL;
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070036 CAM_ERR(CAM_CRM, "Hdl_tbl is already present");
Sagar Gore8d91a622017-02-23 14:57:18 -080037 goto hdl_tbl_check_failed;
38 }
39
Jing Zhouefe94f52017-04-26 12:04:14 -070040 hdl_tbl_local = kzalloc(sizeof(*hdl_tbl), GFP_KERNEL);
41 if (!hdl_tbl_local) {
Sagar Gore8d91a622017-02-23 14:57:18 -080042 rc = -ENOMEM;
43 goto hdl_tbl_alloc_failed;
44 }
Jing Zhouefe94f52017-04-26 12:04:14 -070045 spin_lock_bh(&hdl_tbl_lock);
46 if (hdl_tbl) {
47 spin_unlock_bh(&hdl_tbl_lock);
48 rc = -EEXIST;
49 kfree(hdl_tbl_local);
50 goto hdl_tbl_check_failed;
51 }
52 hdl_tbl = hdl_tbl_local;
53 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -080054
55 bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES) * sizeof(long);
Lakshmi Narayana Kalavalaaae1e6b2017-06-14 09:58:40 -070056 hdl_tbl->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
Sagar Gore8d91a622017-02-23 14:57:18 -080057 if (!hdl_tbl->bitmap) {
58 rc = -ENOMEM;
59 goto bitmap_alloc_fail;
60 }
61 hdl_tbl->bits = bitmap_size * BITS_PER_BYTE;
Sagar Gore8d91a622017-02-23 14:57:18 -080062
63 return rc;
64
65bitmap_alloc_fail:
66 kfree(hdl_tbl);
67 hdl_tbl = NULL;
68hdl_tbl_alloc_failed:
69hdl_tbl_check_failed:
Sagar Gore8d91a622017-02-23 14:57:18 -080070 return rc;
71}
72
73int cam_req_mgr_util_deinit(void)
74{
Jing Zhouefe94f52017-04-26 12:04:14 -070075 spin_lock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -080076 if (!hdl_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070077 CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
Jing Zhouefe94f52017-04-26 12:04:14 -070078 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -080079 return -EINVAL;
80 }
81
82 kfree(hdl_tbl->bitmap);
83 hdl_tbl->bitmap = NULL;
84 kfree(hdl_tbl);
85 hdl_tbl = NULL;
Jing Zhouefe94f52017-04-26 12:04:14 -070086 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -080087
88 return 0;
89}
90
91int cam_req_mgr_util_free_hdls(void)
92{
93 int i = 0;
94
Jing Zhouefe94f52017-04-26 12:04:14 -070095 spin_lock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -080096 if (!hdl_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -070097 CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
Jing Zhouefe94f52017-04-26 12:04:14 -070098 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -080099 return -EINVAL;
100 }
101
102 for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++) {
103 if (hdl_tbl->hdl[i].state == HDL_ACTIVE) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700104 CAM_ERR(CAM_CRM, "Dev handle = %x session_handle = %x",
Sagar Gore8d91a622017-02-23 14:57:18 -0800105 hdl_tbl->hdl[i].hdl_value,
106 hdl_tbl->hdl[i].session_hdl);
107 hdl_tbl->hdl[i].state = HDL_FREE;
108 clear_bit(i, hdl_tbl->bitmap);
109 }
110 }
111 bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES);
Jing Zhouefe94f52017-04-26 12:04:14 -0700112 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800113
114 return 0;
115}
116
117static int32_t cam_get_free_handle_index(void)
118{
119 int idx;
120
121 idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits);
122
123 if (idx >= CAM_REQ_MGR_MAX_HANDLES || idx < 0)
124 return -ENOSR;
125
126 set_bit(idx, hdl_tbl->bitmap);
127
128 return idx;
129}
130
131int32_t cam_create_session_hdl(void *priv)
132{
133 int idx;
134 int rand = 0;
135 int32_t handle = 0;
136
Jing Zhouefe94f52017-04-26 12:04:14 -0700137 spin_lock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800138 if (!hdl_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700139 CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
Jing Zhouefe94f52017-04-26 12:04:14 -0700140 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800141 return -EINVAL;
142 }
143
144 idx = cam_get_free_handle_index();
145 if (idx < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700146 CAM_ERR(CAM_CRM, "Unable to create session handle");
Jing Zhouefe94f52017-04-26 12:04:14 -0700147 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800148 return idx;
149 }
150
151 get_random_bytes(&rand, CAM_REQ_MGR_RND1_BYTES);
152 handle = GET_DEV_HANDLE(rand, HDL_TYPE_SESSION, idx);
153 hdl_tbl->hdl[idx].session_hdl = handle;
154 hdl_tbl->hdl[idx].hdl_value = handle;
155 hdl_tbl->hdl[idx].type = HDL_TYPE_SESSION;
156 hdl_tbl->hdl[idx].state = HDL_ACTIVE;
157 hdl_tbl->hdl[idx].priv = priv;
158 hdl_tbl->hdl[idx].ops = NULL;
Jing Zhouefe94f52017-04-26 12:04:14 -0700159 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800160
161 return handle;
162}
163
164int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
165{
166 int idx;
167 int rand = 0;
168 int32_t handle;
169
Jing Zhouefe94f52017-04-26 12:04:14 -0700170 spin_lock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800171 if (!hdl_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700172 CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
Jing Zhouefe94f52017-04-26 12:04:14 -0700173 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800174 return -EINVAL;
175 }
176
177 idx = cam_get_free_handle_index();
178 if (idx < 0) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700179 CAM_ERR(CAM_CRM, "Unable to create device handle");
Jing Zhouefe94f52017-04-26 12:04:14 -0700180 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800181 return idx;
182 }
183
184 get_random_bytes(&rand, CAM_REQ_MGR_RND1_BYTES);
185 handle = GET_DEV_HANDLE(rand, HDL_TYPE_DEV, idx);
186 hdl_tbl->hdl[idx].session_hdl = hdl_data->session_hdl;
187 hdl_tbl->hdl[idx].hdl_value = handle;
188 hdl_tbl->hdl[idx].type = HDL_TYPE_DEV;
189 hdl_tbl->hdl[idx].state = HDL_ACTIVE;
190 hdl_tbl->hdl[idx].priv = hdl_data->priv;
191 hdl_tbl->hdl[idx].ops = hdl_data->ops;
Jing Zhouefe94f52017-04-26 12:04:14 -0700192 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800193
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700194 pr_debug("%s: handle = %x", __func__, handle);
Sagar Gore8d91a622017-02-23 14:57:18 -0800195 return handle;
196}
197
198void *cam_get_device_priv(int32_t dev_hdl)
199{
200 int idx;
201 int type;
202 void *priv;
203
Jing Zhouefe94f52017-04-26 12:04:14 -0700204 spin_lock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800205 if (!hdl_tbl) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700206 CAM_ERR_RATE_LIMIT(CAM_CRM, "Hdl tbl is NULL");
Sagar Gore8d91a622017-02-23 14:57:18 -0800207 goto device_priv_fail;
208 }
209
210 idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
211 if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700212 CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid idx");
Sagar Gore8d91a622017-02-23 14:57:18 -0800213 goto device_priv_fail;
214 }
215
216 if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700217 CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid state");
Sagar Gore8d91a622017-02-23 14:57:18 -0800218 goto device_priv_fail;
219 }
220
221 type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl);
222 if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700223 CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid type");
Sagar Gore8d91a622017-02-23 14:57:18 -0800224 goto device_priv_fail;
225 }
226
227 if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700228 CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid hdl");
Sagar Gore8d91a622017-02-23 14:57:18 -0800229 goto device_priv_fail;
230 }
231
232 priv = hdl_tbl->hdl[idx].priv;
Jing Zhouefe94f52017-04-26 12:04:14 -0700233 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800234
235 return priv;
236
237device_priv_fail:
Jing Zhouefe94f52017-04-26 12:04:14 -0700238 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800239 return NULL;
240}
241
242void *cam_get_device_ops(int32_t dev_hdl)
243{
244 int idx;
245 int type;
246 void *ops;
247
Jing Zhouefe94f52017-04-26 12:04:14 -0700248 spin_lock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800249 if (!hdl_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700250 CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
Sagar Gore8d91a622017-02-23 14:57:18 -0800251 goto device_ops_fail;
252 }
253
254 idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
255 if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700256 CAM_ERR(CAM_CRM, "Invalid idx");
Sagar Gore8d91a622017-02-23 14:57:18 -0800257 goto device_ops_fail;
258 }
259
260 if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700261 CAM_ERR(CAM_CRM, "Invalid state");
Sagar Gore8d91a622017-02-23 14:57:18 -0800262 goto device_ops_fail;
263 }
264
265 type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl);
266 if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700267 CAM_ERR(CAM_CRM, "Invalid type");
Sagar Gore8d91a622017-02-23 14:57:18 -0800268 goto device_ops_fail;
269 }
270
271 if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700272 CAM_ERR(CAM_CRM, "Invalid hdl");
Sagar Gore8d91a622017-02-23 14:57:18 -0800273 goto device_ops_fail;
274 }
275
276 ops = hdl_tbl->hdl[idx].ops;
Jing Zhouefe94f52017-04-26 12:04:14 -0700277 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800278
279 return ops;
280
281device_ops_fail:
Jing Zhouefe94f52017-04-26 12:04:14 -0700282 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800283 return NULL;
284}
285
286static int cam_destroy_hdl(int32_t dev_hdl, int dev_hdl_type)
287{
288 int idx;
289 int type;
290
Jing Zhouefe94f52017-04-26 12:04:14 -0700291 spin_lock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800292 if (!hdl_tbl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700293 CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
Sagar Gore8d91a622017-02-23 14:57:18 -0800294 goto destroy_hdl_fail;
295 }
296
297 idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
298 if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
Venkat Chinta686c9e52018-01-20 14:33:25 -0800299 CAM_ERR(CAM_CRM, "Invalid idx %d", idx);
Sagar Gore8d91a622017-02-23 14:57:18 -0800300 goto destroy_hdl_fail;
301 }
302
303 if (hdl_tbl->hdl[idx].state != HDL_ACTIVE) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700304 CAM_ERR(CAM_CRM, "Invalid state");
Sagar Gore8d91a622017-02-23 14:57:18 -0800305 goto destroy_hdl_fail;
306 }
307
308 type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl);
309 if (type != dev_hdl_type) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700310 CAM_ERR(CAM_CRM, "Invalid type %d, %d", type, dev_hdl_type);
Sagar Gore8d91a622017-02-23 14:57:18 -0800311 goto destroy_hdl_fail;
312 }
313
314 if (hdl_tbl->hdl[idx].hdl_value != dev_hdl) {
Jigarkumar Zala36ad7172017-07-18 19:52:14 -0700315 CAM_ERR(CAM_CRM, "Invalid hdl");
Sagar Gore8d91a622017-02-23 14:57:18 -0800316 goto destroy_hdl_fail;
317 }
318
319 hdl_tbl->hdl[idx].state = HDL_FREE;
Harsh Shaha606d182017-11-10 00:15:58 -0800320 hdl_tbl->hdl[idx].ops = NULL;
321 hdl_tbl->hdl[idx].priv = NULL;
Sagar Gore8d91a622017-02-23 14:57:18 -0800322 clear_bit(idx, hdl_tbl->bitmap);
Jing Zhouefe94f52017-04-26 12:04:14 -0700323 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800324
325 return 0;
326
327destroy_hdl_fail:
Jing Zhouefe94f52017-04-26 12:04:14 -0700328 spin_unlock_bh(&hdl_tbl_lock);
Sagar Gore8d91a622017-02-23 14:57:18 -0800329 return -EINVAL;
330}
331
332int cam_destroy_device_hdl(int32_t dev_hdl)
333{
334 return cam_destroy_hdl(dev_hdl, HDL_TYPE_DEV);
335}
336
337int cam_destroy_session_hdl(int32_t dev_hdl)
338{
339 return cam_destroy_hdl(dev_hdl, HDL_TYPE_SESSION);
340}