msm_audio_ion.c 27 KB

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