msm_audio_ion.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/init.h>
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <linux/err.h>
  10. #include <linux/delay.h>
  11. #include <linux/slab.h>
  12. #include <linux/mutex.h>
  13. #include <linux/list.h>
  14. #include <linux/dma-mapping.h>
  15. #include <linux/dma-buf.h>
  16. #include <linux/iosys-map.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/of_device.h>
  19. #include <linux/export.h>
  20. #include <linux/ioctl.h>
  21. #include <linux/compat.h>
  22. #include <linux/cdev.h>
  23. #include <linux/fs.h>
  24. #include <linux/device.h>
  25. #ifndef CONFIG_SPF_CORE
  26. #include <ipc/apr.h>
  27. #endif
  28. #include <dsp/msm_audio_ion.h>
  29. #include <linux/msm_audio.h>
  30. #include <linux/qcom_scm.h>
  31. #include <soc/qcom/secure_buffer.h>
  32. MODULE_IMPORT_NS(DMA_BUF);
  33. #define MSM_AUDIO_ION_PROBED (1 << 0)
  34. #define MSM_AUDIO_ION_PHYS_ADDR(alloc_data) \
  35. alloc_data->table->sgl->dma_address
  36. #define MSM_AUDIO_SMMU_SID_OFFSET 32
  37. #define TZ_PIL_PROTECT_MEM_SUBSYS_ID 0x0C
  38. #define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D
  39. #define MSM_AUDIO_ION_DRIVER_NAME "msm_audio_ion"
  40. #define MINOR_NUMBER_COUNT 1
  41. struct msm_audio_ion_private {
  42. bool smmu_enabled;
  43. struct device *cb_dev;
  44. u8 device_status;
  45. struct list_head alloc_list;
  46. struct mutex list_mutex;
  47. u64 smmu_sid_bits;
  48. u32 smmu_version;
  49. bool is_non_hypervisor;
  50. char *driver_name;
  51. /*char dev related data */
  52. dev_t ion_major;
  53. struct class *ion_class;
  54. struct device *chardev;
  55. struct cdev cdev;
  56. };
  57. struct msm_audio_alloc_data {
  58. size_t len;
  59. struct iosys_map *vmap;
  60. struct dma_buf *dma_buf;
  61. struct dma_buf_attachment *attach;
  62. struct sg_table *table;
  63. struct list_head list;
  64. };
  65. struct msm_audio_ion_fd_list_private {
  66. struct mutex list_mutex;
  67. /*list to store fd, phy. addr and handle data */
  68. struct list_head fd_list;
  69. };
  70. static struct msm_audio_ion_fd_list_private msm_audio_ion_fd_list = {0,};
  71. static bool msm_audio_ion_fd_list_init = false;
  72. struct msm_audio_fd_data {
  73. int fd;
  74. size_t plen;
  75. void *handle;
  76. dma_addr_t paddr;
  77. struct device *dev;
  78. struct list_head list;
  79. bool hyp_assign;
  80. };
  81. static void msm_audio_ion_add_allocation(
  82. struct msm_audio_ion_private *msm_audio_ion_data,
  83. struct msm_audio_alloc_data *alloc_data)
  84. {
  85. /*
  86. * Since these APIs can be invoked by multiple
  87. * clients, there is need to make sure the list
  88. * of allocations is always protected
  89. */
  90. mutex_lock(&(msm_audio_ion_data->list_mutex));
  91. list_add_tail(&(alloc_data->list),
  92. &(msm_audio_ion_data->alloc_list));
  93. mutex_unlock(&(msm_audio_ion_data->list_mutex));
  94. }
  95. /* This function is called with ion_data list mutex lock */
  96. static int msm_audio_ion_map_kernel(struct dma_buf *dma_buf,
  97. struct msm_audio_ion_private *ion_data, struct iosys_map *iosys_vmap)
  98. {
  99. int rc = 0;
  100. struct msm_audio_alloc_data *alloc_data = NULL;
  101. rc = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
  102. if (rc) {
  103. pr_err("%s: kmap dma_buf_begin_cpu_access fail\n", __func__);
  104. goto exit;
  105. }
  106. rc = dma_buf_vmap(dma_buf, iosys_vmap);
  107. if (rc) {
  108. pr_err("%s: kernel mapping of dma_buf failed\n",
  109. __func__);
  110. dma_buf_end_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
  111. goto exit;
  112. }
  113. /*
  114. * TBD: remove the below section once new API
  115. * for mapping kernel virtual address is available.
  116. */
  117. mutex_lock(&(ion_data->list_mutex));
  118. list_for_each_entry(alloc_data, &(ion_data->alloc_list),
  119. list) {
  120. if (alloc_data->dma_buf == dma_buf) {
  121. alloc_data->vmap = iosys_vmap;
  122. break;
  123. }
  124. }
  125. mutex_unlock(&(ion_data->list_mutex));
  126. exit:
  127. return rc;
  128. }
  129. /* This function is called with ion_data list mutex lock */
  130. static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
  131. dma_addr_t *addr, size_t *len, bool is_iova,
  132. struct msm_audio_ion_private *ion_data)
  133. {
  134. struct msm_audio_alloc_data *alloc_data = NULL;
  135. int rc = 0;
  136. struct iosys_map *iosys_vmap = NULL;
  137. struct device *cb_dev = ion_data->cb_dev;
  138. iosys_vmap = kzalloc(sizeof(*iosys_vmap), GFP_KERNEL);
  139. if (!iosys_vmap)
  140. return -ENOMEM;
  141. /* Data required per buffer mapping */
  142. alloc_data = kzalloc(sizeof(*alloc_data), GFP_KERNEL);
  143. if (!alloc_data) {
  144. kfree(iosys_vmap);
  145. return -ENOMEM;
  146. }
  147. alloc_data->dma_buf = dma_buf;
  148. alloc_data->len = dma_buf->size;
  149. *len = dma_buf->size;
  150. /* Attach the dma_buf to context bank device */
  151. alloc_data->attach = dma_buf_attach(alloc_data->dma_buf,
  152. cb_dev);
  153. if (IS_ERR(alloc_data->attach)) {
  154. rc = PTR_ERR(alloc_data->attach);
  155. dev_err(cb_dev,
  156. "%s: Fail to attach dma_buf to CB, rc = %d\n",
  157. __func__, rc);
  158. goto free_alloc_data;
  159. }
  160. /*
  161. * Get the scatter-gather list.
  162. * There is no info as this is a write buffer or
  163. * read buffer, hence the request is bi-directional
  164. * to accommodate both read and write mappings.
  165. */
  166. alloc_data->table = dma_buf_map_attachment(alloc_data->attach,
  167. DMA_BIDIRECTIONAL);
  168. if (IS_ERR(alloc_data->table)) {
  169. rc = PTR_ERR(alloc_data->table);
  170. dev_err(cb_dev,
  171. "%s: Fail to map attachment, rc = %d\n",
  172. __func__, rc);
  173. goto detach_dma_buf;
  174. }
  175. /* physical address from mapping */
  176. if (!is_iova) {
  177. *addr = sg_phys(alloc_data->table->sgl);
  178. rc = msm_audio_ion_map_kernel((void *)dma_buf, ion_data, iosys_vmap);
  179. if (rc) {
  180. pr_err("%s: ION memory mapping for AUDIO failed, err:%d\n",
  181. __func__, rc);
  182. rc = -ENOMEM;
  183. goto detach_dma_buf;
  184. }
  185. alloc_data->vmap = iosys_vmap;
  186. } else {
  187. *addr = MSM_AUDIO_ION_PHYS_ADDR(alloc_data);
  188. kfree(iosys_vmap);
  189. }
  190. msm_audio_ion_add_allocation(ion_data, alloc_data);
  191. return rc;
  192. detach_dma_buf:
  193. dma_buf_detach(alloc_data->dma_buf,
  194. alloc_data->attach);
  195. free_alloc_data:
  196. kfree(iosys_vmap);
  197. kfree(alloc_data);
  198. alloc_data = NULL;
  199. return rc;
  200. }
  201. static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf, struct msm_audio_ion_private *ion_data)
  202. {
  203. int rc = 0;
  204. struct msm_audio_alloc_data *alloc_data = NULL;
  205. struct list_head *ptr, *next;
  206. bool found = false;
  207. struct device *cb_dev = ion_data->cb_dev;
  208. /*
  209. * Though list_for_each_safe is delete safe, lock
  210. * should be explicitly acquired to avoid race condition
  211. * on adding elements to the list.
  212. */
  213. list_for_each_safe(ptr, next,
  214. &(ion_data->alloc_list)) {
  215. alloc_data = list_entry(ptr, struct msm_audio_alloc_data,
  216. list);
  217. if (alloc_data->dma_buf == dma_buf) {
  218. found = true;
  219. dma_buf_unmap_attachment(alloc_data->attach,
  220. alloc_data->table,
  221. DMA_BIDIRECTIONAL);
  222. dma_buf_detach(alloc_data->dma_buf,
  223. alloc_data->attach);
  224. dma_buf_put(alloc_data->dma_buf);
  225. list_del(&(alloc_data->list));
  226. kfree(alloc_data->vmap);
  227. kfree(alloc_data);
  228. alloc_data = NULL;
  229. break;
  230. }
  231. }
  232. if (!found) {
  233. dev_err(cb_dev,
  234. "%s: cannot find allocation, dma_buf %pK",
  235. __func__, dma_buf);
  236. rc = -EINVAL;
  237. }
  238. return rc;
  239. }
  240. static int msm_audio_ion_get_phys(struct dma_buf *dma_buf,
  241. dma_addr_t *addr, size_t *len, bool is_iova,
  242. struct msm_audio_ion_private *ion_data)
  243. {
  244. int rc = 0;
  245. rc = msm_audio_dma_buf_map(dma_buf, addr, len, is_iova, ion_data);
  246. if (rc) {
  247. pr_err("%s: failed to map DMA buf, err = %d\n",
  248. __func__, rc);
  249. goto err;
  250. }
  251. if (ion_data->smmu_enabled && is_iova) {
  252. /* Append the SMMU SID information to the IOVA address */
  253. *addr |= ion_data->smmu_sid_bits;
  254. }
  255. pr_debug("phys=%pK, len=%zd, rc=%d\n", &(*addr), *len, rc);
  256. err:
  257. return rc;
  258. }
  259. static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf, struct msm_audio_ion_private *ion_data)
  260. {
  261. int rc = 0;
  262. struct iosys_map *iosys_vmap = NULL;
  263. struct msm_audio_alloc_data *alloc_data = NULL;
  264. struct device *cb_dev = ion_data->cb_dev;
  265. /*
  266. * TBD: remove the below section once new API
  267. * for unmapping kernel virtual address is available.
  268. */
  269. list_for_each_entry(alloc_data, &(ion_data->alloc_list),
  270. list) {
  271. if (alloc_data->dma_buf == dma_buf) {
  272. iosys_vmap = alloc_data->vmap;
  273. break;
  274. }
  275. }
  276. if (!iosys_vmap) {
  277. dev_err(cb_dev,
  278. "%s: cannot find allocation for dma_buf %pK",
  279. __func__, dma_buf);
  280. rc = -EINVAL;
  281. goto err;
  282. }
  283. dma_buf_vunmap(dma_buf, iosys_vmap);
  284. rc = dma_buf_end_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
  285. if (rc) {
  286. dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n",
  287. __func__);
  288. goto err;
  289. }
  290. err:
  291. return rc;
  292. }
  293. /* This function is called with ion_data list mutex lock */
  294. static int msm_audio_ion_buf_map(struct dma_buf *dma_buf, dma_addr_t *paddr,
  295. size_t *plen, struct iosys_map *iosys_vmap,
  296. struct msm_audio_ion_private *ion_data)
  297. {
  298. int rc = 0;
  299. bool is_iova = true;
  300. if (!dma_buf || !paddr || !plen) {
  301. pr_err("%s: Invalid params\n", __func__);
  302. return -EINVAL;
  303. }
  304. rc = msm_audio_ion_get_phys(dma_buf, paddr, plen, is_iova, ion_data);
  305. if (rc) {
  306. pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
  307. __func__, rc);
  308. dma_buf_put(dma_buf);
  309. goto err;
  310. }
  311. rc = msm_audio_ion_map_kernel(dma_buf, ion_data, iosys_vmap);
  312. if (rc) {
  313. pr_err("%s: ION memory mapping for AUDIO failed, err:%d\n",
  314. __func__, rc);
  315. rc = -ENOMEM;
  316. mutex_lock(&(ion_data->list_mutex));
  317. msm_audio_dma_buf_unmap(dma_buf, ion_data);
  318. mutex_unlock(&(ion_data->list_mutex));
  319. goto err;
  320. }
  321. err:
  322. return rc;
  323. }
  324. void msm_audio_fd_list_debug(void)
  325. {
  326. struct msm_audio_fd_data *msm_audio_fd_data = NULL;
  327. list_for_each_entry(msm_audio_fd_data,
  328. &msm_audio_ion_fd_list.fd_list, list) {
  329. pr_debug("%s fd %d handle %pK phy. addr %pK\n", __func__,
  330. msm_audio_fd_data->fd, msm_audio_fd_data->handle,
  331. (void *)msm_audio_fd_data->paddr);
  332. }
  333. }
  334. void msm_audio_update_fd_list(struct msm_audio_fd_data *msm_audio_fd_data)
  335. {
  336. struct msm_audio_fd_data *msm_audio_fd_data1 = NULL;
  337. mutex_lock(&(msm_audio_ion_fd_list.list_mutex));
  338. list_for_each_entry(msm_audio_fd_data1,
  339. &msm_audio_ion_fd_list.fd_list, list) {
  340. if (msm_audio_fd_data1->fd == msm_audio_fd_data->fd) {
  341. pr_err("%s fd already present, not updating the list",
  342. __func__);
  343. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  344. return;
  345. }
  346. }
  347. list_add_tail(&msm_audio_fd_data->list, &msm_audio_ion_fd_list.fd_list);
  348. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  349. }
  350. void msm_audio_delete_fd_entry(void *handle)
  351. {
  352. struct msm_audio_fd_data *msm_audio_fd_data = NULL;
  353. struct list_head *ptr, *next;
  354. if (!handle) {
  355. pr_err("%s Invalid handle\n", __func__);
  356. return;
  357. }
  358. mutex_lock(&(msm_audio_ion_fd_list.list_mutex));
  359. list_for_each_safe(ptr, next,
  360. &msm_audio_ion_fd_list.fd_list) {
  361. msm_audio_fd_data = list_entry(ptr, struct msm_audio_fd_data,
  362. list);
  363. if (msm_audio_fd_data->handle == handle) {
  364. pr_debug("%s deleting handle %pK entry from list\n",
  365. __func__, handle);
  366. list_del(&(msm_audio_fd_data->list));
  367. kfree(msm_audio_fd_data);
  368. break;
  369. }
  370. }
  371. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  372. }
  373. int msm_audio_get_phy_addr(int fd, dma_addr_t *paddr, size_t *pa_len)
  374. {
  375. struct msm_audio_fd_data *msm_audio_fd_data = NULL;
  376. int status = -EINVAL;
  377. if (!paddr) {
  378. pr_err("%s Invalid paddr param status %d\n", __func__, status);
  379. return status;
  380. }
  381. pr_debug("%s, fd %d\n", __func__, fd);
  382. mutex_lock(&(msm_audio_ion_fd_list.list_mutex));
  383. list_for_each_entry(msm_audio_fd_data,
  384. &msm_audio_ion_fd_list.fd_list, list) {
  385. if (msm_audio_fd_data->fd == fd) {
  386. *paddr = msm_audio_fd_data->paddr;
  387. *pa_len = msm_audio_fd_data->plen;
  388. status = 0;
  389. pr_debug("%s Found fd %d paddr %pK\n",
  390. __func__, fd, paddr);
  391. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  392. return status;
  393. }
  394. }
  395. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  396. return status;
  397. }
  398. EXPORT_SYMBOL(msm_audio_get_phy_addr);
  399. static int msm_audio_set_hyp_assign(int fd, bool assign)
  400. {
  401. struct msm_audio_fd_data *msm_audio_fd_data = NULL;
  402. int status = -EINVAL;
  403. pr_debug("%s, fd %d\n", __func__, fd);
  404. mutex_lock(&(msm_audio_ion_fd_list.list_mutex));
  405. list_for_each_entry(msm_audio_fd_data,
  406. &msm_audio_ion_fd_list.fd_list, list) {
  407. if (msm_audio_fd_data->fd == fd) {
  408. status = 0;
  409. pr_debug("%s Found fd %d\n", __func__, fd);
  410. msm_audio_fd_data->hyp_assign = assign;
  411. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  412. return status;
  413. }
  414. }
  415. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  416. return status;
  417. }
  418. void msm_audio_get_handle(int fd, void **handle)
  419. {
  420. struct msm_audio_fd_data *msm_audio_fd_data = NULL;
  421. pr_debug("%s fd %d\n", __func__, fd);
  422. mutex_lock(&(msm_audio_ion_fd_list.list_mutex));
  423. *handle = NULL;
  424. list_for_each_entry(msm_audio_fd_data,
  425. &msm_audio_ion_fd_list.fd_list, list) {
  426. if (msm_audio_fd_data->fd == fd) {
  427. *handle = (struct dma_buf *)msm_audio_fd_data->handle;
  428. pr_debug("%s handle %pK\n", __func__, *handle);
  429. break;
  430. }
  431. }
  432. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  433. }
  434. /**
  435. * msm_audio_ion_import-
  436. * Import ION buffer with given file descriptor
  437. *
  438. * @dma_buf: dma_buf for the ION memory
  439. * @fd: file descriptor for the ION memory
  440. * @ionflag: flags associated with ION buffer
  441. * @bufsz: buffer size
  442. * @paddr: Physical address to be assigned with allocated region
  443. * @plen: length of allocated region to be assigned
  444. * @iosys_vmap: Virtual mapping vmap pointer to be assigned
  445. *
  446. * Returns 0 on success or error on failure
  447. */
  448. static int msm_audio_ion_import(struct dma_buf **dma_buf, int fd,
  449. unsigned long *ionflag, size_t bufsz,
  450. dma_addr_t *paddr, size_t *plen, struct iosys_map *iosys_vmap,
  451. struct msm_audio_ion_private *ion_data)
  452. {
  453. int rc = 0;
  454. if (!(ion_data->device_status & MSM_AUDIO_ION_PROBED)) {
  455. pr_debug("%s: probe is not done, deferred\n", __func__);
  456. return -EPROBE_DEFER;
  457. }
  458. if (!dma_buf || !paddr || !plen) {
  459. pr_err("%s: Invalid params\n", __func__);
  460. return -EINVAL;
  461. }
  462. /* bufsz should be 0 and fd shouldn't be 0 as of now */
  463. *dma_buf = dma_buf_get(fd);
  464. pr_debug("%s: dma_buf =%pK, fd=%d\n", __func__, *dma_buf, fd);
  465. if (IS_ERR_OR_NULL((void *)(*dma_buf))) {
  466. pr_err("%s: dma_buf_get failed\n", __func__);
  467. rc = -EINVAL;
  468. goto err;
  469. }
  470. if (ionflag != NULL) {
  471. rc = dma_buf_get_flags(*dma_buf, ionflag);
  472. if (rc) {
  473. pr_err("%s: could not get flags for the dma_buf\n",
  474. __func__);
  475. goto err_ion_flag;
  476. }
  477. }
  478. if (ion_data->smmu_enabled) {
  479. rc = msm_audio_ion_buf_map(*dma_buf, paddr, plen, iosys_vmap, ion_data);
  480. if (rc) {
  481. pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
  482. goto err;
  483. }
  484. pr_debug("%s: mapped address = %pK, size=%zd\n", __func__,
  485. iosys_vmap->vaddr, bufsz);
  486. } else {
  487. msm_audio_dma_buf_map(*dma_buf, paddr, plen, true, ion_data);
  488. }
  489. return 0;
  490. err_ion_flag:
  491. dma_buf_put(*dma_buf);
  492. err:
  493. *dma_buf = NULL;
  494. return rc;
  495. }
  496. /**
  497. * msm_audio_ion_free -
  498. * fress ION memory for given client and handle
  499. *
  500. * @dma_buf: dma_buf for the ION memory
  501. *
  502. * Returns 0 on success or error on failure
  503. */
  504. /* This funtion is called with ion_data list mutex lock */
  505. static int msm_audio_ion_free(struct dma_buf *dma_buf, struct msm_audio_ion_private *ion_data)
  506. {
  507. int ret = 0;
  508. if (!dma_buf) {
  509. pr_err("%s: dma_buf invalid\n", __func__);
  510. return -EINVAL;
  511. }
  512. mutex_lock(&(ion_data->list_mutex));
  513. if (ion_data->smmu_enabled) {
  514. ret = msm_audio_ion_unmap_kernel(dma_buf, ion_data);
  515. if (ret) {
  516. mutex_unlock(&(ion_data->list_mutex));
  517. return ret;
  518. }
  519. }
  520. msm_audio_dma_buf_unmap(dma_buf, ion_data);
  521. mutex_unlock(&(ion_data->list_mutex));
  522. return 0;
  523. }
  524. static int msm_audio_hyp_unassign(struct msm_audio_fd_data *msm_audio_fd_data)
  525. {
  526. int ret = 0;
  527. u64 src_vmid_unmap_list = BIT(VMID_LPASS) | BIT(VMID_ADSP_HEAP);
  528. struct qcom_scm_vmperm dst_vmids_unmap[] = {{QCOM_SCM_VMID_HLOS,
  529. PERM_READ | PERM_WRITE | PERM_EXEC}};
  530. if (msm_audio_fd_data->hyp_assign) {
  531. ret = qcom_scm_assign_mem(msm_audio_fd_data->paddr, msm_audio_fd_data->plen,
  532. &src_vmid_unmap_list, dst_vmids_unmap, ARRAY_SIZE(dst_vmids_unmap));
  533. if (ret < 0) {
  534. pr_err("%s: qcom assign unmap failed result = %d addr = 0x%pK size = %d\n",
  535. __func__, ret, msm_audio_fd_data->paddr, msm_audio_fd_data->plen);
  536. }
  537. msm_audio_fd_data->hyp_assign = false;
  538. pr_debug("%s: qcom scm unmap success\n", __func__);
  539. }
  540. return ret;
  541. }
  542. /**
  543. * msm_audio_ion_crash_handler -
  544. * handles cleanup after userspace crashes.
  545. *
  546. * To be called from machine driver.
  547. */
  548. void msm_audio_ion_crash_handler(void)
  549. {
  550. struct msm_audio_fd_data *msm_audio_fd_data = NULL;
  551. struct list_head *ptr, *next;
  552. void *handle = NULL;
  553. struct msm_audio_ion_private *ion_data = NULL;
  554. pr_debug("Inside %s\n", __func__);
  555. if(!msm_audio_ion_fd_list_init) {
  556. pr_err("%s: list not initialized yet, hence returning .... ", __func__);
  557. return;
  558. }
  559. mutex_lock(&(msm_audio_ion_fd_list.list_mutex));
  560. list_for_each_entry(msm_audio_fd_data,
  561. &msm_audio_ion_fd_list.fd_list, list) {
  562. if(msm_audio_fd_data) {
  563. handle = msm_audio_fd_data->handle;
  564. ion_data = dev_get_drvdata(msm_audio_fd_data->dev);
  565. /* clean if CMA was used*/
  566. if (msm_audio_fd_data->hyp_assign)
  567. msm_audio_hyp_unassign(msm_audio_fd_data);
  568. if(handle)
  569. msm_audio_ion_free(handle, ion_data);
  570. }
  571. }
  572. list_for_each_safe(ptr, next,
  573. &msm_audio_ion_fd_list.fd_list) {
  574. if(ptr) {
  575. msm_audio_fd_data = list_entry(ptr, struct msm_audio_fd_data,
  576. list);
  577. if(msm_audio_fd_data) {
  578. list_del(&(msm_audio_fd_data->list));
  579. kfree(msm_audio_fd_data);
  580. }
  581. }
  582. }
  583. mutex_unlock(&(msm_audio_ion_fd_list.list_mutex));
  584. }
  585. EXPORT_SYMBOL(msm_audio_ion_crash_handler);
  586. static int msm_audio_ion_open(struct inode *inode, struct file *file)
  587. {
  588. int ret = 0;
  589. struct msm_audio_ion_private *ion_data = container_of(inode->i_cdev,
  590. struct msm_audio_ion_private,
  591. cdev);
  592. struct device *dev = ion_data->chardev;
  593. pr_debug("Inside %s\n", __func__);
  594. get_device(dev);
  595. return ret;
  596. }
  597. static int msm_audio_ion_release(struct inode *inode, struct file *file)
  598. {
  599. struct msm_audio_ion_private *ion_data = container_of(inode->i_cdev,
  600. struct msm_audio_ion_private,
  601. cdev);
  602. struct device *dev = ion_data->chardev;
  603. pr_debug("Inside %s\n", __func__);
  604. put_device(dev);
  605. return 0;
  606. }
  607. static long msm_audio_ion_ioctl(struct file *file, unsigned int ioctl_num,
  608. unsigned long __user ioctl_param)
  609. {
  610. void *mem_handle;
  611. dma_addr_t paddr;
  612. size_t pa_len = 0;
  613. struct iosys_map *iosys_vmap = NULL;
  614. int ret = 0;
  615. u64 src_vmid_map_list = BIT(QCOM_SCM_VMID_HLOS);
  616. struct qcom_scm_vmperm dst_vmids_map[] = {{VMID_LPASS, PERM_READ | PERM_WRITE},
  617. {VMID_ADSP_HEAP, PERM_READ | PERM_WRITE}};
  618. u64 src_vmid_unmap_list = BIT(VMID_LPASS) | BIT(VMID_ADSP_HEAP);
  619. struct qcom_scm_vmperm dst_vmids_unmap[] = {{QCOM_SCM_VMID_HLOS,
  620. PERM_READ | PERM_WRITE | PERM_EXEC}};
  621. struct msm_audio_fd_data *msm_audio_fd_data = NULL;
  622. struct msm_audio_ion_private *ion_data =
  623. container_of(file->f_inode->i_cdev, struct msm_audio_ion_private, cdev);
  624. pr_debug("%s ioctl num %u\n", __func__, ioctl_num);
  625. switch (ioctl_num) {
  626. case IOCTL_MAP_PHYS_ADDR:
  627. iosys_vmap = kzalloc(sizeof(struct msm_audio_fd_data), GFP_KERNEL);
  628. if (!iosys_vmap)
  629. return -ENOMEM;
  630. msm_audio_fd_data = kzalloc((sizeof(struct msm_audio_fd_data)),
  631. GFP_KERNEL);
  632. if (!msm_audio_fd_data) {
  633. kfree(iosys_vmap);
  634. return -ENOMEM;
  635. }
  636. ret = msm_audio_ion_import((struct dma_buf **)&mem_handle, (int)ioctl_param,
  637. NULL, 0, &paddr, &pa_len, iosys_vmap, ion_data);
  638. if (ret < 0) {
  639. pr_err("%s Memory map Failed %d\n", __func__, ret);
  640. kfree(iosys_vmap);
  641. kfree(msm_audio_fd_data);
  642. return ret;
  643. }
  644. msm_audio_fd_data->fd = (int)ioctl_param;
  645. msm_audio_fd_data->handle = mem_handle;
  646. msm_audio_fd_data->paddr = paddr;
  647. msm_audio_fd_data->plen = pa_len;
  648. msm_audio_fd_data->dev = ion_data->cb_dev;
  649. msm_audio_update_fd_list(msm_audio_fd_data);
  650. break;
  651. case IOCTL_UNMAP_PHYS_ADDR:
  652. msm_audio_get_handle((int)ioctl_param, &mem_handle);
  653. ret = msm_audio_ion_free(mem_handle, ion_data);
  654. if (ret < 0) {
  655. pr_err("%s Ion free failed %d\n", __func__, ret);
  656. return ret;
  657. }
  658. msm_audio_delete_fd_entry(mem_handle);
  659. break;
  660. case IOCTL_MAP_HYP_ASSIGN:
  661. ret = msm_audio_get_phy_addr((int)ioctl_param, &paddr, &pa_len);
  662. if (ret < 0) {
  663. pr_err("%s get phys addr failed %d\n", __func__, ret);
  664. return ret;
  665. }
  666. ret = qcom_scm_assign_mem(paddr, pa_len, &src_vmid_map_list,
  667. dst_vmids_map, ARRAY_SIZE(dst_vmids_map));
  668. if (ret < 0) {
  669. pr_err("%s: qcom_assign failed result = %d addr = 0x%pK size = %d\n",
  670. __func__, ret, paddr, pa_len);
  671. return ret;
  672. }
  673. pr_debug("%s: qcom scm assign success\n", __func__);
  674. msm_audio_set_hyp_assign((int)ioctl_param, true);
  675. break;
  676. case IOCTL_UNMAP_HYP_ASSIGN:
  677. ret = msm_audio_get_phy_addr((int)ioctl_param, &paddr, &pa_len);
  678. if (ret < 0) {
  679. pr_err("%s get phys addr failed %d\n", __func__, ret);
  680. return ret;
  681. }
  682. ret = qcom_scm_assign_mem(paddr, pa_len, &src_vmid_unmap_list,
  683. dst_vmids_unmap, ARRAY_SIZE(dst_vmids_unmap));
  684. if (ret < 0) {
  685. pr_err("%s: qcom scm unassign failed result = %d addr = 0x%pK size = %d\n",
  686. __func__, ret, paddr, pa_len);
  687. return ret;
  688. }
  689. pr_debug("%s: qcom scm unassign success\n", __func__);
  690. msm_audio_set_hyp_assign((int)ioctl_param, false);
  691. break;
  692. default:
  693. pr_err("%s Entered default. Invalid ioctl num %u",
  694. __func__, ioctl_num);
  695. ret = -EINVAL;
  696. break;
  697. }
  698. return ret;
  699. }
  700. /* support of 32bit userspace on 64bit platforms */
  701. #ifdef CONFIG_COMPAT
  702. static long msm_audio_ion_ioctl_compat(struct file *file, unsigned int cmd,
  703. unsigned long arg)
  704. {
  705. return msm_audio_ion_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
  706. }
  707. #endif
  708. static const struct of_device_id msm_audio_ion_dt_match[] = {
  709. { .compatible = "qcom,msm-audio-ion" },
  710. { .compatible = "qcom,msm-audio-ion-cma"},
  711. { }
  712. };
  713. MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
  714. static const struct file_operations msm_audio_ion_fops = {
  715. .owner = THIS_MODULE,
  716. .open = msm_audio_ion_open,
  717. .release = msm_audio_ion_release,
  718. .unlocked_ioctl = msm_audio_ion_ioctl,
  719. #ifdef CONFIG_COMPAT
  720. .compat_ioctl = msm_audio_ion_ioctl_compat,
  721. #endif
  722. };
  723. static int msm_audio_ion_reg_chrdev(struct msm_audio_ion_private *ion_data)
  724. {
  725. int ret = 0;
  726. ret = alloc_chrdev_region(&ion_data->ion_major, 0,
  727. MINOR_NUMBER_COUNT, ion_data->driver_name);
  728. if (ret < 0) {
  729. pr_err("%s alloc_chr_dev_region failed ret : %d\n",
  730. __func__, ret);
  731. return ret;
  732. }
  733. pr_debug("%s major number %d", __func__, MAJOR(ion_data->ion_major));
  734. ion_data->ion_class = class_create(THIS_MODULE,
  735. ion_data->driver_name);
  736. if (IS_ERR(ion_data->ion_class)) {
  737. ret = PTR_ERR(ion_data->ion_class);
  738. pr_err("%s class create failed. ret : %d", __func__, ret);
  739. goto err_class;
  740. }
  741. ion_data->chardev = device_create(ion_data->ion_class, NULL,
  742. ion_data->ion_major, NULL,
  743. ion_data->driver_name);
  744. if (IS_ERR(ion_data->chardev)) {
  745. ret = PTR_ERR(ion_data->chardev);
  746. pr_err("%s device create failed ret : %d\n", __func__, ret);
  747. goto err_device;
  748. }
  749. cdev_init(&ion_data->cdev, &msm_audio_ion_fops);
  750. ret = cdev_add(&ion_data->cdev, ion_data->ion_major, 1);
  751. if (ret) {
  752. pr_err("%s cdev add failed, ret : %d\n", __func__, ret);
  753. goto err_cdev;
  754. }
  755. return ret;
  756. err_cdev:
  757. device_destroy(ion_data->ion_class, ion_data->ion_major);
  758. err_device:
  759. class_destroy(ion_data->ion_class);
  760. err_class:
  761. unregister_chrdev_region(0, MINOR_NUMBER_COUNT);
  762. return ret;
  763. }
  764. static int msm_audio_ion_unreg_chrdev(struct msm_audio_ion_private *ion_data)
  765. {
  766. cdev_del(&ion_data->cdev);
  767. device_destroy(ion_data->ion_class, ion_data->ion_major);
  768. class_destroy(ion_data->ion_class);
  769. unregister_chrdev_region(0, MINOR_NUMBER_COUNT);
  770. return 0;
  771. }
  772. static int msm_audio_ion_probe(struct platform_device *pdev)
  773. {
  774. int rc = 0;
  775. u64 smmu_sid = 0;
  776. u64 smmu_sid_mask = 0;
  777. const char *msm_audio_ion_dt = "qcom,smmu-enabled";
  778. const char *msm_audio_ion_non_hyp = "qcom,non-hyp-assign";
  779. const char *msm_audio_ion_smmu = "qcom,smmu-version";
  780. const char *msm_audio_ion_smmu_sid_mask = "qcom,smmu-sid-mask";
  781. bool smmu_enabled;
  782. bool is_non_hypervisor_en;
  783. struct device *dev = &pdev->dev;
  784. struct of_phandle_args iommuspec;
  785. struct msm_audio_ion_private *msm_audio_ion_data = NULL;
  786. #ifndef CONFIG_SPF_CORE
  787. enum apr_subsys_state q6_state;
  788. #endif
  789. dev_err(dev, "%s: msm_audio_ion_probe\n", __func__);
  790. if (dev->of_node == NULL) {
  791. dev_err(dev,
  792. "%s: device tree is not found\n",
  793. __func__);
  794. return 0;
  795. }
  796. msm_audio_ion_data = devm_kzalloc(&pdev->dev, (sizeof(struct msm_audio_ion_private)),
  797. GFP_KERNEL);
  798. if (!msm_audio_ion_data)
  799. return -ENOMEM;
  800. is_non_hypervisor_en = of_property_read_bool(dev->of_node,
  801. msm_audio_ion_non_hyp);
  802. msm_audio_ion_data->is_non_hypervisor = is_non_hypervisor_en;
  803. smmu_enabled = of_property_read_bool(dev->of_node,
  804. msm_audio_ion_dt);
  805. msm_audio_ion_data->smmu_enabled = smmu_enabled;
  806. if (!smmu_enabled)
  807. dev_dbg(dev, "%s: SMMU is Disabled\n", __func__);
  808. #ifndef CONFIG_SPF_CORE
  809. q6_state = apr_get_q6_state();
  810. if (q6_state == APR_SUBSYS_DOWN) {
  811. dev_info(dev,
  812. "defering %s, adsp_state %d\n",
  813. __func__, q6_state);
  814. return -EPROBE_DEFER;
  815. }
  816. #endif
  817. dev_dbg(dev, "%s: adsp is ready\n", __func__);
  818. if (smmu_enabled) {
  819. msm_audio_ion_data->driver_name = "msm_audio_ion";
  820. rc = of_property_read_u32(dev->of_node,
  821. msm_audio_ion_smmu,
  822. &(msm_audio_ion_data->smmu_version));
  823. if (rc) {
  824. dev_err(dev,
  825. "%s: qcom,smmu_version missing in DT node\n",
  826. __func__);
  827. return rc;
  828. }
  829. dev_dbg(dev, "%s: SMMU is Enabled. SMMU version is (%d)",
  830. __func__, msm_audio_ion_data->smmu_version);
  831. /* Get SMMU SID information from Devicetree */
  832. rc = of_property_read_u64(dev->of_node,
  833. msm_audio_ion_smmu_sid_mask,
  834. &smmu_sid_mask);
  835. if (rc) {
  836. dev_err(dev,
  837. "%s: qcom,smmu-sid-mask missing in DT node, using default\n",
  838. __func__);
  839. smmu_sid_mask = 0xFFFFFFFFFFFFFFFF;
  840. }
  841. rc = of_parse_phandle_with_args(dev->of_node, "iommus",
  842. "#iommu-cells", 0, &iommuspec);
  843. if (rc)
  844. dev_err(dev, "%s: could not get smmu SID, ret = %d\n",
  845. __func__, rc);
  846. else
  847. smmu_sid = (iommuspec.args[0] & smmu_sid_mask);
  848. msm_audio_ion_data->smmu_sid_bits =
  849. smmu_sid << MSM_AUDIO_SMMU_SID_OFFSET;
  850. } else {
  851. msm_audio_ion_data->driver_name = "msm_audio_ion_cma";
  852. }
  853. if (!rc)
  854. msm_audio_ion_data->device_status |= MSM_AUDIO_ION_PROBED;
  855. msm_audio_ion_data->cb_dev = dev;
  856. dev_set_drvdata(dev, msm_audio_ion_data);
  857. if (!msm_audio_ion_fd_list_init) {
  858. INIT_LIST_HEAD(&msm_audio_ion_fd_list.fd_list);
  859. mutex_init(&(msm_audio_ion_fd_list.list_mutex));
  860. msm_audio_ion_fd_list_init = true;
  861. }
  862. INIT_LIST_HEAD(&msm_audio_ion_data->alloc_list);
  863. mutex_init(&(msm_audio_ion_data->list_mutex));
  864. rc = msm_audio_ion_reg_chrdev(msm_audio_ion_data);
  865. if (rc) {
  866. pr_err("%s register char dev failed, rc : %d", __func__, rc);
  867. return rc;
  868. }
  869. return rc;
  870. }
  871. static int msm_audio_ion_remove(struct platform_device *pdev)
  872. {
  873. struct msm_audio_ion_private *ion_data = dev_get_drvdata(&pdev->dev);
  874. ion_data->smmu_enabled = 0;
  875. ion_data->device_status = 0;
  876. msm_audio_ion_unreg_chrdev(ion_data);
  877. return 0;
  878. }
  879. static struct platform_driver msm_audio_ion_driver = {
  880. .driver = {
  881. .name = "msm-audio-ion",
  882. .owner = THIS_MODULE,
  883. .of_match_table = msm_audio_ion_dt_match,
  884. .suppress_bind_attrs = true,
  885. },
  886. .probe = msm_audio_ion_probe,
  887. .remove = msm_audio_ion_remove,
  888. };
  889. int __init msm_audio_ion_init(void)
  890. {
  891. pr_debug("%s: msm_audio_ion_init called \n",__func__);
  892. return platform_driver_register(&msm_audio_ion_driver);
  893. }
  894. void msm_audio_ion_exit(void)
  895. {
  896. platform_driver_unregister(&msm_audio_ion_driver);
  897. }
  898. module_init(msm_audio_ion_init);
  899. module_exit(msm_audio_ion_exit);
  900. MODULE_DESCRIPTION("MSM Audio ION module");
  901. MODULE_LICENSE("GPL v2");