Re: [Internet]Re: [PATCH] fbcon: Out-Of-Bounds write in sys_imageblit, add range check
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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+
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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); +