msm_audio_ion.c 26 KB

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