Re: [Freedreno] [PATCHv6 3/6] drm/msm: rearrange the gpu_rmw() function

2020-10-26 Thread Jordan Crouse
On Mon, Oct 26, 2020 at 05:24:02PM +0530, Sai Prakash Ranjan wrote:
> From: Sharat Masetty 
> 
> The register read-modify-write construct is generic enough
> that it can be used by other subsystems as needed, create
> a more generic rmw() function and have the gpu_rmw() use
> this new function.
> 
> Signed-off-by: Sharat Masetty 
> Reviewed-by: Jordan Crouse 
> Signed-off-by: Sai Prakash Ranjan 

Rob - this should be safe to pull with msm-next regardless of the merge status
of the iommu side of things. Hopefully everything will be pulled for 5.11 but if
it isn't it would be good to get this out of the cycle.

Jordan

> ---
>  drivers/gpu/drm/msm/msm_drv.c | 8 
>  drivers/gpu/drm/msm/msm_drv.h | 1 +
>  drivers/gpu/drm/msm/msm_gpu.h | 5 +
>  3 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 49685571dc0e..a1e22b974b77 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -180,6 +180,14 @@ u32 msm_readl(const void __iomem *addr)
>   return val;
>  }
>  
> +void msm_rmw(void __iomem *addr, u32 mask, u32 or)
> +{
> + u32 val = msm_readl(addr);
> +
> + val &= ~mask;
> + msm_writel(val | or, addr);
> +}
> +
>  struct msm_vblank_work {
>   struct work_struct work;
>   int crtc_id;
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index b9dd8f8f4887..655b3b0424a1 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -478,6 +478,7 @@ void __iomem *msm_ioremap_quiet(struct platform_device 
> *pdev, const char *name,
>   const char *dbgname);
>  void msm_writel(u32 data, void __iomem *addr);
>  u32 msm_readl(const void __iomem *addr);
> +void msm_rmw(void __iomem *addr, u32 mask, u32 or);
>  
>  struct msm_gpu_submitqueue;
>  int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private 
> *ctx);
> diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> index 6c9e1fdc1a76..b2b419277953 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.h
> +++ b/drivers/gpu/drm/msm/msm_gpu.h
> @@ -246,10 +246,7 @@ static inline u32 gpu_read(struct msm_gpu *gpu, u32 reg)
>  
>  static inline void gpu_rmw(struct msm_gpu *gpu, u32 reg, u32 mask, u32 or)
>  {
> - uint32_t val = gpu_read(gpu, reg);
> -
> - val &= ~mask;
> - gpu_write(gpu, reg, val | or);
> + msm_rmw(gpu->mmio + (reg << 2), mask, or);
>  }
>  
>  static inline u64 gpu_read64(struct msm_gpu *gpu, u32 lo, u32 hi)
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCHv6 4/6] drm/msm/a6xx: Add support for using system cache(LLC)

2020-10-26 Thread Jordan Crouse
On Mon, Oct 26, 2020 at 05:24:03PM +0530, Sai Prakash Ranjan wrote:
> From: Sharat Masetty 
> 
> The last level system cache can be partitioned to 32 different
> slices of which GPU has two slices preallocated. One slice is
> used for caching GPU buffers and the other slice is used for
> caching the GPU SMMU pagetables. This 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 to set the right TCR attributes. 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.
> 
> DOMAIN_ATTR_SYS_CACHE 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 
> [saiprakash.ranjan: fix to set attr before device attach to iommu and rebase]
> Signed-off-by: Sai Prakash Ranjan 

As with the previous patch this doesn't exactly need the IOMMU side changes
outside of the update to the domain attribute enum.

If the attribute didn't exist we would just lose no-write-allocate which is
undesirable but not devastating.

Hopefully the arm-smmu changes are ready to go but I'm just trying to figure
out a game plan to keep Sai from having to maintain these patches
for another cycle.

Jordan

> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   | 83 +
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.h   |  4 ++
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 17 +
>  3 files changed, 104 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 8915882e..151190ff62f7 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -8,7 +8,9 @@
>  #include "a6xx_gpu.h"
>  #include "a6xx_gmu.xml.h"
>  
> +#include 
>  #include 
> +#include 
>  
>  #define GPU_PAS_ID 13
>  
> @@ -1022,6 +1024,79 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
>   return IRQ_HANDLED;
>  }
>  
> +static void a6xx_llc_rmw(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 mask, u32 
> or)
> +{
> + return msm_rmw(a6xx_gpu->llc_mmio + (reg << 2), mask, or);
> +}
> +
> +static void a6xx_llc_write(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 value)
> +{
> + return msm_writel(value, a6xx_gpu->llc_mmio + (reg << 2));
> +}
> +
> +static void a6xx_llc_deactivate(struct a6xx_gpu *a6xx_gpu)
> +{
> + llcc_slice_deactivate(a6xx_gpu->llc_slice);
> + llcc_slice_deactivate(a6xx_gpu->htw_llc_slice);
> +}
> +
> +static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
> +{
> + u32 cntl1_regval = 0;
> +
> + if (IS_ERR(a6xx_gpu->llc_mmio))
> + return;
> +
> + if (!llcc_slice_activate(a6xx_gpu->llc_slice)) {
> + u32 gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice);
> +
> + gpu_scid &= 0x1f;
> + cntl1_regval = (gpu_scid << 0) | (gpu_scid << 5) | (gpu_scid << 
> 10) |
> +(gpu_scid << 15) | (gpu_scid << 20);
> + }
> +
> + if (!llcc_slice_activate(a6xx_gpu->htw_llc_slice)) {
> + u32 gpuhtw_scid = llcc_get_slice_id(a6xx_gpu->htw_llc_slice);
> +
> + gpuhtw_scid &= 0x1f;
> + cntl1_regval |= FIELD_PREP(GENMASK(29, 25), gpuhtw_scid);
> + }
> +
> + if (cntl1_regval) {
> + /*
> +  * Program the slice IDs for the various GPU blocks and GPU MMU
> +  * pagetables
> +  */
> + a6xx_llc_write(a6xx_gpu, REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1, 
> cntl1_regval);
> +
> + /*
> +  * Program cacheability overrides to not allocate cache lines on
> +  * a write miss
> +  */
> + a6xx_llc_rmw(a6xx_gpu, REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0, 
> 0xF, 0x03);
> + }
> +}
> +
> +static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu)
> +{
> + llcc_slice_putd(a6xx_gpu->llc_slice);
> + llcc_slice_putd(a6xx_gpu->htw_llc_slice);
> +}
> +
> +static void a6xx_llc_slices_init(struct platform_device *pdev,
> + struct a6xx_gpu *a6xx_gpu)
> +{
> + a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem", "gpu_cx");
> + if (IS_ERR(a6xx_gpu->llc_mmio))
> + return;
> +
> + a6xx_gpu->llc_slice = llcc_slice_getd(LLCC_GPU);
> + a6xx_gpu->htw_llc_slice = llcc_slice_getd(LLCC_GPUHTW);
> +
> + if (IS_ERR(a6xx_gpu->llc_slice) && IS_ERR(a6xx_gpu->htw_llc_slice))
> + a6xx_gpu->llc_mmio = ERR_PTR(-EINVAL);
> +}
> +
>  static int a6xx_pm_resume(struct msm_gpu *gpu)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> @@ -1038,6 +1113,8 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
>  
>   msm_gpu_resu

[Freedreno] [PATCH] drm/msm/a6xx: Add support for using system cache on MMU500 based targets

2020-10-26 Thread Jordan Crouse
This is an extension to the series [1] to enable the System Cache (LLC) for
Adreno a6xx targets.

GPU targets with an MMU-500 attached have a slightly different process for
enabling system cache. Use the compatible string on the IOMMU phandle
to see if an MMU-500 is attached and modify the programming sequence
accordingly.

[1] https://patchwork.freedesktop.org/series/83037/

Signed-off-by: Jordan Crouse 
---

 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 46 +--
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h |  1 +
 2 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 95c98c642876..b7737732fbb6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1042,6 +1042,8 @@ static void a6xx_llc_deactivate(struct a6xx_gpu *a6xx_gpu)
 
 static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
 {
+   struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+   struct msm_gpu *gpu = &adreno_gpu->base;
u32 cntl1_regval = 0;
 
if (IS_ERR(a6xx_gpu->llc_mmio))
@@ -1055,11 +1057,17 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
   (gpu_scid << 15) | (gpu_scid << 20);
}
 
+   /*
+* For targets with a MMU500, activate the slice but don't program the
+* register.  The XBL will take care of that.
+*/
if (!llcc_slice_activate(a6xx_gpu->htw_llc_slice)) {
-   u32 gpuhtw_scid = llcc_get_slice_id(a6xx_gpu->htw_llc_slice);
+   if (!a6xx_gpu->have_mmu500) {
+   u32 gpuhtw_scid = 
llcc_get_slice_id(a6xx_gpu->htw_llc_slice);
 
-   gpuhtw_scid &= 0x1f;
-   cntl1_regval |= FIELD_PREP(GENMASK(29, 25), gpuhtw_scid);
+   gpuhtw_scid &= 0x1f;
+   cntl1_regval |= FIELD_PREP(GENMASK(29, 25), 
gpuhtw_scid);
+   }
}
 
if (cntl1_regval) {
@@ -1067,13 +1075,20 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
 * Program the slice IDs for the various GPU blocks and GPU MMU
 * pagetables
 */
-   a6xx_llc_write(a6xx_gpu, REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1, 
cntl1_regval);
-
-   /*
-* Program cacheability overrides to not allocate cache lines on
-* a write miss
-*/
-   a6xx_llc_rmw(a6xx_gpu, REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0, 
0xF, 0x03);
+   if (a6xx_gpu->have_mmu500)
+   gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0),
+   cntl1_regval);
+   else {
+   a6xx_llc_write(a6xx_gpu,
+   REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1, 
cntl1_regval);
+
+   /*
+* Program cacheability overrides to not allocate cache
+* lines on a write miss
+*/
+   a6xx_llc_rmw(a6xx_gpu,
+   REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0, 0xF, 
0x03);
+   }
}
 }
 
@@ -1086,10 +1101,21 @@ static void a6xx_llc_slices_destroy(struct a6xx_gpu 
*a6xx_gpu)
 static void a6xx_llc_slices_init(struct platform_device *pdev,
struct a6xx_gpu *a6xx_gpu)
 {
+   struct device_node *phandle;
+
a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem", "gpu_cx");
if (IS_ERR(a6xx_gpu->llc_mmio))
return;
 
+   /*
+* There is a different programming path for targets with an mmu500
+* attached, so detect if that is the case
+*/
+   phandle = of_parse_phandle(pdev->dev.of_node, "iommus", 0);
+   a6xx_gpu->have_mmu500 = (phandle &&
+   of_device_is_compatible(phandle, "arm,mmu500"));
+   of_node_put(phandle);
+
a6xx_gpu->llc_slice = llcc_slice_getd(LLCC_GPU);
a6xx_gpu->htw_llc_slice = llcc_slice_getd(LLCC_GPUHTW);
 
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 9e6079af679c..e793d329e77b 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -32,6 +32,7 @@ struct a6xx_gpu {
void __iomem *llc_mmio;
void *llc_slice;
void *htw_llc_slice;
+   bool have_mmu500;
 };
 
 #define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base)
-- 
2.25.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH] drm/msm/a6xx: Add support for using system cache on MMU500 based targets

2020-10-27 Thread Jordan Crouse
On Tue, Oct 27, 2020 at 12:38:02PM +0530, Sai Prakash Ranjan wrote:
> On 2020-10-27 00:24, Jordan Crouse wrote:
> >This is an extension to the series [1] to enable the System Cache (LLC)
> >for
> >Adreno a6xx targets.
> >
> >GPU targets with an MMU-500 attached have a slightly different process for
> >enabling system cache. Use the compatible string on the IOMMU phandle
> >to see if an MMU-500 is attached and modify the programming sequence
> >accordingly.
> >
> >[1] https://patchwork.freedesktop.org/series/83037/
> >
> >Signed-off-by: Jordan Crouse 
> >---
> >
> > drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 46 +--
> > drivers/gpu/drm/msm/adreno/a6xx_gpu.h |  1 +
> > 2 files changed, 37 insertions(+), 10 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >index 95c98c642876..b7737732fbb6 100644
> >--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >@@ -1042,6 +1042,8 @@ static void a6xx_llc_deactivate(struct a6xx_gpu
> >*a6xx_gpu)
> >
> > static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
> > {
> >+struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
> >+struct msm_gpu *gpu = &adreno_gpu->base;
> > u32 cntl1_regval = 0;
> >
> > if (IS_ERR(a6xx_gpu->llc_mmio))
> >@@ -1055,11 +1057,17 @@ static void a6xx_llc_activate(struct a6xx_gpu
> >*a6xx_gpu)
> >(gpu_scid << 15) | (gpu_scid << 20);
> > }
> >
> >+/*
> >+ * For targets with a MMU500, activate the slice but don't program the
> >+ * register.  The XBL will take care of that.
> >+ */
> > if (!llcc_slice_activate(a6xx_gpu->htw_llc_slice)) {
> >-u32 gpuhtw_scid = llcc_get_slice_id(a6xx_gpu->htw_llc_slice);
> >+if (!a6xx_gpu->have_mmu500) {
> >+u32 gpuhtw_scid = 
> >llcc_get_slice_id(a6xx_gpu->htw_llc_slice);
> >
> >-gpuhtw_scid &= 0x1f;
> >-cntl1_regval |= FIELD_PREP(GENMASK(29, 25), gpuhtw_scid);
> >+gpuhtw_scid &= 0x1f;
> >+cntl1_regval |= FIELD_PREP(GENMASK(29, 25), 
> >gpuhtw_scid);
> >+}
> > }
> >
> > if (cntl1_regval) {
> >@@ -1067,13 +1075,20 @@ static void a6xx_llc_activate(struct a6xx_gpu
> >*a6xx_gpu)
> >  * Program the slice IDs for the various GPU blocks and GPU MMU
> >  * pagetables
> >  */
> >-a6xx_llc_write(a6xx_gpu, REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1,
> >cntl1_regval);
> >-
> >-/*
> >- * Program cacheability overrides to not allocate cache lines on
> >- * a write miss
> >- */
> >-a6xx_llc_rmw(a6xx_gpu, REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0, 
> >0xF,
> >0x03);
> >+if (a6xx_gpu->have_mmu500)
> >+gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0),
> >+cntl1_regval);
> >+else {
> >+a6xx_llc_write(a6xx_gpu,
> >+REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1, 
> >cntl1_regval);
> >+
> >+/*
> >+ * Program cacheability overrides to not allocate cache
> >+ * lines on a write miss
> >+ */
> >+a6xx_llc_rmw(a6xx_gpu,
> >+REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0, 0xF, 
> >0x03);
> >+}
> > }
> > }
> >
> >@@ -1086,10 +1101,21 @@ static void a6xx_llc_slices_destroy(struct
> >a6xx_gpu *a6xx_gpu)
> > static void a6xx_llc_slices_init(struct platform_device *pdev,
> > struct a6xx_gpu *a6xx_gpu)
> > {
> >+struct device_node *phandle;
> >+
> > a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem", "gpu_cx");
> > if (IS_ERR(a6xx_gpu->llc_mmio))
> > return;
> >
> >+/*
> >+ * There is a different programming path for targets with an mmu500
> >+ * attached, so detect if that is the case
> >+ */
> >+phandle = of_parse_phandle(pdev->dev.of_node, "iommus", 0);
> >+a6xx_gpu->have_mmu500 = (phandle &&
> >+of_device_is_compatible(phandle, "arm,mmu500"));
> >+of_node

Re: [Freedreno] [PATCH] drm/msm: a5xx: Make preemption reset case reentrant

2020-11-03 Thread Jordan Crouse
On Mon, Nov 02, 2020 at 09:02:25PM +0100, Marijn Suijten wrote:
> nr_rings is reset to 1, but when this function is called for a second
> (and third!) time nr_rings > 1 is false, thus the else case is entered
> to set up a buffer for the RPTR shadow and consequently written to
> RB_RPTR_ADDR, hanging platforms without WHERE_AM_I firmware support.
> 
> Restructure the condition in such a way that shadow buffer setup only
> ever happens when has_whereami is true; otherwise preemption is only
> finalized when the number of ring buffers has not been reset to 1 yet.
> 
> Fixes: 8907afb476ac ("drm/msm: Allow a5xx to mark the RPTR shadow as 
> privileged")
> Signed-off-by: Marijn Suijten 
> Tested-by: AngeloGioacchino Del Regno 
> 

Way better. Thanks for doing this.

Reviewed-by: Jordan Crouse 

> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 12 ++--
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index d6804a802355..9a202a7da131 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -755,12 +755,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
>   gpu_write(gpu, REG_A5XX_CP_RB_CNTL,
>   MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
>  
> - /* Disable preemption if WHERE_AM_I isn't available */
> - if (!a5xx_gpu->has_whereami && gpu->nr_rings > 1) {
> - a5xx_preempt_fini(gpu);
> - gpu->nr_rings = 1;
> - } else {
> - /* Create a privileged buffer for the RPTR shadow */
> + /* Create a privileged buffer for the RPTR shadow */
> + if (a5xx_gpu->has_whereami) {
>   if (!a5xx_gpu->shadow_bo) {
>   a5xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
>   sizeof(u32) * gpu->nr_rings,
> @@ -774,6 +770,10 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
>  
>   gpu_write64(gpu, REG_A5XX_CP_RB_RPTR_ADDR,
>   REG_A5XX_CP_RB_RPTR_ADDR_HI, shadowptr(a5xx_gpu, 
> gpu->rb[0]));
> + } else if (gpu->nr_rings > 1) {
> + /* Disable preemption if WHERE_AM_I isn't available */
> + a5xx_preempt_fini(gpu);
> + gpu->nr_rings = 1;
>   }
>  
>   a5xx_preempt_hw_init(gpu);
> -- 
> 2.29.2
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [RFC PATCH v1 0/3] iommu/arm-smmu: adreno-smmu page fault handling

2020-11-09 Thread Jordan Crouse
This is an RFC to add an Adreno GPU specific handler for pagefaults. The first
patch starts by wiring up report_iommu_fault for arm-smmu. The next patch adds
a adreno-smmu-priv function hook to capture a handful of important debugging
registers such as TTBR0, CONTEXTIDR, FSYNR0 and others. This is used by the
third patch to print more detailed information on page fault such as the TTBR0
for the pagetable that caused the fault and the source of the fault as
determined by a combination of the FSYNR1 register and an internal GPU
register.

This code provides a solid base that we can expand on later for even more
extensive GPU side page fault debugging capabilities.

Jordan Crouse (3):
  iommu/arm-smmu: Add support for driver IOMMU fault handlers
  drm/msm: Add an adreno-smmu-priv callback to get pagefault info
  drm/msm: Improve the a6xx page fault handler

 drivers/gpu/drm/msm/adreno/a5xx_gpu.c  |  4 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  | 76 +-
 drivers/gpu/drm/msm/msm_iommu.c| 11 +++-
 drivers/gpu/drm/msm/msm_mmu.h  |  4 +-
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.c  | 16 -
 drivers/iommu/arm/arm-smmu/arm-smmu.h  |  2 +
 include/linux/adreno-smmu-priv.h   | 31 -
 8 files changed, 151 insertions(+), 12 deletions(-)

-- 
2.25.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [RFC PATCH v1 3/3] drm/msm: Improve the a6xx page fault handler

2020-11-09 Thread Jordan Crouse
Use the new adreno-smmu-priv fault info function to get more SMMU
debug registers and print the current TTBR0 to debug per-instance
pagetables and figure out which GPU block generated the request.

Signed-off-by: Jordan Crouse 
---

 drivers/gpu/drm/msm/adreno/a5xx_gpu.c |  4 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 76 +--
 drivers/gpu/drm/msm/msm_iommu.c   | 11 +++-
 drivers/gpu/drm/msm/msm_mmu.h |  4 +-
 4 files changed, 87 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index d6804a802355..ed4cb81af874 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -933,7 +933,7 @@ bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer 
*ring)
return true;
 }
 
-static int a5xx_fault_handler(void *arg, unsigned long iova, int flags)
+static int a5xx_fault_handler(void *arg, unsigned long iova, int flags, void 
*data)
 {
struct msm_gpu *gpu = arg;
pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d 
(%u,%u,%u,%u)\n",
@@ -943,7 +943,7 @@ static int a5xx_fault_handler(void *arg, unsigned long 
iova, int flags)
gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(6)),
gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(7)));
 
-   return -EFAULT;
+   return 0;
 }
 
 static void a5xx_cp_err_irq(struct msm_gpu *gpu)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 948f3656c20c..ac6e8cd5cf1a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -905,18 +905,88 @@ static void a6xx_recover(struct msm_gpu *gpu)
msm_gpu_hw_init(gpu);
 }
 
-static int a6xx_fault_handler(void *arg, unsigned long iova, int flags)
+static const char *a6xx_uche_fault_block(struct msm_gpu *gpu, u32 mid)
+{
+   static const char *uche_clients[7] = {
+   "VFD", "SP", "VSC", "VPC", "HLSQ", "PC", "LRZ",
+   };
+   u32 val;
+
+   if (mid < 1 || mid > 3)
+   return "UNKNOWN";
+
+   /*
+* The source of the data depends on the mid ID read from FSYNR1.
+* and the client ID read from the UCHE block
+*/
+   val = gpu_read(gpu, REG_A6XX_UCHE_CLIENT_PF);
+
+   /* mid = 3 is most precise and refers to only one block per client */
+   if (mid == 3)
+   return uche_clients[val & 7];
+
+   /* For mid=2 the source is TP or VFD except when the client id is 0 */
+   if (mid == 2)
+   return ((val & 7) == 0) ? "TP" : "TP|VFD";
+
+   /* For mid=1 just return "UCHE" as a catchall for everything else */
+   return "UCHE";
+}
+
+static const char *a6xx_fault_block(struct msm_gpu *gpu, u32 id)
+{
+   if (id == 0)
+   return "CP";
+   else if (id == 4)
+   return "CCU";
+   else if (id == 6)
+   return "CDP Prefetch";
+
+   return a6xx_uche_fault_block(gpu, id);
+}
+
+#define ARM_SMMU_FSR_TF BIT(1)
+#define ARM_SMMU_FSR_PFBIT(3)
+#define ARM_SMMU_FSR_EFBIT(4)
+
+static int a6xx_fault_handler(void *arg, unsigned long iova, int flags, void 
*data)
 {
struct msm_gpu *gpu = arg;
+   struct adreno_smmu_fault_info *info = data;
+   const char *type = "UNKNOWN";
 
-   pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d 
(%u,%u,%u,%u)\n",
+   /*
+* Print a default message if we couldn't get the data from the
+* adreno-smmu-priv
+*/
+   if (!info) {
+   pr_warn_ratelimited("*** gpu fault: iova=%.16lx flags=%d 
(%u,%u,%u,%u)\n",
iova, flags,
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(4)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(5)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(6)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(7)));
 
-   return -EFAULT;
+   return 0;
+   }
+
+   if (info->fsr & ARM_SMMU_FSR_TF)
+   type = "TRANSLATION";
+   else if (info->fsr & ARM_SMMU_FSR_PF)
+   type = "PERMISSION";
+   else if (info->fsr & ARM_SMMU_FSR_EF)
+   type = "EXTERNAL";
+
+   pr_warn_ratelimited("*** gpu fault: ttbr0=%.16llx iova=%.16lx dir=%s 
type=%s source=%s (%u,%u,%u,%u)\n",
+   info->ttbr0, iova,
+   flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ", type,
+   a6xx_fault_block(gpu, info->fsynr1 & 0xff),
+   gpu_read(gpu, REG

Re: [Freedreno] [PATCH 1/2] drm/msm/a6xx: Clear shadow on suspend

2020-11-10 Thread Jordan Crouse
On Tue, Nov 10, 2020 at 10:43:59AM -0800, Rob Clark wrote:
> From: Rob Clark 
> 
> Clear the shadow rptr on suspend.  Otherwise, when we resume, we can
> have a stale value until CP_WHERE_AM_I executes.  If we suspend near
> the ringbuffer wraparound point, this can lead to a chicken/egg
> situation where we are waiting for ringbuffer space to write the
> CP_WHERE_AM_I (or CP_INIT) packet, because we mistakenly believe that
> the ringbuffer is full (due to stale rptr value in the shadow).
> 
> Fixes errors like:
> 
>   [drm:adreno_wait_ring [msm]] *ERROR* timeout waiting for space in 
> ringbuffer 0
> 
> in the resume path.
> 
> Fixes: d3a569fccfa0 ("drm/msm: a6xx: Use WHERE_AM_I for eligible targets")
> Signed-off-by: Rob Clark 

Reviewed-by: Jordan Crouse 

> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 11 ++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 2f236aadfa9c..fcb0aabbc985 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -1043,12 +1043,21 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
> + int i, ret;
>  
>   trace_msm_gpu_suspend(0);
>  
>   devfreq_suspend_device(gpu->devfreq.devfreq);
>  
> - return a6xx_gmu_stop(a6xx_gpu);
> + ret = a6xx_gmu_stop(a6xx_gpu);
> + if (ret)
> + return ret;
> +
> + if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami)
> + for (i = 0; i < gpu->nr_rings; i++)
> + a6xx_gpu->shadow[i] = 0;
> +
> + return 0;
>  }
>  
>  static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
> -- 
> 2.28.0
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 2/2] drm/msm/a5xx: Clear shadow on suspend

2020-11-10 Thread Jordan Crouse
On Tue, Nov 10, 2020 at 10:44:00AM -0800, Rob Clark wrote:
> From: Rob Clark 
> 
> Similar to the previous patch, clear shadow on suspend to avoid timeouts
> waiting for ringbuffer space.
> 
> Fixes: 8907afb476ac ("drm/msm: Allow a5xx to mark the RPTR shadow as 
> privileged")
> Signed-off-by: Rob Clark 

Reviewed-by: Jordan Crouse 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 12 +++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index b0005ccd81c6..8fa5c917d017 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -1206,7 +1206,9 @@ static int a5xx_pm_resume(struct msm_gpu *gpu)
>  static int a5xx_pm_suspend(struct msm_gpu *gpu)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
>   u32 mask = 0xf;
> + int i, ret;
>  
>   /* A510 has 3 XIN ports in VBIF */
>   if (adreno_is_a510(adreno_gpu))
> @@ -1226,7 +1228,15 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu)
>   gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C);
>   gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x);
>  
> - return msm_gpu_pm_suspend(gpu);
> + ret = msm_gpu_pm_suspend(gpu);
> + if (ret)
> + return ret;
> +
> + if (a5xx_gpu->has_whereami)
> + for (i = 0; i < gpu->nr_rings; i++)
> + a5xx_gpu->shadow[i] = 0;
> +
> + return 0;
>  }
>  
>  static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
> -- 
> 2.28.0
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH] drm/msm: adreno: Make speed-bin support generic

2020-11-12 Thread Jordan Crouse
On Thu, Nov 12, 2020 at 09:19:04PM +0530, Akhil P Oommen wrote:
> So far a530v2 gpu has support for detecting its supported opps
> based on a fuse value called speed-bin. This patch makes this
> support generic across gpu families. This is in preparation to
> extend speed-bin support to a6x family.
> 
> Signed-off-by: Akhil P Oommen 
> ---
> This patch is rebased on top of msm-next-staging branch in rob's tree.
> 
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c  | 34 --
>  drivers/gpu/drm/msm/adreno/adreno_device.c |  4 ++
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c| 71 
> ++
>  drivers/gpu/drm/msm/adreno/adreno_gpu.h|  5 +++
>  4 files changed, 80 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 8fa5c91..7d42321 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -1531,38 +1531,6 @@ static const struct adreno_gpu_funcs funcs = {
>   .get_timestamp = a5xx_get_timestamp,
>  };
>  
> -static void check_speed_bin(struct device *dev)
> -{
> - struct nvmem_cell *cell;
> - u32 val;
> -
> - /*
> -  * If the OPP table specifies a opp-supported-hw property then we have
> -  * to set something with dev_pm_opp_set_supported_hw() or the table
> -  * doesn't get populated so pick an arbitrary value that should
> -  * ensure the default frequencies are selected but not conflict with any
> -  * actual bins
> -  */
> - val = 0x80;
> -
> - cell = nvmem_cell_get(dev, "speed_bin");
> -
> - if (!IS_ERR(cell)) {
> - void *buf = nvmem_cell_read(cell, NULL);
> -
> - if (!IS_ERR(buf)) {
> - u8 bin = *((u8 *) buf);
> -
> - val = (1 << bin);
> - kfree(buf);
> - }
> -
> - nvmem_cell_put(cell);
> - }
> -
> - dev_pm_opp_set_supported_hw(dev, &val, 1);
> -}
> -
>  struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
>  {
>   struct msm_drm_private *priv = dev->dev_private;
> @@ -1588,8 +1556,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
>  
>   a5xx_gpu->lm_leakage = 0x4E001A;
>  
> - check_speed_bin(&pdev->dev);
> -
>   ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4);
>   if (ret) {
>   a5xx_destroy(&(a5xx_gpu->base.base));
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
> b/drivers/gpu/drm/msm/adreno/adreno_device.c
> index 87c8b03..e0ff16c 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> @@ -18,6 +18,8 @@ bool snapshot_debugbus = false;
>  MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU 
> devcoredump (if not fused off)");
>  module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600);
>  
> +const u32 a530v2_speedbins[] = {0, 1, 2, 3, 4, 5, 6, 7};
> +
>  static const struct adreno_info gpulist[] = {
>   {
>   .rev   = ADRENO_REV(2, 0, 0, 0),
> @@ -163,6 +165,8 @@ static const struct adreno_info gpulist[] = {
>   ADRENO_QUIRK_FAULT_DETECT_MASK,
>   .init = a5xx_gpu_init,
>   .zapfw = "a530_zap.mdt",
> + .speedbins = a530v2_speedbins,
> + .speedbins_count = ARRAY_SIZE(a530v2_speedbins),
>   }, {
>   .rev = ADRENO_REV(5, 4, 0, 2),
>   .revn = 540,
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index f21561d..cdd0c11 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -14,6 +14,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include "adreno_gpu.h"
>  #include "msm_gem.h"
> @@ -891,6 +892,69 @@ void adreno_gpu_ocmem_cleanup(struct adreno_ocmem 
> *adreno_ocmem)
>  adreno_ocmem->hdl);
>  }
>  
> +static int adreno_set_supported_hw(struct device *dev,
> + struct adreno_gpu *adreno_gpu)
> +{
> + u8 speedbins_count = adreno_gpu->info->speedbins_count;
> + const u32 *speedbins = adreno_gpu->info->speedbins;

We don't need to make this generic and put it in the table. Just call the
function from the target specific code and pass the speedbin array and size from
there.

> + struct nvmem_cell *cell;
> + u32 bin, i;
> + u32 val = 0;
> + void *buf, *opp_table;
> +
> + cell = nvmem_cell_get(dev, "speed_bin");
> + /*
> +  * -ENOENT means that the platform doesn't support speedbin which is
> +  * fine
> +  */
> + if (PTR_ERR(cell) == -ENOENT)
> + return 0;
> + else if (IS_ERR(cell))
> + return PTR_ERR(cell);
> +
> + /* A speedbin table is must if the platform supports speedbin */
> + if (!speedbins) {
> + DRM_DEV_ERROR(dev, "speed-bin table is missing\n");
> + re

Re: [Freedreno] [PATCH 06/40] drm/msm/adreno/a6xx_gpu: Staticise local function 'a6xx_idle'

2020-11-13 Thread Jordan Crouse
On Fri, Nov 13, 2020 at 01:49:04PM +, Lee Jones wrote:
> Fixes the following W=1 kernel build warning(s):
> 
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c:33:6: warning: no previous prototype 
> for ‘a6xx_idle’ [-Wmissing-prototypes]
> 
> Cc: Rob Clark 
> Cc: Sean Paul 
> Cc: David Airlie 
> Cc: Daniel Vetter 
> Cc: linux-arm-...@vger.kernel.org
> Cc: dri-de...@lists.freedesktop.org
> Cc: freedreno@lists.freedesktop.org
> Signed-off-by: Lee Jones 

Reviewed-by: Jordan Crouse 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index fcb0aabbc9852..03c2f7e0c9497 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -30,7 +30,7 @@ static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
>   A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT);
>  }
>  
> -bool a6xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
> +static bool a6xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
>  {
>   /* wait for CP to drain ringbuffer: */
>   if (!adreno_idle(gpu, ring))
> -- 
> 2.25.1
> 
> ___
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH] drm/msm: adreno: Make speed-bin support generic

2020-11-16 Thread Jordan Crouse
On Mon, Nov 16, 2020 at 07:40:03PM +0530, Akhil P Oommen wrote:
> On 11/12/2020 10:05 PM, Jordan Crouse wrote:
> >On Thu, Nov 12, 2020 at 09:19:04PM +0530, Akhil P Oommen wrote:
> >>So far a530v2 gpu has support for detecting its supported opps
> >>based on a fuse value called speed-bin. This patch makes this
> >>support generic across gpu families. This is in preparation to
> >>extend speed-bin support to a6x family.
> >>
> >>Signed-off-by: Akhil P Oommen 
> >>---
> >>This patch is rebased on top of msm-next-staging branch in rob's tree.
> >>
> >>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c  | 34 --
> >>  drivers/gpu/drm/msm/adreno/adreno_device.c |  4 ++
> >>  drivers/gpu/drm/msm/adreno/adreno_gpu.c| 71 
> >> ++
> >>  drivers/gpu/drm/msm/adreno/adreno_gpu.h|  5 +++
> >>  4 files changed, 80 insertions(+), 34 deletions(-)
> >>
> >>diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> >>b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> >>index 8fa5c91..7d42321 100644
> >>--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> >>+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> >>@@ -1531,38 +1531,6 @@ static const struct adreno_gpu_funcs funcs = {
> >>.get_timestamp = a5xx_get_timestamp,
> >>  };
> >>-static void check_speed_bin(struct device *dev)
> >>-{
> >>-   struct nvmem_cell *cell;
> >>-   u32 val;
> >>-
> >>-   /*
> >>-* If the OPP table specifies a opp-supported-hw property then we have
> >>-* to set something with dev_pm_opp_set_supported_hw() or the table
> >>-* doesn't get populated so pick an arbitrary value that should
> >>-* ensure the default frequencies are selected but not conflict with any
> >>-* actual bins
> >>-*/
> >>-   val = 0x80;
> >>-
> >>-   cell = nvmem_cell_get(dev, "speed_bin");
> >>-
> >>-   if (!IS_ERR(cell)) {
> >>-   void *buf = nvmem_cell_read(cell, NULL);
> >>-
> >>-   if (!IS_ERR(buf)) {
> >>-   u8 bin = *((u8 *) buf);
> >>-
> >>-   val = (1 << bin);
> >>-   kfree(buf);
> >>-   }
> >>-
> >>-   nvmem_cell_put(cell);
> >>-   }
> >>-
> >>-   dev_pm_opp_set_supported_hw(dev, &val, 1);
> >>-}
> >>-
> >>  struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
> >>  {
> >>struct msm_drm_private *priv = dev->dev_private;
> >>@@ -1588,8 +1556,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
> >>a5xx_gpu->lm_leakage = 0x4E001A;
> >>-   check_speed_bin(&pdev->dev);
> >>-
> >>ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4);
> >>if (ret) {
> >>a5xx_destroy(&(a5xx_gpu->base.base));
> >>diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
> >>b/drivers/gpu/drm/msm/adreno/adreno_device.c
> >>index 87c8b03..e0ff16c 100644
> >>--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> >>+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> >>@@ -18,6 +18,8 @@ bool snapshot_debugbus = false;
> >>  MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU 
> >> devcoredump (if not fused off)");
> >>  module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600);
> >>+const u32 a530v2_speedbins[] = {0, 1, 2, 3, 4, 5, 6, 7};
> >>+
> >>  static const struct adreno_info gpulist[] = {
> >>{
> >>.rev   = ADRENO_REV(2, 0, 0, 0),
> >>@@ -163,6 +165,8 @@ static const struct adreno_info gpulist[] = {
> >>ADRENO_QUIRK_FAULT_DETECT_MASK,
> >>.init = a5xx_gpu_init,
> >>.zapfw = "a530_zap.mdt",
> >>+   .speedbins = a530v2_speedbins,
> >>+   .speedbins_count = ARRAY_SIZE(a530v2_speedbins),
> >>}, {
> >>.rev = ADRENO_REV(5, 4, 0, 2),
> >>.revn = 540,
> >>diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> >>b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >>index f21561d..cdd0c11 100644
> >>--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >>+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >>@@ -14,6 +14,7 @@
> >>  #include 
> >>  #include 
> >>  #inclu

Re: [Freedreno] [PATCH 3/3] drm/msm/shrinker: Only iterate dontneed objs

2020-11-16 Thread Jordan Crouse
On Sat, Nov 14, 2020 at 11:30:10AM -0800, Rob Clark wrote:
> From: Rob Clark 
> 
> In situations where the GPU is mostly idle, all or nearly all buffer
> objects will be in the inactive list.  But if the system is under memory
> pressure (from something other than GPU), we could still get a lot of
> shrinker calls.  Which results in traversing a list of thousands of objs
> and in the end finding nothing to shrink.  Which isn't so efficient.
> 
> Instead split the inactive_list into two lists, one inactive objs which
> are shrinkable, and a second one for those that are not.  This way we
> can avoid traversing objs which we know are not shrinker candidates.
> 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/msm_debugfs.c  |  3 ++-
>  drivers/gpu/drm/msm/msm_drv.c  |  3 ++-
>  drivers/gpu/drm/msm/msm_drv.h  |  8 +++---
>  drivers/gpu/drm/msm/msm_gem.c  | 34 --
>  drivers/gpu/drm/msm/msm_gem_shrinker.c |  7 +++---
>  5 files changed, 40 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_debugfs.c 
> b/drivers/gpu/drm/msm/msm_debugfs.c
> index 64afbed89821..85ad0babc326 100644
> --- a/drivers/gpu/drm/msm/msm_debugfs.c
> +++ b/drivers/gpu/drm/msm/msm_debugfs.c
> @@ -124,7 +124,8 @@ static int msm_gem_show(struct drm_device *dev, struct 
> seq_file *m)
>   }
>  
>   seq_printf(m, "Inactive Objects:\n");
> - msm_gem_describe_objects(&priv->inactive_list, m);
> + msm_gem_describe_objects(&priv->inactive_dontneed, m);
> + msm_gem_describe_objects(&priv->inactive_willneed, m);
>  
>   mutex_unlock(&priv->mm_lock);
>  
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 4d808769e6ed..39a54f364aa8 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -465,7 +465,8 @@ static int msm_drm_init(struct device *dev, struct 
> drm_driver *drv)
>  
>   priv->wq = alloc_ordered_workqueue("msm", 0);
>  
> - INIT_LIST_HEAD(&priv->inactive_list);
> + INIT_LIST_HEAD(&priv->inactive_willneed);
> + INIT_LIST_HEAD(&priv->inactive_dontneed);
>   mutex_init(&priv->mm_lock);
>  
>   /* Teach lockdep about lock ordering wrt. shrinker: */
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index f869ed67b5da..ed18c5bed10f 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -175,8 +175,9 @@ struct msm_drm_private {
>   struct msm_perf_state *perf;
>  
>   /*
> -  * List of inactive GEM objects.  Every bo is either in the 
> inactive_list
> -  * or gpu->active_list (for the gpu it is active on[1])
> +  * Lists of inactive GEM objects.  Every bo is either in one of the
> +  * inactive lists (depending on whether or not it is shrinkable) or
> +  * gpu->active_list (for the gpu it is active on[1])
>*
>* These lists are protected by mm_lock.  If struct_mutex is involved, 
> it
>* should be aquired prior to mm_lock.  One should *not* hold mm_lock in
> @@ -185,7 +186,8 @@ struct msm_drm_private {
>* [1] if someone ever added support for the old 2d cores, there could 
> be
>* more than one gpu object
>*/
> - struct list_head inactive_list;
> + struct list_head inactive_willneed;  /* inactive + !shrinkable */
> + struct list_head inactive_dontneed;  /* inactive +  shrinkable */
>   struct mutex mm_lock;
>  
>   struct workqueue_struct *wq;
> diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
> index 2795288b0a95..de8d2cfada24 100644
> --- a/drivers/gpu/drm/msm/msm_gem.c
> +++ b/drivers/gpu/drm/msm/msm_gem.c
> @@ -17,6 +17,7 @@
>  #include "msm_gpu.h"
>  #include "msm_mmu.h"
>  
> +static void update_inactive(struct msm_gem_object *msm_obj);
>  
>  static dma_addr_t physaddr(struct drm_gem_object *obj)
>  {
> @@ -678,6 +679,12 @@ int msm_gem_madvise(struct drm_gem_object *obj, unsigned 
> madv)
>  
>   madv = msm_obj->madv;
>  
> + /* If the obj is inactive, we might need to move it
> +  * between inactive lists
> +  */
> + if (msm_obj->active_count == 0)
> + update_inactive(msm_obj);
> +
>   msm_gem_unlock(obj);
>  
>   return (madv != __MSM_MADV_PURGED);
> @@ -781,19 +788,31 @@ void msm_gem_active_get(struct drm_gem_object *obj, 
> struct msm_gpu *gpu)
>  void msm_gem_active_put(struct drm_gem_object *obj)
>  {
>   struct msm_gem_object *msm_obj = to_msm_bo(obj);
> - struct msm_drm_private *priv = obj->dev->dev_private;
>  
>   might_sleep();
>   WARN_ON(!msm_gem_is_locked(obj));
>  
>   if (--msm_obj->active_count == 0) {
> - mutex_lock(&priv->mm_lock);
> - list_del_init(&msm_obj->mm_list);
> - list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
> - mutex_unlock(&priv->mm_lock);
> + update_inactive(msm_obj);
>   }
>  }
>  
> +static void updat

Re: [Freedreno] [RESEND PATCH v2 4/5] drm/msm: add DRM_MSM_GEM_SYNC_CACHE for non-coherent cache maintenance

2020-11-16 Thread Jordan Crouse
On Sat, Nov 14, 2020 at 10:17:12AM -0500, Jonathan Marek wrote:
> This makes it possible to use the non-coherent cached MSM_BO_CACHED mode,
> which otherwise doesn't provide any method for cleaning/invalidating the
> cache to sync with the device.
> 
> Signed-off-by: Jonathan Marek 
> ---
>  drivers/gpu/drm/msm/msm_drv.c | 21 +
>  drivers/gpu/drm/msm/msm_drv.h |  2 ++
>  drivers/gpu/drm/msm/msm_gem.c | 23 +++
>  include/uapi/drm/msm_drm.h| 20 
>  4 files changed, 66 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index bae48afca82e..3f17acdf6594 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -959,6 +959,26 @@ static int msm_ioctl_submitqueue_close(struct drm_device 
> *dev, void *data,
>   return msm_submitqueue_remove(file->driver_priv, id);
>  }
>  
> +static int msm_ioctl_gem_sync_cache(struct drm_device *dev, void *data,
> + struct drm_file *file)
> +{
> + struct drm_msm_gem_sync_cache *args = data;
> + struct drm_gem_object *obj;
> +
> + if (args->flags & ~MSM_GEM_SYNC_CACHE_FLAGS)
> + return -EINVAL;
> +
> + obj = drm_gem_object_lookup(file, args->handle);
> + if (!obj)
> + return -ENOENT;
> +
> + msm_gem_sync_cache(obj, args->flags, args->offset, args->end);
> +
> + drm_gem_object_put(obj);
> +
> + return 0;
> +}
> +
>  static const struct drm_ioctl_desc msm_ioctls[] = {
>   DRM_IOCTL_DEF_DRV(MSM_GET_PARAM,msm_ioctl_get_param,
> DRM_RENDER_ALLOW),
>   DRM_IOCTL_DEF_DRV(MSM_GEM_NEW,  msm_ioctl_gem_new,  
> DRM_RENDER_ALLOW),
> @@ -971,6 +991,7 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
>   DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW,   msm_ioctl_submitqueue_new,   
> DRM_RENDER_ALLOW),
>   DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, 
> DRM_RENDER_ALLOW),
>   DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, 
> DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(MSM_GEM_SYNC_CACHE,msm_ioctl_gem_sync_cache,
> DRM_RENDER_ALLOW),
>  };
>  
>  static const struct vm_operations_struct vm_ops = {
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index 22ebecb28349..f170f843010e 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -318,6 +318,8 @@ void msm_gem_active_get(struct drm_gem_object *obj, 
> struct msm_gpu *gpu);
>  void msm_gem_active_put(struct drm_gem_object *obj);
>  int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t 
> *timeout);
>  int msm_gem_cpu_fini(struct drm_gem_object *obj);
> +void msm_gem_sync_cache(struct drm_gem_object *obj, uint32_t flags,
> + size_t range_start, size_t range_end);
>  void msm_gem_free_object(struct drm_gem_object *obj);
>  int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
>   uint32_t size, uint32_t flags, uint32_t *handle, char *name);
> diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
> index 3d8254b5de16..039738696f9a 100644
> --- a/drivers/gpu/drm/msm/msm_gem.c
> +++ b/drivers/gpu/drm/msm/msm_gem.c
> @@ -797,6 +797,29 @@ int msm_gem_cpu_fini(struct drm_gem_object *obj)
>   return 0;
>  }
>  
> +void msm_gem_sync_cache(struct drm_gem_object *obj, uint32_t flags,
> + size_t range_start, size_t range_end)
> +{
> + struct msm_gem_object *msm_obj = to_msm_bo(obj);
> + struct device *dev = msm_obj->base.dev->dev;
> +

On a6xx targets with I/O coherency you can skip this (assuming that the IOMMU
flag has been set for this buffer). I'm not sure if one of the other patches
already does the bypass but I mention it here since this is the point of
no-return.

Jordan

> + /* exit early if get_pages() hasn't been called yet */
> + if (!msm_obj->pages)
> + return;
> +
> + /* TODO: sync only the specified range */
> +
> + if (flags & MSM_GEM_SYNC_FOR_DEVICE) {
> + dma_sync_sg_for_device(dev, msm_obj->sgt->sgl,
> + msm_obj->sgt->nents, DMA_TO_DEVICE);
> + }
> +
> + if (flags & MSM_GEM_SYNC_FOR_CPU) {
> + dma_sync_sg_for_cpu(dev, msm_obj->sgt->sgl,
> + msm_obj->sgt->nents, DMA_FROM_DEVICE);
> + }
> +}
> +
>  #ifdef CONFIG_DEBUG_FS
>  static void describe_fence(struct dma_fence *fence, const char *type,
>   struct seq_file *m)
> diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
> index 474497e8743a..c8288f328528 100644
> --- a/include/uapi/drm/msm_drm.h
> +++ b/include/uapi/drm/msm_drm.h
> @@ -319,6 +319,24 @@ struct drm_msm_submitqueue_query {
>   __u32 pad;
>  };
>  
> +/*
> + * Host cache maintenance (relevant for MSM_BO_CACHED)
> + * driver may both clean/invalidate (flush) for clean
> + */
> +
> +#define MSM_GEM_SYNC_FOR_DEVICE 

Re: [Freedreno] [RESEND PATCH v2 4/5] drm/msm: add DRM_MSM_GEM_SYNC_CACHE for non-coherent cache maintenance

2020-11-16 Thread Jordan Crouse
On Sat, Nov 14, 2020 at 11:39:45AM -0800, Rob Clark wrote:
> On Sat, Nov 14, 2020 at 10:58 AM Jonathan Marek  wrote:
> >
> > On 11/14/20 1:46 PM, Rob Clark wrote:
> > > On Sat, Nov 14, 2020 at 8:24 AM Christoph Hellwig  wrote:
> > >>
> > >> On Sat, Nov 14, 2020 at 10:17:12AM -0500, Jonathan Marek wrote:
> > >>> +void msm_gem_sync_cache(struct drm_gem_object *obj, uint32_t flags,
> > >>> + size_t range_start, size_t range_end)
> > >>> +{
> > >>> + struct msm_gem_object *msm_obj = to_msm_bo(obj);
> > >>> + struct device *dev = msm_obj->base.dev->dev;
> > >>> +
> > >>> + /* exit early if get_pages() hasn't been called yet */
> > >>> + if (!msm_obj->pages)
> > >>> + return;
> > >>> +
> > >>> + /* TODO: sync only the specified range */
> > >>> +
> > >>> + if (flags & MSM_GEM_SYNC_FOR_DEVICE) {
> > >>> + dma_sync_sg_for_device(dev, msm_obj->sgt->sgl,
> > >>> + msm_obj->sgt->nents, DMA_TO_DEVICE);
> > >>> + }
> > >>> +
> > >>> + if (flags & MSM_GEM_SYNC_FOR_CPU) {
> > >>> + dma_sync_sg_for_cpu(dev, msm_obj->sgt->sgl,
> > >>> + msm_obj->sgt->nents, DMA_FROM_DEVICE);
> > >>> + }
> > >>
> > >> Splitting this helper from the only caller is rather strange, epecially
> > >> with the two unused arguments.  And I think the way this is specified
> > >> to take a range, but ignoring it is actively dangerous.  User space will
> > >> rely on it syncing everything sooner or later and then you are stuck.
> > >> So just define a sync all primitive for now, and if you really need a
> > >> range sync and have actually implemented it add a new ioctl for that.
> > >
> > > We do already have a split of ioctl "layer" which enforces valid ioctl
> > > params, etc, and gem (or other) module code which is called by the
> > > ioctl func.  So I think it is fine to keep this split here.  (Also, I
> > > think at some point there will be a uring type of ioctl alternative
> > > which would re-use the same gem func.)
> > >
> > > But I do agree that the range should be respected or added later..
> > > drm_ioctl() dispatch is well prepared for extending ioctls.
> > >
> > > And I assume there should be some validation that the range is aligned
> > > to cache-line?  Or can we flush a partial cache line?
> > >
> >
> > The range is intended to be "sync at least this range", so that
> > userspace doesn't have to worry about details like that.
> >
> 
> I don't think userspace can *not* worry about details like that.
> Consider a case where the cpu and gpu are simultaneously accessing
> different parts of a buffer (for ex, sub-allocation).  There needs to
> be cache-line separation between the two.

There is at least one compute conformance test that I can think of that does
exactly this.

Jordan

> BR,
> -R
> ___
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH v2 0/3] iommu/arm-smmu: adreno-smmu page fault handling

2020-11-24 Thread Jordan Crouse
This is a stack to add an Adreno GPU specific handler for pagefaults. The first
patch starts by wiring up report_iommu_fault for arm-smmu. The next patch adds
a adreno-smmu-priv function hook to capture a handful of important debugging
registers such as TTBR0, CONTEXTIDR, FSYNR0 and others. This is used by the
third patch to print more detailed information on page fault such as the TTBR0
for the pagetable that caused the fault and the source of the fault as
determined by a combination of the FSYNR1 register and an internal GPU
register.

This code provides a solid base that we can expand on later for even more
extensive GPU side page fault debugging capabilities.

v2: Fix comment wording and function pointer check per Rob Clark

Jordan Crouse (3):
  iommu/arm-smmu: Add support for driver IOMMU fault handlers
  drm/msm: Add an adreno-smmu-priv callback to get pagefault info
  drm/msm: Improve the a6xx page fault handler

 drivers/gpu/drm/msm/adreno/a5xx_gpu.c  |  4 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  | 76 +-
 drivers/gpu/drm/msm/msm_iommu.c| 11 +++-
 drivers/gpu/drm/msm/msm_mmu.h  |  4 +-
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.c  | 16 -
 drivers/iommu/arm/arm-smmu/arm-smmu.h  |  2 +
 include/linux/adreno-smmu-priv.h   | 31 -
 8 files changed, 151 insertions(+), 12 deletions(-)

-- 
2.25.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH v2 3/3] drm/msm: Improve the a6xx page fault handler

2020-11-24 Thread Jordan Crouse
Use the new adreno-smmu-priv fault info function to get more SMMU
debug registers and print the current TTBR0 to debug per-instance
pagetables and figure out which GPU block generated the request.

Signed-off-by: Jordan Crouse 
---

 drivers/gpu/drm/msm/adreno/a5xx_gpu.c |  4 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 76 +--
 drivers/gpu/drm/msm/msm_iommu.c   | 11 +++-
 drivers/gpu/drm/msm/msm_mmu.h |  4 +-
 4 files changed, 87 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index d6804a802355..ed4cb81af874 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -933,7 +933,7 @@ bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer 
*ring)
return true;
 }
 
-static int a5xx_fault_handler(void *arg, unsigned long iova, int flags)
+static int a5xx_fault_handler(void *arg, unsigned long iova, int flags, void 
*data)
 {
struct msm_gpu *gpu = arg;
pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d 
(%u,%u,%u,%u)\n",
@@ -943,7 +943,7 @@ static int a5xx_fault_handler(void *arg, unsigned long 
iova, int flags)
gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(6)),
gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(7)));
 
-   return -EFAULT;
+   return 0;
 }
 
 static void a5xx_cp_err_irq(struct msm_gpu *gpu)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 948f3656c20c..ac6e8cd5cf1a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -905,18 +905,88 @@ static void a6xx_recover(struct msm_gpu *gpu)
msm_gpu_hw_init(gpu);
 }
 
-static int a6xx_fault_handler(void *arg, unsigned long iova, int flags)
+static const char *a6xx_uche_fault_block(struct msm_gpu *gpu, u32 mid)
+{
+   static const char *uche_clients[7] = {
+   "VFD", "SP", "VSC", "VPC", "HLSQ", "PC", "LRZ",
+   };
+   u32 val;
+
+   if (mid < 1 || mid > 3)
+   return "UNKNOWN";
+
+   /*
+* The source of the data depends on the mid ID read from FSYNR1.
+* and the client ID read from the UCHE block
+*/
+   val = gpu_read(gpu, REG_A6XX_UCHE_CLIENT_PF);
+
+   /* mid = 3 is most precise and refers to only one block per client */
+   if (mid == 3)
+   return uche_clients[val & 7];
+
+   /* For mid=2 the source is TP or VFD except when the client id is 0 */
+   if (mid == 2)
+   return ((val & 7) == 0) ? "TP" : "TP|VFD";
+
+   /* For mid=1 just return "UCHE" as a catchall for everything else */
+   return "UCHE";
+}
+
+static const char *a6xx_fault_block(struct msm_gpu *gpu, u32 id)
+{
+   if (id == 0)
+   return "CP";
+   else if (id == 4)
+   return "CCU";
+   else if (id == 6)
+   return "CDP Prefetch";
+
+   return a6xx_uche_fault_block(gpu, id);
+}
+
+#define ARM_SMMU_FSR_TF BIT(1)
+#define ARM_SMMU_FSR_PFBIT(3)
+#define ARM_SMMU_FSR_EFBIT(4)
+
+static int a6xx_fault_handler(void *arg, unsigned long iova, int flags, void 
*data)
 {
struct msm_gpu *gpu = arg;
+   struct adreno_smmu_fault_info *info = data;
+   const char *type = "UNKNOWN";
 
-   pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d 
(%u,%u,%u,%u)\n",
+   /*
+* Print a default message if we couldn't get the data from the
+* adreno-smmu-priv
+*/
+   if (!info) {
+   pr_warn_ratelimited("*** gpu fault: iova=%.16lx flags=%d 
(%u,%u,%u,%u)\n",
iova, flags,
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(4)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(5)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(6)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(7)));
 
-   return -EFAULT;
+   return 0;
+   }
+
+   if (info->fsr & ARM_SMMU_FSR_TF)
+   type = "TRANSLATION";
+   else if (info->fsr & ARM_SMMU_FSR_PF)
+   type = "PERMISSION";
+   else if (info->fsr & ARM_SMMU_FSR_EF)
+   type = "EXTERNAL";
+
+   pr_warn_ratelimited("*** gpu fault: ttbr0=%.16llx iova=%.16lx dir=%s 
type=%s source=%s (%u,%u,%u,%u)\n",
+   info->ttbr0, iova,
+   flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ", type,
+   a6xx_fault_block(gpu, info->fsynr1 & 0xff),
+   gpu_read(gpu, REG

Re: [Freedreno] [PATCH v2 1/3] drm/msm: adreno: Make speed-bin support generic

2020-11-30 Thread Jordan Crouse
On Fri, Nov 27, 2020 at 06:19:44PM +0530, Akhil P Oommen wrote:
> So far a530v2 gpu has support for detecting its supported opps
> based on a fuse value called speed-bin. This patch makes this
> support generic across gpu families. This is in preparation to
> extend speed-bin support to a6x family.
> 
> Signed-off-by: Akhil P Oommen 
> ---
> Changes from v1:
>   1. Added the changes to support a618 sku to the series.
>   2. Avoid failing probe in case of an unsupported sku. (Rob)
> 
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c  | 34 --
>  drivers/gpu/drm/msm/adreno/adreno_device.c |  4 ++
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c| 71 
> ++
>  drivers/gpu/drm/msm/adreno/adreno_gpu.h|  5 +++
>  4 files changed, 80 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 8fa5c91..7d42321 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -1531,38 +1531,6 @@ static const struct adreno_gpu_funcs funcs = {
>   .get_timestamp = a5xx_get_timestamp,
>  };
>  
> -static void check_speed_bin(struct device *dev)
> -{
> - struct nvmem_cell *cell;
> - u32 val;
> -
> - /*
> -  * If the OPP table specifies a opp-supported-hw property then we have
> -  * to set something with dev_pm_opp_set_supported_hw() or the table
> -  * doesn't get populated so pick an arbitrary value that should
> -  * ensure the default frequencies are selected but not conflict with any
> -  * actual bins
> -  */
> - val = 0x80;
> -
> - cell = nvmem_cell_get(dev, "speed_bin");
> -
> - if (!IS_ERR(cell)) {
> - void *buf = nvmem_cell_read(cell, NULL);
> -
> - if (!IS_ERR(buf)) {
> - u8 bin = *((u8 *) buf);
> -
> - val = (1 << bin);
> - kfree(buf);
> - }
> -
> - nvmem_cell_put(cell);
> - }
> -
> - dev_pm_opp_set_supported_hw(dev, &val, 1);
> -}
> -
>  struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
>  {
>   struct msm_drm_private *priv = dev->dev_private;
> @@ -1588,8 +1556,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
>  
>   a5xx_gpu->lm_leakage = 0x4E001A;
>  
> - check_speed_bin(&pdev->dev);
> -
>   ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4);
>   if (ret) {
>   a5xx_destroy(&(a5xx_gpu->base.base));
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
> b/drivers/gpu/drm/msm/adreno/adreno_device.c
> index 87c8b03..e0ff16c 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> @@ -18,6 +18,8 @@ bool snapshot_debugbus = false;
>  MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU 
> devcoredump (if not fused off)");
>  module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600);
>  
> +const u32 a530v2_speedbins[] = {0, 1, 2, 3, 4, 5, 6, 7};
> +
>  static const struct adreno_info gpulist[] = {
>   {
>   .rev   = ADRENO_REV(2, 0, 0, 0),
> @@ -163,6 +165,8 @@ static const struct adreno_info gpulist[] = {
>   ADRENO_QUIRK_FAULT_DETECT_MASK,
>   .init = a5xx_gpu_init,
>   .zapfw = "a530_zap.mdt",
> + .speedbins = a530v2_speedbins,
> + .speedbins_count = ARRAY_SIZE(a530v2_speedbins),
>   }, {
>   .rev = ADRENO_REV(5, 4, 0, 2),
>   .revn = 540,
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index f21561d..b342fa4 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -14,6 +14,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include "adreno_gpu.h"
>  #include "msm_gem.h"
> @@ -891,6 +892,69 @@ void adreno_gpu_ocmem_cleanup(struct adreno_ocmem 
> *adreno_ocmem)
>  adreno_ocmem->hdl);
>  }
>  
> +static int adreno_set_supported_hw(struct device *dev,
> + struct adreno_gpu *adreno_gpu)
> +{
> + u8 speedbins_count = adreno_gpu->info->speedbins_count;
> + const u32 *speedbins = adreno_gpu->info->speedbins;
> + struct nvmem_cell *cell;
> + u32 bin, i;
> + u32 val = 0;
> + void *buf, *opp_table;
> +
> + cell = nvmem_cell_get(dev, "speed_bin");
> + /*
> +  * -ENOENT means that the platform doesn't support speedbin which is
> +  * fine
> +  */
> + if (PTR_ERR(cell) == -ENOENT)
> + return 0;
> + else if (IS_ERR(cell))
> + return PTR_ERR(cell);
> +
> + if (!speedbins)
> + goto done;
> +
> + buf = nvmem_cell_read(cell, NULL);
> + if (IS_ERR(buf)) {
> + nvmem_cell_put(cell);
> + return PTR_ERR(buf);
> + }
> +
> + bin = *((u32 *) buf);
> +
> + for (i = 0; i <

Re: [Freedreno] [PATCH v2 1/3] drm/msm: adreno: Make speed-bin support generic

2020-12-02 Thread Jordan Crouse
On Wed, Dec 02, 2020 at 08:53:51PM +0530, Akhil P Oommen wrote:
> On 11/30/2020 10:32 PM, Jordan Crouse wrote:
> >On Fri, Nov 27, 2020 at 06:19:44PM +0530, Akhil P Oommen wrote:
> >>So far a530v2 gpu has support for detecting its supported opps
> >>based on a fuse value called speed-bin. This patch makes this
> >>support generic across gpu families. This is in preparation to
> >>extend speed-bin support to a6x family.
> >>
> >>Signed-off-by: Akhil P Oommen 
> >>---
> >>Changes from v1:
> >>1. Added the changes to support a618 sku to the series.
> >>2. Avoid failing probe in case of an unsupported sku. (Rob)
> >>
> >>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c  | 34 --
> >>  drivers/gpu/drm/msm/adreno/adreno_device.c |  4 ++
> >>  drivers/gpu/drm/msm/adreno/adreno_gpu.c| 71 
> >> ++
> >>  drivers/gpu/drm/msm/adreno/adreno_gpu.h|  5 +++
> >>  4 files changed, 80 insertions(+), 34 deletions(-)
> >>
> >>diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> >>b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> >>index 8fa5c91..7d42321 100644
> >>--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> >>+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> >>@@ -1531,38 +1531,6 @@ static const struct adreno_gpu_funcs funcs = {
> >>.get_timestamp = a5xx_get_timestamp,
> >>  };
> >>-static void check_speed_bin(struct device *dev)
> >>-{
> >>-   struct nvmem_cell *cell;
> >>-   u32 val;
> >>-
> >>-   /*
> >>-* If the OPP table specifies a opp-supported-hw property then we have
> >>-* to set something with dev_pm_opp_set_supported_hw() or the table
> >>-* doesn't get populated so pick an arbitrary value that should
> >>-* ensure the default frequencies are selected but not conflict with any
> >>-* actual bins
> >>-*/
> >>-   val = 0x80;
> >>-
> >>-   cell = nvmem_cell_get(dev, "speed_bin");
> >>-
> >>-   if (!IS_ERR(cell)) {
> >>-   void *buf = nvmem_cell_read(cell, NULL);
> >>-
> >>-   if (!IS_ERR(buf)) {
> >>-   u8 bin = *((u8 *) buf);
> >>-
> >>-   val = (1 << bin);
> >>-   kfree(buf);
> >>-   }
> >>-
> >>-   nvmem_cell_put(cell);
> >>-   }
> >>-
> >>-   dev_pm_opp_set_supported_hw(dev, &val, 1);
> >>-}
> >>-
> >>  struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
> >>  {
> >>struct msm_drm_private *priv = dev->dev_private;
> >>@@ -1588,8 +1556,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
> >>a5xx_gpu->lm_leakage = 0x4E001A;
> >>-   check_speed_bin(&pdev->dev);
> >>-
> >>ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4);
> >>if (ret) {
> >>a5xx_destroy(&(a5xx_gpu->base.base));
> >>diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
> >>b/drivers/gpu/drm/msm/adreno/adreno_device.c
> >>index 87c8b03..e0ff16c 100644
> >>--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> >>+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> >>@@ -18,6 +18,8 @@ bool snapshot_debugbus = false;
> >>  MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU 
> >> devcoredump (if not fused off)");
> >>  module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600);
> >>+const u32 a530v2_speedbins[] = {0, 1, 2, 3, 4, 5, 6, 7};
> >>+
> >>  static const struct adreno_info gpulist[] = {
> >>{
> >>.rev   = ADRENO_REV(2, 0, 0, 0),
> >>@@ -163,6 +165,8 @@ static const struct adreno_info gpulist[] = {
> >>ADRENO_QUIRK_FAULT_DETECT_MASK,
> >>.init = a5xx_gpu_init,
> >>.zapfw = "a530_zap.mdt",
> >>+   .speedbins = a530v2_speedbins,
> >>+   .speedbins_count = ARRAY_SIZE(a530v2_speedbins),
> >>}, {
> >>.rev = ADRENO_REV(5, 4, 0, 2),
> >>.revn = 540,
> >>diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> >>b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >>index f21561d..b342fa4 100644
> >>--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >>+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >>@@ -14,6 +14,7 @

Re: [Freedreno] [PATCH v3 1/2] drm/msm: Add speed-bin support to a618 gpu

2021-01-04 Thread Jordan Crouse
On Mon, Dec 07, 2020 at 04:12:07PM +0530, Akhil P Oommen wrote:
> Some GPUs support different max frequencies depending on the platform.
> To identify the correct variant, we should check the gpu speedbin
> fuse value. Add support for this speedbin detection to a6xx family
> along with the required fuse details for a618 gpu.
> 
> Signed-off-by: Akhil P Oommen 
> ---
> Changes from v2:
>   1. Made the changes a6xx specific to save space.
> Changes from v1:
>   1. Added the changes to support a618 sku to the series.
>   2. Avoid failing probe in case of an unsupported sku. (Rob)
> 
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 74 
> +++
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.h |  2 +
>  2 files changed, 76 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 1306618..6304578 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -10,10 +10,13 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #define GPU_PAS_ID 13
>  
> +const u32 a618_speedbins[] = {0, 169, 174};

This still feels too generic to me - this could easily be something like:

static u32 a618_get_speed_bin(int rev)
{
if (rev == 0)
return 0;
else if (rev == 169)
return 1;
else if (rev == 174)
return 2;

return UINT_MAX;
}

I know Akhil can see a future where there might be other "pro" targets but it is
unclear to me when those will see upstream support and even if they do a
handful of inline-able functions still seem better to me than a group of const
arrays.

> +
>  static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> @@ -1208,6 +1211,10 @@ static void a6xx_destroy(struct msm_gpu *gpu)
>   a6xx_gmu_remove(a6xx_gpu);
>  
>   adreno_gpu_cleanup(adreno_gpu);
> +
> + if (a6xx_gpu->opp_table)
> + dev_pm_opp_put_supported_hw(a6xx_gpu->opp_table);
> +
>   kfree(a6xx_gpu);
>  }
>  
> @@ -1264,6 +1271,67 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, 
> struct msm_ringbuffer *ring)
>   return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR);
>  }
>  
> +static u32 fuse_to_supp_hw(struct device *dev, u32 revn, u32 fuse)
> +{
> + int i;
> +
> + if (revn == 618) {
> + for (i = 0; i < ARRAY_SIZE(a618_speedbins); i++) {
> + if (fuse == a618_speedbins[i])
> + return  (1 << i);
> + }
> + }

u32 val = UINT_MAX;

if (revn == 618)
val = a618_get_speed_bin(fuse);

if (val == UINT_MAX)
DRM_DEV_ERROR(dev, "Missing support for speed-bin %u. Some OPPs may not
be supported by hardware", fuse);

return val;

> +
> + DRM_DEV_ERROR(dev,
> + "missing support for speed-bin: %u. Some OPPs may not 
> be supported by hardware",
> + fuse);
> + return ~0U;
> +}
> +
> +static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu 
> *a6xx_gpu,
> + u32 revn)
> +{
> +
> + struct opp_table *opp_table;
> + struct nvmem_cell *cell;
> + u32 supp_hw = ~0U;
> + void *buf;
> +
> + cell = nvmem_cell_get(dev, "speed_bin");
> + /*
> +  * -ENOENT means that the platform doesn't support speedbin which is
> +  * fine
> +  */
> + if (PTR_ERR(cell) == -ENOENT)
> + return 0;
> + else if (IS_ERR(cell)) {
> + DRM_DEV_ERROR(dev,
> + "failed to read speed-bin. Some OPPs may not be 
> supported by hardware");
> + goto done;
> + }
> +
> + buf = nvmem_cell_read(cell, NULL);
> + if (IS_ERR(buf)) {
> + nvmem_cell_put(cell);
> + DRM_DEV_ERROR(dev,
> + "failed to read speed-bin. Some OPPs may not be 
> supported by hardware");
> + goto done;
> + }
> +
> + supp_hw = fuse_to_supp_hw(dev, revn, *((u32 *) buf));
> +
> + kfree(buf);
> + nvmem_cell_put(cell);
> +
> +done:
> + opp_table = dev_pm_opp_set_supported_hw(dev, &supp_hw, 1);
> + if (IS_ERR(opp_table))
> + return PTR_ERR(opp_table);
> +
> + a6xx_gpu->opp_table = opp_table;
> + return 0;
> +}

Beyond the comments above, I think the rest of this is reasonable.

Jordan

> +
>  static const struct adreno_gpu_funcs funcs = {
>   .base = {
>   .get_param = adreno_get_param,
> @@ -1325,6 +1393,12 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
>  
>   a6xx_llc_slices_init(pdev, a6xx_gpu);
>  
> + ret = a6xx_set_supported_hw(&pdev->dev, a6xx_gpu, info->revn);
> + if (ret) {
> + a6xx_destroy(&(a6xx_gpu->base.base));
> + return ERR_PTR(ret);
> + }
> +
>   ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
>   if (ret) {
>  

Re: [Freedreno] [PATCH] drm/msm: Only enable A6xx LLCC code on A6xx

2021-01-04 Thread Jordan Crouse
On Mon, Jan 04, 2021 at 08:30:41PM +0100, Konrad Dybcio wrote:
> Using this code on A5xx (and probably older too) causes a
> smmu bug.
> 
> Fixes: 474dadb8b0d5 ("drm/msm/a6xx: Add support for using system cache(LLC)")
> Signed-off-by: Konrad Dybcio 
> Tested-by: AngeloGioacchino Del Regno 
> 

Yep, I can see how this would be not ideal.

Reviewed-by: Jordan Crouse 

> ---
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 21 -
>  drivers/gpu/drm/msm/adreno/adreno_gpu.h |  5 +
>  2 files changed, 17 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index 6cf9975e951e..f09175698827 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -191,8 +191,6 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu,
>   struct platform_device *pdev)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> - struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
> - struct io_pgtable_domain_attr pgtbl_cfg;
>   struct iommu_domain *iommu;
>   struct msm_mmu *mmu;
>   struct msm_gem_address_space *aspace;
> @@ -202,13 +200,18 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu,
>   if (!iommu)
>   return NULL;
>  
> - /*
> -  * This allows GPU to set the bus attributes required to use system
> -  * cache on behalf of the iommu page table walker.
> -  */
> - if (!IS_ERR(a6xx_gpu->htw_llc_slice)) {
> - pgtbl_cfg.quirks = IO_PGTABLE_QUIRK_ARM_OUTER_WBWA;
> - iommu_domain_set_attr(iommu, DOMAIN_ATTR_IO_PGTABLE_CFG, 
> &pgtbl_cfg);
> +
> + if (adreno_is_a6xx(adreno_gpu)) {
> + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
> + struct io_pgtable_domain_attr pgtbl_cfg;
> + /*
> + * This allows GPU to set the bus attributes required to use 
> system
> + * cache on behalf of the iommu page table walker.
> + */
> + if (!IS_ERR(a6xx_gpu->htw_llc_slice)) {
> + pgtbl_cfg.quirks = IO_PGTABLE_QUIRK_ARM_OUTER_WBWA;
> + iommu_domain_set_attr(iommu, 
> DOMAIN_ATTR_IO_PGTABLE_CFG, &pgtbl_cfg);
> + }
>   }
>  
>   mmu = msm_iommu_new(&pdev->dev, iommu);
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> index 4574d85c5680..08421fa54a50 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> @@ -226,6 +226,11 @@ static inline int adreno_is_a540(struct adreno_gpu *gpu)
>   return gpu->revn == 540;
>  }
>  
> +static inline bool adreno_is_a6xx(struct adreno_gpu *gpu)
> +{
> + return ((gpu->revn < 700 && gpu->revn > 599));
> +}
> +
>  static inline int adreno_is_a618(struct adreno_gpu *gpu)
>  {
> return gpu->revn == 618;
> -- 
> 2.29.2
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH] drm/msm: Only enable A6xx LLCC code on A6xx

2021-01-11 Thread Jordan Crouse
On Mon, Jan 11, 2021 at 09:54:12AM +0530, Sai Prakash Ranjan wrote:
> Hi Rob,
> 
> On 2021-01-08 22:16, Rob Clark wrote:
> >On Fri, Jan 8, 2021 at 6:05 AM Sai Prakash Ranjan
> > wrote:
> >>
> >>On 2021-01-08 19:09, Konrad Dybcio wrote:
>  Konrad, can you please test this below change without your change?
> >>>
> >>> This brings no difference, a BUG still happens. We're still calling
> >>> to_a6xx_gpu on ANY device that's probed! Too bad it won't turn my A330
> >>> into an A640..
> >>>
> >>> Also, relying on disabling LLCC in the config is out of question as it
> >>> makes the arm32 kernel not compile with DRM/MSM and it just removes
> >>> the functionality on devices with a6xx.. (unless somebody removes the
> >>> dependency on it, which in my opinion is even worse and will cause
> >>> more problems for developers!).
> >>>
> >>
> >>Disabling LLCC is not the suggestion, I was under the impression that
> >>was the cause here for the smmu bug. Anyways, the check for llc slice
> >>in case llcc is disabled is not correct as well. I will send a patch for
> >>that as well.
> >>
> >>> The bigger question is how and why did that piece of code ever make it
> >>> to adreno_gpu.c and not a6xx_gpu.c?
> >>>
> >>
> >>My mistake, I will move it.
> >
> >Thanks, since we don't have kernel-CI coverage for gpu, and there
> >probably isn't one person who has all the different devices supported
> >(or enough hours in the day to test them all), it is probably
> >better/safer to keep things in the backend code that is specific to a
> >given generation.
> >
> 
> Agreed, I will post this change soon and will introduce some feature
> check as well because we will need it for iommu prot flag as per discussion
> here - https://lore.kernel.org/lkml/20210108181830.GA5457@willie-the-truck/
> 
> >>> To solve it in a cleaner way I propose to move it to an a6xx-specific
> >>> file, or if it's going to be used with next-gen GPUs, perhaps manage
> >>> calling of this code via an adreno quirk/feature in adreno_device.c.
> >>> Now that I think about it, A5xx GPMU en/disable could probably managed
> >>> like that, instead of using tons of if-statements for each GPU model
> >>> that has it..
> >>>
> >>> While we're at it, do ALL (and I truly do mean ALL, including the
> >>> low-end ones, this will be important later on) A6xx GPUs make use of
> >>> that feature?
> >>>
> >>
> >>I do not have a list of all A6XX GPUs with me currently, but from what
> >>I know, A618, A630, A640, A650 has the support.
> >>
> >
> >From the PoV of bringing up new a6xx, we should probably consider that
> >some of them may not *yet* have LLCC enabled.  I have an 8cx laptop
> >and once I find time to get the display working, the next step would
> >be bringing up a680.. and I'd probably like to start without LLCC..
> >
> 
> Right, once I move the LLCC code to a6xx specific address space creation,
> without LLCC slices for GPU specified in qcom llcc driver, we will not
> be using it.

Right. The problem here was that we were assuming an a6xx container in generic
code. Testing the existence of LLCC or not is a different problem but it is my
understanding that if we set the attribute without LLCC enabled it just gets
ignored. Is that correct Sai?

Jordan

> Thanks,
> Sai
> 
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH v4 1/2] drm/msm: Add speed-bin support to a618 gpu

2021-01-11 Thread Jordan Crouse
On Fri, Jan 08, 2021 at 11:45:30PM +0530, Akhil P Oommen wrote:
> Some GPUs support different max frequencies depending on the platform.
> To identify the correct variant, we should check the gpu speedbin
> fuse value. Add support for this speedbin detection to a6xx family
> along with the required fuse details for a618 gpu.

Reviewed-by: Jordan Crouse 

> Signed-off-by: Akhil P Oommen 
> ---
> Changes from v2:
>   1. Made the changes a6xx specific to save space.
> Changes from v1:
>   1. Added the changes to support a618 sku to the series.
>   2. Avoid failing probe in case of an unsupported sku. (Rob)
> Changes from v3:
>   1. Replace a618_speedbins[] with a function. (Jordan)
> 
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 83 
> +++
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.h |  2 +
>  2 files changed, 85 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 1306618..499d134 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -10,6 +10,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #define GPU_PAS_ID 13
> @@ -1208,6 +1209,10 @@ static void a6xx_destroy(struct msm_gpu *gpu)
>   a6xx_gmu_remove(a6xx_gpu);
>  
>   adreno_gpu_cleanup(adreno_gpu);
> +
> + if (a6xx_gpu->opp_table)
> + dev_pm_opp_put_supported_hw(a6xx_gpu->opp_table);
> +
>   kfree(a6xx_gpu);
>  }
>  
> @@ -1264,6 +1269,78 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, 
> struct msm_ringbuffer *ring)
>   return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR);
>  }
>  
> +static u32 a618_get_speed_bin(u32 fuse)
> +{
> + if (fuse == 0)
> + return 0;
> + else if (fuse == 169)
> + return 1;
> + else if (fuse == 174)
> + return 2;
> +
> + return UINT_MAX;
> +}
> +
> +static u32 fuse_to_supp_hw(struct device *dev, u32 revn, u32 fuse)
> +{
> + u32 val = UINT_MAX;
> +
> + if (revn == 618)
> + val = a618_get_speed_bin(fuse);
> +
> + if (val == UINT_MAX) {
> + DRM_DEV_ERROR(dev,
> + "missing support for speed-bin: %u. Some OPPs may not 
> be supported by hardware",
> + fuse);
> + return UINT_MAX;
> + }
> +
> + return (1 << val);
> +}
> +
> +static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu 
> *a6xx_gpu,
> + u32 revn)
> +{
> + struct opp_table *opp_table;
> + struct nvmem_cell *cell;
> + u32 supp_hw = UINT_MAX;
> + void *buf;
> +
> + cell = nvmem_cell_get(dev, "speed_bin");
> + /*
> +  * -ENOENT means that the platform doesn't support speedbin which is
> +  * fine
> +  */
> + if (PTR_ERR(cell) == -ENOENT)
> + return 0;
> + else if (IS_ERR(cell)) {
> + DRM_DEV_ERROR(dev,
> + "failed to read speed-bin. Some OPPs may not be 
> supported by hardware");
> + goto done;
> + }
> +
> + buf = nvmem_cell_read(cell, NULL);
> + if (IS_ERR(buf)) {
> + nvmem_cell_put(cell);
> + DRM_DEV_ERROR(dev,
> + "failed to read speed-bin. Some OPPs may not be 
> supported by hardware");
> + goto done;
> + }
> +
> + supp_hw = fuse_to_supp_hw(dev, revn, *((u32 *) buf));
> +
> + kfree(buf);
> + nvmem_cell_put(cell);
> +
> +done:
> + opp_table = dev_pm_opp_set_supported_hw(dev, &supp_hw, 1);
> + if (IS_ERR(opp_table))
> + return PTR_ERR(opp_table);
> +
> + a6xx_gpu->opp_table = opp_table;
> + return 0;
> +}
> +
>  static const struct adreno_gpu_funcs funcs = {
>   .base = {
>   .get_param = adreno_get_param,
> @@ -1325,6 +1402,12 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
>  
>   a6xx_llc_slices_init(pdev, a6xx_gpu);
>  
> + ret = a6xx_set_supported_hw(&pdev->dev, a6xx_gpu, info->revn);
> + if (ret) {
> + a6xx_destroy(&(a6xx_gpu->base.base));
> + return ERR_PTR(ret);
> + }
> +
>   ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
>   if (ret) {
>   a6xx_destroy(&(a6xx_gpu->base.base));
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> index e793d32..ce0610c 100644
> --- a/drivers/gpu/drm/msm/adre

Re: [Freedreno] [PATCH v3 5/7] drm/msm/a5xx: Fix VPC protect value in gpu_write()

2021-01-14 Thread Jordan Crouse
On Wed, Jan 13, 2021 at 07:33:37PM +0100, AngeloGioacchino Del Regno wrote:
> From: Konrad Dybcio 
> 
> The upstream API for some reason uses logbase2 instead of
> just passing the argument as-is, whereas downstream CAF
> kernel does the latter.
> 
> Hence, a mistake has been made when porting:
> 4 is the value that's supposed to be passed, but
> log2(4) = 2. Changing the value to 16 (= 2^4) fixes
> the issue.

I like keeping it in human readable values because its easier to visually
identify how many registers are saved without doing math.

Reviewed-by: Jordan Crouse 

> Signed-off-by: Konrad Dybcio 
> Signed-off-by: AngeloGioacchino Del Regno 
> 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 66980f4cd93e..24ab51bb5a01 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -821,7 +821,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
>  
>   /* VPC */
>   gpu_write(gpu, REG_A5XX_CP_PROTECT(14), ADRENO_PROTECT_RW(0xE68, 8));
> - gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 4));
> + gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 16));
>  
>   /* UCHE */
>   gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
> -- 
> 2.29.2
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH v3 6/7] drm/msm/a5xx: Disable flat shading optimization

2021-01-14 Thread Jordan Crouse
On Wed, Jan 13, 2021 at 07:33:38PM +0100, AngeloGioacchino Del Regno wrote:
> From: Konrad Dybcio 
> 
> Port over the command from downstream to prevent undefined
> behaviour.

Reviewed-by: Jordan Crouse 

> Signed-off-by: Konrad Dybcio 
> Signed-off-by: AngeloGioacchino Del Regno 
> 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 24ab51bb5a01..23fc851756de 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -791,6 +791,9 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
>   adreno_is_a540(adreno_gpu))
>   gpu_write(gpu, REG_A5XX_UCHE_DBG_ECO_CNTL_2, regbit);
>  
> + /* Disable All flat shading optimization (ALLFLATOPTDIS) */
> + gpu_rmw(gpu, REG_A5XX_VPC_DBG_ECO_CNTL, 0, (1 << 10));
> +
>   /* Protect registers from the CP */
>   gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x0007);
>  
> -- 
> 2.29.2
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH v3 7/7] drm/msm/a5xx: Disable UCHE global filter

2021-01-14 Thread Jordan Crouse
On Wed, Jan 13, 2021 at 07:33:39PM +0100, AngeloGioacchino Del Regno wrote:
> From: Konrad Dybcio 
> 
> Port over the command from downstream to prevent undefined
> behaviour.

Reviewed-by: Jordan Crouse 

> Signed-off-by: Konrad Dybcio 
> Signed-off-by: AngeloGioacchino Del Regno 
> 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx.xml.h | 2 ++
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 3 +++
>  2 files changed, 5 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx.xml.h 
> b/drivers/gpu/drm/msm/adreno/a5xx.xml.h
> index 346cc6ff3a36..7b9fcfe95c04 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx.xml.h
> +++ b/drivers/gpu/drm/msm/adreno/a5xx.xml.h
> @@ -2367,6 +2367,8 @@ static inline uint32_t A5XX_VSC_RESOLVE_CNTL_Y(uint32_t 
> val)
>  
>  #define REG_A5XX_UCHE_ADDR_MODE_CNTL 0x0e80
>  
> +#define REG_A5XX_UCHE_MODE_CNTL  
> 0x0e81
> +
>  #define REG_A5XX_UCHE_SVM_CNTL   
> 0x0e82
>  
>  #define REG_A5XX_UCHE_WRITE_THRU_BASE_LO 0x0e87
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 23fc851756de..7e553d3efeb2 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -754,6 +754,9 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
>   adreno_is_a512(adreno_gpu))
>   gpu_rmw(gpu, REG_A5XX_RB_DBG_ECO_CNTL, 0, (1 << 9));
>  
> + /* Disable UCHE global filter as SP can invalidate/flush independently 
> */
> + gpu_write(gpu, REG_A5XX_UCHE_MODE_CNTL, BIT(29));
> +
>   /* Enable USE_RETENTION_FLOPS */
>   gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x0200);
>  
> -- 
> 2.29.2
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 1/3] drm/msm: Fix race of GPU init vs timestamp power management.

2021-01-28 Thread Jordan Crouse
On Wed, Jan 27, 2021 at 03:39:44PM -0800, Eric Anholt wrote:
> We were using the same force-poweron bit in the two codepaths, so they
> could race to have one of them lose GPU power early.
> 
> Signed-off-by: Eric Anholt 
> Cc: sta...@vger.kernel.org # v5.9

You can add:
Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support")

Because that was my ugly.

Reviewed-by: Jordan Crouse 

> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 ++---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.h |  8 
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c |  4 ++--
>  3 files changed, 32 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 78836b4fb98e..378dc7f190c3 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -264,6 +264,16 @@ int _a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum 
> a6xx_gmu_oob_state state, char
>   }
>   name = "GPU_SET";
>   break;
> + case GMU_OOB_PERFCOUNTER_SET:
> + if (gmu->legacy) {
> + request = GMU_OOB_PERFCOUNTER_REQUEST;
> + ack = GMU_OOB_PERFCOUNTER_ACK;
> + } else {
> + request = GMU_OOB_PERFCOUNTER_REQUEST_NEW;
> + ack = GMU_OOB_PERFCOUNTER_ACK_NEW;
> + }
> + name = "PERFCOUNTER";
> + break;
>   case GMU_OOB_BOOT_SLUMBER:
>   request = GMU_OOB_BOOT_SLUMBER_REQUEST;
>   ack = GMU_OOB_BOOT_SLUMBER_ACK;
> @@ -302,9 +312,14 @@ int _a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum 
> a6xx_gmu_oob_state state, char
>  void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
>  {
>   if (!gmu->legacy) {
> - WARN_ON(state != GMU_OOB_GPU_SET);
> - gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
> - 1 << GMU_OOB_GPU_SET_CLEAR_NEW);
> + if (state == GMU_OOB_GPU_SET) {
> + gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
> + 1 << GMU_OOB_GPU_SET_CLEAR_NEW);
> + } else {
> + WARN_ON(state != GMU_OOB_PERFCOUNTER_SET);
> + gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
> + 1 << GMU_OOB_PERFCOUNTER_CLEAR_NEW);
> + }
>   return;
>   }
>  
> @@ -313,6 +328,10 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum 
> a6xx_gmu_oob_state state)
>   gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
>   1 << GMU_OOB_GPU_SET_CLEAR);
>   break;
> + case GMU_OOB_PERFCOUNTER_SET:
> + gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
> + 1 << GMU_OOB_PERFCOUNTER_CLEAR);
> + break;
>   case GMU_OOB_BOOT_SLUMBER:
>   gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
>   1 << GMU_OOB_BOOT_SLUMBER_CLEAR);
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h 
> b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> index c6d2bced8e5d..9fa278de2106 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> @@ -156,6 +156,7 @@ enum a6xx_gmu_oob_state {
>   GMU_OOB_BOOT_SLUMBER = 0,
>   GMU_OOB_GPU_SET,
>   GMU_OOB_DCVS_SET,
> + GMU_OOB_PERFCOUNTER_SET,
>  };
>  
>  /* These are the interrupt / ack bits for each OOB request that are set
> @@ -190,6 +191,13 @@ enum a6xx_gmu_oob_state {
>  #define GMU_OOB_GPU_SET_ACK_NEW  31
>  #define GMU_OOB_GPU_SET_CLEAR_NEW31
>  
> +#define GMU_OOB_PERFCOUNTER_REQUEST  17
> +#define GMU_OOB_PERFCOUNTER_ACK  25
> +#define GMU_OOB_PERFCOUNTER_CLEAR25
> +
> +#define GMU_OOB_PERFCOUNTER_REQUEST_NEW  28
> +#define GMU_OOB_PERFCOUNTER_ACK_NEW  30
> +#define GMU_OOB_PERFCOUNTER_CLEAR_NEW30
>  
>  void a6xx_hfi_init(struct a6xx_gmu *gmu);
>  int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index c8a9010c1a1d..7424a70b9d35 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -1177,12 +1177,12 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, 
> uint64_t *value)
>   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
>  
>   /* Force the GPU power on so we can read this register */
> - a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
> + a6xx_gmu_set_oob(&a

Re: [Freedreno] [PATCH 2/3] drm/msm: Fix races managing the OOB state for timestamp vs timestamps.

2021-01-28 Thread Jordan Crouse
On Wed, Jan 27, 2021 at 03:39:45PM -0800, Eric Anholt wrote:
> Now that we're not racing with GPU setup, also fix races of timestamps
> against other timestamps.  In CI, we were seeing this path trigger
> timeouts on setting the GMU bit, especially on the first set of tests
> right after boot (it's probably easier to lose the race than one might
> think, given that we start many tests in parallel, and waiting for NFS
> to page in code probably means that lots of tests hit the same point
> of screen init at the same time).
> 
> Signed-off-by: Eric Anholt 
> Cc: sta...@vger.kernel.org # v5.9

The joys of not having a global mutex locking everything.

Reviewed-by: Jordan Crouse 

> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 7424a70b9d35..e8f0b5325a7f 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -1175,6 +1175,9 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, 
> uint64_t *value)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
> + static DEFINE_MUTEX(perfcounter_oob);
> +
> + mutex_lock(&perfcounter_oob);
>  
>   /* Force the GPU power on so we can read this register */
>   a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
> @@ -1183,6 +1186,7 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, 
> uint64_t *value)
>   REG_A6XX_RBBM_PERFCTR_CP_0_HI);
>  
>   a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
> + mutex_unlock(&perfcounter_oob);
>   return 0;
>  }
>  
> -- 
> 2.30.0
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 3/3] drm/msm: Clean up GMU OOB set/clear handling.

2021-01-28 Thread Jordan Crouse
On Wed, Jan 27, 2021 at 03:39:46PM -0800, Eric Anholt wrote:
> Now that the bug is fixed in the minimal way for stable, go make the
> code table-driven.
> 
> Signed-off-by: Eric Anholt 

There shouldn't be too many more OOB bits, but this is a good cleanup
regardless.

Reviewed-by: Jordan Crouse 

> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 124 +-
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.h |  55 
>  2 files changed, 77 insertions(+), 102 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 378dc7f190c3..c497e0942141 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -245,47 +245,66 @@ static int a6xx_gmu_hfi_start(struct a6xx_gmu *gmu)
>   return ret;
>  }
>  
> +struct a6xx_gmu_oob_bits {
> + int set, ack, set_new, ack_new;
> + const char *name;
> +};
> +
> +/* These are the interrupt / ack bits for each OOB request that are set
> + * in a6xx_gmu_set_oob and a6xx_clear_oob
> + */
> +static const struct a6xx_gmu_oob_bits a6xx_gmu_oob_bits[] = {
> + [GMU_OOB_GPU_SET] = {
> + .name = "GPU_SET",
> + .set = 16,
> + .ack = 24,
> + .set_new = 30,
> + .ack_new = 31,
> + },
> +
> + [GMU_OOB_PERFCOUNTER_SET] = {
> + .name = "PERFCOUNTER",
> + .set = 17,
> + .ack = 25,
> + .set_new = 28,
> + .ack_new = 30,
> + },
> +
> + [GMU_OOB_BOOT_SLUMBER] = {
> + .name = "BOOT_SLUMBER",
> + .set = 22,
> + .ack = 30,
> + },
> +
> + [GMU_OOB_DCVS_SET] = {
> + .name = "GPU_DCVS",
> + .set = 23,
> + .ack = 31,
> + },
> +};
> +
>  /* Trigger a OOB (out of band) request to the GMU */
>  int _a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state, 
> char *file, int line)
>  {
>   int ret;
>   u32 val;
>   int request, ack;
> - const char *name;
>  
> - switch (state) {
> - case GMU_OOB_GPU_SET:
> - if (gmu->legacy) {
> - request = GMU_OOB_GPU_SET_REQUEST;
> - ack = GMU_OOB_GPU_SET_ACK;
> - } else {
> - request = GMU_OOB_GPU_SET_REQUEST_NEW;
> - ack = GMU_OOB_GPU_SET_ACK_NEW;
> - }
> - name = "GPU_SET";
> - break;
> - case GMU_OOB_PERFCOUNTER_SET:
> - if (gmu->legacy) {
> - request = GMU_OOB_PERFCOUNTER_REQUEST;
> - ack = GMU_OOB_PERFCOUNTER_ACK;
> - } else {
> - request = GMU_OOB_PERFCOUNTER_REQUEST_NEW;
> - ack = GMU_OOB_PERFCOUNTER_ACK_NEW;
> - }
> - name = "PERFCOUNTER";
> - break;
> - case GMU_OOB_BOOT_SLUMBER:
> - request = GMU_OOB_BOOT_SLUMBER_REQUEST;
> - ack = GMU_OOB_BOOT_SLUMBER_ACK;
> - name = "BOOT_SLUMBER";
> - break;
> - case GMU_OOB_DCVS_SET:
> - request = GMU_OOB_DCVS_REQUEST;
> - ack = GMU_OOB_DCVS_ACK;
> - name = "GPU_DCVS";
> - break;
> - default:
> + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
>   return -EINVAL;
> +
> + if (gmu->legacy) {
> + request = a6xx_gmu_oob_bits[state].set;
> + ack = a6xx_gmu_oob_bits[state].ack;
> + } else {
> + request = a6xx_gmu_oob_bits[state].set_new;
> + ack = a6xx_gmu_oob_bits[state].ack_new;
> + if (!request || !ack) {
> + DRM_DEV_ERROR(gmu->dev,
> +   "Invalid non-legacy GMU request %s\n",
> +   a6xx_gmu_oob_bits[state].name);
> + return -EINVAL;
> + }
>   }
>  
>   /* Trigger the equested OOB operation */
> @@ -299,7 +318,7 @@ int _a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum 
> a6xx_gmu_oob_state state, char
>   DRM_DEV_ERROR(gmu->dev,
>   "%s:%d Timeout waiting for GMU OOB set %s: 0x%x\n",
>   file, line,
> - name,
> + a6xx_gmu_oob_bits[state].name,
>   gmu_read(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO));
>  
>   /* Clear the

Re: [Freedreno] [PATCH 1/3] drm/msm: Fix race of GPU init vs timestamp power management.

2021-01-29 Thread Jordan Crouse
On Thu, Jan 28, 2021 at 11:17:16AM -0800, Eric Anholt wrote:
> On Thu, Jan 28, 2021 at 10:52 AM Jordan Crouse  wrote:
> >
> > On Wed, Jan 27, 2021 at 03:39:44PM -0800, Eric Anholt wrote:
> > > We were using the same force-poweron bit in the two codepaths, so they
> > > could race to have one of them lose GPU power early.
> > >
> > > Signed-off-by: Eric Anholt 
> > > Cc: sta...@vger.kernel.org # v5.9
> >
> > You can add:
> > Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support")
> >
> > Because that was my ugly.
> >
> > Reviewed-by: Jordan Crouse 
> 
> I only pointed it at 5.9 because it looked like it would probably
> conflict against older branches.  I can add the fixes tag if you'd
> like, though.

Fair enough. It is a good bug to fix but not if there are a lot of conflicts to
deal with.

Jordan
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 2/3] iommu/io-pgtable-arm: Add IOMMU_LLC page protection flag

2021-02-01 Thread Jordan Crouse
On Mon, Feb 01, 2021 at 08:20:44AM -0800, Rob Clark wrote:
> On Mon, Feb 1, 2021 at 3:16 AM Will Deacon  wrote:
> >
> > On Fri, Jan 29, 2021 at 03:12:59PM +0530, Sai Prakash Ranjan wrote:
> > > On 2021-01-29 14:35, Will Deacon wrote:
> > > > On Mon, Jan 11, 2021 at 07:45:04PM +0530, Sai Prakash Ranjan wrote:
> > > > > Add a new page protection flag IOMMU_LLC which can be used
> > > > > by non-coherent masters to set cacheable memory attributes
> > > > > for an outer level of cache called as last-level cache or
> > > > > system cache. Initial user of this page protection flag is
> > > > > the adreno gpu and then can later be used by other clients
> > > > > such as video where this can be used for per-buffer based
> > > > > mapping.
> > > > >
> > > > > Signed-off-by: Sai Prakash Ranjan 
> > > > > ---
> > > > >  drivers/iommu/io-pgtable-arm.c | 3 +++
> > > > >  include/linux/iommu.h  | 6 ++
> > > > >  2 files changed, 9 insertions(+)
> > > > >
> > > > > diff --git a/drivers/iommu/io-pgtable-arm.c
> > > > > b/drivers/iommu/io-pgtable-arm.c
> > > > > index 7439ee7fdcdb..ebe653ef601b 100644
> > > > > --- a/drivers/iommu/io-pgtable-arm.c
> > > > > +++ b/drivers/iommu/io-pgtable-arm.c
> > > > > @@ -415,6 +415,9 @@ static arm_lpae_iopte
> > > > > arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
> > > > >   else if (prot & IOMMU_CACHE)
> > > > >   pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE
> > > > >   << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> > > > > + else if (prot & IOMMU_LLC)
> > > > > + pte |= (ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE
> > > > > + << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> > > > >   }
> > > > >
> > > > >   if (prot & IOMMU_CACHE)
> > > > > diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> > > > > index ffaa389ea128..1f82057df531 100644
> > > > > --- a/include/linux/iommu.h
> > > > > +++ b/include/linux/iommu.h
> > > > > @@ -31,6 +31,12 @@
> > > > >   * if the IOMMU page table format is equivalent.
> > > > >   */
> > > > >  #define IOMMU_PRIV   (1 << 5)
> > > > > +/*
> > > > > + * Non-coherent masters can use this page protection flag to set
> > > > > cacheable
> > > > > + * memory attributes for only a transparent outer level of cache,
> > > > > also known as
> > > > > + * the last-level or system cache.
> > > > > + */
> > > > > +#define IOMMU_LLC(1 << 6)
> > > >
> > > > On reflection, I'm a bit worried about exposing this because I think it
> > > > will
> > > > introduce a mismatched virtual alias with the CPU (we don't even have a
> > > > MAIR
> > > > set up for this memory type). Now, we also have that issue for the PTW,
> > > > but
> > > > since we always use cache maintenance (i.e. the streaming API) for
> > > > publishing the page-tables to a non-coheren walker, it works out.
> > > > However,
> > > > if somebody expects IOMMU_LLC to be coherent with a DMA API coherent
> > > > allocation, then they're potentially in for a nasty surprise due to the
> > > > mismatched outer-cacheability attributes.
> > > >
> > >
> > > Can't we add the syscached memory type similar to what is done on android?
> >
> > Maybe. How does the GPU driver map these things on the CPU side?
> 
> Currently we use writecombine mappings for everything, although there
> are some cases that we'd like to use cached (but have not merged
> patches that would give userspace a way to flush/invalidate)
> 
> BR,
> -R

LLC/system cache doesn't have a relationship with the CPU cache.  Its just a
little accelerator that sits on the connection from the GPU to DDR and caches
accesses. The hint that Sai is suggesting is used to mark the buffers as
'no-write-allocate' to prevent GPU write operations from being cached in the LLC
which a) isn't interesting and b) takes up cache space for read operations.

Its easiest to think of the LLC as a bonus accelerator that has no cost for
us to use outside of the unfortunate per buffer hint.

We do have to worry about the CPU cache w.r.t I/O coherency (which is a
different hint) and in that case we have all of concerns that Will identified.

Jordan
-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH] drm/msm: a6xx: Make sure the SQE microcode is safe

2021-02-09 Thread Jordan Crouse
Most a6xx targets have security issues that were fixed with new versions
of the microcode(s). Make sure that we are booting with a safe version of
the microcode for the target and print a message and error if not.

Signed-off-by: Jordan Crouse 
---

 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 67 +--
 1 file changed, 54 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index ba8e9d3cf0fe..cfb0d5f63784 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -522,28 +522,61 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
 }
 
-static void a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
+/*
+ * Check that the microcode version is new enough to include several key
+ * security fixes. Return true if the ucode is safe.
+ */
+static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
struct drm_gem_object *obj)
 {
+   struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
u32 *buf = msm_gem_get_vaddr(obj);
+   bool ret = false;
 
if (IS_ERR(buf))
-   return;
+   return false;
 
/*
-* If the lowest nibble is 0xa that is an indication that this microcode
-* has been patched. The actual version is in dword [3] but we only care
-* about the patchlevel which is the lowest nibble of dword [3]
-*
-* Otherwise check that the firmware is greater than or equal to 1.90
-* which was the first version that had this fix built in
+* Targets up to a640 (a618, a630 and a640) need to check for a
+* microcode version that is patched to support the whereami opcode or
+* one that is new enough to include it by default.
 */
-   if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1)
-   a6xx_gpu->has_whereami = true;
-   else if ((buf[0] & 0xfff) > 0x190)
-   a6xx_gpu->has_whereami = true;
+   if (adreno_is_a618(adreno_gpu) || adreno_is_a630(adreno_gpu) ||
+   adreno_is_a640(adreno_gpu)) {
+   /*
+* If the lowest nibble is 0xa that is an indication that this
+* microcode has been patched. The actual version is in dword
+* [3] but we only care about the patchlevel which is the lowest
+* nibble of dword [3]
+*
+* Otherwise check that the firmware is greater than or equal
+* to 1.90 which was the first version that had this fix built
+* in
+*/
+   if buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) ||
+   (buf[0] & 0xfff) > 0x190) {
+   a6xx_gpu->has_whereami = true;
+   ret = true;
+   }
+   }  else {
+   /*
+* a650 tier targets don't need whereami but still need to be
+* equal to or newer than 1.95 for other security fixes
+*/
+   if (adreno_is_a640(adreno_gpu)) {
+   if ((buf[0] & 0xfff) >= 0x195)
+   ret = true;
+   }
+
+   /*
+* When a660 is added those targets should return true here
+* since those have all the critiical security fixes built in
+* from the start
+*/
+   }
 
msm_gem_put_vaddr(obj);
+   return ret;
 }
 
 static int a6xx_ucode_init(struct msm_gpu *gpu)
@@ -566,7 +599,15 @@ static int a6xx_ucode_init(struct msm_gpu *gpu)
}
 
msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw");
-   a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo);
+   if (!a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo)) {
+   DRM_DEV_ERROR(&gpu->pdev->dev,
+   "SQE ucode version is too old. It is likely 
unsafe\n");
+   msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->aspace);
+   drm_gem_object_put(a6xx_gpu->sqe_bo);
+
+   a6xx_gpu->sqe_bo = NULL;
+   return -EPERM;
+   }
}
 
gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE_LO,
-- 
2.25.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH v2] drm/msm: a6xx: Make sure the SQE microcode is safe

2021-02-09 Thread Jordan Crouse
Most a6xx targets have security issues that were fixed with new versions
of the microcode(s). Make sure that we are booting with a safe version of
the microcode for the target and print a message and error if not.

v2: Add more informative error messages and fix typos

Signed-off-by: Jordan Crouse 
---

 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 77 ++-
 1 file changed, 64 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index ba8e9d3cf0fe..064b7face504 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -522,28 +522,73 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
 }
 
-static void a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
+/*
+ * Check that the microcode version is new enough to include several key
+ * security fixes. Return true if the ucode is safe.
+ */
+static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
struct drm_gem_object *obj)
 {
+   struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+   struct msm_gpu *gpu = &adreno_gpu->base;
u32 *buf = msm_gem_get_vaddr(obj);
+   bool ret = false;
 
if (IS_ERR(buf))
-   return;
+   return false;
 
/*
-* If the lowest nibble is 0xa that is an indication that this microcode
-* has been patched. The actual version is in dword [3] but we only care
-* about the patchlevel which is the lowest nibble of dword [3]
-*
-* Otherwise check that the firmware is greater than or equal to 1.90
-* which was the first version that had this fix built in
+* Targets up to a640 (a618, a630 and a640) need to check for a
+* microcode version that is patched to support the whereami opcode or
+* one that is new enough to include it by default.
 */
-   if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1)
-   a6xx_gpu->has_whereami = true;
-   else if ((buf[0] & 0xfff) > 0x190)
-   a6xx_gpu->has_whereami = true;
+   if (adreno_is_a618(adreno_gpu) || adreno_is_a630(adreno_gpu) ||
+   adreno_is_a640(adreno_gpu)) {
+   /*
+* If the lowest nibble is 0xa that is an indication that this
+* microcode has been patched. The actual version is in dword
+* [3] but we only care about the patchlevel which is the lowest
+* nibble of dword [3]
+*
+* Otherwise check that the firmware is greater than or equal
+* to 1.90 which was the first version that had this fix built
+* in
+*/
+   if buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) ||
+   (buf[0] & 0xfff) >= 0x190) {
+   a6xx_gpu->has_whereami = true;
+   ret = true;
+   goto out;
+   }
 
+   DRM_DEV_ERROR(&gpu->pdev->dev,
+   "a630 SQE ucode is too old. Have version %x need at 
least %x\n",
+   buf[0] & 0xfff, 0x190);
+   }  else {
+   /*
+* a650 tier targets don't need whereami but still need to be
+* equal to or newer than 1.95 for other security fixes
+*/
+   if (adreno_is_a650(adreno_gpu)) {
+   if ((buf[0] & 0xfff) >= 0x195) {
+   ret = true;
+   goto out;
+   }
+
+   DRM_DEV_ERROR(&gpu->pdev->dev,
+   "a650 SQE ucode is too old. Have version %x 
need at least %x\n",
+   buf[0] & 0xfff, 0x195);
+   }
+
+   /*
+* When a660 is added those targets should return true here
+* since those have all the critical security fixes built in
+* from the start
+*/
+   }
+out:
msm_gem_put_vaddr(obj);
+   return ret;
 }
 
 static int a6xx_ucode_init(struct msm_gpu *gpu)
@@ -566,7 +611,13 @@ static int a6xx_ucode_init(struct msm_gpu *gpu)
}
 
msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw");
-   a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo);
+   if (!a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo)) {
+   msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->aspace);
+   drm_gem_object_put(a6xx_gpu->sqe_bo);
+
+   a6xx_gpu->sqe_bo = NULL;
+   return -EPERM;
+   }
}
 
gp

Re: [Freedreno] [PATCH] drm/msm: fix a6xx_gmu_clear_oob

2021-02-09 Thread Jordan Crouse
On Mon, Feb 08, 2021 at 01:55:54PM -0500, Jonathan Marek wrote:
> The cleanup patch broke a6xx_gmu_clear_oob, fix it by adding the missing
> bitshift operation.
> 
> Fixes: 555c50a4a19b ("drm/msm: Clean up GMU OOB set/clear handling")
> Signed-off-by: Jonathan Marek 

Thanks.  I feel silly that I missed that.

Reviewed-by: Jordan Crouse 

> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 71c917f909af..91cf46f84025 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -339,7 +339,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum 
> a6xx_gmu_oob_state state)
>   else
>   bit = a6xx_gmu_oob_bits[state].ack_new;
>  
> - gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, bit);
> + gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, 1 << bit);
>  }
>  
>  /* Enable CPU control of SPTP power power collapse */
> -- 
> 2.26.1
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH v2] drm/msm: a6xx: Make sure the SQE microcode is safe

2021-02-11 Thread Jordan Crouse
On Thu, Feb 11, 2021 at 06:50:28PM +0530, Akhil P Oommen wrote:
> On 2/10/2021 6:22 AM, Jordan Crouse wrote:
> >Most a6xx targets have security issues that were fixed with new versions
> >of the microcode(s). Make sure that we are booting with a safe version of
> >the microcode for the target and print a message and error if not.
> >
> >v2: Add more informative error messages and fix typos
> >
> >Signed-off-by: Jordan Crouse 
> >---
> >
> >  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 77 ++-
> >  1 file changed, 64 insertions(+), 13 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> >b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >index ba8e9d3cf0fe..064b7face504 100644
> >--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >@@ -522,28 +522,73 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
> > return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
> >  }
> >-static void a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
> >+/*
> >+ * Check that the microcode version is new enough to include several key
> >+ * security fixes. Return true if the ucode is safe.
> >+ */
> >+static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
> > struct drm_gem_object *obj)
> >  {
> >+struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
> >+struct msm_gpu *gpu = &adreno_gpu->base;
> > u32 *buf = msm_gem_get_vaddr(obj);
> >+bool ret = false;
> > if (IS_ERR(buf))
> >-return;
> >+return false;
> > /*
> >- * If the lowest nibble is 0xa that is an indication that this microcode
> >- * has been patched. The actual version is in dword [3] but we only care
> >- * about the patchlevel which is the lowest nibble of dword [3]
> >- *
> >- * Otherwise check that the firmware is greater than or equal to 1.90
> >- * which was the first version that had this fix built in
> >+ * Targets up to a640 (a618, a630 and a640) need to check for a
> >+ * microcode version that is patched to support the whereami opcode or
> >+ * one that is new enough to include it by default.
> >  */
> >-if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1)
> >-a6xx_gpu->has_whereami = true;
> >-else if ((buf[0] & 0xfff) > 0x190)
> >-a6xx_gpu->has_whereami = true;
> >+if (adreno_is_a618(adreno_gpu) || adreno_is_a630(adreno_gpu) ||
> >+adreno_is_a640(adreno_gpu)) {
> >+/*
> >+ * If the lowest nibble is 0xa that is an indication that this
> >+ * microcode has been patched. The actual version is in dword
> >+ * [3] but we only care about the patchlevel which is the lowest
> >+ * nibble of dword [3]
> >+ *
> >+ * Otherwise check that the firmware is greater than or equal
> >+ * to 1.90 which was the first version that had this fix built
> >+ * in
> >+ */
> >+if buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) ||
> >+(buf[0] & 0xfff) >= 0x190) {
> >+a6xx_gpu->has_whereami = true;
> >+ret = true;
> >+goto out;
> >+}
> >+DRM_DEV_ERROR(&gpu->pdev->dev,
> >+"a630 SQE ucode is too old. Have version %x need at 
> >least %x\n",
> >+buf[0] & 0xfff, 0x190);
> >+}  else {
> >+/*
> >+ * a650 tier targets don't need whereami but still need to be
> >+ * equal to or newer than 1.95 for other security fixes
> >+ */
> >+if (adreno_is_a650(adreno_gpu)) {
> >+if ((buf[0] & 0xfff) >= 0x195) {
> >+ret = true;
> >+goto out;
> >+}
> >+
> >+DRM_DEV_ERROR(&gpu->pdev->dev,
> >+"a650 SQE ucode is too old. Have version %x 
> >need at least %x\n",
> >+buf[0] & 0xfff, 0x195);
> >+}
> >+
> >+/*
> >+ * When a660 is added those targets should return true here
> >+ * since those have all the critical security fixes built in
> >+ * from th

Re: [Freedreno] [PATCH] drm/msm/a6xx: fix for kernels without CONFIG_NVMEM

2021-02-17 Thread Jordan Crouse
On Wed, Feb 17, 2021 at 07:14:16PM +0530, Akhil P Oommen wrote:
> On 2/17/2021 8:36 AM, Rob Clark wrote:
> >On Tue, Feb 16, 2021 at 12:10 PM Jonathan Marek  wrote:
> >>
> >>Ignore nvmem_cell_get() EOPNOTSUPP error in the same way as a ENOENT error,
> >>to fix the case where the kernel was compiled without CONFIG_NVMEM.
> >>
> >>Fixes: fe7952c629da ("drm/msm: Add speed-bin support to a618 gpu")
> >>Signed-off-by: Jonathan Marek 
> >>---
> >>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 6 +++---
> >>  1 file changed, 3 insertions(+), 3 deletions(-)
> >>
> >>diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> >>b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >>index ba8e9d3cf0fe..7fe5d97606aa 100644
> >>--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >>+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >>@@ -1356,10 +1356,10 @@ static int a6xx_set_supported_hw(struct device 
> >>*dev, struct a6xx_gpu *a6xx_gpu,
> >>
> >> cell = nvmem_cell_get(dev, "speed_bin");
> >> /*
> >>-* -ENOENT means that the platform doesn't support speedbin which is
> >>-* fine
> >>+* -ENOENT means no speed bin in device tree,
> >>+* -EOPNOTSUPP means kernel was built without CONFIG_NVMEM
> >
> >very minor nit, it would be nice to at least preserve the gist of the
> >"which is fine" (ie. some variation of "this is an optional thing and
> >things won't catch fire without it" ;-))
> >
> >(which is, I believe, is true, hopefully Akhil could confirm.. if not
> >we should have a harder dependency on CONFIG_NVMEM..)
> IIRC, if the gpu opp table in the DT uses the 'opp-supported-hw' property,
> we will see some error during boot up if we don't call
> dev_pm_opp_set_supported_hw(). So calling "nvmem_cell_get(dev, "speed_bin")"
> is a way to test this.
> 
> If there is no other harm, we can put a hard dependency on CONFIG_NVMEM.

I'm not sure if we want to go this far given the squishiness about module
dependencies. As far as I know we are the only driver that uses this seriously
on QCOM SoCs and this is only needed for certain targets. I don't know if we
want to force every target to build NVMEM and QFPROM on our behalf. But maybe
I'm just saying that because Kconfig dependencies tend to break my brain (and
then Arnd has to send a patch to fix it).

Jordan

> -Akhil.
> >
> >BR,
> >-R
> >
> >>  */
> >>-   if (PTR_ERR(cell) == -ENOENT)
> >>+   if (PTR_ERR(cell) == -ENOENT || PTR_ERR(cell) == -EOPNOTSUPP)
> >> return 0;
> >> else if (IS_ERR(cell)) {
> >> DRM_DEV_ERROR(dev,
> >>--
> >>2.26.1
> >>
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH v3 0/3] iommu/arm-smmu: adreno-smmu page fault handling

2021-02-25 Thread Jordan Crouse
(resending for the 5.13 cycle)

This is a stack to add an Adreno GPU specific handler for pagefaults. The first
patch starts by wiring up report_iommu_fault for arm-smmu. The next patch adds
a adreno-smmu-priv function hook to capture a handful of important debugging
registers such as TTBR0, CONTEXTIDR, FSYNR0 and others. This is used by the
third patch to print more detailed information on page fault such as the TTBR0
for the pagetable that caused the fault and the source of the fault as
determined by a combination of the FSYNR1 register and an internal GPU
register.

This code provides a solid base that we can expand on later for even more
extensive GPU side page fault debugging capabilities.

v3: Always clear FSR even if the target driver is going to handle resume
v2: Fix comment wording and function pointer check per Rob Clark

Jordan Crouse (3):
  iommu/arm-smmu: Add support for driver IOMMU fault handlers
  drm/msm: Add an adreno-smmu-priv callback to get pagefault info
  drm/msm: Improve the a6xx page fault handler

 drivers/gpu/drm/msm/adreno/a5xx_gpu.c  |  4 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  | 76 +-
 drivers/gpu/drm/msm/msm_iommu.c| 11 +++-
 drivers/gpu/drm/msm/msm_mmu.h  |  4 +-
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.c  |  9 ++-
 drivers/iommu/arm/arm-smmu/arm-smmu.h  |  2 +
 include/linux/adreno-smmu-priv.h   | 31 -
 8 files changed, 145 insertions(+), 11 deletions(-)

-- 
2.25.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH v3 3/3] drm/msm: Improve the a6xx page fault handler

2021-02-25 Thread Jordan Crouse
Use the new adreno-smmu-priv fault info function to get more SMMU
debug registers and print the current TTBR0 to debug per-instance
pagetables and figure out which GPU block generated the request.

Signed-off-by: Jordan Crouse 
---

 drivers/gpu/drm/msm/adreno/a5xx_gpu.c |  4 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 76 +--
 drivers/gpu/drm/msm/msm_iommu.c   | 11 +++-
 drivers/gpu/drm/msm/msm_mmu.h |  4 +-
 4 files changed, 87 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 7e553d3efeb2..56b548921c4e 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1075,7 +1075,7 @@ bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer 
*ring)
return true;
 }
 
-static int a5xx_fault_handler(void *arg, unsigned long iova, int flags)
+static int a5xx_fault_handler(void *arg, unsigned long iova, int flags, void 
*data)
 {
struct msm_gpu *gpu = arg;
pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d 
(%u,%u,%u,%u)\n",
@@ -1085,7 +1085,7 @@ static int a5xx_fault_handler(void *arg, unsigned long 
iova, int flags)
gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(6)),
gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(7)));
 
-   return -EFAULT;
+   return 0;
 }
 
 static void a5xx_cp_err_irq(struct msm_gpu *gpu)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 064b7face504..97eabd87740c 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -959,18 +959,88 @@ static void a6xx_recover(struct msm_gpu *gpu)
msm_gpu_hw_init(gpu);
 }
 
-static int a6xx_fault_handler(void *arg, unsigned long iova, int flags)
+static const char *a6xx_uche_fault_block(struct msm_gpu *gpu, u32 mid)
+{
+   static const char *uche_clients[7] = {
+   "VFD", "SP", "VSC", "VPC", "HLSQ", "PC", "LRZ",
+   };
+   u32 val;
+
+   if (mid < 1 || mid > 3)
+   return "UNKNOWN";
+
+   /*
+* The source of the data depends on the mid ID read from FSYNR1.
+* and the client ID read from the UCHE block
+*/
+   val = gpu_read(gpu, REG_A6XX_UCHE_CLIENT_PF);
+
+   /* mid = 3 is most precise and refers to only one block per client */
+   if (mid == 3)
+   return uche_clients[val & 7];
+
+   /* For mid=2 the source is TP or VFD except when the client id is 0 */
+   if (mid == 2)
+   return ((val & 7) == 0) ? "TP" : "TP|VFD";
+
+   /* For mid=1 just return "UCHE" as a catchall for everything else */
+   return "UCHE";
+}
+
+static const char *a6xx_fault_block(struct msm_gpu *gpu, u32 id)
+{
+   if (id == 0)
+   return "CP";
+   else if (id == 4)
+   return "CCU";
+   else if (id == 6)
+   return "CDP Prefetch";
+
+   return a6xx_uche_fault_block(gpu, id);
+}
+
+#define ARM_SMMU_FSR_TF BIT(1)
+#define ARM_SMMU_FSR_PFBIT(3)
+#define ARM_SMMU_FSR_EFBIT(4)
+
+static int a6xx_fault_handler(void *arg, unsigned long iova, int flags, void 
*data)
 {
struct msm_gpu *gpu = arg;
+   struct adreno_smmu_fault_info *info = data;
+   const char *type = "UNKNOWN";
 
-   pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d 
(%u,%u,%u,%u)\n",
+   /*
+* Print a default message if we couldn't get the data from the
+* adreno-smmu-priv
+*/
+   if (!info) {
+   pr_warn_ratelimited("*** gpu fault: iova=%.16lx flags=%d 
(%u,%u,%u,%u)\n",
iova, flags,
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(4)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(5)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(6)),
gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(7)));
 
-   return -EFAULT;
+   return 0;
+   }
+
+   if (info->fsr & ARM_SMMU_FSR_TF)
+   type = "TRANSLATION";
+   else if (info->fsr & ARM_SMMU_FSR_PF)
+   type = "PERMISSION";
+   else if (info->fsr & ARM_SMMU_FSR_EF)
+   type = "EXTERNAL";
+
+   pr_warn_ratelimited("*** gpu fault: ttbr0=%.16llx iova=%.16lx dir=%s 
type=%s source=%s (%u,%u,%u,%u)\n",
+   info->ttbr0, iova,
+   flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ", type,
+   a6xx_fault_block(gpu, info->fsynr1 & 0xff),
+   gpu_read(gpu, REG

[Freedreno] [PATCH] mailmap: Update email address for Jordan Crouse

2021-03-25 Thread Jordan Crouse
jcrouse at codeaurora.org ha started bouncing. Redirect to a
more permanent address.

Signed-off-by: Jordan Crouse 
---

 .mailmap | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.mailmap b/.mailmap
index 85b93cdefc87..8c489cb1d1ce 100644
--- a/.mailmap
+++ b/.mailmap
@@ -165,6 +165,7 @@ Johan Hovold  
 Johan Hovold  
 John Paul Adrian Glaubitz 
 John Stultz 
+Jordan Crouse  
  
  
  
-- 
2.25.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH] drm/msm: a6xx: fix version check for the A650 SQE microcode

2021-04-01 Thread Jordan Crouse
On Wed, Mar 31, 2021 at 05:02:23PM +0300, Dmitry Baryshkov wrote:
> I suppose the microcode version check for a650 is incorrect. It checks
> for the version 1.95, while the firmware released have major version of 0:
> 0.91 (vulnerable), 0.99 (fixing the issue).
> 
> Lower version requirements to accept firmware 0.99.

Ugh, my ugly.  .95 is the actual version that fixed it but since .99 is what is
going into the l-f repo it is fine to use that as a baseline.

Acked-by: Jordan Crouse 


> Fixes: 8490f02a3ca4 ("drm/msm: a6xx: Make sure the SQE microcode is safe")
> Cc: Akhil P Oommen 
> Cc: Jordan Crouse 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index cb2df8736ca8..896b47dc9c85 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -567,17 +567,17 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu 
> *a6xx_gpu,
>   }  else {
>   /*
>* a650 tier targets don't need whereami but still need to be
> -  * equal to or newer than 1.95 for other security fixes
> +  * equal to or newer than 0.95 for other security fixes
>*/
>   if (adreno_is_a650(adreno_gpu)) {
> - if ((buf[0] & 0xfff) >= 0x195) {
> + if ((buf[0] & 0xfff) >= 0x095) {
>   ret = true;
>   goto out;
>   }
>  
>   DRM_DEV_ERROR(&gpu->pdev->dev,
>   "a650 SQE ucode is too old. Have version %x 
> need at least %x\n",
> - buf[0] & 0xfff, 0x195);
> + buf[0] & 0xfff, 0x095);
>   }
>  
>   /*
> -- 
> 2.30.2
> 
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 1/2] drm/msm: Fix a5xx/a6xx timestamps

2021-04-02 Thread Jordan Crouse
On Wed, Mar 24, 2021 at 06:23:52PM -0700, Rob Clark wrote:
> From: Rob Clark 
> 
> They were reading a counter that was configured to ALWAYS_COUNT (ie.
> cycles that the GPU is doing something) rather than ALWAYS_ON.  This
> isn't the thing that userspace is looking for.

Acked-by: Jordan Crouse 

> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 4 ++--
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 ++--
>  2 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index a5af223eaf50..bb82fcd9df81 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -1241,8 +1241,8 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu)
>  
>  static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
>  {
> - *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
> - REG_A5XX_RBBM_PERFCTR_CP_0_HI);
> + *value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO,
> + REG_A5XX_RBBM_ALWAYSON_COUNTER_HI);
>  
>   return 0;
>  }
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 130661898546..59718c304488 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -1173,8 +1173,8 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, 
> uint64_t *value)
>   /* Force the GPU power on so we can read this register */
>   a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
>  
> - *value = gpu_read64(gpu, REG_A6XX_RBBM_PERFCTR_CP_0_LO,
> - REG_A6XX_RBBM_PERFCTR_CP_0_HI);
> + *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO,
> + REG_A6XX_CP_ALWAYS_ON_COUNTER_HI);
>  
>   a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
>   return 0;
> -- 
> 2.29.2
> 
> ___
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 2/2] drm/msm: Add param for userspace to query suspend count

2021-04-02 Thread Jordan Crouse
On Wed, Mar 24, 2021 at 06:23:53PM -0700, Rob Clark wrote:
> From: Rob Clark 
> 
> Performance counts, and ALWAYS_ON counters used for capturing GPU
> timestamps, lose their state across suspend/resume cycles.  Userspace
> tooling for performance monitoring needs to be aware of this.  For
> example, after a suspend userspace needs to recalibrate it's offset
> between CPU and GPU time.
> 

Acked-by: Jordan Crouse 

> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 3 +++
>  drivers/gpu/drm/msm/msm_drv.c   | 1 +
>  drivers/gpu/drm/msm/msm_gpu.c   | 2 ++
>  drivers/gpu/drm/msm/msm_gpu.h   | 2 ++
>  include/uapi/drm/msm_drm.h  | 1 +
>  5 files changed, 9 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index f09175698827..e473b7c9ff7f 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -280,6 +280,9 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, 
> uint64_t *value)
>   case MSM_PARAM_FAULTS:
>   *value = gpu->global_faults;
>   return 0;
> + case MSM_PARAM_SUSPENDS:
> + *value = gpu->suspend_count;
> + return 0;
>   default:
>   DBG("%s: invalid param: %u", gpu->name, param);
>   return -EINVAL;
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index b29e439eb299..4f9fa0189a07 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -39,6 +39,7 @@
>   *   GEM object's debug name
>   * - 1.5.0 - Add SUBMITQUERY_QUERY ioctl
>   * - 1.6.0 - Syncobj support
> + * - 1.7.0 - Add MSM_PARAM_SUSPENDS to access suspend count
>   */
>  #define MSM_VERSION_MAJOR1
>  #define MSM_VERSION_MINOR6
> diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
> index 7bdb01f202f4..ab888d83b887 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.c
> +++ b/drivers/gpu/drm/msm/msm_gpu.c
> @@ -256,6 +256,8 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
>   if (ret)
>   return ret;
>  
> + gpu->suspend_count++;
> +
>   return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> index d7cd02cd2109..18baf935e143 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.h
> +++ b/drivers/gpu/drm/msm/msm_gpu.h
> @@ -152,6 +152,8 @@ struct msm_gpu {
>   ktime_t time;
>   } devfreq;
>  
> + uint32_t suspend_count;
> +
>   struct msm_gpu_state *crashstate;
>   /* True if the hardware supports expanded apriv (a650 and newer) */
>   bool hw_apriv;
> diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
> index a6c1f3eb2623..5596d7c37f9e 100644
> --- a/include/uapi/drm/msm_drm.h
> +++ b/include/uapi/drm/msm_drm.h
> @@ -76,6 +76,7 @@ struct drm_msm_timespec {
>  #define MSM_PARAM_NR_RINGS   0x07
>  #define MSM_PARAM_PP_PGTABLE 0x08  /* => 1 for per-process pagetables, else 
> 0 */
>  #define MSM_PARAM_FAULTS 0x09
> +#define MSM_PARAM_SUSPENDS   0x0a
>  
>  struct drm_msm_param {
>   __u32 pipe;   /* in, MSM_PIPE_x */
> -- 
> 2.29.2
> 
> ___
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 2/2] drm/msm: Periodically update RPTR shadow

2021-05-02 Thread Jordan Crouse
On Wed, Apr 28, 2021 at 12:36:49PM -0700, Rob Clark wrote:
> From: Rob Clark 
> 
> On a5xx and a6xx devices that are using CP_WHERE_AM_I to update a
> ringbuffer read-ptr shadow value, periodically emit a CP_WHERE_AM_I
> every 32 commands, so that a later submit waiting for ringbuffer
> space to become available sees partial progress, rather than not
> seeing rptr advance at all until the GPU gets to the end of the
> submit that it is currently chewing on.

Acked-by: Jordan Crouse 

> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 29 ++-
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 27 +++--
>  2 files changed, 45 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 0c8faad3b328..5202f1498a48 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -18,6 +18,18 @@ static void a5xx_dump(struct msm_gpu *gpu);
>  
>  #define GPU_PAS_ID 13
>  
> +static void update_shadow_rptr(struct msm_gpu *gpu, struct msm_ringbuffer 
> *ring)
> +{
> + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
> +
> + if (a5xx_gpu->has_whereami) {
> + OUT_PKT7(ring, CP_WHERE_AM_I, 2);
> + OUT_RING(ring, lower_32_bits(shadowptr(a5xx_gpu, ring)));
> + OUT_RING(ring, upper_32_bits(shadowptr(a5xx_gpu, ring)));
> + }
> +}
> +
>  void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
>   bool sync)
>  {
> @@ -30,11 +42,8 @@ void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer 
> *ring,
>* Most flush operations need to issue a WHERE_AM_I opcode to sync up
>* the rptr shadow
>*/
> - if (a5xx_gpu->has_whereami && sync) {
> - OUT_PKT7(ring, CP_WHERE_AM_I, 2);
> - OUT_RING(ring, lower_32_bits(shadowptr(a5xx_gpu, ring)));
> - OUT_RING(ring, upper_32_bits(shadowptr(a5xx_gpu, ring)));
> - }
> + if (sync)
> + update_shadow_rptr(gpu, ring);
>  
>   if (unlikely(ring->overflow))
>   return;
> @@ -171,6 +180,16 @@ static void a5xx_submit(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit)
>   ibs++;
>   break;
>   }
> +
> + /*
> +  * Periodically update shadow-wptr if needed, so that we
> +  * can see partial progress of submits with large # of
> +  * cmds.. otherwise we could needlessly stall waiting for
> +  * ringbuffer state, simply due to looking at a shadow
> +  * rptr value that has not been updated
> +  */
> + if ((ibs % 32) == 0)
> + update_shadow_rptr(gpu, ring);
>   }
>  
>   /*
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 4a4728a774c0..2986e36ffd8d 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -52,21 +52,25 @@ static bool a6xx_idle(struct msm_gpu *gpu, struct 
> msm_ringbuffer *ring)
>   return true;
>  }
>  
> -static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
> +static void update_shadow_rptr(struct msm_gpu *gpu, struct msm_ringbuffer 
> *ring)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
> - uint32_t wptr;
> - unsigned long flags;
>  
>   /* Expanded APRIV doesn't need to issue the WHERE_AM_I opcode */
>   if (a6xx_gpu->has_whereami && !adreno_gpu->base.hw_apriv) {
> - struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
> -
>   OUT_PKT7(ring, CP_WHERE_AM_I, 2);
>   OUT_RING(ring, lower_32_bits(shadowptr(a6xx_gpu, ring)));
>   OUT_RING(ring, upper_32_bits(shadowptr(a6xx_gpu, ring)));
>   }
> +}
> +
> +static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
> +{
> + uint32_t wptr;
> + unsigned long flags;
> +
> + update_shadow_rptr(gpu, ring);
>  
>   if (unlikely(ring->overflow))
>   return;
> @@ -148,7 +152,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit)
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
>   struct msm_ringbuffer *ring = submit->ring;
> - unsigned int i;
> + unsigned int i, 

Re: [Freedreno] [PATCH 1/5] drm/msm: remove unnecessary mmap logic for cached BOs

2021-05-02 Thread Jordan Crouse
On Fri, Apr 23, 2021 at 03:08:17PM -0400, Jonathan Marek wrote:
> No one knows what this is for anymore, so just remove it.

Acked-by: Jordan Crouse 

> Signed-off-by: Jonathan Marek 
> ---
>  drivers/gpu/drm/msm/msm_gem.c | 15 +++
>  1 file changed, 3 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
> index b199942266a2..09abda42d764 100644
> --- a/drivers/gpu/drm/msm/msm_gem.c
> +++ b/drivers/gpu/drm/msm/msm_gem.c
> @@ -207,21 +207,12 @@ int msm_gem_mmap_obj(struct drm_gem_object *obj,
>   vma->vm_flags &= ~VM_PFNMAP;
>   vma->vm_flags |= VM_MIXEDMAP;
>  
> - if (msm_obj->flags & MSM_BO_WC) {
> + if (msm_obj->flags & MSM_BO_WC)
>   vma->vm_page_prot = 
> pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
> - } else if (msm_obj->flags & MSM_BO_UNCACHED) {
> + else if (msm_obj->flags & MSM_BO_UNCACHED)
>   vma->vm_page_prot = 
> pgprot_noncached(vm_get_page_prot(vma->vm_flags));
> - } else {
> - /*
> -  * Shunt off cached objs to shmem file so they have their own
> -  * address_space (so unmap_mapping_range does what we want,
> -  * in particular in the case of mmap'd dmabufs)
> -  */
> - vma->vm_pgoff = 0;
> - vma_set_file(vma, obj->filp);
> -
> + else
>   vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
> - }
>  
>   return 0;
>  }
> -- 
> 2.26.1
> 
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 2/5] drm/msm: replace MSM_BO_UNCACHED with MSM_BO_WC for internal objects

2021-05-02 Thread Jordan Crouse
On Fri, Apr 23, 2021 at 03:08:18PM -0400, Jonathan Marek wrote:
> msm_gem_get_vaddr() currently always maps as writecombine, so use the right
> flag instead of relying on broken behavior (things don't actually work if
> they are mapped as uncached).

Ugh - I can't believe this was stil in there.

Acked-by: Jordan Crouse 

> Signed-off-by: Jonathan Marek 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   | 4 ++--
>  drivers/gpu/drm/msm/adreno/a5xx_power.c | 2 +-
>  drivers/gpu/drm/msm/adreno/a5xx_preempt.c   | 4 ++--
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   | 2 +-
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 2 +-
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +-
>  drivers/gpu/drm/msm/dsi/dsi_host.c  | 2 +-
>  7 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index ce13d49e615b..eb0f884eaf30 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -902,7 +902,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
>   if (!a5xx_gpu->shadow_bo) {
>   a5xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
>   sizeof(u32) * gpu->nr_rings,
> - MSM_BO_UNCACHED | MSM_BO_MAP_PRIV,
> + MSM_BO_WC | MSM_BO_MAP_PRIV,
>   gpu->aspace, &a5xx_gpu->shadow_bo,
>   &a5xx_gpu->shadow_iova);
>  
> @@ -1407,7 +1407,7 @@ static int a5xx_crashdumper_init(struct msm_gpu *gpu,
>   struct a5xx_crashdumper *dumper)
>  {
>   dumper->ptr = msm_gem_kernel_new_locked(gpu->dev,
> - SZ_1M, MSM_BO_UNCACHED, gpu->aspace,
> + SZ_1M, MSM_BO_WC, gpu->aspace,
>   &dumper->bo, &dumper->iova);
>  
>   if (!IS_ERR(dumper->ptr))
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_power.c
> index c35b06b46fcc..cdb165236a88 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c
> @@ -363,7 +363,7 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
>   bosize = (cmds_size + (cmds_size / TYPE4_MAX_PAYLOAD) + 1) << 2;
>  
>   ptr = msm_gem_kernel_new_locked(drm, bosize,
> - MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace,
> + MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace,
>   &a5xx_gpu->gpmu_bo, &a5xx_gpu->gpmu_iova);
>   if (IS_ERR(ptr))
>   return;
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
> index 42eaef7ad7c7..ee72510ff8ce 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
> @@ -230,7 +230,7 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu,
>  
>   ptr = msm_gem_kernel_new(gpu->dev,
>   A5XX_PREEMPT_RECORD_SIZE + A5XX_PREEMPT_COUNTER_SIZE,
> - MSM_BO_UNCACHED | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova);
> + MSM_BO_WC | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova);
>  
>   if (IS_ERR(ptr))
>   return PTR_ERR(ptr);
> @@ -238,7 +238,7 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu,
>   /* The buffer to store counters needs to be unprivileged */
>   counters = msm_gem_kernel_new(gpu->dev,
>   A5XX_PREEMPT_COUNTER_SIZE,
> - MSM_BO_UNCACHED, gpu->aspace, &counters_bo, &counters_iova);
> + MSM_BO_WC, gpu->aspace, &counters_bo, &counters_iova);
>   if (IS_ERR(counters)) {
>   msm_gem_kernel_put(bo, gpu->aspace, true);
>   return PTR_ERR(counters);
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 5214a15db95f..1716984c68a8 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -852,7 +852,7 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
>   if (!a6xx_gpu->shadow_bo) {
>   a6xx_gpu->shadow = msm_gem_kernel_new_locked(gpu->dev,
>   sizeof(u32) * gpu->nr_rings,
> - MSM_BO_UNCACHED | MSM_BO_MAP_PRIV,
> + MSM_BO_WC | MSM_BO_MAP_PRIV,
>   gpu->aspace, &a6xx_gpu->shadow_bo,
>   &a6xx_gpu->shadow_iova);
>  
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu

Re: [Freedreno] [PATCH 3/5] drm/msm: use the right pgprot when mapping BOs in the kernel

2021-05-02 Thread Jordan Crouse
On Fri, Apr 23, 2021 at 03:08:19PM -0400, Jonathan Marek wrote:
> Use the same logic as the userspace mapping.
> 
> This fixes msm_rd with cached BOs.
> 

Acked-by: Jordan Crouse 

> Signed-off-by: Jonathan Marek 
> ---
>  drivers/gpu/drm/msm/msm_gem.c | 19 +++
>  1 file changed, 11 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
> index 09abda42d764..0f58937be0a9 100644
> --- a/drivers/gpu/drm/msm/msm_gem.c
> +++ b/drivers/gpu/drm/msm/msm_gem.c
> @@ -199,6 +199,15 @@ void msm_gem_put_pages(struct drm_gem_object *obj)
>   /* when we start tracking the pin count, then do something here */
>  }
>  
> +static pgprot_t msm_gem_pgprot(struct msm_gem_object *msm_obj, pgprot_t prot)
> +{
> + if (msm_obj->flags & MSM_BO_WC)
> + return pgprot_writecombine(prot);
> + if (msm_obj->flags & MSM_BO_UNCACHED)
> + return pgprot_noncached(prot);
> + return prot;
> +}
> +
>  int msm_gem_mmap_obj(struct drm_gem_object *obj,
>   struct vm_area_struct *vma)
>  {
> @@ -206,13 +215,7 @@ int msm_gem_mmap_obj(struct drm_gem_object *obj,
>  
>   vma->vm_flags &= ~VM_PFNMAP;
>   vma->vm_flags |= VM_MIXEDMAP;
> -
> - if (msm_obj->flags & MSM_BO_WC)
> - vma->vm_page_prot = 
> pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
> - else if (msm_obj->flags & MSM_BO_UNCACHED)
> - vma->vm_page_prot = 
> pgprot_noncached(vm_get_page_prot(vma->vm_flags));
> - else
> - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
> + vma->vm_page_prot = msm_gem_pgprot(msm_obj, 
> vm_get_page_prot(vma->vm_flags));
>  
>   return 0;
>  }
> @@ -632,7 +635,7 @@ static void *get_vaddr(struct drm_gem_object *obj, 
> unsigned madv)
>   goto fail;
>   }
>   msm_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
> - VM_MAP, pgprot_writecombine(PAGE_KERNEL));
> + VM_MAP, msm_gem_pgprot(msm_obj, PAGE_KERNEL));
>   if (msm_obj->vaddr == NULL) {
>   ret = -ENOMEM;
>   goto fail;
> -- 
> 2.26.1
> 
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 5/5] drm/msm: deprecate MSM_BO_UNCACHED (map as writecombine instead)

2021-05-02 Thread Jordan Crouse
On Fri, Apr 23, 2021 at 03:08:21PM -0400, Jonathan Marek wrote:
> There shouldn't be any reason to ever use uncached over writecombine,
> so just use writecombine for MSM_BO_UNCACHED.

Extremely correct.

> 
> Note: userspace never used MSM_BO_UNCACHED anyway
> 

Acked-by: Jordan Crouse 

> Signed-off-by: Jonathan Marek 
> ---
>  drivers/gpu/drm/msm/msm_gem.c | 4 +---
>  include/uapi/drm/msm_drm.h| 2 +-
>  2 files changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
> index 2e92e80009c8..56bca9178253 100644
> --- a/drivers/gpu/drm/msm/msm_gem.c
> +++ b/drivers/gpu/drm/msm/msm_gem.c
> @@ -201,10 +201,8 @@ void msm_gem_put_pages(struct drm_gem_object *obj)
>  
>  static pgprot_t msm_gem_pgprot(struct msm_gem_object *msm_obj, pgprot_t prot)
>  {
> - if (msm_obj->flags & MSM_BO_WC)
> + if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED))
>   return pgprot_writecombine(prot);
> - if (msm_obj->flags & MSM_BO_UNCACHED)
> - return pgprot_noncached(prot);
>   return prot;
>  }
>  
> diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
> index a92d90a6d96f..f075851021c3 100644
> --- a/include/uapi/drm/msm_drm.h
> +++ b/include/uapi/drm/msm_drm.h
> @@ -94,7 +94,7 @@ struct drm_msm_param {
>  /* cache modes */
>  #define MSM_BO_CACHED0x0001
>  #define MSM_BO_WC0x0002
> -#define MSM_BO_UNCACHED  0x0004
> +#define MSM_BO_UNCACHED  0x0004 /* deprecated, use MSM_BO_WC */
>  #define MSM_BO_CACHED_COHERENT 0x08
>  
>  #define MSM_BO_FLAGS (MSM_BO_SCANOUT | \
> -- 
> 2.26.1
> 
> ___
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH v4 5/6] drm/msm: Add crashdump support for stalled SMMU

2021-06-08 Thread Jordan Crouse
On Tue, Jun 01, 2021 at 03:47:24PM -0700, Rob Clark wrote:
> From: Rob Clark 
> 
> For collecting devcoredumps with the SMMU stalled after an iova fault,
> we need to skip the parts of the GPU state which are normally collected
> with the hw crashdumper, since with the SMMU stalled the hw would be
> unable to write out the requested state to memory.

On a5xx and a6xx you can query RBBM_STATUS3 bit 24 to see if the IOMMU is
stalled.  That could be an alternative option to adding the "stalled"
infrastructure across all targets.

Jordan
>
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/a2xx_gpu.c   |  2 +-
>  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   |  5 ++-
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.h   |  2 +-
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 43 -
>  drivers/gpu/drm/msm/msm_debugfs.c   |  2 +-
>  drivers/gpu/drm/msm/msm_gpu.c   |  7 ++--
>  drivers/gpu/drm/msm/msm_gpu.h   |  2 +-
>  9 files changed, 47 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
> index bdc989183c64..d2c31fae64fd 100644
> --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
> @@ -434,7 +434,7 @@ static void a2xx_dump(struct msm_gpu *gpu)
>   adreno_dump(gpu);
>  }
>  
> -static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu)
> +static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu, bool 
> stalled)
>  {
>   struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
>  
> diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
> index 4534633fe7cd..b1a6f87d74ef 100644
> --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
> @@ -464,7 +464,7 @@ static void a3xx_dump(struct msm_gpu *gpu)
>   adreno_dump(gpu);
>  }
>  
> -static struct msm_gpu_state *a3xx_gpu_state_get(struct msm_gpu *gpu)
> +static struct msm_gpu_state *a3xx_gpu_state_get(struct msm_gpu *gpu, bool 
> stalled)
>  {
>   struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
>  
> diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
> index 82bebb40234d..22780a594d6f 100644
> --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
> @@ -549,7 +549,7 @@ static const unsigned int a405_registers[] = {
>   ~0 /* sentinel */
>  };
>  
> -static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu)
> +static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu, bool 
> stalled)
>  {
>   struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
>  
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index a0eef5d9b89b..2e7714b1a17f 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -1519,7 +1519,7 @@ static void a5xx_gpu_state_get_hlsq_regs(struct msm_gpu 
> *gpu,
>   msm_gem_kernel_put(dumper.bo, gpu->aspace, true);
>  }
>  
> -static struct msm_gpu_state *a5xx_gpu_state_get(struct msm_gpu *gpu)
> +static struct msm_gpu_state *a5xx_gpu_state_get(struct msm_gpu *gpu, bool 
> stalled)
>  {
>   struct a5xx_gpu_state *a5xx_state = kzalloc(sizeof(*a5xx_state),
>   GFP_KERNEL);
> @@ -1536,7 +1536,8 @@ static struct msm_gpu_state *a5xx_gpu_state_get(struct 
> msm_gpu *gpu)
>   a5xx_state->base.rbbm_status = gpu_read(gpu, REG_A5XX_RBBM_STATUS);
>  
>   /* Get the HLSQ regs with the help of the crashdumper */
> - a5xx_gpu_state_get_hlsq_regs(gpu, a5xx_state);
> + if (!stalled)
> + a5xx_gpu_state_get_hlsq_regs(gpu, a5xx_state);
>  
>   a5xx_set_hwcg(gpu, true);
>  
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> index ce0610c5256f..e0f06ce4e1a9 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> @@ -86,7 +86,7 @@ unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu);
>  void a6xx_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
>   struct drm_printer *p);
>  
> -struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu);
> +struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu, bool stalled);
>  int a6xx_gpu_state_put(struct msm_gpu_state *state);
>  
>  #endif /* __A6XX_GPU_H__ */
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> index c1699b4f9a89..d0af68a76c4f 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> @@ -833,6 +833,21 @@ static void a6xx_get_registers(struct msm_gpu *gpu,
>   a6xx_state, &a6xx_vb

Re: [Freedreno] [PATCH v4 6/6] drm/msm: devcoredump iommu fault support

2021-06-08 Thread Jordan Crouse
On Tue, Jun 01, 2021 at 03:47:25PM -0700, Rob Clark wrote:
> From: Rob Clark 
> 
> Wire up support to stall the SMMU on iova fault, and collect a devcore-
> dump snapshot for easier debugging of faults.
> 
> Currently this is a6xx-only, but mostly only because so far it is the
> only one using adreno-smmu-priv.
> 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   | 29 +--
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 15 
>  drivers/gpu/drm/msm/msm_gem.h   |  1 +
>  drivers/gpu/drm/msm/msm_gem_submit.c|  1 +
>  drivers/gpu/drm/msm/msm_gpu.c   | 48 +
>  drivers/gpu/drm/msm/msm_gpu.h   | 17 +
>  drivers/gpu/drm/msm/msm_gpummu.c|  5 +++
>  drivers/gpu/drm/msm/msm_iommu.c | 11 ++
>  drivers/gpu/drm/msm/msm_mmu.h   |  1 +
>  9 files changed, 126 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 094dc17fd20f..0dcde917e575 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -1008,6 +1008,16 @@ static int a6xx_fault_handler(void *arg, unsigned long 
> iova, int flags, void *da
>   struct msm_gpu *gpu = arg;
>   struct adreno_smmu_fault_info *info = data;
>   const char *type = "UNKNOWN";
> + const char *block;
> + bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
> +
> + /*
> +  * If we aren't going to be resuming later from fault_worker, then do
> +  * it now.
> +  */
> + if (!do_devcoredump) {
> + gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu);
> + }
>  
>   /*
>* Print a default message if we couldn't get the data from the
> @@ -1031,15 +1041,30 @@ static int a6xx_fault_handler(void *arg, unsigned 
> long iova, int flags, void *da
>   else if (info->fsr & ARM_SMMU_FSR_EF)
>   type = "EXTERNAL";
>  
> + block = a6xx_fault_block(gpu, info->fsynr1 & 0xff);
> +
>   pr_warn_ratelimited("*** gpu fault: ttbr0=%.16llx iova=%.16lx dir=%s 
> type=%s source=%s (%u,%u,%u,%u)\n",
>   info->ttbr0, iova,
> - flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ", type,
> - a6xx_fault_block(gpu, info->fsynr1 & 0xff),
> + flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ",
> + type, block,
>   gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(4)),
>   gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(5)),
>   gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(6)),
>   gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(7)));
>  
> + if (do_devcoredump) {
> + /* Turn off the hangcheck timer to keep it from bothering us */
> + del_timer(&gpu->hangcheck_timer);
> +
> + gpu->fault_info.ttbr0 = info->ttbr0;
> + gpu->fault_info.iova  = iova;
> + gpu->fault_info.flags = flags;
> + gpu->fault_info.type  = type;
> + gpu->fault_info.block = block;
> +
> + kthread_queue_work(gpu->worker, &gpu->fault_work);
> + }
> +
>   return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index cf897297656f..4e88d4407667 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -684,6 +684,21 @@ void adreno_show(struct msm_gpu *gpu, struct 
> msm_gpu_state *state,
>   adreno_gpu->info->revn, adreno_gpu->rev.core,
>   adreno_gpu->rev.major, adreno_gpu->rev.minor,
>   adreno_gpu->rev.patchid);
> + /*
> +  * If this is state collected due to iova fault, so fault related info
> +  *
> +  * TTBR0 would not be zero, so this is a good way to distinguish
> +  */
> + if (state->fault_info.ttbr0) {
> + const struct msm_gpu_fault_info *info = &state->fault_info;
> +
> + drm_puts(p, "fault-info:\n");
> + drm_printf(p, "  - ttbr0=%.16llx\n", info->ttbr0);
> + drm_printf(p, "  - iova=%.16lx\n", info->iova);
> + drm_printf(p, "  - dir=%s\n", info->flags & IOMMU_FAULT_WRITE ? 
> "WRITE" : "READ");
> + drm_printf(p, "  - type=%s\n", info->type);
> + drm_printf(p, "  - source=%s\n", info->block);
> + }
>  
>   drm_printf(p, "rbbm-status: 0x%08x\n", state->rbbm_status);
>  
> diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
> index 03e2cc2a2ce1..405f8411e395 100644
> --- a/drivers/gpu/drm/msm/msm_gem.h
> +++ b/drivers/gpu/drm/msm/msm_gem.h
> @@ -328,6 +328,7 @@ struct msm_gem_submit {
>   struct dma_fence *fence;
>   struct msm_gpu_submitqueue *queue;
>   struct pid *pid;/* submitting process */
> + bool fault_dumped;  /* Limit devcoredump dum

Re: [Freedreno] [PATCH v5 4/5] iommu/arm-smmu-qcom: Add stall support

2021-06-11 Thread Jordan Crouse
On Thu, Jun 10, 2021 at 02:44:12PM -0700, Rob Clark wrote:
> From: Rob Clark 
> 
> Add, via the adreno-smmu-priv interface, a way for the GPU to request
> the SMMU to stall translation on faults, and then later resume the
> translation, either retrying or terminating the current translation.
> 
> This will be used on the GPU side to "freeze" the GPU while we snapshot
> useful state for devcoredump.
> 

Acked-by: Jordan Crouse 

> Signed-off-by: Rob Clark 
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 33 ++
>  include/linux/adreno-smmu-priv.h   |  7 +
>  2 files changed, 40 insertions(+)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index b2e31ea84128..61fc645c1325 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -13,6 +13,7 @@ struct qcom_smmu {
>   struct arm_smmu_device smmu;
>   bool bypass_quirk;
>   u8 bypass_cbndx;
> + u32 stall_enabled;
>  };
>  
>  static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu)
> @@ -23,12 +24,17 @@ static struct qcom_smmu *to_qcom_smmu(struct 
> arm_smmu_device *smmu)
>  static void qcom_adreno_smmu_write_sctlr(struct arm_smmu_device *smmu, int 
> idx,
>   u32 reg)
>  {
> + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> +
>   /*
>* On the GPU device we want to process subsequent transactions after a
>* fault to keep the GPU from hanging
>*/
>   reg |= ARM_SMMU_SCTLR_HUPCF;
>  
> + if (qsmmu->stall_enabled & BIT(idx))
> + reg |= ARM_SMMU_SCTLR_CFCFG;
> +
>   arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, reg);
>  }
>  
> @@ -48,6 +54,31 @@ static void qcom_adreno_smmu_get_fault_info(const void 
> *cookie,
>   info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, 
> ARM_SMMU_CB_CONTEXTIDR);
>  }
>  
> +static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
> +{
> + struct arm_smmu_domain *smmu_domain = (void *)cookie;
> + struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
> +
> + if (enabled)
> + qsmmu->stall_enabled |= BIT(cfg->cbndx);
> + else
> + qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
> +}
> +
> +static void qcom_adreno_smmu_resume_translation(const void *cookie, bool 
> terminate)
> +{
> + struct arm_smmu_domain *smmu_domain = (void *)cookie;
> + struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> + struct arm_smmu_device *smmu = smmu_domain->smmu;
> + u32 reg = 0;
> +
> + if (terminate)
> + reg |= ARM_SMMU_RESUME_TERMINATE;
> +
> + arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_RESUME, reg);
> +}
> +
>  #define QCOM_ADRENO_SMMU_GPU_SID 0
>  
>  static bool qcom_adreno_smmu_is_gpu_device(struct device *dev)
> @@ -173,6 +204,8 @@ static int qcom_adreno_smmu_init_context(struct 
> arm_smmu_domain *smmu_domain,
>   priv->get_ttbr1_cfg = qcom_adreno_smmu_get_ttbr1_cfg;
>   priv->set_ttbr0_cfg = qcom_adreno_smmu_set_ttbr0_cfg;
>   priv->get_fault_info = qcom_adreno_smmu_get_fault_info;
> + priv->set_stall = qcom_adreno_smmu_set_stall;
> + priv->resume_translation = qcom_adreno_smmu_resume_translation;
>  
>   return 0;
>  }
> diff --git a/include/linux/adreno-smmu-priv.h 
> b/include/linux/adreno-smmu-priv.h
> index 53fe32fb9214..c637e0997f6d 100644
> --- a/include/linux/adreno-smmu-priv.h
> +++ b/include/linux/adreno-smmu-priv.h
> @@ -45,6 +45,11 @@ struct adreno_smmu_fault_info {
>   * TTBR0 translation is enabled with the specified cfg
>   * @get_fault_info: Called by the GPU fault handler to get information about
>   *  the fault
> + * @set_stall: Configure whether stall on fault (CFCFG) is enabled.  Call
> + * before set_ttbr0_cfg().  If stalling on fault is enabled,
> + * the GPU driver must call resume_translation()
> + * @resume_translation: Resume translation after a fault
> + *
>   *
>   * The GPU driver (drm/msm) and adreno-smmu work together for controlling
>   * the GPU's SMMU instance.  This is by necessity, as the GPU is directly
> @@ -60,6 +65,8 @@ struct adreno_smmu_priv {
>  const struct io_pgtable_cfg *(*get_ttbr1_cfg)(const void *cookie);
>  int (*set_ttbr0_cfg)(const void *cookie, const struct io_pgtable_cfg 
> *cfg);
>  void (*get_fault_info)(const void *cookie, struct adreno_smmu_fault_info 
> *info);
> +void (*set_stall)(const void *cookie, bool enabled);
> +void (*resume_translation)(const void *cookie, bool terminate);
>  };
>  
>  #endif /* __ADRENO_SMMU_PRIV_H */
> -- 
> 2.31.1
> 
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH v5 5/5] drm/msm: devcoredump iommu fault support

2021-06-11 Thread Jordan Crouse
On Thu, Jun 10, 2021 at 02:44:13PM -0700, Rob Clark wrote:
> From: Rob Clark 
> 
> Wire up support to stall the SMMU on iova fault, and collect a devcore-
> dump snapshot for easier debugging of faults.
> 
> Currently this is a6xx-only, but mostly only because so far it is the
> only one using adreno-smmu-priv.

Acked-by: Jordan Crouse 
 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   | 19 +++-
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   | 38 +++-
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 42 ++
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 15 +++
>  drivers/gpu/drm/msm/msm_gem.h   |  1 +
>  drivers/gpu/drm/msm/msm_gem_submit.c|  1 +
>  drivers/gpu/drm/msm/msm_gpu.c   | 48 +
>  drivers/gpu/drm/msm/msm_gpu.h   | 17 
>  drivers/gpu/drm/msm/msm_gpummu.c|  5 +++
>  drivers/gpu/drm/msm/msm_iommu.c | 11 +
>  drivers/gpu/drm/msm/msm_mmu.h   |  1 +
>  11 files changed, 186 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index eb030b00bff4..7a271de9a212 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -1200,6 +1200,15 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu)
>   struct drm_device *dev = gpu->dev;
>   struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);
>  
> + /*
> +  * If stalled on SMMU fault, we could trip the GPU's hang detection,
> +  * but the fault handler will trigger the devcore dump, and we want
> +  * to otherwise resume normally rather than killing the submit, so
> +  * just bail.
> +  */
> + if (gpu_read(gpu, REG_A5XX_RBBM_STATUS3) & BIT(24))
> + return;
> +
>   DRM_DEV_ERROR(dev->dev, "gpu fault ring %d fence %x status %8.8X rb 
> %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
>   ring ? ring->id : -1, ring ? ring->seqno : 0,
>   gpu_read(gpu, REG_A5XX_RBBM_STATUS),
> @@ -1523,6 +1532,7 @@ static struct msm_gpu_state *a5xx_gpu_state_get(struct 
> msm_gpu *gpu)
>  {
>   struct a5xx_gpu_state *a5xx_state = kzalloc(sizeof(*a5xx_state),
>   GFP_KERNEL);
> + bool stalled = !!(gpu_read(gpu, REG_A5XX_RBBM_STATUS3) & BIT(24));
>  
>   if (!a5xx_state)
>   return ERR_PTR(-ENOMEM);
> @@ -1535,8 +1545,13 @@ static struct msm_gpu_state *a5xx_gpu_state_get(struct 
> msm_gpu *gpu)
>  
>   a5xx_state->base.rbbm_status = gpu_read(gpu, REG_A5XX_RBBM_STATUS);
>  
> - /* Get the HLSQ regs with the help of the crashdumper */
> - a5xx_gpu_state_get_hlsq_regs(gpu, a5xx_state);
> + /*
> +  * Get the HLSQ regs with the help of the crashdumper, but only if
> +  * we are not stalled in an iommu fault (in which case the crashdumper
> +  * would not have access to memory)
> +  */
> + if (!stalled)
> + a5xx_gpu_state_get_hlsq_regs(gpu, a5xx_state);
>  
>   a5xx_set_hwcg(gpu, true);
>  
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index fc19db10bff1..c3699408bd1f 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -1081,6 +1081,16 @@ static int a6xx_fault_handler(void *arg, unsigned long 
> iova, int flags, void *da
>   struct msm_gpu *gpu = arg;
>   struct adreno_smmu_fault_info *info = data;
>   const char *type = "UNKNOWN";
> + const char *block;
> + bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
> +
> + /*
> +  * If we aren't going to be resuming later from fault_worker, then do
> +  * it now.
> +  */
> + if (!do_devcoredump) {
> + gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu);
> + }
>  
>   /*
>* Print a default message if we couldn't get the data from the
> @@ -1104,15 +1114,30 @@ static int a6xx_fault_handler(void *arg, unsigned 
> long iova, int flags, void *da
>   else if (info->fsr & ARM_SMMU_FSR_EF)
>   type = "EXTERNAL";
>  
> + block = a6xx_fault_block(gpu, info->fsynr1 & 0xff);
> +
>   pr_warn_ratelimited("*** gpu fault: ttbr0=%.16llx iova=%.16lx dir=%s 
> type=%s source=%s (%u,%u,%u,%u)\n",
>   info->ttbr0, iova,
> - flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ"

Re: [Freedreno] [DPU PATCH 10/11] drm/msm/dpu: correct dpu_io_util.h include path

2018-05-30 Thread Jordan Crouse
On Wed, May 30, 2018 at 08:19:47PM +0530, Rajesh Yadav wrote:
> dpu_io_util.h is moved from standard include path
> to driver folder, correct the include path in code.
> 
> Signed-off-by: Rajesh Yadav 

If the previous patch doesn't compile without this fix you should squash them.

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c | 1 -
>  drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h | 2 +-
>  2 files changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c
> index 24c3274..f997bd9 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c
> @@ -20,7 +20,6 @@
>  #include 
>  #include 
>  #include 
> -#include 
>  
>  #include "dpu_power_handle.h"
>  #include "dpu_trace.h"
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h
> index 9a6d4b9..193f468 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h
> @@ -21,7 +21,7 @@
>  #define DPU_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 16
>  #define DPU_POWER_HANDLE_DISABLE_BUS_IB_QUOTA0
>  
> -#include 
> +#include "dpu_io_util.h"
>  
>  /* event will be triggered before power handler disable */
>  #define DPU_POWER_EVENT_PRE_DISABLE  0x1

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH v2 2/3] drm/msm: move suspend/resume devfreq to their own functions

2018-05-31 Thread Jordan Crouse
On Thu, May 31, 2018 at 12:52:03PM +0530, Sharat Masetty wrote:
> This is needed for hardware revisions which do not rely on the generic
> suspend, resume handlers for power management.
> 
> Signed-off-by: Sharat Masetty 
> ---
>  drivers/gpu/drm/msm/msm_gpu.c | 23 +++
>  drivers/gpu/drm/msm/msm_gpu.h |  2 ++
>  2 files changed, 17 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
> index d7586f2..c5d4627 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.c
> +++ b/drivers/gpu/drm/msm/msm_gpu.c
> @@ -203,6 +203,19 @@ static int disable_axi(struct msm_gpu *gpu)
>   return 0;
>  }
>  
> +void msm_gpu_resume_devfreq(struct msm_gpu *gpu)
> +{
> + gpu->devfreq.busy_cycles = 0;
> + gpu->devfreq.time = ktime_get();
> +
> + devfreq_resume_device(gpu->devfreq.devfreq);
> +}

I'm on the fence about this - it isn't strictly needed because it would be fine
for the 6xx code to duplicate three lines of code but it does make it easier to
update the statistics in one place. If others feel more strongly, chime in.

> +void msm_gpu_suspend_devfreq(struct msm_gpu *gpu)
> +{
> + devfreq_suspend_device(gpu->devfreq.devfreq);
> +}

This on the other hand is entirely not needed. When 6xx does its thing it can
just call devfreq_suspend_device directly. It is doubtful we will ever need
anything more than this one line to stop devfreq.

>  int msm_gpu_pm_resume(struct msm_gpu *gpu)
>  {
>   int ret;
> @@ -221,12 +234,7 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
>   if (ret)
>   return ret;
>  
> - if (gpu->devfreq.devfreq) {
> - gpu->devfreq.busy_cycles = 0;
> - gpu->devfreq.time = ktime_get();
> -
> - devfreq_resume_device(gpu->devfreq.devfreq);
> - }
> + msm_gpu_resume_devfreq(gpu);
>  
>   gpu->needs_hw_init = true;
>  
> @@ -239,8 +247,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
>  
>   DBG("%s", gpu->name);
>  
> - if (gpu->devfreq.devfreq)
> - devfreq_suspend_device(gpu->devfreq.devfreq);
> + msm_gpu_suspend_devfreq(gpu);
>  
>   ret = disable_axi(gpu);
>   if (ret)
> diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> index b824117..1876b81 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.h
> +++ b/drivers/gpu/drm/msm/msm_gpu.h
> @@ -226,6 +226,8 @@ static inline void gpu_write64(struct msm_gpu *gpu, u32 
> lo, u32 hi, u64 val)
>  
>  int msm_gpu_pm_suspend(struct msm_gpu *gpu);
>  int msm_gpu_pm_resume(struct msm_gpu *gpu);
> +void msm_gpu_resume_devfreq(struct msm_gpu *gpu);
> +void msm_gpu_suspend_devfreq(struct msm_gpu *gpu);
>  
>  int msm_gpu_hw_init(struct msm_gpu *gpu);
>  
> -- 
> 1.9.1

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH] drm/msm: Add OUT_RING64() helper macro

2018-05-31 Thread Jordan Crouse
On Thu, May 31, 2018 at 04:01:51PM +0530, Sharat Masetty wrote:
> This patch adds a simple helper function to help write 64 bit payloads
> to the ringbuffer.
> 
> Signed-off-by: Sharat Masetty 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   | 12 
>  drivers/gpu/drm/msm/adreno/a5xx_power.c |  3 +--
>  drivers/gpu/drm/msm/msm_ringbuffer.h|  6 ++
>  3 files changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 5cdf104..7a58a01 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -223,8 +223,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit,
>  
>   /* Set the save preemption record for the ring/command */
>   OUT_PKT4(ring, REG_A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_LO, 2);
> - OUT_RING(ring, lower_32_bits(a5xx_gpu->preempt_iova[submit->ring->id]));
> - OUT_RING(ring, upper_32_bits(a5xx_gpu->preempt_iova[submit->ring->id]));
> + OUT_RING64(ring, a5xx_gpu->preempt_iova[submit->ring->id]);
>  
>   /* Turn back on protected mode */
>   OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
> @@ -248,8 +247,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit,
>   break;
>   case MSM_SUBMIT_CMD_BUF:
>   OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
> - OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
> - OUT_RING(ring, upper_32_bits(submit->cmd[i].iova));
> + OUT_RING64(ring, submit->cmd[i].iova);
>   OUT_RING(ring, submit->cmd[i].size);
>   ibs++;
>   break;
> @@ -282,8 +280,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit,
>*/
>   OUT_PKT7(ring, CP_EVENT_WRITE, 4);
>   OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
> - OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence)));
> - OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
> + OUT_RING64(ring, rbmemptr(ring, fence));
>   OUT_RING(ring, submit->seqno);
>  
>   /* Yield the floor on command completion */
> @@ -469,8 +466,7 @@ static int a5xx_preempt_start(struct msm_gpu *gpu)
>  
>   /* Set the save preemption record for the ring/command */
>   OUT_PKT4(ring, REG_A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_LO, 2);
> - OUT_RING(ring, lower_32_bits(a5xx_gpu->preempt_iova[ring->id]));
> - OUT_RING(ring, upper_32_bits(a5xx_gpu->preempt_iova[ring->id]));
> + OUT_RING64(ring, a5xx_gpu->preempt_iova[ring->id]);
>  
>   /* Turn back on protected mode */
>   OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_power.c
> index e9c0e56..ea5bfa5 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c
> @@ -190,8 +190,7 @@ static int a5xx_gpmu_init(struct msm_gpu *gpu)
>  
>   /* Kick off the IB to load the GPMU microcode */
>   OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
> - OUT_RING(ring, lower_32_bits(a5xx_gpu->gpmu_iova));
> - OUT_RING(ring, upper_32_bits(a5xx_gpu->gpmu_iova));
> + OUT_RING64(ring, a5xx_gpu->gpmu_iova);
>   OUT_RING(ring, a5xx_gpu->gpmu_dwords);
>  
>   /* Turn back on protected mode */
> diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h 
> b/drivers/gpu/drm/msm/msm_ringbuffer.h
> index cffce09..ea8fc39 100644
> --- a/drivers/gpu/drm/msm/msm_ringbuffer.h
> +++ b/drivers/gpu/drm/msm/msm_ringbuffer.h
> @@ -61,4 +61,10 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu 
> *gpu, int id,
>   *(ring->next++) = data;
>  }
>  
> +static inline void
> +OUT_RING64(struct msm_ringbuffer *ring, uint64_t data)

I prefer u64 instead of uint64_t for code.

> +{
> + OUT_RING(ring, lower_32_bits(data));
> + OUT_RING(ring, upper_32_bits(data));
> +}
>  #endif /* __MSM_RINGBUFFER_H__ */
> -- 
> 1.9.1

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH] gpu: drm: msm: Change return type to vm_fault_t

2018-05-31 Thread Jordan Crouse
On Mon, May 28, 2018 at 12:38:41PM +0530, Souptick Joarder wrote:
> On Mon, May 21, 2018 at 10:59 PM, Souptick Joarder  
> wrote:
> > Use new return type vm_fault_t for fault handler. For
> > now, this is just documenting that the function returns
> > a VM_FAULT value rather than an errno. Once all instances
> > are converted, vm_fault_t will become a distinct type.
> >
> > Ref- commit 1c8f422059ae ("mm: change return type to vm_fault_t")
> >
> > Previously vm_insert_mixed() returns err which driver
> > mapped into VM_FAULT_* type. The new function
> > vmf_insert_mixed() will replace this inefficiency by
> > returning VM_FAULT_* type.
> >
> > vmf_error() is the newly introduce inline function
> > in 4.17-rc6.
> >
> > Signed-off-by: Souptick Joarder 
> > Reviewed-by: Matthew Wilcox 
> > ---
> >  drivers/gpu/drm/msm/msm_drv.h |  3 ++-
> >  drivers/gpu/drm/msm/msm_gem.c | 33 ++---
> >  2 files changed, 12 insertions(+), 24 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> > index 0a653dd..44b4ca7 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -33,6 +33,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #include 
> >  #include 
> > @@ -188,7 +189,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void 
> > *data,
> >  int msm_gem_mmap_obj(struct drm_gem_object *obj,
> > struct vm_area_struct *vma);
> >  int msm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
> > -int msm_gem_fault(struct vm_fault *vmf);
> > +vm_fault_t msm_gem_fault(struct vm_fault *vmf);
> >  uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj);
> >  int msm_gem_get_iova(struct drm_gem_object *obj,
> > struct msm_gem_address_space *aspace, uint64_t *iova);
> > diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
> > index 07376de..27a5ab5 100644
> > --- a/drivers/gpu/drm/msm/msm_gem.c
> > +++ b/drivers/gpu/drm/msm/msm_gem.c
> > @@ -217,7 +217,7 @@ int msm_gem_mmap(struct file *filp, struct 
> > vm_area_struct *vma)
> > return msm_gem_mmap_obj(vma->vm_private_data, vma);
> >  }
> >
> > -int msm_gem_fault(struct vm_fault *vmf)
> > +vm_fault_t msm_gem_fault(struct vm_fault *vmf)
> >  {
> > struct vm_area_struct *vma = vmf->vma;
> > struct drm_gem_object *obj = vma->vm_private_data;
> > @@ -225,15 +225,18 @@ int msm_gem_fault(struct vm_fault *vmf)
> > struct page **pages;
> > unsigned long pfn;
> > pgoff_t pgoff;
> > -   int ret;
> > +   int err;
> > +   vm_fault_t ret;
> >
> > /*
> >  * vm_ops.open/drm_gem_mmap_obj and close get and put
> >  * a reference on obj. So, we dont need to hold one here.
> >  */
> > -   ret = mutex_lock_interruptible(&msm_obj->lock);
> > -   if (ret)
> > +   err = mutex_lock_interruptible(&msm_obj->lock);
> > +   if (err) {
> > +   ret = VM_FAULT_NOPAGE;
> > goto out;
> > +   }
> >
> > if (WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) {
> > mutex_unlock(&msm_obj->lock);
> > @@ -243,7 +246,7 @@ int msm_gem_fault(struct vm_fault *vmf)
> > /* make sure we have pages attached now */
> > pages = get_pages(obj);
> > if (IS_ERR(pages)) {
> > -   ret = PTR_ERR(pages);
> > +   ret = vmf_error(PTR_ERR(pages));
> > goto out_unlock;
> > }
> >
> > @@ -255,27 +258,11 @@ int msm_gem_fault(struct vm_fault *vmf)
> > VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
> > pfn, pfn << PAGE_SHIFT);
> >
> > -   ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, 
> > PFN_DEV));
> > -
> > +   ret = vmf_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, 
> > PFN_DEV));
> >  out_unlock:
> > mutex_unlock(&msm_obj->lock);
> >  out:
> > -   switch (ret) {
> > -   case -EAGAIN:
> > -   case 0:
> > -   case -ERESTARTSYS:
> > -   case -EINTR:
> > -   case -EBUSY:
> > -   /*
> > -* EBUSY is ok: this just means that another thread
> > -* already did the job.
> > -*/
> > -   return VM_FAULT_NOPAGE;
> > -   case -ENOMEM:
> > -   return VM_FAULT_OOM;
> > -   default:
> > -   return VM_FAULT_SIGBUS;
> > -   }
> > +   return ret;
> >  }
> >
> >  /** get mmap offset */
> > --
> > 1.9.1
> >
> 
> Any comment for this patch ?

Sorry for the delay, I wanted to get a chance to test it. It seems to pass the
usual regression tests. LGTM.

Jordan

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedren

[Freedreno] [PATCH] rnndb: a6xx: Updates

2018-06-04 Thread Jordan Crouse
Convert some MASK/SHIFT "registers" into bitmasks, correct the bit positions
for GMU_SPTPRAC_PWR_CLK_STATUS and add a few more definitions.
---
 rnndb/adreno/a6xx.xml | 134 ++
 rnndb/adreno/a6xx_gmu.xml |   4 +-
 2 files changed, 79 insertions(+), 59 deletions(-)

diff --git a/rnndb/adreno/a6xx.xml b/rnndb/adreno/a6xx.xml
index 40a35197..779c566a 100644
--- a/rnndb/adreno/a6xx.xml
+++ b/rnndb/adreno/a6xx.xml
@@ -161,6 +161,11 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">

 
 
+
+   
+   
+
+
 


@@ -217,6 +222,7 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   

 

@@ -273,6 +279,7 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   



@@ -696,15 +703,18 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
-   
-   
-   
-   
-   
-   
-   
-   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   



@@ -713,24 +723,26 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   



@@ -767,6 +779,7 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   



@@ -817,8 +830,9 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
-   
+   
+   
+   



@@ -874,7 +888,6 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   



@@ -900,13 +913,19 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
-   
-   
-   
-   
-   
-   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+   
+   
+   



@@ -915,28 +934,29 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+


-   
-   



diff --git a/rnndb/adreno/a6xx_gmu.xml b/rnndb/adreno/a6xx_gmu.xml
index 2fd22f82..4a212d51 100644
--- a/rnndb/adreno/a6xx_gmu.xml
+++ b/rnndb/adreno/a6xx_gmu.xml
@@ -84,8 +84,8 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
-   
+   
+   



-- 
2.17.0

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 1/3] drm/msm: Add a helper function to parse clock names

2018-06-04 Thread Jordan Crouse
Add a helper function to parse the clock names and set up
the bulk data so we can take advantage of the bulk clock
functions instead of rolling our own.  This is added
as a helper function so the upcoming a6xx GMU code can
also take avantage of it.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/msm_drv.c | 57 +
 drivers/gpu/drm/msm/msm_drv.h |  4 +++
 drivers/gpu/drm/msm/msm_gpu.c | 60 ++-
 drivers/gpu/drm/msm/msm_gpu.h |  2 +-
 4 files changed, 72 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 7f7321eb5312..3e86fc9be39f 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -78,6 +78,63 @@ module_param(modeset, bool, 0600);
  * Util/helpers:
  */
 
+int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk)
+{
+   struct property *prop;
+   const char *name;
+   struct clk_bulk_data *local;
+   int i = 0, ret, count;
+
+   count = of_property_count_strings(dev->of_node, "clock-names");
+   if (count < 1)
+   return 0;
+
+   local = devm_kcalloc(dev, sizeof(struct clk_bulk_data *),
+   count, GFP_KERNEL);
+   if (!local)
+   return -ENOMEM;
+
+   of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
+   local[i].id = devm_kstrdup(dev, name, GFP_KERNEL);
+   if (!local[i].id) {
+   devm_kfree(dev, local);
+   return -ENOMEM;
+   }
+
+   i++;
+   }
+
+   ret = devm_clk_bulk_get(dev, count, local);
+
+   if (ret) {
+   for (i = 0; i < count; i++)
+   devm_kfree(dev, (void *) local[i].id);
+   devm_kfree(dev, local);
+
+   return ret;
+   }
+
+   *bulk = local;
+   return count;
+}
+
+struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
+   const char *name)
+{
+   int i;
+   char n[32];
+
+   snprintf(n, sizeof(n), "%s_clk", name);
+
+   for (i = 0; bulk && i < count; i++) {
+   if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n))
+   return bulk[i].clk;
+   }
+
+
+   return NULL;
+}
+
 struct clk *msm_clk_get(struct platform_device *pdev, const char *name)
 {
struct clk *clk;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 17cefca1d566..011c34ad1f93 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -307,6 +307,10 @@ static inline void msm_perf_debugfs_cleanup(struct 
msm_drm_private *priv) {}
 #endif
 
 struct clk *msm_clk_get(struct platform_device *pdev, const char *name);
+int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk);
+
+struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
+   const char *name);
 void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
const char *dbgname);
 void msm_writel(u32 data, void __iomem *addr);
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 1c09acfb4028..d4d5a68e468d 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -141,8 +141,6 @@ static int disable_pwrrail(struct msm_gpu *gpu)
 
 static int enable_clk(struct msm_gpu *gpu)
 {
-   int i;
-
if (gpu->core_clk && gpu->fast_rate)
clk_set_rate(gpu->core_clk, gpu->fast_rate);
 
@@ -150,28 +148,14 @@ static int enable_clk(struct msm_gpu *gpu)
if (gpu->rbbmtimer_clk)
clk_set_rate(gpu->rbbmtimer_clk, 1920);
 
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_prepare(gpu->grp_clks[i]);
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_enable(gpu->grp_clks[i]);
+   clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks);
 
return 0;
 }
 
 static int disable_clk(struct msm_gpu *gpu)
 {
-   int i;
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_disable(gpu->grp_clks[i]);
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_unprepare(gpu->grp_clks[i]);
+   clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks);
 
/*
 * Set the clock to a deliberately low rate. On older targets the clock
@@ -660,44 +644,20 @@ static irqreturn_t irq_handler(int irq, void *data)
return gpu->funcs->irq(gpu);
 }
 
-static struct clk *get_clock(struct device *dev, const char *name)
-{
-   struct clk *clk = 

[Freedreno] [PATCH 2/3] drm/msm: Add generated headers for A6XX

2018-06-04 Thread Jordan Crouse
From: Sharat Masetty 

Add initial register headers for A6XX targets.

Signed-off-by: Sharat Masetty 
Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/adreno/a6xx.xml.h | 1784 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h |  382 +
 2 files changed, 2166 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h

diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h 
b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
new file mode 100644
index ..5af12fe3f95c
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
@@ -0,0 +1,1784 @@
+#ifndef A6XX_XML
+#define A6XX_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git 
repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- ./adreno.xml   (501 bytes, from 2018-05-23 16:51:57)
+- ./freedreno_copyright.xml  (   1572 bytes, from 2016-10-24 21:12:27)
+- ./adreno/a2xx.xml  (  36805 bytes, from 2018-05-23 16:51:57)
+- ./adreno/adreno_common.xml (  13634 bytes, from 2018-05-23 16:51:57)
+- ./adreno/adreno_pm4.xml(  38703 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a3xx.xml  (  83840 bytes, from 2017-12-05 18:20:27)
+- ./adreno/a4xx.xml  ( 112086 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a5xx.xml  ( 146494 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a6xx.xml  (  69957 bytes, from 2018-05-23 17:09:08)
+- ./adreno/a6xx_gmu.xml  (  10431 bytes, from 2018-05-23 16:52:19)
+- ./adreno/ocmem.xml (   1773 bytes, from 2016-10-24 21:12:27)
+
+Copyright (C) 2013-2018 by the following authors:
+- Rob Clark  (robclark)
+- Ilia Mirkin  (imirkin)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+enum a6xx_cp_perfcounter_select {
+   PERF_CP_ALWAYS_COUNT = 0,
+};
+
+enum a6xx_event_write {
+   PC_CCU_INVALIDATE_DEPTH = 24,
+   PC_CCU_INVALIDATE_COLOR = 25,
+};
+
+#define A6XX_RBBM_INT_0_MASK_RBBM_GPU_IDLE 0x0001
+#define A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR  0x0002
+#define A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW   0x0040
+#define A6XX_RBBM_INT_0_MASK_RBBM_GPC_ERROR0x0080
+#define A6XX_RBBM_INT_0_MASK_CP_SW 0x0100
+#define A6XX_RBBM_INT_0_MASK_CP_HW_ERROR   0x0200
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_DEPTH_TS 0x0400
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_COLOR_TS 0x0800
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_RESOLVE_TS 0x1000
+#define A6XX_RBBM_INT_0_MASK_CP_IB20x2000
+#define A6XX_RBBM_INT_0_MASK_CP_IB10x4000
+#define A6XX_RBBM_INT_0_MASK_CP_RB 0x8000
+#define A6XX_RBBM_INT_0_MASK_CP_RB_DONE_TS 0x0002
+#define A6XX_RBBM_INT_0_MASK_CP_WT_DONE_TS 0x0004
+#define A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS 0x0010
+#define A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW 0x0040
+#define A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT  0x0080
+#define A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS   0x0100
+#define A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR0x0200
+#define A6XX_RBBM_INT_0_MASK_DEBBUS_INTR_0 0x0400
+#define A6XX_RBBM_INT_0_MASK_DEBBUS_INTR_1 0x0800
+#define A6XX_RBBM_INT_0_MASK_ISDB_CPU_IRQ  0x4000
+#define A6XX_RBBM_INT_0_MASK_ISDB_UNDER_DEBUG  0x8000
+#define A6XX_CP_INT_CP_OPCODE_ERROR0x0001
+#define A6XX_C

[Freedreno] [v4 0/3] Add support for Adreno a6xx

2018-06-04 Thread Jordan Crouse
This is initial version of a6xx support for the Adreno a6xx GPU
family as found on the sdm845 SoC.  This code is ahead of most of the rest of
the sdm845 code that would be needed to actually bring up a device and it is
definitely far in advance of any user side support for the a6xx GPU so this is
mainly just a chance to look over the code structure and get a feel for the
direction that the hardware is going in.

The a6xx GPU is an iteration of the a5xx family so most of the GPU side code
looks pretty close to the same except for the usual register differences. The
big different is in power control.  On the a5xx there was a rudimentary device
called the GMU that did some basic power stuff but left most of the complexity
to the kernel.  On the a6xx the power complexity is being moved to a component
called the GMU (graphics management unit).

This stack has a number of dependencies that are in various stages of being
merged:

https://patchwork.kernel.org/patch/10286375/ - dev_pm_opp_get_of_node()
https://patchwork.kernel.org/patch/10333575/ - command DB
https://patchwork.kernel.org/patch/10301163/ - pm_runtime ops for arm-smmu

[v4 - Add clock parsing helper function and use it for GPU and GMU.  Update
recommended clock gating settings. Fix a bug in the CMD DB parser. Update
register values from updated database ]

[v3 - fix inverted register definition for GMU_SPTPRAC_CLK_STATUS; fix incorrect
register check in a5xx_gmu_gx_is_on(), use dev_pm_opp_get_of_node() from
Rajendra and Viresh to read the qcom,level from the device tree; read qcom,level
from the DT to get the voltage level to pass to the GMU, fix issues
identified by smatch]

[v2 - addressed comments from Lucas Stach; added pm_runtime_get_supplier calls
for accesses to the GMU IOMMU; moved to SPDX headers for new files]

*** BLURB HERE ***

Jordan Crouse (2):
  drm/msm: Add a helper function to parse clock names
  drm/msm: Add A6XX device support

Sharat Masetty (1):
  drm/msm: Add generated headers for A6XX

 drivers/gpu/drm/msm/Makefile   |3 +
 drivers/gpu/drm/msm/adreno/a6xx.xml.h  | 1784 
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c  | 1174 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h  |  162 ++
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h  |  382 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  |  807 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h  |   60 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c  |  435 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.h  |  127 ++
 drivers/gpu/drm/msm/adreno/adreno_device.c |   12 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.c|2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h|4 +
 drivers/gpu/drm/msm/msm_drv.c  |   57 +
 drivers/gpu/drm/msm/msm_drv.h  |4 +
 drivers/gpu/drm/msm/msm_gpu.c  |   62 +-
 drivers/gpu/drm/msm/msm_gpu.h  |2 +-
 16 files changed, 5024 insertions(+), 53 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.h

-- 
2.17.0

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 3/3] drm/msm: Add A6XX device support

2018-06-04 Thread Jordan Crouse
Add support for the A6XX family of Adreno GPUs. The biggest addition
is the GMU (Graphics Management Unit) which takes over most of the
power management of the GPU itself but in a ironic twist of fate
needs a goodly amount of management itself.  Add support for the
A6XX core code, the GMU and the HFI (hardware firmware interface)
queue that the CPU uses to communicate with the GMU.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/Makefile   |3 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c  | 1174 
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h  |  162 +++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  |  807 ++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h  |   60 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c  |  435 
 drivers/gpu/drm/msm/adreno/a6xx_hfi.h  |  127 +++
 drivers/gpu/drm/msm/adreno/adreno_device.c |   12 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.c|2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h|4 +
 drivers/gpu/drm/msm/msm_gpu.c  |2 +-
 11 files changed, 2786 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index cd40c050b2d7..4affc665c0de 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -10,6 +10,9 @@ msm-y := \
adreno/a5xx_gpu.o \
adreno/a5xx_power.o \
adreno/a5xx_preempt.o \
+   adreno/a6xx_gpu.o \
+   adreno/a6xx_gmu.o \
+   adreno/a6xx_hfi.o \
hdmi/hdmi.o \
hdmi/hdmi_audio.o \
hdmi/hdmi_bridge.o \
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
new file mode 100644
index ..bd835c37a112
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -0,0 +1,1174 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "a6xx_gpu.h"
+#include "a6xx_gmu.xml.h"
+
+static irqreturn_t a6xx_gmu_irq(int irq, void *data)
+{
+   struct a6xx_gmu *gmu = data;
+   u32 status;
+
+   status = gmu_read(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_STATUS);
+   gmu_write(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_CLR, status);
+
+   if (status & A6XX_GMU_AO_HOST_INTERRUPT_STATUS_WDOG_BITE) {
+   dev_err_ratelimited(gmu->dev, "GMU watchdog expired\n");
+
+   /* Temporary until we can recover safely */
+   BUG();
+   }
+
+   if (status &  A6XX_GMU_AO_HOST_INTERRUPT_STATUS_HOST_AHB_BUS_ERROR)
+   dev_err_ratelimited(gmu->dev, "GMU AHB bus error\n");
+
+   if (status & A6XX_GMU_AO_HOST_INTERRUPT_STATUS_FENCE_ERR)
+   dev_err_ratelimited(gmu->dev, "GMU fence error: 0x%x\n",
+   gmu_read(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS));
+
+   return IRQ_HANDLED;
+}
+
+static irqreturn_t a6xx_hfi_irq(int irq, void *data)
+{
+   struct a6xx_gmu *gmu = data;
+   u32 status;
+
+   status = gmu_read(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO);
+   gmu_write(gmu, REG_A6XX_GMU_GMU2HOST_INTR_CLR, status);
+
+   if (status & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ)
+   tasklet_schedule(&gmu->hfi_tasklet);
+
+   if (status & A6XX_GMU_GMU2HOST_INTR_INFO_CM3_FAULT) {
+   dev_err_ratelimited(gmu->dev, "GMU firmware fault\n");
+
+   /* Temporary until we can recover safely */
+   BUG();
+   }
+
+   return IRQ_HANDLED;
+}
+
+/* Check to see if the GX rail is still powered */
+static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
+{
+   u32 val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
+
+   return !(val &
+   (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
+   A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
+}
+
+static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu)
+{
+   u32 val;
+   int local = gmu->idle_level;
+
+   /* SPTP and IFPC both report as IFPC */
+   if (gmu->idle_level == GMU_IDLE_STATE_SPTP)
+   local = GMU_IDLE_STATE_IFPC;
+
+   val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE);
+
+   if (val == local) {
+   if (gmu->idle_level != GMU_IDLE_STATE_IFPC ||
+   !a6xx_gmu_gx_is_on(gmu))
+   return true;
+   }
+
+   return false;
+}
+
+/* Wait for the GMU to get to its most idle state */
+int a6xx_gmu_wait_for_idle(struct a6xx_gpu *a6xx_gpu)
+{
+   stru

Re: [Freedreno] [PATCH v4 0/3] re-factor devfreq common code

2018-06-11 Thread Jordan Crouse
On Fri, Jun 08, 2018 at 11:56:04AM +0530, Sharat Masetty wrote:
> This series re-factors the devfreq code a bit in preparation for the upcoming
> A6x related devfreq changes. The code applies cleanly on 4.17 and has been
> verified on DB820C.
> 
> V2: Addressed code review comments from Jordan Crouse.
> V3: Added a new patch for devfreq cleanup.
> V4: removed "drm/msm: move suspend/resume devfreq to their own functions"(for
> now)
> 
> Sharat Masetty (3):
>   drm/msm: suspend devfreq on init
>   drm/msm: re-factor devfreq code
>   drm/msm: unregister devfreq upon clean up
> 
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 16 
>  drivers/gpu/drm/msm/msm_gpu.c | 27 ++-
>  drivers/gpu/drm/msm/msm_gpu.h |  4 +++-
>  3 files changed, 33 insertions(+), 14 deletions(-)

Rob, it would be great to get these queued for 4.19 since they make life better
for the eventual a6xx changes.

Thanks,
Jordan

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 3/5] drm/msm/adreno: Load the firmware before bringing up the hardware

2018-06-11 Thread Jordan Crouse
Failure to load firwmare is the primary reason to fail adreno_load_gpu().
Try to load it first before going into the hardware initialization code and
unwinding it. This is important for a6xx because the GMU gets loaded from
the runtime power code and it is more costly to fail in that path because
of missing firmware.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 23 +-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 0c0eaad68065..d70e7d145dae 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -155,6 +155,7 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
struct msm_drm_private *priv = dev->dev_private;
struct platform_device *pdev = priv->gpu_pdev;
struct msm_gpu *gpu = NULL;
+   struct adreno_gpu *adreno_gpu;
int ret;
 
if (pdev)
@@ -165,7 +166,27 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
return NULL;
}
 
-   pm_runtime_get_sync(&pdev->dev);
+   adreno_gpu = to_adreno_gpu(gpu);
+
+   /*
+* The number one reason for HW init to fail is if the firmware isn't
+* loaded yet. Try that first and don't bother continuing on
+* otherwise
+*/
+
+   ret = adreno_load_fw(adreno_gpu);
+   if (ret)
+   return NULL;
+
+   /* Make sure pm runtime is active and reset any previous errors */
+   pm_runtime_set_active(&pdev->dev);
+
+   ret = pm_runtime_get_sync(&pdev->dev);
+   if (ret < 0) {
+   dev_err(dev->dev, "Couldn't power up the GPU: %d\n", ret);
+   return NULL;
+   }
+
mutex_lock(&dev->struct_mutex);
ret = msm_gpu_hw_init(gpu);
mutex_unlock(&dev->struct_mutex);
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 0/5] drm/msm: Add support for Adreno a6xx

2018-06-11 Thread Jordan Crouse
This is an initial version of support for the Adreno a6xx GPU family starting
with the a630 from the sdm845 SoC. This code is ahead of much of the sdm845
code that would be needed to actually bring up a device and it is also in
advance of any user side support for the a6xx GPU so this is mainly just a
chance to look over the code structure and get a feel for the
direction that the hardware is going in.

The a6xx GPU is an iteration of a5xx so most of the GPU side code looks pretty
identical except for the usual register differences. The big different is in
power control. On the a5xx there was a rudimentary device called the GPMU that
did some basic power stuff but left most of the complexity to the kernel.

On the a6xx the power complexity is being moved to a component
called the GMU (graphics management unit) which handles the power control of the
GPU and shuts it down quickly after it goes idle.

This stack has a number of dependencies that are in various stages of being
merged:

https://patchwork.kernel.org/patch/10286375/ - dev_pm_opp_get_of_node()
https://patchwork.kernel.org/patch/10333575/ - command DB
https://patchwork.kernel.org/patch/10301163/ - pm_runtime ops for arm-smmu

[v5 - Move firmware loading to adreno_load_gpu() so it is easier to fail if the
firmware isn't found ]

[v4 - Add clock parsing helper function and use it for GPU and GMU. Update
recommended clock gating settings. Fix a bug in the CMD DB parser. Update
register values from updated database ]

[v3 - fix inverted register definition for GMU_SPTPRAC_CLK_STATUS; fix incorrect
register check in a5xx_gmu_gx_is_on(), use dev_pm_opp_get_of_node() from
Rajendra and Viresh to read the qcom,level from the device tree; read qcom,level
from the DT to get the voltage level to pass to the GMU, fix issues
identified by smatch]

[v2 - addressed comments from Lucas Stach; added pm_runtime_get_supplier calls
for accesses to the GMU IOMMU; moved to SPDX headers for new files]

Jordan Crouse (4):
  drm/msm: Remove pm_runtime operations from msm_iommu
  drm/msm: Add a helper function to parse clock names
  drm/msm/adreno: Load the firmware before bringing up the hardware
  drm/msm: Add A6XX device support

Sharat Masetty (1):
  drm/msm: Add generated headers for A6XX

 drivers/gpu/drm/msm/Makefile   |3 +
 drivers/gpu/drm/msm/adreno/a6xx.xml.h  | 1784 
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c  | 1172 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h  |  162 ++
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h  |  382 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  |  807 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h  |   60 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c  |  435 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.h  |  127 ++
 drivers/gpu/drm/msm/adreno/adreno_device.c |   35 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c|2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h|4 +
 drivers/gpu/drm/msm/msm_drv.c  |   57 +
 drivers/gpu/drm/msm/msm_drv.h  |4 +
 drivers/gpu/drm/msm/msm_gpu.c  |   62 +-
 drivers/gpu/drm/msm/msm_gpu.h  |2 +-
 drivers/gpu/drm/msm/msm_iommu.c|8 -
 17 files changed, 5044 insertions(+), 62 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.h

-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 1/5] drm/msm: Remove pm_runtime operations from msm_iommu

2018-06-11 Thread Jordan Crouse
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.

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);
 
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

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 2/5] drm/msm: Add a helper function to parse clock names

2018-06-11 Thread Jordan Crouse
Add a helper function to parse the clock names and set up
the bulk data so we can take advantage of the bulk clock
functions instead of rolling our own. This is added
as a helper function so the upcoming a6xx GMU code can
also take advantage of it.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/msm_drv.c | 57 +
 drivers/gpu/drm/msm/msm_drv.h |  4 +++
 drivers/gpu/drm/msm/msm_gpu.c | 60 ++-
 drivers/gpu/drm/msm/msm_gpu.h |  2 +-
 4 files changed, 72 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 7f7321eb5312..3e86fc9be39f 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -78,6 +78,63 @@ module_param(modeset, bool, 0600);
  * Util/helpers:
  */
 
+int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk)
+{
+   struct property *prop;
+   const char *name;
+   struct clk_bulk_data *local;
+   int i = 0, ret, count;
+
+   count = of_property_count_strings(dev->of_node, "clock-names");
+   if (count < 1)
+   return 0;
+
+   local = devm_kcalloc(dev, sizeof(struct clk_bulk_data *),
+   count, GFP_KERNEL);
+   if (!local)
+   return -ENOMEM;
+
+   of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
+   local[i].id = devm_kstrdup(dev, name, GFP_KERNEL);
+   if (!local[i].id) {
+   devm_kfree(dev, local);
+   return -ENOMEM;
+   }
+
+   i++;
+   }
+
+   ret = devm_clk_bulk_get(dev, count, local);
+
+   if (ret) {
+   for (i = 0; i < count; i++)
+   devm_kfree(dev, (void *) local[i].id);
+   devm_kfree(dev, local);
+
+   return ret;
+   }
+
+   *bulk = local;
+   return count;
+}
+
+struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
+   const char *name)
+{
+   int i;
+   char n[32];
+
+   snprintf(n, sizeof(n), "%s_clk", name);
+
+   for (i = 0; bulk && i < count; i++) {
+   if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n))
+   return bulk[i].clk;
+   }
+
+
+   return NULL;
+}
+
 struct clk *msm_clk_get(struct platform_device *pdev, const char *name)
 {
struct clk *clk;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 17cefca1d566..011c34ad1f93 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -307,6 +307,10 @@ static inline void msm_perf_debugfs_cleanup(struct 
msm_drm_private *priv) {}
 #endif
 
 struct clk *msm_clk_get(struct platform_device *pdev, const char *name);
+int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk);
+
+struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
+   const char *name);
 void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
const char *dbgname);
 void msm_writel(u32 data, void __iomem *addr);
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 1c09acfb4028..d4d5a68e468d 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -141,8 +141,6 @@ static int disable_pwrrail(struct msm_gpu *gpu)
 
 static int enable_clk(struct msm_gpu *gpu)
 {
-   int i;
-
if (gpu->core_clk && gpu->fast_rate)
clk_set_rate(gpu->core_clk, gpu->fast_rate);
 
@@ -150,28 +148,14 @@ static int enable_clk(struct msm_gpu *gpu)
if (gpu->rbbmtimer_clk)
clk_set_rate(gpu->rbbmtimer_clk, 1920);
 
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_prepare(gpu->grp_clks[i]);
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_enable(gpu->grp_clks[i]);
+   clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks);
 
return 0;
 }
 
 static int disable_clk(struct msm_gpu *gpu)
 {
-   int i;
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_disable(gpu->grp_clks[i]);
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_unprepare(gpu->grp_clks[i]);
+   clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks);
 
/*
 * Set the clock to a deliberately low rate. On older targets the clock
@@ -660,44 +644,20 @@ static irqreturn_t irq_handler(int irq, void *data)
return gpu->funcs->irq(gpu);
 }
 
-static struct clk *get_clock(struct device *dev, const char *name)
-{
-   struct clk *clk = 

[Freedreno] [PATCH 5/5] drm/msm: Add A6XX device support

2018-06-11 Thread Jordan Crouse
Add support for the A6XX family of Adreno GPUs. The biggest addition
is the GMU (Graphics Management Unit) which takes over most of the
power management of the GPU itself but in a ironic twist of fate
needs a goodly amount of management itself. Add support for the
A6XX core code, the GMU and the HFI (hardware firmware interface)
queue that the CPU uses to communicate with the GMU.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/Makefile   |3 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c  | 1172 
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h  |  162 +++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  |  807 ++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h  |   60 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c  |  435 
 drivers/gpu/drm/msm/adreno/a6xx_hfi.h  |  127 +++
 drivers/gpu/drm/msm/adreno/adreno_device.c |   12 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.c|2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h|4 +
 drivers/gpu/drm/msm/msm_gpu.c  |2 +-
 11 files changed, 2784 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index cd40c050b2d7..4affc665c0de 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -10,6 +10,9 @@ msm-y := \
adreno/a5xx_gpu.o \
adreno/a5xx_power.o \
adreno/a5xx_preempt.o \
+   adreno/a6xx_gpu.o \
+   adreno/a6xx_gmu.o \
+   adreno/a6xx_hfi.o \
hdmi/hdmi.o \
hdmi/hdmi_audio.o \
hdmi/hdmi_bridge.o \
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
new file mode 100644
index ..9ecd7afe6321
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -0,0 +1,1172 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "a6xx_gpu.h"
+#include "a6xx_gmu.xml.h"
+
+static irqreturn_t a6xx_gmu_irq(int irq, void *data)
+{
+   struct a6xx_gmu *gmu = data;
+   u32 status;
+
+   status = gmu_read(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_STATUS);
+   gmu_write(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_CLR, status);
+
+   if (status & A6XX_GMU_AO_HOST_INTERRUPT_STATUS_WDOG_BITE) {
+   dev_err_ratelimited(gmu->dev, "GMU watchdog expired\n");
+
+   /* Temporary until we can recover safely */
+   BUG();
+   }
+
+   if (status &  A6XX_GMU_AO_HOST_INTERRUPT_STATUS_HOST_AHB_BUS_ERROR)
+   dev_err_ratelimited(gmu->dev, "GMU AHB bus error\n");
+
+   if (status & A6XX_GMU_AO_HOST_INTERRUPT_STATUS_FENCE_ERR)
+   dev_err_ratelimited(gmu->dev, "GMU fence error: 0x%x\n",
+   gmu_read(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS));
+
+   return IRQ_HANDLED;
+}
+
+static irqreturn_t a6xx_hfi_irq(int irq, void *data)
+{
+   struct a6xx_gmu *gmu = data;
+   u32 status;
+
+   status = gmu_read(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO);
+   gmu_write(gmu, REG_A6XX_GMU_GMU2HOST_INTR_CLR, status);
+
+   if (status & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ)
+   tasklet_schedule(&gmu->hfi_tasklet);
+
+   if (status & A6XX_GMU_GMU2HOST_INTR_INFO_CM3_FAULT) {
+   dev_err_ratelimited(gmu->dev, "GMU firmware fault\n");
+
+   /* Temporary until we can recover safely */
+   BUG();
+   }
+
+   return IRQ_HANDLED;
+}
+
+/* Check to see if the GX rail is still powered */
+static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
+{
+   u32 val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
+
+   return !(val &
+   (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
+   A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
+}
+
+static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu)
+{
+   u32 val;
+   int local = gmu->idle_level;
+
+   /* SPTP and IFPC both report as IFPC */
+   if (gmu->idle_level == GMU_IDLE_STATE_SPTP)
+   local = GMU_IDLE_STATE_IFPC;
+
+   val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE);
+
+   if (val == local) {
+   if (gmu->idle_level != GMU_IDLE_STATE_IFPC ||
+   !a6xx_gmu_gx_is_on(gmu))
+   return true;
+   }
+
+   return false;
+}
+
+/* Wait for the GMU to get to its most idle state */
+int a6xx_gmu_wait_for_idle(struct a6xx_gpu *a6xx_gpu)
+{
+   stru

[Freedreno] [PATCH 4/5] drm/msm: Add generated headers for A6XX

2018-06-11 Thread Jordan Crouse
From: Sharat Masetty 

Add initial register headers for A6XX targets.

Signed-off-by: Sharat Masetty 
Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/adreno/a6xx.xml.h | 1784 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h |  382 +
 2 files changed, 2166 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h

diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h 
b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
new file mode 100644
index ..5af12fe3f95c
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
@@ -0,0 +1,1784 @@
+#ifndef A6XX_XML
+#define A6XX_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git 
repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- ./adreno.xml   (501 bytes, from 2018-05-23 16:51:57)
+- ./freedreno_copyright.xml  (   1572 bytes, from 2016-10-24 21:12:27)
+- ./adreno/a2xx.xml  (  36805 bytes, from 2018-05-23 16:51:57)
+- ./adreno/adreno_common.xml (  13634 bytes, from 2018-05-23 16:51:57)
+- ./adreno/adreno_pm4.xml(  38703 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a3xx.xml  (  83840 bytes, from 2017-12-05 18:20:27)
+- ./adreno/a4xx.xml  ( 112086 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a5xx.xml  ( 146494 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a6xx.xml  (  69957 bytes, from 2018-05-23 17:09:08)
+- ./adreno/a6xx_gmu.xml  (  10431 bytes, from 2018-05-23 16:52:19)
+- ./adreno/ocmem.xml (   1773 bytes, from 2016-10-24 21:12:27)
+
+Copyright (C) 2013-2018 by the following authors:
+- Rob Clark  (robclark)
+- Ilia Mirkin  (imirkin)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+enum a6xx_cp_perfcounter_select {
+   PERF_CP_ALWAYS_COUNT = 0,
+};
+
+enum a6xx_event_write {
+   PC_CCU_INVALIDATE_DEPTH = 24,
+   PC_CCU_INVALIDATE_COLOR = 25,
+};
+
+#define A6XX_RBBM_INT_0_MASK_RBBM_GPU_IDLE 0x0001
+#define A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR  0x0002
+#define A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW   0x0040
+#define A6XX_RBBM_INT_0_MASK_RBBM_GPC_ERROR0x0080
+#define A6XX_RBBM_INT_0_MASK_CP_SW 0x0100
+#define A6XX_RBBM_INT_0_MASK_CP_HW_ERROR   0x0200
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_DEPTH_TS 0x0400
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_COLOR_TS 0x0800
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_RESOLVE_TS 0x1000
+#define A6XX_RBBM_INT_0_MASK_CP_IB20x2000
+#define A6XX_RBBM_INT_0_MASK_CP_IB10x4000
+#define A6XX_RBBM_INT_0_MASK_CP_RB 0x8000
+#define A6XX_RBBM_INT_0_MASK_CP_RB_DONE_TS 0x0002
+#define A6XX_RBBM_INT_0_MASK_CP_WT_DONE_TS 0x0004
+#define A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS 0x0010
+#define A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW 0x0040
+#define A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT  0x0080
+#define A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS   0x0100
+#define A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR0x0200
+#define A6XX_RBBM_INT_0_MASK_DEBBUS_INTR_0 0x0400
+#define A6XX_RBBM_INT_0_MASK_DEBBUS_INTR_1 0x0800
+#define A6XX_RBBM_INT_0_MASK_ISDB_CPU_IRQ  0x4000
+#define A6XX_RBBM_INT_0_MASK_ISDB_UNDER_DEBUG  0x8000
+#define A6XX_CP_INT_CP_OPCODE_ERROR0x0001
+#define A6XX_C

Re: [Freedreno] [DPU PATCH 1/4] drm/msm/dpu: add atomic private object to dpu kms

2018-06-13 Thread Jordan Crouse
On Tue, Jun 12, 2018 at 06:17:44PM -0700, Jeykumar Sankaran wrote:
> Subclass drm private state for DPU for handling driver
> specific data. Adds atomic private object and private object
> lock to dpu kms. Provides helper function to retrieve DPU
> private data from current atomic state.
> 
> Signed-off-by: Jeykumar Sankaran 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 
> +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 15 
>  2 files changed, 81 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> index fe614c0..a4ab783 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> @@ -1076,6 +1076,10 @@ static void dpu_kms_destroy(struct msm_kms *kms)
>  
>   dpu_kms = to_dpu_kms(kms);
>   _dpu_kms_hw_destroy(dpu_kms);
> +
> + drm_atomic_private_obj_fini(&dpu_kms->priv_obj);
> + drm_modeset_lock_fini(&dpu_kms->priv_obj_lock);
> +
>  }
>  
>  static void dpu_kms_preclose(struct msm_kms *kms, struct drm_file *file)
> @@ -1618,10 +1622,59 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>   return rc;
>  }
>  
> +struct dpu_private_state *dpu_get_private_state(struct drm_atomic_state 
> *state)
> +{
> + struct msm_drm_private *priv = state->dev->dev_private;
> + struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
> + struct drm_private_state *priv_state;
> + int rc = 0;
> +
> + rc = drm_modeset_lock(&dpu_kms->priv_obj_lock, state->acquire_ctx);
> + if (rc)
> + return ERR_PTR(rc);
> +
> + priv_state = drm_atomic_get_private_obj_state(state,
> + &dpu_kms->priv_obj);
> + if (!priv_state)
> + return NULL;

I'll have to see later when this function is used, but I generally don't like it
when functions return both ERR_PTR and NULL on error but I'm leaving open the
possibility that this could NULL for legitimate reasons. If not, please convert
to a ERR_PTR.

> + return to_dpu_private_state(priv_state);
> +}
> +
> +static struct drm_private_state *
> +dpu_private_obj_duplicate_state(struct drm_private_obj *obj)
> +{
> + struct dpu_private_state *dpu_priv_state;
> +
> + dpu_priv_state = kmemdup(obj->state,
> + sizeof(*dpu_priv_state), GFP_KERNEL);
> + if (!dpu_priv_state)
> + return NULL;
> +
> + __drm_atomic_helper_private_obj_duplicate_state(obj,
> + &dpu_priv_state->base);
> +
> + return &dpu_priv_state->base;
> +}
> +
> +static void dpu_private_obj_destroy_state(struct drm_private_obj *obj,
> +   struct drm_private_state *state)
> +{
> + struct dpu_private_state *dpu_priv_state = to_dpu_private_state(state);
> +
> + kfree(dpu_priv_state);
> +}
> +
> +static const struct drm_private_state_funcs priv_obj_funcs = {
> + .atomic_duplicate_state = dpu_private_obj_duplicate_state,
> + .atomic_destroy_state = dpu_private_obj_destroy_state,
> +};
> +
>  struct msm_kms *dpu_kms_init(struct drm_device *dev)
>  {
>   struct msm_drm_private *priv;
>   struct dpu_kms *dpu_kms;
> + struct dpu_private_state *dpu_priv_state;
>   int irq;
>  
>   if (!dev || !dev->dev_private) {
> @@ -1639,6 +1692,19 @@ struct msm_kms *dpu_kms_init(struct drm_device *dev)
>   }
>   dpu_kms->base.irq = irq;
>  
> + /* Initialize private obj's */
> + drm_modeset_lock_init(&dpu_kms->priv_obj_lock);
> +
> + dpu_priv_state = kzalloc(sizeof(*dpu_priv_state), GFP_KERNEL);
> + if (!dpu_priv_state) {
> + DPU_ERROR("failed to allocate dpu priv obj\n");

We don't need an error message on memory failure - you will have no problem
identifying when this went boom if it goes boom.

> + return ERR_PTR(-ENOMEM);
> + }
> +
> + drm_atomic_private_obj_init(&dpu_kms->priv_obj,
> + &dpu_priv_state->base,
> + &priv_obj_funcs);
> +
>   return &dpu_kms->base;
>  }
>  
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index 046e6f7..924d8967 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -190,6 +190,9 @@ struct dpu_kms {
>   struct dpu_hw_vbif *hw_vbif[VBIF_MAX];
>   struct dpu_hw_mdp *hw_mdp;
>  
> + struct drm_modeset_lock priv_obj_lock;
> + struct drm_private_obj priv_obj;
> +
>   bool has_danger_ctrl;
>  
>   struct platform_device *pdev;
> @@ -197,12 +200,24 @@ struct dpu_kms {
>   struct dss_module_power mp;
>  };
>  
> +struct dpu_private_state {
> + struct drm_private_state base;
> +};
> +
>  struct vsync_info {
>   u32 frame_count;
>   u32 line_count;
>  };
>  
>  #define to_dpu_kms(x) container_of(x, struct dpu_kms, base)
> +#define to_dpu_private_state(x) container_of(x, struct dpu_private_state, 
> ba

Re: [Freedreno] [DPU PATCH 4/4] drm/msm/dpu: use private obj to track hw resources

2018-06-13 Thread Jordan Crouse
On Tue, Jun 12, 2018 at 06:17:47PM -0700, Jeykumar Sankaran wrote:
> Switch to state based resource management. This patch
> overhauls the resource manager and HW allocation methods by
> maintaining the global resource pool and allocated hw
> blocks in respective drm component states.
> 
> Global resource manager(RM) is tracked in private object.
> Allocation strategy is switched from single point allocation
> of HW resources for the display pipeline to per component
> based allocation, where each drm component allocates HW
> blocks mapped to it's domain and tracks them in their respective
> state objects.
> 
> Fixes resource contention due to race conditions between
> user space and display thread by reserving resources
> only in atomic check.
> 
> Signed-off-by: Jeykumar Sankaran 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   | 210 +++---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h   |  59 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 223 ++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h|   4 -
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |   9 +-
>  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c   |  32 +-
>  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  86 +--
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|  19 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h|   8 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 805 
> ++---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 149 ++--
>  11 files changed, 534 insertions(+), 1070 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 426e2ad..a484c06 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -47,6 +47,8 @@
>  #define RIGHT_MIXER 1
>  
>  #define MISR_BUFF_SIZE   256
> +#define MAX_VDISPLAY_SPLIT   1080
> +
>  
>  static inline struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
>  {
> @@ -142,9 +144,9 @@ static void _dpu_crtc_program_lm_output_roi(struct 
> drm_crtc *crtc)
>   crtc_state = to_dpu_crtc_state(crtc->state);
>  
>   lm_horiz_position = 0;
> - for (lm_idx = 0; lm_idx < dpu_crtc->num_mixers; lm_idx++) {
> + for (lm_idx = 0; lm_idx < crtc_state->num_mixers; lm_idx++) {
>   const struct dpu_rect *lm_roi = &crtc_state->lm_bounds[lm_idx];
> - struct dpu_hw_mixer *hw_lm = dpu_crtc->mixers[lm_idx].hw_lm;
> + struct dpu_hw_mixer *hw_lm = crtc_state->mixers[lm_idx].hw_lm;
>   struct dpu_hw_mixer_cfg cfg;
>  
>   if (dpu_kms_rect_is_null(lm_roi))
> @@ -182,7 +184,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
> *crtc,
>   return;
>   }
>  
> - ctl = mixer->hw_ctl;
> + ctl = mixer->lm_ctl;
>   lm = mixer->hw_lm;
>   stage_cfg = &dpu_crtc->stage_cfg;
>   cstate = to_dpu_crtc_state(crtc->state);
> @@ -237,7 +239,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
> *crtc,
>   format->base.pixel_format, fb ? fb->modifier : 0);
>  
>   /* blend config update */
> - for (lm_idx = 0; lm_idx < dpu_crtc->num_mixers; lm_idx++) {
> + for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) {
>   _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate);
>  
>   mixer[lm_idx].flush_mask |= flush_mask;
> @@ -260,7 +262,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
> *crtc,
>  static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
>  {
>   struct dpu_crtc *dpu_crtc;
> - struct dpu_crtc_state *dpu_crtc_state;
> + struct dpu_crtc_state *cstate;
>   struct dpu_crtc_mixer *mixer;
>   struct dpu_hw_ctl *ctl;
>   struct dpu_hw_mixer *lm;
> @@ -271,26 +273,26 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
>   return;
>  
>   dpu_crtc = to_dpu_crtc(crtc);
> - dpu_crtc_state = to_dpu_crtc_state(crtc->state);
> - mixer = dpu_crtc->mixers;
> + cstate = to_dpu_crtc_state(crtc->state);
> + mixer = cstate->mixers;
>  
>   DPU_DEBUG("%s\n", dpu_crtc->name);
>  
> - if (dpu_crtc->num_mixers > CRTC_DUAL_MIXERS) {
> - DPU_ERROR("invalid number mixers: %d\n", dpu_crtc->num_mixers);
> + if (cstate->num_mixers > CRTC_DUAL_MIXERS) {
> + DPU_ERROR("invalid number mixers: %d\n", cstate->num_mixers);

Nit - this could be worded a bit better - "too many mixers" would be better, but
I have to ask - under what circumstances would the number of mixers be larger
than CRTC_DUAL_MIXERS and/or why don't we support a dynamic number of mixers?

>   return;
>   }



> +static void _dpu_crtc_setup_mixers(struct drm_crtc_state *crtc_state)
>  {
> - struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
> - struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
> - st

Re: [Freedreno] [PATCH 1/5] drm/msm: Remove pm_runtime operations from msm_iommu

2018-06-14 Thread Jordan Crouse
On Thu, Jun 14, 2018 at 12:30:35PM +0530, Vivek Gautam wrote:
> 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.

Right - I told Rob about that in IRC but I should have mentioned it here as
well. In order to do this we need to be sure that all of of the possible MMU
combinations are covered.

> >
> > 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);

I'll do that. Thanks.

Jordan

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [DPU PATCH] drm/msm/dsi: add only dsi nodes with a valid device to list

2018-06-18 Thread Jordan Crouse
On Fri, Jun 15, 2018 at 11:05:57PM -0700, Abhinav Kumar wrote:
> Before adding a DSI node to the private list check if the
> node has a valid device connected to it through an endpoint.
> 
> This is required in cases where the chipset supports multiple
> DSI hosts but only one of them is being used.
> 
> In the current implementation even inactive nodes get added
> resulting in creation of redundant connectors.
> 
> Signed-off-by: Abhinav Kumar 
> ---
>  drivers/gpu/drm/msm/dsi/dsi.c  |  6 +-
>  drivers/gpu/drm/msm/dsi/dsi.h  |  1 +
>  drivers/gpu/drm/msm/dsi/dsi_host.c | 10 ++
>  3 files changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
> index b744bcc..46a4906 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi.c
> @@ -120,7 +120,11 @@ static int dsi_bind(struct device *dev, struct device 
> *master, void *data)
>   if (IS_ERR(msm_dsi))
>   return PTR_ERR(msm_dsi);
>  
> - priv->dsi[msm_dsi->id] = msm_dsi;
> + /* Add only the host which has a device attached to it */
> + if (msm_dsi_has_valid_device(msm_dsi->host)) {
> + pr_info("id = %d has valid device\n", msm_dsi->id);

This seems like a debug message that slipped through.

> + priv->dsi[msm_dsi->id] = msm_dsi;
> + }
>  
>   return 0;
>  }
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
> index 70d9a9a..aa198ef 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.h
> +++ b/drivers/gpu/drm/msm/dsi/dsi.h
> @@ -180,6 +180,7 @@ void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host 
> *host,
>  int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
>   struct drm_device *dev);
>  int msm_dsi_host_init(struct msm_dsi *msm_dsi);
> +bool msm_dsi_has_valid_device(struct mipi_dsi_host *host);
>  int msm_dsi_runtime_suspend(struct device *dev);
>  int msm_dsi_runtime_resume(struct device *dev);
>  
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
> b/drivers/gpu/drm/msm/dsi/dsi_host.c
> index 2f1a278..25d65e5 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -470,6 +470,16 @@ static void dsi_bus_clk_disable(struct msm_dsi_host 
> *msm_host)
>   clk_disable_unprepare(msm_host->bus_clks[i]);
>  }
>  
> +bool msm_dsi_has_valid_device(struct mipi_dsi_host *host)
> +{
> + struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
> +
> + if (msm_host->device_node)
> + return true;
> +
> + return false;

Nit, return (msm_host->device_node) ? true : false; works just as well.

> +}
> +
>  int msm_dsi_runtime_suspend(struct device *dev)
>  {
>   struct platform_device *pdev = to_platform_device(dev);

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 2/3] drm/msm: Replace drm_gem_object_{un/reference} with put, get functions

2018-06-18 Thread Jordan Crouse
On Mon, Jun 18, 2018 at 03:02:19PM +0200, Thomas Zimmermann wrote:
> This patch unifies the naming of DRM functions for reference counting
> of struct drm_gem_object. The resulting code is more aligned with the
> rest of the Linux kernel interfaces.

Thanks for doing this.

> Signed-off-by: Thomas Zimmermann 

Reviewed-by: Jordan Crouse 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_debugfs.c | 4 ++--
>  drivers/gpu/drm/msm/adreno/a5xx_power.c   | 2 +-
>  drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 2 +-
>  drivers/gpu/drm/msm/msm_gem_submit.c  | 4 ++--
>  4 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
> index 059ec7d394d0..d2127b1c4ece 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
> @@ -132,14 +132,14 @@ reset_set(void *data, u64 val)
>   if (a5xx_gpu->pm4_bo) {
>   if (a5xx_gpu->pm4_iova)
>   msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);
> - drm_gem_object_unreference(a5xx_gpu->pm4_bo);
> + drm_gem_object_put(a5xx_gpu->pm4_bo);
>   a5xx_gpu->pm4_bo = NULL;
>   }
>  
>   if (a5xx_gpu->pfp_bo) {
>   if (a5xx_gpu->pfp_iova)
>   msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->aspace);
> - drm_gem_object_unreference(a5xx_gpu->pfp_bo);
> + drm_gem_object_put(a5xx_gpu->pfp_bo);
>   a5xx_gpu->pfp_bo = NULL;
>   }
>  
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_power.c
> index e9c0e56dbec0..7a41e1c147e4 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c
> @@ -323,7 +323,7 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
>   if (a5xx_gpu->gpmu_iova)
>   msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
>   if (a5xx_gpu->gpmu_bo)
> - drm_gem_object_unreference(a5xx_gpu->gpmu_bo);
> + drm_gem_object_put(a5xx_gpu->gpmu_bo);
>  
>   a5xx_gpu->gpmu_bo = NULL;
>   a5xx_gpu->gpmu_iova = 0;
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
> index 970c7963ae29..f3c21f827a4d 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
> @@ -272,7 +272,7 @@ void a5xx_preempt_fini(struct msm_gpu *gpu)
>   if (a5xx_gpu->preempt_iova[i])
>   msm_gem_put_iova(a5xx_gpu->preempt_bo[i], gpu->aspace);
>  
> - drm_gem_object_unreference(a5xx_gpu->preempt_bo[i]);
> + drm_gem_object_put(a5xx_gpu->preempt_bo[i]);
>   a5xx_gpu->preempt_bo[i] = NULL;
>   }
>  }
> diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c 
> b/drivers/gpu/drm/msm/msm_gem_submit.c
> index 7bd83e0afa97..7a7923e6220d 100644
> --- a/drivers/gpu/drm/msm/msm_gem_submit.c
> +++ b/drivers/gpu/drm/msm/msm_gem_submit.c
> @@ -144,7 +144,7 @@ static int submit_lookup_objects(struct msm_gem_submit 
> *submit,
>   goto out_unlock;
>   }
>  
> - drm_gem_object_reference(obj);
> + drm_gem_object_get(obj);
>  
>   submit->bos[i].obj = msm_obj;
>  
> @@ -396,7 +396,7 @@ static void submit_cleanup(struct msm_gem_submit *submit)
>   struct msm_gem_object *msm_obj = submit->bos[i].obj;
>   submit_unlock_unpin_bo(submit, i, false);
>   list_del_init(&msm_obj->submit_entry);
> - drm_gem_object_unreference(&msm_obj->base);
> + drm_gem_object_put(&msm_obj->base);
>   }
>  
>   ww_acquire_fini(&submit->ticket);
> -- 
> 2.14.4
> 
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [DPU PATCH] drm/msm/dsi: add only dsi nodes with a valid device to list

2018-06-19 Thread Jordan Crouse
On Mon, Jun 18, 2018 at 03:11:44PM -0700, abhin...@codeaurora.org wrote:
> Hi Jordan
> 
> Thanks for the review.
> 
> Comments inline.
> 
> Abhinav
> On 2018-06-18 07:23, Jordan Crouse wrote:
> >On Fri, Jun 15, 2018 at 11:05:57PM -0700, Abhinav Kumar wrote:
> >>Before adding a DSI node to the private list check if the
> >>node has a valid device connected to it through an endpoint.
> >>
> >>This is required in cases where the chipset supports multiple
> >>DSI hosts but only one of them is being used.
> >>
> >>In the current implementation even inactive nodes get added
> >>resulting in creation of redundant connectors.
> >>
> >>Signed-off-by: Abhinav Kumar 
> >>---
> >> drivers/gpu/drm/msm/dsi/dsi.c  |  6 +-
> >> drivers/gpu/drm/msm/dsi/dsi.h  |  1 +
> >> drivers/gpu/drm/msm/dsi/dsi_host.c | 10 ++
> >> 3 files changed, 16 insertions(+), 1 deletion(-)
> >>
> >>diff --git a/drivers/gpu/drm/msm/dsi/dsi.c
> >>b/drivers/gpu/drm/msm/dsi/dsi.c
> >>index b744bcc..46a4906 100644
> >>--- a/drivers/gpu/drm/msm/dsi/dsi.c
> >>+++ b/drivers/gpu/drm/msm/dsi/dsi.c
> >>@@ -120,7 +120,11 @@ static int dsi_bind(struct device *dev,
> >>struct device *master, void *data)
> >>if (IS_ERR(msm_dsi))
> >>return PTR_ERR(msm_dsi);
> >>
> >>-   priv->dsi[msm_dsi->id] = msm_dsi;
> >>+   /* Add only the host which has a device attached to it */
> >>+   if (msm_dsi_has_valid_device(msm_dsi->host)) {
> >>+   pr_info("id = %d has valid device\n", msm_dsi->id);
> >
> >This seems like a debug message that slipped through.
> [Abhinav] No, this was intentionally added. This will be printed
> only at probe and at most 2 times.
> This gives the information about how many devices have been initialized.

If that is the case then it should be properly constructed. It should use
dev_info like the rest of the messages in this file and it should be written
in simple present tense with the end user in mind as an audience. 
Something like:

dev_info(dev, "DSI device %d is valid\n", msm_dsi->id);

or

dev_info(dev, ""DSI device %d is initialized\n", msm_dsi->id);

Jordan

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 2/5] drm/msm: Add a helper function to parse clock names

2018-06-19 Thread Jordan Crouse
Add a helper function to parse the clock names and set up
the bulk data so we can take advantage of the bulk clock
functions instead of rolling our own. This is added
as a helper function so the upcoming a6xx GMU code can
also take advantage of it.

[v2 - set gpu->nr_clocks to 0 on failed parse ]

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/msm_drv.c | 57 ++
 drivers/gpu/drm/msm/msm_drv.h |  4 +++
 drivers/gpu/drm/msm/msm_gpu.c | 58 ++-
 drivers/gpu/drm/msm/msm_gpu.h |  2 +-
 4 files changed, 72 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 7f7321eb5312..3e86fc9be39f 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -78,6 +78,63 @@ module_param(modeset, bool, 0600);
  * Util/helpers:
  */
 
+int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk)
+{
+   struct property *prop;
+   const char *name;
+   struct clk_bulk_data *local;
+   int i = 0, ret, count;
+
+   count = of_property_count_strings(dev->of_node, "clock-names");
+   if (count < 1)
+   return 0;
+
+   local = devm_kcalloc(dev, sizeof(struct clk_bulk_data *),
+   count, GFP_KERNEL);
+   if (!local)
+   return -ENOMEM;
+
+   of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
+   local[i].id = devm_kstrdup(dev, name, GFP_KERNEL);
+   if (!local[i].id) {
+   devm_kfree(dev, local);
+   return -ENOMEM;
+   }
+
+   i++;
+   }
+
+   ret = devm_clk_bulk_get(dev, count, local);
+
+   if (ret) {
+   for (i = 0; i < count; i++)
+   devm_kfree(dev, (void *) local[i].id);
+   devm_kfree(dev, local);
+
+   return ret;
+   }
+
+   *bulk = local;
+   return count;
+}
+
+struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
+   const char *name)
+{
+   int i;
+   char n[32];
+
+   snprintf(n, sizeof(n), "%s_clk", name);
+
+   for (i = 0; bulk && i < count; i++) {
+   if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n))
+   return bulk[i].clk;
+   }
+
+
+   return NULL;
+}
+
 struct clk *msm_clk_get(struct platform_device *pdev, const char *name)
 {
struct clk *clk;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 17cefca1d566..011c34ad1f93 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -307,6 +307,10 @@ static inline void msm_perf_debugfs_cleanup(struct 
msm_drm_private *priv) {}
 #endif
 
 struct clk *msm_clk_get(struct platform_device *pdev, const char *name);
+int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk);
+
+struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
+   const char *name);
 void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
const char *dbgname);
 void msm_writel(u32 data, void __iomem *addr);
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 1c09acfb4028..827644f0e1a7 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -141,8 +141,6 @@ static int disable_pwrrail(struct msm_gpu *gpu)
 
 static int enable_clk(struct msm_gpu *gpu)
 {
-   int i;
-
if (gpu->core_clk && gpu->fast_rate)
clk_set_rate(gpu->core_clk, gpu->fast_rate);
 
@@ -150,28 +148,14 @@ static int enable_clk(struct msm_gpu *gpu)
if (gpu->rbbmtimer_clk)
clk_set_rate(gpu->rbbmtimer_clk, 1920);
 
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_prepare(gpu->grp_clks[i]);
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_enable(gpu->grp_clks[i]);
+   clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks);
 
return 0;
 }
 
 static int disable_clk(struct msm_gpu *gpu)
 {
-   int i;
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_disable(gpu->grp_clks[i]);
-
-   for (i = gpu->nr_clocks - 1; i >= 0; i--)
-   if (gpu->grp_clks[i])
-   clk_unprepare(gpu->grp_clks[i]);
+   clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks);
 
/*
 * Set the clock to a deliberately low rate. On older targets the clock
@@ -660,44 +644,22 @@ static irqreturn_t irq_handler(int irq, void *data)
return gpu->funcs->irq(gpu);
 }
 
-static struct clk *get_clock(struct device *dev, c

[Freedreno] [PATCH 3/5] drm/msm/adreno: Load the firmware before bringing up the hardware

2018-06-19 Thread Jordan Crouse
Failure to load firmware is the primary reason to fail adreno_load_gpu().
Try to load it first before going into the hardware initialization code and
unwinding it. This is important for a6xx because the GMU gets loaded from
the runtime power code and it is more costly to fail in that path because
of missing firmware.

[v2 - fix compile error caused by adreno_load_fw declared static in
 adreno_gpu ]

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 23 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c|  2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h|  2 +-
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 44813624a286..37746f1d54cf 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -155,6 +155,7 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
struct msm_drm_private *priv = dev->dev_private;
struct platform_device *pdev = priv->gpu_pdev;
struct msm_gpu *gpu = NULL;
+   struct adreno_gpu *adreno_gpu;
int ret;
 
if (pdev)
@@ -165,7 +166,27 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
return NULL;
}
 
-   pm_runtime_get_sync(&pdev->dev);
+   adreno_gpu = to_adreno_gpu(gpu);
+
+   /*
+* The number one reason for HW init to fail is if the firmware isn't
+* loaded yet. Try that first and don't bother continuing on
+* otherwise
+*/
+
+   ret = adreno_load_fw(adreno_gpu);
+   if (ret)
+   return NULL;
+
+   /* Make sure pm runtime is active and reset any previous errors */
+   pm_runtime_set_active(&pdev->dev);
+
+   ret = pm_runtime_get_sync(&pdev->dev);
+   if (ret < 0) {
+   dev_err(dev->dev, "Couldn't power up the GPU: %d\n", ret);
+   return NULL;
+   }
+
mutex_lock(&dev->struct_mutex);
ret = msm_gpu_hw_init(gpu);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index bcbf9f2a29f9..ae693c28d66c 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -138,7 +138,7 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const char 
*fwname)
return ERR_PTR(-ENOENT);
 }
 
-static int adreno_load_fw(struct adreno_gpu *adreno_gpu)
+int adreno_load_fw(struct adreno_gpu *adreno_gpu)
 {
int i;
 
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index bc9ec27e9ed8..81397935d847 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -227,7 +227,7 @@ 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);
 void adreno_gpu_cleanup(struct adreno_gpu *gpu);
-
+int adreno_load_fw(struct adreno_gpu *adreno_gpu);
 
 /* ringbuffer helpers (the parts that are adreno specific) */
 
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 4/5] drm/msm: Add generated headers for A6XX

2018-06-19 Thread Jordan Crouse
From: Sharat Masetty 

Add initial register headers for A6XX targets.

Signed-off-by: Sharat Masetty 
Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/adreno/a6xx.xml.h | 1784 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h |  382 +
 2 files changed, 2166 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h

diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h 
b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
new file mode 100644
index ..5af12fe3f95c
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
@@ -0,0 +1,1784 @@
+#ifndef A6XX_XML
+#define A6XX_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git 
repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- ./adreno.xml   (501 bytes, from 2018-05-23 16:51:57)
+- ./freedreno_copyright.xml  (   1572 bytes, from 2016-10-24 21:12:27)
+- ./adreno/a2xx.xml  (  36805 bytes, from 2018-05-23 16:51:57)
+- ./adreno/adreno_common.xml (  13634 bytes, from 2018-05-23 16:51:57)
+- ./adreno/adreno_pm4.xml(  38703 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a3xx.xml  (  83840 bytes, from 2017-12-05 18:20:27)
+- ./adreno/a4xx.xml  ( 112086 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a5xx.xml  ( 146494 bytes, from 2018-05-23 16:51:57)
+- ./adreno/a6xx.xml  (  69957 bytes, from 2018-05-23 17:09:08)
+- ./adreno/a6xx_gmu.xml  (  10431 bytes, from 2018-05-23 16:52:19)
+- ./adreno/ocmem.xml (   1773 bytes, from 2016-10-24 21:12:27)
+
+Copyright (C) 2013-2018 by the following authors:
+- Rob Clark  (robclark)
+- Ilia Mirkin  (imirkin)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+enum a6xx_cp_perfcounter_select {
+   PERF_CP_ALWAYS_COUNT = 0,
+};
+
+enum a6xx_event_write {
+   PC_CCU_INVALIDATE_DEPTH = 24,
+   PC_CCU_INVALIDATE_COLOR = 25,
+};
+
+#define A6XX_RBBM_INT_0_MASK_RBBM_GPU_IDLE 0x0001
+#define A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR  0x0002
+#define A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW   0x0040
+#define A6XX_RBBM_INT_0_MASK_RBBM_GPC_ERROR0x0080
+#define A6XX_RBBM_INT_0_MASK_CP_SW 0x0100
+#define A6XX_RBBM_INT_0_MASK_CP_HW_ERROR   0x0200
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_DEPTH_TS 0x0400
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_COLOR_TS 0x0800
+#define A6XX_RBBM_INT_0_MASK_CP_CCU_RESOLVE_TS 0x1000
+#define A6XX_RBBM_INT_0_MASK_CP_IB20x2000
+#define A6XX_RBBM_INT_0_MASK_CP_IB10x4000
+#define A6XX_RBBM_INT_0_MASK_CP_RB 0x8000
+#define A6XX_RBBM_INT_0_MASK_CP_RB_DONE_TS 0x0002
+#define A6XX_RBBM_INT_0_MASK_CP_WT_DONE_TS 0x0004
+#define A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS 0x0010
+#define A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW 0x0040
+#define A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT  0x0080
+#define A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS   0x0100
+#define A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR0x0200
+#define A6XX_RBBM_INT_0_MASK_DEBBUS_INTR_0 0x0400
+#define A6XX_RBBM_INT_0_MASK_DEBBUS_INTR_1 0x0800
+#define A6XX_RBBM_INT_0_MASK_ISDB_CPU_IRQ  0x4000
+#define A6XX_RBBM_INT_0_MASK_ISDB_UNDER_DEBUG  0x8000
+#define A6XX_CP_INT_CP_OPCODE_ERROR0x0001
+#define A6XX_C

[Freedreno] [PATCH 5/5] drm/msm: Add A6XX device support

2018-06-19 Thread Jordan Crouse
Add support for the A6XX family of Adreno GPUs. The biggest addition
is the GMU (Graphics Management Unit) which takes over most of the
power management of the GPU itself but in a ironic twist of fate
needs a goodly amount of management itself.  Add support for the
A6XX core code, the GMU and the HFI (hardware firmware interface)
queue that the CPU uses to communicate with the GMU.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/Makefile   |3 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c  | 1172 
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h  |  162 +++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  |  807 ++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h  |   60 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c  |  435 
 drivers/gpu/drm/msm/adreno/a6xx_hfi.h  |  127 +++
 drivers/gpu/drm/msm/adreno/adreno_device.c |   12 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.h|3 +
 drivers/gpu/drm/msm/msm_gpu.c  |2 +-
 10 files changed, 2782 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index cd40c050b2d7..4affc665c0de 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -10,6 +10,9 @@ msm-y := \
adreno/a5xx_gpu.o \
adreno/a5xx_power.o \
adreno/a5xx_preempt.o \
+   adreno/a6xx_gpu.o \
+   adreno/a6xx_gmu.o \
+   adreno/a6xx_hfi.o \
hdmi/hdmi.o \
hdmi/hdmi_audio.o \
hdmi/hdmi_bridge.o \
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
new file mode 100644
index ..9ecd7afe6321
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -0,0 +1,1172 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "a6xx_gpu.h"
+#include "a6xx_gmu.xml.h"
+
+static irqreturn_t a6xx_gmu_irq(int irq, void *data)
+{
+   struct a6xx_gmu *gmu = data;
+   u32 status;
+
+   status = gmu_read(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_STATUS);
+   gmu_write(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_CLR, status);
+
+   if (status & A6XX_GMU_AO_HOST_INTERRUPT_STATUS_WDOG_BITE) {
+   dev_err_ratelimited(gmu->dev, "GMU watchdog expired\n");
+
+   /* Temporary until we can recover safely */
+   BUG();
+   }
+
+   if (status &  A6XX_GMU_AO_HOST_INTERRUPT_STATUS_HOST_AHB_BUS_ERROR)
+   dev_err_ratelimited(gmu->dev, "GMU AHB bus error\n");
+
+   if (status & A6XX_GMU_AO_HOST_INTERRUPT_STATUS_FENCE_ERR)
+   dev_err_ratelimited(gmu->dev, "GMU fence error: 0x%x\n",
+   gmu_read(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS));
+
+   return IRQ_HANDLED;
+}
+
+static irqreturn_t a6xx_hfi_irq(int irq, void *data)
+{
+   struct a6xx_gmu *gmu = data;
+   u32 status;
+
+   status = gmu_read(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO);
+   gmu_write(gmu, REG_A6XX_GMU_GMU2HOST_INTR_CLR, status);
+
+   if (status & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ)
+   tasklet_schedule(&gmu->hfi_tasklet);
+
+   if (status & A6XX_GMU_GMU2HOST_INTR_INFO_CM3_FAULT) {
+   dev_err_ratelimited(gmu->dev, "GMU firmware fault\n");
+
+   /* Temporary until we can recover safely */
+   BUG();
+   }
+
+   return IRQ_HANDLED;
+}
+
+/* Check to see if the GX rail is still powered */
+static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
+{
+   u32 val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
+
+   return !(val &
+   (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
+   A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
+}
+
+static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu)
+{
+   u32 val;
+   int local = gmu->idle_level;
+
+   /* SPTP and IFPC both report as IFPC */
+   if (gmu->idle_level == GMU_IDLE_STATE_SPTP)
+   local = GMU_IDLE_STATE_IFPC;
+
+   val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE);
+
+   if (val == local) {
+   if (gmu->idle_level != GMU_IDLE_STATE_IFPC ||
+   !a6xx_gmu_gx_is_on(gmu))
+   return true;
+   }
+
+   return false;
+}
+
+/* Wait for the GMU to get to its most idle state */
+int a6xx_gmu_wait_for_idle(struct a6xx_gpu *a6xx_gpu)
+{
+   struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+
+   retu

[Freedreno] [PATCH 1/5] drm/msm: Remove pm_runtime operations from msm_iommu

2018-06-19 Thread Jordan Crouse
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.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/msm_iommu.c | 13 +
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index b23d33622f37..e80c79b3bb5c 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -38,13 +38,8 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char 
* const *names,
int cnt)
 {
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);
-
-   return ret;
+   return iommu_attach_device(iommu->domain, mmu->dev);
 }
 
 static void msm_iommu_detach(struct msm_mmu *mmu, const char * const *names,
@@ -52,9 +47,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 +56,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 +67,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

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [v6 PATCH 0/5] drm/msm: Add support for Adreno a6xx

2018-06-19 Thread Jordan Crouse
This is an initial version of support for the Adreno a6xx GPU family starting
with the a630 from the sdm845 SoC. This code is ahead of much of the sdm845
code that would be needed to actually bring up a device and it is also in
advance of any user side support for the a6xx GPU so this is mainly just a
chance to look over the code structure and get a feel for the
direction that the hardware is going in.

The a6xx GPU is an iteration of a5xx so most of the GPU side code looks pretty
identical except for the usual register differences. The big different is in
power control. On the a5xx there was a rudimentary device called the GPMU that
did some basic power stuff but left most of the complexity to the kernel.

On the a6xx the power complexity is being moved to a component
called the GMU (graphics management unit) which handles the power control of the
GPU and shuts it down quickly after it goes idle.

This stack has a number of dependencies that are in various stages of being
merged:

https://patchwork.kernel.org/patch/10286375/ - dev_pm_opp_get_of_node()
https://patchwork.kernel.org/patch/10333575/ - command DB
https://patchwork.kernel.org/patch/10301163/ - pm_runtime ops for arm-smmu

[v6 - set nr_clocks to 0 when parsing fails and minor cleanup in msm_iommu for
Vivek. Fix compile error in the load firmware patch ]

[v5 - Move firmware loading to adreno_load_gpu() so it is easier to fail if the
firmware isn't found ]

[v4 - Add clock parsing helper function and use it for GPU and GMU. Update
recommended clock gating settings. Fix a bug in the CMD DB parser. Update
register values from updated database ]

[v3 - fix inverted register definition for GMU_SPTPRAC_CLK_STATUS; fix incorrect
register check in a5xx_gmu_gx_is_on(), use dev_pm_opp_get_of_node() from
Rajendra and Viresh to read the qcom,level from the device tree; read qcom,level
from the DT to get the voltage level to pass to the GMU, fix issues
identified by smatch]

[v2 - addressed comments from Lucas Stach; added pm_runtime_get_supplier calls
for accesses to the GMU IOMMU; moved to SPDX headers for new files]

Jordan Crouse (4):
  drm/msm: Remove pm_runtime operations from msm_iommu
  drm/msm: Add a helper function to parse clock names
  drm/msm/adreno: Load the firmware before bringing up the hardware
  drm/msm: Add A6XX device support

Sharat Masetty (1):
  drm/msm: Add generated headers for A6XX

 drivers/gpu/drm/msm/Makefile   |3 +
 drivers/gpu/drm/msm/adreno/a6xx.xml.h  | 1784 
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c  | 1172 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h  |  162 ++
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h  |  382 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c  |  807 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h  |   60 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c  |  435 +
 drivers/gpu/drm/msm/adreno/a6xx_hfi.h  |  127 ++
 drivers/gpu/drm/msm/adreno/adreno_device.c |   35 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c|2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h|5 +-
 drivers/gpu/drm/msm/msm_drv.c  |   57 +
 drivers/gpu/drm/msm/msm_drv.h  |4 +
 drivers/gpu/drm/msm/msm_gpu.c  |   60 +-
 drivers/gpu/drm/msm/msm_gpu.h  |2 +-
 drivers/gpu/drm/msm/msm_iommu.c|   13 +-
 17 files changed, 5045 insertions(+), 65 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu.h
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.c
 create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_hfi.h

-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [DPU PATCH 09/11] drm/msm/dpu: Remove unused code and move the header

2018-06-22 Thread Jordan Crouse
On Fri, Jun 22, 2018 at 09:51:28AM -0400, Sean Paul wrote:
> On Wed, May 30, 2018 at 10:50 AM Rajesh Yadav  wrote:
> >
> > From: Jordan Crouse 
> >
> > Remove unused code from dpu_io_util.c.  The functions are only
> > used inside of the msm driver so remove the EXPORT_SYMBOL
> > tags and move the header dpu_io_util.h from include/linux.
> >
> > Signed-off-by: Jordan Crouse 
> > [rya...@codeaurora.org: rebased and removed some extra unused code]
> > Signed-off-by: Rajesh Yadav 
> 
> Hi Rajesh and Jordan,
> I'm backporting this series for testing, and have found that the
> mdss-pll driver uses both dpu_io_util and a bunch of functions/struct
> members removed in this patchset. Do we anticipate having to add those
> back for mdss-pll?

At some point in the distant past some of the downstream folks discovered that
they were using relatively similar functions so they decided to share the code.
The code originally lived in the display driver so it happened that the exported
code continued to be hosted there.

I'm not sure what the upstream status of the mdss-pll code is but I can't
imagine that sharing this code would be in the long term plan and even if it
was basic module guidelines would dictate that it would live with mdss-pll
which would be more likely to be either be built in or act as a dependency for
DPU.

Jordan

> > ---
> >  drivers/gpu/drm/msm/dpu_io_util.c | 380 
> > +-
> >  drivers/gpu/drm/msm/dpu_io_util.h |  61 ++
> >  drivers/gpu/drm/msm/msm_drv.h |   1 -
> >  include/linux/dpu_io_util.h   | 115 
> >  4 files changed, 66 insertions(+), 491 deletions(-)
> >  create mode 100644 drivers/gpu/drm/msm/dpu_io_util.h
> >  delete mode 100644 include/linux/dpu_io_util.h
> >
> > diff --git a/drivers/gpu/drm/msm/dpu_io_util.c 
> > b/drivers/gpu/drm/msm/dpu_io_util.c
> > index ecc297c..f7caec3 100644
> > --- a/drivers/gpu/drm/msm/dpu_io_util.c
> > +++ b/drivers/gpu/drm/msm/dpu_io_util.c
> > @@ -13,318 +13,9 @@
> >
> >  #include 
> >  #include 
> > -#include 
> > -#include 
> >  #include 
> > -#include 
> >
> > -#define MAX_I2C_CMDS  16
> > -void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug)
> > -{
> > -   u32 in_val;
> > -
> > -   if (!io || !io->base) {
> > -   DEV_ERR("%pS->%s: invalid input\n",
> > -   __builtin_return_address(0), __func__);
> > -   return;
> > -   }
> > -
> > -   if (offset > io->len) {
> > -   DEV_ERR("%pS->%s: offset out of range\n",
> > -   __builtin_return_address(0), __func__);
> > -   return;
> > -   }
> > -
> > -   writel_relaxed(value, io->base + offset);
> > -   if (debug) {
> > -   in_val = readl_relaxed(io->base + offset);
> > -   DEV_DBG("[%08x] => %08x [%08x]\n",
> > -   (u32)(unsigned long)(io->base + offset),
> > -   value, in_val);
> > -   }
> > -} /* dss_reg_w */
> > -EXPORT_SYMBOL(dss_reg_w);
> > -
> > -u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug)
> > -{
> > -   u32 value;
> > -
> > -   if (!io || !io->base) {
> > -   DEV_ERR("%pS->%s: invalid input\n",
> > -   __builtin_return_address(0), __func__);
> > -   return -EINVAL;
> > -   }
> > -
> > -   if (offset > io->len) {
> > -   DEV_ERR("%pS->%s: offset out of range\n",
> > -   __builtin_return_address(0), __func__);
> > -   return -EINVAL;
> > -   }
> > -
> > -   value = readl_relaxed(io->base + offset);
> > -   if (debug)
> > -   DEV_DBG("[%08x] <= %08x\n",
> > -   (u32)(unsigned long)(io->base + offset), value);
> > -
> > -   return value;
> > -} /* dss_reg_r */
> > -EXPORT_SYMBOL(dss_reg_r);
> > -
> > -void dss_reg_dump(void __iomem *base, u32 length, const char *prefix,
> > -   u32 debug)
> > -{
> > -   if (debug)
> > -   print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 32, 4,
> > -   (void *)base, length, false);
> > -} /* dss_reg_dump */
> > -EXPORT_SYMBOL(dss_reg_dump);
> > -
> > -static st

Re: [Freedreno] [DPU PATCH 04/15] drm/msm: Remove more dpu-related code from msm_drv

2018-06-28 Thread Jordan Crouse
On Thu, Jun 28, 2018 at 02:28:55PM -0400, Sean Paul wrote:
> This time the iomap/iounmap helper functions. Move map into dpu and
> refactor it to reflect their actual use. iounmap wasn't useful, so
> delete it and call iounmap directly.
> 
> Signed-off-by: Sean Paul 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  | 38 +---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 13 ++--
>  drivers/gpu/drm/msm/msm_drv.c| 23 --
>  drivers/gpu/drm/msm/msm_drv.h|  2 --
>  4 files changed, 38 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> index 0b813a089cba..beba919a6ef6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> @@ -77,6 +77,25 @@ bool dpu_is_custom_client(void)
>   return dpucustom;
>  }
>  
> +static unsigned long dpu_iomap_size(struct platform_device *pdev,
> + const char *name)
> +{
> + struct resource *res;
> +
> + if (!name) {
> + DRM_ERROR("Resource name unspecified\n");
> + return 0;
> + }

Maybe Just a WARN instead - a custom string isn't needed for a case that will
never happen outside of developer error.



-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 03/13] drm: Add drm_puts() to complement drm_printf()

2018-06-29 Thread Jordan Crouse
Add drm_puts() for a much faster path to print constant strings
into a drm_printer object with memcpy and friends. This can
shave seconds off of really large outputs such as GPU dumps.

If the drm_printer object supports a custom puts function then
use that otherwise fall back to the slower legacy printf call.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/drm_print.c | 9 +
 include/drm/drm_print.h | 2 ++
 2 files changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index 03d1f98e5ac7..8fd489248a50 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -122,6 +122,15 @@ void __drm_printfn_debug(struct drm_printer *p, struct 
va_format *vaf)
 }
 EXPORT_SYMBOL(__drm_printfn_debug);
 
+void drm_puts(struct drm_printer *p, const char *str)
+{
+   if (p->puts)
+   p->puts(p, str);
+   else
+   drm_printf(p, "%s", str);
+}
+EXPORT_SYMBOL(drm_puts);
+
 /**
  * drm_printf - print to a &drm_printer stream
  * @p: the &drm_printer
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index 0ea440fb5ec3..b16f4ecaa984 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -69,6 +69,7 @@
 struct drm_printer {
/* private: */
void (*printfn)(struct drm_printer *p, struct va_format *vaf);
+   void (*puts)(struct drm_printer *p, const char *str);
void *arg;
const char *prefix;
 };
@@ -80,6 +81,7 @@ void __drm_printfn_debug(struct drm_printer *p, struct 
va_format *vaf);
 
 __printf(2, 3)
 void drm_printf(struct drm_printer *p, const char *f, ...);
+void drm_puts(struct drm_printer *p, const char *str);
 
 __printf(2, 0)
 /**
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 01/13] include: Move ascii85 functions from i915 to linux/ascii85.h

2018-06-29 Thread Jordan Crouse
The i915 DRM driver very cleverly used ascii85 encoding for their
GPU state file. Move the encode functions to a general header file to
support other drivers that might be interested in the same
functionality.

v3: Fix error_puts -> err_puts pointed out by the 01.org bot
v2: Update API to be cleaner for the caller as suggested by Chris Wilson

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/i915/i915_gpu_error.c | 34 +++
 include/linux/ascii85.h   | 39 +++
 2 files changed, 43 insertions(+), 30 deletions(-)
 create mode 100644 include/linux/ascii85.h

diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index df234dc23274..284e899ca8ff 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "i915_gpu_error.h"
 #include "i915_drv.h"
@@ -522,35 +523,12 @@ void i915_error_printf(struct drm_i915_error_state_buf 
*e, const char *f, ...)
va_end(args);
 }
 
-static int
-ascii85_encode_len(int len)
-{
-   return DIV_ROUND_UP(len, 4);
-}
-
-static bool
-ascii85_encode(u32 in, char *out)
-{
-   int i;
-
-   if (in == 0)
-   return false;
-
-   out[5] = '\0';
-   for (i = 5; i--; ) {
-   out[i] = '!' + in % 85;
-   in /= 85;
-   }
-
-   return true;
-}
-
 static void print_error_obj(struct drm_i915_error_state_buf *m,
struct intel_engine_cs *engine,
const char *name,
struct drm_i915_error_object *obj)
 {
-   char out[6];
+   char out[ASCII85_BUFSZ];
int page;
 
if (!obj)
@@ -572,12 +550,8 @@ static void print_error_obj(struct 
drm_i915_error_state_buf *m,
len -= obj->unused;
len = ascii85_encode_len(len);
 
-   for (i = 0; i < len; i++) {
-   if (ascii85_encode(obj->pages[page][i], out))
-   err_puts(m, out);
-   else
-   err_puts(m, "z");
-   }
+   for (i = 0; i < len; i++)
+   err_puts(m, ascii85_encode(obj->pages[page][i], out));
}
err_puts(m, "\n");
 }
diff --git a/include/linux/ascii85.h b/include/linux/ascii85.h
new file mode 100644
index ..11b9146a3bc4
--- /dev/null
+++ b/include/linux/ascii85.h
@@ -0,0 +1,39 @@
+
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2008 Intel Corporation
+ * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _ASCII85_H_
+#define _ASCII85_H_
+
+#include 
+
+#define ASCII85_BUFSZ 6
+
+static inline long
+ascii85_encode_len(long len)
+{
+   return DIV_ROUND_UP(len, 4);
+}
+
+static inline char *
+ascii85_encode(u32 in, char *out)
+{
+   int i;
+
+   if (in == 0)
+   return "z";
+
+   out[5] = '\0';
+   for (i = 5; i--; ) {
+   out[i] = '!' + in % 85;
+   in /= 85;
+   }
+
+   return out;
+}
+
+#endif
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 04/13] drm: Add puts function for the seq_file printer

2018-06-29 Thread Jordan Crouse
Add support for drm_puts() to use seq_puts() to help speed up
up print time for constant strings.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/drm_print.c | 6 ++
 include/drm/drm_print.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index 8fd489248a50..bef8f0ec5d73 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -104,6 +104,12 @@ void __drm_printfn_coredump(struct drm_printer *p, struct 
va_format *vaf)
 }
 EXPORT_SYMBOL(__drm_printfn_coredump);
 
+void __drm_puts_seq_file(struct drm_printer *p, const char *str)
+{
+   seq_puts(p->arg, str);
+}
+EXPORT_SYMBOL(__drm_puts_seq_file);
+
 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
 {
seq_printf(p->arg, "%pV", vaf);
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index b16f4ecaa984..3bc6ba4b7b2c 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -76,6 +76,7 @@ struct drm_printer {
 
 void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
+void __drm_puts_seq_file(struct drm_printer *p, const char *str);
 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
 
@@ -144,6 +145,7 @@ static inline struct drm_printer 
drm_seq_file_printer(struct seq_file *f)
 {
struct drm_printer p = {
.printfn = __drm_printfn_seq_file,
+   .puts = __drm_puts_seq_file,
.arg = f,
};
return p;
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 08/13] drm/msm/gpu: Rearrange the code that collects the task during a hang

2018-06-29 Thread Jordan Crouse
Do a bit of cleanup to prepare for upcoming changes to pass the
hanging task comm and cmdline to the crash dump function.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/msm_gpu.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 1c09acfb4028..2ca354047250 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -314,6 +314,7 @@ static void recover_worker(struct work_struct *work)
struct msm_drm_private *priv = dev->dev_private;
struct msm_gem_submit *submit;
struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu);
+   char *comm = NULL, *cmd = NULL;
int i;
 
mutex_lock(&dev->struct_mutex);
@@ -327,7 +328,7 @@ static void recover_worker(struct work_struct *work)
rcu_read_lock();
task = pid_task(submit->pid, PIDTYPE_PID);
if (task) {
-   char *cmd;
+   comm = kstrdup(task->comm, GFP_KERNEL);
 
/*
 * So slightly annoying, in other paths like
@@ -342,20 +343,21 @@ static void recover_worker(struct work_struct *work)
mutex_unlock(&dev->struct_mutex);
cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL);
mutex_lock(&dev->struct_mutex);
+   }
+   rcu_read_unlock();
 
+   if (comm && cmd) {
dev_err(dev->dev, "%s: offending task: %s (%s)\n",
-   gpu->name, task->comm, cmd);
+   gpu->name, comm, cmd);
 
msm_rd_dump_submit(priv->hangrd, submit,
-   "offending task: %s (%s)", task->comm, cmd);
-
-   kfree(cmd);
-   } else {
+   "offending task: %s (%s)", comm, cmd);
+   } else
msm_rd_dump_submit(priv->hangrd, submit, NULL);
-   }
-   rcu_read_unlock();
}
 
+   kfree(cmd);
+   kfree(comm);
 
/*
 * Update all the rings with the latest and greatest fence.. this
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 02/13] drm: drm_printer: Add printer for devcoredump

2018-06-29 Thread Jordan Crouse
Add a drm printer suitable for use with the read callback for
devcoredump or other suitable buffer based output format that
isn't otherwise covered by seq_file.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/drm_print.c | 74 +
 include/drm/drm_print.h | 27 ++
 2 files changed, 101 insertions(+)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index b25f98f33f6c..03d1f98e5ac7 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -30,6 +30,80 @@
 #include 
 #include 
 
+void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
+{
+   struct drm_print_iterator *iterator = p->arg;
+   ssize_t len;
+
+   if (!iterator->remain)
+   return;
+
+   /* Figure out how big the string will be */
+   len = snprintf(NULL, 0, "%pV", vaf);
+
+   if (iterator->offset < iterator->start) {
+   char *buf;
+   ssize_t copy;
+
+   if (iterator->offset + len <= iterator->start) {
+   iterator->offset += len;
+   return;
+   }
+
+   /* Print the string into a temporary buffer */
+   buf = kmalloc(len + 1,
+   GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+   if (!buf)
+   return;
+
+   snprintf(buf, len + 1, "%pV", vaf);
+
+   copy = len - (iterator->start - iterator->offset);
+
+   if (copy > iterator->remain)
+   copy = iterator->remain;
+
+   /* Copy out the bit of the string that we need */
+   memcpy(iterator->data,
+   buf + (iterator->start - iterator->offset), copy);
+
+   iterator->offset = iterator->start + copy;
+   iterator->remain -= copy;
+
+   kfree(buf);
+   } else {
+   char *buf;
+   ssize_t pos = iterator->offset - iterator->start;
+
+   if (len < iterator->remain) {
+   snprintf(((char *) iterator->data) + pos,
+   iterator->remain, "%pV", vaf);
+
+   iterator->offset += len;
+   iterator->remain -= len;
+
+   return;
+   }
+
+   /* Print the string into a temporary buffer */
+   buf = kmalloc(len + 1,
+   GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+   if (!buf)
+   return;
+
+   snprintf(buf, len + 1, "%pV", vaf);
+
+   /* Copy out the remaining bits */
+   memcpy(iterator->data + pos, buf, iterator->remain);
+
+   iterator->offset += iterator->remain;
+   iterator->remain = 0;
+
+   kfree(buf);
+   }
+}
+EXPORT_SYMBOL(__drm_printfn_coredump);
+
 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
 {
seq_printf(p->arg, "%pV", vaf);
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index e1a46e9991cc..0ea440fb5ec3 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -73,6 +73,7 @@ struct drm_printer {
const char *prefix;
 };
 
+void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
@@ -104,6 +105,32 @@ drm_vprintf(struct drm_printer *p, const char *fmt, 
va_list *va)
 #define drm_printf_indent(printer, indent, fmt, ...) \
drm_printf((printer), "%.*s" fmt, (indent), "\t\t\t\t\tX", 
##__VA_ARGS__)
 
+struct drm_print_iterator {
+   void *data;
+
+   ssize_t start;
+   ssize_t offset;
+   ssize_t remain;
+};
+
+/**
+ * drm_coredump_printer - construct a &drm_printer that can output to a buffer
+ * from the read function for devcoredump
+ * @iter: A pointer to a struct drm_print_iterator for the read instance
+ *
+ * RETURNS:
+ * The &drm_printer object
+ */
+static inline struct drm_printer
+drm_coredump_printer(struct drm_print_iterator *iter)
+{
+   struct drm_printer p = {
+   .printfn = __drm_printfn_coredump,
+   .arg = iter,
+   };
+   return p;
+}
+
 /**
  * drm_seq_file_printer - construct a &drm_printer that outputs to &seq_file
  * @f:  the &struct seq_file to output to
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [v6 00/13] drm/msm: Capture and dump the GPU crash state

2018-06-29 Thread Jordan Crouse
This is revision 6 implementing a GPU crash state for drm/msm
(https://patchwork.freedesktop.org/series/36097/). This patchset fixes a
few bugs and adds a drm_puts() function to print constant strings faster.

The object of this code is to store and provide enough information to debug
software and hardware issues on the Adreno hardware in a semi human-readable
format that can also be parsed by scripts.

THe full set of changes here capture basic information about the GPU, the
status and contents of the ringbuffers, a snapshot of the current register state
and the active buffers from the hanging submit.

The data is printed with devcoredump.  For example, after a hang you can get
the data from /sys/class/devcoredump/devcdX/data where X is a unique number.

v6: Add drm_puts() and use it in the appropriate place.  Clean up a few minor 
bugs here and there.
v5: Fix symbol error in i915_gpu_error.c thanks to 01 dot org bot. Added
open/release functions for the show debugfs file to get the state per Chris
Wilson. Slightly modified the register output format to be more YAML friendly
also per Chris.
v4: Add buffer dump for the active submit. Fix refcount issue with devcoredump.
Change header for a5xx registers to registers-hlsq because I'm told YAML
requires unique tags.
v3: Make recommended changes to ascii85 per Chris Wilson. Use devcoredump to
dump crash states as suggested by Bjorn Andersson and add a new drm_print
facility to facilitate that. Remove the now obsolete 'crash' debugfs node.
Add documentation for the crash dump output.
v2: Convert output to yaml, use ascii85 to dump ringbuffer contents.

Jordan Crouse (13):
  include: Move ascii85 functions from i915 to linux/ascii85.h
  drm: drm_printer: Add printer for devcoredump
  drm: Add drm_puts() to complement drm_printf()
  drm: Add puts function for the seq_file printer
  drm: Add puts callback for the coredump printer
  drm/msm/gpu: Capture the state of the GPU
  drm/msm/gpu: Convert the GPU show function to use the GPU state
  drm/msm/gpu: Rearrange the code that collects the task during a hang
  drm/msm/gpu: Capture the GPU state on a GPU hang
  drm/msm/adreno: Convert the show/crash file format
  drm/msm/adreno: Add ringbuffer data to the GPU state
  drm/msm/adreno: Add a5xx specific registers for the GPU state
  drm/msm/gpu: Add the buffer objects from the submit to the crash dump

 Documentation/gpu/drm-msm-crash-dump.txt |  58 ++
 drivers/gpu/drm/drm_print.c  | 131 
 drivers/gpu/drm/i915/i915_gpu_error.c|  34 +---
 drivers/gpu/drm/msm/Kconfig  |   1 +
 drivers/gpu/drm/msm/adreno/a3xx_gpu.c|  30 +--
 drivers/gpu/drm/msm/adreno/a4xx_gpu.c|  22 ++-
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c| 242 +--
 drivers/gpu/drm/msm/adreno/adreno_gpu.c  | 184 +++--
 drivers/gpu/drm/msm/adreno/adreno_gpu.h  |  10 +-
 drivers/gpu/drm/msm/msm_debugfs.c|  93 -
 drivers/gpu/drm/msm/msm_gpu.c| 143 +-
 drivers/gpu/drm/msm/msm_gpu.h|  67 ++-
 include/drm/drm_print.h  |  33 
 include/linux/ascii85.h  |  39 
 14 files changed, 987 insertions(+), 100 deletions(-)
 create mode 100644 Documentation/gpu/drm-msm-crash-dump.txt
 create mode 100644 include/linux/ascii85.h

-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 07/13] drm/msm/gpu: Convert the GPU show function to use the GPU state

2018-06-29 Thread Jordan Crouse
Convert the existing GPU show function to use the GPU state to
dump the information rather than reading it directly from the hardware.
This will require an additional step to capture the state before
dumping it for the existing nodes but it will greatly facilitate reusing
the same code for dumping a previously captured state from a GPU hang.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/adreno/a3xx_gpu.c   | 11 +--
 drivers/gpu/drm/msm/adreno/a4xx_gpu.c   | 12 +---
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c   | 18 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.c | 30 
 drivers/gpu/drm/msm/adreno/adreno_gpu.h |  3 +-
 drivers/gpu/drm/msm/msm_debugfs.c   | 92 ++---
 drivers/gpu/drm/msm/msm_gpu.h   |  3 +-
 7 files changed, 104 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index b707b5bca9ab..4cffec2b6adc 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -411,15 +411,6 @@ static const unsigned int a3xx_registers[] = {
~0   /* sentinel */
 };
 
-#ifdef CONFIG_DEBUG_FS
-static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
-{
-   seq_printf(m, "status:   %08x\n",
-   gpu_read(gpu, REG_A3XX_RBBM_STATUS));
-   adreno_show(gpu, m);
-}
-#endif
-
 /* would be nice to not have to duplicate the _show() stuff with printk(): */
 static void a3xx_dump(struct msm_gpu *gpu)
 {
@@ -464,7 +455,7 @@ static const struct adreno_gpu_funcs funcs = {
.irq = a3xx_irq,
.destroy = a3xx_destroy,
 #ifdef CONFIG_DEBUG_FS
-   .show = a3xx_show,
+   .show = adreno_show,
 #endif
.gpu_state_get = a3xx_gpu_state_get,
.gpu_state_put = adreno_gpu_state_put,
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 17e97ebc1077..95f08c22e8d7 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -455,16 +455,6 @@ static const unsigned int a4xx_registers[] = {
~0 /* sentinel */
 };
 
-#ifdef CONFIG_DEBUG_FS
-static void a4xx_show(struct msm_gpu *gpu, struct seq_file *m)
-{
-   seq_printf(m, "status:   %08x\n",
-   gpu_read(gpu, REG_A4XX_RBBM_STATUS));
-   adreno_show(gpu, m);
-
-}
-#endif
-
 static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu)
 {
struct msm_gpu_state *state = adreno_gpu_state_get(gpu);
@@ -551,7 +541,7 @@ static const struct adreno_gpu_funcs funcs = {
.irq = a4xx_irq,
.destroy = a4xx_destroy,
 #ifdef CONFIG_DEBUG_FS
-   .show = a4xx_show,
+   .show = adreno_show,
 #endif
.gpu_state_get = a4xx_gpu_state_get,
.gpu_state_put = adreno_gpu_state_put,
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 9e85e4f7016d..5f1aab3c1cb1 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1215,22 +1215,6 @@ static struct msm_gpu_state *a5xx_gpu_state_get(struct 
msm_gpu *gpu)
return state;
 }
 
-#ifdef CONFIG_DEBUG_FS
-static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
-{
-   seq_printf(m, "status:   %08x\n",
-   gpu_read(gpu, REG_A5XX_RBBM_STATUS));
-
-   /*
-* Temporarily disable hardware clock gating before going into
-* adreno_show to avoid issues while reading the registers
-*/
-   a5xx_set_hwcg(gpu, false);
-   adreno_show(gpu, m);
-   a5xx_set_hwcg(gpu, true);
-}
-#endif
-
 static struct msm_ringbuffer *a5xx_active_ring(struct msm_gpu *gpu)
 {
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -1260,7 +1244,7 @@ static const struct adreno_gpu_funcs funcs = {
.irq = a5xx_irq,
.destroy = a5xx_destroy,
 #ifdef CONFIG_DEBUG_FS
-   .show = a5xx_show,
+   .show = adreno_show,
.debugfs_init = a5xx_debugfs_init,
 #endif
.gpu_busy = a5xx_gpu_busy,
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index c7a0d278c59e..0e937eedcec5 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -423,38 +423,34 @@ void adreno_gpu_state_put(struct msm_gpu_state *state)
 }
 
 #ifdef CONFIG_DEBUG_FS
-void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
+void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
+   struct seq_file *m)
 {
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
int i;
 
+   if (IS_ERR_OR_NULL(state))
+   return;
+
+   seq_printf(m, "status:   %08x\n", state->rbbm_status);
seq_printf(m, "revision: %d (%d.%d.%d.%d)\n",
 

[Freedreno] [PATCH 06/13] drm/msm/gpu: Capture the state of the GPU

2018-06-29 Thread Jordan Crouse
Add the infrastructure to capture the current state of the GPU and
store it in memory so that it can be dumped later.

For now grab the same basic ringbuffer information and registers
that are provided by the debugfs 'gpu' node but obviously this should
be extended to capture a much larger set of GPU information.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/adreno/a3xx_gpu.c   | 15 +++
 drivers/gpu/drm/msm/adreno/a4xx_gpu.c   | 14 +++
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c   | 22 ++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c | 54 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.h |  3 ++
 drivers/gpu/drm/msm/msm_gpu.h   | 19 +
 6 files changed, 127 insertions(+)

diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 3ebbeb3a9b68..b707b5bca9ab 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -427,6 +427,19 @@ static void a3xx_dump(struct msm_gpu *gpu)
gpu_read(gpu, REG_A3XX_RBBM_STATUS));
adreno_dump(gpu);
 }
+
+static struct msm_gpu_state *a3xx_gpu_state_get(struct msm_gpu *gpu)
+{
+   struct msm_gpu_state *state = adreno_gpu_state_get(gpu);
+
+   if (IS_ERR(state))
+   return state;
+
+   state->rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS);
+
+   return state;
+}
+
 /* Register offset defines for A3XX */
 static const unsigned int a3xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE),
@@ -453,6 +466,8 @@ static const struct adreno_gpu_funcs funcs = {
 #ifdef CONFIG_DEBUG_FS
.show = a3xx_show,
 #endif
+   .gpu_state_get = a3xx_gpu_state_get,
+   .gpu_state_put = adreno_gpu_state_put,
},
 };
 
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 16d3d596638e..17e97ebc1077 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -465,6 +465,18 @@ static void a4xx_show(struct msm_gpu *gpu, struct seq_file 
*m)
 }
 #endif
 
+static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu)
+{
+   struct msm_gpu_state *state = adreno_gpu_state_get(gpu);
+
+   if (IS_ERR(state))
+   return state;
+
+   state->rbbm_status = gpu_read(gpu, REG_A4XX_RBBM_STATUS);
+
+   return state;
+}
+
 /* Register offset defines for A4XX, in order of enum adreno_regs */
 static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A4XX_CP_RB_BASE),
@@ -541,6 +553,8 @@ static const struct adreno_gpu_funcs funcs = {
 #ifdef CONFIG_DEBUG_FS
.show = a4xx_show,
 #endif
+   .gpu_state_get = a4xx_gpu_state_get,
+   .gpu_state_put = adreno_gpu_state_put,
},
.get_timestamp = a4xx_get_timestamp,
 };
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index d39400e5bc42..9e85e4f7016d 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1195,6 +1195,26 @@ static int a5xx_get_timestamp(struct msm_gpu *gpu, 
uint64_t *value)
return 0;
 }
 
+static struct msm_gpu_state *a5xx_gpu_state_get(struct msm_gpu *gpu)
+{
+   struct msm_gpu_state *state;
+
+   /*
+* Temporarily disable hardware clock gating before going into
+* adreno_show to avoid issues while reading the registers
+*/
+   a5xx_set_hwcg(gpu, false);
+
+   state = adreno_gpu_state_get(gpu);
+
+   if (!IS_ERR(state))
+   state->rbbm_status = gpu_read(gpu, REG_A5XX_RBBM_STATUS);
+
+   a5xx_set_hwcg(gpu, true);
+
+   return state;
+}
+
 #ifdef CONFIG_DEBUG_FS
 static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
 {
@@ -1244,6 +1264,8 @@ static const struct adreno_gpu_funcs funcs = {
.debugfs_init = a5xx_debugfs_init,
 #endif
.gpu_busy = a5xx_gpu_busy,
+   .gpu_state_get = a5xx_gpu_state_get,
+   .gpu_state_put = adreno_gpu_state_put,
},
.get_timestamp = a5xx_get_timestamp,
 };
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index bcbf9f2a29f9..c7a0d278c59e 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -368,6 +368,60 @@ bool adreno_idle(struct msm_gpu *gpu, struct 
msm_ringbuffer *ring)
return false;
 }
 
+struct msm_gpu_state *adreno_gpu_state_get(struct msm_gpu *gpu)
+{
+   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+   struct msm_gpu_state *state;
+   int i, count = 0;
+
+   state = kzalloc(sizeof(*state), GFP_KERNEL);
+   if (!state)
+   return ERR_PTR(-ENOMEM);
+
+   do_gettimeofday(&state->time);
+
+

[Freedreno] [PATCH 05/13] drm: Add put callback for the coredump printer

2018-06-29 Thread Jordan Crouse
Add a put function for the coredump printer to bypass printf()
for constant strings for a speed boost.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/drm_print.c | 42 +
 include/drm/drm_print.h |  2 ++
 2 files changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index bef8f0ec5d73..bec912215b35 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -30,6 +30,48 @@
 #include 
 #include 
 
+void __drm_puts_coredump(struct drm_printer *p, const char *str)
+{
+   struct drm_print_iterator *iterator = p->arg;
+
+   ssize_t len;
+
+   if (!iterator->remain)
+   return;
+
+   if (iterator->offset < iterator->start) {
+   ssize_t copy;
+
+   len = strlen(str);
+
+   if (iterator->offset + len <= iterator->start) {
+   iterator->offset += len;
+   return;
+   }
+
+   copy = len - (iterator->start - iterator->offset);
+
+   if (copy > iterator->remain)
+   copy = iterator->remain;
+
+   /* Copy out the bit of the string that we need */
+   memcpy(iterator->data,
+   str + (iterator->start - iterator->offset), copy);
+
+   iterator->offset = iterator->start + copy;
+   iterator->remain -= copy;
+   } else {
+   ssize_t pos = iterator->offset - iterator->start;
+
+   len = min_t(ssize_t, strlen(str), iterator->remain);
+
+   memcpy(iterator->data + pos, str, len);
+
+   iterator->offset += len;
+   iterator->remain -= len;
+   }
+}
+
 void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
 {
struct drm_print_iterator *iterator = p->arg;
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index 3bc6ba4b7b2c..2a903ee7b428 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -75,6 +75,7 @@ struct drm_printer {
 };
 
 void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf);
+void __drm_puts_coredump(struct drm_printer *p, const char *str);
 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
 void __drm_puts_seq_file(struct drm_printer *p, const char *str);
 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
@@ -129,6 +130,7 @@ drm_coredump_printer(struct drm_print_iterator *iter)
 {
struct drm_printer p = {
.printfn = __drm_printfn_coredump,
+   .puts = __drm_puts_coredump,
.arg = iter,
};
return p;
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 09/13] drm/msm/gpu: Capture the GPU state on a GPU hang

2018-06-29 Thread Jordan Crouse
Capture the GPU state on a GPU hang and store it for later playback
via the devcoredump facility. Only one crash state is stored at a
time on the assumption that the first hang is usually the most
interesting. The existing crash state can be cleared after capturing
it and then a new one will be captured on the next hang.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/Kconfig |  1 +
 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   |  4 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c | 36 +++
 drivers/gpu/drm/msm/adreno/adreno_gpu.h |  6 +-
 drivers/gpu/drm/msm/msm_debugfs.c   |  5 +-
 drivers/gpu/drm/msm/msm_gpu.c   | 83 -
 drivers/gpu/drm/msm/msm_gpu.h   | 38 ++-
 9 files changed, 154 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 38cbde971b48..843a9d40c05e 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -12,6 +12,7 @@ config DRM_MSM
select SHMEM
select TMPFS
select QCOM_SCM
+   select WANT_DEV_COREDUMP
select SND_SOC_HDMI_CODEC if SND_SOC
select SYNC_FILE
select PM_OPP
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 4cffec2b6adc..fc502e412132 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -454,7 +454,7 @@ static const struct adreno_gpu_funcs funcs = {
.active_ring = adreno_active_ring,
.irq = a3xx_irq,
.destroy = a3xx_destroy,
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
.show = adreno_show,
 #endif
.gpu_state_get = a3xx_gpu_state_get,
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 95f08c22e8d7..8129cf037db1 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -540,7 +540,7 @@ static const struct adreno_gpu_funcs funcs = {
.active_ring = adreno_active_ring,
.irq = a4xx_irq,
.destroy = a4xx_destroy,
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
.show = adreno_show,
 #endif
.gpu_state_get = a4xx_gpu_state_get,
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 5f1aab3c1cb1..16074fa6bf1e 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1243,8 +1243,10 @@ static const struct adreno_gpu_funcs funcs = {
.active_ring = a5xx_active_ring,
.irq = a5xx_irq,
.destroy = a5xx_destroy,
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
.show = adreno_show,
+#endif
+#if defined(CONFIG_DEBUG_FS)
.debugfs_init = a5xx_debugfs_init,
 #endif
.gpu_busy = a5xx_gpu_busy,
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 0e937eedcec5..163542487e2c 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -378,6 +378,8 @@ struct msm_gpu_state *adreno_gpu_state_get(struct msm_gpu 
*gpu)
if (!state)
return ERR_PTR(-ENOMEM);
 
+   kref_init(&state->ref);
+
do_gettimeofday(&state->time);
 
for (i = 0; i < gpu->nr_rings; i++) {
@@ -413,18 +415,28 @@ struct msm_gpu_state *adreno_gpu_state_get(struct msm_gpu 
*gpu)
return state;
 }
 
-void adreno_gpu_state_put(struct msm_gpu_state *state)
+static void adreno_gpu_state_destroy(struct kref *kref)
 {
-   if (IS_ERR_OR_NULL(state))
-   return;
+   struct msm_gpu_state *state = container_of(kref,
+   struct msm_gpu_state, ref);
 
+   kfree(state->comm);
+   kfree(state->cmd);
kfree(state->registers);
kfree(state);
 }
 
-#ifdef CONFIG_DEBUG_FS
+int adreno_gpu_state_put(struct msm_gpu_state *state)
+{
+   if (IS_ERR_OR_NULL(state))
+   return 1;
+
+   return kref_put(&state->ref, adreno_gpu_state_destroy);
+}
+
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
 void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
-   struct seq_file *m)
+   struct drm_printer *p)
 {
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
int i;
@@ -432,23 +444,23 @@ void adreno_show(struct msm_gpu *gpu, struct 
msm_gpu_state *state,
if (IS_ERR_OR_NULL(state))
return;
 
-   seq_printf(m, "status:   %08x\n", state->rbbm_status);
-   seq_printf(m, "revision: %d (%d.%d.%d.%d)\n",
+

[Freedreno] [PATCH 13/13] drm/msm/gpu: Add the buffer objects from the submit to the crash dump

2018-06-29 Thread Jordan Crouse
For hangs, dump copy out the contents of the buffer objects attached to the
guilty submission and print them in the crash dump report.

Signed-off-by: Jordan Crouse 
---
 Documentation/gpu/drm-msm-crash-dump.txt |  7 +++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c  | 58 
 drivers/gpu/drm/msm/msm_gpu.c| 48 ++--
 drivers/gpu/drm/msm/msm_gpu.h|  9 
 4 files changed, 109 insertions(+), 13 deletions(-)

diff --git a/Documentation/gpu/drm-msm-crash-dump.txt 
b/Documentation/gpu/drm-msm-crash-dump.txt
index 7083075c6f87..b9804dd112db 100644
--- a/Documentation/gpu/drm-msm-crash-dump.txt
+++ b/Documentation/gpu/drm-msm-crash-dump.txt
@@ -40,6 +40,13 @@ bos: # List of buffers from the hanging submission 
(if known)
data:   # [ascii85] The contents of the ring encoded as ascii85.
# Only the unused portions of the ring will be printed
# (up to a maximum of 'size' bytes)
+bos:   # List of buffers from the hanging submission (if known)
+  -iova:   # [hex] GPU address of the buffer
+   size:   # [decimal] Size of the buffer (in bytes)
+   data:   # [ascii85] The contents of the buffer encoded as
+   # ascii85. Only the contents of buffers marked as
+   # readable are dumped. Trailing zeros at the end of the
+   # buffer won't be dumped.
 registers: # Sets of register values. This section can be used multiple
# times for different ranges of registers. Each register will be
# on its own line.
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index be81fe1f6a35..ce8b7af0a77d 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -438,6 +438,10 @@ void adreno_gpu_state_destroy(struct msm_gpu_state *state)
for (i = 0; i < ARRAY_SIZE(state->ring); i++)
kfree(state->ring[i].data);
 
+   for (i = 0; state->bos && i < state->nr_bos; i++)
+   kvfree(state->bos[i].data);
+
+   kfree(state->bos);
kfree(state->comm);
kfree(state->cmd);
kfree(state->registers);
@@ -461,6 +465,39 @@ int adreno_gpu_state_put(struct msm_gpu_state *state)
 }
 
 #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
+
+static void adreno_show_object(struct drm_printer *p, u32 *ptr, int len)
+{
+   char out[ASCII85_BUFSZ];
+   long l, datalen, i;
+
+   if (!ptr || !len)
+   return;
+
+   /*
+* Only dump the non-zero part of the buffer - rarely will any data
+* completely fill the entire allocated size of the buffer
+*/
+   for (datalen = 0, i = 0; i < len >> 2; i++) {
+   if (ptr[i])
+   datalen = i << 2;
+   }
+
+   /* Skip printing the object if it is empty */
+   if (datalen == 0)
+   return;
+
+   l = ascii85_encode_len(datalen);
+
+   drm_puts(p, "data: !!ascii85 |\n");
+   drm_puts(p, " ");
+
+   for (i = 0; i < l; i++)
+   drm_puts(p, ascii85_encode(ptr[i], out));
+
+   drm_puts(p, "\n");
+}
+
 void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
struct drm_printer *p)
 {
@@ -487,19 +524,20 @@ void adreno_show(struct msm_gpu *gpu, struct 
msm_gpu_state *state,
drm_printf(p, "wptr: %d\n", state->ring[i].wptr);
drm_printf(p, "size: %d\n", MSM_GPU_RINGBUFFER_SZ);
 
-   if (state->ring[i].data && state->ring[i].data_size) {
-   u32 *ptr = (u32 *) state->ring[i].data;
-   char out[ASCII85_BUFSZ];
-   long len = ascii85_encode_len(state->ring[i].data_size);
-   int j;
+   adreno_show_object(p, state->ring[i].data,
+   state->ring[i].data_size);
+   }
 
-   drm_printf(p, "data: !!ascii85 |\n");
-   drm_printf(p, " ");
+   if (state->bos) {
+   drm_puts(p, "bos:\n");
 
-   for (j = 0; j < len; j++)
-   drm_printf(p, ascii85_encode(ptr[j], out));
+   for (i = 0; i < state->nr_bos; i++) {
+   drm_printf(p, "  - iova: 0x%016llx\n",
+   state->bos[i].iova);
+   drm_printf(p, "size: %ld\n", state->bos[i].size);
 
-   drm_printf(p, "\n");
+   adreno_show_object(p, state->bos[i].data,
+   sta

[Freedreno] [PATCH 11/13] drm/msm/adreno: Add ringbuffer data to the GPU state

2018-06-29 Thread Jordan Crouse
Add the contents of each ringbuffer to the GPU state and dump the
data in the crash file encoded with ascii85. To save space only
the used portions of the ringbuffer are dumped.

Signed-off-by: Jordan Crouse 
---
 Documentation/gpu/drm-msm-crash-dump.txt |  5 +++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c  | 41 
 drivers/gpu/drm/msm/msm_gpu.h|  2 ++
 3 files changed, 48 insertions(+)

diff --git a/Documentation/gpu/drm-msm-crash-dump.txt 
b/Documentation/gpu/drm-msm-crash-dump.txt
index 930e4c970a62..7083075c6f87 100644
--- a/Documentation/gpu/drm-msm-crash-dump.txt
+++ b/Documentation/gpu/drm-msm-crash-dump.txt
@@ -35,6 +35,11 @@ bos: # List of buffers from the hanging submission 
(if known)
# ascii85. Only the contents of buffers marked as
# readable are dumped. Trailing zeros at the end of the
# buffer won't be dumped.
+   size:   # [decimal] The maximum size of the ring programmed in
+   # the hardware
+   data:   # [ascii85] The contents of the ring encoded as ascii85.
+   # Only the unused portions of the ring will be printed
+   # (up to a maximum of 'size' bytes)
 registers: # Sets of register values. This section can be used multiple
# times for different ranges of registers. Each register will be
# on its own line.
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 15fe0d029ba6..92acce377253 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -17,6 +17,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include 
 #include 
 #include "adreno_gpu.h"
 #include "msm_gem.h"
@@ -383,10 +384,30 @@ struct msm_gpu_state *adreno_gpu_state_get(struct msm_gpu 
*gpu)
do_gettimeofday(&state->time);
 
for (i = 0; i < gpu->nr_rings; i++) {
+   int size = 0, j;
+
state->ring[i].fence = gpu->rb[i]->memptrs->fence;
state->ring[i].seqno = gpu->rb[i]->seqno;
state->ring[i].rptr = get_rptr(adreno_gpu, gpu->rb[i]);
state->ring[i].wptr = get_wptr(gpu->rb[i]);
+
+   /*
+* Only copy used parts of the ring buffers (this should save
+* data size for lightly used rings)
+*/
+   for (j = 0; j < MSM_GPU_RINGBUFFER_SZ >> 2; j++)
+   if (gpu->rb[i]->start[j])
+   size = j;
+
+   if (size) {
+   state->ring[i].data = kmalloc((size + 1) << 2,
+   GFP_KERNEL);
+   if (state->ring[i].data) {
+   memcpy(state->ring[i].data, gpu->rb[i]->start,
+   (size + 1) << 2);
+   state->ring[i].data_size = (size + 1) << 2;
+   }
+   }
}
 
/* Count the number of registers */
@@ -417,9 +438,13 @@ struct msm_gpu_state *adreno_gpu_state_get(struct msm_gpu 
*gpu)
 
 static void adreno_gpu_state_destroy(struct kref *kref)
 {
+   int i;
struct msm_gpu_state *state = container_of(kref,
struct msm_gpu_state, ref);
 
+   for (i = 0; i < ARRAY_SIZE(state->ring); i++)
+   kfree(state->ring[i].data);
+
kfree(state->comm);
kfree(state->cmd);
kfree(state->registers);
@@ -459,6 +484,22 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state 
*state,
drm_printf(p, "retired-fence: %d\n", state->ring[i].fence);
drm_printf(p, "rptr: %d\n", state->ring[i].rptr);
drm_printf(p, "wptr: %d\n", state->ring[i].wptr);
+   drm_printf(p, "size: %d\n", MSM_GPU_RINGBUFFER_SZ);
+
+   if (state->ring[i].data && state->ring[i].data_size) {
+   u32 *ptr = (u32 *) state->ring[i].data;
+   char out[ASCII85_BUFSZ];
+   long len = ascii85_encode_len(state->ring[i].data_size);
+   int j;
+
+   drm_printf(p, "data: !!ascii85 |\n");
+   drm_printf(p, " ");
+
+   for (j = 0; j < len; j++)
+   drm_printf(p, ascii85_encode(ptr[j], out));
+
+   drm_printf(p, "\n");
+   }
}
 
drm_puts(p, "registers:\n");
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/ms

[Freedreno] [PATCH 12/13] drm/msm/adreno: Add a5xx specific registers for the GPU state

2018-06-29 Thread Jordan Crouse
HLSQ, SP and TP registers are only accessible from a special
aperture and to make matters worse the aperture is blocked from
the CPU on targets that can support secure rendering. Luckily the
GPU hardware has its own purpose built register dumper that can
access the registers from the aperture. Add a5xx specific code
to program the crashdumper and retrieve the wayward registers
and dump them for the crash state.

Also, remove a block of registers the regular CPU accessible
list that aren't useful for debug which helps reduce the size
of the crash state file by a goodly amount.

Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/msm/adreno/a3xx_gpu.c   |   8 +-
 drivers/gpu/drm/msm/adreno/a4xx_gpu.c   |   8 +-
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c   | 236 ++--
 drivers/gpu/drm/msm/adreno/adreno_gpu.c |  23 +--
 drivers/gpu/drm/msm/adreno/adreno_gpu.h |   4 +-
 5 files changed, 248 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index fc502e412132..669c2d4b070d 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -421,10 +421,12 @@ static void a3xx_dump(struct msm_gpu *gpu)
 
 static struct msm_gpu_state *a3xx_gpu_state_get(struct msm_gpu *gpu)
 {
-   struct msm_gpu_state *state = adreno_gpu_state_get(gpu);
+   struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
 
-   if (IS_ERR(state))
-   return state;
+   if (!state)
+   return ERR_PTR(-ENOMEM);
+
+   adreno_gpu_state_get(gpu, state);
 
state->rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS);
 
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 8129cf037db1..7c4e6dc1ed59 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -457,10 +457,12 @@ static const unsigned int a4xx_registers[] = {
 
 static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu)
 {
-   struct msm_gpu_state *state = adreno_gpu_state_get(gpu);
+   struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
 
-   if (IS_ERR(state))
-   return state;
+   if (!state)
+   return ERR_PTR(-ENOMEM);
+
+   adreno_gpu_state_get(gpu, state);
 
state->rbbm_status = gpu_read(gpu, REG_A4XX_RBBM_STATUS);
 
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 16074fa6bf1e..bd84f71d27d8 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "msm_gem.h"
 #include "msm_mmu.h"
 #include "a5xx_gpu.h"
@@ -1123,8 +1124,9 @@ static const u32 a5xx_registers[] = {
0xE800, 0xE806, 0xE810, 0xE89A, 0xE8A0, 0xE8A4, 0xE8AA, 0xE8EB,
0xE900, 0xE905, 0xEB80, 0xEB8F, 0xEBB0, 0xEBB0, 0xEC00, 0xEC05,
0xEC08, 0xECE9, 0xECF0, 0xECF0, 0xEA80, 0xEA80, 0xEA82, 0xEAA3,
-   0xEAA5, 0xEAC2, 0xA800, 0xA8FF, 0xAC60, 0xAC60, 0xB000, 0xB97F,
-   0xB9A0, 0xB9BF, ~0
+   0xEAA5, 0xEAC2, 0xA800, 0xA800, 0xA820, 0xA828, 0xA840, 0xA87D,
+   0XA880, 0xA88D, 0xA890, 0xA8A3, 0xA8D0, 0xA8D8, 0xA8E0, 0xA8F5,
+   0xAC60, 0xAC60, ~0,
 };
 
 static void a5xx_dump(struct msm_gpu *gpu)
@@ -1195,25 +1197,233 @@ static int a5xx_get_timestamp(struct msm_gpu *gpu, 
uint64_t *value)
return 0;
 }
 
+struct a5xx_crashdumper {
+   void *ptr;
+   struct drm_gem_object *bo;
+   u64 iova;
+};
+
+struct a5xx_gpu_state {
+   struct msm_gpu_state base;
+   u32 *hlsqregs;
+};
+
+#define gpu_poll_timeout(gpu, addr, val, cond, interval, timeout) \
+   readl_poll_timeout((gpu)->mmio + ((addr) << 2), val, cond, \
+   interval, timeout)
+
+static int a5xx_crashdumper_init(struct msm_gpu *gpu,
+   struct a5xx_crashdumper *dumper)
+{
+   dumper->ptr = msm_gem_kernel_new_locked(gpu->dev,
+   SZ_1M, MSM_BO_UNCACHED, gpu->aspace,
+   &dumper->bo, &dumper->iova);
+
+   if (IS_ERR(dumper->ptr))
+   return PTR_ERR(dumper->ptr);
+
+   return 0;
+}
+
+static void a5xx_crashdumper_free(struct msm_gpu *gpu,
+   struct a5xx_crashdumper *dumper)
+{
+   msm_gem_put_iova(dumper->bo, gpu->aspace);
+   msm_gem_put_vaddr(dumper->bo);
+
+   drm_gem_object_unreference(dumper->bo);
+}
+
+static int a5xx_crashdumper_run(struct msm_gpu *gpu,
+   struct a5xx_crashdumper *dumper)
+{
+   u32 val;
+
+   if (IS_ERR_OR_NULL(dumper->ptr))
+   return -EINVAL;
+
+   gpu_write64(gpu, REG_A5XX_CP_CRASH_SCRIPT_BASE_LO,
+   REG_A5XX_CP_CRASH_SCRIPT_BASE_HI, dumper->iova);
+
+   gpu_write(gpu, REG_A5XX_CP_CRASH_DUMP_CNTL, 1);
+
+   return gpu_poll_timeout(gpu, REG_A5XX_C

[Freedreno] [PATCH 10/13] drm/msm/adreno: Convert the show/crash file format

2018-06-29 Thread Jordan Crouse
Convert the format of the 'show' debugfs file and the crash
dump to a  format resembling YAML. This should be easier to
parse and be more flexible for future changes and expansions.

Signed-off-by: Jordan Crouse 
---
 Documentation/gpu/drm-msm-crash-dump.txt | 46 
 drivers/gpu/drm/msm/adreno/adreno_gpu.c  | 20 ++-
 2 files changed, 58 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/gpu/drm-msm-crash-dump.txt

diff --git a/Documentation/gpu/drm-msm-crash-dump.txt 
b/Documentation/gpu/drm-msm-crash-dump.txt
new file mode 100644
index ..930e4c970a62
--- /dev/null
+++ b/Documentation/gpu/drm-msm-crash-dump.txt
@@ -0,0 +1,46 @@
+# drm/msm GPU crash dump format
+#
+# This is a description of the format of the drm/msm GPU crash dump format that
+# can be read from /sys/kernel/dri/X/show or from devcoredump following a GPU
+# hang or fault
+
+---
+kernel:# [string] The kernel version as printed by UTS_RELEASE
+module:# [string] The module that generated the crash dump
+time:  # [seconds.microseconds] The kernel time at crash
+comm:  # [string] comm string for the binary that generated the fault
+   # (if known)
+cmdline:   # [string] the cmdline for the binary that generated the fault
+   # (if known)
+revision:  # [ id core.major.minor.patchlevel] The GPU id followed by the
+   # individual components of the id separated by dots
+rbbm-status:   # [hex] The current value of RBBM_STATUS which shows what GPU
+   # components were in use at the time of the crash
+ringbuffer:# Ringbuffer data. There will be a sequence for each ringbuffer
+  -id: # [decimal] Ringbuffer identifier (0 based index)
+   last-fence: # [decimal] The last fence issued on the ring
+   retired-fence:  # [decimal] THe last fence retired on the ring
+   rptr:   # [decimal] The current read pointer (rptr) for the ring
+   wptr:   # [decimal] The current write pointer (wptr) for the
+   # ring
+   size:   # [decimal] The maximum size of the ring programmed in
+   # the hardware
+   data:   # [ascii85] The contents of the ring encoded as ascii85.
+   # Only the unused portions of the ring will be printed
+   # (up to a maximum of 'size' bytes)
+bos:   # List of buffers from the hanging submission (if known)
+  -iova:   # [hex] GPU address of the buffer
+   size:   # [decimal] Size of the buffer (in bytes)
+   data:   # [ascii85] The contents of the buffer encoded as
+   # ascii85. Only the contents of buffers marked as
+   # readable are dumped. Trailing zeros at the end of the
+   # buffer won't be dumped.
+registers: # Sets of register values. This section can be used multiple
+   # times for different ranges of registers. Each register will be
+   # on its own line.
+  - [offset, value]# offset: [hex] byte offset of the register
+   # value: [hex] value of the register
+
+registers-hlsq: # (5xx only) Same format as registers. Register data that
+   # only accessible from the HLSQ aperture captured by the
+   # HW based crashdumper
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 163542487e2c..15fe0d029ba6 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -444,23 +444,27 @@ void adreno_show(struct msm_gpu *gpu, struct 
msm_gpu_state *state,
if (IS_ERR_OR_NULL(state))
return;
 
-   drm_printf(p, "status:   %08x\n", state->rbbm_status);
drm_printf(p, "revision: %d (%d.%d.%d.%d)\n",
adreno_gpu->info->revn, adreno_gpu->rev.core,
adreno_gpu->rev.major, adreno_gpu->rev.minor,
adreno_gpu->rev.patchid);
 
-   for (i = 0; i < gpu->nr_rings; i++) {
-   drm_printf(p, "rb %d: fence:%d/%d\n", i,
-   state->ring[i].fence, state->ring[i].seqno);
+   drm_printf(p, "rbbm-status: 0x%08x\n", state->rbbm_status);
+
+   drm_puts(p, "ringbuffer:\n");
 
-   drm_printf(p, "  rptr: %d\n", state->ring[i].rptr);
-   drm_printf(p, "rb wptr:  %d\n", state->ring[i].wptr);
+   for (i = 0; i < gpu->nr_rings; i++) {
+   drm_printf(p, "  - id: %d\n", i);
+   drm_printf(p, "last-fence: %d\n", state->ring[i].seqno);
+   drm_printf(p, "retired-fence: %d\n", state->ring[i].f

Re: [Freedreno] [PATCH] drm/msm/adreno: Remove VLA usage

2018-06-29 Thread Jordan Crouse
On Fri, Jun 29, 2018 at 10:47:31PM +0200, Arnd Bergmann wrote:
> On Fri, Jun 29, 2018 at 8:48 PM, Kees Cook  wrote:
> > In the quest to remove all stack VLA usage from the kernel[1], this
> > switches to using a kasprintf()ed buffer. Return paths are updated
> > to free the allocation.
> >
> > [1] 
> > https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qpxydaacu1rq...@mail.gmail.com
> >
> > Signed-off-by: Kees Cook 
> > ---
> >  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   |  7 +--
> >  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 28 +
> >  2 files changed, 24 insertions(+), 11 deletions(-)
> 
> This seems fine, though using a fixed-length string is probably just
> as well here,
> given that the 'fwname' variable is always set to the constant string
> "a530_zap.mdt"
> at the moment, which is not very long.

We could make it fixed but since this code is only called once this
feels safer.

Jordan

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH] drm/msm/adreno: Remove VLA usage

2018-06-29 Thread Jordan Crouse
On Fri, Jun 29, 2018 at 11:48:18AM -0700, Kees Cook wrote:
> In the quest to remove all stack VLA usage from the kernel[1], this
> switches to using a kasprintf()ed buffer. Return paths are updated
> to free the allocation.
> 
> [1] 
> https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qpxydaacu1rq...@mail.gmail.com

Thanks for doing this.

Acked-by: Jordan Crouse 

> Signed-off-by: Kees Cook 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   |  7 +--
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 28 +
>  2 files changed, 24 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index d39400e5bc42..f5f76f8151f9 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -11,6 +11,7 @@
>   *
>   */
>  
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -19,6 +20,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include "msm_gem.h"
>  #include "msm_mmu.h"
>  #include "a5xx_gpu.h"
> @@ -91,12 +93,13 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const 
> char *fwname)
>   ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID,
>   mem_region, mem_phys, mem_size, NULL);
>   } else {
> - char newname[strlen("qcom/") + strlen(fwname) + 1];
> + char *newname;
>  
> - sprintf(newname, "qcom/%s", fwname);
> + newname = kasprintf(GFP_KERNEL, "qcom/%s", fwname);
>  
>   ret = qcom_mdt_load(dev, fw, newname, GPU_PAS_ID,
>   mem_region, mem_phys, mem_size, NULL);
> + kfree(newname);
>   }
>   if (ret)
>   goto out;
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index bcbf9f2a29f9..bfaafdfc7eb2 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -17,7 +17,9 @@
>   * this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include 
>  #include 
> +#include 
>  #include "adreno_gpu.h"
>  #include "msm_gem.h"
>  #include "msm_mmu.h"
> @@ -70,10 +72,12 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const 
> char *fwname)
>  {
>   struct drm_device *drm = adreno_gpu->base.dev;
>   const struct firmware *fw = NULL;
> - char newname[strlen("qcom/") + strlen(fwname) + 1];
> + char *newname;
>   int ret;
>  
> - sprintf(newname, "qcom/%s", fwname);
> + newname = kasprintf(GFP_KERNEL, "qcom/%s", fwname);
> + if (!newname)
> + return ERR_PTR(-ENOMEM);
>  
>   /*
>* Try first to load from qcom/$fwfile using a direct load (to avoid
> @@ -87,11 +91,12 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const 
> char *fwname)
>   dev_info(drm->dev, "loaded %s from new location\n",
>   newname);
>   adreno_gpu->fwloc = FW_LOCATION_NEW;
> - return fw;
> + goto out;
>   } else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) {
>   dev_err(drm->dev, "failed to load %s: %d\n",
>   newname, ret);
> - return ERR_PTR(ret);
> + fw = ERR_PTR(ret);
> + goto out;
>   }
>   }
>  
> @@ -106,11 +111,12 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const 
> char *fwname)
>   dev_info(drm->dev, "loaded %s from legacy location\n",
>   newname);
>   adreno_gpu->fwloc = FW_LOCATION_LEGACY;
> - return fw;
> + goto out;
>   } else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) {
>   dev_err(drm->dev, "failed to load %s: %d\n",
>   fwname, ret);
> - return ERR_PTR(ret);
> + fw = ERR_PTR(ret);
> + goto out;
>   }
>   }
>  
> @@ -126,16 +132,20 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const 
> char *fwname)
>   dev_info(drm->dev, "loaded %s with helper\n",
>   newname);
>   adreno_gpu->fwloc = FW_LOCATION_HELPER;
> - 

Re: [Freedreno] [DPU PATCH 3/3] arm64: dts: qcom: sdm845: Add dpu to sdm845 dts file

2018-07-03 Thread Jordan Crouse
On Tue, Jul 03, 2018 at 03:48:12PM -0400, Sean Paul wrote:
> Signed-off-by: Sean Paul 
> ---
>  arch/arm64/boot/dts/qcom/sdm845.dtsi | 182 +++
>  1 file changed, 182 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi 
> b/arch/arm64/boot/dts/qcom/sdm845.dtsi
> index cdaabeb3c995..537269636b43 100644
> --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
> @@ -221,6 +221,188 @@
>   #interrupt-cells = <2>;
>   };
>  
> + mdss: mdss@ae0 {
> + compatible = "qcom,dpu-mdss";
> + reg = <0xae0 0x1000>;
> + reg-names = "mdss_phys";
> +
> + power-domains = <&clock_dispcc 0>;
> +
> + clocks = <&gcc GCC_DISP_AHB_CLK>,
> +  <&gcc GCC_DISP_AXI_CLK>,
> +  <&clock_dispcc DISP_CC_MDSS_MDP_CLK>;
> + clock-names = "iface_clk", "bus_clk", "core_clk";

Rob and others have pointed out correctly that the suffix (_clk/_irq/_reg)
is not necessary nor desirable for resource names. We've been slowly trying to
turn the tide downstream but a bunch of the sdm845 code will need fixing.



Jordan
-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [v7 00/13] drm/msm: Capture and dump the GPU crash state

2018-07-12 Thread Jordan Crouse
This is revision t implementing a GPU crash state for drm/msm
(https://patchwork.freedesktop.org/series/36097/). This patchset fixes a
few things that the build bot found.

The object of this code is to store and provide enough information to debug
software and hardware issues on the Adreno hardware in a semi human-readable
format that can also be parsed by scripts.

THe full set of changes here capture basic information about the GPU, the
status and contents of the ringbuffers, a snapshot of the current register state
and the active buffers from the hanging submit.

The data is printed with devcoredump.  For example, after a hang you can get
the data from /sys/class/devcoredump/devcdX/data where X is a unique number.

v7: Add EXPORT_SYMBOL for __drm_puts_coredump and use %zd to print a size_t
variable for the bo dump thanks to the ever vigilant zero one bot.
v6: Add drm_puts() and use it in the appropriate place.  Clean up a few minor
bugs here and there.
v5: Fix symbol error in i915_gpu_error.c thanks to 01 dot org bot. Added
open/release functions for the show debugfs file to get the state per Chris
Wilson. Slightly modified the register output format to be more YAML friendly
also per Chris.
v4: Add buffer dump for the active submit. Fix refcount issue with devcoredump.
Change header for a5xx registers to registers-hlsq because I'm told YAML
requires unique tags.
v3: Make recommended changes to ascii85 per Chris Wilson. Use devcoredump to
dump crash states as suggested by Bjorn Andersson and add a new drm_print
facility to facilitate that. Remove the now obsolete 'crash' debugfs node.
Add documentation for the crash dump output.
v2: Convert output to yaml, use ascii85 to dump ringbuffer contents.

Jordan Crouse (13):
  include: Move ascii85 functions from i915 to linux/ascii85.h
  drm: drm_printer: Add printer for devcoredump
  drm: Add drm_puts() to complement drm_printf()
  drm: Add a -puts() function for the seq_file printer
  drm: Add put callback for the coredump printer
  drm/msm/gpu: Capture the state of the GPU
  drm/msm/gpu: Convert the GPU show function to use the GPU state
  drm/msm/gpu: Rearrange the code that collects the task during a hang
  drm/msm/gpu: Capture the GPU state on a GPU hang
  drm/msm/adreno: Convert the show/crash file format
  drm/msm/adreno: Add ringbuffer data to the GPU state
  drm/msm/adreno: Add a5xx specific registers for the GPU state
  drm/msm/gpu: Add the buffer objects from the submit to the crash dump

 Documentation/gpu/drm-msm-crash-dump.txt |  58 ++
 drivers/gpu/drm/drm_print.c  | 132 +
 drivers/gpu/drm/i915/i915_gpu_error.c|  34 +---
 drivers/gpu/drm/msm/Kconfig  |   1 +
 drivers/gpu/drm/msm/adreno/a3xx_gpu.c|  30 +--
 drivers/gpu/drm/msm/adreno/a4xx_gpu.c|  22 ++-
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c| 242 +--
 drivers/gpu/drm/msm/adreno/adreno_gpu.c  | 184 +++--
 drivers/gpu/drm/msm/adreno/adreno_gpu.h  |  10 +-
 drivers/gpu/drm/msm/msm_debugfs.c|  93 -
 drivers/gpu/drm/msm/msm_gpu.c| 143 +-
 drivers/gpu/drm/msm/msm_gpu.h|  67 ++-
 include/drm/drm_print.h  |  33 
 include/linux/ascii85.h  |  39 
 14 files changed, 988 insertions(+), 100 deletions(-)
 create mode 100644 Documentation/gpu/drm-msm-crash-dump.txt
 create mode 100644 include/linux/ascii85.h

-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


[Freedreno] [PATCH 05/13] drm: Add put callback for the coredump printer

2018-07-12 Thread Jordan Crouse
Add a put function for the coredump printer to bypass printf()
for constant strings for a speed boost.

v2: Add EXPORT_SYMBOL for _drm_puts_coredump
Signed-off-by: Jordan Crouse 
---
 drivers/gpu/drm/drm_print.c | 43 +
 include/drm/drm_print.h |  2 ++
 2 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index bef8f0ec5d73..ff20f4a764c8 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -30,6 +30,49 @@
 #include 
 #include 
 
+void __drm_puts_coredump(struct drm_printer *p, const char *str)
+{
+   struct drm_print_iterator *iterator = p->arg;
+
+   ssize_t len;
+
+   if (!iterator->remain)
+   return;
+
+   if (iterator->offset < iterator->start) {
+   ssize_t copy;
+
+   len = strlen(str);
+
+   if (iterator->offset + len <= iterator->start) {
+   iterator->offset += len;
+   return;
+   }
+
+   copy = len - (iterator->start - iterator->offset);
+
+   if (copy > iterator->remain)
+   copy = iterator->remain;
+
+   /* Copy out the bit of the string that we need */
+   memcpy(iterator->data,
+   str + (iterator->start - iterator->offset), copy);
+
+   iterator->offset = iterator->start + copy;
+   iterator->remain -= copy;
+   } else {
+   ssize_t pos = iterator->offset - iterator->start;
+
+   len = min_t(ssize_t, strlen(str), iterator->remain);
+
+   memcpy(iterator->data + pos, str, len);
+
+   iterator->offset += len;
+   iterator->remain -= len;
+   }
+}
+EXPORT_SYMBOL(__drm_puts_coredump);
+
 void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
 {
struct drm_print_iterator *iterator = p->arg;
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index 3bc6ba4b7b2c..2a903ee7b428 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -75,6 +75,7 @@ struct drm_printer {
 };
 
 void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf);
+void __drm_puts_coredump(struct drm_printer *p, const char *str);
 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
 void __drm_puts_seq_file(struct drm_printer *p, const char *str);
 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
@@ -129,6 +130,7 @@ drm_coredump_printer(struct drm_print_iterator *iter)
 {
struct drm_printer p = {
.printfn = __drm_printfn_coredump,
+   .puts = __drm_puts_coredump,
.arg = iter,
};
return p;
-- 
2.17.1

___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


  1   2   3   4   5   6   7   8   9   10   >