msm_audio_ion.c 26 KB

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