From 6ed8bf232a153d6a769d714c8d7af1c69298b3b6 Mon Sep 17 00:00:00 2001 From: Nikhilesh Reddy Date: Mon, 1 Jun 2015 16:08:32 -0700 Subject: [PATCH 1/4] uio: Add snapshot of MSM sharedmem driver This is a snapshot of the MSM sharedmem driver as of msm-3.14 commit: commit <149717c0> ("uio: msm_sharedmem: Add custom mmap") + sharedmem qmi logic is removed. The following changes are included: 02d55287 uio: msm_sharedmem: Restrict debugfs write to root. de961fc7 uio: msm_sharedmem: Return ENOMEM if the shared mem addr is zero. b974ce64 uio: msm_sharedmem: Add addtional information to debugfs c46af547 uio: msm_sharedmem: Add support for dynamic shared memory allocation Change-Id: I49902f018bde1d59d41027b7e46268cc17231a3e Signed-off-by: Nikhilesh Reddy Signed-off-by: Ritesh Harjani Signed-off-by: Ankit Jain Signed-off-by: Richard Patrick --- drivers/uio/Kconfig | 10 ++ drivers/uio/Makefile | 1 + drivers/uio/msm_sharedmem/Makefile | 2 + drivers/uio/msm_sharedmem/msm_sharedmem.c | 180 ++++++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 drivers/uio/msm_sharedmem/Makefile create mode 100644 drivers/uio/msm_sharedmem/msm_sharedmem.c diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 202ee81cfc2b..413dcab496dd 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -165,4 +165,14 @@ config UIO_HV_GENERIC to network and storage devices from userspace. If you compile this as a module, it will be called uio_hv_generic. + +config UIO_MSM_SHAREDMEM + bool "MSM shared memory driver" + default n + help + Provides the clients with their respective alloted shared memory + addresses which are used as transport buffer. + + If you don't know what to do here, say N. + endif diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index c285dd2a4539..0f175f2804a2 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o obj-$(CONFIG_UIO_MF624) += uio_mf624.o obj-$(CONFIG_UIO_FSL_ELBC_GPCM) += uio_fsl_elbc_gpcm.o obj-$(CONFIG_UIO_HV_GENERIC) += uio_hv_generic.o +obj-$(CONFIG_UIO_MSM_SHAREDMEM) += msm_sharedmem/ diff --git a/drivers/uio/msm_sharedmem/Makefile b/drivers/uio/msm_sharedmem/Makefile new file mode 100644 index 000000000000..70b503700e00 --- /dev/null +++ b/drivers/uio/msm_sharedmem/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_UIO_MSM_SHAREDMEM) := msm_sharedmem.o diff --git a/drivers/uio/msm_sharedmem/msm_sharedmem.c b/drivers/uio/msm_sharedmem/msm_sharedmem.c new file mode 100644 index 000000000000..3548c6c3091f --- /dev/null +++ b/drivers/uio/msm_sharedmem/msm_sharedmem.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + */ + +#define DRIVER_NAME "msm_sharedmem" +#define pr_fmt(fmt) DRIVER_NAME ": %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include + +#define CLIENT_ID_PROP "qcom,client-id" + +static int uio_get_mem_index(struct uio_info *info, struct vm_area_struct *vma) +{ + if (vma->vm_pgoff >= MAX_UIO_MAPS) + return -EINVAL; + + if (info->mem[vma->vm_pgoff].size == 0) + return -EINVAL; + + return (int)vma->vm_pgoff; +} + +static int sharedmem_mmap(struct uio_info *info, struct vm_area_struct *vma) +{ + int result; + struct uio_mem *mem; + int mem_index = uio_get_mem_index(info, vma); + + if (mem_index < 0) { + pr_err("mem_index is invalid errno %d\n", mem_index); + return mem_index; + } + + mem = info->mem + mem_index; + + if (vma->vm_end - vma->vm_start > mem->size) { + pr_err("vm_end[%lu] - vm_start[%lu] [%lu] > mem->size[%lu]\n", + vma->vm_end, vma->vm_start, + (vma->vm_end - vma->vm_start), mem->size); + return -EINVAL; + } + pr_debug("Attempting to setup mmap.\n"); + + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + result = remap_pfn_range(vma, + vma->vm_start, + mem->addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + if (result != 0) + pr_err("mmap Failed with errno %d\n", result); + else + pr_debug("mmap success\n"); + + return result; +} + +static int msm_sharedmem_probe(struct platform_device *pdev) +{ + int ret = 0; + struct uio_info *info = NULL; + struct resource *clnt_res = NULL; + u32 client_id = ((u32)~0U); + u32 shared_mem_size = 0; + void *shared_mem = NULL; + phys_addr_t shared_mem_pyhsical = 0; + bool is_addr_dynamic = false; + + /* Get the addresses from platform-data */ + if (!pdev->dev.of_node) { + pr_err("Node not found\n"); + ret = -ENODEV; + goto out; + } + clnt_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!clnt_res) { + pr_err("resource not found\n"); + return -ENODEV; + } + + ret = of_property_read_u32(pdev->dev.of_node, CLIENT_ID_PROP, + &client_id); + if (ret) { + client_id = ((u32)~0U); + pr_warn("qcom,client-id property not found\n"); + } + + info = devm_kzalloc(&pdev->dev, sizeof(struct uio_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + shared_mem_size = resource_size(clnt_res); + shared_mem_pyhsical = clnt_res->start; + + if (shared_mem_size == 0) { + pr_err("Shared memory size is zero\n"); + return -EINVAL; + } + + if (shared_mem_pyhsical == 0) { + is_addr_dynamic = true; + shared_mem = dma_alloc_coherent(&pdev->dev, shared_mem_size, + &shared_mem_pyhsical, GFP_KERNEL); + if (shared_mem == NULL) + return -ENOMEM; + } + + /* Setup device */ + info->mmap = sharedmem_mmap; /* Custom mmap function. */ + info->name = clnt_res->name; + info->version = "1.0"; + info->mem[0].addr = shared_mem_pyhsical; + info->mem[0].size = shared_mem_size; + info->mem[0].memtype = UIO_MEM_PHYS; + + ret = uio_register_device(&pdev->dev, info); + if (ret) { + pr_err("uio register failed ret=%d\n", ret); + goto out; + } + dev_set_drvdata(&pdev->dev, info); + + pr_info("Device created for client '%s'\n", clnt_res->name); +out: + return ret; +} + +static int msm_sharedmem_remove(struct platform_device *pdev) +{ + struct uio_info *info = dev_get_drvdata(&pdev->dev); + + uio_unregister_device(info); + + return 0; +} + +static const struct of_device_id msm_sharedmem_of_match[] = { + {.compatible = "qcom,sharedmem-uio",}, + {}, +}; +MODULE_DEVICE_TABLE(of, msm_sharedmem_of_match); + +static struct platform_driver msm_sharedmem_driver = { + .probe = msm_sharedmem_probe, + .remove = msm_sharedmem_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = msm_sharedmem_of_match, + }, +}; + + +static int __init msm_sharedmem_init(void) +{ + int result; + + result = platform_driver_register(&msm_sharedmem_driver); + if (result != 0) { + pr_err("Platform driver registration failed\n"); + return result; + } + return 0; +} + +static void __exit msm_sharedmem_exit(void) +{ + platform_driver_unregister(&msm_sharedmem_driver); +} + +module_init(msm_sharedmem_init); +module_exit(msm_sharedmem_exit); + +MODULE_LICENSE("GPL v2"); From a9937c5125e3d2bcfadaa45aae3e203604e0b243 Mon Sep 17 00:00:00 2001 From: Nikhilesh Reddy Date: Thu, 4 Jun 2015 11:31:42 -0700 Subject: [PATCH 2/4] uio: msm_sharedmem: Add support for HYP call Add support for HYP call to setup the sharedmem permissions for the MPSS client. Change-Id: I3b48ae962865d8d0a0ea6e3fbb8e21278b59c690 Signed-off-by: Nikhilesh Reddy [riteshh@codeaurora.org: fixed trivial merge conflicts] Signed-off-by: Ritesh Harjani Signed-off-by: Ankit Jain Signed-off-by: Richard Patrick --- drivers/uio/msm_sharedmem/msm_sharedmem.c | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/uio/msm_sharedmem/msm_sharedmem.c b/drivers/uio/msm_sharedmem/msm_sharedmem.c index 3548c6c3091f..503c444ba344 100644 --- a/drivers/uio/msm_sharedmem/msm_sharedmem.c +++ b/drivers/uio/msm_sharedmem/msm_sharedmem.c @@ -13,7 +13,10 @@ #include #include +#include + #define CLIENT_ID_PROP "qcom,client-id" +#define MPSS_RMTS_CLIENT_ID 1 static int uio_get_mem_index(struct uio_info *info, struct vm_area_struct *vma) { @@ -62,6 +65,31 @@ static int sharedmem_mmap(struct uio_info *info, struct vm_area_struct *vma) return result; } +/* Setup the shared ram permissions. + * This function currently supports the mpss client only. + */ +static void setup_shared_ram_perms(u32 client_id, phys_addr_t addr, u32 size) +{ + int ret; + u32 source_vmlist[1] = {VMID_HLOS}; + int dest_vmids[2] = {VMID_HLOS, VMID_MSS_MSA}; + int dest_perms[2] = {PERM_READ|PERM_WRITE, + PERM_READ|PERM_WRITE}; + + if (client_id != MPSS_RMTS_CLIENT_ID) + return; + + ret = hyp_assign_phys(addr, size, source_vmlist, 1, dest_vmids, + dest_perms, 2); + if (ret != 0) { + if (ret == -EINVAL) + pr_warn("hyp_assign_phys is not supported!\n"); + else + pr_err("hyp_assign_phys failed IPA=0x%016llX size=%u err=%d\n", + addr, size, ret); + } +} + static int msm_sharedmem_probe(struct platform_device *pdev) { int ret = 0; @@ -112,6 +140,9 @@ static int msm_sharedmem_probe(struct platform_device *pdev) return -ENOMEM; } + /* Set up the permissions for the shared ram that was allocated. */ + setup_shared_ram_perms(client_id, shared_mem_pyhsical, shared_mem_size); + /* Setup device */ info->mmap = sharedmem_mmap; /* Custom mmap function. */ info->name = clnt_res->name; From 5a12bcfdc2495ec0efee470c72e43cc4ae1e5074 Mon Sep 17 00:00:00 2001 From: Prasad Sodagudi Date: Wed, 7 Oct 2015 23:04:40 +0530 Subject: [PATCH 3/4] uio: msm_sharedmem: Use proper format to print phys_addr_t Use proper printk format specifier to print phys_addr_t type variable. Change-Id: I7c55e44e813d8d41e1ead03280044c8542a24922 Signed-off-by: Prasad Sodagudi [riteshh@codeaurora.org: fixed trivial merge conflicts] Signed-off-by: Ritesh Harjani Signed-off-by: Ankit Jain Signed-off-by: Richard Patrick --- drivers/uio/msm_sharedmem/msm_sharedmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/uio/msm_sharedmem/msm_sharedmem.c b/drivers/uio/msm_sharedmem/msm_sharedmem.c index 503c444ba344..8b8abc055be0 100644 --- a/drivers/uio/msm_sharedmem/msm_sharedmem.c +++ b/drivers/uio/msm_sharedmem/msm_sharedmem.c @@ -85,8 +85,8 @@ static void setup_shared_ram_perms(u32 client_id, phys_addr_t addr, u32 size) if (ret == -EINVAL) pr_warn("hyp_assign_phys is not supported!\n"); else - pr_err("hyp_assign_phys failed IPA=0x%016llX size=%u err=%d\n", - addr, size, ret); + pr_err("hyp_assign_phys failed IPA=0x016%pa size=%u err=%d\n", + &addr, size, ret); } } From 9e97a7be893b642a9812fe1a69f698e69ef9800c Mon Sep 17 00:00:00 2001 From: Nikhilesh Reddy Date: Wed, 16 Mar 2016 14:31:23 -0700 Subject: [PATCH 4/4] uio: msm_sharedmem: Fix format specifier to print resource_size_t Use proper printk format specifier %pa to print resource_size_t type variable. Change-Id: I77b1f3ded0957d4a572c5c05996a3649a9b1fb45 Signed-off-by: Nikhilesh Reddy [riteshh@codeaurora.org: fixed trivial merge conflicts] Signed-off-by: Ritesh Harjani Signed-off-by: Ankit Jain Signed-off-by: Richard Patrick --- drivers/uio/msm_sharedmem/msm_sharedmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/uio/msm_sharedmem/msm_sharedmem.c b/drivers/uio/msm_sharedmem/msm_sharedmem.c index 8b8abc055be0..faced5a29d36 100644 --- a/drivers/uio/msm_sharedmem/msm_sharedmem.c +++ b/drivers/uio/msm_sharedmem/msm_sharedmem.c @@ -43,9 +43,9 @@ static int sharedmem_mmap(struct uio_info *info, struct vm_area_struct *vma) mem = info->mem + mem_index; if (vma->vm_end - vma->vm_start > mem->size) { - pr_err("vm_end[%lu] - vm_start[%lu] [%lu] > mem->size[%lu]\n", + pr_err("vm_end[%lu] - vm_start[%lu] [%lu] > mem->size[%pa]\n", vma->vm_end, vma->vm_start, - (vma->vm_end - vma->vm_start), mem->size); + (vma->vm_end - vma->vm_start), &mem->size); return -EINVAL; } pr_debug("Attempting to setup mmap.\n");