qcom_sync_file.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  5. */
  6. #define pr_fmt(fmt) "%s: " fmt, __func__
  7. #include <linux/module.h>
  8. #include <linux/kernel.h>
  9. #include <linux/init.h>
  10. #include <linux/types.h>
  11. #include <linux/cdev.h>
  12. #include <linux/file.h>
  13. #include <linux/fs.h>
  14. #include <linux/uaccess.h>
  15. #include <linux/slab.h>
  16. #include <linux/mutex.h>
  17. #include <linux/dma-fence.h>
  18. #include <linux/dma-fence-array.h>
  19. #include <linux/sync_file.h>
  20. #include <uapi/sync_fence/qcom_sync_file.h>
  21. #include <linux/soc/qcom/qcom_sync_file.h>
  22. #define CLASS_NAME "sync"
  23. #define DRV_NAME "spec_sync"
  24. #define DRV_VERSION 1
  25. #define NAME_LEN 32
  26. #define FENCE_MIN 1
  27. #define FENCE_MAX 32
  28. #if IS_ENABLED(CONFIG_DEBUG_FS)
  29. #define MAX_DEVICE_SUPPORTED 2
  30. #else
  31. #define MAX_DEVICE_SUPPORTED 1
  32. #endif
  33. #define DUMMY_CONTEXT 0xfafadadafafadada
  34. #define DUMMY_SEQNO 0xefa9ce00efa9ce00
  35. struct dummy_spec_fence {
  36. struct dma_fence fence;
  37. spinlock_t lock;
  38. };
  39. struct sync_device {
  40. /* device info */
  41. struct class *dev_class;
  42. dev_t dev_num;
  43. struct device *dev;
  44. struct cdev *cdev;
  45. struct mutex lock;
  46. struct dummy_spec_fence *dummy_fence;
  47. /* device drv data */
  48. atomic_t device_available;
  49. char name[NAME_LEN];
  50. uint32_t version;
  51. struct mutex l_lock;
  52. struct list_head fence_array_list;
  53. wait_queue_head_t wait_queue;
  54. };
  55. struct fence_array_node {
  56. struct dma_fence_array *fence_array;
  57. struct list_head list;
  58. };
  59. /* Speculative Sync Device Driver State */
  60. static struct sync_device sync_dev;
  61. static const char *spec_fence_get_name_dummy(struct dma_fence *fence)
  62. {
  63. return "dummy_fence";
  64. }
  65. static const struct dma_fence_ops dummy_spec_fence_ops = {
  66. .get_driver_name = spec_fence_get_name_dummy,
  67. .get_timeline_name = spec_fence_get_name_dummy,
  68. };
  69. static bool sanitize_fence_array(struct dma_fence_array *fence)
  70. {
  71. struct fence_array_node *node;
  72. int ret = false;
  73. mutex_lock(&sync_dev.l_lock);
  74. list_for_each_entry(node, &sync_dev.fence_array_list, list) {
  75. if (node->fence_array == fence) {
  76. ret = true;
  77. break;
  78. }
  79. }
  80. mutex_unlock(&sync_dev.l_lock);
  81. return ret;
  82. }
  83. static void clear_fence_array_tracker(bool force_clear)
  84. {
  85. struct fence_array_node *node, *temp;
  86. struct dma_fence_array *array;
  87. struct dma_fence *fence;
  88. bool is_signaled;
  89. mutex_lock(&sync_dev.l_lock);
  90. list_for_each_entry_safe(node, temp, &sync_dev.fence_array_list, list) {
  91. array = node->fence_array;
  92. fence = &array->base;
  93. is_signaled = dma_fence_is_signaled(fence);
  94. if (force_clear && !array->fences)
  95. array->num_fences = 0;
  96. pr_debug("force_clear:%d is_signaled:%d pending:%d\n", force_clear, is_signaled,
  97. atomic_read(&array->num_pending));
  98. if (force_clear && !is_signaled && atomic_dec_and_test(&array->num_pending))
  99. dma_fence_signal(fence);
  100. if (force_clear || is_signaled) {
  101. dma_fence_put(fence);
  102. list_del(&node->list);
  103. kfree(node);
  104. }
  105. }
  106. mutex_unlock(&sync_dev.l_lock);
  107. }
  108. static struct sync_device *spec_fence_init_locked(struct sync_device *obj, const char *name)
  109. {
  110. if (atomic_read(&obj->device_available) >= MAX_DEVICE_SUPPORTED) {
  111. pr_err("number of device fds are limited to %d, device opened:%d\n",
  112. MAX_DEVICE_SUPPORTED, atomic_read(&obj->device_available));
  113. return NULL;
  114. } else if (!atomic_read(&obj->device_available)) {
  115. memset(obj->name, 0, NAME_LEN);
  116. strscpy(obj->name, name, sizeof(obj->name));
  117. }
  118. atomic_inc(&obj->device_available);
  119. return obj;
  120. }
  121. static int spec_sync_open(struct inode *inode, struct file *file)
  122. {
  123. char task_comm[TASK_COMM_LEN];
  124. struct sync_device *obj = &sync_dev;
  125. int ret = 0;
  126. if (!inode || !inode->i_cdev || !file) {
  127. pr_err("NULL pointer passed\n");
  128. return -EINVAL;
  129. }
  130. mutex_lock(&sync_dev.lock);
  131. get_task_comm(task_comm, current);
  132. obj = spec_fence_init_locked(obj, task_comm);
  133. if (!obj) {
  134. pr_err("Spec device exists owner:%s caller:%s\n", sync_dev.name, task_comm);
  135. ret = -EEXIST;
  136. goto end;
  137. }
  138. file->private_data = obj;
  139. end:
  140. mutex_unlock(&sync_dev.lock);
  141. return ret;
  142. }
  143. static int spec_sync_release(struct inode *inode, struct file *file)
  144. {
  145. int ret = 0;
  146. struct sync_device *obj = file->private_data;
  147. mutex_lock(&sync_dev.lock);
  148. if (!atomic_read(&obj->device_available)) {
  149. pr_err("no device to release!!\n");
  150. ret = -ENODEV;
  151. goto end;
  152. }
  153. atomic_dec(&obj->device_available);
  154. if (!atomic_read(&obj->device_available))
  155. clear_fence_array_tracker(true);
  156. end:
  157. mutex_unlock(&sync_dev.lock);
  158. return ret;
  159. }
  160. static int spec_sync_ioctl_get_ver(struct sync_device *obj, unsigned long __user arg)
  161. {
  162. uint32_t version = obj->version;
  163. if (copy_to_user((void __user *)arg, &version, sizeof(uint32_t)))
  164. return -EFAULT;
  165. return 0;
  166. }
  167. static int spec_sync_create_array(struct fence_create_data *f)
  168. {
  169. int fd = get_unused_fd_flags(O_CLOEXEC);
  170. struct sync_file *sync_file;
  171. struct dma_fence_array *fence_array;
  172. struct fence_array_node *node;
  173. struct dma_fence **fences;
  174. struct dummy_spec_fence *dummy_fence_p = sync_dev.dummy_fence;
  175. bool signal_any;
  176. int i, ret = 0;
  177. if (fd < 0) {
  178. pr_err("failed to get_unused_fd_flags\n");
  179. return fd;
  180. }
  181. if (f->num_fences < FENCE_MIN || f->num_fences > FENCE_MAX) {
  182. pr_err("invalid arguments num_fences:%d\n", f->num_fences);
  183. ret = -ERANGE;
  184. goto error_args;
  185. }
  186. fences = kmalloc_array(f->num_fences, sizeof(void *), GFP_KERNEL|__GFP_ZERO);
  187. if (!fences) {
  188. ret = -ENOMEM;
  189. goto error_args;
  190. }
  191. for (i = 0; i < f->num_fences; i++) {
  192. fences[i] = &dummy_fence_p->fence;
  193. /*
  194. * Increase dummy-fences refcount here, we must do this since any call to
  195. * fence-array release while dummy-fences are the children of the fence-array
  196. * will decrement the dummy_fence refcount. Therefore, to prevent the release
  197. * of the dummy_fence fences, we must keep an extra refcount for every time that
  198. * the fence-array->release can decrement its children's refcount. the extra
  199. * refcount will be decreased impilictly when dma_fence_put(&fence_array->base)
  200. * called.
  201. */
  202. dma_fence_get(&dummy_fence_p->fence);
  203. }
  204. signal_any = f->flags & SPEC_FENCE_SIGNAL_ALL ? false : true;
  205. fence_array = dma_fence_array_create(f->num_fences, fences,
  206. dma_fence_context_alloc(1), 0, signal_any);
  207. if (!fence_array) {
  208. /* fence-array create failed, remove extra refcounts */
  209. for (i = 0; i < f->num_fences; i++)
  210. dma_fence_put(&dummy_fence_p->fence);
  211. kfree(fences);
  212. ret = -EINVAL;
  213. goto error_args;
  214. }
  215. /* Set the enable signal such that signalling is not done during wait*/
  216. set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence_array->base.flags);
  217. set_bit(SPEC_FENCE_FLAG_FENCE_ARRAY, &fence_array->base.flags);
  218. sync_file = sync_file_create(&fence_array->base);
  219. if (!sync_file) {
  220. pr_err("sync_file_create fail\n");
  221. ret = -EINVAL;
  222. goto err;
  223. }
  224. node = kzalloc((sizeof(struct fence_array_node)), GFP_KERNEL);
  225. if (!node) {
  226. fput(sync_file->file);
  227. ret = -ENOMEM;
  228. goto err;
  229. }
  230. fd_install(fd, sync_file->file);
  231. node->fence_array = fence_array;
  232. mutex_lock(&sync_dev.l_lock);
  233. list_add_tail(&node->list, &sync_dev.fence_array_list);
  234. mutex_unlock(&sync_dev.l_lock);
  235. pr_debug("spec fd:%d num_fences:%u\n", fd, f->num_fences);
  236. return fd;
  237. err:
  238. dma_fence_put(&fence_array->base);
  239. error_args:
  240. put_unused_fd(fd);
  241. return ret;
  242. }
  243. static int spec_sync_ioctl_create_fence(struct sync_device *obj, unsigned long __user arg)
  244. {
  245. struct fence_create_data f;
  246. int fd;
  247. if (copy_from_user(&f, (void __user *)arg, sizeof(f)))
  248. return -EFAULT;
  249. fd = spec_sync_create_array(&f);
  250. if (fd < 0)
  251. return fd;
  252. f.out_bind_fd = fd;
  253. if (copy_to_user((void __user *)arg, &f, sizeof(f)))
  254. return -EFAULT;
  255. return 0;
  256. }
  257. int spec_sync_wait_bind_array(struct dma_fence_array *fence_array, u32 timeout_ms)
  258. {
  259. int ret;
  260. /* Check if fence-array is a speculative fence */
  261. if (!fence_array || !test_bit(SPEC_FENCE_FLAG_FENCE_ARRAY, &fence_array->base.flags)) {
  262. pr_err("invalid fence!\n");
  263. return -EINVAL;
  264. } else if (test_bit(SPEC_FENCE_FLAG_FENCE_ARRAY_BOUND, &fence_array->base.flags)) {
  265. /* This fence-array is already bound, just return success */
  266. return 0;
  267. }
  268. /* Wait for the fence-array bind */
  269. ret = wait_event_timeout(sync_dev.wait_queue,
  270. test_bit(SPEC_FENCE_FLAG_FENCE_ARRAY_BOUND, &fence_array->base.flags),
  271. msecs_to_jiffies(timeout_ms));
  272. if (!ret) {
  273. pr_err("timed out waiting for bind fence-array %d\n", timeout_ms);
  274. ret = -ETIMEDOUT;
  275. } else {
  276. ret = 0;
  277. }
  278. return ret;
  279. }
  280. EXPORT_SYMBOL(spec_sync_wait_bind_array);
  281. static int spec_sync_bind_array(struct fence_bind_data *sync_bind_info)
  282. {
  283. struct dma_fence_array *fence_array;
  284. struct dma_fence *fence = NULL;
  285. struct dma_fence *user_fence = NULL;
  286. int *user_fds, ret = 0, i;
  287. u32 num_fences;
  288. fence = sync_file_get_fence(sync_bind_info->out_bind_fd);
  289. if (!fence) {
  290. pr_err("dma fence failure out_fd:%d\n", sync_bind_info->out_bind_fd);
  291. return -EINVAL;
  292. }
  293. if (dma_fence_is_signaled(fence)) {
  294. pr_err("spec fence is already signaled, out_fd:%d\n",
  295. sync_bind_info->out_bind_fd);
  296. ret = -EINVAL;
  297. goto end;
  298. }
  299. fence_array = container_of(fence, struct dma_fence_array, base);
  300. if (!sanitize_fence_array(fence_array)) {
  301. pr_err("spec fence not found in the registered list out_fd:%d\n",
  302. sync_bind_info->out_bind_fd);
  303. ret = -EINVAL;
  304. goto end;
  305. }
  306. num_fences = fence_array->num_fences;
  307. for (i = 0; i < num_fences; i++) {
  308. if (!(fence_array->fences[i]->context == DUMMY_CONTEXT &&
  309. fence_array->fences[i]->seqno == DUMMY_SEQNO)) {
  310. pr_err("fence array already populated, spec fd:%d status:%d flags:0x%x\n",
  311. sync_bind_info->out_bind_fd, dma_fence_get_status(fence),
  312. fence->flags);
  313. ret = -EINVAL;
  314. goto end;
  315. }
  316. }
  317. user_fds = kzalloc(num_fences * (sizeof(int)), GFP_KERNEL);
  318. if (!user_fds) {
  319. ret = -ENOMEM;
  320. goto end;
  321. }
  322. if (copy_from_user(user_fds, (void __user *)sync_bind_info->fds,
  323. num_fences * sizeof(int))) {
  324. ret = -EFAULT;
  325. goto out;
  326. }
  327. spin_lock(fence->lock);
  328. for (i = 0; i < num_fences; i++) {
  329. user_fence = sync_file_get_fence(user_fds[i]);
  330. if (!user_fence) {
  331. pr_warn("bind fences are invalid !! user_fd:%d out_bind_fd:%d\n",
  332. user_fds[i], sync_bind_info->out_bind_fd);
  333. ret = -EINVAL;
  334. goto bind_invalid;
  335. }
  336. fence_array->fences[i] = user_fence;
  337. /*
  338. * At this point the fence-array fully contains valid fences and no more the
  339. * dummy-fence, therefore, we must release the extra refcount that the
  340. * creation of the speculative fence added to the dummy-fence.
  341. */
  342. dma_fence_put(&sync_dev.dummy_fence->fence);
  343. pr_debug("spec fd:%d i:%d bind fd:%d error:%d\n", sync_bind_info->out_bind_fd,
  344. i, user_fds[i], fence_array->fences[i]->error);
  345. }
  346. clear_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags);
  347. spin_unlock(fence->lock);
  348. dma_fence_enable_sw_signaling(&fence_array->base);
  349. clear_fence_array_tracker(false);
  350. bind_invalid:
  351. set_bit(SPEC_FENCE_FLAG_FENCE_ARRAY_BOUND, &fence_array->base.flags);
  352. wake_up_all(&sync_dev.wait_queue);
  353. if (ret) {
  354. dma_fence_set_error(fence, -EINVAL);
  355. spin_unlock(fence->lock);
  356. dma_fence_signal(fence);
  357. clear_fence_array_tracker(false);
  358. }
  359. out:
  360. kfree(user_fds);
  361. end:
  362. dma_fence_put(fence);
  363. return ret;
  364. }
  365. static int spec_sync_ioctl_bind(struct sync_device *obj, unsigned long __user arg)
  366. {
  367. struct fence_bind_data sync_bind_info;
  368. if (copy_from_user(&sync_bind_info, (void __user *)arg, sizeof(struct fence_bind_data)))
  369. return -EFAULT;
  370. if (sync_bind_info.out_bind_fd < 0) {
  371. pr_err("Invalid out_fd:%d\n", sync_bind_info.out_bind_fd);
  372. return -EINVAL;
  373. }
  374. return spec_sync_bind_array(&sync_bind_info);
  375. }
  376. static long spec_sync_ioctl(struct file *file, unsigned int cmd,
  377. unsigned long arg)
  378. {
  379. struct sync_device *obj = file->private_data;
  380. int ret = 0;
  381. switch (cmd) {
  382. case SPEC_SYNC_IOC_CREATE_FENCE:
  383. ret = spec_sync_ioctl_create_fence(obj, arg);
  384. break;
  385. case SPEC_SYNC_IOC_BIND:
  386. ret = spec_sync_ioctl_bind(obj, arg);
  387. break;
  388. case SPEC_SYNC_IOC_GET_VER:
  389. ret = spec_sync_ioctl_get_ver(obj, arg);
  390. break;
  391. default:
  392. ret = -ENOTTY;
  393. }
  394. return ret;
  395. }
  396. const struct file_operations spec_sync_fops = {
  397. .owner = THIS_MODULE,
  398. .open = spec_sync_open,
  399. .release = spec_sync_release,
  400. .unlocked_ioctl = spec_sync_ioctl,
  401. };
  402. static int spec_sync_register_device(void)
  403. {
  404. struct dummy_spec_fence *dummy_fence_p = NULL;
  405. int ret;
  406. sync_dev.dev_class = class_create(THIS_MODULE, CLASS_NAME);
  407. if (sync_dev.dev_class == NULL) {
  408. pr_err("%s: class_create fail.\n", __func__);
  409. goto res_err;
  410. }
  411. ret = alloc_chrdev_region(&sync_dev.dev_num, 0, 1, DRV_NAME);
  412. if (ret) {
  413. pr_err("%s: alloc_chrdev_region fail.\n", __func__);
  414. goto alloc_chrdev_region_err;
  415. }
  416. sync_dev.dev = device_create(sync_dev.dev_class, NULL,
  417. sync_dev.dev_num,
  418. &sync_dev, DRV_NAME);
  419. if (IS_ERR(sync_dev.dev)) {
  420. pr_err("%s: device_create fail.\n", __func__);
  421. goto device_create_err;
  422. }
  423. sync_dev.cdev = cdev_alloc();
  424. if (sync_dev.cdev == NULL) {
  425. pr_err("%s: cdev_alloc fail.\n", __func__);
  426. goto cdev_alloc_err;
  427. }
  428. cdev_init(sync_dev.cdev, &spec_sync_fops);
  429. sync_dev.cdev->owner = THIS_MODULE;
  430. ret = cdev_add(sync_dev.cdev, sync_dev.dev_num, 1);
  431. if (ret) {
  432. pr_err("%s: cdev_add fail.\n", __func__);
  433. goto cdev_add_err;
  434. }
  435. sync_dev.version = DRV_VERSION;
  436. mutex_init(&sync_dev.lock);
  437. mutex_init(&sync_dev.l_lock);
  438. INIT_LIST_HEAD(&sync_dev.fence_array_list);
  439. init_waitqueue_head(&sync_dev.wait_queue);
  440. dummy_fence_p = kzalloc(sizeof(struct dummy_spec_fence), GFP_KERNEL);
  441. if (!dummy_fence_p) {
  442. ret = -ENOMEM;
  443. goto cdev_add_err;
  444. }
  445. spin_lock_init(&dummy_fence_p->lock);
  446. dma_fence_init(&dummy_fence_p->fence, &dummy_spec_fence_ops, &dummy_fence_p->lock,
  447. DUMMY_CONTEXT, DUMMY_SEQNO);
  448. sync_dev.dummy_fence = dummy_fence_p;
  449. return 0;
  450. cdev_add_err:
  451. cdev_del(sync_dev.cdev);
  452. cdev_alloc_err:
  453. device_destroy(sync_dev.dev_class, sync_dev.dev_num);
  454. device_create_err:
  455. unregister_chrdev_region(sync_dev.dev_num, 1);
  456. alloc_chrdev_region_err:
  457. class_destroy(sync_dev.dev_class);
  458. res_err:
  459. return -ENODEV;
  460. }
  461. static int __init spec_sync_init(void)
  462. {
  463. int ret = 0;
  464. ret = spec_sync_register_device();
  465. if (ret) {
  466. pr_err("%s: speculative sync driver register fail.\n", __func__);
  467. return ret;
  468. }
  469. return ret;
  470. }
  471. static void __exit spec_sync_deinit(void)
  472. {
  473. cdev_del(sync_dev.cdev);
  474. device_destroy(sync_dev.dev_class, sync_dev.dev_num);
  475. unregister_chrdev_region(sync_dev.dev_num, 1);
  476. class_destroy(sync_dev.dev_class);
  477. dma_fence_put(&sync_dev.dummy_fence->fence);
  478. }
  479. module_init(spec_sync_init);
  480. module_exit(spec_sync_deinit);
  481. MODULE_DESCRIPTION("QCOM Speculative Sync Driver");
  482. MODULE_LICENSE("GPL v2");