Re: [Freedreno] [PATCH] of/device: add blacklist for iommu dma_ops
On Mon, Jun 3, 2019 at 4:47 PM Christoph Hellwig wrote: > > If you (and a few others actors in the thread) want people to actually > read what you wrote please follow proper mailing list ettiquette. I've > given up on reading all the recent mails after scrolling through two > pages of full quotes. Apologies for not cutting down the quoted text. I will be more careful next time onwards. Regards Vivek -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH] of/device: add blacklist for iommu dma_ops
On Mon, Jun 3, 2019 at 4:14 PM Rob Clark wrote: > > On Mon, Jun 3, 2019 at 12:57 AM Vivek Gautam > wrote: > > > > > > > > On 6/3/2019 11:50 AM, Tomasz Figa wrote: > > > On Mon, Jun 3, 2019 at 4:40 AM Rob Clark wrote: > > >> On Fri, May 10, 2019 at 7:35 AM Rob Clark wrote: > > >>> On Tue, Dec 4, 2018 at 2:29 PM Rob Herring wrote: > > >>>> On Sat, Dec 1, 2018 at 10:54 AM Rob Clark wrote: > > >>>>> This solves a problem we see with drm/msm, caused by getting > > >>>>> iommu_dma_ops while we attach our own domain and manage it directly at > > >>>>> the iommu API level: > > >>>>> > > >>>>>[0038] user address but active_mm is swapper > > >>>>>Internal error: Oops: 9605 [#1] PREEMPT SMP > > >>>>>Modules linked in: > > >>>>>CPU: 7 PID: 70 Comm: kworker/7:1 Tainted: GW > > >>>>> 4.19.3 #90 > > >>>>>Hardware name: xxx (DT) > > >>>>>Workqueue: events deferred_probe_work_func > > >>>>>pstate: 80c9 (Nzcv daif +PAN +UAO) > > >>>>>pc : iommu_dma_map_sg+0x7c/0x2c8 > > >>>>>lr : iommu_dma_map_sg+0x40/0x2c8 > > >>>>>sp : ff80095eb4f0 > > >>>>>x29: ff80095eb4f0 x28: > > >>>>>x27: ffc0f9431578 x26: > > >>>>>x25: x24: 0003 > > >>>>>x23: 0001 x22: ffc0fa9ac010 > > >>>>>x21: x20: ffc0fab40980 > > >>>>>x19: ffc0fab40980 x18: 0003 > > >>>>>x17: 01c4 x16: 0007 > > >>>>>x15: 000e x14: > > >>>>>x13: x12: 0028 > > >>>>>x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f > > >>>>>x9 : x8 : ffc0fab409a0 > > >>>>>x7 : x6 : 0002 > > >>>>>x5 : 0001 x4 : > > >>>>>x3 : 0001 x2 : 0002 > > >>>>>x1 : ffc0f9431578 x0 : > > >>>>>Process kworker/7:1 (pid: 70, stack limit = 0x17d08ffb) > > >>>>>Call trace: > > >>>>> iommu_dma_map_sg+0x7c/0x2c8 > > >>>>> __iommu_map_sg_attrs+0x70/0x84 > > >>>>> get_pages+0x170/0x1e8 > > >>>>> msm_gem_get_iova+0x8c/0x128 > > >>>>> _msm_gem_kernel_new+0x6c/0xc8 > > >>>>> msm_gem_kernel_new+0x4c/0x58 > > >>>>> dsi_tx_buf_alloc_6g+0x4c/0x8c > > >>>>> msm_dsi_host_modeset_init+0xc8/0x108 > > >>>>> msm_dsi_modeset_init+0x54/0x18c > > >>>>> _dpu_kms_drm_obj_init+0x430/0x474 > > >>>>> dpu_kms_hw_init+0x5f8/0x6b4 > > >>>>> msm_drm_bind+0x360/0x6c8 > > >>>>> try_to_bring_up_master.part.7+0x28/0x70 > > >>>>> component_master_add_with_match+0xe8/0x124 > > >>>>> msm_pdev_probe+0x294/0x2b4 > > >>>>> platform_drv_probe+0x58/0xa4 > > >>>>> really_probe+0x150/0x294 > > >>>>> driver_probe_device+0xac/0xe8 > > >>>>> __device_attach_driver+0xa4/0xb4 > > >>>>> bus_for_each_drv+0x98/0xc8 > > >>>>> __device_attach+0xac/0x12c > > >>>>> device_initial_probe+0x24/0x30 > > >>>>> bus_probe_device+0x38/0x98 > > >>>>> deferred_probe_work_func+0x78/0xa4 > > >>>>> process_one_work+0x24c/0x3dc > > >>>>> worker_thread+0x280/0x360 > > >>>>> kthread+0x134/0x13c > > >>>>> ret_from_fork+0x10/0x18 > > >>>>>Code: d284 91000725 6b17039f 5400048a (f9401f40) > > >>>>>---[ end trace f22dda57f3648e2c ]--- > > >>>>>Kernel panic - not syncing: Fatal exception > > >>>>>SMP: stopping secondary CPUs > > >>>>>Kernel Offset: disable
Re: [Freedreno] [PATCH] of/device: add blacklist for iommu dma_ops
On 6/3/2019 11:50 AM, Tomasz Figa wrote: On Mon, Jun 3, 2019 at 4:40 AM Rob Clark wrote: On Fri, May 10, 2019 at 7:35 AM Rob Clark wrote: On Tue, Dec 4, 2018 at 2:29 PM Rob Herring wrote: On Sat, Dec 1, 2018 at 10:54 AM Rob Clark wrote: This solves a problem we see with drm/msm, caused by getting iommu_dma_ops while we attach our own domain and manage it directly at the iommu API level: [0038] user address but active_mm is swapper Internal error: Oops: 9605 [#1] PREEMPT SMP Modules linked in: CPU: 7 PID: 70 Comm: kworker/7:1 Tainted: GW 4.19.3 #90 Hardware name: xxx (DT) Workqueue: events deferred_probe_work_func pstate: 80c9 (Nzcv daif +PAN +UAO) pc : iommu_dma_map_sg+0x7c/0x2c8 lr : iommu_dma_map_sg+0x40/0x2c8 sp : ff80095eb4f0 x29: ff80095eb4f0 x28: x27: ffc0f9431578 x26: x25: x24: 0003 x23: 0001 x22: ffc0fa9ac010 x21: x20: ffc0fab40980 x19: ffc0fab40980 x18: 0003 x17: 01c4 x16: 0007 x15: 000e x14: x13: x12: 0028 x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f x9 : x8 : ffc0fab409a0 x7 : x6 : 0002 x5 : 0001 x4 : x3 : 0001 x2 : 0002 x1 : ffc0f9431578 x0 : Process kworker/7:1 (pid: 70, stack limit = 0x17d08ffb) Call trace: iommu_dma_map_sg+0x7c/0x2c8 __iommu_map_sg_attrs+0x70/0x84 get_pages+0x170/0x1e8 msm_gem_get_iova+0x8c/0x128 _msm_gem_kernel_new+0x6c/0xc8 msm_gem_kernel_new+0x4c/0x58 dsi_tx_buf_alloc_6g+0x4c/0x8c msm_dsi_host_modeset_init+0xc8/0x108 msm_dsi_modeset_init+0x54/0x18c _dpu_kms_drm_obj_init+0x430/0x474 dpu_kms_hw_init+0x5f8/0x6b4 msm_drm_bind+0x360/0x6c8 try_to_bring_up_master.part.7+0x28/0x70 component_master_add_with_match+0xe8/0x124 msm_pdev_probe+0x294/0x2b4 platform_drv_probe+0x58/0xa4 really_probe+0x150/0x294 driver_probe_device+0xac/0xe8 __device_attach_driver+0xa4/0xb4 bus_for_each_drv+0x98/0xc8 __device_attach+0xac/0x12c device_initial_probe+0x24/0x30 bus_probe_device+0x38/0x98 deferred_probe_work_func+0x78/0xa4 process_one_work+0x24c/0x3dc worker_thread+0x280/0x360 kthread+0x134/0x13c ret_from_fork+0x10/0x18 Code: d284 91000725 6b17039f 5400048a (f9401f40) ---[ end trace f22dda57f3648e2c ]--- Kernel panic - not syncing: Fatal exception SMP: stopping secondary CPUs Kernel Offset: disabled CPU features: 0x0,22802a18 Memory Limit: none The problem is that when drm/msm does it's own iommu_attach_device(), now the domain returned by iommu_get_domain_for_dev() is drm/msm's domain, and it doesn't have domain->iova_cookie. We kind of avoided this problem prior to sdm845/dpu because the iommu was attached to the mdp node in dt, which is a child of the toplevel mdss node (which corresponds to the dev passed in dma_map_sg()). But with sdm845, now the iommu is attached at the mdss level so we hit the iommu_dma_ops in dma_map_sg(). But auto allocating/attaching a domain before the driver is probed was already a blocking problem for enabling per-context pagetables for the GPU. This problem is also now solved with this patch. Fixes: 97890ba9289c dma-mapping: detect and configure IOMMU in of_dma_configure Tested-by: Douglas Anderson Signed-off-by: Rob Clark --- This is an alternative/replacement for [1]. What it lacks in elegance it makes up for in practicality ;-) [1] https://patchwork.freedesktop.org/patch/264930/ drivers/of/device.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/of/device.c b/drivers/of/device.c index 5957cd4fa262..15ffee00fb22 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -72,6 +72,14 @@ int of_device_add(struct platform_device *ofdev) return device_add(>dev); } +static const struct of_device_id iommu_blacklist[] = { + { .compatible = "qcom,mdp4" }, + { .compatible = "qcom,mdss" }, + { .compatible = "qcom,sdm845-mdss" }, + { .compatible = "qcom,adreno" }, + {} +}; Not completely clear to whether this is still needed or not, but this really won't scale. Why can't the driver for these devices override whatever has been setup by default? fwiw, at the moment it is not needed, but it will become needed again to implement per-context pagetables (although I suppose for this we only need to blacklist qcom,adreno and not also the display nodes). So, another case I've come across, on the display side.. I'm working on handling the case where bootloader enables display (and takes iommu out of reset).. as soon as DMA domain gets attached we get iommu faults, because bootloader has
[Freedreno] [PATCH v2 1/1] drm/prime: Use sg_dma_len() macro to get sg's length
After mapping a sg list the we should use sg_dma_address() and sg_dma_len() macros to access sg->address and sg->length. Fix the same for sg->length in drm_prime_sg_to_page_addr_arrays(). Signed-off-by: Vivek Gautam --- Changes since v1: - Fixed compilation error: replaced sg_dma_length() with sg_dma_len(). This came while debugging one dmabuf import issue that we are seeing on sdm845 target. The dmabuf which is prepared by video (venus in this case), is imported by drm device. The import call flow looks like follows: drm_gem_prime_import() - drm_gem_prime_import_dev() - dma_buf_attach() & dma_buf_map_attachment() - From dma_buf_map_attachment() - vb2_dma_sg_dmabuf_ops_map() - dma_map_sg(): this updates the sg->nents. From debugging, the sg table mapping results in sg's 'nents' to be less that the original nents. Now drm device prepares the page information based on this sg table, and messes up with the mappings, and we start seeing random crashes as below from drm's memory space. Although this change isn't helping to fix the issue currently, but this fix seems the right thing to do. One thing to notice is that, if we restore the sg->nents to sg->orig_nents in vb2_dma_sg_dmabuf_ops_map(), we don't see the below corruptions. Any pointers on this will be highly appreciated. Thanks. -- [ 338.070558] Unable to handle kernel paging request at virtual address 4038 [ 338.078751] Mem abort info: [ 338.081671] ESR = 0x9604 [ 338.084860] Exception class = DABT (current EL), IL = 32 bits [ 338.090972] SET = 0, FnV = 0 [ 338.094139] EA = 0, S1PTW = 0 [ 338.097393] Data abort info: [ 338.100375] ISV = 0, ISS = 0x0004 [ 338.104362] CM = 0, WnR = 0 [ 338.107446] [4038] address between user and kernel address ranges [ 338.114801] Internal error: Oops: 9604 [#1] PREEMPT SMP [ 338.120527] Modules linked in: rfcomm uinput cdc_ether venus_dec venus_enc usbnet videobuf2_dma_sg videobuf2_memops hci_uart btqca bluetooth r8152 mii ath10k_snoc venus_core ath10k_core v4l2_mem2mem videobuf2_v4l2 videobuf2_common ath mac80211 ecdh_generic qcom_q6v5_mss lzo lzo_compress qcom_q6v5_adsp qcom_common qcom_q6v5 zram bridge stp llc ipt_MASQUERADE fuse snd_seq_dummy snd_seq snd_seq_device cfg80211 joydev [ 338.158192] CPU: 4 PID: 3235 Comm: chrome Tainted: GW 4.19.0 #2 [ 338.165700] Hardware name: Google Cheza (rev1) (DT) [ 338.170720] pstate: 8049 (Nzcv daif +PAN -UAO) [ 338.175660] pc : drm_mm_insert_node_in_range+0xfc/0x348 [ 338.181035] lr : drm_mm_insert_node_in_range+0x24/0x348 [ 338.186407] sp : ff8013033b30 [ 338.189816] x29: ff8013033bd0 x28: ff8008591894 [ 338.195275] x27: 0010 x26: [ 338.200734] x25: x24: [ 338.206194] x23: x22: ffc0f48b7e08 [ 338.211656] x21: x20: 005d [ 338.217118] x19: x18: [ 338.222581] x17: x16: [ 338.228046] x15: x14: [ 338.233511] x13: 0001 x12: ffc0b1da7200 [ 338.238978] x11: 0010 x10: 0010 [ 338.244437] x9 : 0008 x8 : 4000 [ 338.249898] x7 : x6 : [ 338.255361] x5 : x4 : [ 338.260823] x3 : x2 : 005d [ 338.266285] x1 : ffc0b1da7100 x0 : ffc0b0215800 [ 338.271748] Process chrome (pid: 3235, stack limit = 0x0900f416) [ 338.278628] Call trace: [ 338.281151] drm_mm_insert_node_in_range+0xfc/0x348 [ 338.286168] msm_gem_map_vma+0x60/0xdc [ 338.290022] msm_gem_get_iova+0xb4/0xf4 [ 338.293967] msm_ioctl_gem_info+0x90/0xdc [ 338.298089] drm_ioctl_kernel+0xa8/0xe8 [ 338.302043] drm_ioctl+0x218/0x384 [ 338.305547] drm_compat_ioctl+0xd8/0xe8 [ 338.309503] __arm64_compat_sys_ioctl+0x134/0x20c [ 338.314339] el0_svc_common+0xa0/0xf0 [ 338.318108] el0_svc_compat_handler+0x2c/0x38 [ 338.322588] el0_svc_compat+0x8/0x18 [ 338.326274] Code: f94066c8 aa1f03e0 321d03e9 321c03ea (f9401d0b) [ 338.332538] ---[ end trace 5c09e60869887d87 ]--- [ 338.354633] Kernel panic - not syncing: Fatal exception [ 338.360018] SMP: stopping secondary CPUs [ 338.364179] Kernel Offset: disabled [ 338.367779] CPU features: 0x0,22802a18 [ 338.371643] Memory Limit: none -- drivers/gpu/drm/drm_prime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 231e3f6d5f41..aa87ba9c0d7b 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -945,7 +945,7 @@ int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, index = 0; for_each_sg(sgt->sgl, sg, sgt->nents, count) { - len = sg->length; +
Re: [Freedreno] [PATCH 1/1] drm/prime: Use sg_dma_len() macro to get sg's length
On Mon, Jan 7, 2019 at 4:14 PM kbuild test robot wrote: > > Hi Vivek, > > Thank you for the patch! Yet something to improve: > > [auto build test ERROR on linus/master] > [also build test ERROR on v5.0-rc1 next-20190107] > [if your patch is applied to the wrong git tree, please drop us a note to > help improve the system] > > url: > https://github.com/0day-ci/linux/commits/Vivek-Gautam/drm-prime-Use-sg_dma_len-macro-to-get-sg-s-length/20190107-181350 > config: x86_64-randconfig-x013-201901 (attached as .config) > compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 > reproduce: > # save the attached .config to linux build tree > make ARCH=x86_64 > > All errors (new ones prefixed by >>): > >drivers/gpu/drm/drm_prime.c: In function > 'drm_prime_sg_to_page_addr_arrays': > >> drivers/gpu/drm/drm_prime.c:948:9: error: implicit declaration of function > >> 'sg_dma_length'; did you mean 'sg_dma_len'? > >> [-Werror=implicit-function-declaration] > len = sg_dma_length(sg); > ^ > sg_dma_len Sorry, my fat finger :( This should be as suggested - sg_dma_len(). Thanks Vivek >cc1: some warnings being treated as errors > > vim +948 drivers/gpu/drm/drm_prime.c > >926 >927 /** >928 * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page > array >929 * @sgt: scatter-gather table to convert >930 * @pages: optional array of page pointers to store the page array in >931 * @addrs: optional array to store the dma bus address of each page >932 * @max_entries: size of both the passed-in arrays >933 * >934 * Exports an sg table into an array of pages and addresses. This is > currently >935 * required by the TTM driver in order to do correct fault handling. >936 */ >937 int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct > page **pages, >938 dma_addr_t *addrs, int > max_entries) >939 { >940 unsigned count; >941 struct scatterlist *sg; >942 struct page *page; >943 u32 len, index; >944 dma_addr_t addr; >945 >946 index = 0; >947 for_each_sg(sgt->sgl, sg, sgt->nents, count) { > > 948 len = sg_dma_length(sg); >949 page = sg_page(sg); >950 addr = sg_dma_address(sg); >951 >952 while (len > 0) { >953 if (WARN_ON(index >= max_entries)) >954 return -1; >955 if (pages) >956 pages[index] = page; >957 if (addrs) >958 addrs[index] = addr; >959 >960 page++; >961 addr += PAGE_SIZE; >962 len -= PAGE_SIZE; >963 index++; >964 } >965 } >966 return 0; >967 } >968 EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays); >969 > > --- > 0-DAY kernel test infrastructureOpen Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH 1/1] drm/prime: Use sg_dma_len() macro to get sg's length
After mapping a sg list we should use sg_dma_address(), and sg_dma_len() macros to access sg->address and sg->length. Fix the same for sg->length in drm_prime_sg_to_page_addr_arrays(). Signed-off-by: Vivek Gautam --- This came while debugging one dmabuf import issue that we are seeing on sdm845 target. The dmabuf which is prepared by video (venus in this case), is imported by drm device. The import call flow looks like follows: drm_gem_prime_import() - drm_gem_prime_import_dev() - dma_buf_attach() & dma_buf_map_attachment() - From dma_buf_map_attachment() - vb2_dma_sg_dmabuf_ops_map() - dma_map_sg(): this updates the sg->nents. From debugging, the sg table mapping results in sg's 'nents' to be less that the original nents. Now drm device prepares the page information based on this sg table, and messes up with the mappings, and we start seeing random crashes as below from drm's memory space. Although this change isn't helping to fix the issue currently, but this fix seems the right thing to do. One thing to notice is that, if we restore the sg->nents to sg->orig_nents in vb2_dma_sg_dmabuf_ops_map(), we don't see the below corruptions. Any pointers on this will be highly appreciated. Thanks. -- [ 338.070558] Unable to handle kernel paging request at virtual address 4038 [ 338.078751] Mem abort info: [ 338.081671] ESR = 0x9604 [ 338.084860] Exception class = DABT (current EL), IL = 32 bits [ 338.090972] SET = 0, FnV = 0 [ 338.094139] EA = 0, S1PTW = 0 [ 338.097393] Data abort info: [ 338.100375] ISV = 0, ISS = 0x0004 [ 338.104362] CM = 0, WnR = 0 [ 338.107446] [4038] address between user and kernel address ranges [ 338.114801] Internal error: Oops: 9604 [#1] PREEMPT SMP [ 338.120527] Modules linked in: rfcomm uinput cdc_ether venus_dec venus_enc usbnet videobuf2_dma_sg videobuf2_memops hci_uart btqca bluetooth r8152 mii ath10k_snoc venus_core ath10k_core v4l2_mem2mem videobuf2_v4l2 videobuf2_common ath mac80211 ecdh_generic qcom_q6v5_mss lzo lzo_compress qcom_q6v5_adsp qcom_common qcom_q6v5 zram bridge stp llc ipt_MASQUERADE fuse snd_seq_dummy snd_seq snd_seq_device cfg80211 joydev [ 338.158192] CPU: 4 PID: 3235 Comm: chrome Tainted: GW 4.19.0 #2 [ 338.165700] Hardware name: Google Cheza (rev1) (DT) [ 338.170720] pstate: 8049 (Nzcv daif +PAN -UAO) [ 338.175660] pc : drm_mm_insert_node_in_range+0xfc/0x348 [ 338.181035] lr : drm_mm_insert_node_in_range+0x24/0x348 [ 338.186407] sp : ff8013033b30 [ 338.189816] x29: ff8013033bd0 x28: ff8008591894 [ 338.195275] x27: 0010 x26: [ 338.200734] x25: x24: [ 338.206194] x23: x22: ffc0f48b7e08 [ 338.211656] x21: x20: 005d [ 338.217118] x19: x18: [ 338.222581] x17: x16: [ 338.228046] x15: x14: [ 338.233511] x13: 0001 x12: ffc0b1da7200 [ 338.238978] x11: 0010 x10: 0010 [ 338.244437] x9 : 0008 x8 : 4000 [ 338.249898] x7 : x6 : [ 338.255361] x5 : x4 : [ 338.260823] x3 : x2 : 005d [ 338.266285] x1 : ffc0b1da7100 x0 : ffc0b0215800 [ 338.271748] Process chrome (pid: 3235, stack limit = 0x0900f416) [ 338.278628] Call trace: [ 338.281151] drm_mm_insert_node_in_range+0xfc/0x348 [ 338.286168] msm_gem_map_vma+0x60/0xdc [ 338.290022] msm_gem_get_iova+0xb4/0xf4 [ 338.293967] msm_ioctl_gem_info+0x90/0xdc [ 338.298089] drm_ioctl_kernel+0xa8/0xe8 [ 338.302043] drm_ioctl+0x218/0x384 [ 338.305547] drm_compat_ioctl+0xd8/0xe8 [ 338.309503] __arm64_compat_sys_ioctl+0x134/0x20c [ 338.314339] el0_svc_common+0xa0/0xf0 [ 338.318108] el0_svc_compat_handler+0x2c/0x38 [ 338.322588] el0_svc_compat+0x8/0x18 [ 338.326274] Code: f94066c8 aa1f03e0 321d03e9 321c03ea (f9401d0b) [ 338.332538] ---[ end trace 5c09e60869887d87 ]--- [ 338.354633] Kernel panic - not syncing: Fatal exception [ 338.360018] SMP: stopping secondary CPUs [ 338.364179] Kernel Offset: disabled [ 338.367779] CPU features: 0x0,22802a18 [ 338.371643] Memory Limit: none -- drivers/gpu/drm/drm_prime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 231e3f6d5f41..0d9b1c43523a 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -945,7 +945,7 @@ int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, index = 0; for_each_sg(sgt->sgl, sg, sgt->nents, count) { - len = sg->length; + len = sg_dma_length(sg); page = sg_page(sg);
Re: [Freedreno] [PATCH] of/device: add blacklist for iommu dma_ops
On Mon, Dec 3, 2018 at 7:56 PM Rob Clark wrote: > > On Mon, Dec 3, 2018 at 7:45 AM Robin Murphy wrote: > > > > Hi Rob, > > > > On 01/12/2018 16:53, Rob Clark wrote: > > > This solves a problem we see with drm/msm, caused by getting > > > iommu_dma_ops while we attach our own domain and manage it directly at > > > the iommu API level: > > > > > >[0038] user address but active_mm is swapper > > >Internal error: Oops: 9605 [#1] PREEMPT SMP > > >Modules linked in: > > >CPU: 7 PID: 70 Comm: kworker/7:1 Tainted: GW 4.19.3 #90 > > >Hardware name: xxx (DT) > > >Workqueue: events deferred_probe_work_func > > >pstate: 80c9 (Nzcv daif +PAN +UAO) > > >pc : iommu_dma_map_sg+0x7c/0x2c8 > > >lr : iommu_dma_map_sg+0x40/0x2c8 > > >sp : ff80095eb4f0 > > >x29: ff80095eb4f0 x28: > > >x27: ffc0f9431578 x26: > > >x25: x24: 0003 > > >x23: 0001 x22: ffc0fa9ac010 > > >x21: x20: ffc0fab40980 > > >x19: ffc0fab40980 x18: 0003 > > >x17: 01c4 x16: 0007 > > >x15: 000e x14: > > >x13: x12: 0028 > > >x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f > > >x9 : x8 : ffc0fab409a0 > > >x7 : x6 : 0002 > > >x5 : 0001 x4 : > > >x3 : 0001 x2 : 0002 > > >x1 : ffc0f9431578 x0 : > > >Process kworker/7:1 (pid: 70, stack limit = 0x17d08ffb) > > >Call trace: > > > iommu_dma_map_sg+0x7c/0x2c8 > > > __iommu_map_sg_attrs+0x70/0x84 > > > get_pages+0x170/0x1e8 > > > msm_gem_get_iova+0x8c/0x128 > > > _msm_gem_kernel_new+0x6c/0xc8 > > > msm_gem_kernel_new+0x4c/0x58 > > > dsi_tx_buf_alloc_6g+0x4c/0x8c > > > msm_dsi_host_modeset_init+0xc8/0x108 > > > msm_dsi_modeset_init+0x54/0x18c > > > _dpu_kms_drm_obj_init+0x430/0x474 > > > dpu_kms_hw_init+0x5f8/0x6b4 > > > msm_drm_bind+0x360/0x6c8 > > > try_to_bring_up_master.part.7+0x28/0x70 > > > component_master_add_with_match+0xe8/0x124 > > > msm_pdev_probe+0x294/0x2b4 > > > platform_drv_probe+0x58/0xa4 > > > really_probe+0x150/0x294 > > > driver_probe_device+0xac/0xe8 > > > __device_attach_driver+0xa4/0xb4 > > > bus_for_each_drv+0x98/0xc8 > > > __device_attach+0xac/0x12c > > > device_initial_probe+0x24/0x30 > > > bus_probe_device+0x38/0x98 > > > deferred_probe_work_func+0x78/0xa4 > > > process_one_work+0x24c/0x3dc > > > worker_thread+0x280/0x360 > > > kthread+0x134/0x13c > > > ret_from_fork+0x10/0x18 > > >Code: d284 91000725 6b17039f 5400048a (f9401f40) > > >---[ end trace f22dda57f3648e2c ]--- > > >Kernel panic - not syncing: Fatal exception > > >SMP: stopping secondary CPUs > > >Kernel Offset: disabled > > >CPU features: 0x0,22802a18 > > >Memory Limit: none > > > > > > The problem is that when drm/msm does it's own iommu_attach_device(), > > > now the domain returned by iommu_get_domain_for_dev() is drm/msm's > > > domain, and it doesn't have domain->iova_cookie. > > > > Does this crash still happen with 4.20-rc? Because as of 6af588fed391 it > > really shouldn't. > > > > > We kind of avoided this problem prior to sdm845/dpu because the iommu > > > was attached to the mdp node in dt, which is a child of the toplevel > > > mdss node (which corresponds to the dev passed in dma_map_sg()). But > > > with sdm845, now the iommu is attached at the mdss level so we hit the > > > iommu_dma_ops in dma_map_sg(). > > > > > > But auto allocating/attaching a domain before the driver is probed was > > > already a blocking problem for enabling per-context pagetables for the > > > GPU. This problem is also now solved with this patch. > > > > s/solved/worked around/ > > > > If you want a guarantee of actually getting a specific hardware context > > allocated for a given domain, there needs to be code in the IOMMU driver > > to understand and honour that. Implicitly depending on whatever happens > > to fall out of current driver behaviour on current systems is not a real > > solution. > > > > > Fixes: 97890ba9289c dma-mapping: detect and configure IOMMU in > > > of_dma_configure > > > > That's rather misleading, since the crash described above depends on at > > least two other major changes which came long after that commit. > > > > It's not that I don't understand exactly what you want here - just that > > this commit message isn't a coherent justification for that ;) > > > > > Tested-by: Douglas Anderson > > > Signed-off-by: Rob Clark > > > --- > > > This is an alternative/replacement for [1]. What it lacks in elegance > > > it makes up for in practicality ;-) > > > > > > [1]
[Freedreno] [PATCH v19 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2
Add bindings doc for Qcom's smmu-v2 implementation. Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Rob Herring Reviewed-by: Robin Murphy --- Changes since v18: None. .../devicetree/bindings/iommu/arm,smmu.txt | 39 ++ 1 file changed, 39 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..a6504b37cc21 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,10 +17,16 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. + Qcom SoCs must contain, as below, SoC-specific compatibles + along with "qcom,smmu-v2": + "qcom,msm8996-smmu-v2", "qcom,smmu-v2", + "qcom,sdm845-smmu-v2", "qcom,smmu-v2". + - reg : Base address and size of the SMMU. - #global-interrupts : The number of global interrupts exposed by the @@ -71,6 +77,22 @@ conditions. or using stream matching with #iommu-cells = <2>, and may be ignored if present in such cases. +- clock-names:List of the names of clocks input to the device. The + required list depends on particular implementation and + is as follows: + - for "qcom,smmu-v2": +- "bus": clock required for downstream bus access and + for the smmu ptw, +- "iface": clock required to access smmu's registers + through the TCU's programming interface. + - unspecified for other implementations. + +- clocks: Specifiers for all clocks listed in the clock-names property, + as per generic clock bindings. + +- power-domains: Specifiers for power domains required to be powered on for + the SMMU to operate, as per generic power domain bindings. + ** Deprecated properties: - mmu-masters (deprecated in favour of the generic "iommus" binding) : @@ -137,3 +159,20 @@ conditions. iommu-map = <0 0 0x400>; ... }; + + /* Qcom's arm,smmu-v2 implementation */ + smmu4: iommu@d0 { + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; + reg = <0xd0 0x1>; + + #global-interrupts = <1>; + interrupts = , +, +; + #iommu-cells = <1>; + power-domains = < MDSS_GDSC>; + + clocks = < SMMU_MDP_AXI_CLK>, +< SMMU_MDP_AHB_CLK>; + clock-names = "bus", "iface"; + }; -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v19 3/5] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- Changes since v18: None. drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 1917d214c4d9..b6b11642b3a9 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1500,6 +1500,9 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER); + return 0; out_cfg_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v19 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. On msm8996, multiple cores, viz. mdss, video, etc. use this smmu. On sdm845, this smmu is used with gpu. Add bindings for the same. Signed-off-by: Vivek Gautam Reviewed-by: Rob Herring Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- Changes since v18: None. drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index b6b11642b3a9..ba18d89d4732 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -120,6 +120,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -2030,6 +2031,7 @@ ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2); static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, @@ -2038,6 +2040,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-401", .data = _mmu401 }, { .compatible = "arm,mmu-500", .data = _mmu500 }, { .compatible = "cavium,smmu-v2", .data = _smmuv2 }, + { .compatible = "qcom,smmu-v2", .data = _smmuv2 }, { }, }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v19 2/5] iommu/arm-smmu: Invoke pm_runtime across the driver
From: Sricharan R Enable pm-runtime on devices that implement a pm domain. Then, add pm runtime hooks to several iommu_ops to power cycle the smmu device for explicit TLB invalidation requests, and register space accesses, etc. We need these hooks when the smmu, linked to its master through device links, has to be powered-up without the master device being in context. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- Changes since v18: None. drivers/iommu/arm-smmu.c | 108 ++- 1 file changed, 98 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 602b67d4f2d6..1917d214c4d9 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -270,6 +270,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + return pm_runtime_get_sync(smmu->dev); + + return 0; +} + +static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_put(smmu->dev); +} + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -929,11 +943,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -948,6 +966,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + arm_smmu_rpm_put(smmu); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1229,10 +1249,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; smmu = fwspec_smmu(fwspec); + + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return ret; + /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); if (ret < 0) - return ret; + goto rpm_put; /* * Sanity check the domain. We don't support domains across @@ -1242,49 +1267,74 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); - return -EINVAL; + ret = -EINVAL; + goto rpm_put; } /* Looks ok, so add the device to the domain */ - return arm_smmu_domain_add_master(smmu_domain, fwspec); + ret = arm_smmu_domain_add_master(smmu_domain, fwspec); + +rpm_put: + arm_smmu_rpm_put(smmu); + return ret; } static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + int ret; if (!ops) return -ENODEV; - return ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_get(smmu); + ret = ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_put(smmu); + + return ret; } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + size_t ret; if (!ops) return 0; - return ops->unmap(ops, iova, size); + arm_smmu_rpm_get(smmu); + ret = ops->unmap(ops, iova, size); + arm_smmu_rpm_put(smmu); + + return ret; } static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + struct arm_smmu_device *smmu = smmu_domain->smmu; - if (smmu_domain->tlb_ops) + if (smm
[Freedreno] [PATCH v19 0/5] iommu/arm-smmu: Add runtime pm/sleep support
Changes since v18: - Addressing Stephen's comment [5]: Replaced the entire clock bulk data filling and handling with devm_clk_bulk_get_all(). Changes since v17: - Addressing Will's comment to embed Thor's change [2] for pulling clocks information from device tree. This is done by squashing Thor's change [2] in v17's 1/5 patch [3]. - Another minor change is addition of runtime pm hooks to arm_smmu_iova_to_phys_hard(). Previous version of this patch series is @ [1]. Also refer to [4] for change logs for previous versions. [1] https://lore.kernel.org/patchwork/cover/1017699/ [2] https://lore.kernel.org/patchwork/patch/996143/ [3] https://lore.kernel.org/patchwork/patch/1013167/ [4] https://lore.kernel.org/patchwork/cover/979429/ [5] https://lore.kernel.org/patchwork/patch/1017700/ Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (2): dt-bindings: arm-smmu: Add bindings for qcom,smmu-v2 iommu/arm-smmu: Add support for qcom,smmu-v2 variant .../devicetree/bindings/iommu/arm,smmu.txt | 39 + drivers/iommu/arm-smmu.c | 170 +++-- 2 files changed, 197 insertions(+), 12 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v18 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
On Fri, Nov 30, 2018 at 11:45 PM Will Deacon wrote: > > On Thu, Nov 29, 2018 at 08:25:20PM +0530, Vivek Gautam wrote: > > On Wed, Nov 28, 2018 at 10:07 PM Robin Murphy wrote: > > > > > > On 28/11/2018 16:24, Stephen Boyd wrote: > > > > Quoting Vivek Gautam (2018-11-27 02:11:41) > > > >> @@ -1966,6 +1970,23 @@ static const struct of_device_id > > > >> arm_smmu_of_match[] = { > > > >> }; > > > >> MODULE_DEVICE_TABLE(of, arm_smmu_of_match); > > > >> > > > >> +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, > > > >> + const char * const *clks) > > > >> +{ > > > >> + int i; > > > >> + > > > >> + if (smmu->num_clks < 1) > > > >> + return; > > > >> + > > > >> + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, > > > >> + sizeof(*smmu->clks), GFP_KERNEL); > > > >> + if (!smmu->clks) > > > >> + return; > > > >> + > > > >> + for (i = 0; i < smmu->num_clks; i++) > > > >> + smmu->clks[i].id = clks[i]; > > > > > > > > Is this clk_bulk_get_all()? > > > > From what I remember, and now I could go back to v7 and check [1], we parked > > clk_bulk_get out of OF's sole purview as we also have > > arm_smmu_device_acpi_probe() besides arm_smmu_device_dt_probe(). > > > > arm_smmu_device_dt_probe() could get the clocks from dt and fill in > > the clock bulk data, and > > similarly, arm_smmu_device_acpi_probe() could fill the clock bulk data > > by getting it from ACPI. > > > > clk_bulk_get_all() seems like going only the OF way. > > Is there another way here to have something common between ACPI > > and OF, and then do the clk_bulk_get? > > I'd say just go with clk_bulk_get_all() and if somebody really wants to > mess with the SMMU clocks on a system booted via ACPI, then it's their > problem to solve. My understanding is that the design of IORT makes this > next to impossible to solve anyway, because a static table is used and > therefore we're unable to run whatever ASL methods need to be invoked to > mess with the clocks. Sure then. I will respin this patch-series. > > Will -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v18 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
On Wed, Nov 28, 2018 at 10:07 PM Robin Murphy wrote: > > On 28/11/2018 16:24, Stephen Boyd wrote: > > Quoting Vivek Gautam (2018-11-27 02:11:41) > >> @@ -1966,6 +1970,23 @@ static const struct of_device_id > >> arm_smmu_of_match[] = { > >> }; > >> MODULE_DEVICE_TABLE(of, arm_smmu_of_match); > >> > >> +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, > >> + const char * const *clks) > >> +{ > >> + int i; > >> + > >> + if (smmu->num_clks < 1) > >> + return; > >> + > >> + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, > >> + sizeof(*smmu->clks), GFP_KERNEL); > >> + if (!smmu->clks) > >> + return; > >> + > >> + for (i = 0; i < smmu->num_clks; i++) > >> + smmu->clks[i].id = clks[i]; > > > > Is this clk_bulk_get_all()? From what I remember, and now I could go back to v7 and check [1], we parked clk_bulk_get out of OF's sole purview as we also have arm_smmu_device_acpi_probe() besides arm_smmu_device_dt_probe(). arm_smmu_device_dt_probe() could get the clocks from dt and fill in the clock bulk data, and similarly, arm_smmu_device_acpi_probe() could fill the clock bulk data by getting it from ACPI. clk_bulk_get_all() seems like going only the OF way. Is there another way here to have something common between ACPI and OF, and then do the clk_bulk_get? [1] https://lore.kernel.org/patchwork/patch/881365/ Thanks & regards Vivek > > Ooh, did that finally get merged while we weren't looking? Great! > > Much as I don't want to drag this series out to a v19, it *would* be > neat if we no longer need to open-code that bit... > > Robin. > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v3 1/1] drm: msm: Replace dma_map_sg with dma_sync_sg*
dma_map_sg() expects a DMA domain. However, the drm devices have been traditionally using unmanaged iommu domain which is non-dma type. Using dma mapping APIs with that domain is bad. Replace dma_map_sg() calls with dma_sync_sg_for_device{|cpu}() to do the cache maintenance. Signed-off-by: Vivek Gautam Suggested-by: Tomasz Figa Cc: Rob Clark Cc: Christoph Hellwig Cc: Robin Murphy Cc: Jordan Crouse Cc: Sean Paul --- Changes since v2: - Addressed Tomasz's comment to keep DMA_BIDIRECTIONAL dma direction flag intact. - Updated comment for sg's dma-address assignment as per Tomasz' suggestion. drivers/gpu/drm/msm/msm_gem.c | 33 - 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 00c795ced02c..7048e9fe00c6 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -81,6 +81,8 @@ static struct page **get_pages(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct page **p; int npages = obj->size >> PAGE_SHIFT; + struct scatterlist *s; + int i; if (use_pages(obj)) p = drm_gem_get_pages(obj); @@ -104,12 +106,23 @@ static struct page **get_pages(struct drm_gem_object *obj) return ptr; } - /* For non-cached buffers, ensure the new pages are clean + /* +* Some implementations of the DMA mapping ops expect +* physical addresses of the pages to be stored as DMA +* addresses of the sglist entries. To work around it, +* set them here explicitly. +*/ + for_each_sg(msm_obj->sgt->sgl, s, msm_obj->sgt->nents, i) + sg_dma_address(s) = sg_phys(s); + + /* +* For non-cached buffers, ensure the new pages are clean * because display controller, GPU, etc. are not coherent: */ - if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_map_sg(dev->dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + if (msm_obj->flags & (MSM_BO_WC | MSM_BO_UNCACHED)) + dma_sync_sg_for_device(dev->dev, msm_obj->sgt->sgl, + msm_obj->sgt->nents, + DMA_BIDIRECTIONAL); } return msm_obj->pages; @@ -133,14 +146,16 @@ static void put_pages(struct drm_gem_object *obj) if (msm_obj->pages) { if (msm_obj->sgt) { - /* For non-cached buffers, ensure the new + /* +* For non-cached buffers, ensure the new * pages are clean because display controller, * GPU, etc. are not coherent: */ - if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, -msm_obj->sgt->nents, -DMA_BIDIRECTIONAL); + if (msm_obj->flags & (MSM_BO_WC | MSM_BO_UNCACHED)) + dma_sync_sg_for_cpu(obj->dev->dev, + msm_obj->sgt->sgl, + msm_obj->sgt->nents, + DMA_BIDIRECTIONAL); sg_free_table(msm_obj->sgt); kfree(msm_obj->sgt); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v2 1/1] drm: msm: Replace dma_map_sg with dma_sync_sg*
On Wed, Nov 28, 2018 at 6:09 PM Rob Clark wrote: > > On Wed, Nov 28, 2018 at 2:39 AM Christoph Hellwig wrote: > > > > > + /* > > > + * dma_sync_sg_*() flush the physical pages, so point > > > + * sg->dma_address to the physical ones for the right > > > behavior. > > > + */ > > > + for_each_sg(msm_obj->sgt->sgl, s, msm_obj->sgt->nents, i) > > > + sg_dma_address(s) = sg_phys(s); > > > + > > > > I'm sorry, but this is completely bogus and not acceptable. > > > > The only place that is allowed to initialize sg_dma_address is > > dma_map_sg. If the default dma ops don't work for your setup we have > > major a problem and need to fix the dma api / iommu integration instead > > of hacking around it. > > I agree that the dma/iommu integration is very problematic for drm (in > particular, gpu drivers that use the iommu as an gpu mmu).. Really we > need a way that a driver can opt-out of this, and access the cpu cache > APIs directly, skipping the dma API entirely. But as it is, we've had > to hack around the dma API. I'm not really sure this hack is any > worse than abusing dma_(un)map_sg() for doing cache operations. > > I probably should have paid more attention and nak'd the dma/iommu > integration before it landed. But given that now we are stuck in this > situation, while I'm certainly interested if anyone has some ideas > about how to let drivers opt out of the dma/iommu integration and > bypass the dma API layer, I'm ok with replacing a hack with a less-bad > hack. May I take it as a positive nod to respin the next version? Regards Vivek > > BR, > -R -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v18 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. On msm8996, multiple cores, viz. mdss, video, etc. use this smmu. On sdm845, this smmu is used with gpu. Add bindings for the same. Signed-off-by: Vivek Gautam Reviewed-by: Rob Herring Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f02e0f58e696..29ce9e10abd4 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -121,6 +121,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -2031,6 +2032,7 @@ ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2); static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, @@ -2039,6 +2041,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-401", .data = _mmu401 }, { .compatible = "arm,mmu-500", .data = _mmu500 }, { .compatible = "cavium,smmu-v2", .data = _smmuv2 }, + { .compatible = "qcom,smmu-v2", .data = _smmuv2 }, { }, }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v18 3/5] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 5610cc736f9d..f02e0f58e696 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1501,6 +1501,9 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER); + return 0; out_cfg_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v18 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Global locks are also initialized before enabling runtime pm as the runtime_resume() calls device_reset() which does tlb_sync_global() that ultimately requires locks to be initialized. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 108 ++- 1 file changed, 98 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e47c840fc6a8..5610cc736f9d 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -271,6 +271,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + return pm_runtime_get_sync(smmu->dev); + + return 0; +} + +static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_put(smmu->dev); +} + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -930,11 +944,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -949,6 +967,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + arm_smmu_rpm_put(smmu); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1230,10 +1250,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; smmu = fwspec_smmu(fwspec); + + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return ret; + /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); if (ret < 0) - return ret; + goto rpm_put; /* * Sanity check the domain. We don't support domains across @@ -1243,49 +1268,74 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); - return -EINVAL; + ret = -EINVAL; + goto rpm_put; } /* Looks ok, so add the device to the domain */ - return arm_smmu_domain_add_master(smmu_domain, fwspec); + ret = arm_smmu_domain_add_master(smmu_domain, fwspec); + +rpm_put: + arm_smmu_rpm_put(smmu); + return ret; } static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + int ret; if (!ops) return -ENODEV; - return ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_get(smmu); + ret = ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_put(smmu); + + return ret; } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + size_t ret; if (!ops) return 0; - return ops->unmap(ops, iova, size); + arm_smmu_rpm_get(smmu); + ret = ops->unmap(ops, iova, size); + arm_smmu_rpm_put(smmu); + + return ret; } static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + struct arm_smmu_device *smmu = smmu_domain->smmu; - if (smmu_domai
[Freedreno] [PATCH v18 0/5] iommu/arm-smmu: Add runtime pm/sleep support
Looks like this is going to be the final respin before this support finally lands. The change isn't much from v17_resend series [1] besides taking Thor's change [2] for clocks. Changes since v17: - Addressing Will's comment to embed Thor's change [2] for pulling clocks information from device tree. This is done by squashing Thor's change [2] in v17's 1/5 patch [3]. - Another minor change is addition of runtime pm hooks to arm_smmu_iova_to_phys_hard(). Previous version of this patch series is @ [1]. Also refer to [4] for change logs for previous versions. [1] https://lore.kernel.org/patchwork/cover/1013166/ [2] https://lore.kernel.org/patchwork/patch/996143/ [3] https://lore.kernel.org/patchwork/patch/1013167/ [4] https://lore.kernel.org/patchwork/cover/979429/ Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (2): dt-bindings: arm-smmu: Add bindings for qcom,smmu-v2 iommu/arm-smmu: Add support for qcom,smmu-v2 variant .../devicetree/bindings/iommu/arm,smmu.txt | 39 drivers/iommu/arm-smmu.c | 212 +++-- 2 files changed, 239 insertions(+), 12 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v18 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. We pull all the information about clocks from device tree. Also, while we enable the runtime pm add a pm sleep suspend callback that pushes devices to low power state by turning the clocks off in a system sleep. Also add corresponding clock enable path in resume callback. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [Thor: Rework to get clocks from device tree] Signed-off-by: Thor Thayer [vivek: rework for clock and pm ops] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 100 +-- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 5a28ae892504..e47c840fc6a8 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -44,10 +44,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -206,6 +208,8 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clks; + int num_clks; u32 cavium_id_base; /* Specific to Cavium */ @@ -1947,7 +1951,7 @@ struct arm_smmu_match_data { }; #define ARM_SMMU_MATCH_DATA(name, ver, imp)\ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -1966,6 +1970,23 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, + const char * const *clks) +{ + int i; + + if (smmu->num_clks < 1) + return; + + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, + sizeof(*smmu->clks), GFP_KERNEL); + if (!smmu->clks) + return; + + for (i = 0; i < smmu->num_clks; i++) + smmu->clks[i].id = clks[i]; +} + #ifdef CONFIG_ACPI static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) { @@ -2038,6 +2059,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, const struct arm_smmu_match_data *data; struct device *dev = >dev; bool legacy_binding; + const char **parent_names; if (of_property_read_u32(dev->of_node, "#global-interrupts", >num_global_irqs)) { @@ -2048,6 +2070,26 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->num_clks = of_clk_get_parent_count(dev->of_node); + /* check to see if clocks were specified in DT */ + if (smmu->num_clks) { + unsigned int i; + + parent_names = kmalloc_array(smmu->num_clks, +sizeof(*parent_names), +GFP_KERNEL); + if (!parent_names) + return -ENOMEM; + + for (i = 0; i < smmu->num_clks; i++) { + if (of_property_read_string_index(dev->of_node, + "clock-names", i, + _names[i])) + goto fail_clk_name; + } + arm_smmu_fill_clk_data(smmu, parent_names); + kfree(parent_names); + } parse_driver_options(smmu); @@ -2067,6 +2109,12 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK; return 0; + +fail_clk_name: + kfree(parent_names); + /* clock-names required for clocks in devm_clk_bulk_get() */ + dev_err(dev, "clock-names required in device tree\n"); + return -ENODEV;
[Freedreno] [PATCH v2 1/1] drm: msm: Replace dma_map_sg with dma_sync_sg*
dma_map_sg() expects a DMA domain. However, the drm devices have been traditionally using unmanaged iommu domain which is non-dma type. Using dma mapping APIs with that domain is bad. Replace dma_map_sg() calls with dma_sync_sg_for_device{|cpu}() to do the cache maintenance. Signed-off-by: Vivek Gautam Suggested-by: Tomasz Figa Cc: Rob Clark Cc: Jordan Crouse Cc: Sean Paul --- Changes since v1: - Addressed Jordan's and Tomasz's comments for - moving sg dma addresses preparation out of the coditional check to the main path so we do it irrespective of whether the buffer is cached or uncached. - Enhance the comment to explain this dma addresses prepartion. drivers/gpu/drm/msm/msm_gem.c | 31 ++- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 00c795ced02c..1811ac23a31c 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -81,6 +81,8 @@ static struct page **get_pages(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct page **p; int npages = obj->size >> PAGE_SHIFT; + struct scatterlist *s; + int i; if (use_pages(obj)) p = drm_gem_get_pages(obj); @@ -104,12 +106,21 @@ static struct page **get_pages(struct drm_gem_object *obj) return ptr; } - /* For non-cached buffers, ensure the new pages are clean + /* +* dma_sync_sg_*() flush the physical pages, so point +* sg->dma_address to the physical ones for the right behavior. +*/ + for_each_sg(msm_obj->sgt->sgl, s, msm_obj->sgt->nents, i) + sg_dma_address(s) = sg_phys(s); + + /* +* For non-cached buffers, ensure the new pages are clean * because display controller, GPU, etc. are not coherent: */ - if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_map_sg(dev->dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + if (msm_obj->flags & (MSM_BO_WC | MSM_BO_UNCACHED)) + dma_sync_sg_for_device(dev->dev, msm_obj->sgt->sgl, + msm_obj->sgt->nents, + DMA_TO_DEVICE); } return msm_obj->pages; @@ -133,14 +144,16 @@ static void put_pages(struct drm_gem_object *obj) if (msm_obj->pages) { if (msm_obj->sgt) { - /* For non-cached buffers, ensure the new + /* +* For non-cached buffers, ensure the new * pages are clean because display controller, * GPU, etc. are not coherent: */ - if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, -msm_obj->sgt->nents, -DMA_BIDIRECTIONAL); + if (msm_obj->flags & (MSM_BO_WC | MSM_BO_UNCACHED)) + dma_sync_sg_for_cpu(obj->dev->dev, + msm_obj->sgt->sgl, + msm_obj->sgt->nents, + DMA_FROM_DEVICE); sg_free_table(msm_obj->sgt); kfree(msm_obj->sgt); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [RESEND PATCH v17 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
Hi Thor, On 11/26/2018 8:11 PM, Thor Thayer wrote: Hi Vivek, On 11/26/18 4:55 AM, Vivek Gautam wrote: On 11/24/2018 12:04 AM, Will Deacon wrote: On Fri, Nov 23, 2018 at 03:06:29PM +0530, Vivek Gautam wrote: On Fri, Nov 23, 2018 at 2:52 PM Tomasz Figa wrote: On Fri, Nov 23, 2018 at 6:13 PM Vivek Gautam wrote: On Wed, Nov 21, 2018 at 11:09 PM Will Deacon wrote: On Fri, Nov 16, 2018 at 04:54:30PM +0530, Vivek Gautam wrote: @@ -2026,6 +2027,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; These seems redundant if we go down the route proposed by Thor, where we just pull all of the clocks out of the device-tree. In which case, why do we need this match_data at all? Which is better? Driver relying solely on the device tree to tell which all clocks are required to be enabled, or, the driver deciding itself based on the platform's match data, that it should have X, Y, & Z clocks that should be supplied from the device tree. The former would simplify the driver, but would also make it impossible to spot mistakes in DT, which would ultimately surface out as very hard to debug bugs (likely complete system lockups). Thanks. Yea, this is how I understand things presently. Relying on device tree puts the things out of driver's control. But it also has the undesirable effect of having to update the driver code whenever we want to add support for a new SMMU implementation. If we do this all in the DT, as Thor is trying to do, then older kernels will work well with new hardware. Hi Will, Am I unable to understand the intentions here for Thor's clock-fetch design change? I'm having trouble parsing your question, sorry. Please work with Thor so that we have a single way to get the clock information. My preference is to take it from the firmware, for the reason I stated above. Hi Will, Sure, thanks. I will work with Thor to get this going. Hi Thor, Does it sound okay to you to squash your patch [1] into my patch [2] with your 'Signed-off-by' tag? I will update the commit log to include the information about getting clock details from device tree. [1] https://patchwork.kernel.org/patch/10628725/ [2] https://patchwork.kernel.org/patch/10686061/ Yes, that would be great and easier to understand than my patch on top of yours. Additionally, can you remove the "Error:" as Will requested as part of the squash? Thanks for your consent. I have reworked the patch today, and have addressed Will's comment. I will give a try on the board and post it by tomorrow. Best regards Vivek Thank you! Thor Best regards Vivek Will ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [RESEND PATCH v17 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
On 11/26/2018 11:33 AM, Vivek Gautam wrote: On 11/24/2018 12:06 AM, Will Deacon wrote: On Thu, Nov 22, 2018 at 05:32:24PM +0530, Vivek Gautam wrote: Hi Will, On Wed, Nov 21, 2018 at 11:09 PM Will Deacon wrote: On Fri, Nov 16, 2018 at 04:54:27PM +0530, Vivek Gautam wrote: From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Global locks are also initialized before enabling runtime pm as the runtime_resume() calls device_reset() which does tlb_sync_global() that ultimately requires locks to be initialized. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 101 ++- 1 file changed, 91 insertions(+), 10 deletions(-) Given that you're doing the get/put in the TLBI ops unconditionally: static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + struct arm_smmu_device *smmu = smmu_domain->smmu; - if (smmu_domain->tlb_ops) + if (smmu_domain->tlb_ops) { + arm_smmu_rpm_get(smmu); smmu_domain->tlb_ops->tlb_flush_all(smmu_domain); + arm_smmu_rpm_put(smmu); + } } static void arm_smmu_iotlb_sync(struct iommu_domain *domain) { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + struct arm_smmu_device *smmu = smmu_domain->smmu; - if (smmu_domain->tlb_ops) + if (smmu_domain->tlb_ops) { + arm_smmu_rpm_get(smmu); smmu_domain->tlb_ops->tlb_sync(smmu_domain); + arm_smmu_rpm_put(smmu); + } Why do you need them around the map/unmap calls as well? We still have .tlb_add_flush path? Ok, so we could add the ops around that as well. Right now, we've got the runtime pm hooks crossing two parts of the API. Sure, will do that then, and remove the runtime pm hooks from map/unmap. I missed this earlier - We are adding runtime pm hooks in the 'iommu_ops' callbacks and not really to 'tlb_ops'. So how the runtime pm hooks crossing the paths? '.map/.unmap' iommu_ops don't call '.flush_iotlb_all' or '.iotlb_sync' iommu_ops anywhere. E.g., only callers to domain->ops->flush_iotlb_all() are: iommu_dma_flush_iotlb_all(), or iommu_flush_tlb_all() which are not in map/unmap paths. Regards Vivek Thanks Vivek Will ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [RESEND PATCH v17 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
On 11/24/2018 12:04 AM, Will Deacon wrote: On Fri, Nov 23, 2018 at 03:06:29PM +0530, Vivek Gautam wrote: On Fri, Nov 23, 2018 at 2:52 PM Tomasz Figa wrote: On Fri, Nov 23, 2018 at 6:13 PM Vivek Gautam wrote: On Wed, Nov 21, 2018 at 11:09 PM Will Deacon wrote: On Fri, Nov 16, 2018 at 04:54:30PM +0530, Vivek Gautam wrote: @@ -2026,6 +2027,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; These seems redundant if we go down the route proposed by Thor, where we just pull all of the clocks out of the device-tree. In which case, why do we need this match_data at all? Which is better? Driver relying solely on the device tree to tell which all clocks are required to be enabled, or, the driver deciding itself based on the platform's match data, that it should have X, Y, & Z clocks that should be supplied from the device tree. The former would simplify the driver, but would also make it impossible to spot mistakes in DT, which would ultimately surface out as very hard to debug bugs (likely complete system lockups). Thanks. Yea, this is how I understand things presently. Relying on device tree puts the things out of driver's control. But it also has the undesirable effect of having to update the driver code whenever we want to add support for a new SMMU implementation. If we do this all in the DT, as Thor is trying to do, then older kernels will work well with new hardware. Hi Will, Am I unable to understand the intentions here for Thor's clock-fetch design change? I'm having trouble parsing your question, sorry. Please work with Thor so that we have a single way to get the clock information. My preference is to take it from the firmware, for the reason I stated above. Hi Will, Sure, thanks. I will work with Thor to get this going. Hi Thor, Does it sound okay to you to squash your patch [1] into my patch [2] with your 'Signed-off-by' tag? I will update the commit log to include the information about getting clock details from device tree. [1] https://patchwork.kernel.org/patch/10628725/ [2] https://patchwork.kernel.org/patch/10686061/ Best regards Vivek Will ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [RESEND PATCH v17 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
Hi Tomasz, On Fri, Nov 23, 2018 at 2:52 PM Tomasz Figa wrote: > > Hi Vivek, Will, > > On Fri, Nov 23, 2018 at 6:13 PM Vivek Gautam > wrote: > > > > Hi Will, > > > > On Wed, Nov 21, 2018 at 11:09 PM Will Deacon wrote: > > > > > > [+Thor] > > > > > > On Fri, Nov 16, 2018 at 04:54:30PM +0530, Vivek Gautam wrote: > > > > qcom,smmu-v2 is an arm,smmu-v2 implementation with specific > > > > clock and power requirements. > > > > On msm8996, multiple cores, viz. mdss, video, etc. use this > > > > smmu. On sdm845, this smmu is used with gpu. > > > > Add bindings for the same. > > > > > > > > Signed-off-by: Vivek Gautam > > > > Reviewed-by: Rob Herring > > > > Reviewed-by: Tomasz Figa > > > > Tested-by: Srinivas Kandagatla > > > > Reviewed-by: Robin Murphy > > > > --- > > > > drivers/iommu/arm-smmu.c | 13 + > > > > 1 file changed, 13 insertions(+) > > > > > > > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > > > index 2098c3141f5f..d315ca637097 100644 > > > > --- a/drivers/iommu/arm-smmu.c > > > > +++ b/drivers/iommu/arm-smmu.c > > > > @@ -120,6 +120,7 @@ enum arm_smmu_implementation { > > > > GENERIC_SMMU, > > > > ARM_MMU500, > > > > CAVIUM_SMMUV2, > > > > + QCOM_SMMUV2, > > > > }; > > > > > > > > struct arm_smmu_s2cr { > > > > @@ -2026,6 +2027,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, > > > > GENERIC_SMMU); > > > > ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); > > > > ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); > > > > > > > > +static const char * const qcom_smmuv2_clks[] = { > > > > + "bus", "iface", > > > > +}; > > > > + > > > > +static const struct arm_smmu_match_data qcom_smmuv2 = { > > > > + .version = ARM_SMMU_V2, > > > > + .model = QCOM_SMMUV2, > > > > + .clks = qcom_smmuv2_clks, > > > > + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), > > > > +}; > > > > > > These seems redundant if we go down the route proposed by Thor, where we > > > just pull all of the clocks out of the device-tree. In which case, why > > > do we need this match_data at all? > > > > Which is better? Driver relying solely on the device tree to tell > > which all clocks > > are required to be enabled, > > or, the driver deciding itself based on the platform's match data, > > that it should > > have X, Y, & Z clocks that should be supplied from the device tree. > > The former would simplify the driver, but would also make it > impossible to spot mistakes in DT, which would ultimately surface out > as very hard to debug bugs (likely complete system lockups). Thanks. Yea, this is how I understand things presently. Relying on device tree puts the things out of driver's control. Hi Will, Am I unable to understand the intentions here for Thor's clock-fetch design change? > > For qcom_smmuv2, I believe we're eventually going to end up with > platform-specific quirks anyway, so specifying the clocks too wouldn't > hurt. Given that, I'd recommend sticking to the latter, i.e. what this > patch does. > > Best regards, > Tomasz Best regards Vivek > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [RESEND PATCH v17 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
Hi Will, On Wed, Nov 21, 2018 at 11:09 PM Will Deacon wrote: > > [+Thor] > > On Fri, Nov 16, 2018 at 04:54:30PM +0530, Vivek Gautam wrote: > > qcom,smmu-v2 is an arm,smmu-v2 implementation with specific > > clock and power requirements. > > On msm8996, multiple cores, viz. mdss, video, etc. use this > > smmu. On sdm845, this smmu is used with gpu. > > Add bindings for the same. > > > > Signed-off-by: Vivek Gautam > > Reviewed-by: Rob Herring > > Reviewed-by: Tomasz Figa > > Tested-by: Srinivas Kandagatla > > Reviewed-by: Robin Murphy > > --- > > drivers/iommu/arm-smmu.c | 13 + > > 1 file changed, 13 insertions(+) > > > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > index 2098c3141f5f..d315ca637097 100644 > > --- a/drivers/iommu/arm-smmu.c > > +++ b/drivers/iommu/arm-smmu.c > > @@ -120,6 +120,7 @@ enum arm_smmu_implementation { > > GENERIC_SMMU, > > ARM_MMU500, > > CAVIUM_SMMUV2, > > + QCOM_SMMUV2, > > }; > > > > struct arm_smmu_s2cr { > > @@ -2026,6 +2027,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, > > GENERIC_SMMU); > > ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); > > ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); > > > > +static const char * const qcom_smmuv2_clks[] = { > > + "bus", "iface", > > +}; > > + > > +static const struct arm_smmu_match_data qcom_smmuv2 = { > > + .version = ARM_SMMU_V2, > > + .model = QCOM_SMMUV2, > > + .clks = qcom_smmuv2_clks, > > + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), > > +}; > > These seems redundant if we go down the route proposed by Thor, where we > just pull all of the clocks out of the device-tree. In which case, why > do we need this match_data at all? Which is better? Driver relying solely on the device tree to tell which all clocks are required to be enabled, or, the driver deciding itself based on the platform's match data, that it should have X, Y, & Z clocks that should be supplied from the device tree. Thanks Vivek > > Will > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [RESEND PATCH v17 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
Hi Will, On Wed, Nov 21, 2018 at 11:09 PM Will Deacon wrote: > > On Fri, Nov 16, 2018 at 04:54:27PM +0530, Vivek Gautam wrote: > > From: Sricharan R > > > > The smmu device probe/remove and add/remove master device callbacks > > gets called when the smmu is not linked to its master, that is without > > the context of the master device. So calling runtime apis in those places > > separately. > > Global locks are also initialized before enabling runtime pm as the > > runtime_resume() calls device_reset() which does tlb_sync_global() > > that ultimately requires locks to be initialized. > > > > Signed-off-by: Sricharan R > > [vivek: Cleanup pm runtime calls] > > Signed-off-by: Vivek Gautam > > Reviewed-by: Tomasz Figa > > Tested-by: Srinivas Kandagatla > > Reviewed-by: Robin Murphy > > --- > > drivers/iommu/arm-smmu.c | 101 > > ++- > > 1 file changed, 91 insertions(+), 10 deletions(-) > > Given that you're doing the get/put in the TLBI ops unconditionally: > > > static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) > > { > > struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); > > + struct arm_smmu_device *smmu = smmu_domain->smmu; > > > > - if (smmu_domain->tlb_ops) > > + if (smmu_domain->tlb_ops) { > > + arm_smmu_rpm_get(smmu); > > smmu_domain->tlb_ops->tlb_flush_all(smmu_domain); > > + arm_smmu_rpm_put(smmu); > > + } > > } > > > > static void arm_smmu_iotlb_sync(struct iommu_domain *domain) > > { > > struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); > > + struct arm_smmu_device *smmu = smmu_domain->smmu; > > > > - if (smmu_domain->tlb_ops) > > + if (smmu_domain->tlb_ops) { > > + arm_smmu_rpm_get(smmu); > > smmu_domain->tlb_ops->tlb_sync(smmu_domain); > > + arm_smmu_rpm_put(smmu); > > + } > > Why do you need them around the map/unmap calls as well? We still have .tlb_add_flush path? Thanks Vivek > > Will > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH 1/1] drm: msm: Replace dma_map_sg with dma_sync_sg*
Hi Tomasz, Jordan, On 11/21/2018 9:18 AM, Tomasz Figa wrote: Hi Jordan, Vivek, On Wed, Nov 21, 2018 at 12:41 AM Jordan Crouse wrote: On Tue, Nov 20, 2018 at 03:24:37PM +0530, Vivek Gautam wrote: dma_map_sg() expects a DMA domain. However, the drm devices have been traditionally using unmanaged iommu domain which is non-dma type. Using dma mapping APIs with that domain is bad. Replace dma_map_sg() calls with dma_sync_sg_for_device{|cpu}() to do the cache maintenance. Signed-off-by: Vivek Gautam Suggested-by: Tomasz Figa --- Tested on an MTP sdm845: https://github.com/vivekgautam1/linux/tree/v4.19/sdm845-mtp-display-working drivers/gpu/drm/msm/msm_gem.c | 27 --- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 00c795ced02c..d7a7af610803 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -81,6 +81,8 @@ static struct page **get_pages(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct page **p; int npages = obj->size >> PAGE_SHIFT; + struct scatterlist *s; + int i; if (use_pages(obj)) p = drm_gem_get_pages(obj); @@ -107,9 +109,19 @@ static struct page **get_pages(struct drm_gem_object *obj) /* For non-cached buffers, ensure the new pages are clean * because display controller, GPU, etc. are not coherent: */ - if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_map_sg(dev->dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + if (msm_obj->flags & (MSM_BO_WC | MSM_BO_UNCACHED)) { + /* + * Fake up the SG table so that dma_sync_sg_*() + * can be used to flush the pages associated with it. + */ We aren't really faking. The table is real, we are just slightly abusing the sg_dma_address() which makes this comment a bit misleading. Instead I would probably say something like: /* dma_sync_sg_* flushes pages using sg_dma_address() so point it at the * physical page for the right behavior */ Or something like that. It's actually quite complicated, but I agree that the comment isn't very precise. The cases are as follows: - arm64 iommu_dma_ops use sg_phys() https://elixir.bootlin.com/linux/v4.20-rc3/source/arch/arm64/mm/dma-mapping.c#L599 - swiotlb_dma_ops used on arm64 if no IOMMU is available use sg->dma_address directly: https://elixir.bootlin.com/linux/v4.20-rc3/source/kernel/dma/swiotlb.c#L832 - arm_dma_ops use sg_dma_address(): https://elixir.bootlin.com/linux/v4.20-rc3/source/arch/arm/mm/dma-mapping.c#L1130 - arm iommu_ops use sg_page(): https://elixir.bootlin.com/linux/v4.20-rc3/source/arch/arm/mm/dma-mapping.c#L1869 Sounds like a mess... Thanks for the review. Technically with the below assignment we address all of the above. How about an even simpler version of the suggested comment: /* dma_sync_sg_* flushes physical pages, so point sg->dma_address to * the physical one for the right behavior. */ + for_each_sg(msm_obj->sgt->sgl, s, + msm_obj->sgt->nents, i) + sg_dma_address(s) = sg_phys(s); + I'm wondering - wouldn't we want to do this association for cached buffers to so we could sync them correctly in cpu_prep and cpu_fini? Maybe it wouldn't hurt to put this association in the main path (obviously the sync should stay inside the conditional for uncached buffers). Sure, I will move this out of the conditional check. I guess it wouldn't hurt indeed. Note that cpu_prep/fini seem to be missing the sync call currently. I can't say I understand the usage of cpu_prep and cpu_fini(). But I can add the necessary support if you can point me in the right direction. Thanks Best regards Vivek P.S. Jordan, not sure if it's my Gmail or your email client, but your message had all the recipients in a Reply-to header, except you, so pressing Reply to all in my case led to a message that didn't have you in recipients anymore... Best regards, Tomasz ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH 1/1] drm: msm: Replace dma_map_sg with dma_sync_sg*
dma_map_sg() expects a DMA domain. However, the drm devices have been traditionally using unmanaged iommu domain which is non-dma type. Using dma mapping APIs with that domain is bad. Replace dma_map_sg() calls with dma_sync_sg_for_device{|cpu}() to do the cache maintenance. Signed-off-by: Vivek Gautam Suggested-by: Tomasz Figa --- Tested on an MTP sdm845: https://github.com/vivekgautam1/linux/tree/v4.19/sdm845-mtp-display-working drivers/gpu/drm/msm/msm_gem.c | 27 --- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 00c795ced02c..d7a7af610803 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -81,6 +81,8 @@ static struct page **get_pages(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct page **p; int npages = obj->size >> PAGE_SHIFT; + struct scatterlist *s; + int i; if (use_pages(obj)) p = drm_gem_get_pages(obj); @@ -107,9 +109,19 @@ static struct page **get_pages(struct drm_gem_object *obj) /* For non-cached buffers, ensure the new pages are clean * because display controller, GPU, etc. are not coherent: */ - if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_map_sg(dev->dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + if (msm_obj->flags & (MSM_BO_WC | MSM_BO_UNCACHED)) { + /* +* Fake up the SG table so that dma_sync_sg_*() +* can be used to flush the pages associated with it. +*/ + for_each_sg(msm_obj->sgt->sgl, s, + msm_obj->sgt->nents, i) + sg_dma_address(s) = sg_phys(s); + + dma_sync_sg_for_device(dev->dev, msm_obj->sgt->sgl, + msm_obj->sgt->nents, + DMA_TO_DEVICE); + } } return msm_obj->pages; @@ -137,10 +149,11 @@ static void put_pages(struct drm_gem_object *obj) * pages are clean because display controller, * GPU, etc. are not coherent: */ - if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, -msm_obj->sgt->nents, -DMA_BIDIRECTIONAL); + if (msm_obj->flags & (MSM_BO_WC | MSM_BO_UNCACHED)) + dma_sync_sg_for_cpu(obj->dev->dev, + msm_obj->sgt->sgl, + msm_obj->sgt->nents, + DMA_FROM_DEVICE); sg_free_table(msm_obj->sgt); kfree(msm_obj->sgt); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [RESEND PATCH v17 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. On msm8996, multiple cores, viz. mdss, video, etc. use this smmu. On sdm845, this smmu is used with gpu. Add bindings for the same. Signed-off-by: Vivek Gautam Reviewed-by: Rob Herring Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 2098c3141f5f..d315ca637097 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -120,6 +120,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -2026,6 +2027,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; + static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, { .compatible = "arm,smmu-v2", .data = _generic_v2 }, @@ -2033,6 +2045,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-401", .data = _mmu401 }, { .compatible = "arm,mmu-500", .data = _mmu500 }, { .compatible = "cavium,smmu-v2", .data = _smmuv2 }, + { .compatible = "qcom,smmu-v2", .data = _smmuv2 }, { }, }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [RESEND PATCH v17 3/5] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index cae88c9f83ca..2098c3141f5f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1493,6 +1493,9 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER); + return 0; out_cfg_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [RESEND PATCH v17 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2
Add bindings doc for Qcom's smmu-v2 implementation. Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Rob Herring Reviewed-by: Robin Murphy --- .../devicetree/bindings/iommu/arm,smmu.txt | 39 ++ 1 file changed, 39 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..a6504b37cc21 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,10 +17,16 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. + Qcom SoCs must contain, as below, SoC-specific compatibles + along with "qcom,smmu-v2": + "qcom,msm8996-smmu-v2", "qcom,smmu-v2", + "qcom,sdm845-smmu-v2", "qcom,smmu-v2". + - reg : Base address and size of the SMMU. - #global-interrupts : The number of global interrupts exposed by the @@ -71,6 +77,22 @@ conditions. or using stream matching with #iommu-cells = <2>, and may be ignored if present in such cases. +- clock-names:List of the names of clocks input to the device. The + required list depends on particular implementation and + is as follows: + - for "qcom,smmu-v2": +- "bus": clock required for downstream bus access and + for the smmu ptw, +- "iface": clock required to access smmu's registers + through the TCU's programming interface. + - unspecified for other implementations. + +- clocks: Specifiers for all clocks listed in the clock-names property, + as per generic clock bindings. + +- power-domains: Specifiers for power domains required to be powered on for + the SMMU to operate, as per generic power domain bindings. + ** Deprecated properties: - mmu-masters (deprecated in favour of the generic "iommus" binding) : @@ -137,3 +159,20 @@ conditions. iommu-map = <0 0 0x400>; ... }; + + /* Qcom's arm,smmu-v2 implementation */ + smmu4: iommu@d0 { + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; + reg = <0xd0 0x1>; + + #global-interrupts = <1>; + interrupts = , +, +; + #iommu-cells = <1>; + power-domains = < MDSS_GDSC>; + + clocks = < SMMU_MDP_AXI_CLK>, +< SMMU_MDP_AHB_CLK>; + clock-names = "bus", "iface"; + }; -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [RESEND PATCH v17 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Global locks are also initialized before enabling runtime pm as the runtime_resume() calls device_reset() which does tlb_sync_global() that ultimately requires locks to be initialized. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 101 ++- 1 file changed, 91 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f7ab7ce87a94..cae88c9f83ca 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -270,6 +270,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + return pm_runtime_get_sync(smmu->dev); + + return 0; +} + +static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_put(smmu->dev); +} + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -929,11 +943,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -948,6 +966,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + arm_smmu_rpm_put(smmu); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1229,10 +1249,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; smmu = fwspec_smmu(fwspec); + + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return ret; + /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); if (ret < 0) - return ret; + goto rpm_put; /* * Sanity check the domain. We don't support domains across @@ -1242,49 +1267,74 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); - return -EINVAL; + ret = -EINVAL; + goto rpm_put; } /* Looks ok, so add the device to the domain */ - return arm_smmu_domain_add_master(smmu_domain, fwspec); + ret = arm_smmu_domain_add_master(smmu_domain, fwspec); + +rpm_put: + arm_smmu_rpm_put(smmu); + return ret; } static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + int ret; if (!ops) return -ENODEV; - return ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_get(smmu); + ret = ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_put(smmu); + + return ret; } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + size_t ret; if (!ops) return 0; - return ops->unmap(ops, iova, size); + arm_smmu_rpm_get(smmu); + ret = ops->unmap(ops, iova, size); + arm_smmu_rpm_put(smmu); + + return ret; } static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + struct arm_smmu_device *smmu = smmu_domain->smmu; - if (smmu_domai
[Freedreno] [RESEND PATCH v17 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Also, while we enable the runtime pm add a pm sleep suspend callback that pushes devices to low power state by turning the clocks off in a system sleep. Also add corresponding clock enable path in resume callback. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: rework for clock and pm ops] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- drivers/iommu/arm-smmu.c | 77 ++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 5a28ae892504..f7ab7ce87a94 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -206,6 +207,8 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clks; + int num_clks; u32 cavium_id_base; /* Specific to Cavium */ @@ -1944,10 +1947,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) struct arm_smmu_match_data { enum arm_smmu_arch_version version; enum arm_smmu_implementation model; + const char * const *clks; + int num_clks; }; #define ARM_SMMU_MATCH_DATA(name, ver, imp)\ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -1966,6 +1971,23 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, + const char * const *clks) +{ + int i; + + if (smmu->num_clks < 1) + return; + + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, + sizeof(*smmu->clks), GFP_KERNEL); + if (!smmu->clks) + return; + + for (i = 0; i < smmu->num_clks; i++) + smmu->clks[i].id = clks[i]; +} + #ifdef CONFIG_ACPI static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) { @@ -2048,6 +2070,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->num_clks = data->num_clks; + + arm_smmu_fill_clk_data(smmu, data->clks); parse_driver_options(smmu); @@ -2150,6 +2175,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); + if (err) + return err; + + err = clk_bulk_prepare_enable(smmu->num_clks, smmu->clks); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2236,6 +2269,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + + clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); + return 0; } @@ -2244,15 +2280,50 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) arm_smmu_device_remove(pdev); } -static int __maybe_unused arm_smmu_pm_resume(struct device *dev) +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) { struct arm_smmu_device *smmu = dev_get_drvdata(dev); + int ret; + + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); + if (ret) + return ret; arm_smmu_device_reset(smmu); + return 0; } -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + clk_bulk_disable(smmu->num_clks, smmu->clks); +
[Freedreno] [RESEND PATCH v17 0/5] iommu/arm-smmu: Add runtime pm/sleep support
Hi Will, I am resending this series after we concluded on comments [1,2] on v16 of this patch-series, and the subsequent patch [3] was posted. Kindly merge this series. Thanks Vivek Previous version of this patch series is @ [4]. Also refer to [4] for change logs for previous versions. [1] https://lore.kernel.org/patchwork/patch/979430/ [2] https://lore.kernel.org/patchwork/patch/979433/ [3] https://lore.kernel.org/patchwork/patch/994194/ [4] https://lore.kernel.org/patchwork/cover/979429/ Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (2): dt-bindings: arm-smmu: Add bindings for qcom,smmu-v2 iommu/arm-smmu: Add support for qcom,smmu-v2 variant .../devicetree/bindings/iommu/arm,smmu.txt | 39 + drivers/iommu/arm-smmu.c | 192 +++-- 2 files changed, 219 insertions(+), 12 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v17 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Global locks are also initialized before enabling runtime pm as the runtime_resume() calls device_reset() which does tlb_sync_global() that ultimately requires locks to be initialized. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla Reviewed-by: Robin Murphy --- Changes since v16: - Rebased on Will's tree for arm-smmu updates [1]. - Added rpm{get|put} calls to .flush_iotlb_all, and .iotlb_sync callbacks to take care of non-strict tlb flush queue updates. drivers/iommu/arm-smmu.c | 101 ++- 1 file changed, 91 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 59d1430a9f2d..bf106688ab7a 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -269,6 +269,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + return pm_runtime_get_sync(smmu->dev); + + return 0; +} + +static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_put(smmu->dev); +} + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -928,11 +942,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -947,6 +965,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + arm_smmu_rpm_put(smmu); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1228,10 +1248,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; smmu = fwspec_smmu(fwspec); + + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return ret; + /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); if (ret < 0) - return ret; + goto rpm_put; /* * Sanity check the domain. We don't support domains across @@ -1241,49 +1266,74 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); - return -EINVAL; + ret = -EINVAL; + goto rpm_put; } /* Looks ok, so add the device to the domain */ - return arm_smmu_domain_add_master(smmu_domain, fwspec); + ret = arm_smmu_domain_add_master(smmu_domain, fwspec); + +rpm_put: + arm_smmu_rpm_put(smmu); + return ret; } static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + int ret; if (!ops) return -ENODEV; - return ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_get(smmu); + ret = ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_put(smmu); + + return ret; } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + size_t ret; if (!ops) return 0; - return ops->unmap(ops, iova, size); + arm_smmu_rpm_get(smmu); + ret = ops->unmap(ops, iova, size); + arm_smmu_rpm_put(smmu); + + return ret; } static void arm_s
Re: [Freedreno] [PATCH v16 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
On Tue, Oct 2, 2018 at 9:44 AM Vivek Gautam wrote: > > Hi Will, > > On Mon, Oct 1, 2018 at 6:29 PM Will Deacon wrote: > > > > Hi Vivek, > > > > On Thu, Aug 30, 2018 at 08:15:38PM +0530, Vivek Gautam wrote: > > > From: Sricharan R > > > > > > The smmu device probe/remove and add/remove master device callbacks > > > gets called when the smmu is not linked to its master, that is without > > > the context of the master device. So calling runtime apis in those places > > > separately. > > > Global locks are also initialized before enabling runtime pm as the > > > runtime_resume() calls device_reset() which does tlb_sync_global() > > > that ultimately requires locks to be initialized. > > > > > > Signed-off-by: Sricharan R > > > [vivek: Cleanup pm runtime calls] > > > Signed-off-by: Vivek Gautam > > > Reviewed-by: Tomasz Figa > > > Tested-by: Srinivas Kandagatla > > > --- > > > drivers/iommu/arm-smmu.c | 89 > > > +++- > > > 1 file changed, 81 insertions(+), 8 deletions(-) > > > > This doesn't apply on my tree[1], possibly because I've got Robin's > > non-strict > > invalidation queued there. However, that got me thinking -- how does this > > work in conjunction with the timer-based TLB invalidation? Do we need to > > rpm_{get,put} around flush_iotlb_all()? If so, do we still need the calls > > in map/unmap when non-strict mode is in use? For map/unmap(), i think there would be no harm in having additional power.usage_count even for the non-strict mode. So, I will just add rpm{get,put} in arm_smmu_flush_iotlb_all(), and arm_smmu_iotlb_sync(). Regards Vivek > > I haven't tested things with flush queues, but from what it looks like > both .flush_iotlb_all, and .iotlb_sync callbacks need rpm_get/put(). > I will respin the patches. > > Thanks > Vivek > > > > Will > > > > [1] > > https://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git/log/?h=for-joerg/arm-smmu/updates > > > > -- > QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member > of Code Aurora Forum, hosted by The Linux Foundation -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
Hi Will, On Mon, Oct 1, 2018 at 6:29 PM Will Deacon wrote: > > Hi Vivek, > > On Thu, Aug 30, 2018 at 08:15:38PM +0530, Vivek Gautam wrote: > > From: Sricharan R > > > > The smmu device probe/remove and add/remove master device callbacks > > gets called when the smmu is not linked to its master, that is without > > the context of the master device. So calling runtime apis in those places > > separately. > > Global locks are also initialized before enabling runtime pm as the > > runtime_resume() calls device_reset() which does tlb_sync_global() > > that ultimately requires locks to be initialized. > > > > Signed-off-by: Sricharan R > > [vivek: Cleanup pm runtime calls] > > Signed-off-by: Vivek Gautam > > Reviewed-by: Tomasz Figa > > Tested-by: Srinivas Kandagatla > > --- > > drivers/iommu/arm-smmu.c | 89 > > +++- > > 1 file changed, 81 insertions(+), 8 deletions(-) > > This doesn't apply on my tree[1], possibly because I've got Robin's non-strict > invalidation queued there. However, that got me thinking -- how does this > work in conjunction with the timer-based TLB invalidation? Do we need to > rpm_{get,put} around flush_iotlb_all()? If so, do we still need the calls > in map/unmap when non-strict mode is in use? I haven't tested things with flush queues, but from what it looks like both .flush_iotlb_all, and .iotlb_sync callbacks need rpm_get/put(). I will respin the patches. Thanks Vivek > > Will > > [1] > https://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git/log/?h=for-joerg/arm-smmu/updates -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
On Mon, Oct 1, 2018 at 11:19 AM Vivek Gautam wrote: > > HI Ulf, > > On Fri, Sep 28, 2018 at 5:30 PM Ulf Hansson wrote: > > > > On 30 August 2018 at 16:45, Vivek Gautam > > wrote: > > > From: Sricharan R > > > > > > The smmu needs to be functional only when the respective > > > master's using it are active. The device_link feature > > > helps to track such functional dependencies, so that the > > > iommu gets powered when the master device enables itself > > > using pm_runtime. So by adapting the smmu driver for > > > runtime pm, above said dependency can be addressed. > > > > > > This patch adds the pm runtime/sleep callbacks to the > > > driver and also the functions to parse the smmu clocks > > > from DT and enable them in resume/suspend. > > > > > > Also, while we enable the runtime pm add a pm sleep suspend > > > callback that pushes devices to low power state by turning > > > the clocks off in a system sleep. > > > Also add corresponding clock enable path in resume callback. > > > > > > Signed-off-by: Sricharan R > > > Signed-off-by: Archit Taneja > > > [vivek: rework for clock and pm ops] > > > Signed-off-by: Vivek Gautam > > > Reviewed-by: Tomasz Figa > > > Tested-by: Srinivas Kandagatla > > > --- > > > drivers/iommu/arm-smmu.c | 77 > > > ++-- > > > 1 file changed, 74 insertions(+), 3 deletions(-) > > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > > > [...] > > > > > -static int __maybe_unused arm_smmu_pm_resume(struct device *dev) > > > +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) > > > { > > > struct arm_smmu_device *smmu = dev_get_drvdata(dev); > > > + int ret; > > > + > > > + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); > > > + if (ret) > > > + return ret; > > > > > > arm_smmu_device_reset(smmu); > > > + > > > return 0; > > > } > > > > > > -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); > > > +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) > > > +{ > > > + struct arm_smmu_device *smmu = dev_get_drvdata(dev); > > > + > > > + clk_bulk_disable(smmu->num_clks, smmu->clks); > > > + > > > + return 0; > > > +} > > > + > > > +static int __maybe_unused arm_smmu_pm_resume(struct device *dev) > > > +{ > > > + if (pm_runtime_suspended(dev)) > > > + return 0; > > > > Looks like you should be able use pm_runtime_force_resume(), instead > > of using this local trick. Unless I am missing something, of course. > > > > In other words, just assign the system sleep callbacks for resume, to > > pm_runtime_force_resume(). And vice verse for the system suspend > > callbacks, pm_runtime_force_suspend(), of course. > > Thanks for the review. I will change this as suggested. Coming back at this - actually Rafael suggested _not_ to use pm_runtime_force_suspend/resume() when Marek had suggested the same [1]. He also mentioned few caveats/limitations of using these APIs for system sleep ops. Let me know your opinion. Thanks. [1] https://lkml.org/lkml/2018/7/11/978 [2] https://lkml.org/lkml/2018/7/23/334 Best regards Vivek -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
On Mon, Oct 1, 2018 at 3:09 PM Ulf Hansson wrote: > > On 1 October 2018 at 07:49, Vivek Gautam wrote: > > HI Ulf, > > > > On Fri, Sep 28, 2018 at 5:30 PM Ulf Hansson wrote: > >> > >> On 30 August 2018 at 16:45, Vivek Gautam > >> wrote: > >> > From: Sricharan R > >> > > >> > The smmu needs to be functional only when the respective > >> > master's using it are active. The device_link feature > >> > helps to track such functional dependencies, so that the > >> > iommu gets powered when the master device enables itself > >> > using pm_runtime. So by adapting the smmu driver for > >> > runtime pm, above said dependency can be addressed. > >> > > >> > This patch adds the pm runtime/sleep callbacks to the > >> > driver and also the functions to parse the smmu clocks > >> > from DT and enable them in resume/suspend. > >> > > >> > Also, while we enable the runtime pm add a pm sleep suspend > >> > callback that pushes devices to low power state by turning > >> > the clocks off in a system sleep. > >> > Also add corresponding clock enable path in resume callback. > >> > > >> > Signed-off-by: Sricharan R > >> > Signed-off-by: Archit Taneja > >> > [vivek: rework for clock and pm ops] > >> > Signed-off-by: Vivek Gautam > >> > Reviewed-by: Tomasz Figa > >> > Tested-by: Srinivas Kandagatla > >> > --- > >> > drivers/iommu/arm-smmu.c | 77 > >> > ++-- > >> > 1 file changed, 74 insertions(+), 3 deletions(-) > >> > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > >> > >> [...] > >> > >> > -static int __maybe_unused arm_smmu_pm_resume(struct device *dev) > >> > +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) > >> > { > >> > struct arm_smmu_device *smmu = dev_get_drvdata(dev); > >> > + int ret; > >> > + > >> > + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); > >> > + if (ret) > >> > + return ret; > >> > > >> > arm_smmu_device_reset(smmu); > >> > + > >> > return 0; > >> > } > >> > > >> > -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); > >> > +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) > >> > +{ > >> > + struct arm_smmu_device *smmu = dev_get_drvdata(dev); > >> > + > >> > + clk_bulk_disable(smmu->num_clks, smmu->clks); > >> > + > >> > + return 0; > >> > +} > >> > + > >> > +static int __maybe_unused arm_smmu_pm_resume(struct device *dev) > >> > +{ > >> > + if (pm_runtime_suspended(dev)) > >> > + return 0; > >> > >> Looks like you should be able use pm_runtime_force_resume(), instead > >> of using this local trick. Unless I am missing something, of course. > >> > >> In other words, just assign the system sleep callbacks for resume, to > >> pm_runtime_force_resume(). And vice verse for the system suspend > >> callbacks, pm_runtime_force_suspend(), of course. > > > > Thanks for the review. I will change this as suggested. > > > >> > >> > + > >> > + return arm_smmu_runtime_resume(dev); > >> > +} > >> > + > >> > +static int __maybe_unused arm_smmu_pm_suspend(struct device *dev) > >> > +{ > >> > + if (pm_runtime_suspended(dev)) > >> > + return 0; > >> > + > >> > + return arm_smmu_runtime_suspend(dev); > >> > +} > >> > + > >> > +static const struct dev_pm_ops arm_smmu_pm_ops = { > >> > + SET_SYSTEM_SLEEP_PM_OPS(arm_smmu_pm_suspend, arm_smmu_pm_resume) > >> > >> I am wondering if using the ->suspend|resume() callback is really > >> "late/early" enough in the device suspend phase? > >> > >> Others is using the noirq phase and some is even using the syscore > >> ops. Of course it depends on the behavior of the consumers of iommu > >> device, and I guess not everyone is using device links, which for sure > >> improves things in this regards as well. > > > > Well yes, as you said the device links should be able to take care of > > maintaining the correct suspend/resume order of smmu and its clients, > > or am I missing your point here? > > Let me know and I will be happy to incorporate any suggestions. > > Thanks > > If it works fine, then you may keep it as is. > > Just wanted to point out that if any consumers relies on the iommu to > operational to say until the suspend-late phase, then this doesn't > play. Then you need to move your callbacks to the corresponding same > phase. Although I have no means to test the suspend-late phase, tests with graphics and display on db820 haven't shown any anomaly. [snip] Best regards Vivek -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 0/5] iommu/arm-smmu: Add runtime pm/sleep support
Hi Will, On Fri, Sep 28, 2018 at 7:27 PM Will Deacon wrote: > > Hi Vivek, > > On Thu, Aug 30, 2018 at 08:15:36PM +0530, Vivek Gautam wrote: > > This series provides the support for turning on the arm-smmu's > > clocks/power domains using runtime pm. This is done using > > device links between smmu and client devices. The device link > > framework keeps the two devices in correct order for power-cycling > > across runtime PM or across system-wide PM. > > > > With addition of a new device link flag DL_FLAG_AUTOREMOVE_SUPPLIER [7], > > the device links created between arm-smmu and its clients will be > > automatically purged when arm-smmu driver unbinds from its device. > > > > As not all implementations support clock/power gating, we are checking > > for a valid 'smmu->dev's pm_domain' to conditionally enable the runtime > > power management for such smmu implementations that can support it. > > Otherwise, the clocks are turned to be always on in .probe until .remove. > > With conditional runtime pm now, we avoid touching dev->power.lock > > in fastpaths for smmu implementations that don't need to do anything > > useful with pm_runtime. > > This lets us to use the much-argued pm_runtime_get_sync/put_sync() > > calls in map/unmap callbacks so that the clients do not have to > > worry about handling any of the arm-smmu's power. > > > > This series also adds support for Qcom's arm-smmu-v2 variant that > > has different clocks and power requirements. > > > > Previous version of this patch series is @ [1]. > > > > Build tested the series based on 4.19-rc1. > > I'm going to send my pull request to Joerg early next week (probably > Monday), but I'm not keen to include this whilst it has outstanding comments > from Ulf. Your errata workaround patch is in a similar situation, with > outstanding comments from Robin. I am going to address Ulf's comments for pm_runtime_force_suspend/resume() calls in system sleep callbacks and respin the series unless he has any more comments regarding the early/late nature of suspend/resume. So will it do if I respin the series today after waiting for Ulf? The workaround series is going for a discussion now, so i think it can wait. Thanks Best regards Vivek > > Will > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
HI Ulf, On Fri, Sep 28, 2018 at 5:30 PM Ulf Hansson wrote: > > On 30 August 2018 at 16:45, Vivek Gautam wrote: > > From: Sricharan R > > > > The smmu needs to be functional only when the respective > > master's using it are active. The device_link feature > > helps to track such functional dependencies, so that the > > iommu gets powered when the master device enables itself > > using pm_runtime. So by adapting the smmu driver for > > runtime pm, above said dependency can be addressed. > > > > This patch adds the pm runtime/sleep callbacks to the > > driver and also the functions to parse the smmu clocks > > from DT and enable them in resume/suspend. > > > > Also, while we enable the runtime pm add a pm sleep suspend > > callback that pushes devices to low power state by turning > > the clocks off in a system sleep. > > Also add corresponding clock enable path in resume callback. > > > > Signed-off-by: Sricharan R > > Signed-off-by: Archit Taneja > > [vivek: rework for clock and pm ops] > > Signed-off-by: Vivek Gautam > > Reviewed-by: Tomasz Figa > > Tested-by: Srinivas Kandagatla > > --- > > drivers/iommu/arm-smmu.c | 77 > > ++-- > > 1 file changed, 74 insertions(+), 3 deletions(-) > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > [...] > > > -static int __maybe_unused arm_smmu_pm_resume(struct device *dev) > > +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) > > { > > struct arm_smmu_device *smmu = dev_get_drvdata(dev); > > + int ret; > > + > > + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); > > + if (ret) > > + return ret; > > > > arm_smmu_device_reset(smmu); > > + > > return 0; > > } > > > > -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); > > +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) > > +{ > > + struct arm_smmu_device *smmu = dev_get_drvdata(dev); > > + > > + clk_bulk_disable(smmu->num_clks, smmu->clks); > > + > > + return 0; > > +} > > + > > +static int __maybe_unused arm_smmu_pm_resume(struct device *dev) > > +{ > > + if (pm_runtime_suspended(dev)) > > + return 0; > > Looks like you should be able use pm_runtime_force_resume(), instead > of using this local trick. Unless I am missing something, of course. > > In other words, just assign the system sleep callbacks for resume, to > pm_runtime_force_resume(). And vice verse for the system suspend > callbacks, pm_runtime_force_suspend(), of course. Thanks for the review. I will change this as suggested. > > > + > > + return arm_smmu_runtime_resume(dev); > > +} > > + > > +static int __maybe_unused arm_smmu_pm_suspend(struct device *dev) > > +{ > > + if (pm_runtime_suspended(dev)) > > + return 0; > > + > > + return arm_smmu_runtime_suspend(dev); > > +} > > + > > +static const struct dev_pm_ops arm_smmu_pm_ops = { > > + SET_SYSTEM_SLEEP_PM_OPS(arm_smmu_pm_suspend, arm_smmu_pm_resume) > > I am wondering if using the ->suspend|resume() callback is really > "late/early" enough in the device suspend phase? > > Others is using the noirq phase and some is even using the syscore > ops. Of course it depends on the behavior of the consumers of iommu > device, and I guess not everyone is using device links, which for sure > improves things in this regards as well. Well yes, as you said the device links should be able to take care of maintaining the correct suspend/resume order of smmu and its clients, or am I missing your point here? Let me know and I will be happy to incorporate any suggestions. Thanks Regards Vivek > > > + SET_RUNTIME_PM_OPS(arm_smmu_runtime_suspend, > > + arm_smmu_runtime_resume, NULL) > > +}; > > > > static struct platform_driver arm_smmu_driver = { > > .driver = { > > -- > > QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member > > of Code Aurora Forum, hosted by The Linux Foundation > > > > BTW, apologize for very late review comments. > > Besides the above comments, the series looks good to me. > > Kind regards > Uffe > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
On Wed, Sep 26, 2018 at 8:57 PM Robin Murphy wrote: > > On 30/08/18 15:45, Vivek Gautam wrote: > > From: Sricharan R > > > > The smmu needs to be functional only when the respective > > master's using it are active. The device_link feature > > helps to track such functional dependencies, so that the > > iommu gets powered when the master device enables itself > > using pm_runtime. So by adapting the smmu driver for > > runtime pm, above said dependency can be addressed. > > > > This patch adds the pm runtime/sleep callbacks to the > > driver and also the functions to parse the smmu clocks > > from DT and enable them in resume/suspend. > > > > Also, while we enable the runtime pm add a pm sleep suspend > > callback that pushes devices to low power state by turning > > the clocks off in a system sleep. > > Also add corresponding clock enable path in resume callback. > > > > Signed-off-by: Sricharan R > > Signed-off-by: Archit Taneja > > [vivek: rework for clock and pm ops] > > Signed-off-by: Vivek Gautam > > Reviewed-by: Tomasz Figa > > Tested-by: Srinivas Kandagatla > > --- > > drivers/iommu/arm-smmu.c | 77 > > ++-- > > 1 file changed, 74 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > index fd1b80ef9490..d900e007c3c9 100644 > > --- a/drivers/iommu/arm-smmu.c > > +++ b/drivers/iommu/arm-smmu.c > > @@ -48,6 +48,7 @@ > > #include > > #include > > #include > > +#include > > #include > > #include > > > > @@ -205,6 +206,8 @@ struct arm_smmu_device { > > u32 num_global_irqs; > > u32 num_context_irqs; > > unsigned int*irqs; > > + struct clk_bulk_data*clks; > > + int num_clks; > > > > u32 cavium_id_base; /* Specific to Cavium > > */ > > > > @@ -1896,10 +1899,12 @@ static int arm_smmu_device_cfg_probe(struct > > arm_smmu_device *smmu) > > struct arm_smmu_match_data { > > enum arm_smmu_arch_version version; > > enum arm_smmu_implementation model; > > + const char * const *clks; > > + int num_clks; > > }; > > > > #define ARM_SMMU_MATCH_DATA(name, ver, imp) \ > > -static struct arm_smmu_match_data name = { .version = ver, .model = imp } > > +static const struct arm_smmu_match_data name = { .version = ver, .model = > > imp } > > > > ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); > > ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); > > @@ -1918,6 +1923,23 @@ static const struct of_device_id arm_smmu_of_match[] > > = { > > }; > > MODULE_DEVICE_TABLE(of, arm_smmu_of_match); > > > > +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, > > +const char * const *clks) > > +{ > > + int i; > > + > > + if (smmu->num_clks < 1) > > + return; > > + > > + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, > > + sizeof(*smmu->clks), GFP_KERNEL); > > + if (!smmu->clks) > > + return; > > + > > + for (i = 0; i < smmu->num_clks; i++) > > + smmu->clks[i].id = clks[i]; > > +} > > + > > #ifdef CONFIG_ACPI > > static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) > > { > > @@ -2000,6 +2022,9 @@ static int arm_smmu_device_dt_probe(struct > > platform_device *pdev, > > data = of_device_get_match_data(dev); > > smmu->version = data->version; > > smmu->model = data->model; > > + smmu->num_clks = data->num_clks; > > + > > + arm_smmu_fill_clk_data(smmu, data->clks); > > > > parse_driver_options(smmu); > > > > @@ -2098,6 +2123,14 @@ static int arm_smmu_device_probe(struct > > platform_device *pdev) > > smmu->irqs[i] = irq; > > } > > > > + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); > > + if (err) > > + return err; > > + > > + err = clk_bulk_prepare_enable(smmu->num_clks, smmu->clks); > > + if (err) > > + return err; > > + > > Hmm, if we error out
Re: [Freedreno] [PATCH v16 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
Hi Robin, On Wed, Sep 26, 2018 at 9:29 PM Robin Murphy wrote: > > On 30/08/18 15:45, Vivek Gautam wrote: > > qcom,smmu-v2 is an arm,smmu-v2 implementation with specific > > clock and power requirements. > > On msm8996, multiple cores, viz. mdss, video, etc. use this > > smmu. On sdm845, this smmu is used with gpu. > > Add bindings for the same. > > > > Signed-off-by: Vivek Gautam > > Reviewed-by: Rob Herring > > Reviewed-by: Tomasz Figa > > Tested-by: Srinivas Kandagatla > > --- > > drivers/iommu/arm-smmu.c | 13 + > > 1 file changed, 13 insertions(+) > > > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > index 166c8c6da24f..411e5ac57c64 100644 > > --- a/drivers/iommu/arm-smmu.c > > +++ b/drivers/iommu/arm-smmu.c > > @@ -119,6 +119,7 @@ enum arm_smmu_implementation { > > GENERIC_SMMU, > > ARM_MMU500, > > CAVIUM_SMMUV2, > > + QCOM_SMMUV2, > > Hmm, it seems we don't actually need this right now, but maybe that just > means there's more imp-def registers and/or errata to come ;) > > Either way I guess there's no real harm in having it. Thanks for the review. Best regards Vivek > > Reviewed-by: Robin Murphy > > > }; > > > > struct arm_smmu_s2cr { > > @@ -1970,6 +1971,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, > > GENERIC_SMMU); > > ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); > > ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); > > > > +static const char * const qcom_smmuv2_clks[] = { > > + "bus", "iface", > > +}; > > + > > +static const struct arm_smmu_match_data qcom_smmuv2 = { > > + .version = ARM_SMMU_V2, > > + .model = QCOM_SMMUV2, > > + .clks = qcom_smmuv2_clks, > > + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), > > +}; > > + > > static const struct of_device_id arm_smmu_of_match[] = { > > { .compatible = "arm,smmu-v1", .data = _generic_v1 }, > > { .compatible = "arm,smmu-v2", .data = _generic_v2 }, > > @@ -1977,6 +1989,7 @@ static const struct of_device_id arm_smmu_of_match[] > > = { > > { .compatible = "arm,mmu-401", .data = _mmu401 }, > > { .compatible = "arm,mmu-500", .data = _mmu500 }, > > { .compatible = "cavium,smmu-v2", .data = _smmuv2 }, > > + { .compatible = "qcom,smmu-v2", .data = _smmuv2 }, > > { }, > > }; > > MODULE_DEVICE_TABLE(of, arm_smmu_of_match); > > > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
Hi Robin, Will, On Tue, Sep 18, 2018 at 8:41 AM Vivek Gautam wrote: > > Hi Robin, > > On Fri, Sep 7, 2018 at 3:52 PM Vivek Gautam > wrote: > > > > On Fri, Sep 7, 2018 at 3:22 PM Tomasz Figa wrote: > > > > > > On Fri, Sep 7, 2018 at 6:38 PM Vivek Gautam > > > wrote: > > > > > > > > Hi Tomasz, > > > > > > > > > > > > On 9/7/2018 2:46 PM, Tomasz Figa wrote: > > > > > Hi Vivek, > > > > > > > > > > On Thu, Aug 30, 2018 at 11:46 PM Vivek Gautam > > > > > wrote: > > > > >> From: Sricharan R > > > > >> > > > > >> The smmu device probe/remove and add/remove master device callbacks > > > > >> gets called when the smmu is not linked to its master, that is > > > > >> without > > > > >> the context of the master device. So calling runtime apis in those > > > > >> places > > > > >> separately. > > > > >> Global locks are also initialized before enabling runtime pm as the > > > > >> runtime_resume() calls device_reset() which does tlb_sync_global() > > > > >> that ultimately requires locks to be initialized. > > > > >> > > > > >> Signed-off-by: Sricharan R > > > > >> [vivek: Cleanup pm runtime calls] > > > > >> Signed-off-by: Vivek Gautam > > > > >> Reviewed-by: Tomasz Figa > > > > >> Tested-by: Srinivas Kandagatla > > > > >> --- > > > > >> drivers/iommu/arm-smmu.c | 89 > > > > >> +++- > > > > >> 1 file changed, 81 insertions(+), 8 deletions(-) > > > > > [snip] > > > > >> @@ -2215,10 +2281,17 @@ static int arm_smmu_device_remove(struct > > > > >> platform_device *pdev) > > > > >> if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS)) > > > > >> dev_err(>dev, "removing device with active > > > > >> domains!\n"); > > > > >> > > > > >> + arm_smmu_rpm_get(smmu); > > > > >> /* Turn the thing off */ > > > > >> writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + > > > > >> ARM_SMMU_GR0_sCR0); > > > > >> + arm_smmu_rpm_put(smmu); > > > > >> + > > > > >> + if (pm_runtime_enabled(smmu->dev)) > > > > >> + pm_runtime_force_suspend(smmu->dev); > > > > >> + else > > > > >> + clk_bulk_disable(smmu->num_clks, smmu->clks); > > > > >> > > > > >> - clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); > > > > >> + clk_bulk_unprepare(smmu->num_clks, smmu->clks); > > > > > Aren't we missing pm_runtime_disable() here? We'll have the enable > > > > > count unbalanced if the driver is removed and probed again. > > > > > > > > pm_runtime_force_suspend() does a pm_runtime_disable() also if i am not > > > > wrong. > > > > And, as mentioned in a previous thread [1], we were seeing a warning > > > > which we avoided > > > > by keeping force_suspend(). > > > > > > > > [1] https://lkml.org/lkml/2018/7/8/124 > > > > > > I see, thanks. I didn't realize that pm_runtime_force_suspend() > > > already disables runtime PM indeed. Sorry for the noise. > > > > Hi Tomasz, > > No problem. Thanks for looking back at it. > > > > Hi Robin, > > If you are fine with this series, then can you please consider giving > > Reviewed-by, so that we are certain that this series will go in the next > > merge > > window. > > Thanks > > Gentle ping. > You ack will be very helpful in letting Will pull this series for 4.20. > Thanks. I would really appreciate if you could provide your ack for this series. Or if there are any concerns, I am willing to address them. Thanks. Best regards Vivek > > -- > QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member > of Code Aurora Forum, hosted by The Linux Foundation -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
Hi Robin, On Fri, Sep 7, 2018 at 3:52 PM Vivek Gautam wrote: > > On Fri, Sep 7, 2018 at 3:22 PM Tomasz Figa wrote: > > > > On Fri, Sep 7, 2018 at 6:38 PM Vivek Gautam > > wrote: > > > > > > Hi Tomasz, > > > > > > > > > On 9/7/2018 2:46 PM, Tomasz Figa wrote: > > > > Hi Vivek, > > > > > > > > On Thu, Aug 30, 2018 at 11:46 PM Vivek Gautam > > > > wrote: > > > >> From: Sricharan R > > > >> > > > >> The smmu device probe/remove and add/remove master device callbacks > > > >> gets called when the smmu is not linked to its master, that is without > > > >> the context of the master device. So calling runtime apis in those > > > >> places > > > >> separately. > > > >> Global locks are also initialized before enabling runtime pm as the > > > >> runtime_resume() calls device_reset() which does tlb_sync_global() > > > >> that ultimately requires locks to be initialized. > > > >> > > > >> Signed-off-by: Sricharan R > > > >> [vivek: Cleanup pm runtime calls] > > > >> Signed-off-by: Vivek Gautam > > > >> Reviewed-by: Tomasz Figa > > > >> Tested-by: Srinivas Kandagatla > > > >> --- > > > >> drivers/iommu/arm-smmu.c | 89 > > > >> +++- > > > >> 1 file changed, 81 insertions(+), 8 deletions(-) > > > > [snip] > > > >> @@ -2215,10 +2281,17 @@ static int arm_smmu_device_remove(struct > > > >> platform_device *pdev) > > > >> if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS)) > > > >> dev_err(>dev, "removing device with active > > > >> domains!\n"); > > > >> > > > >> + arm_smmu_rpm_get(smmu); > > > >> /* Turn the thing off */ > > > >> writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + > > > >> ARM_SMMU_GR0_sCR0); > > > >> + arm_smmu_rpm_put(smmu); > > > >> + > > > >> + if (pm_runtime_enabled(smmu->dev)) > > > >> + pm_runtime_force_suspend(smmu->dev); > > > >> + else > > > >> + clk_bulk_disable(smmu->num_clks, smmu->clks); > > > >> > > > >> - clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); > > > >> + clk_bulk_unprepare(smmu->num_clks, smmu->clks); > > > > Aren't we missing pm_runtime_disable() here? We'll have the enable > > > > count unbalanced if the driver is removed and probed again. > > > > > > pm_runtime_force_suspend() does a pm_runtime_disable() also if i am not > > > wrong. > > > And, as mentioned in a previous thread [1], we were seeing a warning > > > which we avoided > > > by keeping force_suspend(). > > > > > > [1] https://lkml.org/lkml/2018/7/8/124 > > > > I see, thanks. I didn't realize that pm_runtime_force_suspend() > > already disables runtime PM indeed. Sorry for the noise. > > Hi Tomasz, > No problem. Thanks for looking back at it. > > Hi Robin, > If you are fine with this series, then can you please consider giving > Reviewed-by, so that we are certain that this series will go in the next merge > window. > Thanks Gentle ping. You ack will be very helpful in letting Will pull this series for 4.20. Thanks. Best regards Vivek -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2
On Mon, Sep 10, 2018 at 11:32 PM Rob Herring wrote: > > On Thu, 30 Aug 2018 20:15:40 +0530, Vivek Gautam wrote: > > Add bindings doc for Qcom's smmu-v2 implementation. > > > > Signed-off-by: Vivek Gautam > > Reviewed-by: Tomasz Figa > > Tested-by: Srinivas Kandagatla > > --- > > .../devicetree/bindings/iommu/arm,smmu.txt | 39 > > ++ > > 1 file changed, 39 insertions(+) > > > > Reviewed-by: Rob Herring Thanks Rob. Best regards Vivek -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
On Fri, Sep 7, 2018 at 3:22 PM Tomasz Figa wrote: > > On Fri, Sep 7, 2018 at 6:38 PM Vivek Gautam > wrote: > > > > Hi Tomasz, > > > > > > On 9/7/2018 2:46 PM, Tomasz Figa wrote: > > > Hi Vivek, > > > > > > On Thu, Aug 30, 2018 at 11:46 PM Vivek Gautam > > > wrote: > > >> From: Sricharan R > > >> > > >> The smmu device probe/remove and add/remove master device callbacks > > >> gets called when the smmu is not linked to its master, that is without > > >> the context of the master device. So calling runtime apis in those places > > >> separately. > > >> Global locks are also initialized before enabling runtime pm as the > > >> runtime_resume() calls device_reset() which does tlb_sync_global() > > >> that ultimately requires locks to be initialized. > > >> > > >> Signed-off-by: Sricharan R > > >> [vivek: Cleanup pm runtime calls] > > >> Signed-off-by: Vivek Gautam > > >> Reviewed-by: Tomasz Figa > > >> Tested-by: Srinivas Kandagatla > > >> --- > > >> drivers/iommu/arm-smmu.c | 89 > > >> +++- > > >> 1 file changed, 81 insertions(+), 8 deletions(-) > > > [snip] > > >> @@ -2215,10 +2281,17 @@ static int arm_smmu_device_remove(struct > > >> platform_device *pdev) > > >> if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS)) > > >> dev_err(>dev, "removing device with active > > >> domains!\n"); > > >> > > >> + arm_smmu_rpm_get(smmu); > > >> /* Turn the thing off */ > > >> writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + > > >> ARM_SMMU_GR0_sCR0); > > >> + arm_smmu_rpm_put(smmu); > > >> + > > >> + if (pm_runtime_enabled(smmu->dev)) > > >> + pm_runtime_force_suspend(smmu->dev); > > >> + else > > >> + clk_bulk_disable(smmu->num_clks, smmu->clks); > > >> > > >> - clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); > > >> + clk_bulk_unprepare(smmu->num_clks, smmu->clks); > > > Aren't we missing pm_runtime_disable() here? We'll have the enable > > > count unbalanced if the driver is removed and probed again. > > > > pm_runtime_force_suspend() does a pm_runtime_disable() also if i am not > > wrong. > > And, as mentioned in a previous thread [1], we were seeing a warning > > which we avoided > > by keeping force_suspend(). > > > > [1] https://lkml.org/lkml/2018/7/8/124 > > I see, thanks. I didn't realize that pm_runtime_force_suspend() > already disables runtime PM indeed. Sorry for the noise. Hi Tomasz, No problem. Thanks for looking back at it. Hi Robin, If you are fine with this series, then can you please consider giving Reviewed-by, so that we are certain that this series will go in the next merge window. Thanks Best regards Vivek -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
Hi Tomasz, On 9/7/2018 2:46 PM, Tomasz Figa wrote: Hi Vivek, On Thu, Aug 30, 2018 at 11:46 PM Vivek Gautam wrote: From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Global locks are also initialized before enabling runtime pm as the runtime_resume() calls device_reset() which does tlb_sync_global() that ultimately requires locks to be initialized. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- drivers/iommu/arm-smmu.c | 89 +++- 1 file changed, 81 insertions(+), 8 deletions(-) [snip] @@ -2215,10 +2281,17 @@ static int arm_smmu_device_remove(struct platform_device *pdev) if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS)) dev_err(>dev, "removing device with active domains!\n"); + arm_smmu_rpm_get(smmu); /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + arm_smmu_rpm_put(smmu); + + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_force_suspend(smmu->dev); + else + clk_bulk_disable(smmu->num_clks, smmu->clks); - clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); + clk_bulk_unprepare(smmu->num_clks, smmu->clks); Aren't we missing pm_runtime_disable() here? We'll have the enable count unbalanced if the driver is removed and probed again. pm_runtime_force_suspend() does a pm_runtime_disable() also if i am not wrong. And, as mentioned in a previous thread [1], we were seeing a warning which we avoided by keeping force_suspend(). [1] https://lkml.org/lkml/2018/7/8/124 Thanks Vivek Also, if we add pm_runtime_disable(), we can reorder things a bit and simplify into: arm_smmu_rpm_get(smmu); /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); if (pm_runtime_enabled()) pm_runtime_disable(); arm_smmu_rpm_put(smmu); clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); Best regards, Tomasz ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v16 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2
Hi Rob, On Thu, Aug 30, 2018 at 8:16 PM Vivek Gautam wrote: > > Add bindings doc for Qcom's smmu-v2 implementation. > > Signed-off-by: Vivek Gautam > Reviewed-by: Tomasz Figa > Tested-by: Srinivas Kandagatla > --- I removed your reviewed-by for this particular patch. Can you please consider giving your review if you find the changes okay now. Thanks. Best regards Vivek > .../devicetree/bindings/iommu/arm,smmu.txt | 39 > ++ > 1 file changed, 39 insertions(+) > > diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt > b/Documentation/devicetree/bindings/iommu/arm,smmu.txt > index 8a6ffce12af5..a6504b37cc21 100644 > --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt > +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt > @@ -17,10 +17,16 @@ conditions. > "arm,mmu-401" > "arm,mmu-500" > "cavium,smmu-v2" > +"qcom,smmu-v2" > >depending on the particular implementation and/or the >version of the architecture implemented. > > + Qcom SoCs must contain, as below, SoC-specific compatibles > + along with "qcom,smmu-v2": > + "qcom,msm8996-smmu-v2", "qcom,smmu-v2", > + "qcom,sdm845-smmu-v2", "qcom,smmu-v2". > + > - reg : Base address and size of the SMMU. > > - #global-interrupts : The number of global interrupts exposed by the > @@ -71,6 +77,22 @@ conditions. >or using stream matching with #iommu-cells = <2>, and >may be ignored if present in such cases. > > +- clock-names:List of the names of clocks input to the device. The > + required list depends on particular implementation and > + is as follows: > + - for "qcom,smmu-v2": > +- "bus": clock required for downstream bus access and > + for the smmu ptw, > +- "iface": clock required to access smmu's registers > + through the TCU's programming interface. > + - unspecified for other implementations. > + > +- clocks: Specifiers for all clocks listed in the clock-names > property, > + as per generic clock bindings. > + > +- power-domains: Specifiers for power domains required to be powered on for > + the SMMU to operate, as per generic power domain bindings. > + > ** Deprecated properties: > > - mmu-masters (deprecated in favour of the generic "iommus" binding) : > @@ -137,3 +159,20 @@ conditions. > iommu-map = <0 0 0x400>; > ... > }; > + > + /* Qcom's arm,smmu-v2 implementation */ > + smmu4: iommu@d0 { > + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; > + reg = <0xd0 0x1>; > + > + #global-interrupts = <1>; > + interrupts = , > +, > +; > + #iommu-cells = <1>; > + power-domains = < MDSS_GDSC>; > + > + clocks = < SMMU_MDP_AXI_CLK>, > +< SMMU_MDP_AHB_CLK>; > + clock-names = "bus", "iface"; > + }; > -- > QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member > of Code Aurora Forum, hosted by The Linux Foundation > > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [Patch v15 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2
Hi Rob, On 8/30/2018 6:13 AM, Rob Herring wrote: On Wed, Aug 29, 2018 at 6:23 AM Vivek Gautam wrote: On Wed, Aug 29, 2018 at 2:05 PM Vivek Gautam wrote: Hi Rob, On 8/29/2018 2:04 AM, Rob Herring wrote: On Mon, Aug 27, 2018 at 04:25:50PM +0530, Vivek Gautam wrote: Add bindings doc for Qcom's smmu-v2 implementation. Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- Changes since v14: - This is a new patch added in v15 after noticing the new checkpatch warning for separate dt-bindings doc. - This patch also addresses comments given by Rob and Robin to add a list of valid values of '' in "qcom,-smmu-v2" compatible string. .../devicetree/bindings/iommu/arm,smmu.txt | 47 ++ 1 file changed, 47 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..52198a539606 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,10 +17,24 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,-smmu-v2", "qcom,smmu-v2" The v2 in the compatible string is kind of redundant unless the SoC has other SMMU types. sdm845 has smmu-v2, and smmu-500 [1]. depending on the particular implementation and/or the version of the architecture implemented. + A number of Qcom SoCs use qcom,smmu-v2 version of the IP. + "qcom,-smmu-v2" represents a soc specific compatible + string that should be present along with the "qcom,smmu-v2" + to facilitate SoC specific clocks/power connections and to + address specific bug fixes. + '' string in "qcom,-smmu-v2" should be one of the + following: + msm8996 - for msm8996 Qcom SoC. + sdm845 - for sdm845 Qcom Soc. Rather than all this prose, it would be simpler to just add 2 lines with the full compatibles rather than . The thing is not going to work when/if we move bindings to json-schema also. then we keep adding "qcom,msm8996-smmu-v2", "qcom,smmu-v2" "qcom,msm8998-smmu-v2", "qcom,smmu-v2" "qcom,sdm845-smmu-v2", "qcom,smmu-v2", and from [1] "qcom,sdm845-smmu-500", "arm,mmu-500", etc. for each SoCs? How about following diff on top of this patch? diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 52198a539606..5e6c04876533 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,23 +17,18 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" -"qcom,-smmu-v2", "qcom,smmu-v2" +"qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. - A number of Qcom SoCs use qcom,smmu-v2 version of the IP. - "qcom,-smmu-v2" represents a soc specific compatible - string that should be present along with the "qcom,smmu-v2" - to facilitate SoC specific clocks/power connections and to - address specific bug fixes. - '' string in "qcom,-smmu-v2" should be one of the - following: - msm8996 - for msm8996 Qcom SoC. - sdm845 - for sdm845 Qcom Soc. - - An example string would be - - "qcom,msm8996-smmu-v2", "qcom,smmu-v2". + Qcom SoCs using qcom,smmu-v2 must have soc specific + compatible string attached to "qcom,smmu-v2" to take care + of SoC specific clocks/power connections and to address + specific bug fixes. + Precisely, it should be one of the following: + "qcom,msm8996-smmu-v2", "qcom,smmu-v2", + "qcom,sdm845-smmu-v2", "qcom,smmu-v2". We don't need an explanation of why we need specific compatibles in each binding document (though maybe we need a better explanation somewhere). We just need to know what are valid values for compatibles and this includes any combinations. Generally, this is just a list of combinations. [snip] Fixed this in v16. Thanks. Best regards Vivek ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v16 3/5] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 1bf542010be7..166c8c6da24f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1461,6 +1461,9 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER); + return 0; out_cfg_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v16 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. On msm8996, multiple cores, viz. mdss, video, etc. use this smmu. On sdm845, this smmu is used with gpu. Add bindings for the same. Signed-off-by: Vivek Gautam Reviewed-by: Rob Herring Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- drivers/iommu/arm-smmu.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 166c8c6da24f..411e5ac57c64 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -119,6 +119,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -1970,6 +1971,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; + static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, { .compatible = "arm,smmu-v2", .data = _generic_v2 }, @@ -1977,6 +1989,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-401", .data = _mmu401 }, { .compatible = "arm,mmu-500", .data = _mmu500 }, { .compatible = "cavium,smmu-v2", .data = _smmuv2 }, + { .compatible = "qcom,smmu-v2", .data = _smmuv2 }, { }, }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v16 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2
Add bindings doc for Qcom's smmu-v2 implementation. Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- .../devicetree/bindings/iommu/arm,smmu.txt | 39 ++ 1 file changed, 39 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..a6504b37cc21 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,10 +17,16 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. + Qcom SoCs must contain, as below, SoC-specific compatibles + along with "qcom,smmu-v2": + "qcom,msm8996-smmu-v2", "qcom,smmu-v2", + "qcom,sdm845-smmu-v2", "qcom,smmu-v2". + - reg : Base address and size of the SMMU. - #global-interrupts : The number of global interrupts exposed by the @@ -71,6 +77,22 @@ conditions. or using stream matching with #iommu-cells = <2>, and may be ignored if present in such cases. +- clock-names:List of the names of clocks input to the device. The + required list depends on particular implementation and + is as follows: + - for "qcom,smmu-v2": +- "bus": clock required for downstream bus access and + for the smmu ptw, +- "iface": clock required to access smmu's registers + through the TCU's programming interface. + - unspecified for other implementations. + +- clocks: Specifiers for all clocks listed in the clock-names property, + as per generic clock bindings. + +- power-domains: Specifiers for power domains required to be powered on for + the SMMU to operate, as per generic power domain bindings. + ** Deprecated properties: - mmu-masters (deprecated in favour of the generic "iommus" binding) : @@ -137,3 +159,20 @@ conditions. iommu-map = <0 0 0x400>; ... }; + + /* Qcom's arm,smmu-v2 implementation */ + smmu4: iommu@d0 { + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; + reg = <0xd0 0x1>; + + #global-interrupts = <1>; + interrupts = , +, +; + #iommu-cells = <1>; + power-domains = < MDSS_GDSC>; + + clocks = < SMMU_MDP_AXI_CLK>, +< SMMU_MDP_AHB_CLK>; + clock-names = "bus", "iface"; + }; -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v16 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Also, while we enable the runtime pm add a pm sleep suspend callback that pushes devices to low power state by turning the clocks off in a system sleep. Also add corresponding clock enable path in resume callback. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: rework for clock and pm ops] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- drivers/iommu/arm-smmu.c | 77 ++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fd1b80ef9490..d900e007c3c9 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,8 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clks; + int num_clks; u32 cavium_id_base; /* Specific to Cavium */ @@ -1896,10 +1899,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) struct arm_smmu_match_data { enum arm_smmu_arch_version version; enum arm_smmu_implementation model; + const char * const *clks; + int num_clks; }; #define ARM_SMMU_MATCH_DATA(name, ver, imp)\ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -1918,6 +1923,23 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, + const char * const *clks) +{ + int i; + + if (smmu->num_clks < 1) + return; + + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, + sizeof(*smmu->clks), GFP_KERNEL); + if (!smmu->clks) + return; + + for (i = 0; i < smmu->num_clks; i++) + smmu->clks[i].id = clks[i]; +} + #ifdef CONFIG_ACPI static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) { @@ -2000,6 +2022,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->num_clks = data->num_clks; + + arm_smmu_fill_clk_data(smmu, data->clks); parse_driver_options(smmu); @@ -2098,6 +2123,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); + if (err) + return err; + + err = clk_bulk_prepare_enable(smmu->num_clks, smmu->clks); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2184,6 +2217,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + + clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); + return 0; } @@ -2192,15 +2228,50 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) arm_smmu_device_remove(pdev); } -static int __maybe_unused arm_smmu_pm_resume(struct device *dev) +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) { struct arm_smmu_device *smmu = dev_get_drvdata(dev); + int ret; + + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); + if (ret) + return ret; arm_smmu_device_reset(smmu); + return 0; } -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + clk_bulk_disable(smmu->num_clks, smmu->clks); + + return 0; +} + +static int __
[Freedreno] [PATCH v16 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Global locks are also initialized before enabling runtime pm as the runtime_resume() calls device_reset() which does tlb_sync_global() that ultimately requires locks to be initialized. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- drivers/iommu/arm-smmu.c | 89 +++- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index d900e007c3c9..1bf542010be7 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -268,6 +268,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + return pm_runtime_get_sync(smmu->dev); + + return 0; +} + +static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_put(smmu->dev); +} + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -913,11 +927,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -932,6 +950,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + arm_smmu_rpm_put(smmu); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1213,10 +1233,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; smmu = fwspec_smmu(fwspec); + + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return ret; + /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); if (ret < 0) - return ret; + goto rpm_put; /* * Sanity check the domain. We don't support domains across @@ -1226,33 +1251,50 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); - return -EINVAL; + ret = -EINVAL; + goto rpm_put; } /* Looks ok, so add the device to the domain */ - return arm_smmu_domain_add_master(smmu_domain, fwspec); + ret = arm_smmu_domain_add_master(smmu_domain, fwspec); + +rpm_put: + arm_smmu_rpm_put(smmu); + return ret; } static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + int ret; if (!ops) return -ENODEV; - return ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_get(smmu); + ret = ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_put(smmu); + + return ret; } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + size_t ret; if (!ops) return 0; - return ops->unmap(ops, iova, size); + arm_smmu_rpm_get(smmu); + ret = ops->unmap(ops, iova, size); + arm_smmu_rpm_put(smmu); + + return ret; } static void arm_smmu_iotlb_sync(struct iommu_domain *domain) @@ -1407,7 +1449,13 @@ static int arm_smmu_add_device(struct device *dev) while (i--) cfg->smendx[i] = INVALID_SMENDX; + ret = arm_smmu
[Freedreno] [PATCH v16 0/5] iommu/arm-smmu: Add runtime pm/sleep support
* Dropped the patch [5] that was adding device_link_find() API to device core layer. device_link_del_dev() serves the purpose to directly delete the link between two given devices. [v9] * Removed 'rpm_supported' flag, instead checking on pm_domain to enable runtime pm. * Creating device link only when the runtime pm is enabled, as we don't need a device link besides managing the power dependency between supplier and consumer devices. * Introducing a patch to add device_link_find() API that finds and existing link between supplier and consumer devices. Also, made necessary change to device_link_add() to use this API. * arm_smmu_remove_device() now uses this device_link_find() to find the device link between smmu device and the master device, and then delete this link. * Dropped the destroy_domain_context() fix [4] as it was rather, introducing catastrophically bad problem by destroying 'good dev's domain context. * Added 'Reviwed-by' tag for Tomasz's review. [v8] * Major change - - Added a flag 'rpm_supported' which each platform that supports runtime pm, can enable, and we enable runtime_pm over arm-smmu only when this flag is set. - Adding the conditional pm_runtime_get/put() calls to .map, .unmap and .attach_dev ops. - Dropped the patch [2] that exported pm_runtim_get/put_suupliers(), and also dropped the user driver patch [3] for these APIs. * Clock code further cleanup - doing only clk_bulk_enable() and clk_bulk_disable() in runtime pm callbacks. We shouldn't be taking a slow path (clk_prepare/unprepare()) from these runtime pm callbacks. Thereby, moved clk_bulk_prepare() to arm_smmu_device_probe(), and clk_bulk_unprepare() to arm_smmu_device_remove(). - clk data filling to a common method arm_smmu_fill_clk_data() that fills the clock ids and number of clocks. * Addressed other nits and comments - device_link_add() error path fixed. - Fix for checking negative error value from pm_runtime_get_sync(). - Documentation redo. * Added another patch fixing the error path in arm_smmu_attach_dev() to destroy allocated domain context. ** Change logs for previous versions is available in previous series [9]. [1] https://patchwork.kernel.org/cover/10576921/ [2] https://patchwork.kernel.org/patch/10204945/ [3] https://patchwork.kernel.org/patch/10204925/ [4] https://patchwork.kernel.org/patch/10254105/ [5] https://patchwork.kernel.org/patch/10277975/ [6] https://patchwork.kernel.org/patch/10281613/ [7] https://patchwork.kernel.org/patch/10491481/ [8] https://lore.kernel.org/patchwork/patch/974116/ [9] https://lkml.org/lkml/2018/7/8/124 Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (2): dt-bindings: arm-smmu: Add bindings for qcom,smmu-v2 iommu/arm-smmu: Add support for qcom,smmu-v2 variant .../devicetree/bindings/iommu/arm,smmu.txt | 39 + drivers/iommu/arm-smmu.c | 180 +++-- 2 files changed, 209 insertions(+), 10 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [Patch v15 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
On Thu, Aug 30, 2018 at 3:04 PM Tomasz Figa wrote: > > On Thu, Aug 30, 2018 at 6:22 PM Vivek Gautam > wrote: > > > > On Mon, Aug 27, 2018 at 4:27 PM Vivek Gautam > > wrote: > > > > > > From: Sricharan R > > > > > > The smmu device probe/remove and add/remove master device callbacks > > > gets called when the smmu is not linked to its master, that is without > > > the context of the master device. So calling runtime apis in those places > > > separately. > > > > > > Signed-off-by: Sricharan R > > > [vivek: Cleanup pm runtime calls] > > > Signed-off-by: Vivek Gautam > > > Reviewed-by: Tomasz Figa > > > Tested-by: Srinivas Kandagatla > > > --- > > > > > > Changes since v14: > > > - none. > > > > > > drivers/iommu/arm-smmu.c | 101 > > > +++ > > > 1 file changed, 93 insertions(+), 8 deletions(-) > > > > > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > > index a81224bc6637..23b4a60149b6 100644 > > > --- a/drivers/iommu/arm-smmu.c > > > +++ b/drivers/iommu/arm-smmu.c > > > > [snip] > > > > > @@ -2131,6 +2188,26 @@ static int arm_smmu_device_probe(struct > > > platform_device *pdev) > > > if (err) > > > return err; > > > > > > + /* > > > +* We want to avoid touching dev->power.lock in fastpaths unless > > > +* it's really going to do something useful - pm_runtime_enabled() > > > +* can serve as an ideal proxy for that decision. So, > > > conditionally > > > +* enable pm_runtime. > > > +*/ > > > + if (dev->pm_domain) > > > + pm_runtime_enable(dev); > > > + > > > + err = arm_smmu_rpm_get(smmu); > > > > We shouldn't be doing a runtime_get() yet, as this eventually calls > > arm_smmu_device_reset(). > > arm_smmu_device_reset() should be called only after > > arm_smmu_device_cfg_probe(). > > So, I plan to replace the pm_runtime_get/put() calls in probe() with > > simple clk_bulk_enable() > > to let the driver initialize smmu, and at the end of the probe we can > > disable the clocks and > > enable runtime pm over the device to let it take care of the device > > further-on. > > > > We can avoid the explicit clock disable by just calling > pm_runtime_set_active() before pm_runtime_enable(), assuming that what > probe does is symmetrical with the suspend callback, which would be > called after the latter. Sure, that sounds reasonable. Will use pm_runtime_set_active() instead of explicitly disabling the clocks.Thanks. Best regards Vivek > > Best regards, > Tomasz > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [Patch v15 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
On Mon, Aug 27, 2018 at 4:27 PM Vivek Gautam wrote: > > From: Sricharan R > > The smmu device probe/remove and add/remove master device callbacks > gets called when the smmu is not linked to its master, that is without > the context of the master device. So calling runtime apis in those places > separately. > > Signed-off-by: Sricharan R > [vivek: Cleanup pm runtime calls] > Signed-off-by: Vivek Gautam > Reviewed-by: Tomasz Figa > Tested-by: Srinivas Kandagatla > --- > > Changes since v14: > - none. > > drivers/iommu/arm-smmu.c | 101 > +++ > 1 file changed, 93 insertions(+), 8 deletions(-) > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > index a81224bc6637..23b4a60149b6 100644 > --- a/drivers/iommu/arm-smmu.c > +++ b/drivers/iommu/arm-smmu.c [snip] > @@ -2131,6 +2188,26 @@ static int arm_smmu_device_probe(struct > platform_device *pdev) > if (err) > return err; > > + /* > +* We want to avoid touching dev->power.lock in fastpaths unless > +* it's really going to do something useful - pm_runtime_enabled() > +* can serve as an ideal proxy for that decision. So, conditionally > +* enable pm_runtime. > +*/ > + if (dev->pm_domain) > + pm_runtime_enable(dev); > + > + err = arm_smmu_rpm_get(smmu); We shouldn't be doing a runtime_get() yet, as this eventually calls arm_smmu_device_reset(). arm_smmu_device_reset() should be called only after arm_smmu_device_cfg_probe(). So, I plan to replace the pm_runtime_get/put() calls in probe() with simple clk_bulk_enable() to let the driver initialize smmu, and at the end of the probe we can disable the clocks and enable runtime pm over the device to let it take care of the device further-on. > + if (err < 0) > + return err; > + > + /* Enable clocks explicitly if runtime PM is disabled */ > + if (!pm_runtime_enabled(dev)) { > + err = clk_bulk_enable(smmu->num_clks, smmu->clks); > + if (err) > + return err; > + } > + > err = arm_smmu_device_cfg_probe(smmu); > if (err) > return err; [snip] Best regards Vivek -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [Patch v15 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2
On Wed, Aug 29, 2018 at 2:05 PM Vivek Gautam wrote: > > Hi Rob, > > > On 8/29/2018 2:04 AM, Rob Herring wrote: > > On Mon, Aug 27, 2018 at 04:25:50PM +0530, Vivek Gautam wrote: > >> Add bindings doc for Qcom's smmu-v2 implementation. > >> > >> Signed-off-by: Vivek Gautam > >> Reviewed-by: Tomasz Figa > >> Tested-by: Srinivas Kandagatla > >> --- > >> > >> Changes since v14: > >> - This is a new patch added in v15 after noticing the new > >> checkpatch warning for separate dt-bindings doc. > >> - This patch also addresses comments given by Rob and Robin to add > >> a list of valid values of '' in "qcom,-smmu-v2" > >> compatible string. > >> > >> .../devicetree/bindings/iommu/arm,smmu.txt | 47 > >> ++ > >> 1 file changed, 47 insertions(+) > >> > >> diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt > >> b/Documentation/devicetree/bindings/iommu/arm,smmu.txt > >> index 8a6ffce12af5..52198a539606 100644 > >> --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt > >> +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt > >> @@ -17,10 +17,24 @@ conditions. > >> "arm,mmu-401" > >> "arm,mmu-500" > >> "cavium,smmu-v2" > >> +"qcom,-smmu-v2", "qcom,smmu-v2" > > The v2 in the compatible string is kind of redundant unless the SoC has > > other SMMU types. > > sdm845 has smmu-v2, and smmu-500 [1]. > > >> > >> depending on the particular implementation and/or the > >> version of the architecture implemented. > >> > >> + A number of Qcom SoCs use qcom,smmu-v2 version of the > >> IP. > >> + "qcom,-smmu-v2" represents a soc specific > >> compatible > >> + string that should be present along with the > >> "qcom,smmu-v2" > >> + to facilitate SoC specific clocks/power connections and > >> to > >> + address specific bug fixes. > >> + '' string in "qcom,-smmu-v2" should be one of > >> the > >> + following: > >> + msm8996 - for msm8996 Qcom SoC. > >> + sdm845 - for sdm845 Qcom Soc. > > Rather than all this prose, it would be simpler to just add 2 lines with > > the full compatibles rather than . The thing is not going to > > work when/if we move bindings to json-schema also. > > then we keep adding > "qcom,msm8996-smmu-v2", "qcom,smmu-v2" > "qcom,msm8998-smmu-v2", "qcom,smmu-v2" > "qcom,sdm845-smmu-v2", "qcom,smmu-v2", > and from [1] > "qcom,sdm845-smmu-500", "arm,mmu-500", etc. > for each SoCs? How about following diff on top of this patch? diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 52198a539606..5e6c04876533 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,23 +17,18 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" -"qcom,-smmu-v2", "qcom,smmu-v2" +"qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. - A number of Qcom SoCs use qcom,smmu-v2 version of the IP. - "qcom,-smmu-v2" represents a soc specific compatible - string that should be present along with the "qcom,smmu-v2" - to facilitate SoC specific clocks/power connections and to - address specific bug fixes. - '' string in "qcom,-smmu-v2" should be one of the - following: - msm8996 - for msm8996 Qcom SoC. - sdm845 - for sdm845 Qcom Soc. - - An example string would be - - "qcom,msm8996-smmu-v2", "qcom,smmu-v2". + Qcom SoCs using qcom,smmu-v2 must have soc specific + compatible string attached to "qcom,smmu-v2" to take care + of SoC specific clocks/power connections and to address + specific bug fixes. + Precisely, it should be one of the following: + "qcom,msm8996-smmu-v2", "qcom,smmu-v2", + "qcom,sdm845-smmu-v2", "qcom,smmu-v2". Thanks! Best regards Vivek -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH 5/9] arm64: dts: sdm845: Add gpu and gmu device nodes
Hi Jordan, On Mon, Aug 27, 2018 at 8:42 PM Jordan Crouse wrote: > > Add the nodes to describe the Adreno GPU and GMU devices. > > Signed-off-by: Jordan Crouse > --- > arch/arm64/boot/dts/qcom/sdm845.dtsi | 121 +++ > 1 file changed, 121 insertions(+) > > diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi > b/arch/arm64/boot/dts/qcom/sdm845.dtsi > index cdaabeb3c995..10db0ceb3699 100644 > --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi > +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi > @@ -192,6 +192,59 @@ > method = "smc"; > }; > > +gpu_opp_table: adreno-opp-table { > + compatible = "operating-points-v2-qcom-level"; > + > + opp-71000 { > + opp-hz = /bits/ 64 <71000>; > + qcom,level = <416>; > + }; > + > + opp-67500 { > + opp-hz = /bits/ 64 <67500>; > + qcom,level = <384>; > + }; > + > + opp-59600 { > + opp-hz = /bits/ 64 <59600>; > + qcom,level = <320>; > + }; > + > + opp-52000 { > + opp-hz = /bits/ 64 <52000>; > + qcom,level = <256>; > + }; > + > + opp-41400 { > + opp-hz = /bits/ 64 <41400>; > + qcom,level = <192>; > + }; > + > + opp-34200 { > + opp-hz = /bits/ 64 <34200>; > + qcom,level = <128>; > + }; > + > + opp-25700 { > + opp-hz = /bits/ 64 <25700>; > + qcom,level = <64>; > + }; > + }; > + > + gmu_opp_table: adreno-gmu-opp-table { > + compatible = "operating-points-v2-qcom-level"; > + > + opp-4 { > + opp-hz = /bits/ 64 <4>; > + qcom,level = <128>; > + }; > + > + opp-2 { > + opp-hz = /bits/ 64 <2>; > + qcom,level = <48>; > + }; > + }; > + > soc: soc { > #address-cells = <1>; > #size-cells = <1>; > @@ -323,5 +376,73 @@ > status = "disabled"; > }; > }; > + > + adreno_smmu: adreno-smmu@504 { iommu@504 as pointed out by Rob in [1] > + compatible = "qcom,sdm845-smmu-v2", "qcom,smmu-v2"; > + reg = <0x504 0x1>; > + #iommu-cells = <1>; > + #global-interrupts = <2>; > + interrupts = , > + , > + , > + , > + , > + , > + , > + , > + , > + ; > + clocks = < GCC_GPU_MEMNOC_GFX_CLK>, > + < GCC_GPU_CFG_AHB_CLK>; > + clock-names = "bus", "iface"; > + > + power-domains = < GPU_CX_GDSC>; and for this you need to include the gpucc dt-bindings header which is coming from Amit's gpucc driver patch. [1] https://patchwork.kernel.org/patch/10534999/ Best regards Vivek [snip] -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [Patch v15 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. On msm8996, multiple cores, viz. mdss, video, etc. use this smmu. On sdm845, this smmu is used with gpu. Add bindings for the same. Signed-off-by: Vivek Gautam Reviewed-by: Rob Herring Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- Changes since v14: - Moved out dt-bindings change to separate patch. drivers/iommu/arm-smmu.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index b5e7f72d418c..c0177ea32678 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -119,6 +119,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -1970,6 +1971,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; + static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, { .compatible = "arm,smmu-v2", .data = _generic_v2 }, @@ -1977,6 +1989,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-401", .data = _mmu401 }, { .compatible = "arm,mmu-500", .data = _mmu500 }, { .compatible = "cavium,smmu-v2", .data = _smmuv2 }, + { .compatible = "qcom,smmu-v2", .data = _smmuv2 }, { }, }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [Patch v15 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2
Add bindings doc for Qcom's smmu-v2 implementation. Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- Changes since v14: - This is a new patch added in v15 after noticing the new checkpatch warning for separate dt-bindings doc. - This patch also addresses comments given by Rob and Robin to add a list of valid values of '' in "qcom,-smmu-v2" compatible string. .../devicetree/bindings/iommu/arm,smmu.txt | 47 ++ 1 file changed, 47 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..52198a539606 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,10 +17,24 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,-smmu-v2", "qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. + A number of Qcom SoCs use qcom,smmu-v2 version of the IP. + "qcom,-smmu-v2" represents a soc specific compatible + string that should be present along with the "qcom,smmu-v2" + to facilitate SoC specific clocks/power connections and to + address specific bug fixes. + '' string in "qcom,-smmu-v2" should be one of the + following: + msm8996 - for msm8996 Qcom SoC. + sdm845 - for sdm845 Qcom Soc. + + An example string would be - + "qcom,msm8996-smmu-v2", "qcom,smmu-v2". + - reg : Base address and size of the SMMU. - #global-interrupts : The number of global interrupts exposed by the @@ -71,6 +85,22 @@ conditions. or using stream matching with #iommu-cells = <2>, and may be ignored if present in such cases. +- clock-names:List of the names of clocks input to the device. The + required list depends on particular implementation and + is as follows: + - for "qcom,smmu-v2": +- "bus": clock required for downstream bus access and + for the smmu ptw, +- "iface": clock required to access smmu's registers + through the TCU's programming interface. + - unspecified for other implementations. + +- clocks: Specifiers for all clocks listed in the clock-names property, + as per generic clock bindings. + +- power-domains: Specifiers for power domains required to be powered on for + the SMMU to operate, as per generic power domain bindings. + ** Deprecated properties: - mmu-masters (deprecated in favour of the generic "iommus" binding) : @@ -137,3 +167,20 @@ conditions. iommu-map = <0 0 0x400>; ... }; + + /* Qcom's arm,smmu-v2 implementation */ + smmu4: iommu { + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; + reg = <0xd0 0x1>; + + #global-interrupts = <1>; + interrupts = , +, +; + #iommu-cells = <1>; + power-domains = < MDSS_GDSC>; + + clocks = < SMMU_MDP_AXI_CLK>, +< SMMU_MDP_AHB_CLK>; + clock-names = "bus", "iface"; + }; -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [Patch v15 3/5] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- Changes since v14: - none. drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 23b4a60149b6..b5e7f72d418c 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1461,6 +1461,9 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER); + return 0; out_cfg_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [Patch v15 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops
From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Also, while we enable the runtime pm add a pm sleep suspend callback that pushes devices to low power state by turning the clocks off in a system sleep. Also add corresponding clock enable path in resume callback. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: rework for clock and pm ops] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Tested-by: Srinivas Kandagatla --- Changes since v14: - none. drivers/iommu/arm-smmu.c | 77 ++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fd1b80ef9490..a81224bc6637 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,8 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clks; + int num_clks; u32 cavium_id_base; /* Specific to Cavium */ @@ -1896,10 +1899,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) struct arm_smmu_match_data { enum arm_smmu_arch_version version; enum arm_smmu_implementation model; + const char * const *clks; + int num_clks; }; #define ARM_SMMU_MATCH_DATA(name, ver, imp)\ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -1918,6 +1923,23 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, + const char * const *clks) +{ + int i; + + if (smmu->num_clks < 1) + return; + + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, + sizeof(*smmu->clks), GFP_KERNEL); + if (!smmu->clks) + return; + + for (i = 0; i < smmu->num_clks; i++) + smmu->clks[i].id = clks[i]; +} + #ifdef CONFIG_ACPI static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) { @@ -2000,6 +2022,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->num_clks = data->num_clks; + + arm_smmu_fill_clk_data(smmu, data->clks); parse_driver_options(smmu); @@ -2098,6 +2123,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); + if (err) + return err; + + err = clk_bulk_prepare(smmu->num_clks, smmu->clks); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2184,6 +2217,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + + clk_bulk_unprepare(smmu->num_clks, smmu->clks); + return 0; } @@ -2192,15 +2228,50 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) arm_smmu_device_remove(pdev); } -static int __maybe_unused arm_smmu_pm_resume(struct device *dev) +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) { struct arm_smmu_device *smmu = dev_get_drvdata(dev); + int ret; + + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); + if (ret) + return ret; arm_smmu_device_reset(smmu); + return 0; } -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + clk_bulk_disable(smmu->num_clks, smmu->clks); +
[Freedreno] [Patch v15 0/5] iommu/arm-smmu: Add runtime pm/sleep support
Introducing a patch to add device_link_find() API that finds and existing link between supplier and consumer devices. Also, made necessary change to device_link_add() to use this API. * arm_smmu_remove_device() now uses this device_link_find() to find the device link between smmu device and the master device, and then delete this link. * Dropped the destroy_domain_context() fix [5] as it was rather, introducing catastrophically bad problem by destroying 'good dev's domain context. * Added 'Reviwed-by' tag for Tomasz's review. [v8] * Major change - - Added a flag 'rpm_supported' which each platform that supports runtime pm, can enable, and we enable runtime_pm over arm-smmu only when this flag is set. - Adding the conditional pm_runtime_get/put() calls to .map, .unmap and .attach_dev ops. - Dropped the patch [3] that exported pm_runtim_get/put_suupliers(), and also dropped the user driver patch [4] for these APIs. * Clock code further cleanup - doing only clk_bulk_enable() and clk_bulk_disable() in runtime pm callbacks. We shouldn't be taking a slow path (clk_prepare/unprepare()) from these runtime pm callbacks. Thereby, moved clk_bulk_prepare() to arm_smmu_device_probe(), and clk_bulk_unprepare() to arm_smmu_device_remove(). - clk data filling to a common method arm_smmu_fill_clk_data() that fills the clock ids and number of clocks. * Addressed other nits and comments - device_link_add() error path fixed. - Fix for checking negative error value from pm_runtime_get_sync(). - Documentation redo. * Added another patch fixing the error path in arm_smmu_attach_dev() to destroy allocated domain context. [v7] * Addressed review comments given by Robin Murphy - - Added device_link_del() in .remove_device path. - Error path cleanup in arm_smmu_add_device(). - Added pm_runtime_get/put_sync() in .remove path, and replaced pm_runtime_force_suspend() with pm_runtime_disable(). - clk_names cleanup in arm_smmu_init_clks() * Added 'Reviewed-by' given by Rob H. ** Change logs for previous versions is available in previous series [4]. [1] https://patchwork.kernel.org/patch/10204925/ [2] https://lore.kernel.org/patchwork/cover/968013/ [3] https://patchwork.kernel.org/patch/10204945/ [4] https://patchwork.kernel.org/patch/10204925/ [5] https://patchwork.kernel.org/patch/10254105/ [6] https://patchwork.kernel.org/patch/10277975/ [7] https://patchwork.kernel.org/patch/10281613/ [8] https://patchwork.kernel.org/patch/10491481/ [9] https://lore.kernel.org/patchwork/patch/974116/ Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (2): dt-bindings: arm-smmu: Add bindings for qcom,smmu-v2 iommu/arm-smmu: Add support for qcom,smmu-v2 variant .../devicetree/bindings/iommu/arm,smmu.txt | 47 + drivers/iommu/arm-smmu.c | 194 +++-- 2 files changed, 230 insertions(+), 11 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v14 3/4] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- Change since v13: - No change. drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 1efa5681b905..e558abf1ecfc 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1461,6 +1461,9 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER); + return 0; out_cfg_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v14 4/4] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. This smmu core is used with multiple masters on msm8996, viz. mdss, video, etc. Add bindings for the same. Signed-off-by: Vivek Gautam Reviewed-by: Rob Herring Reviewed-by: Tomasz Figa --- Change since v13: - No change. .../devicetree/bindings/iommu/arm,smmu.txt | 42 ++ drivers/iommu/arm-smmu.c | 13 +++ 2 files changed, 55 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..7c71a6ed465a 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,10 +17,19 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,-smmu-v2", "qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. + A number of Qcom SoCs use qcom,smmu-v2 version of the IP. + "qcom,-smmu-v2" represents a soc specific compatible + string that should be present along with the "qcom,smmu-v2" + to facilitate SoC specific clocks/power connections and to + address specific bug fixes. + An example string would be - + "qcom,msm8996-smmu-v2", "qcom,smmu-v2". + - reg : Base address and size of the SMMU. - #global-interrupts : The number of global interrupts exposed by the @@ -71,6 +80,22 @@ conditions. or using stream matching with #iommu-cells = <2>, and may be ignored if present in such cases. +- clock-names:List of the names of clocks input to the device. The + required list depends on particular implementation and + is as follows: + - for "qcom,smmu-v2": +- "bus": clock required for downstream bus access and + for the smmu ptw, +- "iface": clock required to access smmu's registers + through the TCU's programming interface. + - unspecified for other implementations. + +- clocks: Specifiers for all clocks listed in the clock-names property, + as per generic clock bindings. + +- power-domains: Specifiers for power domains required to be powered on for + the SMMU to operate, as per generic power domain bindings. + ** Deprecated properties: - mmu-masters (deprecated in favour of the generic "iommus" binding) : @@ -137,3 +162,20 @@ conditions. iommu-map = <0 0 0x400>; ... }; + + /* Qcom's arm,smmu-v2 implementation */ + smmu4: iommu { + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; + reg = <0xd0 0x1>; + + #global-interrupts = <1>; + interrupts = , +, +; + #iommu-cells = <1>; + power-domains = < MDSS_GDSC>; + + clocks = < SMMU_MDP_AXI_CLK>, +< SMMU_MDP_AHB_CLK>; + clock-names = "bus", "iface"; + }; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e558abf1ecfc..2b4edba188a5 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -119,6 +119,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -1971,6 +1972,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; + static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, { .compatible = "arm,smmu-v2", .data = _generic_v2 }, @@ -1978,6 +1990,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-401", .data = _mmu401 }, { .compatible = "arm,mmu-500", .data = _mmu500 }, {
[Freedreno] [PATCH v14 2/4] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- Change since v13: - No change. drivers/iommu/arm-smmu.c | 101 +++ 1 file changed, 93 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 5f6a9e3c0079..1efa5681b905 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -268,6 +268,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + return pm_runtime_get_sync(smmu->dev); + + return 0; +} + +static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_put(smmu->dev); +} + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -913,11 +927,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -932,6 +950,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + arm_smmu_rpm_put(smmu); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1213,10 +1233,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; smmu = fwspec_smmu(fwspec); + + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return ret; + /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); if (ret < 0) - return ret; + goto rpm_put; /* * Sanity check the domain. We don't support domains across @@ -1226,33 +1251,50 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); - return -EINVAL; + ret = -EINVAL; + goto rpm_put; } /* Looks ok, so add the device to the domain */ - return arm_smmu_domain_add_master(smmu_domain, fwspec); + ret = arm_smmu_domain_add_master(smmu_domain, fwspec); + +rpm_put: + arm_smmu_rpm_put(smmu); + return ret; } static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + int ret; if (!ops) return -ENODEV; - return ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_get(smmu); + ret = ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_put(smmu); + + return ret; } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + size_t ret; if (!ops) return 0; - return ops->unmap(ops, iova, size); + arm_smmu_rpm_get(smmu); + ret = ops->unmap(ops, iova, size); + arm_smmu_rpm_put(smmu); + + return ret; } static void arm_smmu_iotlb_sync(struct iommu_domain *domain) @@ -1407,7 +1449,13 @@ static int arm_smmu_add_device(struct device *dev) while (i--) cfg->smendx[i] = INVALID_SMENDX; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + goto out_cfg_free; + ret = arm_smmu_master_alloc_smes(dev); + arm_smmu_rpm_put(smmu); + if (ret) goto out
[Freedreno] [PATCH v14 1/4] iommu/arm-smmu: Add pm_runtime/sleep ops
From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Also, while we enable the runtime pm add a pm sleep suspend callback that pushes devices to low power state by turning the clocks off in a system sleep. Also add corresponding clock enable path in resume callback. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: rework for clock and pm ops] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- Changes since v13: - Moved arm_smmu_device_reset() from arm_smmu_pm_resume() to arm_smmu_runtime_resume(). arm_smmu_pm_resume() calls just runtime_resume() now. drivers/iommu/arm-smmu.c | 77 ++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index c73cfce1ccc0..5f6a9e3c0079 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,8 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clks; + int num_clks; u32 cavium_id_base; /* Specific to Cavium */ @@ -1897,10 +1900,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) struct arm_smmu_match_data { enum arm_smmu_arch_version version; enum arm_smmu_implementation model; + const char * const *clks; + int num_clks; }; #define ARM_SMMU_MATCH_DATA(name, ver, imp)\ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -1919,6 +1924,23 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, + const char * const *clks) +{ + int i; + + if (smmu->num_clks < 1) + return; + + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, + sizeof(*smmu->clks), GFP_KERNEL); + if (!smmu->clks) + return; + + for (i = 0; i < smmu->num_clks; i++) + smmu->clks[i].id = clks[i]; +} + #ifdef CONFIG_ACPI static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) { @@ -2001,6 +2023,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->num_clks = data->num_clks; + + arm_smmu_fill_clk_data(smmu, data->clks); parse_driver_options(smmu); @@ -2099,6 +2124,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); + if (err) + return err; + + err = clk_bulk_prepare(smmu->num_clks, smmu->clks); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2181,6 +2214,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + + clk_bulk_unprepare(smmu->num_clks, smmu->clks); + return 0; } @@ -2189,15 +2225,50 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) arm_smmu_device_remove(pdev); } -static int __maybe_unused arm_smmu_pm_resume(struct device *dev) +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) { struct arm_smmu_device *smmu = dev_get_drvdata(dev); + int ret; + + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); + if (ret) + return ret; arm_smmu_device_reset(smmu); + return 0; } -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) +{ + struct arm_smmu_device *s
[Freedreno] [PATCH v14 0/4] iommu/arm-smmu: Add runtime pm/sleep support
ink_add() to use this API. * arm_smmu_remove_device() now uses this device_link_find() to find the device link between smmu device and the master device, and then delete this link. * Dropped the destroy_domain_context() fix [5] as it was rather, introducing catastrophically bad problem by destroying 'good dev's domain context. * Added 'Reviwed-by' tag for Tomasz's review. [v8] * Major change - - Added a flag 'rpm_supported' which each platform that supports runtime pm, can enable, and we enable runtime_pm over arm-smmu only when this flag is set. - Adding the conditional pm_runtime_get/put() calls to .map, .unmap and .attach_dev ops. - Dropped the patch [3] that exported pm_runtim_get/put_suupliers(), and also dropped the user driver patch [4] for these APIs. * Clock code further cleanup - doing only clk_bulk_enable() and clk_bulk_disable() in runtime pm callbacks. We shouldn't be taking a slow path (clk_prepare/unprepare()) from these runtime pm callbacks. Thereby, moved clk_bulk_prepare() to arm_smmu_device_probe(), and clk_bulk_unprepare() to arm_smmu_device_remove(). - clk data filling to a common method arm_smmu_fill_clk_data() that fills the clock ids and number of clocks. * Addressed other nits and comments - device_link_add() error path fixed. - Fix for checking negative error value from pm_runtime_get_sync(). - Documentation redo. * Added another patch fixing the error path in arm_smmu_attach_dev() to destroy allocated domain context. [v7] * Addressed review comments given by Robin Murphy - - Added device_link_del() in .remove_device path. - Error path cleanup in arm_smmu_add_device(). - Added pm_runtime_get/put_sync() in .remove path, and replaced pm_runtime_force_suspend() with pm_runtime_disable(). - clk_names cleanup in arm_smmu_init_clks() * Added 'Reviewed-by' given by Rob H. ** Change logs for previous versions is available in last series [4]. [1] https://patchwork.kernel.org/patch/10204925/ [2] https://lore.kernel.org/patchwork/cover/964655/ [3] https://patchwork.kernel.org/patch/10204945/ [4] https://patchwork.kernel.org/patch/10204925/ [5] https://patchwork.kernel.org/patch/10254105/ [6] https://patchwork.kernel.org/patch/10277975/ [7] https://patchwork.kernel.org/patch/10281613/ [8] https://patchwork.kernel.org/patch/10491481/ [9] https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/log/?h=linux-next [10] https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git/log/?h=next Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (1): iommu/arm-smmu: Add support for qcom,smmu-v2 variant .../devicetree/bindings/iommu/arm,smmu.txt | 42 + drivers/iommu/arm-smmu.c | 194 +++-- 2 files changed, 225 insertions(+), 11 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v13 1/4] iommu/arm-smmu: Add pm_runtime/sleep ops
On 7/26/2018 9:00 PM, Robin Murphy wrote: On 26/07/18 08:12, Vivek Gautam wrote: On Wed, Jul 25, 2018 at 11:46 PM, Vivek Gautam wrote: On Tue, Jul 24, 2018 at 8:51 PM, Robin Murphy wrote: On 19/07/18 11:15, Vivek Gautam wrote: From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Also, while we enable the runtime pm add a pm sleep suspend callback that pushes devices to low power state by turning the clocks off in a system sleep. Also add corresponding clock enable path in resume callback. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: rework for clock and pm ops] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- Changes since v12: - Added pm sleep .suspend callback. This disables the clocks. - Added corresponding change to enable clocks in .resume pm sleep callback. drivers/iommu/arm-smmu.c | 75 ++-- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index c73cfce1ccc0..9138a6fffe04 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c [snip] platform_device *pdev) arm_smmu_device_remove(pdev); } +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + return clk_bulk_enable(smmu->num_clks, smmu->clks); If there's a power domain being automatically switched by genpd then we need a reset here because we may have lost state entirely. Since I remembered the otherwise-useless GPU SMMU on Juno is in a separate power domain, I gave it a poking via sysfs with some debug stuff to dump sCR0 in these callbacks, and the problem is clear: ... [ 4.625551] arm-smmu 2b40.iommu: genpd_runtime_suspend() [ 4.631163] arm-smmu 2b40.iommu: arm_smmu_runtime_suspend: 0x00201936 [ 4.637897] arm-smmu 2b40.iommu: suspend latency exceeded, 6733980 ns [ 21.566983] arm-smmu 2b40.iommu: genpd_runtime_resume() [ 21.584796] arm-smmu 2b40.iommu: arm_smmu_runtime_resume: 0x00220101 [ 21.591452] arm-smmu 2b40.iommu: resume latency exceeded, 6658020 ns ... Qualcomm SoCs have retention enabled for SMMU registers so they don't lose state. ... [ 256.013367] arm-smmu b4.arm,smmu: arm_smmu_runtime_suspend SCR0 = 0x201e36 [ 256.013367] [ 256.019160] arm-smmu b4.arm,smmu: arm_smmu_runtime_resume SCR0 = 0x201e36 [ 256.019160] [ 256.027368] arm-smmu b4.arm,smmu: arm_smmu_runtime_suspend SCR0 = 0x201e36 [ 256.027368] [ 256.036786] arm-smmu b4.arm,smmu: arm_smmu_runtime_resume SCR0 = 0x201e36 ... However after adding arm_smmu_device_reset() in runtime_resume() I observe some performance degradation when kill an instance of 'kmscube' and start it again. The launch time with arm_smmu_device_reset() in runtime_resume() change is more. Could this be because of frequent TLB invalidation and sync? Probably. Plus the reset procedure is a big chunk of MMIO accesses, which for a non-trivial SMMU configuration probably isn't negligible in itself. Unfortunately, unless you know for absolute certain that you don't need to do that, you do. Some more information that i gathered. On Qcom SoCs besides the registers retention, TCU invalidates TLB cache on a CX power collapse exit, which is the system wide suspend case. The arm-smmu software is not aware of this CX power collapse / auto-invalidation. So wouldn't doing an explicit TLB invalidations during runtime resume be detrimental to performance? Indeed it would be, but resuming with TLBs full of random valid-looking junk is even more so. I have one more doubt here - We do runtime power cycle around arm_smmu_map/unmap() too. Now during map/unmap we selectively do TLB maintenance (either tlb_sync or tlb_add_flush). But with runtime pm we want to do TLBIALL*. Is that a problem? It's technically redundant to do both, true, but as we've covered in previous rounds of discussion it's very difficult to know *which* one is sufficient at any given time, so in order to make progress for now I think we have to settle with doing both. Thanks Robin. I will respin the patches as Tomasz also suggested; arm_smmu_runtime_resume() will look like: if (pm_runtime_suspended(dev)) return 0; return arm_smmu_runtime_resume(dev); and, arm_smmu_runtime_resume() will have arm_smmu_device_reset(). Best regards Vivek Robin. -- To unsubscribe from this list: send the line "unsubsc
Re: [Freedreno] [PATCH v13 1/4] iommu/arm-smmu: Add pm_runtime/sleep ops
On Wed, Jul 25, 2018 at 11:46 PM, Vivek Gautam wrote: > On Tue, Jul 24, 2018 at 8:51 PM, Robin Murphy wrote: >> On 19/07/18 11:15, Vivek Gautam wrote: >>> >>> From: Sricharan R >>> >>> The smmu needs to be functional only when the respective >>> master's using it are active. The device_link feature >>> helps to track such functional dependencies, so that the >>> iommu gets powered when the master device enables itself >>> using pm_runtime. So by adapting the smmu driver for >>> runtime pm, above said dependency can be addressed. >>> >>> This patch adds the pm runtime/sleep callbacks to the >>> driver and also the functions to parse the smmu clocks >>> from DT and enable them in resume/suspend. >>> >>> Also, while we enable the runtime pm add a pm sleep suspend >>> callback that pushes devices to low power state by turning >>> the clocks off in a system sleep. >>> Also add corresponding clock enable path in resume callback. >>> >>> Signed-off-by: Sricharan R >>> Signed-off-by: Archit Taneja >>> [vivek: rework for clock and pm ops] >>> Signed-off-by: Vivek Gautam >>> Reviewed-by: Tomasz Figa >>> --- >>> >>> Changes since v12: >>> - Added pm sleep .suspend callback. This disables the clocks. >>> - Added corresponding change to enable clocks in .resume >>>pm sleep callback. >>> >>> drivers/iommu/arm-smmu.c | 75 >>> ++-- >>> 1 file changed, 73 insertions(+), 2 deletions(-) >>> >>> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c >>> index c73cfce1ccc0..9138a6fffe04 100644 >>> --- a/drivers/iommu/arm-smmu.c >>> +++ b/drivers/iommu/arm-smmu.c [snip] >>> platform_device *pdev) >>> arm_smmu_device_remove(pdev); >>> } >>> +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) >>> +{ >>> + struct arm_smmu_device *smmu = dev_get_drvdata(dev); >>> + >>> + return clk_bulk_enable(smmu->num_clks, smmu->clks); >> >> >> If there's a power domain being automatically switched by genpd then we need >> a reset here because we may have lost state entirely. Since I remembered the >> otherwise-useless GPU SMMU on Juno is in a separate power domain, I gave it >> a poking via sysfs with some debug stuff to dump sCR0 in these callbacks, >> and the problem is clear: >> >> ... >> [4.625551] arm-smmu 2b40.iommu: genpd_runtime_suspend() >> [4.631163] arm-smmu 2b40.iommu: arm_smmu_runtime_suspend: 0x00201936 >> [4.637897] arm-smmu 2b40.iommu: suspend latency exceeded, 6733980 ns >> [ 21.566983] arm-smmu 2b40.iommu: genpd_runtime_resume() >> [ 21.584796] arm-smmu 2b40.iommu: arm_smmu_runtime_resume: 0x00220101 >> [ 21.591452] arm-smmu 2b40.iommu: resume latency exceeded, 6658020 ns >> ... > > Qualcomm SoCs have retention enabled for SMMU registers so they don't > lose state. > ... > [ 256.013367] arm-smmu b4.arm,smmu: arm_smmu_runtime_suspend > SCR0 = 0x201e36 > [ 256.013367] > [ 256.019160] arm-smmu b4.arm,smmu: arm_smmu_runtime_resume > SCR0 = 0x201e36 > [ 256.019160] > [ 256.027368] arm-smmu b4.arm,smmu: arm_smmu_runtime_suspend > SCR0 = 0x201e36 > [ 256.027368] > [ 256.036786] arm-smmu b4.arm,smmu: arm_smmu_runtime_resume > SCR0 = 0x201e36 > ... > > However after adding arm_smmu_device_reset() in runtime_resume() I observe > some performance degradation when kill an instance of 'kmscube' and > start it again. > The launch time with arm_smmu_device_reset() in runtime_resume() change is > more. > Could this be because of frequent TLB invalidation and sync? Some more information that i gathered. On Qcom SoCs besides the registers retention, TCU invalidates TLB cache on a CX power collapse exit, which is the system wide suspend case. The arm-smmu software is not aware of this CX power collapse / auto-invalidation. So wouldn't doing an explicit TLB invalidations during runtime resume be detrimental to performance? I have one more doubt here - We do runtime power cycle around arm_smmu_map/unmap() too. Now during map/unmap we selectively do TLB maintenance (either tlb_sync or tlb_add_flush). But with runtime pm we want to do TLBIALL*. Is that a problem? Best regards Vivek > > Best regards > Vivek [snip] -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v13 1/4] iommu/arm-smmu: Add pm_runtime/sleep ops
On Tue, Jul 24, 2018 at 8:51 PM, Robin Murphy wrote: > On 19/07/18 11:15, Vivek Gautam wrote: >> >> From: Sricharan R >> >> The smmu needs to be functional only when the respective >> master's using it are active. The device_link feature >> helps to track such functional dependencies, so that the >> iommu gets powered when the master device enables itself >> using pm_runtime. So by adapting the smmu driver for >> runtime pm, above said dependency can be addressed. >> >> This patch adds the pm runtime/sleep callbacks to the >> driver and also the functions to parse the smmu clocks >> from DT and enable them in resume/suspend. >> >> Also, while we enable the runtime pm add a pm sleep suspend >> callback that pushes devices to low power state by turning >> the clocks off in a system sleep. >> Also add corresponding clock enable path in resume callback. >> >> Signed-off-by: Sricharan R >> Signed-off-by: Archit Taneja >> [vivek: rework for clock and pm ops] >> Signed-off-by: Vivek Gautam >> Reviewed-by: Tomasz Figa >> --- >> >> Changes since v12: >> - Added pm sleep .suspend callback. This disables the clocks. >> - Added corresponding change to enable clocks in .resume >>pm sleep callback. >> >> drivers/iommu/arm-smmu.c | 75 >> ++-- >> 1 file changed, 73 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c >> index c73cfce1ccc0..9138a6fffe04 100644 >> --- a/drivers/iommu/arm-smmu.c >> +++ b/drivers/iommu/arm-smmu.c >> @@ -48,6 +48,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> @@ -205,6 +206,8 @@ struct arm_smmu_device { >> u32 num_global_irqs; >> u32 num_context_irqs; >> unsigned int*irqs; >> + struct clk_bulk_data*clks; >> + int num_clks; >> u32 cavium_id_base; /* Specific to >> Cavium */ >> @@ -1897,10 +1900,12 @@ static int arm_smmu_device_cfg_probe(struct >> arm_smmu_device *smmu) >> struct arm_smmu_match_data { >> enum arm_smmu_arch_version version; >> enum arm_smmu_implementation model; >> + const char * const *clks; >> + int num_clks; >> }; >> #define ARM_SMMU_MATCH_DATA(name, ver, imp) \ >> -static struct arm_smmu_match_data name = { .version = ver, .model = imp } >> +static const struct arm_smmu_match_data name = { .version = ver, .model = >> imp } >> ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); >> ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); >> @@ -1919,6 +1924,23 @@ static const struct of_device_id >> arm_smmu_of_match[] = { >> }; >> MODULE_DEVICE_TABLE(of, arm_smmu_of_match); >> +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, >> + const char * const *clks) >> +{ >> + int i; >> + >> + if (smmu->num_clks < 1) >> + return; >> + >> + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, >> + sizeof(*smmu->clks), GFP_KERNEL); >> + if (!smmu->clks) >> + return; >> + >> + for (i = 0; i < smmu->num_clks; i++) >> + smmu->clks[i].id = clks[i]; >> +} >> + >> #ifdef CONFIG_ACPI >> static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) >> { >> @@ -2001,6 +2023,9 @@ static int arm_smmu_device_dt_probe(struct >> platform_device *pdev, >> data = of_device_get_match_data(dev); >> smmu->version = data->version; >> smmu->model = data->model; >> + smmu->num_clks = data->num_clks; >> + >> + arm_smmu_fill_clk_data(smmu, data->clks); >> parse_driver_options(smmu); >> @@ -2099,6 +2124,14 @@ static int arm_smmu_device_probe(struct >> platform_device *pdev) >> smmu->irqs[i] = irq; >> } >> + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); >> + if (err) >> + return err; >> + >> + err = clk_bulk_prepare(smmu->num_clks, smmu->clks); >> + if (err) >> +
Re: [Freedreno] [PATCH v13 0/4] iommu/arm-smmu: Add runtime pm/sleep support
On Thu, Jul 19, 2018 at 3:45 PM, Vivek Gautam wrote: > This series provides the support for turning on the arm-smmu's > clocks/power domains using runtime pm. This is done using > device links between smmu and client devices. The device link > framework keeps the two devices in correct order for power-cycling > across runtime PM or across system-wide PM. > > With addition of a new device link flag DL_FLAG_AUTOREMOVE_SUPPLIER [8] > (available in linux-next of Rafael's linux-pm tree [9]), the device links > created between arm-smmu and its clients will be automatically purged > when arm-smmu driver unbinds from its device. > > As not all implementations support clock/power gating, we are checking > for a valid 'smmu->dev's pm_domain' to conditionally enable the runtime > power management for such smmu implementations that can support it. > Otherwise, the clocks are turned to be always on in .probe until .remove. > With conditional runtime pm now, we avoid touching dev->power.lock > in fastpaths for smmu implementations that don't need to do anything > useful with pm_runtime. > This lets us to use the much-argued pm_runtime_get_sync/put_sync() > calls in map/unmap callbacks so that the clients do not have to > worry about handling any of the arm-smmu's power. > > This series also adds support for Qcom's arm-smmu-v2 variant that > has different clocks and power requirements. > > Previous version of this patch series is @ [2]. > > Tested this series on msm8996, and sdm845 after pulling in Rafael's linux-pm > linux-next[9] and Joerg's iommu next[10] branches. Hi Rafael, If the changes look good to you now, can you please consider giving your Ack. Thanks. Hi Robin, Will, If the series looks good to you, and if there's a chance, can you please consider picking this series for 4.19. Thanks. Best regards Vivek > > [v13] >Addressing Rafael's comments: >* Added .suspend pm callback to disable the clocks in system wide suspend. >* Added corresponding clock enable in .resume pm callback. >* Explicitly enabling/disabling the clocks now when runtime PM is disabled. >* device_link_add() doesn't depend on pm_runtime_enabled() as we can > use device links across system suspend/resume too. > >Addressing Robin's comments: >* Making device_link_add failures as non-fatal. > >* Removed IOMMU_OF_DECLARE() declaration as we don't need this after Rob's > patch that removed all of these declarations. > > [v12] >* Use new device link's flag introduced in [8] - > DL_FLAG_AUTOREMOVE_SUPPLIER. With this devices links are automatically > purged when arm-smmu driver unbinds. >* Using pm_runtime_force_suspend() instead of pm_runtime_disable() to > avoid following warning from arm_smmu_device_remove() > > [295711.537507] [ cut here ] > [295711.544226] Unpreparing enabled smmu_mdp_ahb_clk > [295711.549099] WARNING: CPU: 0 PID: 1 at ../drivers/clk/clk.c:697 > clk_core_unprepare+0xd8/0xe0 > ... > [295711.674073] Call trace: > [295711.679454] clk_core_unprepare+0xd8/0xe0 > [295711.682059] clk_unprepare+0x28/0x40 > [295711.685964] clk_bulk_unprepare+0x28/0x40 > [295711.689701] arm_smmu_device_remove+0x88/0xd8 > [295711.693692] arm_smmu_device_shutdown+0xc/0x18 > [295711.698120] platform_drv_shutdown+0x20/0x30 > > [v11] >* Some more cleanups for device link. We don't need an explicit > delete for device link from the driver, but just set the flag > DL_FLAG_AUTOREMOVE. > device_link_add() API description says - > "If the DL_FLAG_AUTOREMOVE is set, the link will be removed > automatically when the consumer device driver unbinds." >* Addressed the comments for 'smmu' in arm_smmu_map/unmap(). >* Dropped the patch [7] that introduced device_link_del_dev() API. > > [v10] >* Introduce device_link_del_dev() API to delete the link between > given consumer and supplier devices. The users of device link > do not need to store link pointer to delete the link later. > They can straightaway use this API by passing consumer and > supplier devices. >* Made corresponding changes to arm-smmu driver patch handling the > device links. >* Dropped the patch [6] that was adding device_link_find() API to > device core layer. device_link_del_dev() serves the purpose to > directly delete the link between two given devices. > > [v9] >* Removed 'rpm_supported' flag, instead checking on pm_domain > to enable runtime pm. >* Creating device link only when the runtime pm is enabled, as we > don't need a device lin
[Freedreno] [PATCH v13 3/4] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- Changes since v12: - device_link_add() doesn't depend on pm_runtime_enabled() now. - Treat failure in device link addition as non-fatal. drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 15b20941441a..25ff3bdbf7a3 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1461,6 +1461,9 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER); + return 0; out_cfg_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v13 1/4] iommu/arm-smmu: Add pm_runtime/sleep ops
From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Also, while we enable the runtime pm add a pm sleep suspend callback that pushes devices to low power state by turning the clocks off in a system sleep. Also add corresponding clock enable path in resume callback. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: rework for clock and pm ops] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- Changes since v12: - Added pm sleep .suspend callback. This disables the clocks. - Added corresponding change to enable clocks in .resume pm sleep callback. drivers/iommu/arm-smmu.c | 75 ++-- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index c73cfce1ccc0..9138a6fffe04 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,8 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clks; + int num_clks; u32 cavium_id_base; /* Specific to Cavium */ @@ -1897,10 +1900,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) struct arm_smmu_match_data { enum arm_smmu_arch_version version; enum arm_smmu_implementation model; + const char * const *clks; + int num_clks; }; #define ARM_SMMU_MATCH_DATA(name, ver, imp)\ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -1919,6 +1924,23 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, + const char * const *clks) +{ + int i; + + if (smmu->num_clks < 1) + return; + + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, + sizeof(*smmu->clks), GFP_KERNEL); + if (!smmu->clks) + return; + + for (i = 0; i < smmu->num_clks; i++) + smmu->clks[i].id = clks[i]; +} + #ifdef CONFIG_ACPI static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) { @@ -2001,6 +2023,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->num_clks = data->num_clks; + + arm_smmu_fill_clk_data(smmu, data->clks); parse_driver_options(smmu); @@ -2099,6 +2124,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); + if (err) + return err; + + err = clk_bulk_prepare(smmu->num_clks, smmu->clks); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2181,6 +2214,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + + clk_bulk_unprepare(smmu->num_clks, smmu->clks); + return 0; } @@ -2189,15 +2225,50 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) arm_smmu_device_remove(pdev); } +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + return clk_bulk_enable(smmu->num_clks, smmu->clks); +} + +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + clk_bulk_disable(smmu->num_clks, smmu->clks); + + return 0; +} + static int __maybe_unused arm_smmu_pm_resume(struct device *dev) { struct arm_smmu_device *smmu = dev_get_drvdata(dev); + int ret; + +
[Freedreno] [PATCH v13 4/4] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. This smmu core is used with multiple masters on msm8996, viz. mdss, video, etc. Add bindings for the same. Signed-off-by: Vivek Gautam Reviewed-by: Rob Herring Reviewed-by: Tomasz Figa --- Change since v12: - Removed IOMMU_OF_DECLARE() definition after Rob H's patch that is merged in driver-core-next. .../devicetree/bindings/iommu/arm,smmu.txt | 42 ++ drivers/iommu/arm-smmu.c | 13 +++ 2 files changed, 55 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..7c71a6ed465a 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,10 +17,19 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,-smmu-v2", "qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. + A number of Qcom SoCs use qcom,smmu-v2 version of the IP. + "qcom,-smmu-v2" represents a soc specific compatible + string that should be present along with the "qcom,smmu-v2" + to facilitate SoC specific clocks/power connections and to + address specific bug fixes. + An example string would be - + "qcom,msm8996-smmu-v2", "qcom,smmu-v2". + - reg : Base address and size of the SMMU. - #global-interrupts : The number of global interrupts exposed by the @@ -71,6 +80,22 @@ conditions. or using stream matching with #iommu-cells = <2>, and may be ignored if present in such cases. +- clock-names:List of the names of clocks input to the device. The + required list depends on particular implementation and + is as follows: + - for "qcom,smmu-v2": +- "bus": clock required for downstream bus access and + for the smmu ptw, +- "iface": clock required to access smmu's registers + through the TCU's programming interface. + - unspecified for other implementations. + +- clocks: Specifiers for all clocks listed in the clock-names property, + as per generic clock bindings. + +- power-domains: Specifiers for power domains required to be powered on for + the SMMU to operate, as per generic power domain bindings. + ** Deprecated properties: - mmu-masters (deprecated in favour of the generic "iommus" binding) : @@ -137,3 +162,20 @@ conditions. iommu-map = <0 0 0x400>; ... }; + + /* Qcom's arm,smmu-v2 implementation */ + smmu4: iommu { + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; + reg = <0xd0 0x1>; + + #global-interrupts = <1>; + interrupts = , +, +; + #iommu-cells = <1>; + power-domains = < MDSS_GDSC>; + + clocks = < SMMU_MDP_AXI_CLK>, +< SMMU_MDP_AHB_CLK>; + clock-names = "bus", "iface"; + }; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 25ff3bdbf7a3..7c69736a30f8 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -119,6 +119,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -1971,6 +1972,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; + static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, { .compatible = "arm,smmu-v2", .data = _generic_v2 }, @@ -1978,6 +1990,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-401", .data = _mmu401 },
[Freedreno] [PATCH v13 2/4] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- Changes since v12: - Explicitly enabling and disabling clocks in probe and remove routines if runtime PM is disabled, drivers/iommu/arm-smmu.c | 101 +++ 1 file changed, 93 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 9138a6fffe04..15b20941441a 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -268,6 +268,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + return pm_runtime_get_sync(smmu->dev); + + return 0; +} + +static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_put(smmu->dev); +} + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -913,11 +927,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -932,6 +950,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + arm_smmu_rpm_put(smmu); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1213,10 +1233,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; smmu = fwspec_smmu(fwspec); + + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return ret; + /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); if (ret < 0) - return ret; + goto rpm_put; /* * Sanity check the domain. We don't support domains across @@ -1226,33 +1251,50 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); - return -EINVAL; + ret = -EINVAL; + goto rpm_put; } /* Looks ok, so add the device to the domain */ - return arm_smmu_domain_add_master(smmu_domain, fwspec); + ret = arm_smmu_domain_add_master(smmu_domain, fwspec); + +rpm_put: + arm_smmu_rpm_put(smmu); + return ret; } static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + int ret; if (!ops) return -ENODEV; - return ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_get(smmu); + ret = ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_put(smmu); + + return ret; } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + size_t ret; if (!ops) return 0; - return ops->unmap(ops, iova, size); + arm_smmu_rpm_get(smmu); + ret = ops->unmap(ops, iova, size); + arm_smmu_rpm_put(smmu); + + return ret; } static void arm_smmu_iotlb_sync(struct iommu_domain *domain) @@ -1407,7 +1449,13 @@ static int arm_smmu_add_device(struct device *dev) while (i--) cfg->smendx[i] = INVALID_SMENDX; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + goto out_cfg_free; + ret = arm_smmu_master_alloc_smes(de
[Freedreno] [PATCH v13 0/4] iommu/arm-smmu: Add runtime pm/sleep support
runtime pm, can enable, and we enable runtime_pm over arm-smmu only when this flag is set. - Adding the conditional pm_runtime_get/put() calls to .map, .unmap and .attach_dev ops. - Dropped the patch [3] that exported pm_runtim_get/put_suupliers(), and also dropped the user driver patch [4] for these APIs. * Clock code further cleanup - doing only clk_bulk_enable() and clk_bulk_disable() in runtime pm callbacks. We shouldn't be taking a slow path (clk_prepare/unprepare()) from these runtime pm callbacks. Thereby, moved clk_bulk_prepare() to arm_smmu_device_probe(), and clk_bulk_unprepare() to arm_smmu_device_remove(). - clk data filling to a common method arm_smmu_fill_clk_data() that fills the clock ids and number of clocks. * Addressed other nits and comments - device_link_add() error path fixed. - Fix for checking negative error value from pm_runtime_get_sync(). - Documentation redo. * Added another patch fixing the error path in arm_smmu_attach_dev() to destroy allocated domain context. [v7] * Addressed review comments given by Robin Murphy - - Added device_link_del() in .remove_device path. - Error path cleanup in arm_smmu_add_device(). - Added pm_runtime_get/put_sync() in .remove path, and replaced pm_runtime_force_suspend() with pm_runtime_disable(). - clk_names cleanup in arm_smmu_init_clks() * Added 'Reviewed-by' given by Rob H. ** Change logs for previous versions is available in last series [4]. [1] https://patchwork.kernel.org/patch/10204925/ [2] https://lkml.org/lkml/2018/7/8/124 [3] https://patchwork.kernel.org/patch/10204945/ [4] https://patchwork.kernel.org/patch/10204925/ [5] https://patchwork.kernel.org/patch/10254105/ [6] https://patchwork.kernel.org/patch/10277975/ [7] https://patchwork.kernel.org/patch/10281613/ [8] https://patchwork.kernel.org/patch/10491481/ [9] https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/log/?h=linux-next [10] https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git/log/?h=next Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (1): iommu/arm-smmu: Add support for qcom,smmu-v2 variant .../devicetree/bindings/iommu/arm,smmu.txt | 42 + drivers/iommu/arm-smmu.c | 192 +++-- 2 files changed, 224 insertions(+), 10 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v12 3/4] iommu/arm-smmu: Add the device_link between masters and smmu
On Wed, Jul 11, 2018 at 3:23 PM, Rafael J. Wysocki wrote: > On Sunday, July 8, 2018 7:34:12 PM CEST Vivek Gautam wrote: >> From: Sricharan R >> >> Finally add the device link between the master device and >> smmu, so that the smmu gets runtime enabled/disabled only when the >> master needs it. This is done from add_device callback which gets >> called once when the master is added to the smmu. >> >> Signed-off-by: Sricharan R >> Signed-off-by: Vivek Gautam >> Reviewed-by: Tomasz Figa >> Cc: Rafael J. Wysocki >> Cc: Lukas Wunner >> --- >> >> - Change since v11 >>* Replaced DL_FLAG_AUTOREMOVE flag with DL_FLAG_AUTOREMOVE_SUPPLIER. >> >> drivers/iommu/arm-smmu.c | 12 >> 1 file changed, 12 insertions(+) >> >> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c >> index 09265e206e2d..916cde4954d2 100644 >> --- a/drivers/iommu/arm-smmu.c >> +++ b/drivers/iommu/arm-smmu.c >> @@ -1461,8 +1461,20 @@ static int arm_smmu_add_device(struct device *dev) >> >> iommu_device_link(>iommu, dev); >> >> + if (pm_runtime_enabled(smmu->dev) && > > Why does the creation of the link depend on whether or not runtime PM > is enabled for the MMU device? > > What about system-wide PM and system shutdown? Are they always guaranteed > to happen in the right order without the link? Hi Robin, As Rafael pointed, we should the device link creation should not depend on runtime PM being enabled or not, as we would also want to guarantee that system wide PM callbacks are called in the right order for smmu and clients. Does this change of removing the check for pm_runtime_enabled() from here looks okay to you? FYI, as discussed in the first patch [1] of this series, I will add a system wide suspend callback - arm_smmu_pm_suspend, that would do clock disable, and will add corresponding clock enable calls in arm_smmu_pm_resume(). [1] https://lore.kernel.org/patchwork/patch/960460/ Best regards Vivek > >> + !device_link_add(dev, smmu->dev, >> + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER)) { >> + dev_err(smmu->dev, "Unable to add link to the consumer %s\n", >> + dev_name(dev)); >> + ret = -ENODEV; >> + goto out_unlink; >> + } >> + >> return 0; >> >> +out_unlink: >> + iommu_device_unlink(>iommu, dev); >> + arm_smmu_master_free_smes(fwspec); >> out_cfg_free: >> kfree(cfg); >> out_free: >> > > -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v12 3/4] iommu/arm-smmu: Add the device_link between masters and smmu
On 7/17/2018 1:16 PM, Rafael J. Wysocki wrote: On Mon, Jul 16, 2018 at 1:46 PM, Vivek Gautam wrote: On 7/16/2018 2:25 PM, Rafael J. Wysocki wrote: On Thu, Jul 12, 2018 at 2:41 PM, Vivek Gautam wrote: Hi Rafael, On Wed, Jul 11, 2018 at 4:06 PM, Vivek Gautam wrote: Hi Rafael, On 7/11/2018 3:23 PM, Rafael J. Wysocki wrote: On Sunday, July 8, 2018 7:34:12 PM CEST Vivek Gautam wrote: From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Cc: Rafael J. Wysocki Cc: Lukas Wunner --- - Change since v11 * Replaced DL_FLAG_AUTOREMOVE flag with DL_FLAG_AUTOREMOVE_SUPPLIER. drivers/iommu/arm-smmu.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 09265e206e2d..916cde4954d2 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1461,8 +1461,20 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + if (pm_runtime_enabled(smmu->dev) && Why does the creation of the link depend on whether or not runtime PM is enabled for the MMU device? The main purpose of this device link is to handle the runtime PM synchronization between the supplier (iommu) and consumer (client devices, such as GPU/display). Moreover, the runtime pm is conditionally enabled for smmu devices that support such [1]. Is there something you would like me to modify in this patch? Not really, as long as you are sure that it is correct. :-) You need to remember, however, that if you add system-wide PM callbacks to the driver, the ordering between them and the client device callbacks during system-wide suspend matters as well. Don't you need the link the ensure the correct system-wide suspend ordering too? The fact that currently we handle clocks only through runtime pm callbacks, would it be better to call runtime pm put/get in system-wide PM callbacks. This would be same as i mentioned in the other thread. Well, my point is that there's no reason for system-wide suspend to depend directly on runtime PM (which can be effectively disabled by user space as mentioned for multiple times in this thread). It simply is not efficient to let the clock run while the system as a whole is sleeping (even if power/control has been set to "on" for this particular device) and it should not be too hard to prevent that from happening. You may need an additional flag in the driver for that or similar, but it definitely should be doable. Right, I will modify the things are required. Thanks again for pointing this out. Best regards Vivek Now, that's my advice and I'm not the maintainer of that code, so it is your call (as long as the maintainer agrees with it). Thanks, Rafael ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v12 3/4] iommu/arm-smmu: Add the device_link between masters and smmu
On 7/16/2018 2:25 PM, Rafael J. Wysocki wrote: On Thu, Jul 12, 2018 at 2:41 PM, Vivek Gautam wrote: Hi Rafael, On Wed, Jul 11, 2018 at 4:06 PM, Vivek Gautam wrote: Hi Rafael, On 7/11/2018 3:23 PM, Rafael J. Wysocki wrote: On Sunday, July 8, 2018 7:34:12 PM CEST Vivek Gautam wrote: From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Cc: Rafael J. Wysocki Cc: Lukas Wunner --- - Change since v11 * Replaced DL_FLAG_AUTOREMOVE flag with DL_FLAG_AUTOREMOVE_SUPPLIER. drivers/iommu/arm-smmu.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 09265e206e2d..916cde4954d2 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1461,8 +1461,20 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + if (pm_runtime_enabled(smmu->dev) && Why does the creation of the link depend on whether or not runtime PM is enabled for the MMU device? The main purpose of this device link is to handle the runtime PM synchronization between the supplier (iommu) and consumer (client devices, such as GPU/display). Moreover, the runtime pm is conditionally enabled for smmu devices that support such [1]. Is there something you would like me to modify in this patch? Not really, as long as you are sure that it is correct. :-) You need to remember, however, that if you add system-wide PM callbacks to the driver, the ordering between them and the client device callbacks during system-wide suspend matters as well. Don't you need the link the ensure the correct system-wide suspend ordering too? The fact that currently we handle clocks only through runtime pm callbacks, would it be better to call runtime pm put/get in system-wide PM callbacks. This would be same as i mentioned in the other thread. Best regards Vivek -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v12 1/4] iommu/arm-smmu: Add pm_runtime/sleep ops
HI Rafael, On 7/16/2018 2:21 PM, Rafael J. Wysocki wrote: On Thu, Jul 12, 2018 at 12:57 PM, Vivek Gautam wrote: Hi, On Wed, Jul 11, 2018 at 6:21 PM, Tomasz Figa wrote: On Wed, Jul 11, 2018 at 8:11 PM Rafael J. Wysocki wrote: On Wed, Jul 11, 2018 at 12:55 PM, Vivek Gautam wrote: Hi Rafael, On Wed, Jul 11, 2018 at 3:20 PM, Rafael J. Wysocki wrote: On Sunday, July 8, 2018 7:34:10 PM CEST Vivek Gautam wrote: From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: Clock rework to request bulk of clocks] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- - No change since v11. drivers/iommu/arm-smmu.c | 60 ++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f7a96bcf94a6..a01d0dde21dd 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,8 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clks; + int num_clks; u32 cavium_id_base; /* Specific to Cavium */ @@ -1897,10 +1900,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) struct arm_smmu_match_data { enum arm_smmu_arch_version version; enum arm_smmu_implementation model; + const char * const *clks; + int num_clks; }; #define ARM_SMMU_MATCH_DATA(name, ver, imp) \ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -1919,6 +1924,23 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, +const char * const *clks) +{ + int i; + + if (smmu->num_clks < 1) + return; + + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, + sizeof(*smmu->clks), GFP_KERNEL); + if (!smmu->clks) + return; + + for (i = 0; i < smmu->num_clks; i++) + smmu->clks[i].id = clks[i]; +} + #ifdef CONFIG_ACPI static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) { @@ -2001,6 +2023,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->num_clks = data->num_clks; + + arm_smmu_fill_clk_data(smmu, data->clks); parse_driver_options(smmu); @@ -2099,6 +2124,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); + if (err) + return err; + + err = clk_bulk_prepare(smmu->num_clks, smmu->clks); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2181,6 +2214,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + + clk_bulk_unprepare(smmu->num_clks, smmu->clks); + return 0; } @@ -2197,7 +2233,27 @@ static int __maybe_unused arm_smmu_pm_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + return clk_bulk_enable(smmu->num_clks, smmu->clks); +} + +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + clk_bulk_disable(smmu->num_clks, smmu->clks); + + return 0; +} + +static const struct dev_pm_ops arm_smmu_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(NULL, arm
Re: [Freedreno] [PATCH v12 3/4] iommu/arm-smmu: Add the device_link between masters and smmu
Hi Rafael, On Wed, Jul 11, 2018 at 4:06 PM, Vivek Gautam wrote: > Hi Rafael, > > > > On 7/11/2018 3:23 PM, Rafael J. Wysocki wrote: >> >> On Sunday, July 8, 2018 7:34:12 PM CEST Vivek Gautam wrote: >>> >>> From: Sricharan R >>> >>> Finally add the device link between the master device and >>> smmu, so that the smmu gets runtime enabled/disabled only when the >>> master needs it. This is done from add_device callback which gets >>> called once when the master is added to the smmu. >>> >>> Signed-off-by: Sricharan R >>> Signed-off-by: Vivek Gautam >>> Reviewed-by: Tomasz Figa >>> Cc: Rafael J. Wysocki >>> Cc: Lukas Wunner >>> --- >>> >>> - Change since v11 >>> * Replaced DL_FLAG_AUTOREMOVE flag with DL_FLAG_AUTOREMOVE_SUPPLIER. >>> >>> drivers/iommu/arm-smmu.c | 12 >>> 1 file changed, 12 insertions(+) >>> >>> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c >>> index 09265e206e2d..916cde4954d2 100644 >>> --- a/drivers/iommu/arm-smmu.c >>> +++ b/drivers/iommu/arm-smmu.c >>> @@ -1461,8 +1461,20 @@ static int arm_smmu_add_device(struct device *dev) >>> iommu_device_link(>iommu, dev); >>> + if (pm_runtime_enabled(smmu->dev) && >> >> Why does the creation of the link depend on whether or not runtime PM >> is enabled for the MMU device? > > > The main purpose of this device link is to handle the runtime PM > synchronization > between the supplier (iommu) and consumer (client devices, such as > GPU/display). > Moreover, the runtime pm is conditionally enabled for smmu devices that > support > such [1]. Is there something you would like me to modify in this patch? Best regards Vivek >> >> >> What about system-wide PM and system shutdown? Are they always guaranteed >> to happen in the right order without the link? > > > When there's no runtime PM, there's no clocks, and other resources to be > handled. > So, we don't need device link for system-wide PM and system shutdown to work > correctly. > That's the case with current arm-smmu driver. > Is it something that i am missing here? > > [1] https://lkml.org/lkml/2018/3/8/775 > > Thanks > Vivek >>> >>> + !device_link_add(dev, smmu->dev, >>> + DL_FLAG_PM_RUNTIME | >>> DL_FLAG_AUTOREMOVE_SUPPLIER)) { >>> + dev_err(smmu->dev, "Unable to add link to the consumer >>> %s\n", >>> + dev_name(dev)); >>> + ret = -ENODEV; >>> + goto out_unlink; >>> + } >>> + >>> return 0; >>> +out_unlink: >>> + iommu_device_unlink(>iommu, dev); >>> + arm_smmu_master_free_smes(fwspec); >>> out_cfg_free: >>> kfree(cfg); >>> out_free: >>> >> > > -- > To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v12 2/4] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
On 7/11/2018 4:29 PM, Rafael J. Wysocki wrote: On Wed, Jul 11, 2018 at 12:05 PM, Tomasz Figa wrote: Hi Rafael, Thanks for review. On Wed, Jul 11, 2018 at 6:53 PM Rafael J. Wysocki wrote: On Sunday, July 8, 2018 7:34:11 PM CEST Vivek Gautam wrote: From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- - Change since v11 * Replaced pm_runtime_disable() with pm_runtime_force_suspend() to avoid warning about " Unpreparing enabled clock". Full warning text mentioned in cover patch. drivers/iommu/arm-smmu.c | 92 +++- 1 file changed, 84 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index a01d0dde21dd..09265e206e2d 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -268,6 +268,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) Why do you need the pm_runtime_enabled() checks here and below? pm_runtime_get_sync() and pm_runtime_put() should work just fine if runtime PM is not enabled. Because pm_runtime_get_sync() acquires a spin lock, even if only for the short time of checking if runtime PM is enabled and SMMU driver maintainers didn't want any spin locks in certain IOMMU API code paths on hardware implementations that don't need runtime PM, while we still need to be able to control runtime PM there on hardware implementations that need so. OK, so it is an optimization. It would be good to put a comment in there to that effect. Yea, actually there's a comment placed in arm_smmu_device_probe() where the runtime PM is conditionally enabled. I can add comments for these wrappers too if you would like. Thanks & Regards Vivek ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH v12 1/4] iommu/arm-smmu: Add pm_runtime/sleep ops
Hi Rafael, On Wed, Jul 11, 2018 at 3:20 PM, Rafael J. Wysocki wrote: > On Sunday, July 8, 2018 7:34:10 PM CEST Vivek Gautam wrote: >> From: Sricharan R >> >> The smmu needs to be functional only when the respective >> master's using it are active. The device_link feature >> helps to track such functional dependencies, so that the >> iommu gets powered when the master device enables itself >> using pm_runtime. So by adapting the smmu driver for >> runtime pm, above said dependency can be addressed. >> >> This patch adds the pm runtime/sleep callbacks to the >> driver and also the functions to parse the smmu clocks >> from DT and enable them in resume/suspend. >> >> Signed-off-by: Sricharan R >> Signed-off-by: Archit Taneja >> [vivek: Clock rework to request bulk of clocks] >> Signed-off-by: Vivek Gautam >> Reviewed-by: Tomasz Figa >> --- >> >> - No change since v11. >> >> drivers/iommu/arm-smmu.c | 60 >> ++-- >> 1 file changed, 58 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c >> index f7a96bcf94a6..a01d0dde21dd 100644 >> --- a/drivers/iommu/arm-smmu.c >> +++ b/drivers/iommu/arm-smmu.c >> @@ -48,6 +48,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> >> @@ -205,6 +206,8 @@ struct arm_smmu_device { >> u32 num_global_irqs; >> u32 num_context_irqs; >> unsigned int*irqs; >> + struct clk_bulk_data*clks; >> + int num_clks; >> >> u32 cavium_id_base; /* Specific to Cavium >> */ >> >> @@ -1897,10 +1900,12 @@ static int arm_smmu_device_cfg_probe(struct >> arm_smmu_device *smmu) >> struct arm_smmu_match_data { >> enum arm_smmu_arch_version version; >> enum arm_smmu_implementation model; >> + const char * const *clks; >> + int num_clks; >> }; >> >> #define ARM_SMMU_MATCH_DATA(name, ver, imp) \ >> -static struct arm_smmu_match_data name = { .version = ver, .model = imp } >> +static const struct arm_smmu_match_data name = { .version = ver, .model = >> imp } >> >> ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); >> ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); >> @@ -1919,6 +1924,23 @@ static const struct of_device_id arm_smmu_of_match[] >> = { >> }; >> MODULE_DEVICE_TABLE(of, arm_smmu_of_match); >> >> +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, >> +const char * const *clks) >> +{ >> + int i; >> + >> + if (smmu->num_clks < 1) >> + return; >> + >> + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, >> + sizeof(*smmu->clks), GFP_KERNEL); >> + if (!smmu->clks) >> + return; >> + >> + for (i = 0; i < smmu->num_clks; i++) >> + smmu->clks[i].id = clks[i]; >> +} >> + >> #ifdef CONFIG_ACPI >> static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) >> { >> @@ -2001,6 +2023,9 @@ static int arm_smmu_device_dt_probe(struct >> platform_device *pdev, >> data = of_device_get_match_data(dev); >> smmu->version = data->version; >> smmu->model = data->model; >> + smmu->num_clks = data->num_clks; >> + >> + arm_smmu_fill_clk_data(smmu, data->clks); >> >> parse_driver_options(smmu); >> >> @@ -2099,6 +2124,14 @@ static int arm_smmu_device_probe(struct >> platform_device *pdev) >> smmu->irqs[i] = irq; >> } >> >> + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); >> + if (err) >> + return err; >> + >> + err = clk_bulk_prepare(smmu->num_clks, smmu->clks); >> + if (err) >> + return err; >> + >> err = arm_smmu_device_cfg_probe(smmu); >> if (err) >> return err; >> @@ -2181,6 +2214,9 @@ static int arm_smmu_device_remove(struct >> platform_device *pdev) >> >> /* Turn the thing off */ >> writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
Re: [Freedreno] [PATCH v12 3/4] iommu/arm-smmu: Add the device_link between masters and smmu
Hi Rafael, On 7/11/2018 3:23 PM, Rafael J. Wysocki wrote: On Sunday, July 8, 2018 7:34:12 PM CEST Vivek Gautam wrote: From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Cc: Rafael J. Wysocki Cc: Lukas Wunner --- - Change since v11 * Replaced DL_FLAG_AUTOREMOVE flag with DL_FLAG_AUTOREMOVE_SUPPLIER. drivers/iommu/arm-smmu.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 09265e206e2d..916cde4954d2 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1461,8 +1461,20 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + if (pm_runtime_enabled(smmu->dev) && Why does the creation of the link depend on whether or not runtime PM is enabled for the MMU device? The main purpose of this device link is to handle the runtime PM synchronization between the supplier (iommu) and consumer (client devices, such as GPU/display). Moreover, the runtime pm is conditionally enabled for smmu devices that support such [1]. What about system-wide PM and system shutdown? Are they always guaranteed to happen in the right order without the link? When there's no runtime PM, there's no clocks, and other resources to be handled. So, we don't need device link for system-wide PM and system shutdown to work correctly. That's the case with current arm-smmu driver. Is it something that i am missing here? [1] https://lkml.org/lkml/2018/3/8/775 Thanks Vivek + !device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER)) { + dev_err(smmu->dev, "Unable to add link to the consumer %s\n", + dev_name(dev)); + ret = -ENODEV; + goto out_unlink; + } + return 0; +out_unlink: + iommu_device_unlink(>iommu, dev); + arm_smmu_master_free_smes(fwspec); out_cfg_free: kfree(cfg); out_free: ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v12 3/4] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan R Finally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa Cc: Rafael J. Wysocki Cc: Lukas Wunner --- - Change since v11 * Replaced DL_FLAG_AUTOREMOVE flag with DL_FLAG_AUTOREMOVE_SUPPLIER. drivers/iommu/arm-smmu.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 09265e206e2d..916cde4954d2 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1461,8 +1461,20 @@ static int arm_smmu_add_device(struct device *dev) iommu_device_link(>iommu, dev); + if (pm_runtime_enabled(smmu->dev) && + !device_link_add(dev, smmu->dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER)) { + dev_err(smmu->dev, "Unable to add link to the consumer %s\n", + dev_name(dev)); + ret = -ENODEV; + goto out_unlink; + } + return 0; +out_unlink: + iommu_device_unlink(>iommu, dev); + arm_smmu_master_free_smes(fwspec); out_cfg_free: kfree(cfg); out_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v12 0/4] iommu/arm-smmu: Add runtime pm/sleep support
me pm callbacks. We shouldn't be taking a slow path (clk_prepare/unprepare()) from these runtime pm callbacks. Thereby, moved clk_bulk_prepare() to arm_smmu_device_probe(), and clk_bulk_unprepare() to arm_smmu_device_remove(). - clk data filling to a common method arm_smmu_fill_clk_data() that fills the clock ids and number of clocks. * Addressed other nits and comments - device_link_add() error path fixed. - Fix for checking negative error value from pm_runtime_get_sync(). - Documentation redo. * Added another patch fixing the error path in arm_smmu_attach_dev() to destroy allocated domain context. [v7] * Addressed review comments given by Robin Murphy - - Added device_link_del() in .remove_device path. - Error path cleanup in arm_smmu_add_device(). - Added pm_runtime_get/put_sync() in .remove path, and replaced pm_runtime_force_suspend() with pm_runtime_disable(). - clk_names cleanup in arm_smmu_init_clks() * Added 'Reviewed-by' given by Rob H. [V6] * Added Ack given by Rafael to first patch in the series. * Addressed Rob Herring's comment for adding soc specific compatible string as well besides 'qcom,smmu-v2'. [V5] * Dropped runtime pm calls from "arm_smmu_unmap" op as discussed over the list [3] for the last patch series. * Added a patch to export pm_runtime_get/put_suppliers() APIs to the series as agreed with Rafael [4]. * Added the related patch for msm drm iommu layer to use pm_runtime_get/put_suppliers() APIs in msm_mmu_funcs. * Dropped arm-mmu500 clock patch since that would break existing platforms. * Changed compatible 'qcom,msm8996-smmu-v2' to 'qcom,smmu-v2' to reflect the IP version rather than the platform on which it is used. The same IP is used across multiple platforms including msm8996, and sdm845 etc. * Using clock bulk APIs to handle the clocks available to the IP as suggested by Stephen Boyd. * The first patch in v4 version of the patch-series: ("iommu/arm-smmu: Fix the error path in arm_smmu_add_device") has already made it to mainline. [V4] * Reworked the clock handling part. We now take clock names as data in the driver for supported compatible versions, and loop over them to get, enable, and disable the clocks. * Using qcom,msm8996 based compatibles for bindings instead of a generic qcom compatible. * Refactor MMU500 patch to just add the necessary clock names data and corresponding bindings. * Added the pm_runtime_get/put() calls in .unmap iommu op (fix added by Stanimir on top of previous patch version. * Added a patch to fix error path in arm_smmu_add_device() * Removed patch 3/5 of V3 patch series that added qcom,smmu-v2 bindings. [V3] * Reworked the patches to keep the clocks init/enabling function separately for each compatible. * Added clocks bindings for MMU40x/500. * Added a new compatible for qcom,smmu-v2 implementation and the clock bindings for the same. * Rebased on top of 4.11-rc1 [V2] * Split the patches little differently. * Addressed comments. * Removed the patch #4 [2] from previous post for arm-smmu context save restore. Planning to post this separately after reworking/addressing Robin's feedback. * Reversed the sequence to disable clocks than enabling. This was required for those cases where the clocks are populated in a dependent order from DT. [1] https://lkml.org/lkml/2016/10/20/70 [2] https://patchwork.kernel.org/patch/9389717/ [3] https://patchwork.kernel.org/patch/10204925/ [4] https://patchwork.kernel.org/patch/10102445/ [5] https://lkml.org/lkml/2018/3/22/191 [6] https://patchwork.kernel.org/patch/10204945/ [7] https://patchwork.kernel.org/patch/10204925/ [8] https://patchwork.kernel.org/patch/10254105/ [9] https://patchwork.kernel.org/patch/10277975/ [10] https://patchwork.kernel.org/patch/10281613/ [11] https://patchwork.kernel.org/patch/10491481/ Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (1): iommu/arm-smmu: Add support for qcom,smmu-v2 variant .../devicetree/bindings/iommu/arm,smmu.txt | 42 + drivers/iommu/arm-smmu.c | 178 +++-- 2 files changed, 210 insertions(+), 10 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
[Freedreno] [PATCH v12 2/4] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
From: Sricharan R The smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- - Change since v11 * Replaced pm_runtime_disable() with pm_runtime_force_suspend() to avoid warning about " Unpreparing enabled clock". Full warning text mentioned in cover patch. drivers/iommu/arm-smmu.c | 92 +++- 1 file changed, 84 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index a01d0dde21dd..09265e206e2d 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -268,6 +268,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { 0, NULL}, }; +static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + return pm_runtime_get_sync(smmu->dev); + + return 0; +} + +static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) +{ + if (pm_runtime_enabled(smmu->dev)) + pm_runtime_put(smmu->dev); +} + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -913,11 +927,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -932,6 +950,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + arm_smmu_rpm_put(smmu); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1213,10 +1233,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return -ENODEV; smmu = fwspec_smmu(fwspec); + + ret = arm_smmu_rpm_get(smmu); + if (ret < 0) + return ret; + /* Ensure that the domain is finalised */ ret = arm_smmu_init_domain_context(domain, smmu); if (ret < 0) - return ret; + goto rpm_put; /* * Sanity check the domain. We don't support domains across @@ -1226,33 +1251,50 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); - return -EINVAL; + ret = -EINVAL; + goto rpm_put; } /* Looks ok, so add the device to the domain */ - return arm_smmu_domain_add_master(smmu_domain, fwspec); + ret = arm_smmu_domain_add_master(smmu_domain, fwspec); + +rpm_put: + arm_smmu_rpm_put(smmu); + return ret; } static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + int ret; if (!ops) return -ENODEV; - return ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_get(smmu); + ret = ops->map(ops, iova, paddr, size, prot); + arm_smmu_rpm_put(smmu); + + return ret; } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; + struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + size_t ret; if (!ops) return 0; - return ops->unmap(ops, iova, size); + arm_smmu_rpm_get(smmu); + ret = ops->unmap(ops, iova, size); + arm_smmu_rpm_put(smmu); + + return ret; } static void arm_smmu_iotlb_sync(struct iommu_domain *domain) @@ -1407,7 +1449,13 @@ static int arm_smmu_add_device(struct device *dev) while (i--) cfg->smendx[i] = INVALID_SMENDX; + ret = arm_smmu_rpm_get(smmu); +
[Freedreno] [PATCH v12 4/4] iommu/arm-smmu: Add support for qcom, smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. This smmu core is used with multiple masters on msm8996, viz. mdss, video, etc. Add bindings for the same. Signed-off-by: Vivek Gautam Reviewed-by: Rob Herring Reviewed-by: Tomasz Figa --- - No change since v11. .../devicetree/bindings/iommu/arm,smmu.txt | 42 ++ drivers/iommu/arm-smmu.c | 14 2 files changed, 56 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..7c71a6ed465a 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,10 +17,19 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,-smmu-v2", "qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. + A number of Qcom SoCs use qcom,smmu-v2 version of the IP. + "qcom,-smmu-v2" represents a soc specific compatible + string that should be present along with the "qcom,smmu-v2" + to facilitate SoC specific clocks/power connections and to + address specific bug fixes. + An example string would be - + "qcom,msm8996-smmu-v2", "qcom,smmu-v2". + - reg : Base address and size of the SMMU. - #global-interrupts : The number of global interrupts exposed by the @@ -71,6 +80,22 @@ conditions. or using stream matching with #iommu-cells = <2>, and may be ignored if present in such cases. +- clock-names:List of the names of clocks input to the device. The + required list depends on particular implementation and + is as follows: + - for "qcom,smmu-v2": +- "bus": clock required for downstream bus access and + for the smmu ptw, +- "iface": clock required to access smmu's registers + through the TCU's programming interface. + - unspecified for other implementations. + +- clocks: Specifiers for all clocks listed in the clock-names property, + as per generic clock bindings. + +- power-domains: Specifiers for power domains required to be powered on for + the SMMU to operate, as per generic power domain bindings. + ** Deprecated properties: - mmu-masters (deprecated in favour of the generic "iommus" binding) : @@ -137,3 +162,20 @@ conditions. iommu-map = <0 0 0x400>; ... }; + + /* Qcom's arm,smmu-v2 implementation */ + smmu4: iommu { + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; + reg = <0xd0 0x1>; + + #global-interrupts = <1>; + interrupts = , +, +; + #iommu-cells = <1>; + power-domains = < MDSS_GDSC>; + + clocks = < SMMU_MDP_AXI_CLK>, +< SMMU_MDP_AHB_CLK>; + clock-names = "bus", "iface"; + }; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 916cde4954d2..a9edb17f09bf 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -119,6 +119,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -1980,6 +1981,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; + static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, { .compatible = "arm,smmu-v2", .data = _generic_v2 }, @@ -1987,6 +1999,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-401", .data = _mmu401 }, { .compatible = "arm,mmu-500", .data = _mmu500 }, { .co
[Freedreno] [PATCH v12 1/4] iommu/arm-smmu: Add pm_runtime/sleep ops
From: Sricharan R The smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: Clock rework to request bulk of clocks] Signed-off-by: Vivek Gautam Reviewed-by: Tomasz Figa --- - No change since v11. drivers/iommu/arm-smmu.c | 60 ++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f7a96bcf94a6..a01d0dde21dd 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,8 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clks; + int num_clks; u32 cavium_id_base; /* Specific to Cavium */ @@ -1897,10 +1900,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) struct arm_smmu_match_data { enum arm_smmu_arch_version version; enum arm_smmu_implementation model; + const char * const *clks; + int num_clks; }; #define ARM_SMMU_MATCH_DATA(name, ver, imp)\ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -1919,6 +1924,23 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu, + const char * const *clks) +{ + int i; + + if (smmu->num_clks < 1) + return; + + smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks, + sizeof(*smmu->clks), GFP_KERNEL); + if (!smmu->clks) + return; + + for (i = 0; i < smmu->num_clks; i++) + smmu->clks[i].id = clks[i]; +} + #ifdef CONFIG_ACPI static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu) { @@ -2001,6 +2023,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->num_clks = data->num_clks; + + arm_smmu_fill_clk_data(smmu, data->clks); parse_driver_options(smmu); @@ -2099,6 +2124,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks); + if (err) + return err; + + err = clk_bulk_prepare(smmu->num_clks, smmu->clks); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2181,6 +2214,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + + clk_bulk_unprepare(smmu->num_clks, smmu->clks); + return 0; } @@ -2197,7 +2233,27 @@ static int __maybe_unused arm_smmu_pm_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + return clk_bulk_enable(smmu->num_clks, smmu->clks); +} + +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + clk_bulk_disable(smmu->num_clks, smmu->clks); + + return 0; +} + +static const struct dev_pm_ops arm_smmu_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(NULL, arm_smmu_pm_resume) + SET_RUNTIME_PM_OPS(arm_smmu_runtime_suspend, + arm_smmu_runtime_resume, NULL) +}; static struct platform_driver arm_smmu_driver = { .driver = { -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___
Re: [Freedreno] [PATCH 1/5] drm/msm: Remove pm_runtime operations from msm_iommu
Hi Jordan, On Mon, Jun 11, 2018 at 11:56 PM, Jordan Crouse wrote: > Now that the IOMMU is the master of it's own power we don't need to bring > up the GPU to do IOMMU operations. This is good because bringing up a6xx > requires the GMU so calling pm_runtime_get_sync() too early in the process > gets us into some nasty circular dependency situations. Thanks for the patch. While you are removing these calls, we should add pm_runtime calls to qcom_iommu_map(). That should make qcom_iommu too master of its power control. Then we should be good to go with this patch. > > Signed-off-by: Jordan Crouse > --- > drivers/gpu/drm/msm/msm_iommu.c | 8 > 1 file changed, 8 deletions(-) > > diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c > index b23d33622f37..ccd93ac6a4d8 100644 > --- a/drivers/gpu/drm/msm/msm_iommu.c > +++ b/drivers/gpu/drm/msm/msm_iommu.c > @@ -40,9 +40,7 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char > * const *names, > struct msm_iommu *iommu = to_msm_iommu(mmu); > int ret; > > - pm_runtime_get_sync(mmu->dev); > ret = iommu_attach_device(iommu->domain, mmu->dev); > - pm_runtime_put_sync(mmu->dev); may be just do the following here. return iommu_attach_device(iommu->domain, mmu->dev); Rest looks good. So after the change. Reviewed-by: Vivek Gautam Best regards Vivek > > return ret; > } > @@ -52,9 +50,7 @@ static void msm_iommu_detach(struct msm_mmu *mmu, const > char * const *names, > { > struct msm_iommu *iommu = to_msm_iommu(mmu); > > - pm_runtime_get_sync(mmu->dev); > iommu_detach_device(iommu->domain, mmu->dev); > - pm_runtime_put_sync(mmu->dev); > } > > static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, > @@ -63,9 +59,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, > struct msm_iommu *iommu = to_msm_iommu(mmu); > size_t ret; > > -// pm_runtime_get_sync(mmu->dev); > ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot); > -// pm_runtime_put_sync(mmu->dev); > WARN_ON(ret < 0); > > return (ret == len) ? 0 : -EINVAL; > @@ -76,9 +70,7 @@ static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t > iova, > { > struct msm_iommu *iommu = to_msm_iommu(mmu); > > - pm_runtime_get_sync(mmu->dev); > iommu_unmap(iommu->domain, iova, len); > - pm_runtime_put_sync(mmu->dev); > > return 0; > } > -- > 2.17.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH 5/5] drm/msm/A6xx: Add support for using system cache(llc)
Hi Sharat, On 3/23/2018 12:49 PM, Sharat Masetty wrote: The last level system cache can be partitioned to 32 different slices of which GPU has two slices preallocated. The "gpu" slice is used for caching GPU buffers and the "gpuhtw" slice is used for caching the GPU SMMU pagetables. This patch talks to the core system cache driver to acquire the slice handles, configure the SCID's to those slices and activates and deactivates the slices upon GPU power collapse and restore. Some support from the IOMMU driver is also needed to make use of the system cache. IOMMU_UPSTREAM_HINT is a buffer protection flag which enables caching GPU data buffers in the system cache with memory attributes such as outer cacheable, read-allocate, write-allocate for buffers. The GPU then has the ability to override a few cacheability parameters which it does to override write-allocate to write-no-allocate as the GPU hardware does not benefit much from it. Similarly DOMAIN_ATTR_USE_UPSTREAM_HINT is another domain level attribute used by the IOMMU driver to set the right attributes to cache the hardware pagetables into the system cache. Signed-off-by: Sharat Masetty--- Couple of minor nits. Please see comments inline below. drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 162 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 9 ++ drivers/gpu/drm/msm/msm_iommu.c | 13 +++ drivers/gpu/drm/msm/msm_mmu.h | 3 + 4 files changed, 186 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index bd50674..e4554eb 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -13,6 +13,7 @@ #include #include +#include #include "msm_gem.h" #include "msm_mmu.h" @@ -913,6 +914,154 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu) ~0 }; +#define A6XX_LLC_NUM_GPU_SCIDS 5 +#define A6XX_GPU_LLC_SCID_NUM_BITS 5 + +#define A6XX_GPU_LLC_SCID_MASK \ + ((1 << (A6XX_LLC_NUM_GPU_SCIDS * A6XX_GPU_LLC_SCID_NUM_BITS)) - 1) + +#define A6XX_GPUHTW_LLC_SCID_SHIFT 25 +#define A6XX_GPUHTW_LLC_SCID_MASK \ + (((1 << A6XX_GPU_LLC_SCID_NUM_BITS) - 1) << A6XX_GPUHTW_LLC_SCID_SHIFT) + +static inline void a6xx_gpu_cx_rmw(struct a6xx_llc *llc, + u32 reg, u32 mask, u32 or) +{ + msm_rmw(llc->mmio + (reg << 2), mask, or); +} + +static void a6xx_llc_deactivate(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + struct a6xx_llc *llc = _gpu->llc; + + llcc_slice_deactivate(llc->gpu_llc_slice); + llcc_slice_deactivate(llc->gpuhtw_llc_slice); +} + +static void a6xx_llc_activate(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + struct a6xx_llc *llc = _gpu->llc; + + if (!llc->mmio) + return; + + if (llc->gpu_llc_slice) + if (!llcc_slice_activate(llc->gpu_llc_slice)) + /* Program the sub-cache ID for all GPU blocks */ + a6xx_gpu_cx_rmw(llc, + REG_A6XX_GPU_CX_MISC_SYSTEM_CACHE_CNTL_1, + A6XX_GPU_LLC_SCID_MASK, + (llc->cntl1_regval & + A6XX_GPU_LLC_SCID_MASK)); + + if (llc->gpuhtw_llc_slice) + if (!llcc_slice_activate(llc->gpuhtw_llc_slice)) + /* Program the sub-cache ID for GPU pagetables */ + a6xx_gpu_cx_rmw(llc, + REG_A6XX_GPU_CX_MISC_SYSTEM_CACHE_CNTL_1, + A6XX_GPUHTW_LLC_SCID_MASK, + (llc->cntl1_regval & + A6XX_GPUHTW_LLC_SCID_MASK)); + + /* Program cacheability overrides */ + a6xx_gpu_cx_rmw(llc, REG_A6XX_GPU_CX_MISC_SYSTEM_CACHE_CNTL_0, 0xF, + llc->cntl0_regval); +} + +void a6xx_llc_slices_destroy(struct a6xx_llc *llc) static? +{ + if (llc->mmio) { + iounmap(llc->mmio); + llc->mmio = NULL; + } + + llcc_slice_putd(llc->gpu_llc_slice); + llc->gpu_llc_slice = NULL; + + llcc_slice_putd(llc->gpuhtw_llc_slice); + llc->gpuhtw_llc_slice = NULL; +} + +static int a6xx_llc_slices_init(struct platform_device *pdev, + struct a6xx_llc *llc) +{ + int i; + + /* Get the system cache slice descriptor for GPU and GPUHTWs */ + llc->gpu_llc_slice = llcc_slice_getd(>dev, "gpu"); + if (IS_ERR(llc->gpu_llc_slice)) + llc->gpu_llc_slice = NULL; + + llc->gpuhtw_llc_slice = llcc_slice_getd(>dev, "gpuhtw"); + if (IS_ERR(llc->gpuhtw_llc_slice)) + llc->gpuhtw_llc_slice = NULL; + +
Re: [Freedreno] [PATCH 2/5] arm64:dts:sdm845: Add support for GPU LLCC
Hi Sharat, On 3/23/2018 12:49 PM, Sharat Masetty wrote: Add client side bindings required for the GPU to use the last level system cache. Also add a register range in the GPU CX domain. Signed-off-by: Sharat Masetty--- arch/arm64/boot/dts/qcom/sdm845.dtsi | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index eb0a1b2..7e2d938 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -887,8 +887,8 @@ compatible = "qcom,adreno-630.2", "qcom,adreno"; #stream-id-cells = <16>; - reg = <0x500 0x4>; - reg-names = "kgsl_3d0_reg_memory"; + reg = <0x500 0x4>, <0x509e000 0x10>; + reg-names = "kgsl_3d0_reg_memory", "cx_mem"; /* * Look ma, no clocks! The GPU clocks and power are controlled @@ -898,6 +898,10 @@ interrupts = <0 300 0>; interrupt-names = "kgsl_3d0_irq"; + /* GPU related llc slices */ + cache-slice-names = "gpu", "gpuhtw"; + cache-slices = < 12>, < 11>; Please add corresponding binding doc changes. Best regards Vivek + iommus = <_smmu 0>; operating-points-v2 = <_opp_table>; ___ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [Freedreno] [PATCH 4/5] drm/msm: Pass mmu features to generic layers
Hi Sharat, On 3/23/2018 12:49 PM, Sharat Masetty wrote: Allow different Adreno targets the ability to pass specific mmu features to the generic layers. This will help conditionally configure certain iommu features for certain Adreno targets. Also Add a few simple support functions to support a bitmask of features that a specific MMU implementation supports. Signed-off-by: Sharat MasettyJust a nit; please see my comment below. --- drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 4 +++- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 2 +- drivers/gpu/drm/msm/msm_gpu.c | 6 -- drivers/gpu/drm/msm/msm_gpu.h | 1 + drivers/gpu/drm/msm/msm_mmu.h | 13 + 9 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 1dd84d3..a7a8573 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -492,7 +492,7 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = a3xx_registers; adreno_gpu->reg_offsets = a3xx_register_offsets; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, , 1); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, , 1, 0); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 2884b1b..5e7e15d6 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -574,7 +574,7 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = a4xx_registers; adreno_gpu->reg_offsets = a4xx_register_offsets; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, , 1); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, , 1, 0); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index a4f68af..c9e06ff 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1295,7 +1295,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) check_speed_bin(>dev); - ret = adreno_gpu_init(dev, pdev, adreno_gpu, , 4); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, , 4, 0); if (ret) { a5xx_destroy(&(a5xx_gpu->base.base)); return ERR_PTR(ret); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index e83b066..bd50674 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1040,7 +1040,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = a6xx_registers; adreno_gpu->reg_offsets = a6xx_register_offsets; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, , 4); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, , 4, 0); if (ret) { a6xx_destroy(&(a6xx_gpu->base.base)); return ERR_PTR(ret); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 6657461..a87ec6b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -557,7 +557,8 @@ static int adreno_get_pwrlevels(struct device *dev, int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_gpu *adreno_gpu, - const struct adreno_gpu_funcs *funcs, int nr_rings) + const struct adreno_gpu_funcs *funcs, int nr_rings, + unsigned long mmu_features) { struct adreno_platform_config *config = pdev->dev.platform_data; struct msm_gpu_config adreno_gpu_config = { 0 }; @@ -576,6 +577,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, adreno_gpu_config.va_end = 0x; adreno_gpu_config.nr_rings = nr_rings; + adreno_gpu_config.mmu_features = mmu_features; adreno_get_pwrlevels(>dev, gpu); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index bb9affd..19eda65 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -225,7 +225,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs, - int nr_rings); + int nr_rings, unsigned long mmu_features); void adreno_gpu_cleanup(struct adreno_gpu *gpu); int adreno_load_fw(struct adreno_gpu *adreno_gpu); diff --git a/drivers/gpu/drm/msm/msm_gpu.c
Re: [Freedreno] [PATCH v7 3/6] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
On Fri, Feb 23, 2018 at 9:10 PM, Jordan Crouse <jcro...@codeaurora.org> wrote: > On Fri, Feb 23, 2018 at 04:06:39PM +0530, Vivek Gautam wrote: >> On Fri, Feb 23, 2018 at 5:22 AM, Jordan Crouse <jcro...@codeaurora.org> >> wrote: >> > On Wed, Feb 07, 2018 at 04:01:19PM +0530, Vivek Gautam wrote: >> >> From: Sricharan R <sricha...@codeaurora.org> >> >> >> >> The smmu device probe/remove and add/remove master device callbacks >> >> gets called when the smmu is not linked to its master, that is without >> >> the context of the master device. So calling runtime apis in those places >> >> separately. >> >> >> >> Signed-off-by: Sricharan R <sricha...@codeaurora.org> >> >> [vivek: Cleanup pm runtime calls] >> >> Signed-off-by: Vivek Gautam <vivek.gau...@codeaurora.org> >> >> --- >> >> drivers/iommu/arm-smmu.c | 42 ++ >> >> 1 file changed, 38 insertions(+), 4 deletions(-) >> >> >> >> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c >> >> index 9e2f917e16c2..c024f69c1682 100644 >> >> --- a/drivers/iommu/arm-smmu.c >> >> +++ b/drivers/iommu/arm-smmu.c >> >> @@ -913,11 +913,15 @@ static void arm_smmu_destroy_domain_context(struct >> >> iommu_domain *domain) >> >> struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); >> >> struct arm_smmu_device *smmu = smmu_domain->smmu; >> >> struct arm_smmu_cfg *cfg = _domain->cfg; >> >> - int irq; >> >> + int ret, irq; >> >> >> >> if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) >> >> return; >> >> >> >> + ret = pm_runtime_get_sync(smmu->dev); >> >> + if (ret) >> >> + return; >> >> + >> >> /* >> >>* Disable the context bank and free the page tables before freeing >> >>* it. >> >> @@ -932,6 +936,8 @@ static void arm_smmu_destroy_domain_context(struct >> >> iommu_domain *domain) >> >> >> >> free_io_pgtable_ops(smmu_domain->pgtbl_ops); >> >> __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); >> >> + >> >> + pm_runtime_put_sync(smmu->dev); >> >> } >> >> >> >> static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) >> >> @@ -1407,14 +1413,22 @@ static int arm_smmu_add_device(struct device *dev) >> >> while (i--) >> >> cfg->smendx[i] = INVALID_SMENDX; >> >> >> >> - ret = arm_smmu_master_alloc_smes(dev); >> >> + ret = pm_runtime_get_sync(smmu->dev); >> >> if (ret) >> >> goto out_cfg_free; >> > >> > Hey Vivek, I just hit a problem with this on sdm845. It turns out that >> > pm_runtime_get_sync() returns a positive 1 if the device is already active. >> > >> > I hit this in the GPU code. The a6xx has two platform devices that each >> > use a >> > different sid on the iommu. The GPU is probed normally from a platform >> > driver >> > and it in turn initializes the GMU device by way of a phandle. >> > >> > Because the GMU isn't probed with a platform driver we need to call >> > of_dma_configure() on the device to set up the IOMMU for the device which >> > ends >> > up calling through this path and we discover that the smmu->dev is already >> > powered (pm_runtime_get_sync returns 1). >> > >> > I'm not immediately sure if this is a bug on sdm845 or not because a >> > cursory >> > inspection says that the SMMU device shouldn't be powered at this time but >> > there >> > might be a connection that I'm not seeing. Obviously if the SMMU was left >> > powered thats a bad thing. But putting that aside it is obvious that this >> > code should be accommodating of the possibility that the device is already >> > powered, and so this should be >> > >> > if (ret < 0) >> > goto out_cfg_free; >> >> Right, as Tomasz also pointed, we should surely check the negative value of >> pm_runtime_get_sync(). > > Sorry, I didn't notice that Tomasz had pointed it out as well. I wanted to > quickly get it on the mailing list so you could catch it in your time zone. > >> From
Re: [Freedreno] [PATCH v7 6/6] drm/msm: iommu: Replace runtime calls with runtime suppliers
On Wed, Feb 14, 2018 at 2:46 PM, Tomasz Figa <tf...@chromium.org> wrote: Adding Jordan to this thread as well. > On Wed, Feb 14, 2018 at 6:13 PM, Vivek Gautam > <vivek.gau...@codeaurora.org> wrote: >> Hi Tomasz, >> >> On Wed, Feb 14, 2018 at 11:08 AM, Tomasz Figa <tf...@chromium.org> wrote: >>> On Wed, Feb 14, 2018 at 1:17 PM, Vivek Gautam >>> <vivek.gau...@codeaurora.org> wrote: >>>> Hi Tomasz, >>>> >>>> On Wed, Feb 14, 2018 at 8:31 AM, Tomasz Figa <tf...@chromium.org> wrote: >>>>> On Wed, Feb 14, 2018 at 11:13 AM, Rob Clark <robdcl...@gmail.com> wrote: >>>>>> On Tue, Feb 13, 2018 at 8:59 PM, Tomasz Figa <tf...@chromium.org> wrote: >>>>>>> On Wed, Feb 14, 2018 at 3:03 AM, Rob Clark <robdcl...@gmail.com> wrote: >>>>>>>> On Tue, Feb 13, 2018 at 4:10 AM, Tomasz Figa <tf...@chromium.org> >>>>>>>> wrote: >>>>>>>>> Hi Vivek, >>>>>>>>> >>>>>>>>> Thanks for the patch. Please see my comments inline. >>>>>>>>> >>>>>>>>> On Wed, Feb 7, 2018 at 7:31 PM, Vivek Gautam >>>>>>>>> <vivek.gau...@codeaurora.org> wrote: >>>>>>>>>> While handling the concerned iommu, there should not be a >>>>>>>>>> need to power control the drm devices from iommu interface. >>>>>>>>>> If these drm devices need to be powered around this time, >>>>>>>>>> the respective drivers should take care of this. >>>>>>>>>> >>>>>>>>>> Replace the pm_runtime_get/put_sync() with >>>>>>>>>> pm_runtime_get/put_suppliers() calls, to power-up >>>>>>>>>> the connected iommu through the device link interface. >>>>>>>>>> In case the device link is not setup these get/put_suppliers() >>>>>>>>>> calls will be a no-op, and the iommu driver should take care of >>>>>>>>>> powering on its devices accordingly. >>>>>>>>>> >>>>>>>>>> Signed-off-by: Vivek Gautam <vivek.gau...@codeaurora.org> >>>>>>>>>> --- >>>>>>>>>> drivers/gpu/drm/msm/msm_iommu.c | 16 >>>>>>>>>> 1 file changed, 8 insertions(+), 8 deletions(-) >>>>>>>>>> >>>>>>>>>> diff --git a/drivers/gpu/drm/msm/msm_iommu.c >>>>>>>>>> b/drivers/gpu/drm/msm/msm_iommu.c >>>>>>>>>> index b23d33622f37..1ab629bbee69 100644 >>>>>>>>>> --- a/drivers/gpu/drm/msm/msm_iommu.c >>>>>>>>>> +++ b/drivers/gpu/drm/msm/msm_iommu.c >>>>>>>>>> @@ -40,9 +40,9 @@ static int msm_iommu_attach(struct msm_mmu *mmu, >>>>>>>>>> const char * const *names, >>>>>>>>>> struct msm_iommu *iommu = to_msm_iommu(mmu); >>>>>>>>>> int ret; >>>>>>>>>> >>>>>>>>>> - pm_runtime_get_sync(mmu->dev); >>>>>>>>>> + pm_runtime_get_suppliers(mmu->dev); >>>>>>>>>> ret = iommu_attach_device(iommu->domain, mmu->dev); >>>>>>>>>> - pm_runtime_put_sync(mmu->dev); >>>>>>>>>> + pm_runtime_put_suppliers(mmu->dev); >>>>>>>>> >>>>>>>>> For me, it looks like a wrong place to handle runtime PM of IOMMU >>>>>>>>> here. iommu_attach_device() calls into IOMMU driver's attach_device() >>>>>>>>> callback and that's where necessary runtime PM gets should happen, if >>>>>>>>> any. In other words, driver A (MSM DRM driver) shouldn't be dealing >>>>>>>>> with power state of device controlled by driver B (ARM SMMU). >>>>>>>> >>>>>>>> Note that we end up having to do the same, because of iommu_unmap() >>>>>>>> while DRM driver is powered off.. it might be cleaner if it was all >>>>>>>> self contained in the iommu driver, but that would make it so other >>>>>>>> drivers couldn't call