cam_sync_synx.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #include "cam_sync_synx.h"
  6. /**
  7. * struct cam_synx_obj_row - Synx obj row
  8. */
  9. struct cam_synx_obj_row {
  10. char name[CAM_SYNX_OBJ_NAME_LEN];
  11. uint32_t synx_obj;
  12. enum cam_synx_obj_state state;
  13. cam_sync_callback_for_synx_obj sync_cb;
  14. bool cb_registered_for_sync;
  15. bool sync_signal_synx;
  16. int32_t sync_obj;
  17. };
  18. /**
  19. * struct cam_synx_obj_device - Synx obj device
  20. */
  21. struct cam_synx_obj_device {
  22. struct cam_synx_obj_row rows[CAM_SYNX_MAX_OBJS];
  23. spinlock_t row_spinlocks[CAM_SYNX_MAX_OBJS];
  24. struct synx_session *session_handle;
  25. struct mutex dev_lock;
  26. DECLARE_BITMAP(bitmap, CAM_SYNX_MAX_OBJS);
  27. };
  28. static struct cam_synx_obj_device *g_cam_synx_obj_dev;
  29. static char cam_synx_session_name[64] = "Camera_Generic_Synx_Session";
  30. static int __cam_synx_obj_map_sync_status_util(uint32_t sync_status,
  31. uint32_t *out_synx_status)
  32. {
  33. if (!out_synx_status)
  34. return -EINVAL;
  35. switch (sync_status) {
  36. case CAM_SYNC_STATE_SIGNALED_SUCCESS:
  37. *out_synx_status = SYNX_STATE_SIGNALED_SUCCESS;
  38. break;
  39. case CAM_SYNC_STATE_SIGNALED_CANCEL:
  40. default:
  41. *out_synx_status = SYNX_STATE_SIGNALED_CANCEL;
  42. break;
  43. }
  44. return 0;
  45. }
  46. static int __cam_synx_obj_release(int32_t row_idx)
  47. {
  48. struct cam_synx_obj_row *row = NULL;
  49. spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]);
  50. row = &g_cam_synx_obj_dev->rows[row_idx];
  51. if (row->state == CAM_SYNX_OBJ_STATE_ACTIVE) {
  52. CAM_WARN(CAM_SYNX,
  53. "Unsignaled synx obj being released name: %s synx_obj:%d",
  54. row->name, row->synx_obj);
  55. synx_signal(g_cam_synx_obj_dev->session_handle, row->synx_obj,
  56. SYNX_STATE_SIGNALED_CANCEL);
  57. }
  58. CAM_DBG(CAM_SYNX,
  59. "Releasing synx_obj: %d[%s] row_idx: %u",
  60. row->synx_obj, row->name, row_idx);
  61. synx_release(g_cam_synx_obj_dev->session_handle, row->synx_obj);
  62. /* deinit row */
  63. memset(row, 0, sizeof(struct cam_synx_obj_row));
  64. clear_bit(row_idx, g_cam_synx_obj_dev->bitmap);
  65. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]);
  66. return 0;
  67. }
  68. static int __cam_synx_obj_find_free_idx(uint32_t *idx)
  69. {
  70. int rc = 0;
  71. *idx = find_first_zero_bit(g_cam_synx_obj_dev->bitmap, CAM_SYNX_MAX_OBJS);
  72. if (*idx < CAM_SYNX_MAX_OBJS)
  73. set_bit(*idx, g_cam_synx_obj_dev->bitmap);
  74. else
  75. rc = -ENOMEM;
  76. if (rc)
  77. CAM_ERR(CAM_SYNX, "No free synx idx");
  78. return rc;
  79. }
  80. static void __cam_synx_obj_init_row(uint32_t idx, const char *name,
  81. uint32_t synx_obj)
  82. {
  83. struct cam_synx_obj_row *row;
  84. spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]);
  85. row = &g_cam_synx_obj_dev->rows[idx];
  86. memset(row, 0, sizeof(*row));
  87. row->synx_obj = synx_obj;
  88. row->state = CAM_SYNX_OBJ_STATE_ACTIVE;
  89. strscpy(row->name, name, CAM_SYNX_OBJ_NAME_LEN);
  90. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]);
  91. }
  92. static int __cam_synx_obj_release_row(int32_t row_idx)
  93. {
  94. if ((row_idx < 0) || (row_idx >= CAM_SYNX_MAX_OBJS)) {
  95. CAM_ERR(CAM_SYNX, "synx row idx: %d is invalid",
  96. row_idx);
  97. return -EINVAL;
  98. }
  99. return __cam_synx_obj_release(row_idx);
  100. }
  101. static void __cam_synx_obj_signal_cb(u32 h_synx, int status, void *data)
  102. {
  103. struct cam_synx_obj_signal_sync_obj signal_sync_obj;
  104. struct cam_synx_obj_row *synx_obj_row = NULL;
  105. if (!data) {
  106. CAM_ERR(CAM_SYNX,
  107. "Invalid data passed to synx obj : %d callback function.",
  108. synx_obj_row->synx_obj);
  109. return;
  110. }
  111. synx_obj_row = (struct cam_synx_obj_row *)data;
  112. /* If this synx obj is signaled by sync obj, skip cb */
  113. if (synx_obj_row->sync_signal_synx)
  114. return;
  115. if (synx_obj_row->synx_obj != h_synx) {
  116. CAM_ERR(CAM_SYNX,
  117. "Synx obj: %d callback does not match synx obj: %d in sync table.",
  118. h_synx, synx_obj_row->synx_obj);
  119. return;
  120. }
  121. if (synx_obj_row->state == CAM_SYNX_OBJ_STATE_INVALID) {
  122. CAM_ERR(CAM_SYNX,
  123. "Synx obj :%d is in invalid state: %d",
  124. synx_obj_row->synx_obj, synx_obj_row->state);
  125. return;
  126. }
  127. CAM_DBG(CAM_SYNX, "Synx obj: %d signaled, signal sync obj: %d",
  128. synx_obj_row->synx_obj, synx_obj_row->sync_obj);
  129. if ((synx_obj_row->cb_registered_for_sync) && (synx_obj_row->sync_cb)) {
  130. signal_sync_obj.synx_obj = synx_obj_row->synx_obj;
  131. switch (status) {
  132. case SYNX_STATE_SIGNALED_SUCCESS:
  133. signal_sync_obj.status = CAM_SYNC_STATE_SIGNALED_SUCCESS;
  134. break;
  135. case SYNX_STATE_SIGNALED_CANCEL:
  136. signal_sync_obj.status = CAM_SYNC_STATE_SIGNALED_CANCEL;
  137. break;
  138. default:
  139. CAM_WARN(CAM_SYNX,
  140. "Synx signal status %d is neither SUCCESS nor CANCEL, custom code?",
  141. status);
  142. signal_sync_obj.status = CAM_SYNC_STATE_SIGNALED_ERROR;
  143. break;
  144. }
  145. synx_obj_row->state = CAM_SYNX_OBJ_STATE_SIGNALED;
  146. synx_obj_row->sync_cb(synx_obj_row->sync_obj, &signal_sync_obj);
  147. }
  148. }
  149. int cam_synx_obj_find_obj_in_table(uint32_t synx_obj, int32_t *idx)
  150. {
  151. int i, rc = -EINVAL;
  152. struct cam_synx_obj_row *row = NULL;
  153. for (i = 0; i < CAM_SYNX_MAX_OBJS; i++) {
  154. spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]);
  155. row = &g_cam_synx_obj_dev->rows[i];
  156. if ((row->state != CAM_SYNX_OBJ_STATE_INVALID) &&
  157. (row->synx_obj == synx_obj)) {
  158. *idx = i;
  159. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]);
  160. rc = 0;
  161. break;
  162. }
  163. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]);
  164. }
  165. return rc;
  166. }
  167. static int __cam_synx_obj_release_obj(uint32_t synx_obj)
  168. {
  169. int32_t idx;
  170. if (cam_synx_obj_find_obj_in_table(synx_obj, &idx)) {
  171. CAM_ERR(CAM_SYNX, "Failed to find synx obj: %d", synx_obj);
  172. return -EINVAL;
  173. }
  174. return __cam_synx_obj_release(idx);
  175. }
  176. static int __cam_synx_obj_import(const char *name,
  177. struct synx_import_params *params, int32_t *row_idx)
  178. {
  179. int rc = -1;
  180. uint32_t idx;
  181. if (__cam_synx_obj_find_free_idx(&idx))
  182. goto end;
  183. rc = synx_import(g_cam_synx_obj_dev->session_handle, params);
  184. if (rc) {
  185. CAM_ERR(CAM_SYNX, "Synx import failed for fence : %p",
  186. params->indv.fence);
  187. goto free_idx;
  188. }
  189. *row_idx = idx;
  190. __cam_synx_obj_init_row(idx, name, *params->indv.new_h_synx);
  191. CAM_DBG(CAM_SYNX, "Imported synx obj handle: %d[%s] row_idx: %u",
  192. *params->indv.new_h_synx, name, idx);
  193. return rc;
  194. free_idx:
  195. clear_bit(idx, g_cam_synx_obj_dev->bitmap);
  196. end:
  197. return rc;
  198. }
  199. static int __cam_synx_map_generic_flags_to_create(uint32_t generic_flags,
  200. struct synx_create_params *params)
  201. {
  202. if (!params) {
  203. CAM_ERR(CAM_SYNX, "Create parameters missing");
  204. return -EINVAL;
  205. }
  206. if (CAM_GENERIC_FENCE_FLAG_IS_GLOBAL_SYNX_OBJ & generic_flags)
  207. params->flags |= SYNX_CREATE_GLOBAL_FENCE;
  208. else
  209. params->flags |= SYNX_CREATE_LOCAL_FENCE;
  210. return 0;
  211. }
  212. static int __cam_synx_map_generic_flags_to_import(uint32_t generic_flags,
  213. struct synx_import_indv_params *params)
  214. {
  215. if (!params) {
  216. CAM_ERR(CAM_SYNX, "Import parameters missing");
  217. return -EINVAL;
  218. }
  219. if (CAM_GENERIC_FENCE_FLAG_IS_GLOBAL_SYNX_OBJ & generic_flags)
  220. params->flags |= SYNX_IMPORT_GLOBAL_FENCE;
  221. else
  222. params->flags |= SYNX_IMPORT_LOCAL_FENCE;
  223. return 0;
  224. }
  225. int cam_synx_obj_create(const char *name, uint32_t flags, uint32_t *synx_obj,
  226. int32_t *row_idx)
  227. {
  228. int rc = -1;
  229. uint32_t idx;
  230. struct synx_create_params params;
  231. if (__cam_synx_obj_find_free_idx(&idx))
  232. goto end;
  233. params.fence = NULL;
  234. params.name = name;
  235. params.flags = 0;
  236. params.h_synx = synx_obj;
  237. rc = __cam_synx_map_generic_flags_to_create(flags, &params);
  238. if (rc) {
  239. CAM_ERR(CAM_SYNX, "Failed to generate create flags");
  240. goto free_idx;
  241. }
  242. /*
  243. * Create Global Always - remove after userspace optimizes and
  244. * determines when global Vs local is needed
  245. */
  246. params.flags |= SYNX_CREATE_GLOBAL_FENCE;
  247. rc = synx_create(g_cam_synx_obj_dev->session_handle, &params);
  248. if (rc) {
  249. CAM_ERR(CAM_SYNX, "Failed to create synx obj");
  250. goto free_idx;
  251. }
  252. *row_idx = idx;
  253. __cam_synx_obj_init_row(idx, name, *synx_obj);
  254. CAM_DBG(CAM_SYNX, "Created synx obj handle: %d[%s] row_idx: %u",
  255. *synx_obj, name, idx);
  256. return rc;
  257. free_idx:
  258. clear_bit(idx, g_cam_synx_obj_dev->bitmap);
  259. end:
  260. return rc;
  261. }
  262. int cam_synx_obj_import_dma_fence(const char *name, uint32_t flags, void *fence,
  263. uint32_t *synx_obj, int32_t *row_idx)
  264. {
  265. struct synx_import_params params;
  266. if (!fence) {
  267. CAM_ERR(CAM_SYNX,
  268. "Importing DMA fence failed - fence pointer is NULL");
  269. return -EINVAL;
  270. }
  271. params.indv.flags = 0;
  272. params.indv.fence = fence;
  273. params.indv.new_h_synx = synx_obj;
  274. params.type = SYNX_IMPORT_INDV_PARAMS;
  275. params.indv.flags |= SYNX_IMPORT_DMA_FENCE;
  276. if (__cam_synx_map_generic_flags_to_import(flags, &params.indv)) {
  277. CAM_ERR(CAM_SYNX,
  278. "Importing DMA fence failed - invalid synx import flags");
  279. return -EINVAL;
  280. }
  281. return __cam_synx_obj_import(name, &params, row_idx);
  282. }
  283. int cam_synx_obj_internal_signal(int32_t row_idx,
  284. struct cam_synx_obj_signal *signal_synx_obj)
  285. {
  286. int rc = 0;
  287. uint32_t signal_status;
  288. struct cam_synx_obj_row *row = NULL;
  289. if ((row_idx < 0) || (row_idx >= CAM_SYNX_MAX_OBJS)) {
  290. CAM_ERR(CAM_SYNX, "synx obj row idx: %d is invalid",
  291. row_idx);
  292. return -EINVAL;
  293. }
  294. spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]);
  295. row = &g_cam_synx_obj_dev->rows[row_idx];
  296. /* Ensures sync obj cb is not invoked */
  297. row->sync_signal_synx = true;
  298. if (row->state == CAM_SYNX_OBJ_STATE_SIGNALED) {
  299. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]);
  300. CAM_WARN(CAM_SYNX, "synx obj fd: %d already in signaled state",
  301. signal_synx_obj->synx_obj);
  302. return 0;
  303. }
  304. rc = __cam_synx_obj_map_sync_status_util(signal_synx_obj->status,
  305. &signal_status);
  306. if (rc) {
  307. CAM_WARN(CAM_SYNX,
  308. "Signaling undefined status: %d for synx obj: %d",
  309. signal_synx_obj->status,
  310. signal_synx_obj->synx_obj);
  311. }
  312. rc = synx_signal(g_cam_synx_obj_dev->session_handle,
  313. signal_synx_obj->synx_obj, signal_status);
  314. if (rc)
  315. CAM_WARN(CAM_SYNX, "synx obj: %d already signaled rc: %d",
  316. row->synx_obj, rc);
  317. row->state = CAM_SYNX_OBJ_STATE_SIGNALED;
  318. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]);
  319. CAM_DBG(CAM_SYNX, "synx obj: %d signaled with status: %d rc: %d",
  320. signal_synx_obj->synx_obj, signal_status, rc);
  321. return rc;
  322. }
  323. int cam_synx_obj_release(struct cam_synx_obj_release_params *release_params)
  324. {
  325. if (release_params->use_row_idx)
  326. return __cam_synx_obj_release_row(release_params->u.synx_row_idx);
  327. else
  328. return __cam_synx_obj_release_obj(release_params->u.synx_obj);
  329. }
  330. int cam_synx_obj_signal_obj(struct cam_synx_obj_signal *signal_synx_obj)
  331. {
  332. int rc = 0;
  333. uint32_t idx, signal_status = 0;
  334. struct cam_synx_obj_row *row = NULL;
  335. rc = cam_synx_obj_find_obj_in_table(
  336. signal_synx_obj->synx_obj, &idx);
  337. if (rc) {
  338. CAM_ERR(CAM_SYNX, "Failed to find synx obj: %d",
  339. signal_synx_obj->synx_obj);
  340. return -EINVAL;
  341. }
  342. spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]);
  343. row = &g_cam_synx_obj_dev->rows[idx];
  344. if (row->state == CAM_SYNX_OBJ_STATE_SIGNALED) {
  345. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]);
  346. CAM_WARN(CAM_SYNX, "synx obj: %d already in signaled state",
  347. signal_synx_obj->synx_obj);
  348. return 0;
  349. }
  350. rc = __cam_synx_obj_map_sync_status_util(signal_synx_obj->status,
  351. &signal_status);
  352. if (rc) {
  353. CAM_WARN(CAM_SYNX,
  354. "Signaling undefined sync status: %d for synx obj: %d",
  355. signal_synx_obj->status,
  356. signal_synx_obj->synx_obj);
  357. }
  358. rc = synx_signal(g_cam_synx_obj_dev->session_handle,
  359. signal_synx_obj->synx_obj, signal_status);
  360. if (rc)
  361. CAM_WARN(CAM_SYNX, "synx obj: %d already signaled rc: %d",
  362. row->synx_obj, rc);
  363. row->state = CAM_SYNX_OBJ_STATE_SIGNALED;
  364. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[idx]);
  365. CAM_DBG(CAM_SYNX, "synx obj: %d signaled with status: %d rc: %d",
  366. signal_synx_obj->synx_obj, signal_status, rc);
  367. return rc;
  368. }
  369. int cam_synx_obj_register_cb(int32_t *sync_obj, int32_t row_idx,
  370. cam_sync_callback_for_synx_obj sync_cb)
  371. {
  372. int rc = 0;
  373. struct cam_synx_obj_row *row = NULL;
  374. struct synx_callback_params cb_params;
  375. if (!sync_obj || !sync_cb) {
  376. CAM_ERR(CAM_SYNX, "Invalid args sync_obj: %p sync_cb: %p",
  377. sync_obj, sync_cb);
  378. return -EINVAL;
  379. }
  380. if ((row_idx < 0) || (row_idx >= CAM_SYNX_MAX_OBJS)) {
  381. CAM_ERR(CAM_SYNX, "synx obj idx: %d is invalid",
  382. row_idx);
  383. return -EINVAL;
  384. }
  385. spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]);
  386. row = &g_cam_synx_obj_dev->rows[row_idx];
  387. if (row->state != CAM_SYNX_OBJ_STATE_ACTIVE) {
  388. CAM_ERR(CAM_SYNX,
  389. "synx obj at idx: %d handle: %d is not active, current state: %d",
  390. row_idx, row->synx_obj, row->state);
  391. rc = -EINVAL;
  392. goto end;
  393. }
  394. /**
  395. * If the cb is already registered, return
  396. */
  397. if (row->cb_registered_for_sync) {
  398. CAM_WARN(CAM_SYNX,
  399. "synx obj at idx: %d handle: %d has already registered a cb for sync: %d",
  400. row_idx, row->synx_obj, row->sync_obj);
  401. goto end;
  402. }
  403. cb_params.userdata = row;
  404. cb_params.cancel_cb_func = NULL;
  405. cb_params.h_synx = row->synx_obj;
  406. cb_params.cb_func = __cam_synx_obj_signal_cb;
  407. rc = synx_async_wait(g_cam_synx_obj_dev->session_handle, &cb_params);
  408. if (rc) {
  409. CAM_ERR(CAM_SYNX,
  410. "Failed to register cb for synx obj: %d rc: %d",
  411. row->synx_obj, rc);
  412. goto end;
  413. }
  414. row->sync_cb = sync_cb;
  415. row->sync_obj = *sync_obj;
  416. row->cb_registered_for_sync = true;
  417. CAM_DBG(CAM_SYNX,
  418. "CB successfully registered for synx obj: %d for sync_obj: %d",
  419. row->synx_obj, *sync_obj);
  420. end:
  421. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[row_idx]);
  422. return rc;
  423. }
  424. int __cam_synx_init_session(void)
  425. {
  426. struct synx_queue_desc queue_desc;
  427. struct synx_initialization_params params;
  428. params.name = cam_synx_session_name;
  429. params.ptr = &queue_desc;
  430. params.flags = SYNX_INIT_MAX;
  431. params.id = SYNX_CLIENT_NATIVE;
  432. g_cam_synx_obj_dev->session_handle = synx_initialize(&params);
  433. if (!g_cam_synx_obj_dev->session_handle) {
  434. CAM_ERR(CAM_SYNX, "Synx session initialization failed");
  435. return -EINVAL;
  436. }
  437. CAM_DBG(CAM_SYNX, "Synx session initialized: %p",
  438. g_cam_synx_obj_dev->session_handle);
  439. return 0;
  440. }
  441. void cam_synx_obj_close(void)
  442. {
  443. int i, rc = 0;
  444. struct cam_synx_obj_row *row = NULL;
  445. struct synx_callback_params cb_params;
  446. mutex_lock(&g_cam_synx_obj_dev->dev_lock);
  447. for (i = 0; i < CAM_SYNX_MAX_OBJS; i++) {
  448. spin_lock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]);
  449. row = &g_cam_synx_obj_dev->rows[i];
  450. if (row->state == CAM_SYNX_OBJ_STATE_INVALID) {
  451. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]);
  452. continue;
  453. }
  454. CAM_DBG(CAM_SYNX, "Releasing synx_obj: %d[%s]",
  455. row->synx_obj, row->name);
  456. /* If registered for cb, remove cb */
  457. if (row->cb_registered_for_sync) {
  458. cb_params.userdata = row;
  459. cb_params.cancel_cb_func = NULL;
  460. cb_params.h_synx = row->synx_obj;
  461. cb_params.cb_func = __cam_synx_obj_signal_cb;
  462. rc = synx_cancel_async_wait(
  463. g_cam_synx_obj_dev->session_handle,
  464. &cb_params);
  465. if (rc) {
  466. CAM_WARN(CAM_SYNX,
  467. "Registered callback could not be canceled for synx obj : %d",
  468. cb_params.h_synx);
  469. }
  470. }
  471. /* Signal and release the synx obj */
  472. if (row->state != CAM_SYNX_OBJ_STATE_SIGNALED)
  473. synx_signal(g_cam_synx_obj_dev->session_handle,
  474. row->synx_obj, SYNX_STATE_SIGNALED_CANCEL);
  475. synx_release(g_cam_synx_obj_dev->session_handle,
  476. row->synx_obj);
  477. memset(row, 0, sizeof(struct cam_synx_obj_row));
  478. clear_bit(i, g_cam_synx_obj_dev->bitmap);
  479. spin_unlock_bh(&g_cam_synx_obj_dev->row_spinlocks[i]);
  480. }
  481. mutex_unlock(&g_cam_synx_obj_dev->dev_lock);
  482. CAM_DBG(CAM_SYNX, "Close on Camera SYNX driver");
  483. }
  484. int cam_synx_obj_driver_init(void)
  485. {
  486. int i;
  487. g_cam_synx_obj_dev = kzalloc(sizeof(struct cam_synx_obj_device), GFP_KERNEL);
  488. if (!g_cam_synx_obj_dev)
  489. return -ENOMEM;
  490. if (__cam_synx_init_session())
  491. goto deinit_driver;
  492. mutex_init(&g_cam_synx_obj_dev->dev_lock);
  493. for (i = 0; i < CAM_SYNX_MAX_OBJS; i++)
  494. spin_lock_init(&g_cam_synx_obj_dev->row_spinlocks[i]);
  495. memset(&g_cam_synx_obj_dev->rows, 0, sizeof(g_cam_synx_obj_dev->rows));
  496. memset(&g_cam_synx_obj_dev->bitmap, 0, sizeof(g_cam_synx_obj_dev->bitmap));
  497. bitmap_zero(g_cam_synx_obj_dev->bitmap, CAM_SYNX_MAX_OBJS);
  498. CAM_DBG(CAM_SYNX, "Camera synx obj driver initialized");
  499. return 0;
  500. deinit_driver:
  501. CAM_ERR(CAM_SYNX, "Camera synx obj driver initialization failed");
  502. kfree(g_cam_synx_obj_dev);
  503. g_cam_synx_obj_dev = NULL;
  504. return -EINVAL;
  505. }
  506. void cam_synx_obj_driver_deinit(void)
  507. {
  508. int rc;
  509. if (g_cam_synx_obj_dev->session_handle) {
  510. rc = synx_uninitialize(g_cam_synx_obj_dev->session_handle);
  511. if (rc) {
  512. CAM_ERR(CAM_SYNX,
  513. "Synx failed to uninitialize session: %p, rc: %d",
  514. g_cam_synx_obj_dev->session_handle, rc);
  515. }
  516. }
  517. kfree(g_cam_synx_obj_dev);
  518. g_cam_synx_obj_dev = NULL;
  519. CAM_DBG(CAM_SYNX, "Camera synx obj driver deinitialized");
  520. }