Re: [Internet]Re: [PATCH] fbcon: Out-Of-Bounds write in sys_imageblit, add range check

2021-07-26 Thread gre...@linuxfoundation.org
On Tue, Jul 27, 2021 at 01:53:13AM +, tcs_kernel(腾讯云内核开发者) wrote:
> yres and vyres can be controlled by user mode paramaters, and cause p->vrows 
> to become a negative value. While this value be passed to real_y function, 
> the ypos will be out of screen range.
> This is an out-of-bounds write bug.
> I think updatescrollmode is the right place to validate values supplied by a 
> user ioctl, because only here makes --operation,and 0 is a legal value before 
> that.

Please wrap your changelog text.

> 
> Signed-off-by: Tencent Cloud System tcs_ker...@tencent.com

That is not the name of a person :(

And the format isn't correct, so there's nothing we can do with this
patch, and the patch itself is corrupted and could not be applied :(

Also, what about checking these values earlier?  How can the value be 0
earlier and be acceptable?  Putting bounds on the user-provided values
would be much easier, right?

thanks,

greg k-h


[PATCH] drm/pl111: Remove unused including

2021-07-26 Thread Cai Huoqing
Remove including  that don't need it.

Signed-off-by: Cai Huoqing 
---
 drivers/gpu/drm/pl111/pl111_display.c | 1 -
 drivers/gpu/drm/pl111/pl111_drv.c | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/pl111/pl111_display.c 
b/drivers/gpu/drm/pl111/pl111_display.c
index b5a8859739a2..443e3b932322 100644
--- a/drivers/gpu/drm/pl111/pl111_display.c
+++ b/drivers/gpu/drm/pl111/pl111_display.c
@@ -11,7 +11,6 @@
 
 #include 
 #include 
-#include 
 #include 
 #include 
 
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c 
b/drivers/gpu/drm/pl111/pl111_drv.c
index fa0a737e9dea..520301b405f1 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -44,7 +44,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include 
 #include 
-- 
2.25.1



[PATCH] efi: sysfb_efi: fix build when EFI is not set

2021-07-26 Thread Randy Dunlap
When # CONFIG_EFI is not set, there are 2 definitions of
sysfb_apply_efi_quirks(). The stub from sysfb.h should be used
and the __init function from sysfb_efi.c should not be used.

../drivers/firmware/efi/sysfb_efi.c:337:13: error: redefinition of 
‘sysfb_apply_efi_quirks’
 __init void sysfb_apply_efi_quirks(struct platform_device *pd)
 ^~
In file included from ../drivers/firmware/efi/sysfb_efi.c:26:0:
../include/linux/sysfb.h:65:20: note: previous definition of 
‘sysfb_apply_efi_quirks’ was here
 static inline void sysfb_apply_efi_quirks(struct platform_device *pd)
^~

Signed-off-by: Randy Dunlap 
Cc: Ard Biesheuvel 
Cc: linux-...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: Javier Martinez Canillas 
Cc: Thomas Zimmermann 
Cc: Mark Brown 
Cc: linux-n...@vger.kernel.org
---
 drivers/firmware/efi/sysfb_efi.c |2 ++
 1 file changed, 2 insertions(+)

--- linext-20210726.orig/drivers/firmware/efi/sysfb_efi.c
+++ linext-20210726/drivers/firmware/efi/sysfb_efi.c
@@ -332,6 +332,7 @@ static const struct fwnode_operations ef
.add_links = efifb_add_links,
 };
 
+#ifdef CONFIG_EFI
 static struct fwnode_handle efifb_fwnode;
 
 __init void sysfb_apply_efi_quirks(struct platform_device *pd)
@@ -354,3 +355,4 @@ __init void sysfb_apply_efi_quirks(struc
pd->dev.fwnode = _fwnode;
}
 }
+#endif


Re: [PATCH] drm/msm: Fix display fault handling

2021-07-26 Thread Bjorn Andersson
On Wed 07 Jul 11:01 PDT 2021, Rob Clark wrote:

> From: Rob Clark 
> 
> It turns out that when the display is enabled by the bootloader, we can
> get some transient iommu faults from the display.  Which doesn't go over
> too well when we install a fault handler that is gpu specific.  To avoid
> this, defer installing the fault handler until we get around to setting
> up per-process pgtables (which is adreno_smmu specific).  The arm-smmu
> fallback error reporting is sufficient for reporting display related
> faults (and in fact was all we had prior to f8f934c180f629bb927a04fd90d)
> 
> Reported-by: Dmitry Baryshkov 
> Reported-by: Yassine Oudjana 
> Fixes: 2a574cc05d38 ("drm/msm: Improve the a6xx page fault handler")
> Signed-off-by: Rob Clark 
> Tested-by: John Stultz 

Reviewed-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  drivers/gpu/drm/msm/msm_iommu.c | 11 ++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> index eed2a762e9dd..bcaddbba564d 100644
> --- a/drivers/gpu/drm/msm/msm_iommu.c
> +++ b/drivers/gpu/drm/msm/msm_iommu.c
> @@ -142,6 +142,9 @@ static const struct iommu_flush_ops null_tlb_ops = {
>   .tlb_add_page = msm_iommu_tlb_add_page,
>  };
>  
> +static int msm_fault_handler(struct iommu_domain *domain, struct device *dev,
> + unsigned long iova, int flags, void *arg);
> +
>  struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent)
>  {
>   struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(parent->dev);
> @@ -157,6 +160,13 @@ struct msm_mmu *msm_iommu_pagetable_create(struct 
> msm_mmu *parent)
>   if (!ttbr1_cfg)
>   return ERR_PTR(-ENODEV);
>  
> + /*
> +  * Defer setting the fault handler until we have a valid adreno_smmu
> +  * to avoid accidentially installing a GPU specific fault handler for
> +  * the display's iommu
> +  */
> + iommu_set_fault_handler(iommu->domain, msm_fault_handler, iommu);
> +
>   pagetable = kzalloc(sizeof(*pagetable), GFP_KERNEL);
>   if (!pagetable)
>   return ERR_PTR(-ENOMEM);
> @@ -300,7 +310,6 @@ struct msm_mmu *msm_iommu_new(struct device *dev, struct 
> iommu_domain *domain)
>  
>   iommu->domain = domain;
>   msm_mmu_init(>base, dev, , MSM_MMU_IOMMU);
> - iommu_set_fault_handler(domain, msm_fault_handler, iommu);
>  
>   atomic_set(>pagetables, 0);
>  
> -- 
> 2.31.1
> 


[PATCH 0/1] Increase timeout in i915_gem_contexts selftests

2021-07-26 Thread Matthew Brost
Patch says it all. Seeing a failure in CI [1] and locally on certain TGL
machines with GuC submission enabled. Let's fix this so we can enable CI
on TGL with GuC submission.

Signed-off-by: Matthew Brost 

[1] https://patchwork.freedesktop.org/series/92984/#rev4

Matthew Brost (1):
  drm/i915/selftests: Increase timeout in i915_gem_contexts selftests

 drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.28.0



[PATCH 1/1] drm/i915/selftests: Increase timeout in i915_gem_contexts selftests

2021-07-26 Thread Matthew Brost
Like in the case of several other selftests, generating lots of requests
in a loop takes a bit longer with GuC submission. Increase a timeout in
i915_gem_contexts selftest to take this into account.

Signed-off-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c 
b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
index 8eb5050f8cb3..4d2758718d21 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -94,7 +94,7 @@ static int live_nop_switch(void *arg)
rq = i915_request_get(this);
i915_request_add(this);
}
-   if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+   if (i915_request_wait(rq, 0, HZ) < 0) {
pr_err("Failed to populated %d contexts\n", nctx);
intel_gt_set_wedged(>gt);
i915_request_put(rq);
-- 
2.28.0



Re: [PATCH v1 1/5] dt-bindings: arm: mediatek: mmsys: add mt8195 SoC binding

2021-07-26 Thread Jason-JH Lin
Hi Enric,

On Mon, 2021-07-26 at 12:08 +0200, Enric Balletbo Serra wrote:
> Hi Jason,
> 
> Missatge de Jason-JH Lin  del dia dl., 26
> de jul. 2021 a les 9:02:
> > 
> > On Fri, 2021-07-23 at 13:13 +0200, Enric Balletbo Serra wrote:
> > > Hi Jason,
> > > 
> > > Thank you for your patch.
> > > 
> > > Missatge de jason-jh.lin  del dia dj.,
> > > 22
> > > de jul. 2021 a les 11:26:
> > > > 
> > > > There are 2 display hardware path in mt8195, namely vdosys0 and
> > > > vdosys1, so add their definition in mtk-mmsys documentation.
> > > > 
> > > 
> > > Just having 2 display hardware paths is not a reason to have two
> > > compatibles, isn't the IP block the same? Why do you need to
> > > introduce
> > > the two compatibles?
> > > 
> > > Thanks,
> > >   Enric
> > > 
> > 
> > Hi Enric,
> > 
> > Thanks for reviewing my patch.
> > 
> > The reason for using two compatibles is that vdosys0 and vdosys1
> > are
> > different IP blocks.
> > 
> 
> With that there are different IP blocks, what do you mean? Do you
> mean
> that there are two completely different blocks with completely
> different functionalities?
> 
> Or that there is the same IP block twice? I mean, of course, the
> registers are different but has exactly the same functionality.
> 

They are not the same IP block twice.
Although both vdosys0 and vdosys1 will probe meiatek-drm driver, but
the components on their hardware path are different and their output
panel are also different.

> > Because mmsys provides clock control, other display function blocks
> > may
> > use them as clock provider.
> > 
> > E.g.
> > 1. mmsys with compatible="mediatek,mt8195-vdosys0"
> > [v4,1/6] arm64: dts: mt8195: add display node for vdosys0
> > 
> > 
https://urldefense.com/v3/__https://patchwork.kernel.org/project/linux-mediatek/patch/20210723090233.24007-2-jason-jh@mediatek.com/__;!!CTRNKA9wMg0ARbw!xHjKwv34W7ETFcmQPXRViylF2LbV7C7pE8OeJeNvA93jDdzr_ZBRRm8aIUCvAHSD_qGo$
> >  
> > 
> > ovl0: disp_ovl@1c00 {
> > ...
> > clocks = < CLK_VDO0_DISP_OVL0>;
> > ...
> > };
> > 
> > 2. mmsys with compatible="mediatek,mt8195-vdosys1"
> > [v2,06/14] arm64: dts: mt8195: add display node for vdosys1
> > 
> > 
https://urldefense.com/v3/__https://patchwork.kernel.org/project/linux-mediatek/patch/20210722094551.15255-7-nancy@mediatek.com/__;!!CTRNKA9wMg0ARbw!xHjKwv34W7ETFcmQPXRViylF2LbV7C7pE8OeJeNvA93jDdzr_ZBRRm8aIUCvAP0FOfkc$
> >  
> > 
> > vdo1_rdma0: vdo1_rdma@1c104000 {
> > ...
> > clocks = < CLK_VDO1_MDP_RDMA0>;
> > ...
> > };
> > 
> 
> Note that I am talking without knowing the hardware in detail, but I
> am wondering why I can't have something like this, where every mmsys
> is a clock and reset controller provider.
> 
> vdosys0: syscon@1400 {
>   compatible = "mediatek,mt8195-mmsys", "syscon";
>   reg = <0 0x1400 0 0x1000>;
>   #clock-cells = <1>;
>   #reset-cells = <1>;
> };
> 
> vdosys1: syscon@1500 {
>   compatible = "mediatek,mt8195-mmsys", "syscon";
>   reg = <0 0x1500 0 0x1000>;
>   #clock-cells = <1>;
>   #reset-cells = <1>;
> };
> 
> ovl0: disp_ovl@1c00 {
> ...
>clocks = < CLK_VDO0_DISP_OVL0>;
> ...
> };
> 
> vdo1_rdma0: vdo1_rdma@1c104000 {
> ...
> clocks = < CLK_VDO1_MDP_RDMA0>;
> ...
> };
> 
> What are the differences between vdosys0 and vdosys1 from a hardware
> point of view?
> 
> Cheers,
>   Enric
> 
> > Regards,
> > Jason-JH.Lin
> > 

From a hardware point of view, the components and the ouptut panel of
vdosys0 and vdosys1:
1. The components on meiatek-drm of vdosys0 are OVL0, RDMA0, COLOR0,
CCORR, AAL0, GAMMA, DITHER, DSC0, MERGE0, DP_INTF0 and its output panel
is eDP.

2. The components on meiatek-drm of vdosys1 are PSEUDO_OVL, MERGE5,
DP_INTF1 and its ouptut panel is DP.


The resaon for using two compatibales is that we use different driver
data in mtk-mmsys.c and mtk_drm_drv.c to identify the corresponding 
mmsys is vdosys0 or vdosys1.

Their driver data in mtk_drm_drv.c is defined here:
[v4,4/6] drm/mediatek: add mediatek-drm of vdosys0 support for mt8195

https://patchwork.kernel.org/project/linux-mediatek/patch/20210723090233.24007-5-jason-jh@mediatek.com/
[v2,14/14] drm/mediatek: add mediatek-drm of vdosys1 support for MT8195

https://patchwork.kernel.org/project/linux-mediatek/patch/20210722094551.15255-15-nancy@mediatek.com/

I think using the same compatible is unable to do this. Or do you have
other suggestions to do this with the same compatibe?

Regards,
Jason-JH.Lin

> > > > Signed-off-by: jason-jh.lin 
> > > > ---
> > > > this patch is base on [1][2]
> > > > 
> > > > [1] dt-bindings: arm: mediatek: mmsys: convert to YAML format
> > > > -
> > > > 

[PATCH 2/2] drm/i915/uapi: Add query for hwconfig table

2021-07-26 Thread John . C . Harrison
From: Rodrigo Vivi 

GuC contains a consolidated table with a bunch of information about the
current device.

Previously, this information was spread and hardcoded to all the components
including GuC, i915 and various UMDs. The goal here is to consolidate
the data into GuC in a way that all interested components can grab the
very latest and synchronized information using a simple query.

As per most of the other queries, this one can be called twice.
Once with item.length=0 to determine the exact buffer size, then
allocate the user memory and call it again for to retrieve the
table data. For example:
  struct drm_i915_query_item item = {
.query_id = DRM_I915_QUERY_HWCONCFIG_TABLE;
  };
  query.items_ptr = (int64_t) 
  query.num_items = 1;

  ioctl(fd, DRM_IOCTL_I915_QUERY, query, sizeof(query));

  if (item.length <= 0)
return -ENOENT;

  data = malloc(item.length);
  item.data_ptr = (int64_t) 
  ioctl(fd, DRM_IOCTL_I915_QUERY, query, sizeof(query));

  // Parse the data as appropriate...

The returned array is a simple and flexible KLV (Key/Length/Value)
formatted table. For example, it could be just:
  enum device_attr {
 ATTR_SOME_VALUE = 0,
 ATTR_SOME_MASK  = 1,
  };

  static const u32 hwconfig[] = {
  ATTR_SOME_VALUE,
  1, // Value Length in DWords
  8, // Value

  ATTR_SOME_MASK,
  3,
  0x00, 0x, 0xFF00,
  };

The attribute ids are defined in a hardware spec.

Cc: Tvrtko Ursulin 
Cc: Kenneth Graunke 
Cc: Michal Wajdeczko 
Cc: Slawomir Milczarek 
Signed-off-by: Rodrigo Vivi 
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_query.c | 23 +++
 include/uapi/drm/i915_drm.h   |  1 +
 2 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_query.c 
b/drivers/gpu/drm/i915/i915_query.c
index e49da36c62fb..96bd8fb3e895 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -480,12 +480,35 @@ static int query_memregion_info(struct drm_i915_private 
*i915,
return total_length;
 }
 
+static int query_hwconfig_table(struct drm_i915_private *i915,
+   struct drm_i915_query_item *query_item)
+{
+   struct intel_gt *gt = >gt;
+   struct intel_guc_hwconfig *hwconfig = >uc.guc.hwconfig;
+
+   if (!hwconfig->size || !hwconfig->ptr)
+   return -ENODEV;
+
+   if (query_item->length == 0)
+   return hwconfig->size;
+
+   if (query_item->length < hwconfig->size)
+   return -EINVAL;
+
+   if (copy_to_user(u64_to_user_ptr(query_item->data_ptr),
+hwconfig->ptr, hwconfig->size))
+   return -EFAULT;
+
+   return hwconfig->size;
+}
+
 static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv,
struct drm_i915_query_item *query_item) 
= {
query_topology_info,
query_engine_info,
query_perf_config,
query_memregion_info,
+   query_hwconfig_table,
 };
 
 int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 975087553ea0..a47ac8d35a4a 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -2470,6 +2470,7 @@ struct drm_i915_query_item {
 #define DRM_I915_QUERY_ENGINE_INFO 2
 #define DRM_I915_QUERY_PERF_CONFIG  3
 #define DRM_I915_QUERY_MEMORY_REGIONS   4
+#define DRM_I915_QUERY_HWCONFIG_TABLE   5
 /* Must be kept compact -- no holes and well documented */
 
/**
-- 
2.25.1



[PATCH 0/2] Add support for querying hw info that UMDs need

2021-07-26 Thread John . C . Harrison
From: John Harrison 

Various UMDs require hardware configuration information about the
current platform. A bunch of static information is available in a
fixed table that can be retrieved from the GuC.

Test-with: 20210727002812.43469-2-john.c.harri...@intel.com
UMD: https://github.com/intel/compute-runtime/pull/432/files

Signed-off-by: John Harrison 


John Harrison (1):
  drm/i915/guc: Add fetch of hwconfig table

Rodrigo Vivi (1):
  drm/i915/uapi: Add query for hwconfig table

 drivers/gpu/drm/i915/Makefile |   1 +
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |   1 +
 .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h   |   4 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.c|   3 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   2 +
 .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.c   | 156 ++
 .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.h   |  19 +++
 drivers/gpu/drm/i915/gt/uc/intel_uc.c |   6 +
 drivers/gpu/drm/i915/i915_query.c |  23 +++
 include/uapi/drm/i915_drm.h   |   1 +
 10 files changed, 215 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h

-- 
2.25.1



[PATCH 1/2] drm/i915/guc: Add fetch of hwconfig table

2021-07-26 Thread John . C . Harrison
From: John Harrison 

Implement support for fetching the hardware description table from the
GuC. The call is made twice - once without a destination buffer to
query the size and then a second time to fill in the buffer.

Note that the table is only available on ADL-P and later platforms.

Cc: Michal Wajdeczko 
Signed-off-by: Rodrigo Vivi 
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |   1 +
 .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h   |   4 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.c|   3 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   2 +
 .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.c   | 156 ++
 .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.h   |  19 +++
 drivers/gpu/drm/i915/gt/uc/intel_uc.c |   6 +
 8 files changed, 191 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index bde3d4f462a9..bce7c597f1df 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -189,6 +189,7 @@ i915-y += gt/uc/intel_uc.o \
  gt/uc/intel_guc_log.o \
  gt/uc/intel_guc_log_debugfs.o \
  gt/uc/intel_guc_submission.o \
+ gt/uc/intel_guc_hwconfig.o \
  gt/uc/intel_huc.o \
  gt/uc/intel_huc_debugfs.o \
  gt/uc/intel_huc_fw.o
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h 
b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
index 57e18babdf4b..a66f50e22864 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
@@ -137,6 +137,7 @@ enum intel_guc_action {
INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003,
INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
+   INTEL_GUC_ACTION_GET_HWCONFIG = 0x4100,
INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502,
INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503,
INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505,
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h 
b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
index 488b6061ee89..f9e2a6aaef4a 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
@@ -8,6 +8,10 @@
 
 enum intel_guc_response_status {
INTEL_GUC_RESPONSE_STATUS_SUCCESS = 0x0,
+   INTEL_GUC_RESPONSE_NOT_SUPPORTED = 0x20,
+   INTEL_GUC_RESPONSE_NO_ATTRIBUTE_TABLE = 0x201,
+   INTEL_GUC_RESPONSE_NO_DECRYPTION_KEY = 0x202,
+   INTEL_GUC_RESPONSE_DECRYPTION_FAILED = 0x204,
INTEL_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000,
 };
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 6661dcb02239..e810b56c49f7 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -400,13 +400,14 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 
*request, u32 len,
/*
 * No GuC command should ever take longer than 10ms.
 * Fast commands should still complete in 10us.
+* Except for the hwconfig table query, which takes ~50ms.
 */
ret = __intel_wait_for_register_fw(uncore,
   guc_send_reg(guc, 0),
   GUC_HXG_MSG_0_ORIGIN,
   FIELD_PREP(GUC_HXG_MSG_0_ORIGIN,
  GUC_HXG_ORIGIN_GUC),
-  10, 10, );
+  10, 100, );
if (unlikely(ret)) {
 timeout:
drm_err(>drm, "mmio request %#x: no reply %x\n",
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index d4987cd789ea..b4ba0fa3fbb2 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -15,6 +15,7 @@
 #include "intel_guc_ct.h"
 #include "intel_guc_log.h"
 #include "intel_guc_reg.h"
+#include "intel_guc_hwconfig.h"
 #include "intel_uc_fw.h"
 #include "i915_utils.h"
 #include "i915_vma.h"
@@ -30,6 +31,7 @@ struct intel_guc {
struct intel_uc_fw fw;
struct intel_guc_log log;
struct intel_guc_ct ct;
+   struct intel_guc_hwconfig hwconfig;
 
/* Global engine used to submit requests to GuC */
struct i915_sched_engine *sched_engine;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c
new file mode 100644
index ..af4fc9fdbaaf
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include 

Re: [Internet]Re: [PATCH] fbcon: Out-Of-Bounds write in sys_imageblit, add range check

2021-07-26 Thread 腾讯云内核开发者
yres and vyres can be controlled by user mode paramaters, and cause p->vrows to 
become a negative value. While this value be passed to real_y function, the 
ypos will be out of screen range.
This is an out-of-bounds write bug.
I think updatescrollmode is the right place to validate values supplied by a 
user ioctl, because only here makes --operation,and 0 is a legal value before 
that.

Signed-off-by: Tencent Cloud System tcs_ker...@tencent.com

diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 22bb3892f6bd..0970de46782f 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -1956,11 +1956,12 @@ static void updatescrollmode(struct fbcon_display *p,
int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
   info->var.xres_virtual);
+   int rows = vc->vc_rows;
 
p->vrows = vyres/fh;
-   if (yres > (fh * (vc->vc_rows + 1)))
-   p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
-   if ((yres % fh) && (vyres % fh < yres % fh))
+   if ((yres > (fh * (rows + 1))) && (vyres >= (yres - (fh * rows))) && 
p->vrows)
+   p->vrows -= (yres - (fh * rows)) / fh;
+   if ((yres % fh) && (vyres % fh < yres % fh) && p->vrows)
p->vrows--;
 }

在 2021/7/26 21:45,“Sam Ravnborg” 写入:

Hi,
On Mon, Jul 26, 2021 at 11:32:37AM +, tcs_kernel(腾讯云内核开发者) wrote:
> yres and vyres can be controlled by user mode paramaters, and cause 
p->vrows to become a negative value. While this value be passed to real_y 
function, the ypos will be out of screen range.
> This is an out-of-bounds write bug.

Please investigate if you can validate the user-supplied values for yres
and vyres earlier so the code never reaches the below statements.
This would also make it much more explicit what is going on.

Sam

> 
> 
> diff --git a/drivers/video/fbdev/core/fbcon.c 
b/drivers/video/fbdev/core/fbcon.c
> index 22bb3892f6bd..0970de46782f 100644
> --- a/drivers/video/fbdev/core/fbcon.c
> +++ b/drivers/video/fbdev/core/fbcon.c
> @@ -1956,11 +1956,12 @@ static void updatescrollmode(struct fbcon_display 
*p,
> int yres = FBCON_SWAP(ops->rotate, info->var.yres, 
info->var.xres);
> int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
>info->var.xres_virtual);
> +   int rows = vc->vc_rows;
>  
> p->vrows = vyres/fh;
> -   if (yres > (fh * (vc->vc_rows + 1)))
> -   p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
> -   if ((yres % fh) && (vyres % fh < yres % fh))
> +   if ((yres > (fh * (rows + 1))) && (vyres >= (yres - (fh * rows))) 
&& p->vrows)
> +   p->vrows -= (yres - (fh * rows)) / fh;
> +   if ((yres % fh) && (vyres % fh < yres % fh) && p->vrows)
> p->vrows--;
>  }
> 




[PATCH v3] drm/dsi: Add _NO_ to MIPI_DSI_* flags disabling features

2021-07-26 Thread Nicolas Boichat
Many of the DSI flags have names opposite to their actual effects,
e.g. MIPI_DSI_MODE_EOT_PACKET means that EoT packets will actually
be disabled. Fix this by including _NO_ in the flag names, e.g.
MIPI_DSI_MODE_NO_EOT_PACKET.

Signed-off-by: Nicolas Boichat 
Reviewed-by: Linus Walleij 
Reviewed-by: Robert Foss 
Reviewed-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Xin Ji  # anx7625.c
Reviewed-by: Abhinav Kumar  # msm/dsi
---
I considered adding _DISABLE_ instead, but that'd make the
flag names a big too long.

Generated with:
flag=MIPI_DSI_MODE_VIDEO_HFP; git grep $flag | cut -f1 -d':' | \
  xargs -I{} sed -i -e "s/$flag/MIPI_DSI_MODE_VIDEO_NO_HFP/" {}
flag=MIPI_DSI_MODE_VIDEO_HBP; git grep $flag | cut -f1 -d':' | \
  xargs -I{} sed -i -e "s/$flag/MIPI_DSI_MODE_VIDEO_NO_HBP/" {}
flag=MIPI_DSI_MODE_VIDEO_HSA; git grep $flag | cut -f1 -d':' | \
  xargs -I{} sed -i -e "s/$flag/MIPI_DSI_MODE_VIDEO_NO_HSA/" {}
flag=MIPI_DSI_MODE_EOT_PACKET; git grep $flag | cut -f1 -d':' | \
  xargs -I{} sed -i -e "s/$flag/MIPI_DSI_MODE_NO_EOT_PACKET/" {}
(then minor format changes)

Changes in v3:
 - Added all R-b tags from v1 and v2 (hopefully didn't miss any).

Changes in v2:
 - Rebased on latest linux-next, after some of the flags got fixed
   (Linus Walleij).

 drivers/gpu/drm/bridge/adv7511/adv7533.c | 2 +-
 drivers/gpu/drm/bridge/analogix/anx7625.c| 2 +-
 drivers/gpu/drm/bridge/cdns-dsi.c| 4 ++--
 drivers/gpu/drm/bridge/lontium-lt8912b.c | 2 +-
 drivers/gpu/drm/bridge/tc358768.c| 2 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c  | 8 
 drivers/gpu/drm/mcde/mcde_dsi.c  | 2 +-
 drivers/gpu/drm/mediatek/mtk_dsi.c   | 4 ++--
 drivers/gpu/drm/msm/dsi/dsi_host.c   | 8 
 drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c | 2 +-
 drivers/gpu/drm/panel/panel-dsi-cm.c | 2 +-
 drivers/gpu/drm/panel/panel-elida-kd35t133.c | 2 +-
 drivers/gpu/drm/panel/panel-khadas-ts050.c   | 2 +-
 drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c   | 2 +-
 drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c   | 2 +-
 drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c   | 2 +-
 drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c | 2 +-
 drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c| 4 ++--
 drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c  | 2 +-
 drivers/gpu/drm/panel/panel-simple.c | 2 +-
 drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c | 2 +-
 include/drm/drm_mipi_dsi.h   | 8 
 22 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c 
b/drivers/gpu/drm/bridge/adv7511/adv7533.c
index aa19d5a40e31..59d718bde8c4 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c
@@ -165,7 +165,7 @@ int adv7533_attach_dsi(struct adv7511 *adv)
dsi->lanes = adv->num_dsi_lanes;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
+ MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
 
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index a3d82377066b..be987c836891 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -1307,7 +1307,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO   |
MIPI_DSI_MODE_VIDEO_SYNC_PULSE  |
-   MIPI_DSI_MODE_EOT_PACKET|
+   MIPI_DSI_MODE_NO_EOT_PACKET |
MIPI_DSI_MODE_VIDEO_HSE;
 
if (mipi_dsi_attach(dsi) < 0) {
diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c 
b/drivers/gpu/drm/bridge/cdns-dsi.c
index b31281f76117..e6e331071a00 100644
--- a/drivers/gpu/drm/bridge/cdns-dsi.c
+++ b/drivers/gpu/drm/bridge/cdns-dsi.c
@@ -829,7 +829,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
tmp = DIV_ROUND_UP(dsi_cfg.htotal, nlanes) -
  DIV_ROUND_UP(dsi_cfg.hsa, nlanes);
 
-   if (!(output->dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+   if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes);
 
tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
@@ -902,7 +902,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
tmp = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
tmp &= ~(IF_VID_SELECT_MASK | HOST_EOT_GEN | IF_VID_MODE);
 
-   if (!(output->dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+   if (!(output->dev->mode_flags & 

[PATCH 1/2] drm/i915/guc: Add fetch of hwconfig table

2021-07-26 Thread John . C . Harrison
From: John Harrison 

Implement support for fetching the hardware description table from the
GuC. The call is made twice - once without a destination buffer to
query the size and then a second time to fill in the buffer.

Note that the table is only available on ADL-P and later platforms.

Cc: Michal Wajdeczko 
Signed-off-by: Rodrigo Vivi 
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |   1 +
 .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h   |   4 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.c|   3 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   2 +
 .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.c   | 156 ++
 .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.h   |  19 +++
 drivers/gpu/drm/i915/gt/uc/intel_uc.c |   6 +
 8 files changed, 191 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index bde3d4f462a9..bce7c597f1df 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -189,6 +189,7 @@ i915-y += gt/uc/intel_uc.o \
  gt/uc/intel_guc_log.o \
  gt/uc/intel_guc_log_debugfs.o \
  gt/uc/intel_guc_submission.o \
+ gt/uc/intel_guc_hwconfig.o \
  gt/uc/intel_huc.o \
  gt/uc/intel_huc_debugfs.o \
  gt/uc/intel_huc_fw.o
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h 
b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
index 2d6198e63ebe..30c854c34d8f 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
@@ -126,6 +126,7 @@ enum intel_guc_action {
INTEL_GUC_ACTION_EXIT_S_STATE = 0x502,
INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003,
INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
+   INTEL_GUC_ACTION_GET_HWCONFIG = 0x4100,
INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505,
INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER = 0x4506,
INTEL_GUC_ACTION_LIMIT
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h 
b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
index 488b6061ee89..f9e2a6aaef4a 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
@@ -8,6 +8,10 @@
 
 enum intel_guc_response_status {
INTEL_GUC_RESPONSE_STATUS_SUCCESS = 0x0,
+   INTEL_GUC_RESPONSE_NOT_SUPPORTED = 0x20,
+   INTEL_GUC_RESPONSE_NO_ATTRIBUTE_TABLE = 0x201,
+   INTEL_GUC_RESPONSE_NO_DECRYPTION_KEY = 0x202,
+   INTEL_GUC_RESPONSE_DECRYPTION_FAILED = 0x204,
INTEL_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000,
 };
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 6661dcb02239..e810b56c49f7 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -400,13 +400,14 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 
*request, u32 len,
/*
 * No GuC command should ever take longer than 10ms.
 * Fast commands should still complete in 10us.
+* Except for the hwconfig table query, which takes ~50ms.
 */
ret = __intel_wait_for_register_fw(uncore,
   guc_send_reg(guc, 0),
   GUC_HXG_MSG_0_ORIGIN,
   FIELD_PREP(GUC_HXG_MSG_0_ORIGIN,
  GUC_HXG_ORIGIN_GUC),
-  10, 10, );
+  10, 100, );
if (unlikely(ret)) {
 timeout:
drm_err(>drm, "mmio request %#x: no reply %x\n",
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 72e4653222e2..5988d0311cfc 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -12,6 +12,7 @@
 #include "intel_guc_ct.h"
 #include "intel_guc_log.h"
 #include "intel_guc_reg.h"
+#include "intel_guc_hwconfig.h"
 #include "intel_uc_fw.h"
 #include "i915_utils.h"
 #include "i915_vma.h"
@@ -27,6 +28,7 @@ struct intel_guc {
struct intel_uc_fw fw;
struct intel_guc_log log;
struct intel_guc_ct ct;
+   struct intel_guc_hwconfig hwconfig;
 
/* intel_guc_recv interrupt related state */
spinlock_t irq_lock;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c
new file mode 100644
index ..af4fc9fdbaaf
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "gt/intel_gt.h"
+#include "i915_drv.h"
+#include 

[PATCH 2/2] drm/i915/uapi: Add query for hwconfig table

2021-07-26 Thread John . C . Harrison
From: Rodrigo Vivi 

GuC contains a consolidated table with a bunch of information about the
current device.

Previously, this information was spread and hardcoded to all the components
including GuC, i915 and various UMDs. The goal here is to consolidate
the data into GuC in a way that all interested components can grab the
very latest and synchronized information using a simple query.

As per most of the other queries, this one can be called twice.
Once with item.length=0 to determine the exact buffer size, then
allocate the user memory and call it again for to retrieve the
table data. For example:
  struct drm_i915_query_item item = {
.query_id = DRM_I915_QUERY_HWCONCFIG_TABLE;
  };
  query.items_ptr = (int64_t) 
  query.num_items = 1;

  ioctl(fd, DRM_IOCTL_I915_QUERY, query, sizeof(query));

  if (item.length <= 0)
return -ENOENT;

  data = malloc(item.length);
  item.data_ptr = (int64_t) 
  ioctl(fd, DRM_IOCTL_I915_QUERY, query, sizeof(query));

  // Parse the data as appropriate...

The returned array is a simple and flexible KLV (Key/Length/Value)
formatted table. For example, it could be just:
  enum device_attr {
 ATTR_SOME_VALUE = 0,
 ATTR_SOME_MASK  = 1,
  };

  static const u32 hwconfig[] = {
  ATTR_SOME_VALUE,
  1, // Value Length in DWords
  8, // Value

  ATTR_SOME_MASK,
  3,
  0x00, 0x, 0xFF00,
  };

The attribute ids are defined in a hardware spec.

Cc: Tvrtko Ursulin 
Cc: Kenneth Graunke 
Cc: Michal Wajdeczko 
Cc: Slawomir Milczarek 
Signed-off-by: Rodrigo Vivi 
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_query.c | 23 +++
 include/uapi/drm/i915_drm.h   |  1 +
 2 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_query.c 
b/drivers/gpu/drm/i915/i915_query.c
index e49da36c62fb..96bd8fb3e895 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -480,12 +480,35 @@ static int query_memregion_info(struct drm_i915_private 
*i915,
return total_length;
 }
 
+static int query_hwconfig_table(struct drm_i915_private *i915,
+   struct drm_i915_query_item *query_item)
+{
+   struct intel_gt *gt = >gt;
+   struct intel_guc_hwconfig *hwconfig = >uc.guc.hwconfig;
+
+   if (!hwconfig->size || !hwconfig->ptr)
+   return -ENODEV;
+
+   if (query_item->length == 0)
+   return hwconfig->size;
+
+   if (query_item->length < hwconfig->size)
+   return -EINVAL;
+
+   if (copy_to_user(u64_to_user_ptr(query_item->data_ptr),
+hwconfig->ptr, hwconfig->size))
+   return -EFAULT;
+
+   return hwconfig->size;
+}
+
 static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv,
struct drm_i915_query_item *query_item) 
= {
query_topology_info,
query_engine_info,
query_perf_config,
query_memregion_info,
+   query_hwconfig_table,
 };
 
 int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index e334a8b14ef2..841dfd8bc4e4 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -2328,6 +2328,7 @@ struct drm_i915_query_item {
 #define DRM_I915_QUERY_ENGINE_INFO 2
 #define DRM_I915_QUERY_PERF_CONFIG  3
 #define DRM_I915_QUERY_MEMORY_REGIONS   4
+#define DRM_I915_QUERY_HWCONFIG_TABLE   5
 /* Must be kept compact -- no holes and well documented */
 
/**
-- 
2.25.1



[PATCH 0/2] Add support for querying hw info that UMDs need

2021-07-26 Thread John . C . Harrison
From: John Harrison 

Various UMDs require hardware configuration information about the
current platform. A bunch of static information is available in a
fixed table that can be retrieved from the GuC.

Test-with: 20210727002812.43469-2-john.c.harri...@intel.com
UMD: https://github.com/intel/compute-runtime/pull/432/files

Signed-off-by: John Harrison 


John Harrison (1):
  drm/i915/guc: Add fetch of hwconfig table

Rodrigo Vivi (1):
  drm/i915/uapi: Add query for hwconfig table

 drivers/gpu/drm/i915/Makefile |   1 +
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |   1 +
 .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h   |   4 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.c|   3 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   2 +
 .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.c   | 156 ++
 .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.h   |  19 +++
 drivers/gpu/drm/i915/gt/uc/intel_uc.c |   6 +
 drivers/gpu/drm/i915/i915_query.c |  23 +++
 include/uapi/drm/i915_drm.h   |   1 +
 10 files changed, 215 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.h

-- 
2.25.1



[PATCH v4 3/4] drm/amd/display: Add control mechanism for FPU utilization

2021-07-26 Thread Rodrigo Siqueira
DC invokes DC_FPU_START/END in multiple parts of the code; this can
create a situation where we invoke this FPU operation in a nested way or
exit too early. For avoiding this situation, this commit adds a
mechanism where dc_fpu_begin/end manages the access to
kernel_fpu_begin/end.

Change since V3:
- Rebase

Change since V2:
- Christian: Do not use this_cpu_* between get/put_cpu_ptr().

Change since V1:
- Use a better variable names
- Use get_cpu_ptr and put_cpu_ptr to better balance preemption enable
and disable

Cc: Harry Wentland 
Cc: Anson Jacob 
Cc: Christian König 
Cc: Hersen Wu 
Cc: Aric Cyr 
Cc: Jun Lei 
Cc: Dmytro Laktyushkin 
Cc: Qingqing Zhuo 
Reported-by: kernel test robot 
Signed-off-by: Rodrigo Siqueira 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 13 ++--
 .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.c| 77 +--
 drivers/gpu/drm/amd/display/dc/dc_trace.h |  4 +-
 3 files changed, 63 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index 230bb12c405e..fdcaea22b456 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -638,23 +638,26 @@ TRACE_EVENT(amdgpu_refresh_rate_track,
 );
 
 TRACE_EVENT(dcn_fpu,
-   TP_PROTO(bool begin, const char *function, const int line),
-   TP_ARGS(begin, function, line),
+   TP_PROTO(bool begin, const char *function, const int line, const 
int recursion_depth),
+   TP_ARGS(begin, function, line, recursion_depth),
 
TP_STRUCT__entry(
 __field(bool, begin)
 __field(const char *, function)
 __field(int, line)
+__field(int, recursion_depth)
),
TP_fast_assign(
   __entry->begin = begin;
   __entry->function = function;
   __entry->line = line;
+  __entry->recursion_depth = recursion_depth;
),
-   TP_printk("%s()+%d: %s",
+   TP_printk("%s: recursion_depth: %d: %s()+%d:",
+ __entry->begin ? "begin" : "end",
+ __entry->recursion_depth,
  __entry->function,
- __entry->line,
- __entry->begin ? "begin" : "end"
+ __entry->line
)
 );
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index d4ab27bf8d04..33807d746e76 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -33,6 +33,19 @@
 #include 
 #endif
 
+/**
+ * DOC: DC FPU manipulation overview
+ *
+ * DC core uses FPU operations in multiple parts of the code, which requires a
+ * more specialized way to manage these areas' entrance. To fulfill this
+ * requirement, we created some wrapper functions that encapsulate
+ * kernel_fpu_begin/end to better fit our need in the display component. In
+ * summary, in this file, you can find functions related to FPU operation
+ * management.
+ */
+
+static DEFINE_PER_CPU(int, fpu_recursion_depth);
+
 /**
  * dc_fpu_begin - Enables FPU protection
  * @function_name: A string containing the function name for debug purposes
@@ -48,22 +61,30 @@
  */
 void dc_fpu_begin(const char *function_name, const int line)
 {
-   TRACE_DCN_FPU(true, function_name, line);
+   int *pcpu;
+
+   pcpu = get_cpu_ptr(_recursion_depth);
+   *pcpu += 1;
 
+   if (*pcpu == 1) {
 #if defined(CONFIG_X86)
-   kernel_fpu_begin();
+   kernel_fpu_begin();
 #elif defined(CONFIG_PPC64)
-   if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
-   preempt_disable();
-   enable_kernel_vsx();
-   } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
-   preempt_disable();
-   enable_kernel_altivec();
-   } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
-   preempt_disable();
-   enable_kernel_fp();
-   }
+   if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
+   preempt_disable();
+   enable_kernel_vsx();
+   } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
+   preempt_disable();
+   enable_kernel_altivec();
+   } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
+   preempt_disable();
+   enable_kernel_fp();
+   }
 #endif
+   }
+
+   TRACE_DCN_FPU(true, function_name, line, *pcpu);
+   put_cpu_ptr(_recursion_depth);
 }
 
 /**
@@ -78,19 +99,27 @@ void dc_fpu_begin(const char *function_name, const int line)
  */
 void dc_fpu_end(const char *function_name, const int line)
 

[PATCH v4 1/4] drm/amd/display: Move specific DCN2x code that uses FPU to DML

2021-07-26 Thread Rodrigo Siqueira
The display core files rely on FPU, which requires to be compiled with
special flags. Ideally, we don't want these FPU operations spread around
the DC code; nevertheless, it happens in the current source. This commit
introduces a new directory inside DML for centralizing shared DCN
functions that require FPU and have been used outside DML. For
illustrating this process of transferring FPU functions to the DML
folder, this commit moves one of the functions
dcn20_populate_dml_writeback_from_context) that require FPU access to a
single shared file. Notice that this is the first part of the work, and
it does not fix the FPU issue yet; we still need other patches for
achieving the complete FPU isolation.

Changes since V3:
- Jun: Instead of creating a new directory to keep the FPU code, let's
make the DML folder the only part that requires FPU access. Drop
fpu_operation folder.
- Christian: Fix function code style.

Changes since V2:
- Christian: Remove unnecessary wrapper.
- lkp: Add missing prototype.
- Only compile the FPU operations if the DCN option is enabled.

Change since V1:
- Update documentation and rebase.

Cc: Harry Wentland 
Cc: Anson Jacob 
Cc: Christian König 
Cc: Hersen Wu 
Cc: Aric Cyr 
Cc: Jun Lei 
Cc: Dmytro Laktyushkin 
Cc: Qingqing Zhuo 
Reported-by: kernel test robot 
Signed-off-by: Rodrigo Siqueira 
---
 .../drm/amd/display/dc/dcn20/dcn20_resource.c | 39 +
 .../drm/amd/display/dc/dcn20/dcn20_resource.h |  2 -
 .../drm/amd/display/dc/dcn21/dcn21_resource.c |  2 +
 drivers/gpu/drm/amd/display/dc/dml/Makefile   |  4 +
 .../gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c  | 84 +++
 .../gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h  | 34 
 6 files changed, 126 insertions(+), 39 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index 0b1cd1dbed8b..988d7c02199c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -35,6 +35,8 @@
 #include "include/irq_service_interface.h"
 #include "dcn20/dcn20_resource.h"
 
+#include "dml/dcn2x/dcn2x.h"
+
 #include "dcn10/dcn10_hubp.h"
 #include "dcn10/dcn10_ipp.h"
 #include "dcn20_hubbub.h"
@@ -1974,43 +1976,6 @@ void dcn20_split_stream_for_mpc(
ASSERT(primary_pipe->plane_state);
 }
 
-void dcn20_populate_dml_writeback_from_context(
-   struct dc *dc, struct resource_context *res_ctx, 
display_e2e_pipe_params_st *pipes)
-{
-   int pipe_cnt, i;
-
-   for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
-   struct dc_writeback_info *wb_info = 
_ctx->pipe_ctx[i].stream->writeback_info[0];
-
-   if (!res_ctx->pipe_ctx[i].stream)
-   continue;
-
-   /* Set writeback information */
-   pipes[pipe_cnt].dout.wb_enable = (wb_info->wb_enabled == true) 
? 1 : 0;
-   pipes[pipe_cnt].dout.num_active_wb++;
-   pipes[pipe_cnt].dout.wb.wb_src_height = 
wb_info->dwb_params.cnv_params.crop_height;
-   pipes[pipe_cnt].dout.wb.wb_src_width = 
wb_info->dwb_params.cnv_params.crop_width;
-   pipes[pipe_cnt].dout.wb.wb_dst_width = 
wb_info->dwb_params.dest_width;
-   pipes[pipe_cnt].dout.wb.wb_dst_height = 
wb_info->dwb_params.dest_height;
-   pipes[pipe_cnt].dout.wb.wb_htaps_luma = 1;
-   pipes[pipe_cnt].dout.wb.wb_vtaps_luma = 1;
-   pipes[pipe_cnt].dout.wb.wb_htaps_chroma = 
wb_info->dwb_params.scaler_taps.h_taps_c;
-   pipes[pipe_cnt].dout.wb.wb_vtaps_chroma = 
wb_info->dwb_params.scaler_taps.v_taps_c;
-   pipes[pipe_cnt].dout.wb.wb_hratio = 1.0;
-   pipes[pipe_cnt].dout.wb.wb_vratio = 1.0;
-   if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
-   if (wb_info->dwb_params.output_depth == 
DWB_OUTPUT_PIXEL_DEPTH_8BPC)
-   pipes[pipe_cnt].dout.wb.wb_pixel_format = 
dm_420_8;
-   else
-   pipes[pipe_cnt].dout.wb.wb_pixel_format = 
dm_420_10;
-   } else
-   pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_444_32;
-
-   pipe_cnt++;
-   }
-
-}
-
 int dcn20_populate_dml_pipes_from_context(
struct dc *dc,
struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
index c8f3127bbcdf..6ec8ff45f0f7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
@@ -58,8 +58,6 @@ struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer(
struct dc_state *state,
const 

[PATCH v4 4/4] drm/amd/display: Add DC_FP helper to check FPU state

2021-07-26 Thread Rodrigo Siqueira
To fully isolate FPU operations in a single place, we must avoid
situations where compilers spill FP values to registers due to FP enable
in a specific C file. Note that even if we isolate all FPU functions in
a single file and call its interface from other files, the compiler
might enable the use of FPU before we call DC_FP_START. Nevertheless, it
is the programmer's responsibility to invoke DC_FP_START/END in the
correct place. To highlight situations where developers forgot to use
the FP protection before calling the DC FPU interface functions, we
introduce a helper that checks if the function is invoked under FP
protection. If not, it will trigger a kernel warning.

Changes cince V3:
- Rebase

Changes cince V2 (Christian):
- Do not use this_cpu_* between get/put_cpu_ptr().
- In the kernel documentation, better describe restrictions.
- Make dc_assert_fp_enabled trigger the ASSERT message.

Changes since V1:
- Remove fp_enable variables
- Rename dc_is_fp_enabled to dc_assert_fp_enabled
- Replace wrong variable type

Cc: Harry Wentland 
Cc: Anson Jacob 
Cc: Christian König 
Cc: Hersen Wu 
Cc: Aric Cyr 
Cc: Jun Lei 
Cc: Dmytro Laktyushkin 
Cc: Qingqing Zhuo 
Reported-by: kernel test robot 
Signed-off-by: Rodrigo Siqueira 
---
 .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.c| 19 +++
 .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.h|  1 +
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |  2 ++
 .../gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c  | 18 ++
 4 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index 33807d746e76..c9f47d167472 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -46,6 +46,25 @@
 
 static DEFINE_PER_CPU(int, fpu_recursion_depth);
 
+/**
+ * dc_assert_fp_enabled - Check if FPU protection is enabled
+ *
+ * This function tells if the code is already under FPU protection or not. A
+ * function that works as an API for a set of FPU operations can use this
+ * function for checking if the caller invoked it after DC_FP_START(). For
+ * example, take a look at dcn2x.c file.
+ */
+inline void dc_assert_fp_enabled(void)
+{
+   int *pcpu, depth = 0;
+
+   pcpu = get_cpu_ptr(_recursion_depth);
+   depth = *pcpu;
+   put_cpu_ptr(_recursion_depth);
+
+   ASSERT(depth > 1);
+}
+
 /**
  * dc_fpu_begin - Enables FPU protection
  * @function_name: A string containing the function name for debug purposes
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
index fb54983c5c60..b8275b397920 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
@@ -27,6 +27,7 @@
 #ifndef __DC_FPU_H__
 #define __DC_FPU_H__
 
+void dc_assert_fp_enabled(void);
 void dc_fpu_begin(const char *function_name, const int line);
 void dc_fpu_end(const char *function_name, const int line);
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index 988d7c02199c..e3e01b17c164 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -2357,7 +2357,9 @@ int dcn20_populate_dml_pipes_from_context(
}
 
/* populate writeback information */
+   DC_FP_START();
dc->res_pool->funcs->populate_dml_writeback_from_context(dc, res_ctx, 
pipes);
+   DC_FP_END();
 
return pipe_cnt;
 }
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c
index 8f0f6220327d..c58522436291 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c
@@ -43,6 +43,22 @@
  *that deals with FP register is contained within this call.
  * 3. All function that needs to be accessed outside this file requires a
  *public interface that not uses any FPU reference.
+ * 4. Developers **must not** use DC_FP_START/END in this file, but they need
+ *to ensure that the caller invokes it before access any function available
+ *in this file. For this reason, public functions in this file must invoke
+ *dc_assert_fp_enabled();
+ *
+ * Let's expand a little bit more the idea in the code pattern. To fully
+ * isolate FPU operations in a single place, we must avoid situations where
+ * compilers spill FP values to registers due to FP enable in a specific C
+ * file. Note that even if we isolate all FPU functions in a single file and
+ * call its interface from other files, the compiler might enable the use of
+ * FPU before we call DC_FP_START. Nevertheless, it is the programmer's
+ * responsibility to invoke DC_FP_START/END in the correct place. To highlight
+ * situations where developers forgot to use the FP protection before calling
+ * the DC FPU interface 

[PATCH v4 2/4] drm/amd/display: Add control mechanism for FPU

2021-07-26 Thread Rodrigo Siqueira
DC invokes DC_FPU_START/END in multiple parts of the code; this can
create a situation where we invoke this FPU operation in a nested way or
exit too early. For avoiding this situation, this commit adds a
mechanism where dc_fpu_begin/end manages the access to
kernel_fpu_begin/end.

Change since V3:
- Christian: Move PPC64 code to dc_fpu_begin/end.

Change since V2:
- Christian: Do not use this_cpu_* between get/put_cpu_ptr().

Change since V1:
- Use a better variable names
- Use get_cpu_ptr and put_cpu_ptr to better balance preemption enable
and disable

Cc: Harry Wentland 
Cc: Anson Jacob 
Cc: Christian König 
Cc: Hersen Wu 
Cc: Aric Cyr 
Cc: Jun Lei 
Cc: Dmytro Laktyushkin 
Cc: Qingqing Zhuo 
Signed-off-by: Rodrigo Siqueira 
---
 .../gpu/drm/amd/display/amdgpu_dm/Makefile|  4 +
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 21 
 .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.c| 96 +++
 .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.h| 33 +++
 drivers/gpu/drm/amd/display/dc/dc_trace.h |  3 +
 drivers/gpu/drm/amd/display/dc/os_types.h | 35 +--
 6 files changed, 160 insertions(+), 32 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile 
b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index 91fb72c96545..718e123a3230 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -27,6 +27,10 @@
 
 AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o
 
+ifdef CONFIG_DRM_AMD_DC_DCN
+AMDGPUDM += dc_fpu.o
+endif
+
 ifneq ($(CONFIG_DRM_AMD_DC),)
 AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o 
amdgpu_dm_psr.o
 endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index 46a33f64cf8e..230bb12c405e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -637,6 +637,27 @@ TRACE_EVENT(amdgpu_refresh_rate_track,
  __entry->refresh_rate_ns)
 );
 
+TRACE_EVENT(dcn_fpu,
+   TP_PROTO(bool begin, const char *function, const int line),
+   TP_ARGS(begin, function, line),
+
+   TP_STRUCT__entry(
+__field(bool, begin)
+__field(const char *, function)
+__field(int, line)
+   ),
+   TP_fast_assign(
+  __entry->begin = begin;
+  __entry->function = function;
+  __entry->line = line;
+   ),
+   TP_printk("%s()+%d: %s",
+ __entry->function,
+ __entry->line,
+ __entry->begin ? "begin" : "end"
+   )
+);
+
 #endif /* _AMDGPU_DM_TRACE_H_ */
 
 #undef TRACE_INCLUDE_PATH
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
new file mode 100644
index ..d4ab27bf8d04
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * 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 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 HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dc_trace.h"
+
+#if defined(CONFIG_X86)
+#include 
+#elif defined(CONFIG_PPC64)
+#include 
+#include 
+#endif
+
+/**
+ * dc_fpu_begin - Enables FPU protection
+ * @function_name: A string containing the function name for debug purposes
+ *   (usually __func__)
+ *
+ * @line: A line number where DC_FP_START was invoked for debug purpose
+ *   (usually __LINE__)
+ *
+ * This function is responsible for managing the use of kernel_fpu_begin() with
+ * the advantage of providing an event trace 

[PATCH v4 0/4] drm/amd/display: Introduce FPU directory inside DC

2021-07-26 Thread Rodrigo Siqueira
 Hi,

In the display core, we utilize floats and doubles units for calculating
modesetting parameters. One side effect of our approach to use double-precision
is the fact that we spread multiple FPU access across our driver, which means
that we can accidentally clobber user space FPU state.

# Challenges

1. Keep in mind that this FPU code is ingrained in our display driver and
performs several crucial tasks. Additionally, we already have multiple
architectures available in the kernel and a large set of users; in other words,
we prefer to avoid a radical approach that might break our user's system.

2. We share our display code with other OSs; thus, we need to maintain the
interoperability between these two systems.

3. We need a mechanism for identifying which function uses FPU registers;
fortunately, Peter Zijlstra wrote a series a couple of months ago where he
introduced an FPU check for objtool. I used the following command for
identifying the potential FPU usage:

 ./tools/objtool/objtool check -Ffa "drivers/gpu/drm/amd/display/dc/ANY_FILE.o"

4. Since our code heavily relies on FPU and the fact that we spread
kernel_fpu_begin/end across multiple functions, we can have some complex
scenarios that will require code refactoring. However, we want to avoid
complicated changes since this is a formula to introduce regressions; we want
something that allows us to fix it in small, safe, and reliable steps.

5. Unfortunately, for legacy reasons, we have some problems in how we program
our FPU access, which in some weird scenarios can generate situations where we
try to enter in the fpu mode multiple times or exit too early.

# Our approach

For trying to solve this problem, we came up with the following strategy:

1. Keep in mind that we are using kernel_fpu_begin/end spread in various areas
and sometimes across multiple functions. If we try to move some of the
functions to an isolated place, we can generate a situation where we can call
the FPU protection more than once, causing multiple warnings. We can deal with
this problem by adding a thin management layer around the kernel_fpu_begin/end
used inside the display.

2. We will need a trace mechanism for this FPU management inside our display
code.

3. After we get the thin layer that manages FPU, we can start to move each
function that uses FPU to a centralized place. Our DQE runs multiple tests in
different ASICs every week; we can take advantage of this to ensure that our
FPU patches work does not introduce any regression. The idea is to work on a
specific part of the code every week (e.g., week 1: DCN2, week 1: DCN2.1,
etc.).

4. Finally, after we can isolate the FPU operations in a single place, we can
altogether remove the FPU flags from other files and eliminate an unnecessary
code introduced to deal with this problem. We can also remove the thin layer
added in the step 3.

# This series

To maintain the interoperability between multiple OSes, we already have a
define named DC_FP_START/END, which is a straightforward wrapper to
kernel_fpu_begin/end in the Linux side. In this series, I decided to expand the
scope of this DC_FP_* wrapper to trace FPU entrance and exit in the display
code, but I also add a mechanism for managing the entrance and exit of
kernel_fpu_begin/end. You can see the details on how I did that in the last two
patches.

I also isolate a simple function that requires FPU access to demonstrate my
strategy for isolating this FPU access in a single place. If this series gets
accepted, the following steps consist of moving all FPU functions weekly until
we isolate everything in the DML folder.

Cc: Harry Wentland 
Cc: Anson Jacob 
Cc: Christian König 
Cc: Hersen Wu 
Cc: Aric Cyr 
Cc: Jun Lei 
Cc: Dmytro Laktyushkin 
Cc: Qingqing Zhuo 

Change Since V3:
- Use DML as the FPU folder instead create a new folder
- Add a proper guard to x86 and PPC64

Change Since V2:
- Make sure to compile FPU operation only when DCN is enabled
  (officially, we only enable it for x86).
- Check cross-compile with ARM and x86_32. Everything looks fine.
- Avoid call this_cpu_* operations between get/put_cpu_ptr.
- Fix GCC warnings.
- Update documentation.
- Update our assert mechanism.
- Remove unnecessary wrappers.

Changes since V1:
- Use a better name for variables.
- Update documentation.
- Avoid preemption.

* See update details per commit message

Rodrigo Siqueira (4):
  drm/amd/display: Move specific DCN2x code that uses FPU to DML
  drm/amd/display: Add control mechanism for FPU
  drm/amd/display: Add control mechanism for FPU utilization
  drm/amd/display: Add DC_FP helper to check FPU state

 .../gpu/drm/amd/display/amdgpu_dm/Makefile|   4 +
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   |  24 +++
 .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.c| 144 ++
 .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.h|  34 +
 drivers/gpu/drm/amd/display/dc/dc_trace.h |   3 +
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |  41 +
 

Re: [RESEND PATCH v6 14/14] drm/print: Add tracefs support to the drm logging helpers

2021-07-26 Thread Rodrigo Siqueira
On 07/21, Sean Paul wrote:
> From: Sean Paul 
> 
> This patch adds a new module parameter called drm.trace which accepts
> the same mask as drm.debug. When a debug category is enabled, log
> messages will be put in a new tracefs instance called drm for
> consumption.
> 
> Using the new tracefs instance will allow distros to enable drm logging
> in production without impacting performance or spamming the system
> logs.
> 
> Cc: Daniel Vetter 
> Cc: David Airlie 
> Cc: Jani Nikula 
> Cc: Joonas Lahtinen 
> Cc: Pekka Paalanen 
> Cc: Rob Clark 
> Cc: Steven Rostedt 
> Cc: Thomas Zimmermann 
> Cc: Ville Syrjälä 
> Cc: Chris Wilson 
> Cc: Steven Rostedt 
> Reported-by: kernel test robot  # warning reported in v6
> Acked-by: Pekka Paalanen 
> Signed-off-by: Sean Paul 
> Link: 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.freedesktop.org%2Fpatch%2Fmsgid%2F20191010204823.195540-1-sean%40poorly.rundata=04%7C01%7CRodrigo.Siqueira%40amd.com%7Cbb3d63341a974f70c29208d94c70e119%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637624869979178761%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=NEMZqbDJcEq%2B5Ext3F3%2BLkLNe7JHFa7HNWozh5boJ9M%3Dreserved=0
>  #v1
> Link: 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Farchives%2Fdri-devel%2F2019-November%2F243230.htmldata=04%7C01%7CRodrigo.Siqueira%40amd.com%7Cbb3d63341a974f70c29208d94c70e119%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637624869979178761%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=nA9bS%2BIsuMxcqdTzf9aClkl3ovccPVnInyFyBpDT8Do%3Dreserved=0
>  #v2
> Link: 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.freedesktop.org%2Fpatch%2Fmsgid%2F20191212203301.142437-1-sean%40poorly.rundata=04%7C01%7CRodrigo.Siqueira%40amd.com%7Cbb3d63341a974f70c29208d94c70e119%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637624869979178761%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=Vz6I8SF%2BjoajAR48%2BzJmx6llQAHtww9VROLT4krkZK4%3Dreserved=0
>  #v3
> Link: 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.freedesktop.org%2Fpatch%2Fmsgid%2F20200114172155.215463-1-sean%40poorly.rundata=04%7C01%7CRodrigo.Siqueira%40amd.com%7Cbb3d63341a974f70c29208d94c70e119%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637624869979178761%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=Vcjao5eEZEE6o1Q%2B8CyIalz0UTAiqydOxR8qISbh61I%3Dreserved=0
>  #v4
> Link: 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.freedesktop.org%2Fpatch%2Fmsgid%2F20200608210505.48519-14-sean%40poorly.rundata=04%7C01%7CRodrigo.Siqueira%40amd.com%7Cbb3d63341a974f70c29208d94c70e119%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637624869979178761%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=rc1O7r2SQqR3I3Rn0bSRbS9mZBBH%2Fg7%2BEmGcLexheO0%3Dreserved=0
>  #v5
> Link: 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.freedesktop.org%2Fpatch%2Fmsgid%2F20200818210510.49730-15-sean%40poorly.rundata=04%7C01%7CRodrigo.Siqueira%40amd.com%7Cbb3d63341a974f70c29208d94c70e119%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637624869979178761%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=PblinqQ5Y8NgHJKGZ%2BwUU7hIlZHwiy0SOsXhB7NPegw%3Dreserved=0
>  #v6
> 
> Changes in v5:
> -Re-write to use trace_array and the tracefs instance support
> Changes in v6:
> -Use the new trace_array_init_printk() to initialize global trace
>  buffers
> Changes in v6.5:
> -Fix kernel test robot warning
> -Add a trace printf in __drm_err
> ---
>  Documentation/gpu/drm-uapi.rst |   6 +
>  drivers/gpu/drm/drm_drv.c  |   3 +
>  drivers/gpu/drm/drm_print.c| 223 -
>  include/drm/drm_print.h|  63 --
>  4 files changed, 255 insertions(+), 40 deletions(-)
> 
> diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
> index 7e51dd40bf6e..ce1ea39fb4b9 100644
> --- a/Documentation/gpu/drm-uapi.rst
> +++ b/Documentation/gpu/drm-uapi.rst
> @@ -424,6 +424,12 @@ Debugfs Support
>  .. kernel-doc:: drivers/gpu/drm/drm_debugfs.c
> :export:
>  
> +DRM Tracing
> +---
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_print.c
> +   :doc: DRM Tracing
> +
>  Sysfs Support
>  =
>  
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 8804ec7d3215..71dc0b161b51 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -1034,12 +1034,15 @@ static void drm_core_exit(void)
>   drm_sysfs_destroy();
>   idr_destroy(_minors_idr);
>   drm_connector_ida_destroy();
> + drm_trace_cleanup();
>  }
>  
>  static int __init 

Re: [PATCH v5] drm/msm/dp: add logs across DP driver for ease of debugging

2021-07-26 Thread maitreye

Thank you Stephen for reviewing.

On 2021-07-26 14:31, Stephen Boyd wrote:

Quoting maitreye (2021-07-26 10:36:26)
@@ -509,6 +515,7 @@ static int dp_display_usbpd_attention_cb(struct 
device *dev)

DRM_ERROR("invalid dev\n");
return -EINVAL;
}
+   DRM_DEBUG_DP("sink_request: %d\n", sink_request);


This one is bad. sink_request isn't assigned yet.


Yes, thank you will fix it


dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
@@ -523,6 +530,7 @@ static int dp_display_usbpd_attention_cb(struct 
device *dev)

rc = dp_link_process_request(dp->link);
if (!rc) {
sink_request = dp->link->sink_request;
+   DRM_DEBUG_DP("hpd_state=%d sink_count=%d\n", 
dp->hpd_state, sink_request);


Should that say sink_request?



Yes will fix this


if (sink_request & DS_PORT_STATUS_CHANGED)
rc = 
dp_display_handle_port_ststus_changed(dp);

else


[PATCH v6] drm/msm/dp: add logs across DP driver for ease of debugging

2021-07-26 Thread maitreye
From: Maitreyee Rao 

Add trace points across the MSM DP driver to help debug
interop issues.

Changes in v2:
 - Got rid of redundant log messages.
 - Added %#x instead of 0x%x wherever required.
 - Got rid of __func__ calls in debug messages.
 - Added newline wherever missing.

Changes in v3:
 - Got rid of redundant log messages.
 - Unstuck colon from printf specifier in various places.

Changes in v4:
 - Changed goto statement and used if else-if

Changes in v5:
 - Changed if else if statement,
   to not overwrite the ret variable multiple times.
Changes in v6:
 - Changed a wrong log message.
Signed-off-by: Maitreyee Rao 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c |  8 --
 drivers/gpu/drm/msm/dp/dp_ctrl.c|  5 +++-
 drivers/gpu/drm/msm/dp/dp_display.c | 13 ++
 drivers/gpu/drm/msm/dp/dp_link.c| 50 +
 drivers/gpu/drm/msm/dp/dp_power.c   |  3 +++
 5 files changed, 44 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 32f3575..958d3fa3 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -372,6 +372,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog 
*dp_catalog,
struct dp_catalog_private *catalog = container_of(dp_catalog,
struct dp_catalog_private, dp_catalog);
 
+   DRM_DEBUG_DP("enable=%d\n", enable);
if (enable) {
/*
 * To make sure link reg writes happens before other operation,
@@ -580,6 +581,7 @@ void dp_catalog_hpd_config_intr(struct dp_catalog 
*dp_catalog,
 
config = (en ? config | intr_mask : config & ~intr_mask);
 
+   DRM_DEBUG_DP("intr_mask=%#x config=%#x\n", intr_mask, config);
dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK,
config & DP_DP_HPD_INT_MASK);
 }
@@ -610,6 +612,7 @@ u32 dp_catalog_link_is_connected(struct dp_catalog 
*dp_catalog)
u32 status;
 
status = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
+   DRM_DEBUG_DP("aux status: %#x\n", status);
status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT;
status &= DP_DP_HPD_STATE_STATUS_BITS_MASK;
 
@@ -685,6 +688,7 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog 
*dp_catalog,
/* Make sure to clear the current pattern before starting a new one */
dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0);
 
+   DRM_DEBUG_DP("pattern: %#x\n", pattern);
switch (pattern) {
case DP_PHY_TEST_PATTERN_D10_2:
dp_write_link(catalog, REG_DP_STATE_CTRL,
@@ -745,7 +749,7 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog 
*dp_catalog,
DP_STATE_CTRL_LINK_TRAINING_PATTERN4);
break;
default:
-   DRM_DEBUG_DP("No valid test pattern requested:0x%x\n", pattern);
+   DRM_DEBUG_DP("No valid test pattern requested: %#x\n", pattern);
break;
}
 }
@@ -928,7 +932,7 @@ void dp_catalog_audio_config_acr(struct dp_catalog 
*dp_catalog)
select = dp_catalog->audio_data;
acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14);
 
-   DRM_DEBUG_DP("select = 0x%x, acr_ctrl = 0x%x\n", select, acr_ctrl);
+   DRM_DEBUG_DP("select: %#x, acr_ctrl: %#x\n", select, acr_ctrl);
 
dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl);
 }
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 2a8955c..72de71a 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -122,7 +122,7 @@ void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl)
IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES))
pr_warn("PUSH_IDLE pattern timedout\n");
 
-   pr_debug("mainlink off done\n");
+   DRM_DEBUG_DP("mainlink off done\n");
 }
 
 static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
@@ -1013,6 +1013,8 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private 
*ctrl)
u32 voltage_swing_level = link->phy_params.v_level;
u32 pre_emphasis_level = link->phy_params.p_level;
 
+   DRM_DEBUG_DP("voltage level: %d emphasis level: %d\n", 
voltage_swing_level,
+   pre_emphasis_level);
ret = dp_catalog_ctrl_update_vx_px(ctrl->catalog,
voltage_swing_level, pre_emphasis_level);
 
@@ -1384,6 +1386,7 @@ int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, 
bool reset)
if (reset)
dp_catalog_ctrl_reset(ctrl->catalog);
 
+   DRM_DEBUG_DP("flip=%d\n", flip);
dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_init(phy);
dp_catalog_ctrl_enable_irq(ctrl->catalog, true);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index cf9c645..bbd9541 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -275,6 +275,8 @@ 

Re: [PATCH v2] arm64: dts: qcom: sc7280: Add gpu support

2021-07-26 Thread Stephen Boyd
Quoting Akhil P Oommen (2021-07-24 10:29:00)
> Add the necessary dt nodes for gpu support in sc7280.
>
> Signed-off-by: Akhil P Oommen 
> ---
> This patch has dependency on the GPUCC bindings patch here:
> https://patchwork.kernel.org/project/linux-arm-msm/patch/1619519590-3019-4-git-send-email-t...@codeaurora.org/

To avoid the dependency the plain numbers can be used.

>
> Changes in v2:
> - formatting update and removed a duplicate header (Stephan)
>
>  arch/arm64/boot/dts/qcom/sc7280.dtsi | 116 
> +++
>  1 file changed, 116 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi 
> b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> index 029723a..524a5e0 100644
> --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> @@ -585,6 +586,121 @@
> #clock-cells = <1>;
> };
>
> +   gpu@3d0 {
> +   compatible = "qcom,adreno-635.0", "qcom,adreno";
> +   #stream-id-cells = <16>;
> +   reg = <0 0x03d0 0 0x4>,
> + <0 0x03d9e000 0 0x1000>,
> + <0 0x03d61000 0 0x800>;
> +   reg-names = "kgsl_3d0_reg_memory",
> +   "cx_mem",
> +   "cx_dbgc";
> +   interrupts = ;
> +   iommus = <_smmu 0 0x401>;
> +   operating-points-v2 = <_opp_table>;
> +   qcom,gmu = <>;
> +   interconnects = <_noc MASTER_GFX3D 0 _virt 
> SLAVE_EBI1 0>;
> +   interconnect-names = "gfx-mem";
> +
> +   gpu_opp_table: opp-table {
> +   compatible = "operating-points-v2";
> +
> +   opp-55000 {
> +   opp-hz = /bits/ 64 <55000>;
> +   opp-level = 
> ;
> +   opp-peak-kBps = <6832000>;
> +   };
> +
> +   opp-45000 {
> +   opp-hz = /bits/ 64 <45000>;
> +   opp-level = 
> ;
> +   opp-peak-kBps = <4068000>;
> +   };
> +
> +   opp-31500 {
> +   opp-hz = /bits/ 64 <31500>;
> +   opp-level = 
> ;
> +   opp-peak-kBps = <1804000>;
> +   };
> +   };
> +   };
> +
> +   gmu: gmu@3d69000 {
> +   compatible="qcom,adreno-gmu-635.0", "qcom,adreno-gmu";
> +   reg = <0 0x03d6a000 0 0x34000>,
> +   <0 0x3de 0 0x1>,
> +   <0 0x0b29 0 0x1>;
> +   reg-names = "gmu", "rscc", "gmu_pdc";
> +   interrupts = ,
> +   ;
> +   interrupt-names = "hfi", "gmu";
> +   clocks = < GPU_CC_CX_GMU_CLK>,
> +   < GPU_CC_CXO_CLK>,
> +   < GCC_DDRSS_GPU_AXI_CLK>,
> +   < GCC_GPU_MEMNOC_GFX_CLK>,
> +   < GPU_CC_AHB_CLK>,
> +   < GPU_CC_HUB_CX_INT_CLK>,
> +   < 
> GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>;
> +   clock-names = "gmu",
> + "cxo",
> + "axi",
> + "memnoc",
> + "ahb",
> + "hub",
> + "smmu_vote";
> +   power-domains = < GPU_CC_CX_GDSC>,
> +   < GPU_CC_GX_GDSC>;
> +   power-domain-names = "cx",
> +"gx";
> +   iommus = <_smmu 5 0x400>;
> +   operating-points-v2 = <_opp_table>;
> +
> +   gmu_opp_table: opp-table {
> +   compatible = "operating-points-v2";
> +
> +   opp-2 {
> +   opp-hz = /bits/ 64 <2>;
> +   opp-level = 
> ;
> +   };
> +   };
> +   };
> +
> +   adreno_smmu: iommu@3da {
> +   compatible = "qcom,sc7280-smmu-500", 
> "qcom,adreno-smmu", "arm,mmu-500";
> +  

[PATCH 16/33] drm/i915/guc: Don't complain about reset races

2021-07-26 Thread Matthew Brost
From: John Harrison 

It is impossible to seal all race conditions of resets occurring
concurrent to other operations. At least, not without introducing
excesive mutex locking. Instead, don't complain if it occurs. In
particular, don't complain if trying to send a H2G during a reset.
Whatever the H2G was about should get redone once the reset is over.

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 5 -
 drivers/gpu/drm/i915/gt/uc/intel_uc.c | 4 
 drivers/gpu/drm/i915/gt/uc/intel_uc.h | 2 ++
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
index 18917b443f05..22b4733b55e2 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
@@ -760,7 +760,10 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 
*action, u32 len,
int ret;
 
if (unlikely(!ct->enabled)) {
-   WARN(1, "Unexpected send: action=%#x\n", *action);
+   struct intel_guc *guc = ct_to_guc(ct);
+   struct intel_uc *uc = container_of(guc, struct intel_uc, guc);
+
+   WARN(!uc->reset_in_progress, "Unexpected send: action=%#x\n", 
*action);
return -ENODEV;
}
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index e07c989968f9..77c1fe2ed883 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -550,6 +550,8 @@ void intel_uc_reset_prepare(struct intel_uc *uc)
 {
struct intel_guc *guc = >guc;
 
+   uc->reset_in_progress = true;
+
/* Nothing to do if GuC isn't supported */
if (!intel_uc_supports_guc(uc))
return;
@@ -578,6 +580,8 @@ void intel_uc_reset_finish(struct intel_uc *uc)
 {
struct intel_guc *guc = >guc;
 
+   uc->reset_in_progress = false;
+
/* Firmware expected to be running when this function is called */
if (intel_guc_is_fw_running(guc) && intel_uc_uses_guc_submission(uc))
intel_guc_submission_reset_finish(guc);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
index eaa3202192ac..91315e3f1c58 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
@@ -30,6 +30,8 @@ struct intel_uc {
 
/* Snapshot of GuC log from last failed load */
struct drm_i915_gem_object *load_err_log;
+
+   bool reset_in_progress;
 };
 
 void intel_uc_init_early(struct intel_uc *uc);
-- 
2.28.0



[PATCH 19/33] drm/i915/guc: Fix for error capture after full GPU reset with GuC

2021-07-26 Thread Matthew Brost
From: John Harrison 

In the case of a full GPU reset (e.g. because GuC has died or because
GuC's hang detection has been disabled), the driver can't rely on GuC
reporting the guilty context. Instead, the driver needs to scan all
active contexts and find one that is currently executing, as per the
execlist mode behaviour. In GuC mode, this scan is different to
execlist mode as the active request list is handled very differently.

Similarly, the request state dump in debugfs needs to be handled
differently when in GuC submission mode.

Also refactured some of the request scanning code to avoid duplication
across the multiple code paths that are now replicating it.

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/intel_engine.h|   3 +
 drivers/gpu/drm/i915/gt/intel_engine_cs.c | 140 --
 .../gpu/drm/i915/gt/intel_engine_heartbeat.c  |   8 +
 drivers/gpu/drm/i915/gt/intel_reset.c |   2 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   2 +
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c |  67 +
 .../gpu/drm/i915/gt/uc/intel_guc_submission.h |   3 +
 drivers/gpu/drm/i915/i915_request.c   |  41 +
 drivers/gpu/drm/i915/i915_request.h   |  10 ++
 9 files changed, 229 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h 
b/drivers/gpu/drm/i915/gt/intel_engine.h
index 1db2d3efc71f..c2a5640ae055 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -240,6 +240,9 @@ __printf(3, 4)
 void intel_engine_dump(struct intel_engine_cs *engine,
   struct drm_printer *m,
   const char *header, ...);
+void intel_engine_dump_active_requests(struct list_head *requests,
+  struct i915_request *hung_rq,
+  struct drm_printer *m);
 
 ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine,
   ktime_t *now);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 0da7868c5a13..dea0e522c5c7 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -1684,6 +1684,98 @@ static void print_properties(struct intel_engine_cs 
*engine,
   read_ul(>defaults, p->offset));
 }
 
+static void engine_dump_request(struct i915_request *rq, struct drm_printer 
*m, const char *msg)
+{
+   struct intel_timeline *tl = get_timeline(rq);
+
+   i915_request_show(m, rq, msg, 0);
+
+   drm_printf(m, "\t\tring->start:  0x%08x\n",
+  i915_ggtt_offset(rq->ring->vma));
+   drm_printf(m, "\t\tring->head:   0x%08x\n",
+  rq->ring->head);
+   drm_printf(m, "\t\tring->tail:   0x%08x\n",
+  rq->ring->tail);
+   drm_printf(m, "\t\tring->emit:   0x%08x\n",
+  rq->ring->emit);
+   drm_printf(m, "\t\tring->space:  0x%08x\n",
+  rq->ring->space);
+
+   if (tl) {
+   drm_printf(m, "\t\tring->hwsp:   0x%08x\n",
+  tl->hwsp_offset);
+   intel_timeline_put(tl);
+   }
+
+   print_request_ring(m, rq);
+
+   if (rq->context->lrc_reg_state) {
+   drm_printf(m, "Logical Ring Context:\n");
+   hexdump(m, rq->context->lrc_reg_state, PAGE_SIZE);
+   }
+}
+
+void intel_engine_dump_active_requests(struct list_head *requests,
+  struct i915_request *hung_rq,
+  struct drm_printer *m)
+{
+   struct i915_request *rq;
+   const char *msg;
+   enum i915_request_state state;
+
+   list_for_each_entry(rq, requests, sched.link) {
+   if (rq == hung_rq)
+   continue;
+
+   state = i915_test_request_state(rq);
+   if (state < I915_REQUEST_QUEUED)
+   continue;
+
+   if (state == I915_REQUEST_ACTIVE)
+   msg = "\t\tactive on engine";
+   else
+   msg = "\t\tactive in queue";
+
+   engine_dump_request(rq, m, msg);
+   }
+}
+
+static void engine_dump_active_requests(struct intel_engine_cs *engine, struct 
drm_printer *m)
+{
+   struct i915_request *hung_rq = NULL;
+   struct intel_context *ce;
+   bool guc;
+
+   /*
+* No need for an engine->irq_seqno_barrier() before the seqno reads.
+* The GPU is still running so requests are still executing and any
+* hardware reads will be out of date by the time they are reported.
+* But the intention here is just to report an instantaneous snapshot
+* so that's fine.
+*/
+   lockdep_assert_held(>sched_engine->lock);
+
+   drm_printf(m, "\tRequests:\n");
+
+   guc = 

[PATCH 33/33] drm/i915/guc: Unblock GuC submission on Gen11+

2021-07-26 Thread Matthew Brost
From: Daniele Ceraolo Spurio 

Unblock GuC submission on Gen11+ platforms.

v2:
 (Martin Peres / John H)
  - Delete debug message when GuC is disabled by default on certain
platforms

Signed-off-by: Michal Wajdeczko 
Signed-off-by: Daniele Ceraolo Spurio 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|  1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c |  8 
 drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h |  3 +--
 drivers/gpu/drm/i915/gt/uc/intel_uc.c | 13 -
 4 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 8ab70a2223b0..a9547069ee7e 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -55,6 +55,7 @@ struct intel_guc {
struct ida guc_ids;
struct list_head guc_id_list;
 
+   bool submission_supported;
bool submission_selected;
 
struct i915_vma *ads_vma;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index b760cbf6ca0e..89ff0e4b4bc7 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -2543,6 +2543,13 @@ void intel_guc_submission_disable(struct intel_guc *guc)
/* Note: By the time we're here, GuC may have already been reset */
 }
 
+static bool __guc_submission_supported(struct intel_guc *guc)
+{
+   /* GuC submission is unavailable for pre-Gen11 */
+   return intel_guc_is_supported(guc) &&
+  GRAPHICS_VER(guc_to_gt(guc)->i915) >= 11;
+}
+
 static bool __guc_submission_selected(struct intel_guc *guc)
 {
struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
@@ -2555,6 +2562,7 @@ static bool __guc_submission_selected(struct intel_guc 
*guc)
 
 void intel_guc_submission_init_early(struct intel_guc *guc)
 {
+   guc->submission_supported = __guc_submission_supported(guc);
guc->submission_selected = __guc_submission_selected(guc);
 }
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
index 03bc1c83a4d2..c7ef44fa0c36 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
@@ -38,8 +38,7 @@ int intel_guc_wait_for_pending_msg(struct intel_guc *guc,
 
 static inline bool intel_guc_submission_is_supported(struct intel_guc *guc)
 {
-   /* XXX: GuC submission is unavailable for now */
-   return false;
+   return guc->submission_supported;
 }
 
 static inline bool intel_guc_submission_is_wanted(struct intel_guc *guc)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index 7a69c3c027e9..da57d18d9f6b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -34,8 +34,14 @@ static void uc_expand_default_options(struct intel_uc *uc)
return;
}
 
-   /* Default: enable HuC authentication only */
-   i915->params.enable_guc = ENABLE_GUC_LOAD_HUC;
+   /* Intermediate platforms are HuC authentication only */
+   if (IS_DG1(i915) || IS_ALDERLAKE_S(i915)) {
+   i915->params.enable_guc = ENABLE_GUC_LOAD_HUC;
+   return;
+   }
+
+   /* Default: enable HuC authentication and GuC submission */
+   i915->params.enable_guc = ENABLE_GUC_LOAD_HUC | ENABLE_GUC_SUBMISSION;
 }
 
 /* Reset GuC providing us with fresh state for both GuC and HuC.
@@ -313,9 +319,6 @@ static int __uc_init(struct intel_uc *uc)
if (i915_inject_probe_failure(uc_to_gt(uc)->i915))
return -ENOMEM;
 
-   /* XXX: GuC submission is unavailable for now */
-   GEM_BUG_ON(intel_uc_uses_guc_submission(uc));
-
ret = intel_guc_init(guc);
if (ret)
return ret;
-- 
2.28.0



[PATCH 29/33] drm/i915/selftest: Increase some timeouts in live_requests

2021-07-26 Thread Matthew Brost
Requests may take slightly longer with GuC submission, let's increase
the timeouts in live_requests.

Signed-off-by: Matthew Brost 
---
 drivers/gpu/drm/i915/selftests/i915_request.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c 
b/drivers/gpu/drm/i915/selftests/i915_request.c
index bd5c96a77ba3..d67710d10615 100644
--- a/drivers/gpu/drm/i915/selftests/i915_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_request.c
@@ -1313,7 +1313,7 @@ static int __live_parallel_engine1(void *arg)
i915_request_add(rq);
 
err = 0;
-   if (i915_request_wait(rq, 0, HZ / 5) < 0)
+   if (i915_request_wait(rq, 0, HZ) < 0)
err = -ETIME;
i915_request_put(rq);
if (err)
@@ -1419,7 +1419,7 @@ static int __live_parallel_spin(void *arg)
}
igt_spinner_end();
 
-   if (err == 0 && i915_request_wait(rq, 0, HZ / 5) < 0)
+   if (err == 0 && i915_request_wait(rq, 0, HZ) < 0)
err = -EIO;
i915_request_put(rq);
 
-- 
2.28.0



[PATCH 27/33] drm/i915/selftest: Fix workarounds selftest for GuC submission

2021-07-26 Thread Matthew Brost
From: Rahul Kumar Singh 

When GuC submission is enabled, the GuC controls engine resets. Rather
than explicitly triggering a reset, the driver must submit a hanging
context to GuC and wait for the reset to occur.

Signed-off-by: Rahul Kumar Singh 
Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
Cc: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/gt/intel_engine_types.h  |   1 +
 .../gpu/drm/i915/gt/selftest_workarounds.c| 130 +-
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c |   3 +
 .../i915/selftests/intel_scheduler_helpers.c  |  75 ++
 .../i915/selftests/intel_scheduler_helpers.h  |  27 
 6 files changed, 203 insertions(+), 34 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
 create mode 100644 drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 10b3bb6207ba..ab7679957623 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -280,6 +280,7 @@ i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
 i915-$(CONFIG_DRM_I915_SELFTEST) += \
gem/selftests/i915_gem_client_blt.o \
gem/selftests/igt_gem_utils.o \
+   selftests/intel_scheduler_helpers.o \
selftests/i915_random.o \
selftests/i915_selftest.o \
selftests/igt_atomic.o \
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h 
b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 260cce15cb62..ed91bcff20eb 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -443,6 +443,7 @@ struct intel_engine_cs {
 #define I915_ENGINE_IS_VIRTUAL   BIT(5)
 #define I915_ENGINE_HAS_RELATIVE_MMIO BIT(6)
 #define I915_ENGINE_REQUIRES_CMD_PARSER BIT(7)
+#define I915_ENGINE_WANT_FORCED_PREEMPTION BIT(8)
unsigned int flags;
 
/*
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c 
b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index 7a38ce40feb2..ba7ee69414d5 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -12,6 +12,7 @@
 #include "selftests/igt_flush_test.h"
 #include "selftests/igt_reset.h"
 #include "selftests/igt_spinner.h"
+#include "selftests/intel_scheduler_helpers.h"
 #include "selftests/mock_drm.h"
 
 #include "gem/selftests/igt_gem_utils.h"
@@ -261,28 +262,34 @@ static int do_engine_reset(struct intel_engine_cs *engine)
return intel_engine_reset(engine, "live_workarounds");
 }
 
+static int do_guc_reset(struct intel_engine_cs *engine)
+{
+   /* Currently a no-op as the reset is handled by GuC */
+   return 0;
+}
+
 static int
 switch_to_scratch_context(struct intel_engine_cs *engine,
- struct igt_spinner *spin)
+ struct igt_spinner *spin,
+ struct i915_request **rq)
 {
struct intel_context *ce;
-   struct i915_request *rq;
int err = 0;
 
ce = intel_context_create(engine);
if (IS_ERR(ce))
return PTR_ERR(ce);
 
-   rq = igt_spinner_create_request(spin, ce, MI_NOOP);
+   *rq = igt_spinner_create_request(spin, ce, MI_NOOP);
intel_context_put(ce);
 
-   if (IS_ERR(rq)) {
+   if (IS_ERR(*rq)) {
spin = NULL;
-   err = PTR_ERR(rq);
+   err = PTR_ERR(*rq);
goto err;
}
 
-   err = request_add_spin(rq, spin);
+   err = request_add_spin(*rq, spin);
 err:
if (err && spin)
igt_spinner_end(spin);
@@ -296,6 +303,7 @@ static int check_whitelist_across_reset(struct 
intel_engine_cs *engine,
 {
struct intel_context *ce, *tmp;
struct igt_spinner spin;
+   struct i915_request *rq;
intel_wakeref_t wakeref;
int err;
 
@@ -316,13 +324,24 @@ static int check_whitelist_across_reset(struct 
intel_engine_cs *engine,
goto out_spin;
}
 
-   err = switch_to_scratch_context(engine, );
+   err = switch_to_scratch_context(engine, , );
if (err)
goto out_spin;
 
+   /* Ensure the spinner hasn't aborted */
+   if (i915_request_completed(rq)) {
+   pr_err("%s spinner failed to start\n", name);
+   err = -ETIMEDOUT;
+   goto out_spin;
+   }
+
with_intel_runtime_pm(engine->uncore->rpm, wakeref)
err = reset(engine);
 
+   /* Ensure the reset happens and kills the engine */
+   if (err == 0)
+   err = intel_selftest_wait_for_rq(rq);
+
igt_spinner_end();
 
if (err) {
@@ -787,9 +806,27 @@ static int live_reset_whitelist(void *arg)
continue;
 
if (intel_has_reset_engine(gt)) {
-   err = 

[PATCH 18/33] drm/i915/guc: Capture error state on context reset

2021-07-26 Thread Matthew Brost
We receive notification of an engine reset from GuC at its
completion. Meaning GuC has potentially cleared any HW state
we may have been interested in capturing. GuC resumes scheduling
on the engine post-reset, as the resets are meant to be transparent,
further muddling our error state.

There is ongoing work to define an API for a GuC debug state dump. The
suggestion for now is to manually disable FW initiated resets in cases
where debug state is needed.

Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/intel_context.c   | 20 +++
 drivers/gpu/drm/i915/gt/intel_context.h   |  3 ++
 drivers/gpu/drm/i915/gt/intel_engine.h| 21 ++-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c | 11 --
 drivers/gpu/drm/i915/gt/intel_engine_types.h  |  2 ++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 35 +--
 drivers/gpu/drm/i915/i915_gpu_error.c | 25 ++---
 7 files changed, 91 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_context.c 
b/drivers/gpu/drm/i915/gt/intel_context.c
index 0bf4a13e9759..237b70e98744 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -509,6 +509,26 @@ struct i915_request *intel_context_create_request(struct 
intel_context *ce)
return rq;
 }
 
+struct i915_request *intel_context_find_active_request(struct intel_context 
*ce)
+{
+   struct i915_request *rq, *active = NULL;
+   unsigned long flags;
+
+   GEM_BUG_ON(!intel_engine_uses_guc(ce->engine));
+
+   spin_lock_irqsave(>guc_active.lock, flags);
+   list_for_each_entry_reverse(rq, >guc_active.requests,
+   sched.link) {
+   if (i915_request_completed(rq))
+   break;
+
+   active = rq;
+   }
+   spin_unlock_irqrestore(>guc_active.lock, flags);
+
+   return active;
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftest_context.c"
 #endif
diff --git a/drivers/gpu/drm/i915/gt/intel_context.h 
b/drivers/gpu/drm/i915/gt/intel_context.h
index 974ef85320c2..2ed9bf5f91a5 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.h
+++ b/drivers/gpu/drm/i915/gt/intel_context.h
@@ -200,6 +200,9 @@ int intel_context_prepare_remote_request(struct 
intel_context *ce,
 
 struct i915_request *intel_context_create_request(struct intel_context *ce);
 
+struct i915_request *
+intel_context_find_active_request(struct intel_context *ce);
+
 static inline bool intel_context_is_barrier(const struct intel_context *ce)
 {
return test_bit(CONTEXT_BARRIER_BIT, >flags);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h 
b/drivers/gpu/drm/i915/gt/intel_engine.h
index 8fc76dc8bf98..1db2d3efc71f 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -245,7 +245,7 @@ ktime_t intel_engine_get_busy_time(struct intel_engine_cs 
*engine,
   ktime_t *now);
 
 struct i915_request *
-intel_engine_find_active_request(struct intel_engine_cs *engine);
+intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine);
 
 u32 intel_engine_context_size(struct intel_gt *gt, u8 class);
 struct intel_context *
@@ -313,4 +313,23 @@ intel_engine_get_sibling(struct intel_engine_cs *engine, 
unsigned int sibling)
return engine->cops->get_sibling(engine, sibling);
 }
 
+static inline void
+intel_engine_set_hung_context(struct intel_engine_cs *engine,
+ struct intel_context *ce)
+{
+   engine->hung_ce = ce;
+}
+
+static inline void
+intel_engine_clear_hung_context(struct intel_engine_cs *engine)
+{
+   intel_engine_set_hung_context(engine, NULL);
+}
+
+static inline struct intel_context *
+intel_engine_get_hung_context(struct intel_engine_cs *engine)
+{
+   return engine->hung_ce;
+}
+
 #endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 1eaa658507e1..0da7868c5a13 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -1731,7 +1731,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
drm_printf(m, "\tRequests:\n");
 
spin_lock_irqsave(>sched_engine->lock, flags);
-   rq = intel_engine_find_active_request(engine);
+   rq = intel_engine_execlist_find_hung_request(engine);
if (rq) {
struct intel_timeline *tl = get_timeline(rq);
 
@@ -1842,10 +1842,17 @@ static bool match_ring(struct i915_request *rq)
 }
 
 struct i915_request *
-intel_engine_find_active_request(struct intel_engine_cs *engine)
+intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine)
 {
struct i915_request *request, *active = NULL;
 
+   /*
+* This search does not work in GuC submission mode. However, the GuC
+* will report the hanging context directly to the driver 

[PATCH 23/33] drm/i915/guc: Add golden context to GuC ADS

2021-07-26 Thread Matthew Brost
From: John Harrison 

The media watchdog mechanism involves GuC doing a silent reset and
continue of the hung context. This requires the i915 driver provide a
golden context to GuC in the ADS.

v2:
 (Matthew Brost):
  - Fix memory corruption in shmem_read
 (John H)
  - Use locals rather than defines for LR_* + SKIP_SIZE

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/intel_gt.c |   2 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.c |   5 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.h |   2 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 216 ++---
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h |   1 +
 drivers/gpu/drm/i915/gt/uc/intel_uc.c  |   5 +
 drivers/gpu/drm/i915/gt/uc/intel_uc.h  |   1 +
 7 files changed, 202 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c 
b/drivers/gpu/drm/i915/gt/intel_gt.c
index 46441607d18b..a64aa43f7cd9 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -654,6 +654,8 @@ int intel_gt_init(struct intel_gt *gt)
if (err)
goto err_gt;
 
+   intel_uc_init_late(>uc);
+
err = i915_inject_probe_error(gt->i915, -EIO);
if (err)
goto err_gt;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 68266cbffd1f..979128e28372 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -180,6 +180,11 @@ void intel_guc_init_early(struct intel_guc *guc)
}
 }
 
+void intel_guc_init_late(struct intel_guc *guc)
+{
+   intel_guc_ads_init_late(guc);
+}
+
 static u32 guc_ctl_debug_flags(struct intel_guc *guc)
 {
u32 level = intel_guc_log_get_level(>log);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 8c8cf842c29a..1875303c3bca 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -60,6 +60,7 @@ struct intel_guc {
struct i915_vma *ads_vma;
struct __guc_ads_blob *ads_blob;
u32 ads_regset_size;
+   u32 ads_golden_ctxt_size;
 
struct i915_vma *lrc_desc_pool;
void *lrc_desc_pool_vaddr;
@@ -183,6 +184,7 @@ static inline u32 intel_guc_ggtt_offset(struct intel_guc 
*guc,
 }
 
 void intel_guc_init_early(struct intel_guc *guc);
+void intel_guc_init_late(struct intel_guc *guc);
 void intel_guc_init_send_regs(struct intel_guc *guc);
 void intel_guc_write_params(struct intel_guc *guc);
 int intel_guc_init(struct intel_guc *guc);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index 51fc14ee79cd..6926919bcac6 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -7,6 +7,7 @@
 
 #include "gt/intel_gt.h"
 #include "gt/intel_lrc.h"
+#include "gt/shmem_utils.h"
 #include "intel_guc_ads.h"
 #include "intel_guc_fwif.h"
 #include "intel_uc.h"
@@ -33,6 +34,10 @@
  *  +---+ <== dynamic
  *  | padding   |
  *  +---+ <== 4K aligned
+ *  | golden contexts   |
+ *  +---+
+ *  | padding   |
+ *  +---+ <== 4K aligned
  *  | private data  |
  *  +---+
  *  | padding   |
@@ -52,6 +57,11 @@ static u32 guc_ads_regset_size(struct intel_guc *guc)
return guc->ads_regset_size;
 }
 
+static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc)
+{
+   return PAGE_ALIGN(guc->ads_golden_ctxt_size);
+}
+
 static u32 guc_ads_private_data_size(struct intel_guc *guc)
 {
return PAGE_ALIGN(guc->fw.private_data_size);
@@ -62,12 +72,23 @@ static u32 guc_ads_regset_offset(struct intel_guc *guc)
return offsetof(struct __guc_ads_blob, regset);
 }
 
-static u32 guc_ads_private_data_offset(struct intel_guc *guc)
+static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc)
 {
u32 offset;
 
offset = guc_ads_regset_offset(guc) +
 guc_ads_regset_size(guc);
+
+   return PAGE_ALIGN(offset);
+}
+
+static u32 guc_ads_private_data_offset(struct intel_guc *guc)
+{
+   u32 offset;
+
+   offset = guc_ads_golden_ctxt_offset(guc) +
+guc_ads_golden_ctxt_size(guc);
+
return PAGE_ALIGN(offset);
 }
 
@@ -319,53 +340,166 @@ static void guc_mmio_reg_state_init(struct intel_guc 
*guc,
GEM_BUG_ON(temp_set.size);
 }
 
-/*
- * The first 80 dwords of the register state context, containing the
- * execlists and ppgtt registers.
- */
-#define LR_HW_CONTEXT_SIZE (80 * sizeof(u32))
+static void fill_engine_enable_masks(struct intel_gt *gt,
+   

[PATCH 11/33] drm/i915/guc: Suspend/resume implementation for new interface

2021-07-26 Thread Matthew Brost
The new GuC interface introduces an MMIO H2G command,
INTEL_GUC_ACTION_RESET_CLIENT, which is used to implement suspend. This
MMIO tears down any active contexts generating a context reset G2H CTB
for each. Once that step completes the GuC tears down the CTB
channels. It is safe to suspend once this MMIO H2G command completes
and all G2H CTBs have been processed. In practice the i915 will likely
never receive a G2H as suspend should only be called after the GPU is
idle.

Resume is implemented in the same manner as before - simply reload the
GuC firmware and reinitialize everything (e.g. CTB channels, contexts,
etc..).

v2:
 (Michel / John H)
  - INTEL_GUC_ACTION_RESET_CLIENT 0x5B01 -> 0x5507

Cc: John Harrison 
Signed-off-by: Matthew Brost 
Signed-off-by: Michal Wajdeczko 
Reviewed-by: John Harrison 
---
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |  1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.c| 64 ---
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 15 +++--
 .../gpu/drm/i915/gt/uc/intel_guc_submission.h |  5 ++
 drivers/gpu/drm/i915/gt/uc/intel_uc.c | 20 --
 5 files changed, 54 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h 
b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
index 57e18babdf4b..d832c8f11c11 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
@@ -142,6 +142,7 @@ enum intel_guc_action {
INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505,
INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER = 0x4506,
INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600,
+   INTEL_GUC_ACTION_RESET_CLIENT = 0x5507,
INTEL_GUC_ACTION_LIMIT
 };
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 9b09395b998f..68266cbffd1f 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -524,51 +524,34 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 
rsa_offset)
  */
 int intel_guc_suspend(struct intel_guc *guc)
 {
-   struct intel_uncore *uncore = guc_to_gt(guc)->uncore;
int ret;
-   u32 status;
u32 action[] = {
-   INTEL_GUC_ACTION_ENTER_S_STATE,
-   GUC_POWER_D1, /* any value greater than GUC_POWER_D0 */
+   INTEL_GUC_ACTION_RESET_CLIENT,
};
 
-   /*
-* If GuC communication is enabled but submission is not supported,
-* we do not need to suspend the GuC.
-*/
-   if (!intel_guc_submission_is_used(guc) || !intel_guc_is_ready(guc))
+   if (!intel_guc_is_ready(guc))
return 0;
 
-   /*
-* The ENTER_S_STATE action queues the save/restore operation in GuC FW
-* and then returns, so waiting on the H2G is not enough to guarantee
-* GuC is done. When all the processing is done, GuC writes
-* INTEL_GUC_SLEEP_STATE_SUCCESS to scratch register 14, so we can poll
-* on that. Note that GuC does not ensure that the value in the register
-* is different from INTEL_GUC_SLEEP_STATE_SUCCESS while the action is
-* in progress so we need to take care of that ourselves as well.
-*/
-
-   intel_uncore_write(uncore, SOFT_SCRATCH(14),
-  INTEL_GUC_SLEEP_STATE_INVALID_MASK);
-
-   ret = intel_guc_send(guc, action, ARRAY_SIZE(action));
-   if (ret)
-   return ret;
-
-   ret = __intel_wait_for_register(uncore, SOFT_SCRATCH(14),
-   INTEL_GUC_SLEEP_STATE_INVALID_MASK,
-   0, 0, 10, );
-   if (ret)
-   return ret;
-
-   if (status != INTEL_GUC_SLEEP_STATE_SUCCESS) {
-   DRM_ERROR("GuC failed to change sleep state. "
- "action=0x%x, err=%u\n",
- action[0], status);
-   return -EIO;
+   if (intel_guc_submission_is_used(guc)) {
+   /*
+* This H2G MMIO command tears down the GuC in two steps. First 
it will
+* generate a G2H CTB for every active context indicating a 
reset. In
+* practice the i915 shouldn't ever get a G2H as suspend should 
only be
+* called when the GPU is idle. Next, it tears down the CTBs 
and this
+* H2G MMIO command completes.
+*
+* Don't abort on a failure code from the GuC. Keep going and 
do the
+* clean up in santize() and re-initialisation on resume and 
hopefully
+* the error here won't be problematic.
+*/
+   ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), 
NULL, 0);
+   if (ret)
+   DRM_ERROR("GuC suspend: RESET_CLIENT action failed with 
error %d!\n", ret);
}
 
+   /* Signal that the GuC isn't running. 

[PATCH 09/33] drm/i915: Reset GPU immediately if submission is disabled

2021-07-26 Thread Matthew Brost
If submission is disabled by the backend for any reason, reset the GPU
immediately in the heartbeat code as the backend can't be reenabled
until the GPU is reset.

Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 .../gpu/drm/i915/gt/intel_engine_heartbeat.c  | 62 +++
 .../gpu/drm/i915/gt/intel_engine_heartbeat.h  |  4 ++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c |  9 +++
 drivers/gpu/drm/i915/i915_scheduler.c |  6 ++
 drivers/gpu/drm/i915/i915_scheduler.h |  6 ++
 drivers/gpu/drm/i915/i915_scheduler_types.h   |  5 ++
 6 files changed, 79 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c 
b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
index b6a305e6a974..0b16f19c384e 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
@@ -70,12 +70,30 @@ static void show_heartbeat(const struct i915_request *rq,
 {
struct drm_printer p = drm_debug_printer("heartbeat");
 
-   intel_engine_dump(engine, ,
- "%s heartbeat {seqno:%llx:%lld, prio:%d} not 
ticking\n",
- engine->name,
- rq->fence.context,
- rq->fence.seqno,
- rq->sched.attr.priority);
+   if (!rq) {
+   intel_engine_dump(engine, ,
+ "%s heartbeat not ticking\n",
+ engine->name);
+   } else {
+   intel_engine_dump(engine, ,
+ "%s heartbeat {seqno:%llx:%lld, prio:%d} not 
ticking\n",
+ engine->name,
+ rq->fence.context,
+ rq->fence.seqno,
+ rq->sched.attr.priority);
+   }
+}
+
+static void
+reset_engine(struct intel_engine_cs *engine, struct i915_request *rq)
+{
+   if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
+   show_heartbeat(rq, engine);
+
+   intel_gt_handle_error(engine->gt, engine->mask,
+ I915_ERROR_CAPTURE,
+ "stopped heartbeat on %s",
+ engine->name);
 }
 
 static void heartbeat(struct work_struct *wrk)
@@ -102,6 +120,11 @@ static void heartbeat(struct work_struct *wrk)
if (intel_gt_is_wedged(engine->gt))
goto out;
 
+   if (i915_sched_engine_disabled(engine->sched_engine)) {
+   reset_engine(engine, engine->heartbeat.systole);
+   goto out;
+   }
+
if (engine->heartbeat.systole) {
long delay = READ_ONCE(engine->props.heartbeat_interval_ms);
 
@@ -139,13 +162,7 @@ static void heartbeat(struct work_struct *wrk)
engine->sched_engine->schedule(rq, );
local_bh_enable();
} else {
-   if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
-   show_heartbeat(rq, engine);
-
-   intel_gt_handle_error(engine->gt, engine->mask,
- I915_ERROR_CAPTURE,
- "stopped heartbeat on %s",
- engine->name);
+   reset_engine(engine, rq);
}
 
rq->emitted_jiffies = jiffies;
@@ -194,6 +211,25 @@ void intel_engine_park_heartbeat(struct intel_engine_cs 
*engine)
i915_request_put(fetch_and_zero(>heartbeat.systole));
 }
 
+void intel_gt_unpark_heartbeats(struct intel_gt *gt)
+{
+   struct intel_engine_cs *engine;
+   enum intel_engine_id id;
+
+   for_each_engine(engine, gt, id)
+   if (intel_engine_pm_is_awake(engine))
+   intel_engine_unpark_heartbeat(engine);
+}
+
+void intel_gt_park_heartbeats(struct intel_gt *gt)
+{
+   struct intel_engine_cs *engine;
+   enum intel_engine_id id;
+
+   for_each_engine(engine, gt, id)
+   intel_engine_park_heartbeat(engine);
+}
+
 void intel_engine_init_heartbeat(struct intel_engine_cs *engine)
 {
INIT_DELAYED_WORK(>heartbeat.work, heartbeat);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h 
b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
index a488ea3e84a3..5da6d809a87a 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
@@ -7,6 +7,7 @@
 #define INTEL_ENGINE_HEARTBEAT_H
 
 struct intel_engine_cs;
+struct intel_gt;
 
 void intel_engine_init_heartbeat(struct intel_engine_cs *engine);
 
@@ -16,6 +17,9 @@ int intel_engine_set_heartbeat(struct intel_engine_cs *engine,
 void intel_engine_park_heartbeat(struct intel_engine_cs *engine);
 void intel_engine_unpark_heartbeat(struct intel_engine_cs *engine);
 
+void intel_gt_park_heartbeats(struct intel_gt *gt);
+void 

[PATCH 03/33] drm/i915: Hold reference to intel_context over life of i915_request

2021-07-26 Thread Matthew Brost
Hold a reference to the intel_context over life of an i915_request.
Without this an i915_request can exist after the context has been
destroyed (e.g. request retired, context closed, but user space holds a
reference to the request from an out fence). In the case of GuC
submission + virtual engine, the engine that the request references is
also destroyed which can trigger bad pointer dref in fence ops (e.g.
i915_fence_get_driver_name). We could likely change
i915_fence_get_driver_name to avoid touching the engine but let's just
be safe and hold the intel_context reference.

v2:
 (John Harrison)
  - Update comment explaining how GuC mode and execlists mode deal with
virtual engines differently

Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_request.c | 55 -
 1 file changed, 23 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_request.c 
b/drivers/gpu/drm/i915/i915_request.c
index 39a21d96577e..57c9187aff74 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -125,39 +125,17 @@ static void i915_fence_release(struct dma_fence *fence)
i915_sw_fence_fini(>semaphore);
 
/*
-* Keep one request on each engine for reserved use under mempressure
-*
-* We do not hold a reference to the engine here and so have to be
-* very careful in what rq->engine we poke. The virtual engine is
-* referenced via the rq->context and we released that ref during
-* i915_request_retire(), ergo we must not dereference a virtual
-* engine here. Not that we would want to, as the only consumer of
-* the reserved engine->request_pool is the power management parking,
-* which must-not-fail, and that is only run on the physical engines.
-*
-* Since the request must have been executed to be have completed,
-* we know that it will have been processed by the HW and will
-* not be unsubmitted again, so rq->engine and rq->execution_mask
-* at this point is stable. rq->execution_mask will be a single
-* bit if the last and _only_ engine it could execution on was a
-* physical engine, if it's multiple bits then it started on and
-* could still be on a virtual engine. Thus if the mask is not a
-* power-of-two we assume that rq->engine may still be a virtual
-* engine and so a dangling invalid pointer that we cannot dereference
-*
-* For example, consider the flow of a bonded request through a virtual
-* engine. The request is created with a wide engine mask (all engines
-* that we might execute on). On processing the bond, the request mask
-* is reduced to one or more engines. If the request is subsequently
-* bound to a single engine, it will then be constrained to only
-* execute on that engine and never returned to the virtual engine
-* after timeslicing away, see __unwind_incomplete_requests(). Thus we
-* know that if the rq->execution_mask is a single bit, rq->engine
-* can be a physical engine with the exact corresponding mask.
+* Keep one request on each engine for reserved use under mempressure,
+* do not use with virtual engines as this really is only needed for
+* kernel contexts.
 */
-   if (is_power_of_2(rq->execution_mask) &&
-   !cmpxchg(>engine->request_pool, NULL, rq))
+   if (!intel_engine_is_virtual(rq->engine) &&
+   !cmpxchg(>engine->request_pool, NULL, rq)) {
+   intel_context_put(rq->context);
return;
+   }
+
+   intel_context_put(rq->context);
 
kmem_cache_free(global.slab_requests, rq);
 }
@@ -956,7 +934,19 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
}
}
 
-   rq->context = ce;
+   /*
+* Hold a reference to the intel_context over life of an i915_request.
+* Without this an i915_request can exist after the context has been
+* destroyed (e.g. request retired, context closed, but user space holds
+* a reference to the request from an out fence). In the case of GuC
+* submission + virtual engine, the engine that the request references
+* is also destroyed which can trigger bad pointer dref in fence ops
+* (e.g. i915_fence_get_driver_name). We could likely change these
+* functions to avoid touching the engine but let's just be safe and
+* hold the intel_context reference. In execlist mode the request always
+* eventually points to a physical engine so this isn't an issue.
+*/
+   rq->context = intel_context_get(ce);
rq->engine = ce->engine;
rq->ring = ce->ring;
rq->execution_mask = ce->engine->mask;
@@ -1033,6 +1023,7 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)

[PATCH 30/33] drm/i915/selftest: Fix hangcheck self test for GuC submission

2021-07-26 Thread Matthew Brost
From: John Harrison 

When GuC submission is enabled, the GuC controls engine resets. Rather
than explicitly triggering a reset, the driver must submit a hanging
context to GuC and wait for the reset to occur.

Conversely, one of the tests specifically sends hanging batches to the
engines but wants them to sit around until a manual reset of the full
GT (including GuC itself). That means disabling GuC based engine
resets to prevent those from killing the hanging batch too soon. So,
add support to the scheduling policy helper for disabling resets as
well as making them quicker!

In GuC submission mode, the 'is engine idle' test basically turns into
'is engine PM wakelock held'. Independently, there is a heartbeat
disable helper function that the tests use. For unexplained reasons,
this acquires the engine wakelock before disabling the heartbeat and
only releases it when re-enabling the heartbeat. As one of the tests
tries to do a wait for idle in the middle of a heartbeat disabled
section, it is therefore guaranteed to always fail. Added a 'no_pm'
variant of the heartbeat helper that allows the engine to be asleep
while also having heartbeats disabled.

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
Cc: Matthew Brost 
---
 .../drm/i915/gt/selftest_engine_heartbeat.c   |  22 ++
 .../drm/i915/gt/selftest_engine_heartbeat.h   |   2 +
 drivers/gpu/drm/i915/gt/selftest_hangcheck.c  | 227 +-
 drivers/gpu/drm/i915/gt/selftest_mocs.c   |   3 +-
 .../gpu/drm/i915/gt/selftest_workarounds.c|   6 +-
 .../i915/selftests/intel_scheduler_helpers.c  |  39 ++-
 .../i915/selftests/intel_scheduler_helpers.h  |   8 +-
 7 files changed, 236 insertions(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c 
b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
index 4896e4ccad50..317eebf086c3 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
@@ -405,3 +405,25 @@ void st_engine_heartbeat_enable(struct intel_engine_cs 
*engine)
engine->props.heartbeat_interval_ms =
engine->defaults.heartbeat_interval_ms;
 }
+
+void st_engine_heartbeat_disable_no_pm(struct intel_engine_cs *engine)
+{
+   engine->props.heartbeat_interval_ms = 0;
+
+   /*
+* Park the heartbeat but without holding the PM lock as that
+* makes the engines appear not-idle. Note that if/when unpark
+* is called due to the PM lock being acquired later the
+* heartbeat still won't be enabled because of the above = 0.
+*/
+   if (intel_engine_pm_get_if_awake(engine)) {
+   intel_engine_park_heartbeat(engine);
+   intel_engine_pm_put(engine);
+   }
+}
+
+void st_engine_heartbeat_enable_no_pm(struct intel_engine_cs *engine)
+{
+   engine->props.heartbeat_interval_ms =
+   engine->defaults.heartbeat_interval_ms;
+}
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h 
b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h
index cd27113d5400..81da2cd8e406 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h
@@ -9,6 +9,8 @@
 struct intel_engine_cs;
 
 void st_engine_heartbeat_disable(struct intel_engine_cs *engine);
+void st_engine_heartbeat_disable_no_pm(struct intel_engine_cs *engine);
 void st_engine_heartbeat_enable(struct intel_engine_cs *engine);
+void st_engine_heartbeat_enable_no_pm(struct intel_engine_cs *engine);
 
 #endif /* SELFTEST_ENGINE_HEARTBEAT_H */
diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c 
b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
index f93ba4076b2b..e0e200ba77e9 100644
--- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
@@ -17,6 +17,8 @@
 #include "selftests/igt_flush_test.h"
 #include "selftests/igt_reset.h"
 #include "selftests/igt_atomic.h"
+#include "selftests/igt_spinner.h"
+#include "selftests/intel_scheduler_helpers.h"
 
 #include "selftests/mock_drm.h"
 
@@ -450,6 +452,14 @@ static int igt_reset_nop_engine(void *arg)
IGT_TIMEOUT(end_time);
int err;
 
+   if (intel_engine_uses_guc(engine)) {
+   /* Engine level resets are triggered by GuC when a hang
+* is detected. They can't be triggered by the KMD any
+* more. Thus a nop batch cannot be used as a reset test
+*/
+   continue;
+   }
+
ce = intel_context_create(engine);
if (IS_ERR(ce)) {
pr_err("[%s] Create context failed: %d!\n", 
engine->name, err);
@@ -561,6 +571,10 @@ static int igt_reset_fail_engine(void *arg)
IGT_TIMEOUT(end_time);
int err;
 
+   /* Can't manually break the 

[PATCH 26/33] drm/i915/selftest: Better error reporting from hangcheck selftest

2021-07-26 Thread Matthew Brost
From: John Harrison 

There are many ways in which the hangcheck selftest can fail. Very few
of them actually printed an error message to say what happened. So,
fill in the missing messages.

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
---
 drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 93 
 1 file changed, 75 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c 
b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
index 7aea10aa1fb4..f93ba4076b2b 100644
--- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
@@ -378,6 +378,7 @@ static int igt_reset_nop(void *arg)
ce = intel_context_create(engine);
if (IS_ERR(ce)) {
err = PTR_ERR(ce);
+   pr_err("[%s] Create context failed: %d!\n", 
engine->name, err);
break;
}
 
@@ -387,6 +388,8 @@ static int igt_reset_nop(void *arg)
rq = intel_context_create_request(ce);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
+   pr_err("[%s] Create request failed: 
%d!\n",
+  engine->name, err);
break;
}
 
@@ -401,24 +404,31 @@ static int igt_reset_nop(void *arg)
igt_global_reset_unlock(gt);
 
if (intel_gt_is_wedged(gt)) {
+   pr_err("[%s] GT is wedged!\n", engine->name);
err = -EIO;
break;
}
 
if (i915_reset_count(global) != reset_count + ++count) {
-   pr_err("Full GPU reset not recorded!\n");
+   pr_err("[%s] Reset not recorded: %d vs %d + %d!\n",
+  engine->name, i915_reset_count(global), 
reset_count, count);
err = -EINVAL;
break;
}
 
err = igt_flush_test(gt->i915);
-   if (err)
+   if (err) {
+   pr_err("[%s] Flush failed: %d!\n", engine->name, err);
break;
+   }
} while (time_before(jiffies, end_time));
pr_info("%s: %d resets\n", __func__, count);
 
-   if (igt_flush_test(gt->i915))
+   if (igt_flush_test(gt->i915)) {
+   pr_err("Post flush failed: %d!\n", err);
err = -EIO;
+   }
+
return err;
 }
 
@@ -441,8 +451,10 @@ static int igt_reset_nop_engine(void *arg)
int err;
 
ce = intel_context_create(engine);
-   if (IS_ERR(ce))
+   if (IS_ERR(ce)) {
+   pr_err("[%s] Create context failed: %d!\n", 
engine->name, err);
return PTR_ERR(ce);
+   }
 
reset_count = i915_reset_count(global);
reset_engine_count = i915_reset_engine_count(global, engine);
@@ -550,8 +562,10 @@ static int igt_reset_fail_engine(void *arg)
int err;
 
ce = intel_context_create(engine);
-   if (IS_ERR(ce))
+   if (IS_ERR(ce)) {
+   pr_err("[%s] Create context failed: %d!\n", 
engine->name, err);
return PTR_ERR(ce);
+   }
 
st_engine_heartbeat_disable(engine);
set_bit(I915_RESET_ENGINE + id, >reset.flags);
@@ -711,6 +725,8 @@ static int __igt_reset_engine(struct intel_gt *gt, bool 
active)
rq = hang_create_request(, engine);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
+   pr_err("[%s] Create hang request 
failed: %d!\n",
+  engine->name, err);
break;
}
 
@@ -765,12 +781,16 @@ static int __igt_reset_engine(struct intel_gt *gt, bool 
active)
break;
 
err = igt_flush_test(gt->i915);
-   if (err)
+   if (err) {
+   pr_err("[%s] Flush failed: %d!\n", engine->name, err);
break;
+   }
}
 
-   if (intel_gt_is_wedged(gt))
+   if (intel_gt_is_wedged(gt)) {
+   pr_err("GT is wedged!\n");
err = -EIO;
+   }
 
if (active)
hang_fini();
@@ -837,6 +857,7 @@ static int active_engine(void *data)
ce[count] = intel_context_create(engine);
if (IS_ERR(ce[count])) {
err = 

[PATCH 32/33] drm/i915/guc: Implement GuC priority management

2021-07-26 Thread Matthew Brost
Implement a simple static mapping algorithm of the i915 priority levels
(int, -1k to 1k exposed to user) to the 4 GuC levels. Mapping is as
follows:

i915 level < 0  -> GuC low level (3)
i915 level == 0 -> GuC normal level  (2)
i915 level < INT_MAX-> GuC high level(1)
i915 level == INT_MAX   -> GuC highest level (0)

We believe this mapping should cover the UMD use cases (3 distinct user
levels + 1 kernel level).

In addition to static mapping, a simple counter system is attached to
each context tracking the number of requests inflight on the context at
each level. This is needed as the GuC levels are per context while in
the i915 levels are per request.

v2:
 (Daniele)
  - Add BUILD_BUG_ON to enforce ordering of priority levels
  - Add missing lockdep to guc_prio_fini
  - Check for return before setting context registered flag
  - Map DISPLAY priority or higher to highest guc prio
  - Update comment for guc_prio

Signed-off-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
Reviewed-by: Daniele Ceraolo Spurio 
---
 drivers/gpu/drm/i915/gt/intel_breadcrumbs.c   |   3 +
 drivers/gpu/drm/i915/gt/intel_context_types.h |   9 +-
 drivers/gpu/drm/i915/gt/intel_engine_user.c   |   4 +
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 212 +-
 drivers/gpu/drm/i915/i915_request.c   |   5 +
 drivers/gpu/drm/i915/i915_request.h   |   9 +
 drivers/gpu/drm/i915/i915_scheduler.c |   7 +
 drivers/gpu/drm/i915/i915_scheduler_types.h   |  12 +
 drivers/gpu/drm/i915/i915_trace.h |  17 +-
 include/uapi/drm/i915_drm.h   |   9 +
 10 files changed, 282 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c 
b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
index 2007dc6f6b99..209cf265bf74 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
@@ -245,6 +245,9 @@ static void signal_irq_work(struct irq_work *work)
llist_entry(signal, typeof(*rq), signal_node);
struct list_head cb_list;
 
+   if (rq->engine->sched_engine->retire_inflight_request_prio)
+   
rq->engine->sched_engine->retire_inflight_request_prio(rq);
+
spin_lock(>lock);
list_replace(>fence.cb_list, _list);
__dma_fence_signal__timestamp(>fence, timestamp);
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h 
b/drivers/gpu/drm/i915/gt/intel_context_types.h
index a5bc876face7..e54351a170e2 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -18,8 +18,9 @@
 #include "intel_engine_types.h"
 #include "intel_sseu.h"
 
-#define CONTEXT_REDZONE POISON_INUSE
+#include "uc/intel_guc_fwif.h"
 
+#define CONTEXT_REDZONE POISON_INUSE
 DECLARE_EWMA(runtime, 3, 8);
 
 struct i915_gem_context;
@@ -191,6 +192,12 @@ struct intel_context {
 
/* GuC context blocked fence */
struct i915_sw_fence guc_blocked;
+
+   /*
+* GuC priority management
+*/
+   u8 guc_prio;
+   u32 guc_prio_count[GUC_CLIENT_PRIORITY_NUM];
 };
 
 #endif /* __INTEL_CONTEXT_TYPES__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c 
b/drivers/gpu/drm/i915/gt/intel_engine_user.c
index 84142127ebd8..8f8bea08e734 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c
@@ -11,6 +11,7 @@
 #include "intel_engine.h"
 #include "intel_engine_user.h"
 #include "intel_gt.h"
+#include "uc/intel_guc_submission.h"
 
 struct intel_engine_cs *
 intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
@@ -115,6 +116,9 @@ static void set_scheduler_caps(struct drm_i915_private 
*i915)
disabled |= (I915_SCHEDULER_CAP_ENABLED |
 I915_SCHEDULER_CAP_PRIORITY);
 
+   if (intel_uc_uses_guc_submission(>gt.uc))
+   enabled |= I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP;
+
for (i = 0; i < ARRAY_SIZE(map); i++) {
if (engine->flags & BIT(map[i].engine))
enabled |= BIT(map[i].sched);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 3ff42d6e934f..b760cbf6ca0e 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -81,6 +81,7 @@ guc_create_virtual(struct intel_engine_cs **siblings, 
unsigned int count);
  */
 #define SCHED_STATE_NO_LOCK_ENABLEDBIT(0)
 #define SCHED_STATE_NO_LOCK_PENDING_ENABLE BIT(1)
+#define SCHED_STATE_NO_LOCK_REGISTERED BIT(2)
 static inline bool context_enabled(struct intel_context *ce)
 {
return (atomic_read(>guc_sched_state_no_lock) &
@@ -116,6 +117,24 @@ static inline void 

[PATCH 20/33] drm/i915/guc: Hook GuC scheduling policies up

2021-07-26 Thread Matthew Brost
From: John Harrison 

Use the official driver default scheduling policies for configuring
the GuC scheduler rather than a bunch of hardcoded values.

v2:
 (Matthew Brost)
  - Move I915_ENGINE_WANT_FORCED_PREEMPTION to later patch

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
Cc: Jose Souza 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|  2 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 44 ++-
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c |  8 ++--
 3 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index f355a70bbec4..8c8cf842c29a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -277,6 +277,8 @@ int intel_guc_engine_failure_process_msg(struct intel_guc 
*guc,
 
 void intel_guc_find_hung_context(struct intel_engine_cs *engine);
 
+int intel_guc_global_policies_update(struct intel_guc *guc);
+
 void intel_guc_submission_reset_prepare(struct intel_guc *guc);
 void intel_guc_submission_reset(struct intel_guc *guc, bool stalled);
 void intel_guc_submission_reset_finish(struct intel_guc *guc);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index 97cfaaaf2397..60b73625f686 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -77,14 +77,54 @@ static u32 guc_ads_blob_size(struct intel_guc *guc)
   guc_ads_private_data_size(guc);
 }
 
-static void guc_policies_init(struct guc_policies *policies)
+static void guc_policies_init(struct intel_guc *guc, struct guc_policies 
*policies)
 {
+   struct intel_gt *gt = guc_to_gt(guc);
+   struct drm_i915_private *i915 = gt->i915;
+
policies->dpc_promote_time = GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US;
policies->max_num_work_items = GLOBAL_POLICY_MAX_NUM_WI;
+
policies->global_flags = 0;
+   if (i915->params.reset < 2)
+   policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET;
+
policies->is_valid = 1;
 }
 
+static int guc_action_policies_update(struct intel_guc *guc, u32 policy_offset)
+{
+   u32 action[] = {
+   INTEL_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE,
+   policy_offset
+   };
+
+   return intel_guc_send(guc, action, ARRAY_SIZE(action));
+}
+
+int intel_guc_global_policies_update(struct intel_guc *guc)
+{
+   struct __guc_ads_blob *blob = guc->ads_blob;
+   struct intel_gt *gt = guc_to_gt(guc);
+   intel_wakeref_t wakeref;
+   int ret;
+
+   if (!blob)
+   return -EOPNOTSUPP;
+
+   GEM_BUG_ON(!blob->ads.scheduler_policies);
+
+   guc_policies_init(guc, >policies);
+
+   if (!intel_guc_is_ready(guc))
+   return 0;
+
+   with_intel_runtime_pm(>i915->runtime_pm, wakeref)
+   ret = guc_action_policies_update(guc, 
blob->ads.scheduler_policies);
+
+   return ret;
+}
+
 static void guc_mapping_table_init(struct intel_gt *gt,
   struct guc_gt_system_info *system_info)
 {
@@ -281,7 +321,7 @@ static void __guc_ads_init(struct intel_guc *guc)
u8 engine_class, guc_class;
 
/* GuC scheduling policies */
-   guc_policies_init(>policies);
+   guc_policies_init(guc, >policies);
 
/*
 * GuC expects a per-engine-class context image and size
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 76c2d927e1c3..cea3e3073a71 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -874,6 +874,7 @@ void intel_guc_submission_reset_finish(struct intel_guc 
*guc)
GEM_WARN_ON(atomic_read(>outstanding_submission_g2h));
atomic_set(>outstanding_submission_g2h, 0);
 
+   intel_guc_global_policies_update(guc);
enable_submission(guc);
intel_gt_unpark_heartbeats(guc_to_gt(guc));
 }
@@ -1170,8 +1171,9 @@ static void guc_context_policy_init(struct 
intel_engine_cs *engine,
 {
desc->policy_flags = 0;
 
-   desc->execution_quantum = CONTEXT_POLICY_DEFAULT_EXECUTION_QUANTUM_US;
-   desc->preemption_timeout = CONTEXT_POLICY_DEFAULT_PREEMPTION_TIME_US;
+   /* NB: For both of these, zero means disabled. */
+   desc->execution_quantum = engine->props.timeslice_duration_ms * 1000;
+   desc->preemption_timeout = engine->props.preempt_timeout_ms * 1000;
 }
 
 static int guc_lrc_desc_pin(struct intel_context *ce, bool loop)
@@ -1942,13 +1944,13 @@ static void guc_default_vfuncs(struct intel_engine_cs 
*engine)
engine->set_default_submission = guc_set_default_submission;
 
engine->flags |= I915_ENGINE_HAS_PREEMPTION;
+   engine->flags |= I915_ENGINE_HAS_TIMESLICES;
 
/*
 * TODO: GuC supports timeslicing and 

[PATCH 28/33] drm/i915/selftest: Fix MOCS selftest for GuC submission

2021-07-26 Thread Matthew Brost
From: Rahul Kumar Singh 

When GuC submission is enabled, the GuC controls engine resets. Rather
than explicitly triggering a reset, the driver must submit a hanging
context to GuC and wait for the reset to occur.

Signed-off-by: Rahul Kumar Singh 
Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
Cc: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/selftest_mocs.c | 49 ++---
 1 file changed, 35 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c 
b/drivers/gpu/drm/i915/gt/selftest_mocs.c
index 8763bbeca0f7..b7314739ee40 100644
--- a/drivers/gpu/drm/i915/gt/selftest_mocs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c
@@ -10,6 +10,7 @@
 #include "gem/selftests/mock_context.h"
 #include "selftests/igt_reset.h"
 #include "selftests/igt_spinner.h"
+#include "selftests/intel_scheduler_helpers.h"
 
 struct live_mocs {
struct drm_i915_mocs_table table;
@@ -318,7 +319,8 @@ static int live_mocs_clean(void *arg)
 }
 
 static int active_engine_reset(struct intel_context *ce,
-  const char *reason)
+  const char *reason,
+  bool using_guc)
 {
struct igt_spinner spin;
struct i915_request *rq;
@@ -335,9 +337,13 @@ static int active_engine_reset(struct intel_context *ce,
}
 
err = request_add_spin(rq, );
-   if (err == 0)
+   if (err == 0 && !using_guc)
err = intel_engine_reset(ce->engine, reason);
 
+   /* Ensure the reset happens and kills the engine */
+   if (err == 0)
+   err = intel_selftest_wait_for_rq(rq);
+
igt_spinner_end();
igt_spinner_fini();
 
@@ -345,21 +351,23 @@ static int active_engine_reset(struct intel_context *ce,
 }
 
 static int __live_mocs_reset(struct live_mocs *mocs,
-struct intel_context *ce)
+struct intel_context *ce, bool using_guc)
 {
struct intel_gt *gt = ce->engine->gt;
int err;
 
if (intel_has_reset_engine(gt)) {
-   err = intel_engine_reset(ce->engine, "mocs");
-   if (err)
-   return err;
-
-   err = check_mocs_engine(mocs, ce);
-   if (err)
-   return err;
+   if (!using_guc) {
+   err = intel_engine_reset(ce->engine, "mocs");
+   if (err)
+   return err;
+
+   err = check_mocs_engine(mocs, ce);
+   if (err)
+   return err;
+   }
 
-   err = active_engine_reset(ce, "mocs");
+   err = active_engine_reset(ce, "mocs", using_guc);
if (err)
return err;
 
@@ -395,19 +403,32 @@ static int live_mocs_reset(void *arg)
 
igt_global_reset_lock(gt);
for_each_engine(engine, gt, id) {
+   bool using_guc = intel_engine_uses_guc(engine);
+   struct intel_selftest_saved_policy saved;
struct intel_context *ce;
+   int err2;
+
+   err = intel_selftest_modify_policy(engine, );
+   if (err)
+   break;
 
ce = mocs_context_create(engine);
if (IS_ERR(ce)) {
err = PTR_ERR(ce);
-   break;
+   goto restore;
}
 
intel_engine_pm_get(engine);
-   err = __live_mocs_reset(, ce);
-   intel_engine_pm_put(engine);
 
+   err = __live_mocs_reset(, ce, using_guc);
+
+   intel_engine_pm_put(engine);
intel_context_put(ce);
+
+restore:
+   err2 = intel_selftest_restore_policy(engine, );
+   if (err == 0)
+   err = err2;
if (err)
break;
}
-- 
2.28.0



[PATCH 02/33] drm/i915/guc: Make hangcheck work with GuC virtual engines

2021-07-26 Thread Matthew Brost
From: John Harrison 

The serial number tracking of engines happens at the backend of
request submission and was expecting to only be given physical
engines. However, in GuC submission mode, the decomposition of virtual
to physical engines does not happen in i915. Instead, requests are
submitted to their virtual engine mask all the way through to the
hardware (i.e. to GuC). This would mean that the heart beat code
thinks the physical engines are idle due to the serial number not
incrementing. Which in turns means hangcheck does not work for
GuC virtual engines.

This patch updates the tracking to decompose virtual engines into
their physical constituents and tracks the request against each. This
is not entirely accurate as the GuC will only be issuing the request
to one physical engine. However, it is the best that i915 can do given
that it has no knowledge of the GuC's scheduling decisions.

Downside of this is that all physical engines constituting a GuC
virtual engine will be periodically unparked (even during just a single
context executing) in order to be pinged with a heartbeat request.
However the power and performance cost of this is not expected to be
measurable (due low frequency of heartbeat pulses) and it is considered
an easier option than trying to make changes to GuC firmware.

v2:
 (Tvrtko)
  - Update commit message
  - Have default behavior if no vfunc present

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/intel_engine_types.h  |  2 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 10 ++
 drivers/gpu/drm/i915/i915_request.c   |  6 +-
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h 
b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 3f308a920b50..75a34cd3f1c2 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -382,6 +382,8 @@ struct intel_engine_cs {
void(*park)(struct intel_engine_cs *engine);
void(*unpark)(struct intel_engine_cs *engine);
 
+   void(*bump_serial)(struct intel_engine_cs *engine);
+
void(*set_default_submission)(struct intel_engine_cs 
*engine);
 
const struct intel_context_ops *cops;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 8b3ae5f65cd5..6b08221df143 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -1492,6 +1492,15 @@ static void guc_release(struct intel_engine_cs *engine)
lrc_fini_wa_ctx(engine);
 }
 
+static void virtual_guc_bump_serial(struct intel_engine_cs *engine)
+{
+   struct intel_engine_cs *e;
+   intel_engine_mask_t tmp, mask = engine->mask;
+
+   for_each_engine_masked(e, engine->gt, mask, tmp)
+   e->serial++;
+}
+
 static void guc_default_vfuncs(struct intel_engine_cs *engine)
 {
/* Default vfuncs which can be overridden by each engine. */
@@ -1835,6 +1844,7 @@ guc_create_virtual(struct intel_engine_cs **siblings, 
unsigned int count)
 
ve->base.cops = _guc_context_ops;
ve->base.request_alloc = guc_request_alloc;
+   ve->base.bump_serial = virtual_guc_bump_serial;
 
ve->base.submit_request = guc_submit_request;
 
diff --git a/drivers/gpu/drm/i915/i915_request.c 
b/drivers/gpu/drm/i915/i915_request.c
index 6594cb2f8ebd..39a21d96577e 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -669,7 +669,11 @@ bool __i915_request_submit(struct i915_request *request)
 request->ring->vaddr + request->postfix);
 
trace_i915_request_execute(request);
-   engine->serial++;
+   if (engine->bump_serial)
+   engine->bump_serial(engine);
+   else
+   engine->serial++;
+
result = true;
 
GEM_BUG_ON(test_bit(I915_FENCE_FLAG_ACTIVE, >fence.flags));
-- 
2.28.0



[PATCH 13/33] drm/i915/guc: Handle engine reset failure notification

2021-07-26 Thread Matthew Brost
GuC will notify the driver, via G2H, if it fails to
reset an engine. We recover by resorting to a full GPU
reset.

v2:
 (John Harrison):
  - s/drm_dbg/drm_err

Signed-off-by: Matthew Brost 
Signed-off-by: Fernando Pacheco 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|  2 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c |  3 ++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 43 +++
 3 files changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index c79da154c16d..9c8d53a32e0d 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -271,6 +271,8 @@ int intel_guc_sched_done_process_msg(struct intel_guc *guc,
 const u32 *msg, u32 len);
 int intel_guc_context_reset_process_msg(struct intel_guc *guc,
const u32 *msg, u32 len);
+int intel_guc_engine_failure_process_msg(struct intel_guc *guc,
+const u32 *msg, u32 len);
 
 void intel_guc_submission_reset_prepare(struct intel_guc *guc);
 void intel_guc_submission_reset(struct intel_guc *guc, bool stalled);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
index 231a42887675..18917b443f05 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
@@ -987,6 +987,9 @@ static int ct_process_request(struct intel_guc_ct *ct, 
struct ct_incoming_msg *r
case INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION:
ret = intel_guc_context_reset_process_msg(guc, payload, len);
break;
+   case INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION:
+   ret = intel_guc_engine_failure_process_msg(guc, payload, len);
+   break;
default:
ret = -EOPNOTSUPP;
break;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 7be84b0761b5..d76494e3e271 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -2237,6 +2237,49 @@ int intel_guc_context_reset_process_msg(struct intel_guc 
*guc,
return 0;
 }
 
+static struct intel_engine_cs *
+guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance)
+{
+   struct intel_gt *gt = guc_to_gt(guc);
+   u8 engine_class = guc_class_to_engine_class(guc_class);
+
+   /* Class index is checked in class converter */
+   GEM_BUG_ON(instance > MAX_ENGINE_INSTANCE);
+
+   return gt->engine_class[engine_class][instance];
+}
+
+int intel_guc_engine_failure_process_msg(struct intel_guc *guc,
+const u32 *msg, u32 len)
+{
+   struct intel_engine_cs *engine;
+   u8 guc_class, instance;
+   u32 reason;
+
+   if (unlikely(len != 3)) {
+   drm_err(_to_gt(guc)->i915->drm, "Invalid length %u", len);
+   return -EPROTO;
+   }
+
+   guc_class = msg[0];
+   instance = msg[1];
+   reason = msg[2];
+
+   engine = guc_lookup_engine(guc, guc_class, instance);
+   if (unlikely(!engine)) {
+   drm_err(_to_gt(guc)->i915->drm,
+   "Invalid engine %d:%d", guc_class, instance);
+   return -EPROTO;
+   }
+
+   intel_gt_handle_error(guc_to_gt(guc), engine->mask,
+ I915_ERROR_CAPTURE,
+ "GuC failed to reset %s (reason=0x%08x)\n",
+ engine->name, reason);
+
+   return 0;
+}
+
 void intel_guc_submission_print_info(struct intel_guc *guc,
 struct drm_printer *p)
 {
-- 
2.28.0



[PATCH 21/33] drm/i915/guc: Connect reset modparam updates to GuC policy flags

2021-07-26 Thread Matthew Brost
From: John Harrison 

Changing the reset module parameter has no effect on a running GuC.
The corresponding entry in the ADS must be updated and then the GuC
informed via a Host2GuC message.

The new debugfs interface to module parameters allows this to happen.
However, connecting the parameter data address back to anything useful
is messy. One option would be to pass a new private data structure
address through instead of just the parameter pointer. However, that
means having a new (and different) data structure for each parameter
and a new (and different) write function for each parameter. This
method keeps everything generic by instead using a string lookup on
the directory entry name.

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c |  2 +-
 drivers/gpu/drm/i915/i915_debugfs_params.c | 32 ++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index 60b73625f686..7797766c56a9 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -99,7 +99,7 @@ static int guc_action_policies_update(struct intel_guc *guc, 
u32 policy_offset)
policy_offset
};
 
-   return intel_guc_send(guc, action, ARRAY_SIZE(action));
+   return intel_guc_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, 
true);
 }
 
 int intel_guc_global_policies_update(struct intel_guc *guc)
diff --git a/drivers/gpu/drm/i915/i915_debugfs_params.c 
b/drivers/gpu/drm/i915/i915_debugfs_params.c
index 4e2b077692cb..20424275d41e 100644
--- a/drivers/gpu/drm/i915/i915_debugfs_params.c
+++ b/drivers/gpu/drm/i915/i915_debugfs_params.c
@@ -6,9 +6,21 @@
 #include 
 
 #include "i915_debugfs_params.h"
+#include "gt/intel_gt.h"
+#include "gt/uc/intel_guc.h"
 #include "i915_drv.h"
 #include "i915_params.h"
 
+#define MATCH_DEBUGFS_NODE_NAME(_file, _name) \
+   (strcmp((_file)->f_path.dentry->d_name.name, (_name)) == 0)
+
+#define GET_I915(i915, name, ptr)  \
+   do {\
+   struct i915_params *params; \
+   params = container_of(((void *)(ptr)), typeof(*params), name);  
\
+   (i915) = container_of(params, typeof(*(i915)), params); \
+   } while (0)
+
 /* int param */
 static int i915_param_int_show(struct seq_file *m, void *data)
 {
@@ -24,6 +36,16 @@ static int i915_param_int_open(struct inode *inode, struct 
file *file)
return single_open(file, i915_param_int_show, inode->i_private);
 }
 
+static int notify_guc(struct drm_i915_private *i915)
+{
+   int ret = 0;
+
+   if (intel_uc_uses_guc_submission(>gt.uc))
+   ret = intel_guc_global_policies_update(>gt.uc.guc);
+
+   return ret;
+}
+
 static ssize_t i915_param_int_write(struct file *file,
const char __user *ubuf, size_t len,
loff_t *offp)
@@ -81,8 +103,10 @@ static ssize_t i915_param_uint_write(struct file *file,
 const char __user *ubuf, size_t len,
 loff_t *offp)
 {
+   struct drm_i915_private *i915;
struct seq_file *m = file->private_data;
unsigned int *value = m->private;
+   unsigned int old = *value;
int ret;
 
ret = kstrtouint_from_user(ubuf, len, 0, value);
@@ -95,6 +119,14 @@ static ssize_t i915_param_uint_write(struct file *file,
*value = b;
}
 
+   if (!ret && MATCH_DEBUGFS_NODE_NAME(file, "reset")) {
+   GET_I915(i915, reset, value);
+
+   ret = notify_guc(i915);
+   if (ret)
+   *value = old;
+   }
+
return ret ?: len;
 }
 
-- 
2.28.0



[PATCH 25/33] drm/i915/guc: Support request cancellation

2021-07-26 Thread Matthew Brost
This adds GuC backend support for i915_request_cancel(), which in turn
makes CONFIG_DRM_I915_REQUEST_TIMEOUT work.

This implementation makes use of fence while there are likely simplier
options. A fence was chosen because of another feature coming soon
which requires a user to block on a context until scheduling is
disabled. In that case we return the fence to the user and the user can
wait on that fence.

v2:
 (Daniele)
  - A comment about locking the blocked incr / decr
  - A comments about the use of the fence
  - Update commit message explaining why fence
  - Delete redundant check blocked count in unblock function
  - Ring buffer implementation
  - Comment about blocked in submission path
  - Shorter rpm path
v3:
 (Checkpatch)
  - Fix typos in commit message
 (Daniel)
  - Rework to simplier locking structure in guc_context_block / unblock

Signed-off-by: Matthew Brost 
Cc: Tvrtko Ursulin 
---
 drivers/gpu/drm/i915/gt/intel_context.c   |  13 ++
 drivers/gpu/drm/i915/gt/intel_context.h   |   7 +
 drivers/gpu/drm/i915/gt/intel_context_types.h |   9 +-
 .../drm/i915/gt/intel_execlists_submission.c  |  18 ++
 .../gpu/drm/i915/gt/intel_ring_submission.c   |  16 ++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 188 ++
 drivers/gpu/drm/i915/i915_request.c   |  14 +-
 7 files changed, 251 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_context.c 
b/drivers/gpu/drm/i915/gt/intel_context.c
index 237b70e98744..477c42d7d693 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -366,6 +366,12 @@ static int __intel_context_active(struct i915_active 
*active)
return 0;
 }
 
+static int sw_fence_dummy_notify(struct i915_sw_fence *sf,
+enum i915_sw_fence_notify state)
+{
+   return NOTIFY_DONE;
+}
+
 void
 intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
 {
@@ -399,6 +405,13 @@ intel_context_init(struct intel_context *ce, struct 
intel_engine_cs *engine)
ce->guc_id = GUC_INVALID_LRC_ID;
INIT_LIST_HEAD(>guc_id_link);
 
+   /*
+* Initialize fence to be complete as this is expected to be complete
+* unless there is a pending schedule disable outstanding.
+*/
+   i915_sw_fence_init(>guc_blocked, sw_fence_dummy_notify);
+   i915_sw_fence_commit(>guc_blocked);
+
i915_active_init(>active,
 __intel_context_active, __intel_context_retire, 0);
 }
diff --git a/drivers/gpu/drm/i915/gt/intel_context.h 
b/drivers/gpu/drm/i915/gt/intel_context.h
index 814d9277096a..876bdb08303c 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.h
+++ b/drivers/gpu/drm/i915/gt/intel_context.h
@@ -70,6 +70,13 @@ intel_context_is_pinned(struct intel_context *ce)
return atomic_read(>pin_count);
 }
 
+static inline void intel_context_cancel_request(struct intel_context *ce,
+   struct i915_request *rq)
+{
+   GEM_BUG_ON(!ce->ops->cancel_request);
+   return ce->ops->cancel_request(ce, rq);
+}
+
 /**
  * intel_context_unlock_pinned - Releases the earlier locking of 'pinned' 
status
  * @ce - the context
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h 
b/drivers/gpu/drm/i915/gt/intel_context_types.h
index 57c19ee3e313..a5bc876face7 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -13,6 +13,7 @@
 #include 
 
 #include "i915_active_types.h"
+#include "i915_sw_fence.h"
 #include "i915_utils.h"
 #include "intel_engine_types.h"
 #include "intel_sseu.h"
@@ -42,6 +43,9 @@ struct intel_context_ops {
void (*unpin)(struct intel_context *ce);
void (*post_unpin)(struct intel_context *ce);
 
+   void (*cancel_request)(struct intel_context *ce,
+  struct i915_request *rq);
+
void (*enter)(struct intel_context *ce);
void (*exit)(struct intel_context *ce);
 
@@ -156,7 +160,7 @@ struct intel_context {
 * sched_state: scheduling state of this context using GuC
 * submission
 */
-   u8 sched_state;
+   u16 sched_state;
/*
 * fences: maintains of list of requests that have a submit
 * fence related to GuC submission
@@ -184,6 +188,9 @@ struct intel_context {
 * GuC ID link - in list when unpinned but guc_id still valid in GuC
 */
struct list_head guc_id_link;
+
+   /* GuC context blocked fence */
+   struct i915_sw_fence guc_blocked;
 };
 
 #endif /* __INTEL_CONTEXT_TYPES__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c 
b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index b4a876736074..de5f9c86b9a4 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -114,6 +114,7 

[PATCH 17/33] drm/i915/guc: Enable GuC engine reset

2021-07-26 Thread Matthew Brost
From: John Harrison 

Clear the 'disable resets' flag to allow GuC to reset hung contexts
(detected via pre-emption timeout).

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index fdac8a7805f5..97cfaaaf2397 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -81,8 +81,7 @@ static void guc_policies_init(struct guc_policies *policies)
 {
policies->dpc_promote_time = GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US;
policies->max_num_work_items = GLOBAL_POLICY_MAX_NUM_WI;
-   /* Disable automatic resets as not yet supported. */
-   policies->global_flags = GLOBAL_POLICY_DISABLE_ENGINE_RESET;
+   policies->global_flags = 0;
policies->is_valid = 1;
 }
 
-- 
2.28.0



[PATCH 14/33] drm/i915/guc: Enable the timer expired interrupt for GuC

2021-07-26 Thread Matthew Brost
The GuC can implement execution qunatums, detect hung contexts and
other such things but it requires the timer expired interrupt to do so.

Signed-off-by: Matthew Brost 
CC: John Harrison 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/intel_rps.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c 
b/drivers/gpu/drm/i915/gt/intel_rps.c
index 06e9a8ed4e03..0c8e7f2b06f0 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -1877,6 +1877,10 @@ void intel_rps_init(struct intel_rps *rps)
 
if (GRAPHICS_VER(i915) >= 8 && GRAPHICS_VER(i915) < 11)
rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC;
+
+   /* GuC needs ARAT expired interrupt unmasked */
+   if (intel_uc_uses_guc_submission(_to_gt(rps)->uc))
+   rps->pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK;
 }
 
 void intel_rps_sanitize(struct intel_rps *rps)
-- 
2.28.0



[PATCH 22/33] drm/i915/guc: Include scheduling policies in the debugfs state dump

2021-07-26 Thread Matthew Brost
From: John Harrison 

Added the scheduling policy parameters to the 'guc_info' debugfs state
dump.

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 14 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h |  3 +++
 drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c |  2 ++
 3 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index 7797766c56a9..51fc14ee79cd 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -92,6 +92,20 @@ static void guc_policies_init(struct intel_guc *guc, struct 
guc_policies *polici
policies->is_valid = 1;
 }
 
+void intel_guc_ads_print_policy_info(struct intel_guc *guc,
+struct drm_printer *dp)
+{
+   struct __guc_ads_blob *blob = guc->ads_blob;
+
+   if (unlikely(!blob))
+   return;
+
+   drm_printf(dp, "Global scheduling policies:\n");
+   drm_printf(dp, "  DPC promote time   = %u\n", 
blob->policies.dpc_promote_time);
+   drm_printf(dp, "  Max num work items = %u\n", 
blob->policies.max_num_work_items);
+   drm_printf(dp, "  Flags  = %u\n", 
blob->policies.global_flags);
+}
+
 static int guc_action_policies_update(struct intel_guc *guc, u32 policy_offset)
 {
u32 action[] = {
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h
index b00d3ae1113a..bdcb339a5321 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h
@@ -7,9 +7,12 @@
 #define _INTEL_GUC_ADS_H_
 
 struct intel_guc;
+struct drm_printer;
 
 int intel_guc_ads_create(struct intel_guc *guc);
 void intel_guc_ads_destroy(struct intel_guc *guc);
 void intel_guc_ads_reset(struct intel_guc *guc);
+void intel_guc_ads_print_policy_info(struct intel_guc *guc,
+struct drm_printer *p);
 
 #endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
index 7a454c91a736..72ddfff42f7d 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
@@ -10,6 +10,7 @@
 #include "intel_guc_debugfs.h"
 #include "intel_guc_log_debugfs.h"
 #include "gt/uc/intel_guc_ct.h"
+#include "gt/uc/intel_guc_ads.h"
 #include "gt/uc/intel_guc_submission.h"
 
 static int guc_info_show(struct seq_file *m, void *data)
@@ -29,6 +30,7 @@ static int guc_info_show(struct seq_file *m, void *data)
 
intel_guc_ct_print_info(>ct, );
intel_guc_submission_print_info(guc, );
+   intel_guc_ads_print_policy_info(guc, );
 
return 0;
 }
-- 
2.28.0



[PATCH 31/33] drm/i915/selftest: Bump selftest timeouts for hangcheck

2021-07-26 Thread Matthew Brost
From: John Harrison 

Some testing environments and some heavier tests are slower than
previous limits allowed for. For example, it can take multiple seconds
for the 'context has been reset' notification handler to reach the
'kill the requests' code in the 'active' version of the 'reset
engines' test. During which time the selftest gets bored, gives up
waiting and fails the test.

There is also an async thread that the selftest uses to pump work
through the hardware in parallel to the context that is marked for
reset. That also could get bored waiting for completions and kill the
test off.

Lastly, the flush at the of various test sections can also see
timeouts due to the large amount of work backed up. This is also true
of the live_hwsp_read test.

Signed-off-by: John Harrison 
Signed-off-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 2 +-
 drivers/gpu/drm/i915/selftests/igt_flush_test.c  | 2 +-
 drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c 
b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
index e0e200ba77e9..08f011f893b2 100644
--- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
@@ -879,7 +879,7 @@ static int active_request_put(struct i915_request *rq)
if (!rq)
return 0;
 
-   if (i915_request_wait(rq, 0, 5 * HZ) < 0) {
+   if (i915_request_wait(rq, 0, 10 * HZ) < 0) {
GEM_TRACE("%s timed out waiting for completion of fence 
%llx:%lld\n",
  rq->engine->name,
  rq->fence.context,
diff --git a/drivers/gpu/drm/i915/selftests/igt_flush_test.c 
b/drivers/gpu/drm/i915/selftests/igt_flush_test.c
index 7b0939e3f007..a6c71fca61aa 100644
--- a/drivers/gpu/drm/i915/selftests/igt_flush_test.c
+++ b/drivers/gpu/drm/i915/selftests/igt_flush_test.c
@@ -19,7 +19,7 @@ int igt_flush_test(struct drm_i915_private *i915)
 
cond_resched();
 
-   if (intel_gt_wait_for_idle(gt, HZ / 5) == -ETIME) {
+   if (intel_gt_wait_for_idle(gt, HZ) == -ETIME) {
pr_err("%pS timed out, cancelling all further testing.\n",
   __builtin_return_address(0));
 
diff --git a/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c 
b/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
index dac275e835c4..4b328346b48a 100644
--- a/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
+++ b/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
@@ -12,7 +12,7 @@
 
 #define REDUCED_TIMESLICE  5
 #define REDUCED_PREEMPT10
-#define WAIT_FOR_RESET_TIME1000
+#define WAIT_FOR_RESET_TIME1
 
 int intel_selftest_modify_policy(struct intel_engine_cs *engine,
 struct intel_selftest_saved_policy *saved,
-- 
2.28.0



[PATCH 15/33] drm/i915/guc: Provide mmio list to be saved/restored on engine reset

2021-07-26 Thread Matthew Brost
From: John Harrison 

The driver must provide GuC with a list of mmio registers
that should be saved/restored during a GuC-based engine reset.
Unfortunately, the list must be dynamically allocated as its size is
variable. That means the driver must generate the list twice - once to
work out the size and a second time to actually save it.

v2:
 (Alan / CI)
  - GEN7_GT_MODE -> GEN6_GT_MODE to fix WA selftest failure

Signed-off-by: John Harrison 
Signed-off-by: Fernando Pacheco 
Signed-off-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
Cc: Tvrtko Ursulin 
Reviewed-by: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/intel_workarounds.c   |  46 ++--
 .../gpu/drm/i915/gt/intel_workarounds_types.h |   1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 199 +-
 drivers/gpu/drm/i915/i915_reg.h   |   1 +
 5 files changed, 222 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 3aa5ce3cda8b..9173df59821a 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -150,13 +150,14 @@ static void _wa_add(struct i915_wa_list *wal, const 
struct i915_wa *wa)
 }
 
 static void wa_add(struct i915_wa_list *wal, i915_reg_t reg,
-  u32 clear, u32 set, u32 read_mask)
+  u32 clear, u32 set, u32 read_mask, bool masked_reg)
 {
struct i915_wa wa = {
.reg  = reg,
.clr  = clear,
.set  = set,
.read = read_mask,
+   .masked_reg = masked_reg,
};
 
_wa_add(wal, );
@@ -165,7 +166,7 @@ static void wa_add(struct i915_wa_list *wal, i915_reg_t reg,
 static void
 wa_write_clr_set(struct i915_wa_list *wal, i915_reg_t reg, u32 clear, u32 set)
 {
-   wa_add(wal, reg, clear, set, clear);
+   wa_add(wal, reg, clear, set, clear, false);
 }
 
 static void
@@ -200,20 +201,20 @@ wa_write_clr(struct i915_wa_list *wal, i915_reg_t reg, 
u32 clr)
 static void
 wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
-   wa_add(wal, reg, 0, _MASKED_BIT_ENABLE(val), val);
+   wa_add(wal, reg, 0, _MASKED_BIT_ENABLE(val), val, true);
 }
 
 static void
 wa_masked_dis(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
-   wa_add(wal, reg, 0, _MASKED_BIT_DISABLE(val), val);
+   wa_add(wal, reg, 0, _MASKED_BIT_DISABLE(val), val, true);
 }
 
 static void
 wa_masked_field_set(struct i915_wa_list *wal, i915_reg_t reg,
u32 mask, u32 val)
 {
-   wa_add(wal, reg, 0, _MASKED_FIELD(mask, val), mask);
+   wa_add(wal, reg, 0, _MASKED_FIELD(mask, val), mask, true);
 }
 
 static void gen6_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -533,10 +534,10 @@ static void icl_ctx_workarounds_init(struct 
intel_engine_cs *engine,
wa_masked_en(wal, ICL_HDC_MODE, HDC_FORCE_NON_COHERENT);
 
/* WaEnableFloatBlendOptimization:icl */
-   wa_write_clr_set(wal,
-GEN10_CACHE_MODE_SS,
-0, /* write-only, so skip validation */
-_MASKED_BIT_ENABLE(FLOAT_BLEND_OPTIMIZATION_ENABLE));
+   wa_add(wal, GEN10_CACHE_MODE_SS, 0,
+  _MASKED_BIT_ENABLE(FLOAT_BLEND_OPTIMIZATION_ENABLE),
+  0 /* write-only, so skip validation */,
+  true);
 
/* WaDisableGPGPUMidThreadPreemption:icl */
wa_masked_field_set(wal, GEN8_CS_CHICKEN1,
@@ -581,7 +582,7 @@ static void gen12_ctx_gt_tuning_init(struct intel_engine_cs 
*engine,
   FF_MODE2,
   FF_MODE2_TDS_TIMER_MASK,
   FF_MODE2_TDS_TIMER_128,
-  0);
+  0, false);
 }
 
 static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -619,7 +620,7 @@ static void gen12_ctx_workarounds_init(struct 
intel_engine_cs *engine,
   FF_MODE2,
   FF_MODE2_GS_TIMER_MASK,
   FF_MODE2_GS_TIMER_224,
-  0);
+  0, false);
 
/*
 * Wa_14012131227:dg1
@@ -795,7 +796,7 @@ hsw_gt_workarounds_init(struct drm_i915_private *i915, 
struct i915_wa_list *wal)
wa_add(wal,
   HSW_ROW_CHICKEN3, 0,
   _MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE),
-   0 /* XXX does this reg exist? */);
+  0 /* XXX does this reg exist? */, true);
 
/* WaVSRefCountFullforceMissDisable:hsw */
wa_write_clr(wal, GEN7_FF_THREAD_MODE, GEN7_FF_VS_REF_CNT_FFME);
@@ -1824,10 +1825,10 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, 
struct i915_wa_list *wal)
 * disable bit, which we don't touch here, but it's good
 * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
 */
-   wa_add(wal, GEN7_GT_MODE, 0,
-  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK,
-

[PATCH 24/33] drm/i915/guc: Implement banned contexts for GuC submission

2021-07-26 Thread Matthew Brost
When using GuC submission, if a context gets banned disable scheduling
and mark all inflight requests as complete.

Cc: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gem/i915_gem_context.c   |   2 +-
 drivers/gpu/drm/i915/gt/intel_context.h   |  13 ++
 drivers/gpu/drm/i915/gt/intel_context_types.h |   2 +
 drivers/gpu/drm/i915/gt/intel_reset.c |  32 +---
 .../gpu/drm/i915/gt/intel_ring_submission.c   |  20 +++
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   2 +
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 151 --
 drivers/gpu/drm/i915/i915_trace.h |  10 ++
 8 files changed, 195 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c 
b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index e3df01a201d7..05c3ee191710 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -1084,7 +1084,7 @@ static void kill_engines(struct i915_gem_engines 
*engines, bool ban)
for_each_gem_engine(ce, engines, it) {
struct intel_engine_cs *engine;
 
-   if (ban && intel_context_set_banned(ce))
+   if (ban && intel_context_ban(ce, NULL))
continue;
 
/*
diff --git a/drivers/gpu/drm/i915/gt/intel_context.h 
b/drivers/gpu/drm/i915/gt/intel_context.h
index 2ed9bf5f91a5..814d9277096a 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.h
+++ b/drivers/gpu/drm/i915/gt/intel_context.h
@@ -16,6 +16,7 @@
 #include "intel_engine_types.h"
 #include "intel_ring_types.h"
 #include "intel_timeline_types.h"
+#include "i915_trace.h"
 
 #define CE_TRACE(ce, fmt, ...) do {\
const struct intel_context *ce__ = (ce);\
@@ -243,6 +244,18 @@ static inline bool intel_context_set_banned(struct 
intel_context *ce)
return test_and_set_bit(CONTEXT_BANNED, >flags);
 }
 
+static inline bool intel_context_ban(struct intel_context *ce,
+struct i915_request *rq)
+{
+   bool ret = intel_context_set_banned(ce);
+
+   trace_intel_context_ban(ce);
+   if (ce->ops->ban)
+   ce->ops->ban(ce, rq);
+
+   return ret;
+}
+
 static inline bool
 intel_context_force_single_submission(const struct intel_context *ce)
 {
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h 
b/drivers/gpu/drm/i915/gt/intel_context_types.h
index 035108c10b2c..57c19ee3e313 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -35,6 +35,8 @@ struct intel_context_ops {
 
int (*alloc)(struct intel_context *ce);
 
+   void (*ban)(struct intel_context *ce, struct i915_request *rq);
+
int (*pre_pin)(struct intel_context *ce, struct i915_gem_ww_ctx *ww, 
void **vaddr);
int (*pin)(struct intel_context *ce, void *vaddr);
void (*unpin)(struct intel_context *ce);
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c 
b/drivers/gpu/drm/i915/gt/intel_reset.c
index 4d281bc8a38c..91200c43951f 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -22,7 +22,6 @@
 #include "intel_reset.h"
 
 #include "uc/intel_guc.h"
-#include "uc/intel_guc_submission.h"
 
 #define RESET_MAX_RETRIES 3
 
@@ -39,21 +38,6 @@ static void rmw_clear_fw(struct intel_uncore *uncore, 
i915_reg_t reg, u32 clr)
intel_uncore_rmw_fw(uncore, reg, clr, 0);
 }
 
-static void skip_context(struct i915_request *rq)
-{
-   struct intel_context *hung_ctx = rq->context;
-
-   list_for_each_entry_from_rcu(rq, _ctx->timeline->requests, link) {
-   if (!i915_request_is_active(rq))
-   return;
-
-   if (rq->context == hung_ctx) {
-   i915_request_set_error_once(rq, -EIO);
-   __i915_request_skip(rq);
-   }
-   }
-}
-
 static void client_mark_guilty(struct i915_gem_context *ctx, bool banned)
 {
struct drm_i915_file_private *file_priv = ctx->file_priv;
@@ -88,10 +72,8 @@ static bool mark_guilty(struct i915_request *rq)
bool banned;
int i;
 
-   if (intel_context_is_closed(rq->context)) {
-   intel_context_set_banned(rq->context);
+   if (intel_context_is_closed(rq->context))
return true;
-   }
 
rcu_read_lock();
ctx = rcu_dereference(rq->context->gem_context);
@@ -123,11 +105,9 @@ static bool mark_guilty(struct i915_request *rq)
banned = !i915_gem_context_is_recoverable(ctx);
if (time_before(jiffies, prev_hang + CONTEXT_FAST_HANG_JIFFIES))
banned = true;
-   if (banned) {
+   if (banned)
drm_dbg(>i915->drm, "context %s: guilty %d, banned\n",
ctx->name, atomic_read(>guilty_count));
-   intel_context_set_banned(rq->context);
-   }
 

[PATCH 12/33] drm/i915/guc: Handle context reset notification

2021-07-26 Thread Matthew Brost
GuC will issue a reset on detecting an engine hang and will notify
the driver via a G2H message. The driver will service the notification
by resetting the guilty context to a simple state or banning it
completely.

v2:
 (John Harrison)
  - Move msg[0] lookup after length check
v3:
 (John Harrison)
  - s/drm_dbg/drm_err

Cc: Matthew Brost 
Cc: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|  2 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c |  3 ++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 36 +++
 drivers/gpu/drm/i915/i915_trace.h | 10 ++
 4 files changed, 51 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 7b871f675e48..c79da154c16d 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -269,6 +269,8 @@ int intel_guc_deregister_done_process_msg(struct intel_guc 
*guc,
  const u32 *msg, u32 len);
 int intel_guc_sched_done_process_msg(struct intel_guc *guc,
 const u32 *msg, u32 len);
+int intel_guc_context_reset_process_msg(struct intel_guc *guc,
+   const u32 *msg, u32 len);
 
 void intel_guc_submission_reset_prepare(struct intel_guc *guc);
 void intel_guc_submission_reset(struct intel_guc *guc, bool stalled);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
index 8bb6b1bbcea1..231a42887675 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
@@ -984,6 +984,9 @@ static int ct_process_request(struct intel_guc_ct *ct, 
struct ct_incoming_msg *r
case INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
ret = intel_guc_sched_done_process_msg(guc, payload, len);
break;
+   case INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION:
+   ret = intel_guc_context_reset_process_msg(guc, payload, len);
+   break;
default:
ret = -EOPNOTSUPP;
break;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index d39a312e980a..7be84b0761b5 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -2201,6 +2201,42 @@ int intel_guc_sched_done_process_msg(struct intel_guc 
*guc,
return 0;
 }
 
+static void guc_context_replay(struct intel_context *ce)
+{
+   struct i915_sched_engine *sched_engine = ce->engine->sched_engine;
+
+   __guc_reset_context(ce, true);
+   tasklet_hi_schedule(_engine->tasklet);
+}
+
+static void guc_handle_context_reset(struct intel_guc *guc,
+struct intel_context *ce)
+{
+   trace_intel_context_reset(ce);
+   guc_context_replay(ce);
+}
+
+int intel_guc_context_reset_process_msg(struct intel_guc *guc,
+   const u32 *msg, u32 len)
+{
+   struct intel_context *ce;
+   int desc_idx;
+
+   if (unlikely(len != 1)) {
+   drm_err(_to_gt(guc)->i915->drm, "Invalid length %u", len);
+   return -EPROTO;
+   }
+
+   desc_idx = msg[0];
+   ce = g2h_context_lookup(guc, desc_idx);
+   if (unlikely(!ce))
+   return -EPROTO;
+
+   guc_handle_context_reset(guc, ce);
+
+   return 0;
+}
+
 void intel_guc_submission_print_info(struct intel_guc *guc,
 struct drm_printer *p)
 {
diff --git a/drivers/gpu/drm/i915/i915_trace.h 
b/drivers/gpu/drm/i915/i915_trace.h
index 68b70626c3e2..3f43d904f043 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -920,6 +920,11 @@ DECLARE_EVENT_CLASS(intel_context,
  __entry->guc_sched_state_no_lock)
 );
 
+DEFINE_EVENT(intel_context, intel_context_reset,
+TP_PROTO(struct intel_context *ce),
+TP_ARGS(ce)
+);
+
 DEFINE_EVENT(intel_context, intel_context_register,
 TP_PROTO(struct intel_context *ce),
 TP_ARGS(ce)
@@ -1007,6 +1012,11 @@ trace_i915_request_out(struct i915_request *rq)
 {
 }
 
+static inline void
+trace_intel_context_reset(struct intel_context *ce)
+{
+}
+
 static inline void
 trace_intel_context_register(struct intel_context *ce)
 {
-- 
2.28.0



[PATCH 10/33] drm/i915/guc: Add disable interrupts to guc sanitize

2021-07-26 Thread Matthew Brost
Add disable GuC interrupts to intel_guc_sanitize(). Part of this
requires moving the guc_*_interrupt wrapper function into header file
intel_guc.h.

Signed-off-by: Matthew Brost 
Cc: Daniele Ceraolo Spurio 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.h | 16 
 drivers/gpu/drm/i915/gt/uc/intel_uc.c  | 21 +++--
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index a068e3262676..7b871f675e48 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -224,9 +224,25 @@ static inline bool intel_guc_is_ready(struct intel_guc 
*guc)
return intel_guc_is_fw_running(guc) && intel_guc_ct_enabled(>ct);
 }
 
+static inline void intel_guc_reset_interrupts(struct intel_guc *guc)
+{
+   guc->interrupts.reset(guc);
+}
+
+static inline void intel_guc_enable_interrupts(struct intel_guc *guc)
+{
+   guc->interrupts.enable(guc);
+}
+
+static inline void intel_guc_disable_interrupts(struct intel_guc *guc)
+{
+   guc->interrupts.disable(guc);
+}
+
 static inline int intel_guc_sanitize(struct intel_guc *guc)
 {
intel_uc_fw_sanitize(>fw);
+   intel_guc_disable_interrupts(guc);
intel_guc_ct_sanitize(>ct);
guc->mmio_msg = 0;
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index 9a5ef1dca022..05a2001afde9 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -207,21 +207,6 @@ static void guc_handle_mmio_msg(struct intel_guc *guc)
spin_unlock_irq(>irq_lock);
 }
 
-static void guc_reset_interrupts(struct intel_guc *guc)
-{
-   guc->interrupts.reset(guc);
-}
-
-static void guc_enable_interrupts(struct intel_guc *guc)
-{
-   guc->interrupts.enable(guc);
-}
-
-static void guc_disable_interrupts(struct intel_guc *guc)
-{
-   guc->interrupts.disable(guc);
-}
-
 static int guc_enable_communication(struct intel_guc *guc)
 {
struct intel_gt *gt = guc_to_gt(guc);
@@ -242,7 +227,7 @@ static int guc_enable_communication(struct intel_guc *guc)
guc_get_mmio_msg(guc);
guc_handle_mmio_msg(guc);
 
-   guc_enable_interrupts(guc);
+   intel_guc_enable_interrupts(guc);
 
/* check for CT messages received before we enabled interrupts */
spin_lock_irq(>irq_lock);
@@ -265,7 +250,7 @@ static void guc_disable_communication(struct intel_guc *guc)
 */
guc_clear_mmio_msg(guc);
 
-   guc_disable_interrupts(guc);
+   intel_guc_disable_interrupts(guc);
 
intel_guc_ct_disable(>ct);
 
@@ -463,7 +448,7 @@ static int __uc_init_hw(struct intel_uc *uc)
if (ret)
goto err_out;
 
-   guc_reset_interrupts(guc);
+   intel_guc_reset_interrupts(guc);
 
/* WaEnableuKernelHeaderValidFix:skl */
/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
-- 
2.28.0



[PATCH 06/33] drm/i915: Add i915_sched_engine destroy vfunc

2021-07-26 Thread Matthew Brost
This is required to allow backend specific cleanup

v2:
 (John H)
  - Rework commit message

Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_scheduler.c   | 3 ++-
 drivers/gpu/drm/i915/i915_scheduler.h   | 4 +---
 drivers/gpu/drm/i915/i915_scheduler_types.h | 5 +
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 561c649e59f7..2804fd5b660b 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -431,7 +431,7 @@ void i915_request_show_with_schedule(struct drm_printer *m,
rcu_read_unlock();
 }
 
-void i915_sched_engine_free(struct kref *kref)
+static void default_destroy(struct kref *kref)
 {
struct i915_sched_engine *sched_engine =
container_of(kref, typeof(*sched_engine), ref);
@@ -453,6 +453,7 @@ i915_sched_engine_create(unsigned int subclass)
 
sched_engine->queue = RB_ROOT_CACHED;
sched_engine->queue_priority_hint = INT_MIN;
+   sched_engine->destroy = default_destroy;
 
INIT_LIST_HEAD(_engine->requests);
INIT_LIST_HEAD(_engine->hold);
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index 650ab8e0db9f..3c9504e9f409 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -51,8 +51,6 @@ static inline void i915_priolist_free(struct i915_priolist *p)
 struct i915_sched_engine *
 i915_sched_engine_create(unsigned int subclass);
 
-void i915_sched_engine_free(struct kref *kref);
-
 static inline struct i915_sched_engine *
 i915_sched_engine_get(struct i915_sched_engine *sched_engine)
 {
@@ -63,7 +61,7 @@ i915_sched_engine_get(struct i915_sched_engine *sched_engine)
 static inline void
 i915_sched_engine_put(struct i915_sched_engine *sched_engine)
 {
-   kref_put(_engine->ref, i915_sched_engine_free);
+   kref_put(_engine->ref, sched_engine->destroy);
 }
 
 static inline bool
diff --git a/drivers/gpu/drm/i915/i915_scheduler_types.h 
b/drivers/gpu/drm/i915/i915_scheduler_types.h
index 5935c3152bdc..00384e2c5273 100644
--- a/drivers/gpu/drm/i915/i915_scheduler_types.h
+++ b/drivers/gpu/drm/i915/i915_scheduler_types.h
@@ -163,6 +163,11 @@ struct i915_sched_engine {
 */
void *private_data;
 
+   /**
+* @destroy: destroy schedule engine / cleanup in backend
+*/
+   void(*destroy)(struct kref *kref);
+
/**
 * @kick_backend: kick backend after a request's priority has changed
 */
-- 
2.28.0



[PATCH 07/33] drm/i915: Move active request tracking to a vfunc

2021-07-26 Thread Matthew Brost
Move active request tracking to a backend vfunc rather than assuming all
backends want to do this in the manner. In the of case execlists /
ring submission the tracking is on the physical engine while with GuC
submission it is on the context.

Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/intel_context.c   |  3 ++
 drivers/gpu/drm/i915/gt/intel_context_types.h |  7 
 drivers/gpu/drm/i915/gt/intel_engine_types.h  |  6 +++
 .../drm/i915/gt/intel_execlists_submission.c  | 40 ++
 .../gpu/drm/i915/gt/intel_ring_submission.c   | 22 ++
 drivers/gpu/drm/i915/gt/mock_engine.c | 30 ++
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 33 +++
 drivers/gpu/drm/i915/i915_request.c   | 41 ++-
 drivers/gpu/drm/i915/i915_request.h   |  2 +
 9 files changed, 147 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_context.c 
b/drivers/gpu/drm/i915/gt/intel_context.c
index baa05fddd690..0bf4a13e9759 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -393,6 +393,9 @@ intel_context_init(struct intel_context *ce, struct 
intel_engine_cs *engine)
spin_lock_init(>guc_state.lock);
INIT_LIST_HEAD(>guc_state.fences);
 
+   spin_lock_init(>guc_active.lock);
+   INIT_LIST_HEAD(>guc_active.requests);
+
ce->guc_id = GUC_INVALID_LRC_ID;
INIT_LIST_HEAD(>guc_id_link);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h 
b/drivers/gpu/drm/i915/gt/intel_context_types.h
index 542c98418771..035108c10b2c 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -162,6 +162,13 @@ struct intel_context {
struct list_head fences;
} guc_state;
 
+   struct {
+   /** lock: protects everything in guc_active */
+   spinlock_t lock;
+   /** requests: active requests on this context */
+   struct list_head requests;
+   } guc_active;
+
/* GuC scheduling state flags that do not require a lock. */
atomic_t guc_sched_state_no_lock;
 
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h 
b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index e55776e27a2a..1c7e2724cdae 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -414,6 +414,12 @@ struct intel_engine_cs {
 
void(*release)(struct intel_engine_cs *engine);
 
+   /*
+* Add / remove request from engine active tracking
+*/
+   void(*add_active_request)(struct i915_request *rq);
+   void(*remove_active_request)(struct i915_request *rq);
+
struct intel_engine_execlists execlists;
 
/*
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c 
b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index 6e4959ee5065..b4a876736074 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -3157,6 +3157,42 @@ static void execlists_park(struct intel_engine_cs 
*engine)
cancel_timer(>execlists.preempt);
 }
 
+static void add_to_engine(struct i915_request *rq)
+{
+   lockdep_assert_held(>engine->sched_engine->lock);
+   list_move_tail(>sched.link, >engine->sched_engine->requests);
+}
+
+static void remove_from_engine(struct i915_request *rq)
+{
+   struct intel_engine_cs *engine, *locked;
+
+   /*
+* Virtual engines complicate acquiring the engine timeline lock,
+* as their rq->engine pointer is not stable until under that
+* engine lock. The simple ploy we use is to take the lock then
+* check that the rq still belongs to the newly locked engine.
+*/
+   locked = READ_ONCE(rq->engine);
+   spin_lock_irq(>sched_engine->lock);
+   while (unlikely(locked != (engine = READ_ONCE(rq->engine {
+   spin_unlock(>sched_engine->lock);
+   spin_lock(>sched_engine->lock);
+   locked = engine;
+   }
+   list_del_init(>sched.link);
+
+   clear_bit(I915_FENCE_FLAG_PQUEUE, >fence.flags);
+   clear_bit(I915_FENCE_FLAG_HOLD, >fence.flags);
+
+   /* Prevent further __await_execution() registering a cb, then flush */
+   set_bit(I915_FENCE_FLAG_ACTIVE, >fence.flags);
+
+   spin_unlock_irq(>sched_engine->lock);
+
+   i915_request_notify_execute_cb_imm(rq);
+}
+
 static bool can_preempt(struct intel_engine_cs *engine)
 {
if (GRAPHICS_VER(engine->i915) > 8)
@@ -3251,6 +3287,8 @@ logical_ring_default_vfuncs(struct intel_engine_cs 
*engine)
 
engine->cops = _context_ops;
engine->request_alloc = execlists_request_alloc;
+   engine->add_active_request = add_to_engine;
+   engine->remove_active_request = remove_from_engine;
 

[PATCH 01/33] drm/i915/guc: GuC virtual engines

2021-07-26 Thread Matthew Brost
Implement GuC virtual engines. Rather simple implementation, basically
just allocate an engine, setup context enter / exit function to virtual
engine specific functions, set all other variables / functions to guc
versions, and set the engine mask to that of all the siblings.

v2: Update to work with proto-ctx
v3:
 (Daniele)
  - Drop include, add comment to intel_virtual_engine_has_heartbeat

Cc: Daniele Ceraolo Spurio 
Signed-off-by: Matthew Brost 
Reviewed-by: Daniele Ceraolo Spurio 
---
 drivers/gpu/drm/i915/gem/i915_gem_context.c   |   8 +-
 drivers/gpu/drm/i915/gt/intel_context_types.h |   6 +
 drivers/gpu/drm/i915/gt/intel_engine.h|  30 ++-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c |  14 +
 .../drm/i915/gt/intel_execlists_submission.c  |  29 ++-
 .../drm/i915/gt/intel_execlists_submission.h  |   4 -
 drivers/gpu/drm/i915/gt/selftest_execlists.c  |  12 +-
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 242 +-
 .../gpu/drm/i915/gt/uc/intel_guc_submission.h |   2 +
 9 files changed, 311 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c 
b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 89ca401bf9ae..bc52eeed782a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -74,7 +74,6 @@
 #include "gt/intel_context_param.h"
 #include "gt/intel_engine_heartbeat.h"
 #include "gt/intel_engine_user.h"
-#include "gt/intel_execlists_submission.h" /* virtual_engine */
 #include "gt/intel_gpu_commands.h"
 #include "gt/intel_ring.h"
 
@@ -363,9 +362,6 @@ set_proto_ctx_engines_balance(struct i915_user_extension 
__user *base,
if (!HAS_EXECLISTS(i915))
return -ENODEV;
 
-   if (intel_uc_uses_guc_submission(>gt.uc))
-   return -ENODEV; /* not implement yet */
-
if (get_user(idx, >engine_index))
return -EFAULT;
 
@@ -950,8 +946,8 @@ static struct i915_gem_engines *user_engines(struct 
i915_gem_context *ctx,
break;
 
case I915_GEM_ENGINE_TYPE_BALANCED:
-   ce = intel_execlists_create_virtual(pe[n].siblings,
-   pe[n].num_siblings);
+   ce = intel_engine_create_virtual(pe[n].siblings,
+pe[n].num_siblings);
break;
 
case I915_GEM_ENGINE_TYPE_INVALID:
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h 
b/drivers/gpu/drm/i915/gt/intel_context_types.h
index 4a5518d295c2..542c98418771 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -47,6 +47,12 @@ struct intel_context_ops {
 
void (*reset)(struct intel_context *ce);
void (*destroy)(struct kref *kref);
+
+   /* virtual engine/context interface */
+   struct intel_context *(*create_virtual)(struct intel_engine_cs **engine,
+   unsigned int count);
+   struct intel_engine_cs *(*get_sibling)(struct intel_engine_cs *engine,
+  unsigned int sibling);
 };
 
 struct intel_context {
diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h 
b/drivers/gpu/drm/i915/gt/intel_engine.h
index f911c1224ab2..13bfb7ec33b2 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -273,13 +273,41 @@ intel_engine_has_preempt_reset(const struct 
intel_engine_cs *engine)
return intel_engine_has_preemption(engine);
 }
 
+struct intel_context *
+intel_engine_create_virtual(struct intel_engine_cs **siblings,
+   unsigned int count);
+
+static inline bool
+intel_virtual_engine_has_heartbeat(const struct intel_engine_cs *engine)
+{
+   /*
+* For non-GuC submission we expect the back-end to look at the
+* heartbeat status of the actual physical engine that the work
+* has been (or is being) scheduled on, so we should only reach
+* here with GuC submission enabled.
+*/
+   GEM_BUG_ON(!intel_engine_uses_guc(engine));
+
+   return intel_guc_virtual_engine_has_heartbeat(engine);
+}
+
 static inline bool
 intel_engine_has_heartbeat(const struct intel_engine_cs *engine)
 {
if (!IS_ACTIVE(CONFIG_DRM_I915_HEARTBEAT_INTERVAL))
return false;
 
-   return READ_ONCE(engine->props.heartbeat_interval_ms);
+   if (intel_engine_is_virtual(engine))
+   return intel_virtual_engine_has_heartbeat(engine);
+   else
+   return READ_ONCE(engine->props.heartbeat_interval_ms);
+}
+
+static inline struct intel_engine_cs *
+intel_engine_get_sibling(struct intel_engine_cs *engine, unsigned int sibling)
+{
+   GEM_BUG_ON(!intel_engine_is_virtual(engine));
+   return engine->cops->get_sibling(engine, sibling);
 }
 
 #endif /* _INTEL_RINGBUFFER_H_ */

[PATCH 08/33] drm/i915/guc: Reset implementation for new GuC interface

2021-07-26 Thread Matthew Brost
Reset implementation for new GuC interface. This is the legacy reset
implementation which is called when the i915 owns the engine hang check.
Future patches will offload the engine hang check to GuC but we will
continue to maintain this legacy path as a fallback and this code path
is also required if the GuC dies.

With the new GuC interface it is not possible to reset individual
engines - it is only possible to reset the GPU entirely. This patch
forces an entire chip reset if any engine hangs.

v2:
 (Michal)
  - Check for -EPIPE rather than -EIO (CT deadlock/corrupt check)
v3:
 (John H)
  - Split into a series of smaller patches
v4:
 (John H)
  - Fix typo
  - Add braces around if statements in reset code
v5:
 (Checkpatch)
  - Fix warnings

Cc: John Harrison 
Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/intel_gt_pm.c |   6 +-
 drivers/gpu/drm/i915/gt/intel_reset.c |  18 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.c|  13 -
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   8 +-
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 562 ++
 drivers/gpu/drm/i915/gt/uc/intel_uc.c |  38 +-
 drivers/gpu/drm/i915/gt/uc/intel_uc.h |   3 +
 7 files changed, 516 insertions(+), 132 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c 
b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index d86825437516..cd7b96005d29 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -170,8 +170,6 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
if (intel_gt_is_wedged(gt))
intel_gt_unset_wedged(gt);
 
-   intel_uc_sanitize(>uc);
-
for_each_engine(engine, gt, id)
if (engine->reset.prepare)
engine->reset.prepare(engine);
@@ -187,6 +185,8 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
__intel_engine_reset(engine, false);
}
 
+   intel_uc_reset(>uc, false);
+
for_each_engine(engine, gt, id)
if (engine->reset.finish)
engine->reset.finish(engine);
@@ -239,6 +239,8 @@ int intel_gt_resume(struct intel_gt *gt)
goto err_wedged;
}
 
+   intel_uc_reset_finish(>uc);
+
intel_rps_enable(>rps);
intel_llc_enable(>llc);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c 
b/drivers/gpu/drm/i915/gt/intel_reset.c
index 9586613ee399..721a10e2215e 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -832,6 +832,8 @@ static int gt_reset(struct intel_gt *gt, 
intel_engine_mask_t stalled_mask)
__intel_engine_reset(engine, stalled_mask & engine->mask);
local_bh_enable();
 
+   intel_uc_reset(>uc, true);
+
intel_ggtt_restore_fences(gt->ggtt);
 
return err;
@@ -856,6 +858,8 @@ static void reset_finish(struct intel_gt *gt, 
intel_engine_mask_t awake)
if (awake & engine->mask)
intel_engine_pm_put(engine);
}
+
+   intel_uc_reset_finish(>uc);
 }
 
 static void nop_submit_request(struct i915_request *request)
@@ -909,6 +913,7 @@ static void __intel_gt_set_wedged(struct intel_gt *gt)
for_each_engine(engine, gt, id)
if (engine->reset.cancel)
engine->reset.cancel(engine);
+   intel_uc_cancel_requests(>uc);
local_bh_enable();
 
reset_finish(gt, awake);
@@ -1197,6 +1202,9 @@ int __intel_engine_reset_bh(struct intel_engine_cs 
*engine, const char *msg)
ENGINE_TRACE(engine, "flags=%lx\n", gt->reset.flags);
GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, >reset.flags));
 
+   if (intel_engine_uses_guc(engine))
+   return -ENODEV;
+
if (!intel_engine_pm_get_if_awake(engine))
return 0;
 
@@ -1207,13 +1215,10 @@ int __intel_engine_reset_bh(struct intel_engine_cs 
*engine, const char *msg)
   "Resetting %s for %s\n", engine->name, msg);

atomic_inc(>i915->gpu_error.reset_engine_count[engine->uabi_class]);
 
-   if (intel_engine_uses_guc(engine))
-   ret = intel_guc_reset_engine(>gt->uc.guc, engine);
-   else
-   ret = intel_gt_reset_engine(engine);
+   ret = intel_gt_reset_engine(engine);
if (ret) {
/* If we fail here, we expect to fallback to a global reset */
-   ENGINE_TRACE(engine, "Failed to reset, err: %d\n", ret);
+   ENGINE_TRACE(engine, "Failed to reset %s, err: %d\n", 
engine->name, ret);
goto out;
}
 
@@ -1347,7 +1352,8 @@ void intel_gt_handle_error(struct intel_gt *gt,
 * Try engine reset when available. We fall back to full reset if
 * single reset fails.
 */
-   if (intel_has_reset_engine(gt) && !intel_gt_is_wedged(gt)) {
+   if (!intel_uc_uses_guc_submission(>uc) &&
+   

[PATCH 05/33] drm/i915/guc: Direct all breadcrumbs for a class to single breadcrumbs

2021-07-26 Thread Matthew Brost
With GuC virtual engines the physical engine which a request executes
and completes on isn't known to the i915. Therefore we can't attach a
request to a physical engines breadcrumbs. To work around this we create
a single breadcrumbs per engine class when using GuC submission and
direct all physical engine interrupts to this breadcrumbs.

v2:
 (John H)
  - Rework header file structure so intel_engine_mask_t can be in
intel_engine_types.h

Signed-off-by: Matthew Brost 
CC: John Harrison 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/intel_breadcrumbs.c   | 41 +---
 drivers/gpu/drm/i915/gt/intel_breadcrumbs.h   | 16 -
 .../gpu/drm/i915/gt/intel_breadcrumbs_types.h |  7 ++
 drivers/gpu/drm/i915/gt/intel_engine.h|  3 +
 drivers/gpu/drm/i915/gt/intel_engine_cs.c | 28 +++-
 drivers/gpu/drm/i915/gt/intel_engine_types.h  |  2 +-
 .../drm/i915/gt/intel_execlists_submission.c  |  2 +-
 drivers/gpu/drm/i915/gt/mock_engine.c |  4 +-
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 67 +--
 9 files changed, 133 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c 
b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
index 38cc42783dfb..2007dc6f6b99 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
@@ -15,28 +15,14 @@
 #include "intel_gt_pm.h"
 #include "intel_gt_requests.h"
 
-static bool irq_enable(struct intel_engine_cs *engine)
+static bool irq_enable(struct intel_breadcrumbs *b)
 {
-   if (!engine->irq_enable)
-   return false;
-
-   /* Caller disables interrupts */
-   spin_lock(>gt->irq_lock);
-   engine->irq_enable(engine);
-   spin_unlock(>gt->irq_lock);
-
-   return true;
+   return intel_engine_irq_enable(b->irq_engine);
 }
 
-static void irq_disable(struct intel_engine_cs *engine)
+static void irq_disable(struct intel_breadcrumbs *b)
 {
-   if (!engine->irq_disable)
-   return;
-
-   /* Caller disables interrupts */
-   spin_lock(>gt->irq_lock);
-   engine->irq_disable(engine);
-   spin_unlock(>gt->irq_lock);
+   intel_engine_irq_disable(b->irq_engine);
 }
 
 static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
@@ -57,7 +43,7 @@ static void __intel_breadcrumbs_arm_irq(struct 
intel_breadcrumbs *b)
WRITE_ONCE(b->irq_armed, true);
 
/* Requests may have completed before we could enable the interrupt. */
-   if (!b->irq_enabled++ && irq_enable(b->irq_engine))
+   if (!b->irq_enabled++ && b->irq_enable(b))
irq_work_queue(>irq_work);
 }
 
@@ -76,7 +62,7 @@ static void __intel_breadcrumbs_disarm_irq(struct 
intel_breadcrumbs *b)
 {
GEM_BUG_ON(!b->irq_enabled);
if (!--b->irq_enabled)
-   irq_disable(b->irq_engine);
+   b->irq_disable(b);
 
WRITE_ONCE(b->irq_armed, false);
intel_gt_pm_put_async(b->irq_engine->gt);
@@ -281,7 +267,7 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine)
if (!b)
return NULL;
 
-   b->irq_engine = irq_engine;
+   kref_init(>ref);
 
spin_lock_init(>signalers_lock);
INIT_LIST_HEAD(>signalers);
@@ -290,6 +276,10 @@ intel_breadcrumbs_create(struct intel_engine_cs 
*irq_engine)
spin_lock_init(>irq_lock);
init_irq_work(>irq_work, signal_irq_work);
 
+   b->irq_engine = irq_engine;
+   b->irq_enable = irq_enable;
+   b->irq_disable = irq_disable;
+
return b;
 }
 
@@ -303,9 +293,9 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs *b)
spin_lock_irqsave(>irq_lock, flags);
 
if (b->irq_enabled)
-   irq_enable(b->irq_engine);
+   b->irq_enable(b);
else
-   irq_disable(b->irq_engine);
+   b->irq_disable(b);
 
spin_unlock_irqrestore(>irq_lock, flags);
 }
@@ -325,11 +315,14 @@ void __intel_breadcrumbs_park(struct intel_breadcrumbs *b)
}
 }
 
-void intel_breadcrumbs_free(struct intel_breadcrumbs *b)
+void intel_breadcrumbs_free(struct kref *kref)
 {
+   struct intel_breadcrumbs *b = container_of(kref, typeof(*b), ref);
+
irq_work_sync(>irq_work);
GEM_BUG_ON(!list_empty(>signalers));
GEM_BUG_ON(b->irq_armed);
+
kfree(b);
 }
 
diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h 
b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
index 3ce5ce270b04..be0d4f379a85 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
@@ -9,7 +9,7 @@
 #include 
 #include 
 
-#include "intel_engine_types.h"
+#include "intel_breadcrumbs_types.h"
 
 struct drm_printer;
 struct i915_request;
@@ -17,7 +17,7 @@ struct intel_breadcrumbs;
 
 struct intel_breadcrumbs *
 intel_breadcrumbs_create(struct intel_engine_cs *irq_engine);
-void intel_breadcrumbs_free(struct intel_breadcrumbs *b);
+void intel_breadcrumbs_free(struct 

[PATCH 00/33] Remaining patches for basic GuC submission

2021-07-26 Thread Matthew Brost
The remaining patches for basic GuC submission [1]. Need 1 more RB and
CI results to get this merged. 

v2:
 (Checkpatch)
 - Fix checkpatch warning (1 remaining overrulled) 
 (Daniele)
 - Use an outer lock in guc_context_block / unblock

Signed-off-by: Matthew Brost 

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

Daniele Ceraolo Spurio (1):
  drm/i915/guc: Unblock GuC submission on Gen11+


Daniele Ceraolo Spurio (1):
  drm/i915/guc: Unblock GuC submission on Gen11+

John Harrison (12):
  drm/i915/guc: Make hangcheck work with GuC virtual engines
  drm/i915/guc: Provide mmio list to be saved/restored on engine reset
  drm/i915/guc: Don't complain about reset races
  drm/i915/guc: Enable GuC engine reset
  drm/i915/guc: Fix for error capture after full GPU reset with GuC
  drm/i915/guc: Hook GuC scheduling policies up
  drm/i915/guc: Connect reset modparam updates to GuC policy flags
  drm/i915/guc: Include scheduling policies in the debugfs state dump
  drm/i915/guc: Add golden context to GuC ADS
  drm/i915/selftest: Better error reporting from hangcheck selftest
  drm/i915/selftest: Fix hangcheck self test for GuC submission
  drm/i915/selftest: Bump selftest timeouts for hangcheck

Matthew Brost (18):
  drm/i915/guc: GuC virtual engines
  drm/i915: Hold reference to intel_context over life of i915_request
  drm/i915/guc: Disable bonding extension with GuC submission
  drm/i915/guc: Direct all breadcrumbs for a class to single breadcrumbs
  drm/i915: Add i915_sched_engine destroy vfunc
  drm/i915: Move active request tracking to a vfunc
  drm/i915/guc: Reset implementation for new GuC interface
  drm/i915: Reset GPU immediately if submission is disabled
  drm/i915/guc: Add disable interrupts to guc sanitize
  drm/i915/guc: Suspend/resume implementation for new interface
  drm/i915/guc: Handle context reset notification
  drm/i915/guc: Handle engine reset failure notification
  drm/i915/guc: Enable the timer expired interrupt for GuC
  drm/i915/guc: Capture error state on context reset
  drm/i915/guc: Implement banned contexts for GuC submission
  drm/i915/guc: Support request cancellation
  drm/i915/selftest: Increase some timeouts in live_requests
  drm/i915/guc: Implement GuC priority management

Rahul Kumar Singh (2):
  drm/i915/selftest: Fix workarounds selftest for GuC submission
  drm/i915/selftest: Fix MOCS selftest for GuC submission

 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/gem/i915_gem_context.c   |   15 +-
 drivers/gpu/drm/i915/gt/intel_breadcrumbs.c   |   44 +-
 drivers/gpu/drm/i915/gt/intel_breadcrumbs.h   |   16 +-
 .../gpu/drm/i915/gt/intel_breadcrumbs_types.h |7 +
 drivers/gpu/drm/i915/gt/intel_context.c   |   36 +
 drivers/gpu/drm/i915/gt/intel_context.h   |   23 +
 drivers/gpu/drm/i915/gt/intel_context_types.h |   33 +-
 drivers/gpu/drm/i915/gt/intel_engine.h|   57 +-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c |  183 +-
 .../gpu/drm/i915/gt/intel_engine_heartbeat.c  |   70 +-
 .../gpu/drm/i915/gt/intel_engine_heartbeat.h  |4 +
 drivers/gpu/drm/i915/gt/intel_engine_types.h  |   13 +-
 drivers/gpu/drm/i915/gt/intel_engine_user.c   |4 +
 .../drm/i915/gt/intel_execlists_submission.c  |   89 +-
 .../drm/i915/gt/intel_execlists_submission.h  |4 -
 drivers/gpu/drm/i915/gt/intel_gt.c|2 +
 drivers/gpu/drm/i915/gt/intel_gt_pm.c |6 +-
 drivers/gpu/drm/i915/gt/intel_reset.c |   50 +-
 .../gpu/drm/i915/gt/intel_ring_submission.c   |   58 +
 drivers/gpu/drm/i915/gt/intel_rps.c   |4 +
 drivers/gpu/drm/i915/gt/intel_workarounds.c   |   46 +-
 .../gpu/drm/i915/gt/intel_workarounds_types.h |1 +
 drivers/gpu/drm/i915/gt/mock_engine.c |   34 +-
 .../drm/i915/gt/selftest_engine_heartbeat.c   |   22 +
 .../drm/i915/gt/selftest_engine_heartbeat.h   |2 +
 drivers/gpu/drm/i915/gt/selftest_execlists.c  |   12 +-
 drivers/gpu/drm/i915/gt/selftest_hangcheck.c  |  322 +++-
 drivers/gpu/drm/i915/gt/selftest_mocs.c   |   50 +-
 .../gpu/drm/i915/gt/selftest_workarounds.c|  132 +-
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.c|   82 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|   38 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c|  464 -
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h|4 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c |   11 +-
 .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c|2 +
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 1611 +++--
 .../gpu/drm/i915/gt/uc/intel_guc_submission.h |   13 +-
 drivers/gpu/drm/i915/gt/uc/intel_uc.c |  101 +-
 drivers/gpu/drm/i915/gt/uc/intel_uc.h |6 +
 drivers/gpu/drm/i915/i915_debugfs_params.c|   32 +
 drivers/gpu/drm/i915/i915_gpu_error.c |   25 +-
 drivers/gpu/drm/i915/i915_reg.h   |1 +
 drivers/gpu/drm/i915/i915_request.c   |  162 +-
 drivers/gpu/drm/i915/i915_request.h

[PATCH 04/33] drm/i915/guc: Disable bonding extension with GuC submission

2021-07-26 Thread Matthew Brost
Update the bonding extension to return -ENODEV when using GuC submission
as this extension fundamentally will not work with the GuC submission
interface.

Signed-off-by: Matthew Brost 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c 
b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index bc52eeed782a..e3df01a201d7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -491,6 +491,11 @@ set_proto_ctx_engines_bond(struct i915_user_extension 
__user *base, void *data)
return -EINVAL;
}
 
+   if (intel_engine_uses_guc(master)) {
+   DRM_DEBUG("bonding extension not supported with GuC 
submission");
+   return -ENODEV;
+   }
+
if (get_user(num_bonds, >num_bonds))
return -EFAULT;
 
-- 
2.28.0



Re: [PATCH 2/5] drm/msm/dp: Modify prototype of encoder based API

2021-07-26 Thread Stephen Boyd
Quoting Bjorn Andersson (2021-07-24 21:24:32)
> Functions in the DisplayPort code that relates to individual instances
> (encoders) are passed both the struct msm_dp and the struct drm_encoder. But
> in a situation where multiple DP instances would exist this means that
> the caller need to resolve which struct msm_dp relates to the struct
> drm_encoder at hand.
>
> The information for doing this lookup is available inside the DP driver,
> so update the API to take the struct msm_drm_private and the struct
> drm_encoder and have the DP code figure out which struct msm_dp the
> operation relates to.
>
> Signed-off-by: Bjorn Andersson 
> ---

Reviewed-by: Stephen Boyd 


Re: [PATCH 5/5] drm/msm/dp: Add sc8180x DP controllers

2021-07-26 Thread Stephen Boyd
Quoting Bjorn Andersson (2021-07-24 21:24:36)
> The sc8180x has 2 DP and 1 eDP controllers, add support for these to the
> DP driver.
>
> Link: 
> https://lore.kernel.org/linux-arm-msm/20210511042043.592802-5-bjorn.anders...@linaro.org/
> Signed-off-by: Bjorn Andersson 
> ---
>  drivers/gpu/drm/msm/dp/dp_display.c | 12 
>  1 file changed, 12 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index 92b7646a1bb7..c26805cfcdd1 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -129,8 +129,20 @@ static const struct msm_dp_config sc7180_dp_cfg = {
> .num_dp = 1,
>  };
>
> +static const struct msm_dp_config sc8180x_dp_cfg = {
> +   .io_start = { 0xae9, 0xae98000, 0 },
> +   .num_dp = 3,
> +};
> +
> +static const struct msm_dp_config sc8180x_edp_cfg = {
> +   .io_start = { 0, 0, 0xae9a000 },
> +   .num_dp = 3,
> +};

Can the two structs not be combined into one struct and set as .data for
either compatible?

> +
>  static const struct of_device_id dp_dt_match[] = {
> { .compatible = "qcom,sc7180-dp", .data = _dp_cfg },
> +   { .compatible = "qcom,sc8180x-dp", .data = _dp_cfg },
> +   { .compatible = "qcom,sc8180x-edp", .data = _edp_cfg },
> {}


Re: [PATCH 4/5] dt-bindings: msm/dp: Add SC8180x compatibles

2021-07-26 Thread Stephen Boyd
Quoting Bjorn Andersson (2021-07-24 21:24:35)
> The Qualcomm SC8180x has 2 DP controllers and 1 eDP controller, add
> compatibles for these to the msm/dp binding.
>
> Signed-off-by: Bjorn Andersson 
> ---

Reviewed-by: Stephen Boyd 


Re: [RFC 0/4] dma-fence: Deadline awareness

2021-07-26 Thread Rob Clark
On Mon, Jul 26, 2021 at 4:34 PM Rob Clark  wrote:
>
> From: Rob Clark 
>
> Based on discussion from a previous series[1] to add a "boost" mechanism
> when, for example, vblank deadlines are missed.  Instead of a boost
> callback, this approach adds a way to set a deadline on the fence, by
> which the waiter would like to see the fence signalled.
>
> I've not yet had a chance to re-work the drm/msm part of this, but
> wanted to send this out as an RFC in case I don't have a chance to
> finish the drm/msm part this week.

Fwiw, what I'm thinking for the drm/msm part is a timer set to expire
a bit (couple ms?) before the deadline, which boosts if the timer
expires before the fence is signaled.

Assuming this is roughly in line with what other drivers would do,
possibly there is some room to build this timer into dma-fence itself?

BR,
-R

>
> Original description:
>
> In some cases, like double-buffered rendering, missing vblanks can
> trick the GPU into running at a lower frequence, when really we
> want to be running at a higher frequency to not miss the vblanks
> in the first place.
>
> This is partially inspired by a trick i915 does, but implemented
> via dma-fence for a couple of reasons:
>
> 1) To continue to be able to use the atomic helpers
> 2) To support cases where display and gpu are different drivers
>
> [1] https://patchwork.freedesktop.org/series/90331/
>
> Rob Clark (4):
>   dma-fence: Add deadline awareness
>   drm/vblank: Add helper to get next vblank time
>   drm/atomic-helper: Set fence deadline for vblank
>   drm/scheduler: Add fence deadline support
>
>  drivers/dma-buf/dma-fence.c | 39 +
>  drivers/gpu/drm/drm_atomic_helper.c | 36 +++
>  drivers/gpu/drm/drm_vblank.c| 31 
>  drivers/gpu/drm/scheduler/sched_fence.c | 10 +++
>  drivers/gpu/drm/scheduler/sched_main.c  |  3 ++
>  include/drm/drm_vblank.h|  1 +
>  include/linux/dma-fence.h   | 17 +++
>  7 files changed, 137 insertions(+)
>
> --
> 2.31.1
>


Re: [PATCH 3/5] drm/msm/dp: Support up to 3 DP controllers

2021-07-26 Thread Stephen Boyd
Quoting Bjorn Andersson (2021-07-24 21:24:33)
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index 59ffd6c8f41f..92b7646a1bb7 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -238,8 +251,11 @@ static int dp_display_bind(struct device *dev, struct 
> device *master,
> }
>
> rc = dp_register_audio_driver(dev, dp->audio);
> -   if (rc)
> +   if (rc) {
> DRM_ERROR("Audio registration Dp failed\n");
> +   goto end;
> +   }
> +
>
>  end:
> return rc;

This hunk looks useless. Drop it?

> @@ -1205,6 +1221,26 @@ int dp_display_request_irq(struct msm_dp *dp_display)
> return 0;
>  }
>
> +static int dp_display_get_id(struct platform_device *pdev)
> +{
> +   const struct msm_dp_config *cfg = 
> of_device_get_match_data(>dev);
> +   struct resource *res;
> +   int i;
> +
> +
> +   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +   if (!res)
> +   return -EINVAL;
> +
> +   for (i = 0; i < cfg->num_dp; i++) {
> +   if (cfg->io_start[i] == res->start)
> +   return i;
> +   }
> +
> +   dev_err(>dev, "unknown displayport instance\n");
> +   return -EINVAL;
> +}
> +
>  static int dp_display_probe(struct platform_device *pdev)
>  {
> int rc = 0;
> @@ -1219,6 +1255,10 @@ static int dp_display_probe(struct platform_device 
> *pdev)
> if (!dp)
> return -ENOMEM;
>
> +   dp->id = dp_display_get_id(pdev);
> +   if (dp->id < 0)
> +   return -EINVAL;
> +
> dp->pdev = pdev;
> dp->name = "drm_dp";
>
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index e9232032b266..62d54ef6c2c4 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -161,7 +161,7 @@ struct msm_drm_private {
> /* DSI is shared by mdp4 and mdp5 */
> struct msm_dsi *dsi[2];
>
> -   struct msm_dp *dp;
> +   struct msm_dp *dp[3];

It would be nice to either make this dynamically sized (probably little
gain), somehow make a BUILD_BUG_ON(), or have a WARN_ON if
ARRAY_SIZE(dp) is less than a num_dp so we know somebody messed up.


[RFC 4/4] drm/scheduler: Add fence deadline support

2021-07-26 Thread Rob Clark
From: Rob Clark 

As the finished fence is the one that is exposed to userspace, and
therefore the one that other operations, like atomic update, would
block on, we need to propagate the deadline from from the finished
fence to the actual hw fence.

Signed-off-by: Rob Clark 
---
 drivers/gpu/drm/scheduler/sched_fence.c | 10 ++
 drivers/gpu/drm/scheduler/sched_main.c  |  3 +++
 2 files changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/scheduler/sched_fence.c 
b/drivers/gpu/drm/scheduler/sched_fence.c
index 69de2c76731f..3aa6351d2101 100644
--- a/drivers/gpu/drm/scheduler/sched_fence.c
+++ b/drivers/gpu/drm/scheduler/sched_fence.c
@@ -128,6 +128,15 @@ static void drm_sched_fence_release_finished(struct 
dma_fence *f)
dma_fence_put(>scheduled);
 }
 
+static void drm_sched_fence_set_deadline_finished(struct dma_fence *f,
+ ktime_t deadline)
+{
+   struct drm_sched_fence *fence = to_drm_sched_fence(f);
+
+   if (fence->parent)
+   dma_fence_set_deadline(fence->parent, deadline);
+}
+
 static const struct dma_fence_ops drm_sched_fence_ops_scheduled = {
.get_driver_name = drm_sched_fence_get_driver_name,
.get_timeline_name = drm_sched_fence_get_timeline_name,
@@ -138,6 +147,7 @@ static const struct dma_fence_ops 
drm_sched_fence_ops_finished = {
.get_driver_name = drm_sched_fence_get_driver_name,
.get_timeline_name = drm_sched_fence_get_timeline_name,
.release = drm_sched_fence_release_finished,
+   .set_deadline = drm_sched_fence_set_deadline_finished,
 };
 
 struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f)
diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
b/drivers/gpu/drm/scheduler/sched_main.c
index a2a953693b45..fcc601962e92 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -818,6 +818,9 @@ static int drm_sched_main(void *param)
 
if (!IS_ERR_OR_NULL(fence)) {
s_fence->parent = dma_fence_get(fence);
+   if (test_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT,
+_fence->finished.flags))
+   dma_fence_set_deadline(fence, 
s_fence->finished.deadline);
r = dma_fence_add_callback(fence, _job->cb,
   drm_sched_job_done_cb);
if (r == -ENOENT)
-- 
2.31.1



[RFC 3/4] drm/atomic-helper: Set fence deadline for vblank

2021-07-26 Thread Rob Clark
From: Rob Clark 

For an atomic commit updating a single CRTC (ie. a pageflip) calculate
the next vblank time, and inform the fence(s) of that deadline.

Signed-off-by: Rob Clark 
---
 drivers/gpu/drm/drm_atomic_helper.c | 36 +
 1 file changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index bc3487964fb5..f81b20775b15 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1406,6 +1406,40 @@ void drm_atomic_helper_commit_modeset_enables(struct 
drm_device *dev,
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
 
+/*
+ * For atomic updates which touch just a single CRTC, calculate the time of the
+ * next vblank, and inform all the fences of the of the deadline.
+ */
+static void set_fence_deadline(struct drm_device *dev,
+  struct drm_atomic_state *state)
+{
+   struct drm_crtc *crtc, *wait_crtc = NULL;
+   struct drm_crtc_state *new_crtc_state;
+   struct drm_plane *plane;
+   struct drm_plane_state *new_plane_state;
+   ktime_t vbltime;
+   int i;
+
+   for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) {
+   if (!wait_crtc)
+   return;
+   wait_crtc = crtc;
+   }
+
+   /* If no CRTCs updated, then nothing to do: */
+   if (!wait_crtc)
+   return;
+
+   if (drm_crtc_next_vblank_time(wait_crtc, ))
+   return;
+
+   for_each_new_plane_in_state (state, plane, new_plane_state, i) {
+   if (!new_plane_state->fence)
+   continue;
+   dma_fence_set_deadline(new_plane_state->fence, vbltime);
+   }
+}
+
 /**
  * drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state
  * @dev: DRM device
@@ -1435,6 +1469,8 @@ int drm_atomic_helper_wait_for_fences(struct drm_device 
*dev,
struct drm_plane_state *new_plane_state;
int i, ret;
 
+   set_fence_deadline(dev, state);
+
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
if (!new_plane_state->fence)
continue;
-- 
2.31.1



[RFC 2/4] drm/vblank: Add helper to get next vblank time

2021-07-26 Thread Rob Clark
From: Rob Clark 

Signed-off-by: Rob Clark 
---
 drivers/gpu/drm/drm_vblank.c | 31 +++
 include/drm/drm_vblank.h |  1 +
 2 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 3417e1ac7918..88c824c294dc 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -980,6 +980,37 @@ u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
 
+/**
+ * drm_crtc_next_vblank_time - calculate the time of the next vblank
+ * @crtc: the crtc for which to calculate next vblank time
+ * @vblanktime: pointer to time to receive the next vblank timestamp.
+ *
+ * Calculate the expected time of the next vblank based on time of previous
+ * vblank and frame duration
+ */
+int drm_crtc_next_vblank_time(struct drm_crtc *crtc, ktime_t *vblanktime)
+{
+   unsigned int pipe = drm_crtc_index(crtc);
+   struct drm_vblank_crtc *vblank = >dev->vblank[pipe];
+   u64 count;
+
+   if (!vblank->framedur_ns)
+   return -EINVAL;
+
+   count = drm_vblank_count_and_time(crtc->dev, pipe, vblanktime);
+
+   /*
+* If we don't get a valid count, then we probably also don't
+* have a valid time:
+*/
+   if (!count)
+   return -EINVAL;
+
+   *vblanktime = ktime_add(*vblanktime, ns_to_ktime(vblank->framedur_ns));
+
+   return 0;
+}
+
 static void send_vblank_event(struct drm_device *dev,
struct drm_pending_vblank_event *e,
u64 seq, ktime_t now)
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 733a3e2d1d10..a63bc2c92f3c 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -230,6 +230,7 @@ bool drm_dev_has_vblank(const struct drm_device *dev);
 u64 drm_crtc_vblank_count(struct drm_crtc *crtc);
 u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
   ktime_t *vblanktime);
+int drm_crtc_next_vblank_time(struct drm_crtc *crtc, ktime_t *vblanktime);
 void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
   struct drm_pending_vblank_event *e);
 void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
-- 
2.31.1



[RFC 1/4] dma-fence: Add deadline awareness

2021-07-26 Thread Rob Clark
From: Rob Clark 

Add a way to hint to the fence signaler of an upcoming deadline, such as
vblank, which the fence waiter would prefer not to miss.  This is to aid
the fence signaler in making power management decisions, like boosting
frequency as the deadline approaches and awareness of missing deadlines
so that can be factored in to the frequency scaling.

Signed-off-by: Rob Clark 
---
 drivers/dma-buf/dma-fence.c | 39 +
 include/linux/dma-fence.h   | 17 
 2 files changed, 56 insertions(+)

diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index ce0f5eff575d..2e0d25ab457e 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -910,6 +910,45 @@ dma_fence_wait_any_timeout(struct dma_fence **fences, 
uint32_t count,
 }
 EXPORT_SYMBOL(dma_fence_wait_any_timeout);
 
+
+/**
+ * dma_fence_set_deadline - set desired fence-wait deadline
+ * @fence:the fence that is to be waited on
+ * @deadline: the time by which the waiter hopes for the fence to be
+ *signaled
+ *
+ * Inform the fence signaler of an upcoming deadline, such as vblank, by
+ * which point the waiter would prefer the fence to be signaled by.  This
+ * is intended to give feedback to the fence signaler to aid in power
+ * management decisions, such as boosting GPU frequency if a periodic
+ * vblank deadline is approaching.
+ */
+void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
+{
+   unsigned long flags;
+
+   if (dma_fence_is_signaled(fence))
+   return;
+
+   spin_lock_irqsave(fence->lock, flags);
+
+   /* If we already have an earlier deadline, keep it: */
+   if (test_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT, >flags) &&
+   ktime_before(fence->deadline, deadline)) {
+   spin_unlock_irqrestore(fence->lock, flags);
+   return;
+   }
+
+   fence->deadline = deadline;
+   set_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT, >flags);
+
+   spin_unlock_irqrestore(fence->lock, flags);
+
+   if (fence->ops->set_deadline)
+   fence->ops->set_deadline(fence, deadline);
+}
+EXPORT_SYMBOL(dma_fence_set_deadline);
+
 /**
  * dma_fence_init - Initialize a custom fence.
  * @fence: the fence to initialize
diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
index 6ffb4b2c6371..4e6cfe4e6fbc 100644
--- a/include/linux/dma-fence.h
+++ b/include/linux/dma-fence.h
@@ -88,6 +88,7 @@ struct dma_fence {
/* @timestamp replaced by @rcu on dma_fence_release() */
struct rcu_head rcu;
};
+   ktime_t deadline;
u64 context;
u64 seqno;
unsigned long flags;
@@ -99,6 +100,7 @@ enum dma_fence_flag_bits {
DMA_FENCE_FLAG_SIGNALED_BIT,
DMA_FENCE_FLAG_TIMESTAMP_BIT,
DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+   DMA_FENCE_FLAG_HAS_DEADLINE_BIT,
DMA_FENCE_FLAG_USER_BITS, /* must always be last member */
 };
 
@@ -261,6 +263,19 @@ struct dma_fence_ops {
 */
void (*timeline_value_str)(struct dma_fence *fence,
   char *str, int size);
+
+   /**
+* @set_deadline:
+*
+* Callback to allow a fence waiter to inform the fence signaler of an
+* upcoming deadline, such as vblank, by which point the waiter would
+* prefer the fence to be signaled by.  This is intended to give 
feedback
+* to the fence signaler to aid in power management decisions, such as
+* boosting GPU frequency.
+*
+* This callback is optional.
+*/
+   void (*set_deadline)(struct dma_fence *fence, ktime_t deadline);
 };
 
 void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
@@ -586,6 +601,8 @@ static inline signed long dma_fence_wait(struct dma_fence 
*fence, bool intr)
return ret < 0 ? ret : 0;
 }
 
+void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline);
+
 struct dma_fence *dma_fence_get_stub(void);
 struct dma_fence *dma_fence_allocate_private_stub(void);
 u64 dma_fence_context_alloc(unsigned num);
-- 
2.31.1



[RFC 0/4] dma-fence: Deadline awareness

2021-07-26 Thread Rob Clark
From: Rob Clark 

Based on discussion from a previous series[1] to add a "boost" mechanism
when, for example, vblank deadlines are missed.  Instead of a boost
callback, this approach adds a way to set a deadline on the fence, by
which the waiter would like to see the fence signalled.

I've not yet had a chance to re-work the drm/msm part of this, but
wanted to send this out as an RFC in case I don't have a chance to
finish the drm/msm part this week.

Original description:

In some cases, like double-buffered rendering, missing vblanks can
trick the GPU into running at a lower frequence, when really we
want to be running at a higher frequency to not miss the vblanks
in the first place.

This is partially inspired by a trick i915 does, but implemented
via dma-fence for a couple of reasons:

1) To continue to be able to use the atomic helpers
2) To support cases where display and gpu are different drivers

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

Rob Clark (4):
  dma-fence: Add deadline awareness
  drm/vblank: Add helper to get next vblank time
  drm/atomic-helper: Set fence deadline for vblank
  drm/scheduler: Add fence deadline support

 drivers/dma-buf/dma-fence.c | 39 +
 drivers/gpu/drm/drm_atomic_helper.c | 36 +++
 drivers/gpu/drm/drm_vblank.c| 31 
 drivers/gpu/drm/scheduler/sched_fence.c | 10 +++
 drivers/gpu/drm/scheduler/sched_main.c  |  3 ++
 include/drm/drm_vblank.h|  1 +
 include/linux/dma-fence.h   | 17 +++
 7 files changed, 137 insertions(+)

-- 
2.31.1



Re: [PATCH V3 1/2] dt-bindings: display: bridge: lvds-codec: Document LVDS data mapping select

2021-07-26 Thread Rob Herring
On Mon, Jul 26, 2021 at 11:02:49PM +0200, Marek Vasut wrote:
> Decoder input LVDS format is a property of the decoder chip or even
> its strapping. Add DT property data-mapping the same way lvds-panel
> does, to define the LVDS data mapping.
> 
> Signed-off-by: Marek Vasut 
> Cc: Laurent Pinchart 
> Cc: Rob Herring 
> Cc: Sam Ravnborg 
> Cc: devicet...@vger.kernel.org
> To: dri-devel@lists.freedesktop.org
> ---
> V2: - Use allOf
> - Move the data-mapping to endpoint
> V3: - Rebase on V2 submitted a while ago, reinstate changelog
> - Drop the allOf and un-rebase on previous pclk patch
> ---
>  .../bindings/display/bridge/lvds-codec.yaml   | 31 +++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml 
> b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
> index 304a1367faaa7..f795c671c3ce1 100644
> --- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
> @@ -60,6 +60,21 @@ properties:
>For LVDS encoders, port 1 is the LVDS output
>For LVDS decoders, port 1 is the parallel output
>  
> +properties:
> +  endpoint:
> +$ref: /schemas/media/video-interfaces.yaml#

Adding this means the 'port' needs to reference '$defs/port-base' 
instead of 'properties/port'. Otherwise, it's going to start failing 
when 'unevaluatedProperties' gets implemented (appears to be soon now).

> +unevaluatedProperties: false
> +
> +properties:
> +  data-mapping:
> +enum:
> +  - jeida-18
> +  - jeida-24
> +  - vesa-24
> +description: |
> +  The color signals mapping order. See details in
> +  Documentation/devicetree/bindings/display/panel/lvds.yaml
> +
>  required:
>- port@0
>- port@1
> @@ -71,6 +86,22 @@ properties:
>  
>power-supply: true
>  
> +if:
> +  not:
> +properties:
> +  compatible:
> +contains:
> +  const: lvds-decoder
> +then:
> +  properties:
> +ports:
> +  properties:
> +port@1:
> +  properties:
> +endpoint:
> +  properties:
> +data-mapping: false

With this, I kind of think the schema should be split into encoder and 
decoder schemas. But we can leave that for the next addition...

Rob


Re: [PATCH 10/30] drm/i915/display: remove explicit CNL handling from intel_dmc.c

2021-07-26 Thread Matt Roper
On Fri, Jul 23, 2021 at 05:10:54PM -0700, Lucas De Marchi wrote:
> Remove DMC firmware for CNL.
> 
> Signed-off-by: Lucas De Marchi 

Reviewed-by: Matt Roper 

> ---
>  drivers/gpu/drm/i915/display/intel_dmc.c | 9 -
>  1 file changed, 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c 
> b/drivers/gpu/drm/i915/display/intel_dmc.c
> index 9895fd957df9..3c3c6cb5c0df 100644
> --- a/drivers/gpu/drm/i915/display/intel_dmc.c
> +++ b/drivers/gpu/drm/i915/display/intel_dmc.c
> @@ -70,11 +70,6 @@ MODULE_FIRMWARE(TGL_DMC_PATH);
>  #define ICL_DMC_MAX_FW_SIZE  0x6000
>  MODULE_FIRMWARE(ICL_DMC_PATH);
>  
> -#define CNL_DMC_PATH DMC_PATH(cnl, 1, 07)
> -#define CNL_DMC_VERSION_REQUIRED DMC_VERSION(1, 7)
> -#define CNL_DMC_MAX_FW_SIZE  GLK_DMC_MAX_FW_SIZE
> -MODULE_FIRMWARE(CNL_DMC_PATH);
> -
>  #define GLK_DMC_PATH DMC_PATH(glk, 1, 04)
>  #define GLK_DMC_VERSION_REQUIRED DMC_VERSION(1, 4)
>  #define GLK_DMC_MAX_FW_SIZE  0x4000
> @@ -718,10 +713,6 @@ void intel_dmc_ucode_init(struct drm_i915_private 
> *dev_priv)
>   dmc->fw_path = ICL_DMC_PATH;
>   dmc->required_version = ICL_DMC_VERSION_REQUIRED;
>   dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE;
> - } else if (IS_CANNONLAKE(dev_priv)) {
> - dmc->fw_path = CNL_DMC_PATH;
> - dmc->required_version = CNL_DMC_VERSION_REQUIRED;
> - dmc->max_fw_size = CNL_DMC_MAX_FW_SIZE;
>   } else if (IS_GEMINILAKE(dev_priv)) {
>   dmc->fw_path = GLK_DMC_PATH;
>   dmc->required_version = GLK_DMC_VERSION_REQUIRED;
> -- 
> 2.31.1
> 

-- 
Matt Roper
Graphics Software Engineer
VTT-OSGC Platform Enablement
Intel Corporation
(916) 356-2795


Re: [PATCH 23/30] drm/i915/gt: remove explicit CNL handling from intel_sseu.c

2021-07-26 Thread Matt Roper
On Fri, Jul 23, 2021 at 05:11:07PM -0700, Lucas De Marchi wrote:
> CNL is the only platform with GRAPHICS_VER == 10. With its removal we
> don't need to handle that version anymore.
> 
> Also we can now reduce the max number of slices: the call to
> intel_sseu_set_info() with the highest number of slices comes from SKL
> and BDW with 3 slices. Recent platforms actually increase the
> number of subslices so the number of slices remain 1.
> 
> Signed-off-by: Lucas De Marchi 

Reviewed-by: Matt Roper 

> ---
>  drivers/gpu/drm/i915/gt/intel_sseu.c | 79 
>  drivers/gpu/drm/i915/gt/intel_sseu.h |  2 +-
>  2 files changed, 1 insertion(+), 80 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c 
> b/drivers/gpu/drm/i915/gt/intel_sseu.c
> index 367fd44b81c8..9542c3f3822a 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu.c
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
> @@ -188,83 +188,6 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>   sseu->has_eu_pg = 1;
>  }
>  
> -static void gen10_sseu_info_init(struct intel_gt *gt)
> -{
> - struct intel_uncore *uncore = gt->uncore;
> - struct sseu_dev_info *sseu = >info.sseu;
> - const u32 fuse2 = intel_uncore_read(uncore, GEN8_FUSE2);
> - const int eu_mask = 0xff;
> - u32 subslice_mask, eu_en;
> - int s, ss;
> -
> - intel_sseu_set_info(sseu, 6, 4, 8);
> -
> - sseu->slice_mask = (fuse2 & GEN10_F2_S_ENA_MASK) >>
> - GEN10_F2_S_ENA_SHIFT;
> -
> - /* Slice0 */
> - eu_en = ~intel_uncore_read(uncore, GEN8_EU_DISABLE0);
> - for (ss = 0; ss < sseu->max_subslices; ss++)
> - sseu_set_eus(sseu, 0, ss, (eu_en >> (8 * ss)) & eu_mask);
> - /* Slice1 */
> - sseu_set_eus(sseu, 1, 0, (eu_en >> 24) & eu_mask);
> - eu_en = ~intel_uncore_read(uncore, GEN8_EU_DISABLE1);
> - sseu_set_eus(sseu, 1, 1, eu_en & eu_mask);
> - /* Slice2 */
> - sseu_set_eus(sseu, 2, 0, (eu_en >> 8) & eu_mask);
> - sseu_set_eus(sseu, 2, 1, (eu_en >> 16) & eu_mask);
> - /* Slice3 */
> - sseu_set_eus(sseu, 3, 0, (eu_en >> 24) & eu_mask);
> - eu_en = ~intel_uncore_read(uncore, GEN8_EU_DISABLE2);
> - sseu_set_eus(sseu, 3, 1, eu_en & eu_mask);
> - /* Slice4 */
> - sseu_set_eus(sseu, 4, 0, (eu_en >> 8) & eu_mask);
> - sseu_set_eus(sseu, 4, 1, (eu_en >> 16) & eu_mask);
> - /* Slice5 */
> - sseu_set_eus(sseu, 5, 0, (eu_en >> 24) & eu_mask);
> - eu_en = ~intel_uncore_read(uncore, GEN10_EU_DISABLE3);
> - sseu_set_eus(sseu, 5, 1, eu_en & eu_mask);
> -
> - subslice_mask = (1 << 4) - 1;
> - subslice_mask &= ~((fuse2 & GEN10_F2_SS_DIS_MASK) >>
> -GEN10_F2_SS_DIS_SHIFT);
> -
> - for (s = 0; s < sseu->max_slices; s++) {
> - u32 subslice_mask_with_eus = subslice_mask;
> -
> - for (ss = 0; ss < sseu->max_subslices; ss++) {
> - if (sseu_get_eus(sseu, s, ss) == 0)
> - subslice_mask_with_eus &= ~BIT(ss);
> - }
> -
> - /*
> -  * Slice0 can have up to 3 subslices, but there are only 2 in
> -  * slice1/2.
> -  */
> - intel_sseu_set_subslices(sseu, s, s == 0 ?
> -  subslice_mask_with_eus :
> -  subslice_mask_with_eus & 0x3);
> - }
> -
> - sseu->eu_total = compute_eu_total(sseu);
> -
> - /*
> -  * CNL is expected to always have a uniform distribution
> -  * of EU across subslices with the exception that any one
> -  * EU in any one subslice may be fused off for die
> -  * recovery.
> -  */
> - sseu->eu_per_subslice =
> - intel_sseu_subslice_total(sseu) ?
> - DIV_ROUND_UP(sseu->eu_total, intel_sseu_subslice_total(sseu)) :
> - 0;
> -
> - /* No restrictions on Power Gating */
> - sseu->has_slice_pg = 1;
> - sseu->has_subslice_pg = 1;
> - sseu->has_eu_pg = 1;
> -}
> -
>  static void cherryview_sseu_info_init(struct intel_gt *gt)
>  {
>   struct sseu_dev_info *sseu = >info.sseu;
> @@ -592,8 +515,6 @@ void intel_sseu_info_init(struct intel_gt *gt)
>   bdw_sseu_info_init(gt);
>   else if (GRAPHICS_VER(i915) == 9)
>   gen9_sseu_info_init(gt);
> - else if (GRAPHICS_VER(i915) == 10)
> - gen10_sseu_info_init(gt);
>   else if (GRAPHICS_VER(i915) == 11)
>   gen11_sseu_info_init(gt);
>   else if (GRAPHICS_VER(i915) >= 12)
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h 
> b/drivers/gpu/drm/i915/gt/intel_sseu.h
> index 4cd1a8a7298a..8d85ec05f610 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu.h
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
> @@ -15,7 +15,7 @@ struct drm_i915_private;
>  struct intel_gt;
>  struct drm_printer;
>  
> -#define GEN_MAX_SLICES   (6) /* CNL upper bound */
> +#define GEN_MAX_SLICES   (3) /* SKL upper bound */
> 

[RFC] drm/msm/dp: Allow attaching a drm_panel

2021-07-26 Thread Bjorn Andersson
eDP panels might need some power sequencing and backlight management,
so make it possible to associate a drm_panel with a DP instance and
prepare and enable the panel accordingly.

Signed-off-by: Bjorn Andersson 
---

This solves my immediate problem on my 8cx laptops, of indirectly controlling
the backlight during DPMS. But my panel is powered when I boot it and as such I
get the hpd interrupt and I don't actually have to deal with a power on
sequence - so I'm posting this as an RFC, hoping to get some input on these
other aspects.

If this is acceptable I'd be happy to write up an accompanying DT binding
change that marks port 2 of the DP controller's of_graph as a reference to the
attached panel.

 drivers/gpu/drm/msm/dp/dp_display.c | 15 +--
 drivers/gpu/drm/msm/dp/dp_display.h |  1 +
 drivers/gpu/drm/msm/dp/dp_parser.c  | 19 +++
 drivers/gpu/drm/msm/dp/dp_parser.h  |  1 +
 4 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 206bf7806f51..1db5a3f752d2 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "msm_drv.h"
 #include "msm_kms.h"
@@ -252,6 +253,8 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
goto end;
}
 
+   dp->dp_display.drm_panel = dp->parser->drm_panel;
+
rc = dp_aux_register(dp->aux, drm);
if (rc) {
DRM_ERROR("DRM DP AUX register failed\n");
@@ -867,8 +870,10 @@ static int dp_display_set_mode(struct msm_dp *dp_display,
return 0;
 }
 
-static int dp_display_prepare(struct msm_dp *dp)
+static int dp_display_prepare(struct msm_dp *dp_display)
 {
+   drm_panel_prepare(dp_display->drm_panel);
+
return 0;
 }
 
@@ -886,6 +891,8 @@ static int dp_display_enable(struct dp_display_private *dp, 
u32 data)
if (!rc)
dp_display->power_on = true;
 
+   drm_panel_enable(dp_display->drm_panel);
+
return rc;
 }
 
@@ -915,6 +922,8 @@ static int dp_display_disable(struct dp_display_private 
*dp, u32 data)
if (!dp_display->power_on)
return 0;
 
+   drm_panel_disable(dp_display->drm_panel);
+
/* wait only if audio was enabled */
if (dp_display->audio_enabled) {
/* signal the disconnect event */
@@ -939,8 +948,10 @@ static int dp_display_disable(struct dp_display_private 
*dp, u32 data)
return 0;
 }
 
-static int dp_display_unprepare(struct msm_dp *dp)
+static int dp_display_unprepare(struct msm_dp *dp_display)
 {
+   drm_panel_unprepare(dp_display->drm_panel);
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h 
b/drivers/gpu/drm/msm/dp/dp_display.h
index 8b47cdabb67e..ce337824c95d 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -15,6 +15,7 @@ struct msm_dp {
struct device *codec_dev;
struct drm_connector *connector;
struct drm_encoder *encoder;
+   struct drm_panel *drm_panel;
bool is_connected;
bool audio_enabled;
bool power_on;
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c 
b/drivers/gpu/drm/msm/dp/dp_parser.c
index fc8a6452f641..e6a6e9007bfd 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.c
+++ b/drivers/gpu/drm/msm/dp/dp_parser.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 #include "dp_parser.h"
@@ -276,6 +277,20 @@ static int dp_parser_clock(struct dp_parser *parser)
return 0;
 }
 
+static int dp_parser_find_panel(struct dp_parser *parser)
+{
+   struct device_node *np = parser->pdev->dev.of_node;
+   int rc;
+
+   rc = drm_of_find_panel_or_bridge(np, 2, 0, >drm_panel, NULL);
+   if (rc == -ENODEV)
+   rc = 0;
+   else if (rc)
+   DRM_ERROR("failed to acquire DRM panel: %d\n", rc);
+
+   return rc;
+}
+
 static int dp_parser_parse(struct dp_parser *parser)
 {
int rc = 0;
@@ -297,6 +312,10 @@ static int dp_parser_parse(struct dp_parser *parser)
if (rc)
return rc;
 
+   rc = dp_parser_find_panel(parser);
+   if (rc)
+   return rc;
+
/* Map the corresponding regulator information according to
 * version. Currently, since we only have one supported platform,
 * mapping the regulator directly.
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h 
b/drivers/gpu/drm/msm/dp/dp_parser.h
index 3266b529c090..994ca9336acd 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.h
+++ b/drivers/gpu/drm/msm/dp/dp_parser.h
@@ -122,6 +122,7 @@ struct dp_parser {
struct dp_display_data disp_data;
const struct dp_regulator_cfg *regulator_cfg;
u32 max_dp_lanes;
+   struct drm_panel *drm_panel;
 
int (*parse)(struct dp_parser *parser);
 };
-- 
2.29.2



Re: [PATCH 1/5] drm/msm/dp: Remove global g_dp_display variable

2021-07-26 Thread Stephen Boyd
Quoting Bjorn Andersson (2021-07-24 21:24:31)
> As the Qualcomm DisplayPort driver only supports a single instance of
> the driver the commonly used struct dp_display is kept in a global
> variable. As we introduce additional instances this obviously doesn't
> work.
>
> Replace this with a combination of existing references to adjacent
> objects and drvdata.
>
> Signed-off-by: Bjorn Andersson 
> ---

Thanks for removing the global.

>  drivers/gpu/drm/msm/dp/dp_display.c | 78 ++---
>  1 file changed, 37 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index 70b319a8fe83..8696b36d30e4 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -27,7 +27,6 @@
>  #include "dp_audio.h"
>  #include "dp_debug.h"
>
> -static struct msm_dp *g_dp_display;
>  #define HPD_STRING_SIZE 30
>
>  enum {
> @@ -122,6 +121,13 @@ static const struct of_device_id dp_dt_match[] = {
> {}
>  };
>
> +static struct dp_display_private *dev_to_dp_display_private(struct device 
> *dev)
> +{
> +   struct msm_dp *dp = dev_get_drvdata(dev);
> +
> +   return container_of(dp, struct dp_display_private, dp_display);
> +}
> +
>  static int dp_add_event(struct dp_display_private *dp_priv, u32 event,
> u32 data, u32 delay)
>  {
> @@ -198,14 +204,16 @@ static int dp_display_bind(struct device *dev, struct 
> device *master,
>void *data)
>  {
> int rc = 0;
> -   struct dp_display_private *dp;
> +   struct dp_display_private *dp = dev_to_dp_display_private(dev);
> struct drm_device *drm;
> struct msm_drm_private *priv;
>
> drm = dev_get_drvdata(master);
>
> -   dp = container_of(g_dp_display,
> -   struct dp_display_private, dp_display);
> +   if (!dp) {

How can it be NULL? dev_to_dp_display_private() returns container_of()
pointer so it doesn't look possible.

> +   DRM_ERROR("DP driver bind failed. Invalid driver data\n");
> +   return -EINVAL;
> +   }
>
> dp->dp_display.drm_dev = drm;
> priv = drm->dev_private;


Re: [Intel-gfx] [PATCH 08/33] drm/i915/guc: Reset implementation for new GuC interface

2021-07-26 Thread John Harrison

On 7/22/2021 16:54, Matthew Brost wrote:

Reset implementation for new GuC interface. This is the legacy reset
implementation which is called when the i915 owns the engine hang check.
Future patches will offload the engine hang check to GuC but we will
continue to maintain this legacy path as a fallback and this code path
is also required if the GuC dies.

With the new GuC interface it is not possible to reset individual
engines - it is only possible to reset the GPU entirely. This patch
forces an entire chip reset if any engine hangs.

v2:
  (Michal)
   - Check for -EPIPE rather than -EIO (CT deadlock/corrupt check)
v3:
  (John H)
   - Split into a series of smaller patches
v4:
  (John H)
   - Fix typo
   - Add braces around if statements in reset code

Cc: John Harrison 
Signed-off-by: Matthew Brost 

Reviewed-by: John Harrison 


---
  drivers/gpu/drm/i915/gt/intel_gt_pm.c |   6 +-
  drivers/gpu/drm/i915/gt/intel_reset.c |  18 +-
  drivers/gpu/drm/i915/gt/uc/intel_guc.c|  13 -
  drivers/gpu/drm/i915/gt/uc/intel_guc.h|   8 +-
  .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 561 ++
  drivers/gpu/drm/i915/gt/uc/intel_uc.c |  39 +-
  drivers/gpu/drm/i915/gt/uc/intel_uc.h |   3 +
  7 files changed, 516 insertions(+), 132 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c 
b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index d86825437516..cd7b96005d29 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -170,8 +170,6 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
if (intel_gt_is_wedged(gt))
intel_gt_unset_wedged(gt);
  
-	intel_uc_sanitize(>uc);

-
for_each_engine(engine, gt, id)
if (engine->reset.prepare)
engine->reset.prepare(engine);
@@ -187,6 +185,8 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
__intel_engine_reset(engine, false);
}
  
+	intel_uc_reset(>uc, false);

+
for_each_engine(engine, gt, id)
if (engine->reset.finish)
engine->reset.finish(engine);
@@ -239,6 +239,8 @@ int intel_gt_resume(struct intel_gt *gt)
goto err_wedged;
}
  
+	intel_uc_reset_finish(>uc);

+
intel_rps_enable(>rps);
intel_llc_enable(>llc);
  
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c

index 72251638d4ea..2987282dff6d 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -826,6 +826,8 @@ static int gt_reset(struct intel_gt *gt, 
intel_engine_mask_t stalled_mask)
__intel_engine_reset(engine, stalled_mask & engine->mask);
local_bh_enable();
  
+	intel_uc_reset(>uc, true);

+
intel_ggtt_restore_fences(gt->ggtt);
  
  	return err;

@@ -850,6 +852,8 @@ static void reset_finish(struct intel_gt *gt, 
intel_engine_mask_t awake)
if (awake & engine->mask)
intel_engine_pm_put(engine);
}
+
+   intel_uc_reset_finish(>uc);
  }
  
  static void nop_submit_request(struct i915_request *request)

@@ -903,6 +907,7 @@ static void __intel_gt_set_wedged(struct intel_gt *gt)
for_each_engine(engine, gt, id)
if (engine->reset.cancel)
engine->reset.cancel(engine);
+   intel_uc_cancel_requests(>uc);
local_bh_enable();
  
  	reset_finish(gt, awake);

@@ -1191,6 +1196,9 @@ int __intel_engine_reset_bh(struct intel_engine_cs 
*engine, const char *msg)
ENGINE_TRACE(engine, "flags=%lx\n", gt->reset.flags);
GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, >reset.flags));
  
+	if (intel_engine_uses_guc(engine))

+   return -ENODEV;
+
if (!intel_engine_pm_get_if_awake(engine))
return 0;
  
@@ -1201,13 +1209,10 @@ int __intel_engine_reset_bh(struct intel_engine_cs *engine, const char *msg)

   "Resetting %s for %s\n", engine->name, msg);

atomic_inc(>i915->gpu_error.reset_engine_count[engine->uabi_class]);
  
-	if (intel_engine_uses_guc(engine))

-   ret = intel_guc_reset_engine(>gt->uc.guc, engine);
-   else
-   ret = intel_gt_reset_engine(engine);
+   ret = intel_gt_reset_engine(engine);
if (ret) {
/* If we fail here, we expect to fallback to a global reset */
-   ENGINE_TRACE(engine, "Failed to reset, err: %d\n", ret);
+   ENGINE_TRACE(engine, "Failed to reset %s, err: %d\n", 
engine->name, ret);
goto out;
}
  
@@ -1341,7 +1346,8 @@ void intel_gt_handle_error(struct intel_gt *gt,

 * Try engine reset when available. We fall back to full reset if
 * single reset fails.
 */
-   if (intel_has_reset_engine(gt) && !intel_gt_is_wedged(gt)) {
+   if (!intel_uc_uses_guc_submission(>uc) &&

Re: [PATCH v3 2/3] dt-bindings: Add DT bindings for QiShenglong Gopher 2b panel

2021-07-26 Thread Rob Herring
On Mon, Jul 26, 2021 at 01:15:26AM +0300, Artjom Vejsel wrote:
> Add DT bindings for QiShenglong Gopher 2b 4.3" 480(RGB)x272 TFT LCD panel.
> 
> Signed-off-by: Artjom Vejsel 
> ---
>  .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml 
> b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
> index 3624363938dd..e7f3db118c5d 100644
> --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
> +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
> @@ -244,6 +244,8 @@ properties:
>- powertip,ph800480t013-idf02
>  # QiaoDian XianShi Corporation 4"3 TFT LCD panel
>- qiaodian,qd43003c0-40
> +# Shenzhen QiShenglong Industrialist Co., Ltd. Gopher 2b 4.3" 
> 480(RGB)x272 TFT LCD panel
> +  - qishenglong,gopher2b-lcd-panel

Does 'gopher2b' refer to anything besides this panel? If not, then 
'-lcd-panel' is redundant. Otherwise, '-panel' is redundant. Every LCD 
is a panel.

>  # Rocktech Displays Ltd. RK101II01D-CT 10.1" TFT 1280x800
>- rocktech,rk101ii01d-ct
>  # Rocktech Display Ltd. RK070ER9427 800(RGB)x480 TFT LCD panel
> -- 
> 2.32.0
> 
> 


Re: [PATCH v3 1/3] dt-bindings: Add QiShenglong vendor prefix

2021-07-26 Thread Rob Herring
On Mon, 26 Jul 2021 01:15:25 +0300, Artjom Vejsel wrote:
> Add vendor prefix for Shenzhen QiShenglong Industrialist Co., Ltd.
> QiShenglong is a Chinese manufacturer of handheld gaming consoles, most of
> which run (very old) versions of Linux.
> QiShenglong is known as Hamy.
> 
> Signed-off-by: Artjom Vejsel 
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 

Acked-by: Rob Herring 


Re: [Intel-gfx] [PATCH 31/47] drm/i915/guc: Reset implementation for new GuC interface

2021-07-26 Thread Matthew Brost
On Thu, Jul 15, 2021 at 10:36:51AM +0100, Tvrtko Ursulin wrote:
> 
> On 24/06/2021 08:05, Matthew Brost wrote:
> > Reset implementation for new GuC interface. This is the legacy reset
> > implementation which is called when the i915 owns the engine hang check.
> > Future patches will offload the engine hang check to GuC but we will
> > continue to maintain this legacy path as a fallback and this code path
> > is also required if the GuC dies.
> > 
> > With the new GuC interface it is not possible to reset individual
> > engines - it is only possible to reset the GPU entirely. This patch
> > forces an entire chip reset if any engine hangs.
> 
> No updates after my review comments on 6th of May.
> 
> At least:
> 
> 1. wmb documentation
> 

Yea, missed this. Checkpatch yelled at me too. Will be fixed in next
rev.

> 2. Spin lock cycling I either didn't understand or didn't buy the
> explanation. I don't remember seeing that pattern elsewhere in the driver -
> cycle a spinlock to make sure what was updated inside it is visible you
> said?
>

I did respond - not really my fault if you don't understand a fairly
simple concept but I'll explain again.

Change a variable
Cycle a lock
At this point we know anyone that acquires above lock the variable
change is visible.

I can't be the first person in the Linux kernel to do this nor in the
i915.

This basically allows to seal all the reset races without a BKL.

Also I told you I explain in this a doc patch that will get reposted
after GuC submission lands:
https://patchwork.freedesktop.org/patch/432408/?series=89844=1

> 3. Dropping the lock protecting the list in the middle of
> list_for_each_entry_safe and just continuing to iterate like nothing
> happened. (__unwind_incomplete_requests) Again, perhaps I did not understand
> your explanation properly but you did appear to write:
>

To be honest looking at the code now we likely don't need to drop the
look but regardless I don't think we should change this for the
following reasons.

1. I assure you this is safe and works. I can add a better comment
explaining this though.
2. This is thoroughly tested and resets are the hardest thing to get
stable and working.
3. This code is literally going to get deleted when we move to the DRM
scheduler as all the tracking / unwinding / resubmission will be in the
DRM scheduler core.
4. A 2 second search of the driver found that we do the same thing in
intel_gt_retire_requests_timeout so this isn't unprecedented.

Matt

> """
> We only need the active lock for ce->guc_active.requests list. It is
> indeed safe to drop the lock.
> """
> 
> + spin_lock(>guc_active.lock);
> + list_for_each_entry_safe(rq, rn,
> +  >guc_active.requests,
> +  sched.link) {
> + if (i915_request_completed(rq))
> + continue;
> +
> + list_del_init(>sched.link);
> + spin_unlock(>guc_active.lock);
> ...
> + spin_lock(>guc_active.lock);
> + }
> 
> Safe iterator guards against list_del but dropping the lock means the state
> of the overall list can change so next pointer may or may not be valid,
> requests may be missed, I don't know. Needs a comment explaining why it is
> safe.
> 
> Regards,
> 
> Tvrtko
> 
> > 
> > Cc: John Harrison 
> > Signed-off-by: Matthew Brost 
> > ---
> >   drivers/gpu/drm/i915/gt/intel_context.c   |   3 +
> >   drivers/gpu/drm/i915/gt/intel_context_types.h |   7 +
> >   drivers/gpu/drm/i915/gt/intel_engine_types.h  |   6 +
> >   .../drm/i915/gt/intel_execlists_submission.c  |  40 ++
> >   drivers/gpu/drm/i915/gt/intel_gt_pm.c |   6 +-
> >   drivers/gpu/drm/i915/gt/intel_reset.c |  18 +-
> >   .../gpu/drm/i915/gt/intel_ring_submission.c   |  22 +
> >   drivers/gpu/drm/i915/gt/mock_engine.c |  31 +
> >   drivers/gpu/drm/i915/gt/uc/intel_guc.c|  13 -
> >   drivers/gpu/drm/i915/gt/uc/intel_guc.h|   8 +-
> >   .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 581 ++
> >   drivers/gpu/drm/i915/gt/uc/intel_uc.c |  39 +-
> >   drivers/gpu/drm/i915/gt/uc/intel_uc.h |   3 +
> >   drivers/gpu/drm/i915/i915_request.c   |  41 +-
> >   drivers/gpu/drm/i915/i915_request.h   |   2 +
> >   15 files changed, 649 insertions(+), 171 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gt/intel_context.c 
> > b/drivers/gpu/drm/i915/gt/intel_context.c
> > index b24a1b7a3f88..2f01437056a8 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_context.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_context.c
> > @@ -392,6 +392,9 @@ intel_context_init(struct intel_context *ce, struct 
> > intel_engine_cs *engine)
> > spin_lock_init(>guc_state.lock);
> > INIT_LIST_HEAD(>guc_state.fences);
> > +   spin_lock_init(>guc_active.lock);
> > +   INIT_LIST_HEAD(>guc_active.requests);
> > +
> > ce->guc_id = GUC_INVALID_LRC_ID;
> > INIT_LIST_HEAD(>guc_id_link);
> > diff --git 

Re: [PATCH v2] drm/msm/dp: signal audio plugged change at dp_pm_resume

2021-07-26 Thread Stephen Boyd
Quoting Kuogee Hsieh (2021-07-23 09:55:39)
> There is a scenario that dp cable is unplugged from DUT during system
> suspended  will cause audio option state does not match real connection
> state. Fix this problem by Signaling audio plugged change with realtime
> connection status at dp_pm_resume() so that audio option will be in
> correct state after system resumed.
>
> Changes in V2:
> -- correct Fixes tag commit id.
>
> Fixes: f591dbb5fb8c ("drm/msm/dp: power off DP phy at suspend")
> Signed-off-by: Kuogee Hsieh 
> Reviewed-by: Stephen Boyd 
> ---
>  drivers/gpu/drm/msm/dp/dp_display.c | 4 
>  1 file changed, 4 insertions(+)

I noticed that with or without this patch I still have a problem with an
apple dongle where if I leave the dongle connected but unplug the HDMI
cable during suspend the audio device is still there when I resume. The
display looks to be connected in that case too, according to modetest. I
don't know if you want to roll that into this patch or make another
follow-up patch to fix it, but it seems like the sink count isn't
updated on resume? Did commit f591dbb5fb8c break a bunch of logic in
here because now the link is powered down properly and so sink_count
isn't updated properly?

>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index 78c5301..2b660e9 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -1339,6 +1339,10 @@ static int dp_pm_resume(struct device *dev)
> else
> dp->dp_display.is_connected = false;
>
> +   dp_display_handle_plugged_change(g_dp_display,
> +   dp->dp_display.is_connected);
> +
> +

There's also a double newline here that we should probably remove.

> mutex_unlock(>event_mutex);
>
> return 0;


Re: [Intel-gfx] [PATCH 23/51] drm/i915/guc: Direct all breadcrumbs for a class to single breadcrumbs

2021-07-26 Thread Matthew Brost
On Thu, Jul 22, 2021 at 01:46:08PM +0100, Tvrtko Ursulin wrote:
> 
> On 16/07/2021 21:16, Matthew Brost wrote:
> > With GuC virtual engines the physical engine which a request executes
> > and completes on isn't known to the i915. Therefore we can't attach a
> > request to a physical engines breadcrumbs. To work around this we create
> > a single breadcrumbs per engine class when using GuC submission and
> > direct all physical engine interrupts to this breadcrumbs.
> > 
> > v2:
> >   (John H)
> >- Rework header file structure so intel_engine_mask_t can be in
> >  intel_engine_types.h
> > 
> > Signed-off-by: Matthew Brost 
> > CC: John Harrison 
> > ---
> >   drivers/gpu/drm/i915/gt/intel_breadcrumbs.c   | 41 +---
> >   drivers/gpu/drm/i915/gt/intel_breadcrumbs.h   | 16 -
> >   .../gpu/drm/i915/gt/intel_breadcrumbs_types.h |  7 ++
> >   drivers/gpu/drm/i915/gt/intel_engine.h|  3 +
> >   drivers/gpu/drm/i915/gt/intel_engine_cs.c | 28 +++-
> >   drivers/gpu/drm/i915/gt/intel_engine_types.h  |  2 +-
> >   .../drm/i915/gt/intel_execlists_submission.c  |  2 +-
> >   drivers/gpu/drm/i915/gt/mock_engine.c |  4 +-
> >   .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 67 +--
> >   9 files changed, 133 insertions(+), 37 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c 
> > b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
> > index 38cc42783dfb..2007dc6f6b99 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
> > @@ -15,28 +15,14 @@
> >   #include "intel_gt_pm.h"
> >   #include "intel_gt_requests.h"
> > -static bool irq_enable(struct intel_engine_cs *engine)
> > +static bool irq_enable(struct intel_breadcrumbs *b)
> >   {
> > -   if (!engine->irq_enable)
> > -   return false;
> > -
> > -   /* Caller disables interrupts */
> > -   spin_lock(>gt->irq_lock);
> > -   engine->irq_enable(engine);
> > -   spin_unlock(>gt->irq_lock);
> > -
> > -   return true;
> > +   return intel_engine_irq_enable(b->irq_engine);
> >   }
> > -static void irq_disable(struct intel_engine_cs *engine)
> > +static void irq_disable(struct intel_breadcrumbs *b)
> >   {
> > -   if (!engine->irq_disable)
> > -   return;
> > -
> > -   /* Caller disables interrupts */
> > -   spin_lock(>gt->irq_lock);
> > -   engine->irq_disable(engine);
> > -   spin_unlock(>gt->irq_lock);
> > +   intel_engine_irq_disable(b->irq_engine);
> >   }
> >   static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
> > @@ -57,7 +43,7 @@ static void __intel_breadcrumbs_arm_irq(struct 
> > intel_breadcrumbs *b)
> > WRITE_ONCE(b->irq_armed, true);
> > /* Requests may have completed before we could enable the interrupt. */
> > -   if (!b->irq_enabled++ && irq_enable(b->irq_engine))
> > +   if (!b->irq_enabled++ && b->irq_enable(b))
> > irq_work_queue(>irq_work);
> >   }
> > @@ -76,7 +62,7 @@ static void __intel_breadcrumbs_disarm_irq(struct 
> > intel_breadcrumbs *b)
> >   {
> > GEM_BUG_ON(!b->irq_enabled);
> > if (!--b->irq_enabled)
> > -   irq_disable(b->irq_engine);
> > +   b->irq_disable(b);
> > WRITE_ONCE(b->irq_armed, false);
> > intel_gt_pm_put_async(b->irq_engine->gt);
> > @@ -281,7 +267,7 @@ intel_breadcrumbs_create(struct intel_engine_cs 
> > *irq_engine)
> > if (!b)
> > return NULL;
> > -   b->irq_engine = irq_engine;
> > +   kref_init(>ref);
> > spin_lock_init(>signalers_lock);
> > INIT_LIST_HEAD(>signalers);
> > @@ -290,6 +276,10 @@ intel_breadcrumbs_create(struct intel_engine_cs 
> > *irq_engine)
> > spin_lock_init(>irq_lock);
> > init_irq_work(>irq_work, signal_irq_work);
> > +   b->irq_engine = irq_engine;
> > +   b->irq_enable = irq_enable;
> > +   b->irq_disable = irq_disable;
> > +
> > return b;
> >   }
> > @@ -303,9 +293,9 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs 
> > *b)
> > spin_lock_irqsave(>irq_lock, flags);
> > if (b->irq_enabled)
> > -   irq_enable(b->irq_engine);
> > +   b->irq_enable(b);
> > else
> > -   irq_disable(b->irq_engine);
> > +   b->irq_disable(b);
> > spin_unlock_irqrestore(>irq_lock, flags);
> >   }
> > @@ -325,11 +315,14 @@ void __intel_breadcrumbs_park(struct 
> > intel_breadcrumbs *b)
> > }
> >   }
> > -void intel_breadcrumbs_free(struct intel_breadcrumbs *b)
> > +void intel_breadcrumbs_free(struct kref *kref)
> >   {
> > +   struct intel_breadcrumbs *b = container_of(kref, typeof(*b), ref);
> > +
> > irq_work_sync(>irq_work);
> > GEM_BUG_ON(!list_empty(>signalers));
> > GEM_BUG_ON(b->irq_armed);
> > +
> > kfree(b);
> >   }
> > diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h 
> > b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
> > index 3ce5ce270b04..be0d4f379a85 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
> > +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
> > @@ 

Re: linux-next: build failure due to the drm tree

2021-07-26 Thread Javier Martinez Canillas
Hello Mark,

On 7/26/21 11:36 PM, Mark Brown wrote:
> Hi all,
> 
> Today's -next fails to build an arm64 allnoconfig:
> 
> aarch64-none-linux-gnu-ld: drivers/firmware/sysfb.o: in function `sysfb_init':
> sysfb.c:(.init.text+0xc): undefined reference to `screen_info'
> aarch64-none-linux-gnu-ld: drivers/firmware/sysfb.o: relocation 
> R_AARCH64_ADR_PREL_PG_HI21 against symbol `screen_info' which may bind 
> externally can not be used when making a shared object; recompile with -fPIC
> sysfb.c:(.init.text+0xc): dangerous relocation: unsupported relocation
> aarch64-none-linux-gnu-ld: sysfb.c:(.init.text+0x10): undefined reference to 
> `screen_info'
> make[1]: *** [/tmp/next/build/Makefile:1276: vmlinux] Error 1
> 
> Caused by
> 
>   d391c58271072d0b0f ("drivers/firmware: move x86 Generic System Framebuffers 
> support")
> 

Yes, this was already reported by the kernel test robot and posted a fix
a few days ago: https://lore.kernel.org/patchwork/patch/1465623/

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat



linux-next: build failure due to the drm tree

2021-07-26 Thread Mark Brown
Hi all,

Today's -next fails to build an arm64 allnoconfig:

aarch64-none-linux-gnu-ld: drivers/firmware/sysfb.o: in function `sysfb_init':
sysfb.c:(.init.text+0xc): undefined reference to `screen_info'
aarch64-none-linux-gnu-ld: drivers/firmware/sysfb.o: relocation 
R_AARCH64_ADR_PREL_PG_HI21 against symbol `screen_info' which may bind 
externally can not be used when making a shared object; recompile with -fPIC
sysfb.c:(.init.text+0xc): dangerous relocation: unsupported relocation
aarch64-none-linux-gnu-ld: sysfb.c:(.init.text+0x10): undefined reference to 
`screen_info'
make[1]: *** [/tmp/next/build/Makefile:1276: vmlinux] Error 1

Caused by

  d391c58271072d0b0f ("drivers/firmware: move x86 Generic System Framebuffers 
support")

or one of the related commits.


Re: [PATCH v5] drm/msm/dp: add logs across DP driver for ease of debugging

2021-07-26 Thread Stephen Boyd
Quoting maitreye (2021-07-26 10:36:26)
> @@ -509,6 +515,7 @@ static int dp_display_usbpd_attention_cb(struct device 
> *dev)
> DRM_ERROR("invalid dev\n");
> return -EINVAL;
> }
> +   DRM_DEBUG_DP("sink_request: %d\n", sink_request);

This one is bad. sink_request isn't assigned yet.

>
> dp = container_of(g_dp_display,
> struct dp_display_private, dp_display);
> @@ -523,6 +530,7 @@ static int dp_display_usbpd_attention_cb(struct device 
> *dev)
> rc = dp_link_process_request(dp->link);
> if (!rc) {
> sink_request = dp->link->sink_request;
> +   DRM_DEBUG_DP("hpd_state=%d sink_count=%d\n", dp->hpd_state, 
> sink_request);

Should that say sink_request?

> if (sink_request & DS_PORT_STATUS_CHANGED)
> rc = dp_display_handle_port_ststus_changed(dp);
> else


Re: [PATCH v2 5/5] drm/vkms: Map output framebuffer BOs with drm_gem_fb_vmap()

2021-07-26 Thread Rodrigo Siqueira
On 07/25, Thomas Zimmermann wrote:
> Abstract the framebuffer details by mappings its BOs with a call
> to drm_gem_fb_vmap(). Unmap with drm_gem_fb_vunamp().
> 
> Before, the output address with stored as raw pointer in the priv
> field of struct drm_writeback_job. Introduce the new type
> struct vkms_writeback_job, which holds the output mappings addresses
> while the writeback job is active.
> 
> The patchset also cleans up some internal casting an setup of the
> output addresses. No functional changes.
> 
> Signed-off-by: Thomas Zimmermann 
> ---
>  drivers/gpu/drm/vkms/vkms_composer.c  |  2 +-
>  drivers/gpu/drm/vkms/vkms_drv.h   |  6 +-
>  drivers/gpu/drm/vkms/vkms_writeback.c | 21 ++---
>  3 files changed, 16 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
> b/drivers/gpu/drm/vkms/vkms_composer.c
> index ead8fff81f30..49f109c3a2b3 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -257,7 +257,7 @@ void vkms_composer_worker(struct work_struct *work)
>   return;
>  
>   if (wb_pending)
> - vaddr_out = crtc_state->active_writeback;
> + vaddr_out = crtc_state->active_writeback->map[0].vaddr;
>  
>   ret = compose_active_planes(_out, primary_composer,
>   crtc_state);
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
> index 8c731b6dcba7..8bc9e3f52e1f 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.h
> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> @@ -20,6 +20,10 @@
>  #define XRES_MAX  8192
>  #define YRES_MAX  8192
>  
> +struct vkms_writeback_job {
> + struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];
> +};
> +
>  struct vkms_composer {
>   struct drm_framebuffer fb;
>   struct drm_rect src, dst;
> @@ -57,7 +61,7 @@ struct vkms_crtc_state {
>   int num_active_planes;
>   /* stack of active planes for crc computation, should be in z order */
>   struct vkms_plane_state **active_planes;
> - void *active_writeback;
> + struct vkms_writeback_job *active_writeback;
>  
>   /* below four are protected by vkms_output.composer_lock */
>   bool crc_pending;
> diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c 
> b/drivers/gpu/drm/vkms/vkms_writeback.c
> index 0935686475a0..765bb85ba76c 100644
> --- a/drivers/gpu/drm/vkms/vkms_writeback.c
> +++ b/drivers/gpu/drm/vkms/vkms_writeback.c
> @@ -65,21 +65,23 @@ static int vkms_wb_connector_get_modes(struct 
> drm_connector *connector)
>  static int vkms_wb_prepare_job(struct drm_writeback_connector *wb_connector,
>  struct drm_writeback_job *job)
>  {
> - struct drm_gem_object *gem_obj;
> - struct dma_buf_map map;
> + struct vkms_writeback_job *vkmsjob;
>   int ret;
>  
>   if (!job->fb)
>   return 0;
>  
> - gem_obj = drm_gem_fb_get_obj(job->fb, 0);
> - ret = drm_gem_shmem_vmap(gem_obj, );
> + vkmsjob = kzalloc(sizeof(*vkmsjob), GFP_KERNEL);
> + if (!vkmsjob)
> + return -ENOMEM;
> +
> + ret = drm_gem_fb_vmap(job->fb, vkmsjob->map);
>   if (ret) {
>   DRM_ERROR("vmap failed: %d\n", ret);
>   return ret;
>   }
>  
> - job->priv = map.vaddr;
> + job->priv = vkmsjob;
>  
>   return 0;
>  }
> @@ -87,18 +89,15 @@ static int vkms_wb_prepare_job(struct 
> drm_writeback_connector *wb_connector,
>  static void vkms_wb_cleanup_job(struct drm_writeback_connector *connector,
>   struct drm_writeback_job *job)
>  {
> - struct drm_gem_object *gem_obj;
> + struct vkms_writeback_job *vkmsjob = job->priv;
>   struct vkms_device *vkmsdev;
> - struct dma_buf_map map;
>  
>   if (!job->fb)
>   return;
>  
> - gem_obj = drm_gem_fb_get_obj(job->fb, 0);
> - dma_buf_map_set_vaddr(, job->priv);
> - drm_gem_shmem_vunmap(gem_obj, );
> + drm_gem_fb_vunmap(job->fb, vkmsjob->map);
>  
> - vkmsdev = drm_device_to_vkms_device(gem_obj->dev);
> + vkmsdev = drm_device_to_vkms_device(job->fb->dev);
>   vkms_set_composer(>output, false);
>  }
>  
> -- 
> 2.32.0
>

Reviewed-by: Rodrigo Siqueira  

-- 
Rodrigo Siqueira
https://siqueira.tech


[PATCH V3 2/2] drm/bridge: lvds-codec: Add support for LVDS data mapping select

2021-07-26 Thread Marek Vasut
Decoder input LVDS format is a property of the decoder chip or even
its strapping. Handle data-mapping the same way lvds-panel does. In
case data-mapping is not present, do nothing, since there are still
legacy bindings which do not specify this property.

Signed-off-by: Marek Vasut 
Cc: Laurent Pinchart 
Cc: Sam Ravnborg 
To: dri-devel@lists.freedesktop.org
---
V2: - Move the data-mapping to endpoint
V3: - Rebase on V2 submitted a while ago, reinstate changelog
- Use .atomic_get_input_bus_fmts for the decoder, separate funcs for encoder
---
 drivers/gpu/drm/bridge/lvds-codec.c | 76 -
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/lvds-codec.c 
b/drivers/gpu/drm/bridge/lvds-codec.c
index dcf579a4cf833..afa7ce7ea01e8 100644
--- a/drivers/gpu/drm/bridge/lvds-codec.c
+++ b/drivers/gpu/drm/bridge/lvds-codec.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -22,6 +23,7 @@ struct lvds_codec {
struct regulator *vcc;
struct gpio_desc *powerdown_gpio;
u32 connector_type;
+   unsigned int bus_format;
 };
 
 static inline struct lvds_codec *to_lvds_codec(struct drm_bridge *bridge)
@@ -74,12 +76,50 @@ static const struct drm_bridge_funcs funcs = {
.disable = lvds_codec_disable,
 };
 
+#define MAX_INPUT_SEL_FORMATS 1
+static u32 *
+lvds_codec_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+struct drm_bridge_state *bridge_state,
+struct drm_crtc_state *crtc_state,
+struct drm_connector_state *conn_state,
+u32 output_fmt,
+unsigned int *num_input_fmts)
+{
+   struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
+   u32 *input_fmts;
+
+   *num_input_fmts = 0;
+
+   input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
+GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+
+   input_fmts[0] = lvds_codec->bus_format;
+   *num_input_fmts = MAX_INPUT_SEL_FORMATS;
+
+   return input_fmts;
+}
+
+static const struct drm_bridge_funcs funcs_decoder = {
+   .attach = lvds_codec_attach,
+   .enable = lvds_codec_enable,
+   .disable = lvds_codec_disable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
+   .atomic_get_input_bus_fmts = lvds_codec_atomic_get_input_bus_fmts,
+};
+
 static int lvds_codec_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
struct device_node *panel_node;
+   struct device_node *bus_node;
struct drm_panel *panel;
struct lvds_codec *lvds_codec;
+   const char *mapping;
+   int ret;
 
lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL);
if (!lvds_codec)
@@ -119,13 +159,47 @@ static int lvds_codec_probe(struct platform_device *pdev)
if (IS_ERR(lvds_codec->panel_bridge))
return PTR_ERR(lvds_codec->panel_bridge);
 
+   lvds_codec->bridge.funcs = 
+
+   /*
+* Decoder input LVDS format is a property of the decoder chip or even
+* its strapping. Handle data-mapping the same way lvds-panel does. In
+* case data-mapping is not present, do nothing, since there are still
+* legacy bindings which do not specify this property.
+*/
+   if (lvds_codec->connector_type != DRM_MODE_CONNECTOR_LVDS) {
+   bus_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
+   if (!bus_node) {
+   dev_dbg(dev, "bus DT node not found\n");
+   return -ENXIO;
+   }
+
+   ret = of_property_read_string(bus_node, "data-mapping",
+ );
+   of_node_put(bus_node);
+   if (ret < 0) {
+   dev_err(dev, "missing 'data-mapping' DT property\n");
+   } else {
+   if (!strcmp(mapping, "jeida-18")) {
+   lvds_codec->bus_format = 
MEDIA_BUS_FMT_RGB666_1X7X3_SPWG;
+   } else if (!strcmp(mapping, "jeida-24")) {
+   lvds_codec->bus_format = 
MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
+   } else if (!strcmp(mapping, "vesa-24")) {
+   lvds_codec->bus_format = 
MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;
+   } else {
+   dev_err(dev, "invalid 'data-mapping' DT 
property\n");
+   return -EINVAL;
+   }
+   lvds_codec->bridge.funcs = _decoder;
+   }
+   }
+
/*
 * The panel_bridge 

[PATCH V3 1/2] dt-bindings: display: bridge: lvds-codec: Document LVDS data mapping select

2021-07-26 Thread Marek Vasut
Decoder input LVDS format is a property of the decoder chip or even
its strapping. Add DT property data-mapping the same way lvds-panel
does, to define the LVDS data mapping.

Signed-off-by: Marek Vasut 
Cc: Laurent Pinchart 
Cc: Rob Herring 
Cc: Sam Ravnborg 
Cc: devicet...@vger.kernel.org
To: dri-devel@lists.freedesktop.org
---
V2: - Use allOf
- Move the data-mapping to endpoint
V3: - Rebase on V2 submitted a while ago, reinstate changelog
- Drop the allOf and un-rebase on previous pclk patch
---
 .../bindings/display/bridge/lvds-codec.yaml   | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml 
b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
index 304a1367faaa7..f795c671c3ce1 100644
--- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
@@ -60,6 +60,21 @@ properties:
   For LVDS encoders, port 1 is the LVDS output
   For LVDS decoders, port 1 is the parallel output
 
+properties:
+  endpoint:
+$ref: /schemas/media/video-interfaces.yaml#
+unevaluatedProperties: false
+
+properties:
+  data-mapping:
+enum:
+  - jeida-18
+  - jeida-24
+  - vesa-24
+description: |
+  The color signals mapping order. See details in
+  Documentation/devicetree/bindings/display/panel/lvds.yaml
+
 required:
   - port@0
   - port@1
@@ -71,6 +86,22 @@ properties:
 
   power-supply: true
 
+if:
+  not:
+properties:
+  compatible:
+contains:
+  const: lvds-decoder
+then:
+  properties:
+ports:
+  properties:
+port@1:
+  properties:
+endpoint:
+  properties:
+data-mapping: false
+
 required:
   - compatible
   - ports
-- 
2.30.2



Re: [PATCH v2] drm/msm/dp: signal audio plugged change at dp_pm_resume

2021-07-26 Thread Stephen Boyd
Quoting Kuogee Hsieh (2021-07-23 09:55:39)
> There is a scenario that dp cable is unplugged from DUT during system
> suspended  will cause audio option state does not match real connection
> state. Fix this problem by Signaling audio plugged change with realtime
> connection status at dp_pm_resume() so that audio option will be in
> correct state after system resumed.
>
> Changes in V2:
> -- correct Fixes tag commit id.
>
> Fixes: f591dbb5fb8c ("drm/msm/dp: power off DP phy at suspend")
> Signed-off-by: Kuogee Hsieh 
> Reviewed-by: Stephen Boyd 
> ---
>  drivers/gpu/drm/msm/dp/dp_display.c | 4 
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index 78c5301..2b660e9 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -1339,6 +1339,10 @@ static int dp_pm_resume(struct device *dev)
> else
> dp->dp_display.is_connected = false;
>
> +   dp_display_handle_plugged_change(g_dp_display,

Can this be dp_display instead of g_dp_display?

> +   dp->dp_display.is_connected);
> +
> +
> mutex_unlock(>event_mutex);
>
> return 0;


Re: [PATCH v5] drm/msm/dp: add logs across DP driver for ease of debugging

2021-07-26 Thread Stephen Boyd
Quoting maitreye (2021-07-26 10:36:26)
> From: Maitreyee Rao 
>
> Add trace points across the MSM DP driver to help debug
> interop issues.
>
> Changes in v2:
>  - Got rid of redundant log messages.
>  - Added %#x instead of 0x%x wherever required.
>  - Got rid of __func__ calls in debug messages.
>  - Added newline wherever missing.
>
> Changes in v3:
>  - Got rid of redundant log messages.
>  - Unstuck colon from printf specifier in various places.
>
> Changes in v4:
>  - Changed goto statement and used if else-if
>
> Changes in v5:
>  - Changed if else if statement,
>to not overwrite the ret variable multiple times.
>
> Signed-off-by: Maitreyee Rao 
> ---

Reviewed-by: Stephen Boyd 


[Bug 205089] amdgpu : drm:amdgpu_cs_ioctl : Failed to initialize parser -125

2021-07-26 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=205089

jes...@jnsn.dev changed:

   What|Removed |Added

 CC||jes...@jnsn.dev

--- Comment #14 from jes...@jnsn.dev ---
I'm now seeing this bug again. This time it happening while launching dota2.

Hardware:
 RX 5700 XT
 Ryzen 3800X

Software:
 Mesa 21.1.5 (arch mainline)
 Linux 5.13.4.arch2-1

Log (Notice that it's most recent first):
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: GPU
reset(2) succeeded!
 Jul 26 22:15:55 delusionalStation kernel: [drm:amdgpu_cs_ioctl [amdgpu]]
*ERROR* Failed to initialize parser -125!
 Jul 26 22:15:55 delusionalStation kernel: [drm] Skip scheduling IBs!
 ... A bunch of repeats
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: recover
vram bo from shadow done
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: recover
vram bo from shadow start
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
jpeg_dec uses VM inv eng 5 on hub 1
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
vcn_enc1 uses VM inv eng 4 on hub 1
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
vcn_enc0 uses VM inv eng 1 on hub 1
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
vcn_dec uses VM inv eng 0 on hub 1
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
sdma1 uses VM inv eng 13 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
sdma0 uses VM inv eng 12 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
kiq_2.1.0 uses VM inv eng 11 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
comp_1.3.1 uses VM inv eng 10 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
comp_1.2.1 uses VM inv eng 9 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
comp_1.1.1 uses VM inv eng 8 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
comp_1.0.1 uses VM inv eng 7 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
comp_1.3.0 uses VM inv eng 6 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
comp_1.2.0 uses VM inv eng 5 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
comp_1.1.0 uses VM inv eng 4 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
comp_1.0.0 uses VM inv eng 1 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: ring
gfx_0.0.0 uses VM inv eng 0 on hub 0
 Jul 26 22:15:55 delusionalStation kernel: [drm] JPEG decode initialized
successfully.
 Jul 26 22:15:55 delusionalStation kernel: [drm] VCN decode and encode
initialized successfully(under DPG Mode).
 Jul 26 22:15:55 delusionalStation kernel: [drm] kiq ring mec 2 pipe 1 q 0
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: SMU is
resumed successfully!
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: SMU is
resuming...
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu:
SECUREDISPLAY: securedisplay ta ucode is not available
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: RAP:
optional rap ta ucode is not available
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: RAS:
optional ras ta ucode is not available
 Jul 26 22:15:55 delusionalStation kernel: [drm] reserve 0x90 from
0x81fe40 for PSP TMR
 Jul 26 22:15:55 delusionalStation kernel: [drm] PSP is resuming...
 Jul 26 22:15:55 delusionalStation kernel: [drm] VRAM is lost due to GPU reset!
 Jul 26 22:15:55 delusionalStation kernel: [drm] PCIE GART of 512M enabled
(table at 0x00800030).
 Jul 26 22:15:55 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: GPU
reset succeeded, trying to resume
 Jul 26 22:15:51 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: BACO
reset
 Jul 26 22:15:51 delusionalStation kernel: [drm] free PSP TMR buffer
 Jul 26 22:15:51 delusionalStation kernel: [drm:gfx_v10_0_hw_fini [amdgpu]]
*ERROR* failed to halt cp gfx
 Jul 26 22:15:51 delusionalStation kernel: [drm:gfx_v10_0_hw_fini [amdgpu]]
*ERROR* KCQ disable failed
 Jul 26 22:15:51 delusionalStation kernel: amdgpu :0a:00.0:
[drm:amdgpu_ring_test_helper [amdgpu]] *ERROR* ring kiq_2.1.0 test failed
(-110)
 Jul 26 22:15:51 delusionalStation kernel: [drm:gfx_v10_0_hw_fini [amdgpu]]
*ERROR* KGQ disable failed
 Jul 26 22:15:51 delusionalStation kernel: amdgpu :0a:00.0:
[drm:amdgpu_ring_test_helper [amdgpu]] *ERROR* ring kiq_2.1.0 test failed
(-110)
 Jul 26 22:15:51 delusionalStation kernel: amdgpu :0a:00.0: amdgpu: GPU
reset 

[PATCH V2 2/2] drm/bridge: lvds-codec: Add support for LVDS data mapping select

2021-07-26 Thread Marek Vasut
Decoder input LVDS format is a property of the decoder chip or even
its strapping. Handle data-mapping the same way lvds-panel does. In
case data-mapping is not present, do nothing, since there are still
legacy bindings which do not specify this property.

Signed-off-by: Marek Vasut 
Cc: Laurent Pinchart 
Cc: Sam Ravnborg 
To: dri-devel@lists.freedesktop.org
---
V2: Use .atomic_get_input_bus_fmts for the decoder, separate funcs for encoder
---
 drivers/gpu/drm/bridge/lvds-codec.c | 71 -
 1 file changed, 69 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/lvds-codec.c 
b/drivers/gpu/drm/bridge/lvds-codec.c
index dcf579a4cf833..d7ec8c4e30f33 100644
--- a/drivers/gpu/drm/bridge/lvds-codec.c
+++ b/drivers/gpu/drm/bridge/lvds-codec.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -22,6 +23,7 @@ struct lvds_codec {
struct regulator *vcc;
struct gpio_desc *powerdown_gpio;
u32 connector_type;
+   unsigned int bus_format;
 };
 
 static inline struct lvds_codec *to_lvds_codec(struct drm_bridge *bridge)
@@ -68,18 +70,56 @@ static void lvds_codec_disable(struct drm_bridge *bridge)
"Failed to disable regulator \"vcc\": %d\n", ret);
 }
 
-static const struct drm_bridge_funcs funcs = {
+static const struct drm_bridge_funcs funcs_encoder = {
.attach = lvds_codec_attach,
.enable = lvds_codec_enable,
.disable = lvds_codec_disable,
 };
 
+#define MAX_INPUT_SEL_FORMATS 1
+static u32 *
+lvds_codec_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+struct drm_bridge_state *bridge_state,
+struct drm_crtc_state *crtc_state,
+struct drm_connector_state *conn_state,
+u32 output_fmt,
+unsigned int *num_input_fmts)
+{
+   struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
+   u32 *input_fmts;
+
+   *num_input_fmts = 0;
+
+   input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
+GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+
+   input_fmts[0] = lvds_codec->bus_format;
+   *num_input_fmts = MAX_INPUT_SEL_FORMATS;
+
+   return input_fmts;
+}
+
+static const struct drm_bridge_funcs funcs_decoder = {
+   .attach = lvds_codec_attach,
+   .enable = lvds_codec_enable,
+   .disable = lvds_codec_disable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
+   .atomic_get_input_bus_fmts = lvds_codec_atomic_get_input_bus_fmts,
+};
+
 static int lvds_codec_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
struct device_node *panel_node;
struct drm_panel *panel;
struct lvds_codec *lvds_codec;
+   const char *mapping;
+   int ret;
+   u32 val;
 
lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL);
if (!lvds_codec)
@@ -119,13 +159,40 @@ static int lvds_codec_probe(struct platform_device *pdev)
if (IS_ERR(lvds_codec->panel_bridge))
return PTR_ERR(lvds_codec->panel_bridge);
 
+   /*
+* Decoder input LVDS format is a property of the decoder chip or even
+* its strapping. Handle data-mapping the same way lvds-panel does. In
+* case data-mapping is not present, do nothing, since there are still
+* legacy bindings which do not specify this property.
+*/
+   if (lvds_codec->connector_type != DRM_MODE_CONNECTOR_LVDS) {
+   ret = of_property_read_string(dev->of_node, "data-mapping",
+ );
+   if (ret < 0) {
+   dev_err(dev, "missing 'data-mapping' DT property\n");
+   } else {
+   if (!strcmp(mapping, "jeida-18")) {
+   lvds_codec->bus_format = 
MEDIA_BUS_FMT_RGB666_1X7X3_SPWG;
+   } else if (!strcmp(mapping, "jeida-24")) {
+   lvds_codec->bus_format = 
MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
+   } else if (!strcmp(mapping, "vesa-24")) {
+   lvds_codec->bus_format = 
MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;
+   } else {
+   dev_err(dev, "invalid 'data-mapping' DT 
property\n");
+   return -EINVAL;
+   }
+   }
+   lvds_codec->bridge.funcs = _decoder;
+   } else {
+   lvds_codec->bridge.funcs = _encoder;
+   }
+
/*
 * The panel_bridge bridge is attached to the panel's of_node,
 * but we need a bridge attached to our of_node for 

[PATCH V2 1/2] dt-bindings: display: bridge: lvds-codec: Document LVDS data mapping select

2021-07-26 Thread Marek Vasut
Decoder input LVDS format is a property of the decoder chip or even
its strapping. Add DT property data-mapping the same way lvds-panel
does, to define the LVDS data mapping.

Signed-off-by: Marek Vasut 
Cc: Laurent Pinchart 
Cc: Rob Herring 
Cc: Sam Ravnborg 
Cc: devicet...@vger.kernel.org
To: dri-devel@lists.freedesktop.org
---
V2: Rebase on latest next
---
 .../bindings/display/bridge/lvds-codec.yaml   | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml 
b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
index 304a1367faaa7..33e0c08933b72 100644
--- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
@@ -64,6 +64,15 @@ properties:
   - port@0
   - port@1
 
+  data-mapping:
+enum:
+  - jeida-18
+  - jeida-24
+  - vesa-24
+description: |
+  The color signals mapping order. See details in
+  Documentation/devicetree/bindings/display/panel/lvds.yaml
+
   powerdown-gpios:
 description:
   The GPIO used to control the power down line of this device.
@@ -71,6 +80,16 @@ properties:
 
   power-supply: true
 
+if:
+  not:
+properties:
+  compatible:
+contains:
+  const: lvds-decoder
+then:
+  properties:
+data-mapping: false
+
 required:
   - compatible
   - ports
-- 
2.30.2



Re: [PATCH v2 4/8] video: ep93xx: Prepare clock before using it

2021-07-26 Thread Sam Ravnborg
Hi Nikita,
On Mon, Jul 26, 2021 at 04:59:52PM +0300, Nikita Shubin wrote:
> From: Alexander Sverdlin 
> 
> Use clk_prepare_enable()/clk_disable_unprepare() in preparation for switch
> to Common Clock Framework.
> 
> Signed-off-by: Alexander Sverdlin 
> Signed-off-by: Nikita Shubin 

Thanks, applied to drm-misc-next.
The patch will show up in -next within a week.

Sam


Re: [PATCH v2] drm: add logging for RMFB ioctl

2021-07-26 Thread Sam Ravnborg
Hi Simon,

On Mon, Jul 26, 2021 at 07:49:06AM +, Simon Ser wrote:
> We already have logging for ADDFB2. Add some logging for RMFB as
> well.
> 
> This can be handy when trying to find out why a CRTC gets magically
> disabled.
> 
> v2: make log message more explicit, add log messages to
> drm_framebuffer_remove (Daniel)
> 
> Signed-off-by: Simon Ser 
> Cc: Daniel Vetter 

Looks like some very useful debugging logging.

Acked-by: Sam Ravnborg 


Re: [PATCH 1/5] drm/vmwgfx: unbind in vmw_ttm_unpopulate

2021-07-26 Thread Dave Airlie
On Tue, 27 Jul 2021 at 05:35, Christian König
 wrote:
>
> Am 26.07.21 um 02:03 schrieb Dave Airlie:
> > [SNIP]
> >> But you know, normal human: Only equipped with one head and two hands
> >> and not cloneable.
> > I'm the same, but I'm not seeing where this problem happens at all, do
> > we have any backtraces or demos for this?
>
> I've stumbled over this while working on some patches which accidentally
> broke delayed delete and caused random memory corruption and was
> wondering how that even happened in the first place.
>
> Having stale PTEs in the GART isn't a problem unless you break other
> things. Which is also the reason why I haven't added a CC stable yet.
>
> > I split bind/unbind into the driver, but the driver should still
> > always be moving things to unbound states before an unpopulate is
> > called, is there a driver doing something unexpected here?
>
> Possible, I was only testing with amdgpu and the GART handling is rather
> special there (which was one of the reasons why we did that in the first
> place).
>
> > at worst I'd like to see a WARN_ON put in first and a test in igt that
> > triggers it, because right now I'm not see that path through the
> > drivers/ttm that leads to unpopulated pages ending up happening while
> > bound.
> >
> >  From 5.14-rc3 unpopulate is called from ttm_bo_pipeline_gutting in
> > non-ghost path and there is no unbind,
> > pipeline gutting is called from evict/validate, when there is no
> > placement suggested for the object, is this case getting hit somewhere
> > without the driver having previously unbound things?
>
> Yes, that will hit absolutely. Most likely with VM page tables for
> amdgpu which uses this.

My thing is here we moved binding/unbinding to the driver, if the
driver has a bug
I'd expect the fix to be in the driver side here. I think giving
drivers control over something
and enforcing it in the core/helpers is fine, but I don't think we
should be adding back
the midlayering.

> > ttm_tt_destroy_common: calls unpopulate, everyone calls this directly
> > after unbinding
> > ttm_tt_swapout: calls unpopulate, we don't swapout objects from TT
> > directly, we should always unbind first, this used to have an assert
> > against that,
> > ttm_tt_populate: call unpopulate in failure path
>
> unbinding was moved into the driver, so ttm_tt_swapout() won't unbind
> anything before calling unpopulate as far as I can see.

But we won't call swapout on BOs that aren't in SYSTEM and to be in SYSTEM,
the bo would have to go through the driver move function which will unbind it.

>
> > So any place I can see unpopulate getting called with a bound TT
> > should be a bug, and fixed, we could protect against it better but I'm
> > not seeing the need for this series to outright revert things back as
> > helping.
>
> I'm not reverting this because it is offhand wrong, but making sure the
> GART is clear before unpopulating the TT object sounds like the much
> more natural thing to do and the state machine is something I certainly
> don't see in the backend.
>

I don't think that's the core's responsibility anymore, I'm fine with
adding code and
even an flag that says if the the TT is bound/unbound that unpopulate
can WARN_ON()
against so we get a backtrace and track down where something is
getting unpopulated
without going through the driver move function to be unbound.

Dave.


Re: [PATCH v3 3/3] drm/panel-simple: add Gopher 2b LCD panel

2021-07-26 Thread Sam Ravnborg
Hi Paul,
On Mon, Jul 26, 2021 at 10:02:08AM +0100, Paul Cercueil wrote:
> Hi Artjom,
> 
> Le lun., juil. 26 2021 at 01:15:27 +0300, Artjom Vejsel 
> a écrit :
> > The Gopher 2b LCD panel is used in Gopher 2b handhelds.
> > It's simple panel with NewVision NV3047 driver, but SPI lines are not
> > connected.
> > It has no specific name, since it's unique to that handhelds.
> > lot name at AliExpress: 4.3 inch 40PIN TFT LCD Screen COG NV3047 Drive
> > IC 480(RGB)*272 No Touch 24Bit RGB Interface
> 
> From what I gathered the Gopher2's LCD panel is the exact same that is
> inside the RS-07 handheld. According to the teardown (in [1]), the RS-07
> panel is a Amelin AML043056B0-40 (see [2]).
> 
> Could you verify that? According to the photos, the product code is written
> on the flexible connector.
> 
> If that's the case, instead of using the "qishenglong,gopher2b-lcd-panel"
> compatible string, could you use "amelin,aml043056b0-40"?
> 
> Cheers,
> -Paul

I assume you are going to apply this patch-set when you are happy with it.
OK?

Sam


Re: [PATCH 1/2] dt-bindings: display: simple: Add AUO B133HAN05 & B140HAN06

2021-07-26 Thread Sam Ravnborg
Hi Björn,
On Mon, Jul 26, 2021 at 10:32:59AM -0700, Bjorn Andersson wrote:
> Add bindings for the two AUO panels B133HAN05 and B140HAN06, both
> 1920x1080 panels with 16.7M colors, first being 13.3" and the latter
> 14.0".
> 
> Signed-off-by: Bjorn Andersson 

Thanks, both patches applied to drm-misc-next.

Sam


[PATCH V2] drm: mxsfb: Use bus_format from the nearest bridge if present

2021-07-26 Thread Marek Vasut
In case there is a bridge connected to the LCDIF, use bus_format
from the bridge, otherwise behave as before and use bus_format
from the connector. This way, even if there are multiple bridges
in the display pipeline, the LCDIF will use the correct format.

Reviewed-by: Lucas Stach 
Signed-off-by: Marek Vasut 
Cc: Daniel Abrecht 
Cc: Emil Velikov 
Cc: Laurent Pinchart 
Cc: Lucas Stach 
Cc: Stefan Agner 
---
V2: Drop null checks for variables which must always be non-null,
state and bridge_state
---
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 32 +++
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c 
b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index a6681bb699f14..4501deb48e6b2 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -47,16 +47,13 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private 
*mxsfb, u32 val)
  * Setup the MXSFB registers for decoding the pixels out of the framebuffer and
  * outputting them on the bus.
  */
-static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb)
+static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb,
+ const u32 bus_format)
 {
struct drm_device *drm = mxsfb->drm;
const u32 format = mxsfb->crtc.primary->state->fb->format->format;
-   u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
u32 ctrl, ctrl1;
 
-   if (mxsfb->connector->display_info.num_bus_formats)
-   bus_format = mxsfb->connector->display_info.bus_formats[0];
-
DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
 bus_format);
 
@@ -222,7 +219,8 @@ static dma_addr_t mxsfb_get_fb_paddr(struct drm_plane 
*plane)
return gem->paddr;
 }
 
-static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
+static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb,
+const u32 bus_format)
 {
struct drm_device *drm = mxsfb->crtc.dev;
struct drm_display_mode *m = >crtc.state->adjusted_mode;
@@ -247,7 +245,7 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
if (mxsfb->devdata->has_overlay)
writel(0, mxsfb->base + LCDC_AS_CTRL);
 
-   mxsfb_set_formats(mxsfb);
+   mxsfb_set_formats(mxsfb, bus_format);
 
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
@@ -345,7 +343,9 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
 struct drm_atomic_state *state)
 {
struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
+   struct drm_bridge_state *bridge_state;
struct drm_device *drm = mxsfb->drm;
+   u32 bus_format = 0;
dma_addr_t paddr;
 
pm_runtime_get_sync(drm->dev);
@@ -353,7 +353,23 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
 
drm_crtc_vblank_on(crtc);
 
-   mxsfb_crtc_mode_set_nofb(mxsfb);
+   /* If there is a bridge attached to the LCDIF, use its bus format */
+   if (mxsfb->bridge) {
+   bridge_state =
+   drm_atomic_get_new_bridge_state(state,
+   mxsfb->bridge);
+   bus_format = bridge_state->input_bus_cfg.format;
+   }
+
+   /* If there is no bridge, use bus format from connector */
+   if (!bus_format && mxsfb->connector->display_info.num_bus_formats)
+   bus_format = mxsfb->connector->display_info.bus_formats[0];
+
+   /* If all else fails, default to RGB888_1X24 */
+   if (!bus_format)
+   bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+
+   mxsfb_crtc_mode_set_nofb(mxsfb, bus_format);
 
/* Write cur_buf as well to avoid an initial corrupt frame */
paddr = mxsfb_get_fb_paddr(crtc->primary);
-- 
2.30.2



Re: [PATCH v2 0/3] Error out if 'pixclock' equals zero

2021-07-26 Thread Sam Ravnborg
Hi Zheyu,
On Mon, Jul 26, 2021 at 10:03:52AM +, Zheyu Ma wrote:
> Zheyu Ma (3):
>   video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
>   video: fbdev: kyro: Error out if 'pixclock' equals zero
>   video: fbdev: riva: Error out if 'pixclock' equals zero

Thanks for the quick respin, all patches applied to drm-misc-next.
They will show up in -next within a week or so.

Sam


Re: [PATCH 1/5] drm/vmwgfx: unbind in vmw_ttm_unpopulate

2021-07-26 Thread Christian König

Am 26.07.21 um 02:03 schrieb Dave Airlie:

[SNIP]

But you know, normal human: Only equipped with one head and two hands
and not cloneable.

I'm the same, but I'm not seeing where this problem happens at all, do
we have any backtraces or demos for this?


I've stumbled over this while working on some patches which accidentally 
broke delayed delete and caused random memory corruption and was 
wondering how that even happened in the first place.


Having stale PTEs in the GART isn't a problem unless you break other 
things. Which is also the reason why I haven't added a CC stable yet.



I split bind/unbind into the driver, but the driver should still
always be moving things to unbound states before an unpopulate is
called, is there a driver doing something unexpected here?


Possible, I was only testing with amdgpu and the GART handling is rather 
special there (which was one of the reasons why we did that in the first 
place).



at worst I'd like to see a WARN_ON put in first and a test in igt that
triggers it, because right now I'm not see that path through the
drivers/ttm that leads to unpopulated pages ending up happening while
bound.

 From 5.14-rc3 unpopulate is called from ttm_bo_pipeline_gutting in
non-ghost path and there is no unbind,
pipeline gutting is called from evict/validate, when there is no
placement suggested for the object, is this case getting hit somewhere
without the driver having previously unbound things?


Yes, that will hit absolutely. Most likely with VM page tables for 
amdgpu which uses this.



ttm_tt_destroy_common: calls unpopulate, everyone calls this directly
after unbinding
ttm_tt_swapout: calls unpopulate, we don't swapout objects from TT
directly, we should always unbind first, this used to have an assert
against that,
ttm_tt_populate: call unpopulate in failure path


unbinding was moved into the driver, so ttm_tt_swapout() won't unbind 
anything before calling unpopulate as far as I can see.



So any place I can see unpopulate getting called with a bound TT
should be a bug, and fixed, we could protect against it better but I'm
not seeing the need for this series to outright revert things back as
helping.


I'm not reverting this because it is offhand wrong, but making sure the 
GART is clear before unpopulating the TT object sounds like the much 
more natural thing to do and the state machine is something I certainly 
don't see in the backend.


Regards,
Christian.



Dave.




[PATCH 15/15] drm/i915/guc/rc: Setup and enable GUCRC feature

2021-07-26 Thread Vinay Belgaumkar
This feature hands over the control of HW RC6 to the GuC.
GuC decides when to put HW into RC6 based on it's internal
busyness algorithms.

GUCRC needs GuC submission to be enabled, and only
supported on Gen12+ for now.

When GUCRC is enabled, do not set HW RC6. Use a H2G message
to tell GuC to enable GUCRC. When disabling RC6, tell GuC to
revert RC6 control back to KMD.

v2: Address comments (Michal W)

Reviewed-by: Michal Wajdeczko 
Signed-off-by: Vinay Belgaumkar 
---
 drivers/gpu/drm/i915/Makefile |  1 +
 drivers/gpu/drm/i915/gt/intel_rc6.c   | 22 +++--
 .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |  6 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc.c|  1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc.h|  2 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c | 80 +++
 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h | 31 +++
 drivers/gpu/drm/i915/gt/uc/intel_uc.h |  2 +
 8 files changed, 140 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index d8eac4468df9..3fc17f20d88e 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \
  gt/uc/intel_guc_fw.o \
  gt/uc/intel_guc_log.o \
  gt/uc/intel_guc_log_debugfs.o \
+ gt/uc/intel_guc_rc.o \
  gt/uc/intel_guc_slpc.o \
  gt/uc/intel_guc_submission.o \
  gt/uc/intel_huc.o \
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c 
b/drivers/gpu/drm/i915/gt/intel_rc6.c
index 259d7eb4e165..299fcf10b04b 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6.c
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
@@ -98,11 +98,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60);
set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60);
 
-   /* 3a: Enable RC6 */
-   rc6->ctl_enable =
-   GEN6_RC_CTL_HW_ENABLE |
-   GEN6_RC_CTL_RC6_ENABLE |
-   GEN6_RC_CTL_EI_MODE(1);
+   /* 3a: Enable RC6
+*
+* With GUCRC, we do not enable bit 31 of RC_CTL,
+* thus allowing GuC to control RC6 entry/exit fully instead.
+* We will not set the HW ENABLE and EI bits
+*/
+   if (!intel_guc_rc_enable(>uc.guc))
+   rc6->ctl_enable = GEN6_RC_CTL_RC6_ENABLE;
+   else
+   rc6->ctl_enable =
+   GEN6_RC_CTL_HW_ENABLE |
+   GEN6_RC_CTL_RC6_ENABLE |
+   GEN6_RC_CTL_EI_MODE(1);
 
pg_enable =
GEN9_RENDER_PG_ENABLE |
@@ -513,6 +521,10 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6)
 {
struct drm_i915_private *i915 = rc6_to_i915(rc6);
struct intel_uncore *uncore = rc6_to_uncore(rc6);
+   struct intel_gt *gt = rc6_to_gt(rc6);
+
+   /* Take control of RC6 back from GuC */
+   intel_guc_rc_disable(>uc.guc);
 
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
if (GRAPHICS_VER(i915) >= 9)
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h 
b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
index ca538e5de940..8ff58aff 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
@@ -135,6 +135,7 @@ enum intel_guc_action {
INTEL_GUC_ACTION_SET_CONTEXT_PREEMPTION_TIMEOUT = 0x1007,
INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
+   INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004,
INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502,
INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503,
@@ -145,6 +146,11 @@ enum intel_guc_action {
INTEL_GUC_ACTION_LIMIT
 };
 
+enum intel_guc_rc_options {
+   INTEL_GUCRC_HOST_CONTROL,
+   INTEL_GUCRC_FIRMWARE_CONTROL,
+};
+
 enum intel_guc_preempt_options {
INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 13d162353b1a..fbfcae727d7f 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -159,6 +159,7 @@ void intel_guc_init_early(struct intel_guc *guc)
intel_guc_log_init_early(>log);
intel_guc_submission_init_early(guc);
intel_guc_slpc_init_early(>slpc);
+   intel_guc_rc_init_early(guc);
 
mutex_init(>send_mutex);
spin_lock_init(>irq_lock);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 15ad2eaee473..08919d1b35dc 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -59,6 +59,8 @@ struct 

[PATCH 14/15] drm/i915/guc/slpc: Add SLPC selftest

2021-07-26 Thread Vinay Belgaumkar
Tests that exercise the SLPC get/set frequency interfaces.

Clamp_max will set max frequency to multiple levels and check
that SLPC requests frequency lower than or equal to it.

Clamp_min will set min frequency to different levels and check
if SLPC requests are higher or equal to those levels.

v2: Address review comments (Michal W)
v3: Checkpatch() corrections

Signed-off-by: Vinay Belgaumkar 
---
 drivers/gpu/drm/i915/gt/intel_rps.c   |   1 +
 drivers/gpu/drm/i915/gt/selftest_slpc.c   | 311 ++
 drivers/gpu/drm/i915/gt/selftest_slpc.h   |  12 +
 .../drm/i915/selftests/i915_live_selftests.h  |   1 +
 4 files changed, 325 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c
 create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.h

diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c 
b/drivers/gpu/drm/i915/gt/intel_rps.c
index 48d4147165a9..6237332835fe 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -2318,4 +2318,5 @@ EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
 
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftest_rps.c"
+#include "selftest_slpc.c"
 #endif
diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c 
b/drivers/gpu/drm/i915/gt/selftest_slpc.c
new file mode 100644
index ..5018f686686f
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "selftest_slpc.h"
+
+#define NUM_STEPS 5
+#define H2G_DELAY 5
+#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 1)
+
+static int set_min_freq(struct intel_guc_slpc *slpc, u32 freq)
+{
+   int ret;
+
+   ret = intel_guc_slpc_set_min_freq(slpc, freq);
+   if (ret)
+   pr_err("Could not set min frequency to [%u]\n", freq);
+   else /* Delay to ensure h2g completes */
+   delay_for_h2g();
+
+   return ret;
+}
+
+static int set_max_freq(struct intel_guc_slpc *slpc, u32 freq)
+{
+   int ret;
+
+   ret = intel_guc_slpc_set_max_freq(slpc, freq);
+   if (ret)
+   pr_err("Could not set maximum frequency [%u]\n",
+   freq);
+   else /* Delay to ensure h2g completes */
+   delay_for_h2g();
+
+   return ret;
+}
+
+int live_slpc_clamp_min(void *arg)
+{
+   struct drm_i915_private *i915 = arg;
+   struct intel_gt *gt = >gt;
+   struct intel_guc_slpc *slpc = >uc.guc.slpc;
+   struct intel_rps *rps = >rps;
+   struct intel_engine_cs *engine;
+   enum intel_engine_id id;
+   struct igt_spinner spin;
+   u32 slpc_min_freq, slpc_max_freq;
+   int err = 0;
+
+   if (!intel_uc_uses_guc_slpc(>uc))
+   return 0;
+
+   if (igt_spinner_init(, gt))
+   return -ENOMEM;
+
+   if (intel_guc_slpc_get_max_freq(slpc, _max_freq)) {
+   pr_err("Could not get SLPC max freq\n");
+   return -EIO;
+   }
+
+   if (intel_guc_slpc_get_min_freq(slpc, _min_freq)) {
+   pr_err("Could not get SLPC min freq\n");
+   return -EIO;
+   }
+
+   if (slpc_min_freq == slpc_max_freq) {
+   pr_err("Min/Max are fused to the same value\n");
+   return -EINVAL;
+   }
+
+   intel_gt_pm_wait_for_idle(gt);
+   intel_gt_pm_get(gt);
+   for_each_engine(engine, gt, id) {
+   struct i915_request *rq;
+   u32 step, min_freq, req_freq;
+   u32 act_freq, max_act_freq;
+
+   if (!intel_engine_can_store_dword(engine))
+   continue;
+
+   /* Go from min to max in 5 steps */
+   step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS;
+   max_act_freq = slpc_min_freq;
+   for (min_freq = slpc_min_freq; min_freq < slpc_max_freq;
+   min_freq += step) {
+   err = set_min_freq(slpc, min_freq);
+   if (err)
+   break;
+
+   st_engine_heartbeat_disable(engine);
+
+   rq = igt_spinner_create_request(,
+   engine->kernel_context,
+   MI_NOOP);
+   if (IS_ERR(rq)) {
+   err = PTR_ERR(rq);
+   st_engine_heartbeat_enable(engine);
+   break;
+   }
+
+   i915_request_add(rq);
+
+   if (!igt_wait_for_spinner(, rq)) {
+   pr_err("%s: Spinner did not start\n",
+   engine->name);
+   igt_spinner_end();
+   st_engine_heartbeat_enable(engine);
+   intel_gt_set_wedged(engine->gt);
+  

  1   2   3   >