Re: [PATCH v5] drm/pl111: Initial drm/kms driver for pl111
Re: [PATCH 2/2] drm: add lockdep assert to drm_is_current_master_locked
On 30/7/21 2:08 pm, Boqun Feng wrote: On Fri, Jul 30, 2021 at 12:15:15PM +0800, Desmond Cheong Zhi Xi wrote: In drm_is_current_master_locked, accessing drm_file.master should be protected by either drm_file.master_lookup_lock or drm_device.master_mutex. This was previously awkward to assert with lockdep. Following patch ("locking/lockdep: Provide lockdep_assert{,_once}() helpers"), this assertion is now convenient so we add it in. Signed-off-by: Desmond Cheong Zhi Xi --- drivers/gpu/drm/drm_auth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 9c24b8cc8e36..6f4d7ff23c80 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -63,9 +63,9 @@ static bool drm_is_current_master_locked(struct drm_file *fpriv) { - /* Either drm_device.master_mutex or drm_file.master_lookup_lock -* should be held here. -*/ + lockdep_assert_once(lockdep_is_held(&fpriv->master_lookup_lock) || + lockdep_is_held(&fpriv->minor->dev->master_mutex)); + I think it's better to also add the lockdep_assert() of & (i.e. both held) in the updater side, and have comments pointing to each other. Is it convenient to do in this patchset? If the updater side doesn't need to put the lockdep_assert() (maybe the lock acquire code and the update code are in the same function), it's still better to add some Thanks for the feedback, Boqun. Yeah, I think the updater side maybe doesn't need new lockdep_assert() because what currently happens is either lockdep_assert_held_once(&dev->master_mutex); /* 6 lines of prep */ spin_lock(&fpriv->master_lookup_lock); fpriv->master = new_value; or mutex_lock(&dev->master_mutex); /* 3 lines of checks */ spin_lock(&file_priv->master_lookup_lock); file_priv->master = new_value; comments like: /* * To update drm_file.master, both drm_file.master_lookup_lock * and drm_device.master_mutex are needed, therefore holding * either of them is safe and enough for the read side. */ Just feel it's better to explain the lock design either in the lockdep_assert() or comments. But clarifying the lock design in the documentation sounds like a really good idea. Probably a good place for this would be in the kerneldoc where we also explain the lifetime rules and usage of the pointer outside drm_auth.c: diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 726cfe0ff5f5..a3acb7ac3550 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -233,6 +233,10 @@ struct drm_file { * this only matches &drm_device.master if the master is the currently * active one. * +* To update @master, both &drm_device.master_mutex and +* @master_lookup_lock need to be held, therefore holding either of +* them is safe and enough for the read side. +* * When dereferencing this pointer, either hold struct * &drm_device.master_mutex for the duration of the pointer's use, or * use drm_file_get_master() if struct &drm_device.master_mutex is not Best wishes, Desmond Regards, Boqun return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; } -- 2.25.1
Re: [PATCH 03/14] drm/atmel-hlcdc: Convert to Linux IRQ interfaces
Hi Dan and Sam Am 29.07.21 um 21:55 schrieb dan.sned...@microchip.com: Hi Thomas and Sam, On 7/29/21 12:48 PM, Sam Ravnborg wrote: EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe Hi Thomas, Are you sure, you're testing with the latest drm-misc-next or drm-tip? Because using irq_enabled is deprecated and the flag was recently replaced by commit 1e4cd78ed493 ("drm: Don't test for IRQ support in VBLANK ioctls"). Ok, My fault for testing on the wrong branch. When I test this patch on drm-misc-next it works great. Sorry for the confusion! I was looking at drm-misc-fixes which did not have this commit :-( Just my silly excuse why I was convinced this was the issue. Don't worry. I'll add Sam's R-b and a Tested-by from Dan to the patch. Is that ok? Best regards Thomas Sam Best regards, Dan -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer OpenPGP_signature Description: OpenPGP digital signature
Re: [PATCH 01/64] media: omap3isp: Extract struct group for memcpy() region
On Thu, Jul 29, 2021 at 11:00:48PM -0700, Kees Cook wrote: > On Thu, Jul 29, 2021 at 11:20:39AM +0300, Dan Carpenter wrote: > > On Thu, Jul 29, 2021 at 07:56:27AM +0200, Greg Kroah-Hartman wrote: > > > On Wed, Jul 28, 2021 at 11:37:30PM +0200, David Sterba wrote: > > > > On Wed, Jul 28, 2021 at 02:37:20PM -0700, Bart Van Assche wrote: > > > > > On 7/28/21 2:14 AM, Dan Carpenter wrote: > > > > > > On Wed, Jul 28, 2021 at 10:59:22AM +0200, David Sterba wrote: > > > > > >>> drivers/media/platform/omap3isp/ispstat.c | 5 +-- > > > > > >>> include/uapi/linux/omap3isp.h | 44 > > > > > >>> +-- > > > > > >>> 2 files changed, 36 insertions(+), 13 deletions(-) > > > > > >>> > > > > > >>> diff --git a/drivers/media/platform/omap3isp/ispstat.c > > > > > >>> b/drivers/media/platform/omap3isp/ispstat.c > > > > > >>> index 5b9b57f4d9bf..ea8222fed38e 100644 > > > > > >>> --- a/drivers/media/platform/omap3isp/ispstat.c > > > > > >>> +++ b/drivers/media/platform/omap3isp/ispstat.c > > > > > >>> @@ -512,7 +512,7 @@ int omap3isp_stat_request_statistics(struct > > > > > >>> ispstat *stat, > > > > > >>> int omap3isp_stat_request_statistics_time32(struct ispstat > > > > > >>> *stat, > > > > > >>> struct > > > > > >>> omap3isp_stat_data_time32 *data) > > > > > >>> { > > > > > >>> - struct omap3isp_stat_data data64; > > > > > >>> + struct omap3isp_stat_data data64 = { }; > > > > > >> > > > > > >> Should this be { 0 } ? > > > > > >> > > > > > >> We've seen patches trying to switch from { 0 } to { } but the > > > > > >> answer > > > > > >> was that { 0 } is supposed to be used, > > > > > >> http://www.ex-parrot.com/~chris/random/initialise.html > > > > > >> > > > > > >> (from > > > > > >> https://lore.kernel.org/lkml/fbddb15a-6e46-3f21-23ba-b18f66e34...@suse.com/ > > > > > >> ) > > > > > > > > > > > > In the kernel we don't care about portability so much. Use the = { > > > > > > } > > > > > > GCC extension. If the first member of the struct is a pointer then > > > > > > Sparse will complain about = { 0 }. > > > > > > > > > > +1 for { }. > > > > > > > > Oh, I thought the tendency is is to use { 0 } because that can also > > > > intialize the compound members, by a "scalar 0" as it appears in the > > > > code. > > > > > > > > > > Holes in the structure might not be initialized to anything if you do > > > either one of these as well. > > > > > > Or did we finally prove that is not the case? I can not remember > > > anymore... > > > > Yep. The C11 spec says that struct holes are initialized. > > > > https://lore.kernel.org/netdev/20200731140452.ge24...@ziepe.ca/ > > This is, unfortunately, misleading. The frustrating key word is > "partial" in "updated in C11 to require zero'ing padding when doing > partial initialization of aggregates". If one initializes _all_ the > struct members ... the padding doesn't get initialized. :( (And until > recently, _trailing_ padding wasn't getting initialized even when other > paddings were.) > > I've tried to collect all the different ways the compiler might initialize > a variable in this test: > https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/tree/lib/test_stackinit.c?h=for-next/kspp > > FWIW, there's no difference between -std=gnu99 and -std=c11, and the > test shows that padding is _not_ universally initialized (unless your > compiler supports -ftrivial-auto-var-init=zero, which Clang does, and > GCC will shortly[1]). Running this with GCC 10.3.0, I see this... > > As expected, having no initializer leaves padding (as well as members) > uninitialized: > > stackinit: small_hole_none FAIL (uninit bytes: 24) > stackinit: big_hole_none FAIL (uninit bytes: 128) > stackinit: trailing_hole_none FAIL (uninit bytes: 32) > > Here, "zero" means "= { };" and they get padding initialized: > > stackinit: small_hole_zero ok > stackinit: big_hole_zero ok > stackinit: trailing_hole_zero ok > > Here, "static_partial" means "= { .one_member = 0 };", and > "dynamic_partial" means "= { .one_member = some_variable };". These are > similarly initialized: > > stackinit: small_hole_static_partial ok > stackinit: big_hole_static_partial ok > stackinit: trailing_hole_static_partial ok > > stackinit: small_hole_dynamic_partial ok > stackinit: big_hole_dynamic_partial ok > stackinit: trailing_hole_dynamic_partial ok > > But when _all_ members are initialized, the padding is _not_: > > stackinit: small_hole_static_all FAIL (uninit bytes: 3) > stackinit: big_hole_static_all FAIL (uninit bytes: 124) > stackinit: trailing_hole_static_all FAIL (uninit bytes: 7) > > stackinit: small_hole_dynamic_all FAIL (uninit bytes: 3) > stackinit: big_hole_dynamic_all FAIL (uninit bytes: 124) > stackinit: trailing_hole_dynamic_all FAIL (uninit bytes: 7) > > As expected, assigning to members outside of initialization leaves > padding uninitialized: > > stackinit: small_hole_runtime_partial FAIL (uninit bytes:
Re: [PATCH 01/64] media: omap3isp: Extract struct group for memcpy() region
On Fri, Jul 30, 2021 at 10:38:45AM +0200, David Sterba wrote: > Then is explicit memset the only reliable way accross all compiler > flavors and supported versions? > The = { } initializer works. It's only when you start partially initializing the struct that it doesn't initialize holes. regards, dan carpenter
Re: [PATCH 2/7] drm/sti: Use correct printk format specifiers for size_t
On 7/28/21 5:37 PM, Laurent Pinchart wrote: The correct format specifier for size_t is %zu. Using %d (or %u) generates a warning on 64-bit platforms. Fix it. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/sti/sti_hqvdp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index d09b08995b12..3c61ba8b43e0 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -927,12 +927,12 @@ static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp) header = (struct fw_header *)firmware->data; if (firmware->size < sizeof(*header)) { - DRM_ERROR("Invalid firmware size (%d)\n", firmware->size); + DRM_ERROR("Invalid firmware size (%zu)\n", firmware->size); goto out; } if ((sizeof(*header) + header->rd_size + header->wr_size + header->pmem_size + header->dmem_size) != firmware->size) { - DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n", + DRM_ERROR("Invalid fmw structure (%zu+%d+%d+%d+%d != %zu)\n", Hi Laurent, Looping Benjamin (new email address) and Alain (future maintainer of drm/sti). Reviewed-by: Philippe Cornu Many thanks for your patch, Philippe :-) sizeof(*header), header->rd_size, header->wr_size, header->pmem_size, header->dmem_size, firmware->size);
Re: [PATCH 5/7] drm/sti: Enable COMPILE_TEST on all ARM and ARM64 platforms
On 7/28/21 5:37 PM, Laurent Pinchart wrote: To extend test coverage, relax the dependency on ARCH_STI or ARCH_MULTIPLATFORM to also enable compilation on ARM or ARM4 when Hi Laurent, Looping Benjamin (new email address) and Alain (future maintainer of drm/sti). minor typo (ARM4 -> ARM64) Reviewed-by: Philippe Cornu Many thanks for your patch, Philippe :-) COMPILE_TEST is selected. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/sti/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig index d0cfdd36b38f..e7d18893bc11 100644 --- a/drivers/gpu/drm/sti/Kconfig +++ b/drivers/gpu/drm/sti/Kconfig @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_STI tristate "DRM Support for STMicroelectronics SoC stiH4xx Series" - depends on OF && DRM && (ARCH_STI || ARCH_MULTIPLATFORM) + depends on OF && DRM + depends on ARCH_STI || ARCH_MULTIPLATFORM || ((ARM || ARM64) && COMPILE_TEST) select RESET_CONTROLLER select DRM_KMS_HELPER select DRM_GEM_CMA_HELPER
Re: [PATCH] drm:This patch fixes the checkpatch.pl error to msm_drv.c
On Fri, 30 Jul 2021 at 09:13, zhaoxiao wrote: > > ERROR: do not initialise statics to false > > Signed-off-by: zhaoxiao Could you please resend this patch following the style of the rest of patches being submitted to this area? Subject, more detailed patch description, etc. > --- > drivers/gpu/drm/msm/msm_drv.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c > index 9b8fa2ad0d84..d9ca4bc9620b 100644 > --- a/drivers/gpu/drm/msm/msm_drv.c > +++ b/drivers/gpu/drm/msm/msm_drv.c > @@ -59,7 +59,7 @@ static const struct drm_mode_config_helper_funcs > mode_config_helper_funcs = { > }; > > #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING > -static bool reglog = false; > +static bool reglog; > MODULE_PARM_DESC(reglog, "Enable register read/write logging"); > module_param(reglog, bool, 0600); > #else > @@ -76,7 +76,7 @@ static char *vram = "16m"; > MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without > IOMMU/GPUMMU)"); > module_param(vram, charp, 0); > > -bool dumpstate = false; > +bool dumpstate; > MODULE_PARM_DESC(dumpstate, "Dump KMS state on errors"); > module_param(dumpstate, bool, 0600); > > -- > 2.20.1 > > > -- With best wishes Dmitry
Re: [PATCH 2/2] drm: add lockdep assert to drm_is_current_master_locked
On Fri, Jul 30, 2021 at 04:06:44PM +0800, Desmond Cheong Zhi Xi wrote: > On 30/7/21 2:08 pm, Boqun Feng wrote: > > On Fri, Jul 30, 2021 at 12:15:15PM +0800, Desmond Cheong Zhi Xi wrote: > > > In drm_is_current_master_locked, accessing drm_file.master should be > > > protected by either drm_file.master_lookup_lock or > > > drm_device.master_mutex. This was previously awkward to assert with > > > lockdep. > > > > > > Following patch ("locking/lockdep: Provide lockdep_assert{,_once}() > > > helpers"), this assertion is now convenient so we add it in. > > > > > > Signed-off-by: Desmond Cheong Zhi Xi > > > --- > > > drivers/gpu/drm/drm_auth.c | 6 +++--- > > > 1 file changed, 3 insertions(+), 3 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c > > > index 9c24b8cc8e36..6f4d7ff23c80 100644 > > > --- a/drivers/gpu/drm/drm_auth.c > > > +++ b/drivers/gpu/drm/drm_auth.c > > > @@ -63,9 +63,9 @@ > > > static bool drm_is_current_master_locked(struct drm_file *fpriv) > > > { > > > - /* Either drm_device.master_mutex or drm_file.master_lookup_lock > > > - * should be held here. > > > - */ > > > + lockdep_assert_once(lockdep_is_held(&fpriv->master_lookup_lock) || > > > + lockdep_is_held(&fpriv->minor->dev->master_mutex)); > > > + > > > > I think it's better to also add the lockdep_assert() of & (i.e. both > > held) in the updater side, and have comments pointing to each other. > > > > Is it convenient to do in this patchset? If the updater side doesn't > > need to put the lockdep_assert() (maybe the lock acquire code and the > > update code are in the same function), it's still better to add some > > Thanks for the feedback, Boqun. > > Yeah, I think the updater side maybe doesn't need new lockdep_assert() > because what currently happens is either > > lockdep_assert_held_once(&dev->master_mutex); > /* 6 lines of prep */ > spin_lock(&fpriv->master_lookup_lock); > fpriv->master = new_value; > or > mutex_lock(&dev->master_mutex); > /* 3 lines of checks */ > spin_lock(&file_priv->master_lookup_lock); > file_priv->master = new_value; > > > comments like: > > > > /* > > * To update drm_file.master, both drm_file.master_lookup_lock > > * and drm_device.master_mutex are needed, therefore holding > > * either of them is safe and enough for the read side. > > */ > > > > Just feel it's better to explain the lock design either in the > > lockdep_assert() or comments. > > > > But clarifying the lock design in the documentation sounds like a really > good idea. > > Probably a good place for this would be in the kerneldoc where we also > explain the lifetime rules and usage of the pointer outside drm_auth.c: > > diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h > index 726cfe0ff5f5..a3acb7ac3550 100644 > --- a/include/drm/drm_file.h > +++ b/include/drm/drm_file.h > @@ -233,6 +233,10 @@ struct drm_file { >* this only matches &drm_device.master if the master is the currently >* active one. >* > + * To update @master, both &drm_device.master_mutex and > + * @master_lookup_lock need to be held, therefore holding either of > + * them is safe and enough for the read side. > + * >* When dereferencing this pointer, either hold struct >* &drm_device.master_mutex for the duration of the pointer's use, or >* use drm_file_get_master() if struct &drm_device.master_mutex is not Works for me ;-) For the whole series, feel free to add: Acked-by: Boqun Feng Regards, Boqun > > Best wishes, > Desmond > > > Regards, > > Boqun > > > > > return fpriv->is_master && drm_lease_owner(fpriv->master) == > > > fpriv->minor->dev->master; > > > } > > > -- > > > 2.25.1 > > > >
Re: [Intel-gfx] [PATCH 1/1] drm/i915: Check if engine has heartbeat when closing a context
On 30/07/2021 01:13, John Harrison wrote: On 7/28/2021 17:34, Matthew Brost wrote: If an engine associated with a context does not have a heartbeat, ban it immediately. This is needed for GuC submission as a idle pulse doesn't kick the context off the hardware where it then can check for a heartbeat and ban the context. Pulse, that is a request with I915_PRIORITY_BARRIER, does not preempt a running normal priority context? Why does it matter then whether or not heartbeats are enabled - when heartbeat just ends up sending the same engine pulse (eventually, with raising priority)? It's worse than this. If the engine in question is an individual physical engine then sending a pulse (with sufficiently high priority) will pre-empt the engine and kick the context off. However, the GuC Why it is different for physical vs virtual, aren't both just schedulable contexts with different engine masks for what GuC is concerned? Oh, is it a matter of needing to send pulses to all engines which comprise a virtual one? scheduler does not have hacks in it to check the state of the heartbeat or whether a context is actually a zombie or not. Thus, the context will get resubmitted to the hardware after the pulse completes and effectively nothing will have happened. I would assume that the DRM scheduler which we are meant to be switching to for execlist as well as GuC submission is also unlikely to have hacks for zombie contexts and tests for whether the i915 specific heartbeat has been disabled since the context became a zombie. So when that switch happens, this test will also fail in execlist mode as well as GuC mode. The choices I see here are to simply remove persistence completely (it is a basically a bug that became UAPI because it wasn't caught soon enough!) or to implement it in a way that does not require hacks in the back end scheduler. Apparently, the DRM scheduler is expected to allow zombie contexts to persist until the DRM file handle is closed. So presumably we will have to go with option two. That means flagging a context as being a zombie when it is closed but still active. The driver would then add it to a zombie list owned by the DRM client object. When that client object is closed, i915 would go through the list and genuinely kill all the contexts. No back end scheduler hacks required and no intimate knowledge of the i915 heartbeat mechanism required either. John. This patch also updates intel_engine_has_heartbeat to be a vfunc as we now need to call this function on execlists virtual engines too. Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 +++-- drivers/gpu/drm/i915/gt/intel_context_types.h | 2 ++ drivers/gpu/drm/i915/gt/intel_engine.h | 21 ++- .../drm/i915/gt/intel_execlists_submission.c | 14 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 2 -- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 9c3672bac0e2..b8e01c5ba9e5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1090,8 +1090,9 @@ static void kill_engines(struct i915_gem_engines *engines, bool ban) */ for_each_gem_engine(ce, engines, it) { struct intel_engine_cs *engine; + bool local_ban = ban || !intel_engine_has_heartbeat(ce->engine); In any case (pending me understanding what's really going on there), why would this check not be in kill_context with currently does this: bool ban = (!i915_gem_context_is_persistent(ctx) || !ctx->i915->params.enable_hangcheck); ... kill_engines(pos, ban); So whether to ban decision would be consolidated to one place. In fact, decision on whether to allow persistent is tied to enable_hangcheck, which also drives hearbeat emission. So perhaps one part of the correct fix is to extend the above (kill_context) ban criteria to include hearbeat values anyway. Otherwise isn't it a simple miss that this check fails to account to hearbeat disablement via sysfs? Regards, Tvrtko - if (ban && intel_context_ban(ce, NULL)) + if (local_ban && intel_context_ban(ce, NULL)) continue; /* @@ -1104,7 +1105,7 @@ static void kill_engines(struct i915_gem_engines *engines, bool ban) engine = active_engine(ce); /* First attempt to gracefully cancel the context */ - if (engine && !__cancel_engine(engine) && ban) + if (engine && !__cancel_engine(engine) && local_ban) /* * If we are unable to send a preemptive pulse to bump * the context from the GPU, we have to resort to a full diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/int
[PATCH] drm: Fix oops in damage self-tests by mocking damage property
I've added a new check to make sure that drivers which insepct the damage property have it set up correctly, but somehow missed that this borke the damage selftest in the CI result noise. Fix it up by mocking enough of drm_device and drm_plane so we can call drm_plane_enable_fb_damage_clips() to make the new check happy. Since there's a lot of duplicated mock code already copy-pasted into each test I've also refactored this a bit to trim it down. Signed-off-by: Daniel Vetter Fixes: c7fcbf251397 ("drm/plane: check that fb_damage is set up when used") Cc: José Roberto de Souza (v1) Cc: Ville Syrjälä Cc: Gwan-gyeong Mun Cc: José Roberto de Souza Cc: Hans de Goede Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann --- .../drm/selftests/test-drm_damage_helper.c| 287 +- 1 file changed, 71 insertions(+), 216 deletions(-) diff --git a/drivers/gpu/drm/selftests/test-drm_damage_helper.c b/drivers/gpu/drm/selftests/test-drm_damage_helper.c index 9d2bcdf8bc29..1b585c13e042 100644 --- a/drivers/gpu/drm/selftests/test-drm_damage_helper.c +++ b/drivers/gpu/drm/selftests/test-drm_damage_helper.c @@ -6,9 +6,37 @@ #define pr_fmt(fmt) "drm_damage_helper: " fmt #include +#include +#include #include "test-drm_modeset_common.h" +struct drm_driver mock_driver; +struct drm_device mock_device; +struct drm_object_properties mock_obj_props; +struct drm_plane mock_plane; +struct drm_property mock_prop; + +static void mock_setup(struct drm_plane_state *state) +{ + static bool setup_done = false; + + state->plane = &mock_plane; + + if (setup_done) + return; + + /* just enough so that drm_plane_enable_fb_damage_clips() works */ + mock_device.driver = &mock_driver; + mock_device.mode_config.prop_fb_damage_clips = &mock_prop; + mock_plane.dev = &mock_device; + mock_plane.base.properties = &mock_obj_props; + mock_prop.base.id = 1; /* 0 is an invalid id */ + mock_prop.dev = &mock_device; + + drm_plane_enable_fb_damage_clips(&mock_plane); +} + static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2, int y2) { @@ -70,23 +98,29 @@ static bool check_damage_clip(struct drm_plane_state *state, struct drm_rect *r, return true; } +const struct drm_framebuffer fb = { + .width = 2048, + .height = 2048 +}; + +/* common mocked structs many tests need */ +#define MOCK_VARIABLES() \ + struct drm_plane_state old_state; \ + struct drm_plane_state state = { \ + .crtc = ZERO_SIZE_PTR, \ + .fb = (struct drm_framebuffer *) &fb, \ + .visible = true, \ + }; \ + mock_setup(&old_state); \ + mock_setup(&state); + int igt_damage_iter_no_damage(void *ignored) { struct drm_atomic_helper_damage_iter iter; - struct drm_plane_state old_state; struct drm_rect clip; uint32_t num_hits = 0; - struct drm_framebuffer fb = { - .width = 2048, - .height = 2048 - }; - - struct drm_plane_state state = { - .crtc = ZERO_SIZE_PTR, - .fb = &fb, - .visible = true, - }; + MOCK_VARIABLES(); /* Plane src same as fb size. */ set_plane_src(&old_state, 0, 0, fb.width << 16, fb.height << 16); @@ -104,20 +138,10 @@ int igt_damage_iter_no_damage(void *ignored) int igt_damage_iter_no_damage_fractional_src(void *ignored) { struct drm_atomic_helper_damage_iter iter; - struct drm_plane_state old_state; struct drm_rect clip; uint32_t num_hits = 0; - struct drm_framebuffer fb = { - .width = 2048, - .height = 2048 - }; - - struct drm_plane_state state = { - .crtc = ZERO_SIZE_PTR, - .fb = &fb, - .visible = true, - }; + MOCK_VARIABLES(); /* Plane src has fractional part. */ set_plane_src(&old_state, 0x3fffe, 0x3fffe, @@ -137,20 +161,10 @@ int igt_damage_iter_no_damage_fractional_src(void *ignored) int igt_damage_iter_no_damage_src_moved(void *ignored) { struct drm_atomic_helper_damage_iter iter; - struct drm_plane_state old_state; struct drm_rect clip; uint32_t num_hits = 0; - struct drm_framebuffer fb = { - .width = 2048, - .height = 2048 - }; - - struct drm_plane_state state = { - .crtc = ZERO_SIZE_PTR, - .fb = &fb, - .visible = true, - }; + MOCK_VARIABLES(); /* Plane src moved since old plane state. */ set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); @@ -169,20 +183,10 @@ int igt_damage_iter_no_damage_src_moved(void *ignored) int igt_damage_iter_no_damage_fractional_src_moved(void *ignored) { struct drm_atomic_helper_damage_iter iter;
Re: [PATCH] drm: Fix typo in comments
On Thu, Jul 29, 2021 at 08:20:37PM +0800, Cai Huoqing wrote: > fix typo for drm > > Signed-off-by: Cai Huoqing > --- > drivers/gpu/drm/drm_aperture.c | 2 +- > drivers/gpu/drm/drm_atomic.c| 2 +- > drivers/gpu/drm/drm_atomic_helper.c | 10 +- > drivers/gpu/drm/drm_atomic_uapi.c | 6 +++--- > drivers/gpu/drm/drm_auth.c | 2 +- > drivers/gpu/drm/drm_bridge.c| 2 +- > drivers/gpu/drm/drm_bufs.c | 2 +- > drivers/gpu/drm/drm_cache.c | 2 +- > drivers/gpu/drm/drm_damage_helper.c | 2 +- > drivers/gpu/drm/drm_dp_helper.c | 8 > drivers/gpu/drm/drm_drv.c | 4 ++-- > drivers/gpu/drm/drm_dsc.c | 2 +- > drivers/gpu/drm/drm_edid.c | 4 ++-- > drivers/gpu/drm/drm_fb_helper.c | 2 +- > drivers/gpu/drm/drm_file.c | 6 +++--- > drivers/gpu/drm/drm_format_helper.c | 2 +- > drivers/gpu/drm/drm_framebuffer.c | 2 +- > drivers/gpu/drm/drm_gem.c | 4 ++-- > drivers/gpu/drm/drm_gem_atomic_helper.c | 4 ++-- > drivers/gpu/drm/drm_gem_shmem_helper.c | 2 +- > drivers/gpu/drm/drm_gem_vram_helper.c | 2 +- > drivers/gpu/drm/drm_hdcp.c | 2 +- > drivers/gpu/drm/drm_ioctl.c | 4 ++-- > drivers/gpu/drm/drm_irq.c | 2 +- > drivers/gpu/drm/drm_mm.c| 2 +- > drivers/gpu/drm/drm_mode_object.c | 2 +- > drivers/gpu/drm/drm_modes.c | 4 ++-- > drivers/gpu/drm/drm_plane.c | 2 +- > drivers/gpu/drm/drm_plane_helper.c | 2 +- > drivers/gpu/drm/drm_prime.c | 2 +- > drivers/gpu/drm/drm_probe_helper.c | 2 +- > drivers/gpu/drm/drm_property.c | 2 +- > drivers/gpu/drm/drm_scdc_helper.c | 2 +- > drivers/gpu/drm/drm_syncobj.c | 2 +- > drivers/gpu/drm/drm_vblank.c| 12 ++-- > drivers/gpu/drm/drm_vma_manager.c | 2 +- > 36 files changed, 58 insertions(+), 58 deletions(-) > > diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c > index 9ac39cf11694..74bd4a76b253 100644 > --- a/drivers/gpu/drm/drm_aperture.c > +++ b/drivers/gpu/drm/drm_aperture.c > @@ -78,7 +78,7 @@ > * > * Drivers that are susceptible to being removed by other drivers, such as > * generic EFI or VESA drivers, have to register themselves as owners of > their > - * given framebuffer memory. Ownership of the framebuffer memory is achived > + * given framebuffer memory. Ownership of the framebuffer memory is achieved > * by calling devm_aperture_acquire_from_firmware(). On success, the driver > * is the owner of the framebuffer range. The function fails if the > * framebuffer is already by another driver. See below for an example. > diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c > index d820423fac32..b127e30082ba 100644 > --- a/drivers/gpu/drm/drm_atomic.c > +++ b/drivers/gpu/drm/drm_atomic.c > @@ -723,7 +723,7 @@ static void drm_atomic_plane_print_state(struct > drm_printer *p, > * clocks, scaler units, bandwidth and fifo limits shared among a group of > * planes or CRTCs, and so on) it makes sense to model these as independent > * objects. Drivers then need to do similar state tracking and commit > ordering for > - * such private (since not exposed to userpace) objects as the atomic core > and > + * such private (since not exposed to userspace) objects as the atomic core > and > * helpers already provide for connectors, planes and CRTCs. > * > * To make this easier on drivers the atomic core provides some support to > track > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > b/drivers/gpu/drm/drm_atomic_helper.c > index f7bf1ea62d58..7ee480b6efde 100644 > --- a/drivers/gpu/drm/drm_atomic_helper.c > +++ b/drivers/gpu/drm/drm_atomic_helper.c > @@ -634,7 +634,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, >* connectors and a NULL mode. >* >* The other way around is true as well. enable != 0 > - * iff connectors are attached and a mode is set. > + * if connectors are attached and a mode is set. I think replacing the if with "implies that" is clearer. The other typo fixes look all good to me (but there's a lot and I kinda got blurry-eyed, thanks for doing this). Can you pls respin with that one change? -Daniel >*/ > new_crtc_state->mode_changed = true; > new_crtc_state->connectors_changed = true; > @@ -1686,7 +1686,7 @@ static void commit_work(struct work_struct *work) > } > > /** > - * drm_atomic_helper_async_check - check if state can be commited > asynchronously > + * drm_atomic_helper_async_check - check if state can be committed > asynchronously > * @dev: DRM device > * @state: the driver state object > * >
Re: [RFC v1 0/4] drm: Add support for DRM_CAP_DEFERRED_OUT_FENCE capability
On Thu, Jul 29, 2021 at 01:16:55AM -0700, Vivek Kasireddy wrote: > By separating the OUT_FENCE signalling from pageflip completion allows > a Guest compositor to start a new repaint cycle with a new buffer > instead of waiting for the old buffer to be free. > > This work is based on the idea/suggestion from Simon and Pekka. > > This capability can be a solution for this issue: > https://gitlab.freedesktop.org/wayland/weston/-/issues/514 > > Corresponding Weston MR: > https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/668 Uh I kinda wanted to discuss this a bit more before we jump into typing code, but well I guess not that much work yet. So maybe I'm not understanding the problem, but I think the fundamental underlying issue is that with KMS you can have at most 2 buffers in-flight, due to our queue depth limit of 1 pending flip. Unfortunately that means for virtual hw where it takes a few more steps/vblanks until the framebuffer actually shows up on screen and is scanned out, we suffer deeply. The usual fix for that is to drop the latency and increase throughput, and have more buffers in-flight. Which this patch tries to do. Now I think where we go wrong here is that we're trying to hack this up by defining different semantics for the out-fence and for the drm-event. Imo that's wrong, they're both meant to show eactly the same thing: - when is the new frame actually visible to the user (as in, eyeballs in a human head, preferrably, not the time when we've handed the buffer off to the virtual hw) - when is the previous buffer no longer being used by the scanout hw We do cheat a bit right now in so far that we assume they're both the same, as in, panel-side latency is currently the compositor's problem to figure out. So for virtual hw I think the timestamp and even completion really need to happen only when the buffer has been pushed through the entire virtualization chain, i.e. ideally we get the timestamp from the kms driver from the host side. Currently that's not done, so this is most likely quite broken already (virtio relies on the no-vblank auto event sending, which definitely doesn't wait for anything, or I'm completely missing something). I think instead of hacking up some ill-defined 1.5 queue depth support, what we should do is support queue depth > 1 properly. So: - Change atomic to support queue depth > 1, this needs to be a per-driver thing due to a bunch of issues in driver code. Essentially drivers must never look at obj->state pointers, and only ever look up state through the passed-in drm_atomic_state * update container. - Aside: virtio should loose all it's empty hooks, there's no point in that. - We fix virtio to send out the completion event at the end of this entire pipeline, i.e. virtio code needs to take care of sending out the crtc_state->event correctly. - We probably also want some kind of (maybe per-crtc) recommended queue depth property so compositors know how many buffers to keep in flight. Not sure about that. It's a bit more work, but also a lot less hacking around infrastructure in dubious ways. Thoughts? Cheers, Daniel > > Cc: Daniel Vetter > Cc: Gerd Hoffmann > Cc: Pekka Paalanen > Cc: Simon Ser > Cc: Michel Dänzer > Cc: Tina Zhang > Cc: Dongwon Kim > > Vivek Kasireddy (4): > drm: Add a capability flag to support deferred out_fence signalling > virtio-gpu uapi: Add VIRTIO_GPU_F_OUT_FENCE feature > drm/virtio: Add VIRTIO_GPU_CMD_RESOURCE_OUT_FENCE cmd > drm/virtio: Probe and implement VIRTIO_GPU_F_OUT_FENCE feature > > drivers/gpu/drm/drm_file.c | 11 +++--- > drivers/gpu/drm/drm_ioctl.c | 3 ++ > drivers/gpu/drm/virtio/virtgpu_debugfs.c | 1 + > drivers/gpu/drm/virtio/virtgpu_drv.c | 1 + > drivers/gpu/drm/virtio/virtgpu_drv.h | 6 > drivers/gpu/drm/virtio/virtgpu_fence.c | 9 + > drivers/gpu/drm/virtio/virtgpu_kms.c | 10 -- > drivers/gpu/drm/virtio/virtgpu_plane.c | 44 +++- > drivers/gpu/drm/virtio/virtgpu_vq.c | 17 + > include/drm/drm_mode_config.h| 9 + > include/uapi/drm/drm.h | 1 + > include/uapi/linux/virtio_gpu.h | 12 +++ > 12 files changed, 117 insertions(+), 7 deletions(-) > > -- > 2.30.2 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
[PATCH] drm/vc4: hdmi: make vc4_hdmi_codec_pdata static
This symbol is not used outside of vc4_hdmi.c, so marks it static. Fix the following sparse warning: drivers/gpu/drm/vc4/vc4_hdmi.c:1479:25: warning: symbol 'vc4_hdmi_codec_pdata' was not declared. Should it be static? Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong --- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index b20530c..ca08b64 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1476,7 +1476,7 @@ static int vc4_hdmi_audio_get_eld(struct device *dev, void *data, .audio_startup = vc4_hdmi_audio_startup, }; -struct hdmi_codec_pdata vc4_hdmi_codec_pdata = { +static struct hdmi_codec_pdata vc4_hdmi_codec_pdata = { .ops = &vc4_hdmi_codec_ops, .max_i2s_channels = 8, .i2s = 1, -- 1.8.3.1
Re: [PATCH 48/64] drbd: Use struct_group() to zero algs
On Thu, Jul 29, 2021 at 07:57:47PM -0700, Bart Van Assche wrote: > On 7/29/21 7:31 PM, Kees Cook wrote: > > On Wed, Jul 28, 2021 at 02:45:55PM -0700, Bart Van Assche wrote: > >> On 7/27/21 1:58 PM, Kees Cook wrote: > >>> In preparation for FORTIFY_SOURCE performing compile-time and run-time > >>> field bounds checking for memset(), avoid intentionally writing across > >>> neighboring fields. > >>> > >>> Add a struct_group() for the algs so that memset() can correctly reason > >>> about the size. > >>> > >>> Signed-off-by: Kees Cook > >>> --- > >>> drivers/block/drbd/drbd_main.c | 3 ++- > >>> drivers/block/drbd/drbd_protocol.h | 6 -- > >>> drivers/block/drbd/drbd_receiver.c | 3 ++- > >>> 3 files changed, 8 insertions(+), 4 deletions(-) > >>> > >>> diff --git a/drivers/block/drbd/drbd_main.c > >>> b/drivers/block/drbd/drbd_main.c > >>> index 55234a558e98..b824679cfcb2 100644 > >>> --- a/drivers/block/drbd/drbd_main.c > >>> +++ b/drivers/block/drbd/drbd_main.c > >>> @@ -729,7 +729,8 @@ int drbd_send_sync_param(struct drbd_peer_device > >>> *peer_device) > >>> cmd = apv >= 89 ? P_SYNC_PARAM89 : P_SYNC_PARAM; > >>> /* initialize verify_alg and csums_alg */ > >>> - memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX); > >>> + BUILD_BUG_ON(sizeof(p->algs) != 2 * SHARED_SECRET_MAX); > >>> + memset(&p->algs, 0, sizeof(p->algs)); > >>> if (get_ldev(peer_device->device)) { > >>> dc = > >>> rcu_dereference(peer_device->device->ldev->disk_conf); > >>> diff --git a/drivers/block/drbd/drbd_protocol.h > >>> b/drivers/block/drbd/drbd_protocol.h > >>> index dea59c92ecc1..a882b65ab5d2 100644 > >>> --- a/drivers/block/drbd/drbd_protocol.h > >>> +++ b/drivers/block/drbd/drbd_protocol.h > >>> @@ -283,8 +283,10 @@ struct p_rs_param_89 { > >>> struct p_rs_param_95 { > >>> u32 resync_rate; > >>> - char verify_alg[SHARED_SECRET_MAX]; > >>> - char csums_alg[SHARED_SECRET_MAX]; > >>> + struct_group(algs, > >>> + char verify_alg[SHARED_SECRET_MAX]; > >>> + char csums_alg[SHARED_SECRET_MAX]; > >>> + ); > >>> u32 c_plan_ahead; > >>> u32 c_delay_target; > >>> u32 c_fill_target; > >>> diff --git a/drivers/block/drbd/drbd_receiver.c > >>> b/drivers/block/drbd/drbd_receiver.c > >>> index 1f740e42e457..6df2539e215b 100644 > >>> --- a/drivers/block/drbd/drbd_receiver.c > >>> +++ b/drivers/block/drbd/drbd_receiver.c > >>> @@ -3921,7 +3921,8 @@ static int receive_SyncParam(struct drbd_connection > >>> *connection, struct packet_i > >>> /* initialize verify_alg and csums_alg */ > >>> p = pi->data; > >>> - memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX); > >>> + BUILD_BUG_ON(sizeof(p->algs) != 2 * SHARED_SECRET_MAX); > >>> + memset(&p->algs, 0, sizeof(p->algs)); > >> > >> Using struct_group() introduces complexity. Has it been considered not to > >> modify struct p_rs_param_95 and instead to use two memset() calls instead > >> of > >> one (one memset() call per member)? > > > > I went this direction because using two memset()s (or memcpy()s in other > > patches) changes the machine code. It's not much of a change, but it > > seems easier to justify "no binary changes" via the use of struct_group(). > > > > If splitting the memset() is preferred, I can totally do that instead. > > :) > > I don't have a strong opinion about this. Lars, do you want to comment > on this patch? Fine either way. "no binary changes" sounds good ;-) Thanks, Lars
Re: [PATCH v5 2/6] soc: mediatek: add mtk-mmsys support for mt8195 vdosys0
Hi Jason, Thank you for your patch. On 29/7/21 19:07, jason-jh.lin wrote: > Add mt8195 vdosys0 clock driver name and routing table to > the driver data of mtk-mmsys. > This patch is the one that is really introducing mt8195 mmsys support. It is a bit confusing sent the binding on another patchset. Please include [1] in this patchset so it's clear. [1] https://patchwork.kernel.org/project/linux-mediatek/patch/20210722092624.14401-2-jason-jh@mediatek.com/ > Signed-off-by: jason-jh.lin > --- > This patch is base on [1] > > [1]add mt8195 SoC DRM binding > - https://patchwork.kernel.org/project/linux-mediatek/list/?series=519597 > --- > drivers/soc/mediatek/mt8195-mmsys.h| 96 ++ > drivers/soc/mediatek/mtk-mmsys.c | 11 +++ > include/linux/soc/mediatek/mtk-mmsys.h | 9 +++ > 3 files changed, 116 insertions(+) > create mode 100644 drivers/soc/mediatek/mt8195-mmsys.h > > diff --git a/drivers/soc/mediatek/mt8195-mmsys.h > b/drivers/soc/mediatek/mt8195-mmsys.h > new file mode 100644 > index ..9339a786ec5d > --- /dev/null > +++ b/drivers/soc/mediatek/mt8195-mmsys.h > @@ -0,0 +1,96 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > + > +#ifndef __SOC_MEDIATEK_MT8195_MMSYS_H > +#define __SOC_MEDIATEK_MT8195_MMSYS_H > + > +#define MT8195_VDO0_OVL_MOUT_EN 0xf14 > +#define MT8195_MOUT_DISP_OVL0_TO_DISP_RDMA0 BIT(0) > +#define MT8195_MOUT_DISP_OVL0_TO_DISP_WDMA0 BIT(1) > +#define MT8195_MOUT_DISP_OVL0_TO_DISP_OVL1 BIT(2) > +#define MT8195_MOUT_DISP_OVL1_TO_DISP_RDMA1 BIT(4) > +#define MT8195_MOUT_DISP_OVL1_TO_DISP_WDMA1 BIT(5) > +#define MT8195_MOUT_DISP_OVL1_TO_DISP_OVL0 BIT(6) > + > +#define MT8195_VDO0_SEL_IN 0xf34 > +#define MT8195_SEL_IN_VPP_MERGE_FROM_DSC_WRAP0_OUT (0 << 0) > +#define MT8195_SEL_IN_VPP_MERGE_FROM_DISP_DITHER1(1 << 0) > +#define MT8195_SEL_IN_VPP_MERGE_FROM_VDO1_VIRTUAL0 (2 << 0) > +#define MT8195_SEL_IN_DSC_WRAP0_IN_FROM_DISP_DITHER0 (0 << 4) > +#define MT8195_SEL_IN_DSC_WRAP0_IN_FROM_VPP_MERGE(1 << 4) > +#define MT8195_SEL_IN_DSC_WRAP1_IN_FROM_DISP_DITHER1 (0 << 5) > +#define MT8195_SEL_IN_DSC_WRAP1_IN_FROM_VPP_MERGE(1 << 5) > +#define MT8195_SEL_IN_SINA_VIRTUAL0_FROM_VPP_MERGE (0 << 8) > +#define MT8195_SEL_IN_SINA_VIRTUAL0_FROM_DSC_WRAP1_OUT (1 << 8) > +#define MT8195_SEL_IN_SINB_VIRTUAL0_FROM_DSC_WRAP0_OUT (0 << 9) > +#define MT8195_SEL_IN_DP_INTF0_FROM_DSC_WRAP1_OUT(0 << 12) > +#define MT8195_SEL_IN_DP_INTF0_FROM_VPP_MERGE(1 << > 12) > +#define MT8195_SEL_IN_DP_INTF0_FROM_VDO1_VIRTUAL0(2 << 12) > +#define MT8195_SEL_IN_DSI0_FROM_DSC_WRAP0_OUT(0 << > 16) > +#define MT8195_SEL_IN_DSI0_FROM_DISP_DITHER0 (1 << 16) > +#define MT8195_SEL_IN_DSI1_FROM_DSC_WRAP1_OUT(0 << > 17) > +#define MT8195_SEL_IN_DSI1_FROM_VPP_MERGE(1 << 17) > +#define MT8195_SEL_IN_DISP_WDMA1_FROM_DISP_OVL1 (0 << > 20) > +#define MT8195_SEL_IN_DISP_WDMA1_FROM_VPP_MERGE (1 << > 20) > +#define MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN(0 << > 21) > +#define MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1(1 << > 21) > +#define MT8195_SEL_IN_DISP_WDMA0_FROM_DISP_OVL0 (0 << > 22) > +#define MT8195_SEL_IN_DISP_WDMA0_FROM_VPP_MERGE (1 << > 22) > + > +#define MT8195_VDO0_SEL_OUT 0xf38 > +#define MT8195_SOUT_DISP_DITHER0_TO_DSC_WRAP0_IN (0 << 0) > +#define MT8195_SOUT_DISP_DITHER0_TO_DSI0 (1 << 0) > +#define MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_IN (0 << 1) > +#define MT8195_SOUT_DISP_DITHER1_TO_VPP_MERGE(1 << 1) > +#define MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT(2 << 1) > +#define MT8195_SOUT_VDO1_VIRTUAL0_TO_VPP_MERGE (0 << 4) > +#define MT8195_SOUT_VDO1_VIRTUAL0_TO_DP_INTF0(1 << 4) > +#define MT8195_SOUT_VPP_MERGE_TO_DSI1(0 << 8) > +#define MT8195_SOUT_VPP_MERGE_TO_DP_INTF0(1 << 8) > +#define MT8195_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0 (2 << 8) > +#define MT8195_SOUT_VPP_MERGE_TO_DISP_WDMA1 (3 << 8) > +#define MT8195_SOUT_VPP_MERGE_TO_DSC_WRAP0_IN(4 << 8) > +#define MT8195_SOUT_VPP_MERGE_TO_DSC_WRAP1_IN(0 << > 11) > +#define MT8195_SOUT_VPP_MERGE_TO_DISP_WDMA0 (1 << 11) > +#define MT8195_SOUT_DSC_WRAP0_OUT_TO_DSI0(0 << 12) > +#define MT8195_SOUT_DSC_WRAP0_OUT_TO_SINB_VIRTUAL0 (1 << 12) > +#define MT8195_
Re: [PATCH v5 0/6] Add Mediatek Soc DRM (vdosys0) support for mt8195
Hi Jason, Thank you for your patch. On 29/7/21 19:07, jason-jh.lin wrote: > The hardware path of vdosys0 with eDP panel output need to go through > by several modules, such as, OVL, RDMA, COLOR, CCORR, AAL, GAMMA, > DITHER, DSC and MERGE. > You said in other discussions that vdosys0 has eDP panel output and vdosys1 has DP output. Is it possible to switch the outputs? What I am wondering is if this configuration is hardware specific or board specific, i.e it'll be possible to have another board that has DP output on vdosys0 and eDP output for vdosys1? Thanks, Enric > Change in v5: > - add power-domain property into vdosys0 and vdosys1 dts node. > - add MT8195 prifix and remove unused VDO1 define in mt8195-mmsys.h > > Change in v4: > - extract dt-binding patches to another patch series > https://patchwork.kernel.org/project/linux-mediatek/list/?series=519597 > - squash DSC module into mtk_drm_ddp_comp.c > - add coment and simplify MERGE config function > > Change in v3: > - change mmsys and display dt-bindings document from txt to yaml > - add MERGE additional description in display dt-bindings document > - fix mboxes-cells number of vdosys0 node in dts > - drop mutex eof convert define > - remove pm_runtime apis in DSC and MERGE > - change DSC and MERGE enum to alphabetic order > > Change in v2: > - add DSC yaml file > - add mt8195 drm driver porting parts in to one patch > - remove useless define, variable, structure member and function > - simplify DSC and MERGE file and switch threre order > > jason-jh.lin (6): > arm64: dts: mt8195: add display node for vdosys0 > soc: mediatek: add mtk-mmsys support for mt8195 vdosys0 > soc: mediatek: add mtk-mutex support for mt8195 vdosys0 > drm/mediatek: add mediatek-drm of vdosys0 support for mt8195 > drm/mediatek: add DSC support for mt8195 > drm/mediatek: add MERGE support for mt8195 > > arch/arm64/boot/dts/mediatek/mt8195.dtsi| 112 > drivers/gpu/drm/mediatek/Makefile | 1 + > drivers/gpu/drm/mediatek/mtk_disp_drv.h | 8 + > drivers/gpu/drm/mediatek/mtk_disp_merge.c | 277 > drivers/gpu/drm/mediatek/mtk_disp_rdma.c| 6 + > drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 62 + > drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 2 + > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 32 ++- > drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 + > drivers/soc/mediatek/mt8195-mmsys.h | 96 +++ > drivers/soc/mediatek/mtk-mmsys.c| 11 + > drivers/soc/mediatek/mtk-mutex.c| 93 ++- > include/linux/soc/mediatek/mtk-mmsys.h | 9 + > 13 files changed, 706 insertions(+), 4 deletions(-) > create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_merge.c > create mode 100644 drivers/soc/mediatek/mt8195-mmsys.h >
Aw: [PATCH v7 00/12] Clean up "mediatek,larb"
Full Series tested on BPI-R2/MT7623 Tested-By: Frank Wunderlich regards Frank
Re: [PATCH 3/7] drm/imx/dcss: Enable COMPILE_TEST on all ARM64 platforms
Hi Laurent, On Wed, Jul 28, 2021 at 5:37 PM Laurent Pinchart wrote: > To extend test coverage, relax the dependency on ARCH_MXC to also enable > compilation when COMPILE_TEST is selected. > > Signed-off-by: Laurent Pinchart Thanks for your patch! > --- a/drivers/gpu/drm/imx/dcss/Kconfig > +++ b/drivers/gpu/drm/imx/dcss/Kconfig > @@ -3,7 +3,8 @@ config DRM_IMX_DCSS > select IMX_IRQSTEER > select DRM_KMS_CMA_HELPER > select VIDEOMODE_HELPERS > - depends on DRM && ARCH_MXC && ARM64 > + depends on DRM > + depends on ARM64 && (ARCH_MXC || COMPILE_TEST) As you now have two depends statements, I think this would be easier to read by maintaining a strict separation between "hard" and "soft" dependencies: depends on DRM && ARM64 depends on ARCH_MXC || COMPILE_TEST Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
[PATCH v5] drm/panel: Add support for E Ink VB3300-KCA
Add support for the 10.3" E Ink panel described at: https://www.eink.com/product.html?type=productdetail&id=7 Signed-off-by: Alistair Francis Acked-by: Rob Herring Reviewed-by: Sam Ravnborg --- v5: - Add .connector_type .../bindings/display/panel/panel-simple.yaml | 2 ++ .../devicetree/bindings/vendor-prefixes.yaml | 2 ++ drivers/gpu/drm/panel/panel-simple.c | 30 +++ 3 files changed, 34 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index b3797ba2698b..799e20222551 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -128,6 +128,8 @@ properties: # Emerging Display Technology Corp. WVGA TFT Display with capacitive touch - edt,etm0700g0dh6 - edt,etm0700g0edh6 +# E Ink VB3300-KCA + - eink,vb3300-kca # Evervision Electronics Co. Ltd. VGG804821 5.0" WVGA TFT LCD Panel - evervision,vgg804821 # Foxlink Group 5" WVGA TFT LCD panel diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 71da86e7b3a2..31745c45dd92 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -339,6 +339,8 @@ patternProperties: description: eGalax_eMPIA Technology Inc "^einfochips,.*": description: Einfochips + "^eink,.*": +description: E Ink Corporation "^elan,.*": description: Elan Microelectronic Corp. "^element14,.*": diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 21939d4352cf..90d96091f09f 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -2046,6 +2046,33 @@ static const struct panel_desc edt_etm0700g0bdh6 = { .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, }; +static const struct display_timing eink_vb3300_kca_timing = { + .pixelclock = { 4000, 4000, 4000 }, + .hactive = { 334, 334, 334 }, + .hfront_porch = { 1, 1, 1 }, + .hback_porch = { 1, 1, 1 }, + .hsync_len = { 1, 1, 1 }, + .vactive = { 1405, 1405, 1405 }, + .vfront_porch = { 1, 1, 1 }, + .vback_porch = { 1, 1, 1 }, + .vsync_len = { 1, 1, 1 }, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | +DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE, +}; + +static const struct panel_desc eink_vb3300_kca = { + .timings = &eink_vb3300_kca_timing, + .num_timings = 1, + .bpc = 6, + .size = { + .width = 157, + .height = 209, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, + .connector_type = DRM_MODE_CONNECTOR_DPI, +}; + static const struct display_timing evervision_vgg804821_timing = { .pixelclock = { 2760, 3330, 5000 }, .hactive = { 800, 800, 800 }, @@ -4350,6 +4377,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "edt,etm0700g0edh6", .data = &edt_etm0700g0bdh6, + }, { + .compatible = "eink,vb3300-kca", + .data = &eink_vb3300_kca, }, { .compatible = "evervision,vgg804821", .data = &evervision_vgg804821, -- 2.31.1
Re: [PATCH 3/7] drm/imx/dcss: Enable COMPILE_TEST on all ARM64 platforms
On Fri, 2021-07-30 at 14:10 +0200, Geert Uytterhoeven wrote: > Hi Laurent, > > On Wed, Jul 28, 2021 at 5:37 PM Laurent Pinchart > wrote: > > To extend test coverage, relax the dependency on ARCH_MXC to also enable > > compilation when COMPILE_TEST is selected. > > > > Signed-off-by: Laurent Pinchart > > Thanks for your patch! > > > --- a/drivers/gpu/drm/imx/dcss/Kconfig > > +++ b/drivers/gpu/drm/imx/dcss/Kconfig > > @@ -3,7 +3,8 @@ config DRM_IMX_DCSS > > select IMX_IRQSTEER > > select DRM_KMS_CMA_HELPER > > select VIDEOMODE_HELPERS > > - depends on DRM && ARCH_MXC && ARM64 > > + depends on DRM > > + depends on ARM64 && (ARCH_MXC || COMPILE_TEST) > > As you now have two depends statements, I think this would be easier > to read by maintaining a strict separation between "hard" and "soft" > dependencies: > > depends on DRM && ARM64 > depends on ARCH_MXC || COMPILE_TEST I would let (ARCH_MXC && ARM64) stay together, and as Tomi suggested, lift the ARM64 limitation if COMPILE_TEST is enabled: depends on DRM depends on (ARCH_MXC && ARM64) || COMPILE_TEST regards Philipp
Re: [RFC v1 0/4] drm: Add support for DRM_CAP_DEFERRED_OUT_FENCE capability
On 2021-07-30 12:25 p.m., Daniel Vetter wrote: > On Thu, Jul 29, 2021 at 01:16:55AM -0700, Vivek Kasireddy wrote: >> By separating the OUT_FENCE signalling from pageflip completion allows >> a Guest compositor to start a new repaint cycle with a new buffer >> instead of waiting for the old buffer to be free. >> >> This work is based on the idea/suggestion from Simon and Pekka. >> >> This capability can be a solution for this issue: >> https://gitlab.freedesktop.org/wayland/weston/-/issues/514 >> >> Corresponding Weston MR: >> https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/668 > > Uh I kinda wanted to discuss this a bit more before we jump into typing > code, but well I guess not that much work yet. > > So maybe I'm not understanding the problem, but I think the fundamental > underlying issue is that with KMS you can have at most 2 buffers > in-flight, due to our queue depth limit of 1 pending flip. > > Unfortunately that means for virtual hw where it takes a few more > steps/vblanks until the framebuffer actually shows up on screen and is > scanned out, we suffer deeply. The usual fix for that is to drop the > latency and increase throughput, and have more buffers in-flight. Which > this patch tries to do. Per https://gitlab.freedesktop.org/wayland/weston/-/issues/514#note_986797 , IMO the underlying issue is actually that the guest compositor repaint cycle is not aligned with the host compositor one. If they were aligned, the problem would not occur even without allowing multiple page flips in flight, and latency would be lower. > Now I think where we go wrong here is that we're trying to hack this up by > defining different semantics for the out-fence and for the drm-event. Imo > that's wrong, they're both meant to show eactly the same thing: > - when is the new frame actually visible to the user (as in, eyeballs in a > human head, preferrably, not the time when we've handed the buffer off > to the virtual hw) > - when is the previous buffer no longer being used by the scanout hw > > We do cheat a bit right now in so far that we assume they're both the > same, as in, panel-side latency is currently the compositor's problem to > figure out. > > So for virtual hw I think the timestamp and even completion really need to > happen only when the buffer has been pushed through the entire > virtualization chain, i.e. ideally we get the timestamp from the kms > driver from the host side. Currently that's not done, so this is most > likely quite broken already (virtio relies on the no-vblank auto event > sending, which definitely doesn't wait for anything, or I'm completely > missing something). > > I think instead of hacking up some ill-defined 1.5 queue depth support, > what we should do is support queue depth > 1 properly. So: > > - Change atomic to support queue depth > 1, this needs to be a per-driver > thing due to a bunch of issues in driver code. Essentially drivers must > never look at obj->state pointers, and only ever look up state through > the passed-in drm_atomic_state * update container. > > - Aside: virtio should loose all it's empty hooks, there's no point in > that. > > - We fix virtio to send out the completion event at the end of this entire > pipeline, i.e. virtio code needs to take care of sending out the > crtc_state->event correctly. > > - We probably also want some kind of (maybe per-crtc) recommended queue > depth property so compositors know how many buffers to keep in flight. > Not sure about that. I'd say there would definitely need to be some kind of signal for the display server that it should queue multiple flips, since this is normally not desirable for latency. In other words, this wouldn't really be useful on bare metal (in contrast to the ability to replace a pending flip with a newer one). -- Earthling Michel Dänzer | https://redhat.com Libre software enthusiast | Mesa and X developer
[PATCH v2] drm: Fix typo in comments
fix typo for drm v1->v2: respin with the change "iff ==> implies that" Reviewed-by: Daniel Vetter Signed-off-by: Cai Huoqing --- drivers/gpu/drm/drm_aperture.c | 2 +- drivers/gpu/drm/drm_atomic.c| 2 +- drivers/gpu/drm/drm_atomic_helper.c | 10 +- drivers/gpu/drm/drm_atomic_uapi.c | 6 +++--- drivers/gpu/drm/drm_auth.c | 2 +- drivers/gpu/drm/drm_bridge.c| 2 +- drivers/gpu/drm/drm_bufs.c | 2 +- drivers/gpu/drm/drm_cache.c | 2 +- drivers/gpu/drm/drm_damage_helper.c | 2 +- drivers/gpu/drm/drm_dp_helper.c | 8 drivers/gpu/drm/drm_drv.c | 4 ++-- drivers/gpu/drm/drm_dsc.c | 2 +- drivers/gpu/drm/drm_edid.c | 4 ++-- drivers/gpu/drm/drm_fb_helper.c | 2 +- drivers/gpu/drm/drm_file.c | 6 +++--- drivers/gpu/drm/drm_format_helper.c | 2 +- drivers/gpu/drm/drm_framebuffer.c | 2 +- drivers/gpu/drm/drm_gem.c | 4 ++-- drivers/gpu/drm/drm_gem_atomic_helper.c | 4 ++-- drivers/gpu/drm/drm_gem_shmem_helper.c | 2 +- drivers/gpu/drm/drm_gem_vram_helper.c | 2 +- drivers/gpu/drm/drm_hdcp.c | 2 +- drivers/gpu/drm/drm_ioctl.c | 4 ++-- drivers/gpu/drm/drm_irq.c | 2 +- drivers/gpu/drm/drm_mm.c| 2 +- drivers/gpu/drm/drm_mode_object.c | 2 +- drivers/gpu/drm/drm_modes.c | 4 ++-- drivers/gpu/drm/drm_plane.c | 2 +- drivers/gpu/drm/drm_plane_helper.c | 2 +- drivers/gpu/drm/drm_prime.c | 2 +- drivers/gpu/drm/drm_probe_helper.c | 2 +- drivers/gpu/drm/drm_property.c | 2 +- drivers/gpu/drm/drm_scdc_helper.c | 2 +- drivers/gpu/drm/drm_syncobj.c | 2 +- drivers/gpu/drm/drm_vblank.c| 12 ++-- drivers/gpu/drm/drm_vma_manager.c | 2 +- 36 files changed, 58 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c index 9ac39cf11694..74bd4a76b253 100644 --- a/drivers/gpu/drm/drm_aperture.c +++ b/drivers/gpu/drm/drm_aperture.c @@ -78,7 +78,7 @@ * * Drivers that are susceptible to being removed by other drivers, such as * generic EFI or VESA drivers, have to register themselves as owners of their - * given framebuffer memory. Ownership of the framebuffer memory is achived + * given framebuffer memory. Ownership of the framebuffer memory is achieved * by calling devm_aperture_acquire_from_firmware(). On success, the driver * is the owner of the framebuffer range. The function fails if the * framebuffer is already by another driver. See below for an example. diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index d820423fac32..b127e30082ba 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -723,7 +723,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, * clocks, scaler units, bandwidth and fifo limits shared among a group of * planes or CRTCs, and so on) it makes sense to model these as independent * objects. Drivers then need to do similar state tracking and commit ordering for - * such private (since not exposed to userpace) objects as the atomic core and + * such private (since not exposed to userspace) objects as the atomic core and * helpers already provide for connectors, planes and CRTCs. * * To make this easier on drivers the atomic core provides some support to track diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f7bf1ea62d58..7ee480b6efde 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -634,7 +634,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, * connectors and a NULL mode. * * The other way around is true as well. enable != 0 -* iff connectors are attached and a mode is set. +* implies that connectors are attached and a mode is set. */ new_crtc_state->mode_changed = true; new_crtc_state->connectors_changed = true; @@ -1686,7 +1686,7 @@ static void commit_work(struct work_struct *work) } /** - * drm_atomic_helper_async_check - check if state can be commited asynchronously + * drm_atomic_helper_async_check - check if state can be committed asynchronously * @dev: DRM device * @state: the driver state object * @@ -1695,7 +1695,7 @@ static void commit_work(struct work_struct *work) * but just do in-place changes on the current state. * * It will return 0 if the commit can happen in an asynchronous fashion or error - * if not. Note that error just mean it can't be commited asynchronously, if it + * if not. Note that error just mean it can't be committed asynchronously, if
Re: [RFC v1 0/4] drm: Add support for DRM_CAP_DEFERRED_OUT_FENCE capability
Hi, > - We fix virtio to send out the completion event at the end of this entire > pipeline, i.e. virtio code needs to take care of sending out the > crtc_state->event correctly. That sounds sensible to me. Fence the virtio commands, make sure (on the host side) the command completes only when the work is actually done not only submitted. Has recently been added to qemu for RESOURCE_FLUSH (aka frontbuffer rendering) and doing the same for SET_SCANOUT (aka pageflipping), then send vblank events to userspace on command completion certainly makes sense. take care, Gerd
[ANNOUNCE] xf86-video-amdgpu 21.0.0
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Adam Jackson (2): kms: Handle changes to SourceValidate call chain in xserver 19 Fix link failure with gcc 10 Alex Deucher (1): Bump version for the 21.0.0 release Emil Velikov (10): Use ODEV_ATTRIB_PATH where possible for the device node. Remove drmCheckModesettingSupported and kernel module loading, on Linux Fixup the amdgpu_bus_id() string format Remove NULL check after a "cannot fail" function Store the busid string in AMDGPUEnt Reuse the existing busid string Use the device_id straight from gpu_info Kill off drmOpen/Close/drmSetInterfaceVersion in favour of drmDevices Introduce amdgpu_device_setup helper Factor out common code to amdgpu_probe() Likun Gao (1): Fix drmmode_crtc_scanout_create logic Michel Dänzer (11): Bail from amdgpu_pixmap_get_handle with ShadowFB Handle NULL fb_ptr in pixmap_get_fb glamor: Make pixmap scanout compatible if its dimensions are Drop bo/width/height members from struct drmmode_scanout Drop struct drmmode_scanout altogether in favour of PixmapPtrs Make drmmode_crtc_scanout_create/destroy static Fix build against ABI_VIDEODRV_VERSION 25.2 Replace a few more instances of "master" Check for AMDGPU_CREATE_PIXMAP_SCANOUT in amdgpu_glamor_create_pixmap Drop dri.h includes Include xf86drm.h instead of sarea.h Niclas Zeising (1): Fix return value check of drmIoctl() Peter Hutterer (1): gitlab CI: update to use the latest CI templates git tag: xf86-video-amdgpu-21.0.0 https://xorg.freedesktop.org/archive/individual/driver/xf86-video-amdgpu-21.0.0.tar.bz2 SHA256: 607823034defba6152050e5eb1c4df94b38819ef764291abadd81b620bc2ad88 xf86-video-amdgpu-21.0.0.tar.bz2 SHA512: 44ccc8ddc36f09d1608cf58b6cf85dda090671c46c5643e9453f7d67f4d6850c3c9753eba43539d45773198b8042898a50153b5225780e4b2852410c5521314a xf86-video-amdgpu-21.0.0.tar.bz2 PGP: https://xorg.freedesktop.org/archive/individual/driver/xf86-video-amdgpu-21.0.0.tar.bz2.sig https://xorg.freedesktop.org/archive/individual/driver/xf86-video-amdgpu-21.0.0.tar.gz SHA256: c3df02cc280c120d07eac01559b1e2c09890546f5044d4853209e5eff71a2f7e xf86-video-amdgpu-21.0.0.tar.gz SHA512: c744ff096695b3d80f4dc3977f0952284e890fd72ed635a04c57806747621c32686f5982cf127de47f5895d73d7b52791a27d8eef4034e2e79547b3c8a6ee8c1 xf86-video-amdgpu-21.0.0.tar.gz PGP: https://xorg.freedesktop.org/archive/individual/driver/xf86-video-amdgpu-21.0.0.tar.gz.sig -BEGIN PGP SIGNATURE- iF0EARECAB0WIQQBfpGodcujISWDgPGbTuT5hHTeQAUCYQQDWgAKCRCbTuT5hHTe QHXKAKDIw5l0TpJ8gPvB9tw50WCp2WktpgCgpuhzs+UfUrZZ76OOzRWClz0CbpA= =0H9K -END PGP SIGNATURE-
[RFC PATCH] drm: mock_device can be static
drivers/gpu/drm/selftests/test-drm_damage_helper.c:15:19: warning: symbol 'mock_device' was not declared. Should it be static? drivers/gpu/drm/selftests/test-drm_damage_helper.c:16:30: warning: symbol 'mock_obj_props' was not declared. Should it be static? drivers/gpu/drm/selftests/test-drm_damage_helper.c:17:18: warning: symbol 'mock_plane' was not declared. Should it be static? drivers/gpu/drm/selftests/test-drm_damage_helper.c:18:21: warning: symbol 'mock_prop' was not declared. Should it be static? Reported-by: kernel test robot Signed-off-by: kernel test robot --- test-drm_damage_helper.c |8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/selftests/test-drm_damage_helper.c b/drivers/gpu/drm/selftests/test-drm_damage_helper.c index 1b585c13e042fe..1c19a5d3eefbf8 100644 --- a/drivers/gpu/drm/selftests/test-drm_damage_helper.c +++ b/drivers/gpu/drm/selftests/test-drm_damage_helper.c @@ -12,10 +12,10 @@ #include "test-drm_modeset_common.h" struct drm_driver mock_driver; -struct drm_device mock_device; -struct drm_object_properties mock_obj_props; -struct drm_plane mock_plane; -struct drm_property mock_prop; +static struct drm_device mock_device; +static struct drm_object_properties mock_obj_props; +static struct drm_plane mock_plane; +static struct drm_property mock_prop; static void mock_setup(struct drm_plane_state *state) {
Re: [PATCH] drm: Fix oops in damage self-tests by mocking damage property
Hi Daniel, I love your patch! Perhaps something to improve: [auto build test WARNING on drm-tip/drm-tip] [also build test WARNING on drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next linus/master v5.14-rc3 next-20210729] [cannot apply to drm/drm-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Daniel-Vetter/drm-Fix-oops-in-damage-self-tests-by-mocking-damage-property/20210730-175415 base: git://anongit.freedesktop.org/drm/drm-tip drm-tip config: i386-randconfig-s001-20210730 (attached as .config) compiler: gcc-10 (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0 reproduce: # apt-get install sparse # sparse version: v0.6.3-341-g8af24329-dirty # https://github.com/0day-ci/linux/commit/cfe1add77c3c78aec60eb1645950c6aa2daf8b4d git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Daniel-Vetter/drm-Fix-oops-in-damage-self-tests-by-mocking-damage-property/20210730-175415 git checkout cfe1add77c3c78aec60eb1645950c6aa2daf8b4d # save the attached .config to linux build tree make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash drivers/gpu/drm/selftests/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot sparse warnings: (new ones prefixed by >>) >> drivers/gpu/drm/selftests/test-drm_damage_helper.c:15:19: sparse: sparse: >> symbol 'mock_device' was not declared. Should it be static? >> drivers/gpu/drm/selftests/test-drm_damage_helper.c:16:30: sparse: sparse: >> symbol 'mock_obj_props' was not declared. Should it be static? >> drivers/gpu/drm/selftests/test-drm_damage_helper.c:17:18: sparse: sparse: >> symbol 'mock_plane' was not declared. Should it be static? >> drivers/gpu/drm/selftests/test-drm_damage_helper.c:18:21: sparse: sparse: >> symbol 'mock_prop' was not declared. Should it be static? drivers/gpu/drm/selftests/test-drm_damage_helper.c:101:30: sparse: sparse: symbol 'fb' was not declared. Should it be static? drivers/gpu/drm/selftests/test-drm_damage_helper.c:259:23: sparse: sparse: Using plain integer as NULL pointer Please review and possibly fold the followup patch. --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
Re: [PATCH -next] drm/amdgpu: fix checking pmops when PM_SLEEP is not enabled
Applied. Thanks! Alex On Thu, Jul 29, 2021 at 11:03 PM Randy Dunlap wrote: > > 'pm_suspend_target_state' is only available when CONFIG_PM_SLEEP > is set/enabled. OTOH, when both SUSPEND and HIBERNATION are not set, > PM_SLEEP is not set, so this variable cannot be used. > > ../drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c: In function > ‘amdgpu_acpi_is_s0ix_active’: > ../drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c:1046:11: error: > ‘pm_suspend_target_state’ undeclared (first use in this function); did you > mean ‘__KSYM_pm_suspend_target_state’? > return pm_suspend_target_state == PM_SUSPEND_TO_IDLE; >^~~ >__KSYM_pm_suspend_target_state > > Also use shorter IS_ENABLED(CONFIG_foo) notation for checking the > 2 config symbols. > > Fixes: 91b03fc6b50c ("drm/amdgpu: Check pmops for desired suspend state") > Signed-off-by: Randy Dunlap > Cc: Alex Deucher > Cc: Christian König > Cc: "Pan, Xinhui" > Cc: amd-...@lists.freedesktop.org > Cc: dri-devel@lists.freedesktop.org > Cc: linux-n...@vger.kernel.org > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c |2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > --- linext-20210729.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c > +++ linext-20210729/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c > @@ -1040,7 +1040,7 @@ void amdgpu_acpi_detect(void) > */ > bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) > { > -#if defined(CONFIG_AMD_PMC) || defined(CONFIG_AMD_PMC_MODULE) > +#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_PM_SLEEP) > if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { > if (adev->flags & AMD_IS_APU) > return pm_suspend_target_state == PM_SUSPEND_TO_IDLE;
Re: [PATCH v8 00/14] drm/tegra: Introduce a modern UABI
09.07.2021 22:31, Thierry Reding пишет: > From: Thierry Reding > > Hi all, > > Mikko has been away for a few weeks, so I've been testing and revising > the new UABI patches in the meantime. There are very minor changes to > the naming of some of the UABI fields, but other than that it's mostly > unchanged from v7. > > One notable change is that mappings can now be read-only, write-only, > read-write or none of them (rather than just read-only or read-write), > since those combinations are all supported by the IOMMUs and it might > be useful to make some mappings write-only. > > For a full list of changes in v8, see the changelog in patch 6. > > I've also updated the libdrm_tegra library to work against this version > of the UABI. A branch can be found here: > > https://gitlab.freedesktop.org/tagr/drm/-/commits/drm-tegra-uabi-v8 > > That contains helper APIs for the concepts introduced in this series and > shows how they can be used in various tests that can be run for sanity > checking. > > In addition, Mikko has made updates to the following projects, though > they may need to be updated for the minor changes in v8: > > * vaapi-tegra-driver - https://github.com/cyndis/vaapi-tegra-driver > Experimental support for MPEG2 and H264 decoding on T210, T186 > and T194. > > * xf86-video-opentegra - https://github.com/grate-driver/xf86-video-opentegra > X11 userspace acceleration driver for Tegra20, Tegra30, and Tegra114. > > * grate - https://github.com/grate-driver/grate > 3D rendering testbed for Tegra20, Tegra30, and Tegra114 > > I plan on putting this into linux-next soon after v5.14-rc1 so that this > can get some soak time. > > Thierry > > Mikko Perttunen (14): > gpu: host1x: Add DMA fence implementation > gpu: host1x: Add no-recovery mode > gpu: host1x: Add job release callback > gpu: host1x: Add support for syncpoint waits in CDMA pushbuffer > drm/tegra: Extract tegra_gem_lookup > drm/tegra: Add new UAPI to header > drm/tegra: Boot VIC during runtime PM resume > drm/tegra: Allocate per-engine channel in core code > drm/tegra: Implement new UAPI > drm/tegra: Implement syncpoint management UAPI > drm/tegra: Implement syncpoint wait UAPI > drm/tegra: Implement job submission part of new UAPI > drm/tegra: Add job firewall > drm/tegra: Bump driver version The "gpu: host1x: Add option to skip firewall for a job" of v7 is not here. The tegra_drm_ioctl_channel_map() uses wrong BO size again, which breaks firewall, it was fixed in v7. The DRM_TEGRA_CHANNEL_MAP_WRITE and DRM_TEGRA_CHANNEL_MAP_READ values should be swapped to preserve compatibility with the current userspace. Please fix all the coding style problems reported by "./scripts/checkpatch.pl --strict" and other things reported previously. Re-submit v9.
[PATCH v2 0/6] drm/panel: atna33xc20: Fix the Samsung ATNA33XC20 panel
The overall goal of this series is to make the Samsung ATNA33XC20 panel work more properly. As part of this, we have: * A bugfix for the recently abstracted DP AUX backlight code. * A bugfix for the sequencing of the ti-sn65dsi86 bridge driver. * Removal of the panel from panel-simple and moving it to its own driver. If the bugfixes look good but the rest of the series needs work then those could land early on their own. There's no real compile time dependency on the bugfixes, things are just glitchier without them. NOTE: this series will (slightly) conflict with my other recent series making eDP panels probable [1]. I'll re-post that one atop this one. It should be noted that the fact that the Samsung ATNA33XC20 needs its own panel driver means that it _can't_ handled as a probed driver. I think this is fine, at least for now. I don't think it would be easy to make a unified design with this panel and other panels given that it's an AMOLED panel and has a whole bunch of different components on board. As discussed in IRC, the only difference in v2 is the addition of a "Fixes" tag to patch #3 and the collection of Reviews/Acks from Sean and Robert. If people feel that this is ready to land today then I can help land it (please let me know). Otherwise I'm happy for someone else to actually do the commit next week (I'm on vacation) or I can take it when I get back. [1] https://lore.kernel.org/r/20210723002146.1962910-1-diand...@chromium.org/ Changes in v2: - Added Fixes tag as requested by Sam. Douglas Anderson (6): drm/dp: Don't zero PWMGEN_BIT_COUNT when driver_pwm_freq_hz not specified drm/bridge: ti-sn65dsi86: Fix power off sequence drm/bridge: ti-sn65dsi86: Add some 100 us delays Revert "drm/panel-simple: Add Samsung ATNA33XC20" Revert "drm/panel-simple: Support for delays between GPIO & regulator" drm/panel: atna33xc20: Introduce the Samsung ATNA33XC20 panel drivers/gpu/drm/bridge/ti-sn65dsi86.c | 17 +- drivers/gpu/drm/drm_dp_helper.c | 10 +- drivers/gpu/drm/panel/Kconfig | 12 + drivers/gpu/drm/panel/Makefile| 1 + .../gpu/drm/panel/panel-samsung-atna33xc20.c | 366 ++ drivers/gpu/drm/panel/panel-simple.c | 61 --- 6 files changed, 398 insertions(+), 69 deletions(-) create mode 100644 drivers/gpu/drm/panel/panel-samsung-atna33xc20.c -- 2.32.0.554.ge1b32706d8-goog
[PATCH v2 2/6] drm/bridge: ti-sn65dsi86: Fix power off sequence
When testing with a panel that's apparently a little more persnickety about the correct power sequence (specifically Samsung ATNA33XC20), we found that the ti-sn65dsi86 was doing things just slightly wrong. Looking closely at the ti-sn65dsi86's datasheet, the power off sequence is supposed to be: 1. Clear VSTREAM_ENABLE bit 2. Stop DSI stream from GPU. DSI lanes must be placed in LP11 state. 3. Program the ML_TX_MODE to 0x0 (OFF) 4. Program the DP_NUM_LANES register to 0x0 5. Clear the DP_PLL_EN bit. 6. Deassert the EN pin. 7. Remove power from supply pins Since we were doing the whole sequence in the "disable", I believe that step #2 (stopping the DSI stream from the GPU) wasn't happening. We also weren't setting DP_NUM_LANES to 0. Let's fix this. NOTE: things are a little asymmetric now. For instance, we turn the PLL on in "enable" but now we're not turning it off until "post_disable". It would seem to make sense to move the PLL turning on to "pre_enable" to match. Unfortunately, I don't believe that's allowed. It looks as if (in the non-refclk mode which probably nobody is using) we have to wait until the MIPI clock is there before we can enable the PLL. In any case, the way it is here won't really hurt--it'll just leave the PLL on a little longer. Fixes: a095f15c00e2 ("drm/bridge: add support for sn65dsi86 bridge driver") Signed-off-by: Douglas Anderson Acked-by: Robert Foss Reviewed-by: Sean Paul --- (no changes since v1) drivers/gpu/drm/bridge/ti-sn65dsi86.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 9bf889302bcc..5e932070a1c3 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -766,10 +766,6 @@ static void ti_sn_bridge_disable(struct drm_bridge *bridge) /* disable video stream */ regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG, VSTREAM_ENABLE, 0); - /* semi auto link training mode OFF */ - regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0); - /* disable DP PLL */ - regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 0); } static void ti_sn_bridge_set_dsi_rate(struct ti_sn65dsi86 *pdata) @@ -1106,6 +1102,13 @@ static void ti_sn_bridge_post_disable(struct drm_bridge *bridge) { struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + /* semi auto link training mode OFF */ + regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0); + /* Num lanes to 0 as per power sequencing in data sheet */ + regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK, 0); + /* disable DP PLL */ + regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 0); + if (!pdata->refclk) ti_sn65dsi86_disable_comms(pdata); -- 2.32.0.554.ge1b32706d8-goog
[PATCH v2 1/6] drm/dp: Don't zero PWMGEN_BIT_COUNT when driver_pwm_freq_hz not specified
The function drm_edp_backlight_init() is defined such that the "driver_pwm_freq_hz" parameter is optional--it's 0 if you don't want to futz with it. If you follow this variable through, you'll find out that if it's 0 we won't ever set the "bl->pwmgen_bit_count", leaving it as 0. That means that before using it in drm_edp_backlight_enable() we need to check to see if it's non-zero. Programming this field to zero was confusing the panel I tested with (Samsung ATNA33XC20). The backlight still worked somewhat but the brightness values didn't correspond to what they should have been. Fixes: 867cf9cd73c3 ("drm/dp: Extract i915's eDP backlight code into DRM helpers") Signed-off-by: Douglas Anderson Reviewed-by: Sean Paul --- (no changes since v1) drivers/gpu/drm/drm_dp_helper.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index b5f75ca05774..b8a5c5e49d74 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -3229,10 +3229,12 @@ int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backli new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; - ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count); - if (ret != 1) - drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux pwmgen bit count: %d\n", - aux->name, ret); + if (bl->pwmgen_bit_count) { + ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count); + if (ret != 1) + drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux pwmgen bit count: %d\n", + aux->name, ret); + } } if (bl->pwm_freq_pre_divider) { -- 2.32.0.554.ge1b32706d8-goog
[PATCH v2 3/6] drm/bridge: ti-sn65dsi86: Add some 100 us delays
The manual has always said that we need 100 us delays in a few places. Though it hasn't seemed to be a big deal to skip these, let's add them in case it makes something happier. NOTE: this fixes no known issues but it seems good to make it right. Fixes: a095f15c00e2 ("drm/bridge: add support for sn65dsi86 bridge driver") Signed-off-by: Douglas Anderson Acked-by: Robert Foss Reviewed-by: Sean Paul --- Changes in v2: - Added Fixes tag as requested by Sam. drivers/gpu/drm/bridge/ti-sn65dsi86.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 5e932070a1c3..cd0fccdd8dfd 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -307,6 +307,9 @@ static int __maybe_unused ti_sn65dsi86_resume(struct device *dev) return ret; } + /* td2: min 100 us after regulators before enabling the GPIO */ + usleep_range(100, 110); + gpiod_set_value(pdata->enable_gpio, 1); /* @@ -1096,6 +1099,9 @@ static void ti_sn_bridge_pre_enable(struct drm_bridge *bridge) if (!pdata->refclk) ti_sn65dsi86_enable_comms(pdata); + + /* td7: min 100 us after enable before DSI data */ + usleep_range(100, 110); } static void ti_sn_bridge_post_disable(struct drm_bridge *bridge) -- 2.32.0.554.ge1b32706d8-goog
[PATCH v2 6/6] drm/panel: atna33xc20: Introduce the Samsung ATNA33XC20 panel
The Samsung ATNA33XC20 panel is an AMOLED eDP panel that has backlight control over the DP AUX channel. This panel is _almost_ able to be controlled in a "simple" way (and it originally was implemented in panel-simple.c), but it's really impossible to get the backlight semantics right there without adding wacky special-case code to panel-simple. Let's give up and clone the parts of panel-simple that we need and implement the power sequence that this panel needs. NOTE: we'll still leave the devicetree bindings alone. Even though the power-sequencing is non-standard the bindings are still "simple". Signed-off-by: Douglas Anderson Reviewed-by: Sean Paul --- (no changes since v1) drivers/gpu/drm/panel/Kconfig | 12 + drivers/gpu/drm/panel/Makefile| 1 + .../gpu/drm/panel/panel-samsung-atna33xc20.c | 366 ++ 3 files changed, 379 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-samsung-atna33xc20.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 6b3eb041182c..58430d358489 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -353,6 +353,18 @@ config DRM_PANEL_RONBO_RB070D30 Say Y here if you want to enable support for Ronbo Electronics RB070D30 1024x600 DSI panel. +config DRM_PANEL_SAMSUNG_ATNA33XC20 + tristate "Samsung ATNA33XC20 eDP panel" + depends on OF + depends on BACKLIGHT_CLASS_DEVICE + depends on PM + select VIDEOMODE_HELPERS + select DRM_DP_AUX_BUS + help + DRM panel driver for the Samsung ATNA33XC20 panel. This panel can't + be handled by the DRM_PANEL_SIMPLE driver because its power + sequencing is non-standard. + config DRM_PANEL_SAMSUNG_DB7430 tristate "Samsung DB7430-based DPI panels" depends on OF && SPI && GPIOLIB diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 08debae9b314..1b6fe2008861 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c new file mode 100644 index ..221db6512859 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c @@ -0,0 +1,366 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2021 Google Inc. + * + * Panel driver for the Samsung ATNA33XC20 panel. This panel can't be handled + * by the DRM_PANEL_SIMPLE driver because its power sequencing is non-standard. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct atana33xc20_panel { + struct drm_panel base; + bool prepared; + bool enabled; + bool el3_was_on; + + bool no_hpd; + struct gpio_desc *hpd_gpio; + + struct regulator *supply; + struct gpio_desc *el_on3_gpio; + + struct edid *edid; + + ktime_t powered_off_time; + ktime_t powered_on_time; + ktime_t el_on3_off_time; +}; + +static inline struct atana33xc20_panel *to_atana33xc20(struct drm_panel *panel) +{ + return container_of(panel, struct atana33xc20_panel, base); +} + +static void atana33xc20_wait(ktime_t start_ktime, unsigned int min_ms) +{ + ktime_t now_ktime, min_ktime; + + min_ktime = ktime_add(start_ktime, ms_to_ktime(min_ms)); + now_ktime = ktime_get(); + + if (ktime_before(now_ktime, min_ktime)) + msleep(ktime_to_ms(ktime_sub(min_ktime, now_ktime)) + 1); +} + +static int atana33xc20_suspend(struct device *dev) +{ + struct atana33xc20_panel *p = dev_get_drvdata(dev); + int ret; + + /* +* Note 3 (Example of power off sequence in detail) in spec +* specifies to wait 150 ms after deasserting EL3_ON before +* powering off. +*/ + if (p->el3_was_on) + atana33xc20_wait(p->el_on3_off_time, 150); + + ret = regulator_disable(p->supply); + if (ret) + return ret; + p->powered_off_time = ktime_get(); + p->el3_was_on = false; + + return 0; +} + +static int atana33xc20_resume(struct device *dev) +{ + struct atana33xc20_panel *p = dev_get_drvdata(dev); + bool hpd_asserted = false; + int ret; + + /* T12 (Power off time) is min 500 ms */ +
[PATCH v2 4/6] Revert "drm/panel-simple: Add Samsung ATNA33XC20"
This reverts commit 4bfe6c8f7c23b01719671b69fd29b87a35ccd9d6. This panel's power sequencing really can't be handled properly by panel-simple because of the special sequencing needed for the EL_ON3 GPIO. The only way it was sorta working in the past was by trying to jam that signal into the "enable-gpio", but that really wasn't a good fit. We'll add a custom panel driver for this panel to do it right. Signed-off-by: Douglas Anderson Reviewed-by: Sean Paul --- (no changes since v1) drivers/gpu/drm/panel/panel-simple.c | 33 1 file changed, 33 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 9b286bdf..c8694f7f8e0f 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3621,36 +3621,6 @@ static const struct panel_desc rocktech_rk101ii01d_ct = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; -static const struct drm_display_mode samsung_atna33xc20_mode = { - .clock = 138770, - .hdisplay = 1920, - .hsync_start = 1920 + 48, - .hsync_end = 1920 + 48 + 32, - .htotal = 1920 + 48 + 32 + 80, - .vdisplay = 1080, - .vsync_start = 1080 + 8, - .vsync_end = 1080 + 8 + 8, - .vtotal = 1080 + 8 + 8 + 16, - .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, -}; - -static const struct panel_desc samsung_atna33xc20 = { - .modes = &samsung_atna33xc20_mode, - .num_modes = 1, - .bpc = 10, - .size = { - .width = 294, - .height = 165, - }, - .delay = { - .disable_to_power_off = 200, - .power_to_enable = 400, - .hpd_absent_delay = 200, - .unprepare = 500, - }, - .connector_type = DRM_MODE_CONNECTOR_eDP, -}; - static const struct drm_display_mode samsung_lsn122dl01_c01_mode = { .clock = 271560, .hdisplay = 2560, @@ -4657,9 +4627,6 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "rocktech,rk101ii01d-ct", .data = &rocktech_rk101ii01d_ct, - }, { - .compatible = "samsung,atna33xc20", - .data = &samsung_atna33xc20, }, { .compatible = "samsung,lsn122dl01-c01", .data = &samsung_lsn122dl01_c01, -- 2.32.0.554.ge1b32706d8-goog
[PATCH v2 5/6] Revert "drm/panel-simple: Support for delays between GPIO & regulator"
This reverts commit 18a1488bf1e13fc3fc96d7948466b2166067c6c8. Those delays were added to support the Samsung ATNA33XC20 panel. However, we've moving that to its own panel driver and out of panel-simple. That means we don't need the ability to specify this delay. NOTE: it's unlikely we want to keep this delay "just in case" some other panel needs it. The enable-gpio and the power supply are really supposed to be different ways to specify the same thing: the main enable of the panel. Supporting a delay between them doesn't really make sense. Signed-off-by: Douglas Anderson Reviewed-by: Sean Paul --- (no changes since v1) drivers/gpu/drm/panel/panel-simple.c | 28 1 file changed, 28 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index c8694f7f8e0f..ff8b59471c71 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -132,22 +132,6 @@ struct panel_desc { */ unsigned int prepare_to_enable; - /** -* @delay.power_to_enable: Time for the power to enable the display on. -* -* The time (in milliseconds) to wait after powering up the display -* before asserting its enable pin. -*/ - unsigned int power_to_enable; - - /** -* @delay.disable_to_power_off: Time for the disable to power the display off. -* -* The time (in milliseconds) to wait before powering off the display -* after deasserting its enable pin. -*/ - unsigned int disable_to_power_off; - /** * @delay.enable: Time for the panel to display a valid frame. * @@ -363,10 +347,6 @@ static int panel_simple_suspend(struct device *dev) struct panel_simple *p = dev_get_drvdata(dev); gpiod_set_value_cansleep(p->enable_gpio, 0); - - if (p->desc->delay.disable_to_power_off) - msleep(p->desc->delay.disable_to_power_off); - regulator_disable(p->supply); p->unprepared_time = ktime_get(); @@ -427,9 +407,6 @@ static int panel_simple_prepare_once(struct panel_simple *p) return err; } - if (p->desc->delay.power_to_enable) - msleep(p->desc->delay.power_to_enable); - gpiod_set_value_cansleep(p->enable_gpio, 1); delay = p->desc->delay.prepare; @@ -803,11 +780,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, break; } - if (!panel->enable_gpio && desc->delay.disable_to_power_off) - dev_warn(dev, "Need a delay after disabling panel GPIO, but a GPIO wasn't provided\n"); - if (!panel->enable_gpio && desc->delay.power_to_enable) - dev_warn(dev, "Need a delay before enabling panel GPIO, but a GPIO wasn't provided\n"); - dev_set_drvdata(dev, panel); /* -- 2.32.0.554.ge1b32706d8-goog
Re: [PATCH 7/9] phy: phy-mtk-hdmi: convert to devm_platform_ioremap_resource
Hi, Chunfeng: Chunfeng Yun 於 2021年7月28日 週三 下午3:59寫道: > > Use devm_platform_ioremap_resource to simplify code Acked-by: Chun-Kuang Hu > > Signed-off-by: Chunfeng Yun > --- > drivers/phy/mediatek/phy-mtk-hdmi.c | 7 ++- > 1 file changed, 2 insertions(+), 5 deletions(-) > > diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c > b/drivers/phy/mediatek/phy-mtk-hdmi.c > index 8ad8f717ef43..5fb4217fb8e0 100644 > --- a/drivers/phy/mediatek/phy-mtk-hdmi.c > +++ b/drivers/phy/mediatek/phy-mtk-hdmi.c > @@ -100,7 +100,6 @@ static int mtk_hdmi_phy_probe(struct platform_device > *pdev) > { > struct device *dev = &pdev->dev; > struct mtk_hdmi_phy *hdmi_phy; > - struct resource *mem; > struct clk *ref_clk; > const char *ref_clk_name; > struct clk_init_data clk_init = { > @@ -116,11 +115,9 @@ static int mtk_hdmi_phy_probe(struct platform_device > *pdev) > if (!hdmi_phy) > return -ENOMEM; > > - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > - hdmi_phy->regs = devm_ioremap_resource(dev, mem); > - if (IS_ERR(hdmi_phy->regs)) { > + hdmi_phy->regs = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(hdmi_phy->regs)) > return PTR_ERR(hdmi_phy->regs); > - } > > ref_clk = devm_clk_get(dev, "pll_ref"); > if (IS_ERR(ref_clk)) { > -- > 2.18.0 >
Re: [PATCH 8/9] phy: phy-mtk-mipi-dsi: remove dummy assignment of error number
Hi, Chunfeng: Chunfeng Yun 於 2021年7月28日 週三 下午3:59寫道: > > Return the error number directly without assignment Acked-by: Chun-Kuang Hu > > Signed-off-by: Chunfeng Yun > --- > drivers/phy/mediatek/phy-mtk-mipi-dsi.c | 6 ++ > 1 file changed, 2 insertions(+), 4 deletions(-) > > diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c > b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c > index 01cf31633019..61c942fbf4a1 100644 > --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c > +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c > @@ -203,10 +203,8 @@ static int mtk_mipi_tx_probe(struct platform_device > *pdev) > phy_set_drvdata(phy, mipi_tx); > > phy_provider = devm_of_phy_provider_register(dev, > of_phy_simple_xlate); > - if (IS_ERR(phy_provider)) { > - ret = PTR_ERR(phy_provider); > - return ret; > - } > + if (IS_ERR(phy_provider)) > + return PTR_ERR(phy_provider); > > mipi_tx->dev = dev; > > -- > 2.18.0 >
Re: [PATCH 9/9] phy: phy-mtk-mipi-dsi: convert to devm_platform_ioremap_resource
Hi, Chunfeng: Chunfeng Yun 於 2021年7月28日 週三 下午3:59寫道: > > Use devm_platform_ioremap_resource to simplify code Acked-by: Chun-Kuang Hu > > Signed-off-by: Chunfeng Yun > --- > drivers/phy/mediatek/phy-mtk-mipi-dsi.c | 7 ++- > 1 file changed, 2 insertions(+), 5 deletions(-) > > diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c > b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c > index 61c942fbf4a1..28ad9403c441 100644 > --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c > +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c > @@ -130,7 +130,6 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > struct mtk_mipi_tx *mipi_tx; > - struct resource *mem; > const char *ref_clk_name; > struct clk *ref_clk; > struct clk_init_data clk_init = { > @@ -148,11 +147,9 @@ static int mtk_mipi_tx_probe(struct platform_device > *pdev) > > mipi_tx->driver_data = of_device_get_match_data(dev); > > - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > - mipi_tx->regs = devm_ioremap_resource(dev, mem); > - if (IS_ERR(mipi_tx->regs)) { > + mipi_tx->regs = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(mipi_tx->regs)) > return PTR_ERR(mipi_tx->regs); > - } > > ref_clk = devm_clk_get(dev, NULL); > if (IS_ERR(ref_clk)) { > -- > 2.18.0 >
Re: [PATCH 01/64] media: omap3isp: Extract struct group for memcpy() region
On Fri, Jul 30, 2021 at 12:00:54PM +0300, Dan Carpenter wrote: > On Fri, Jul 30, 2021 at 10:38:45AM +0200, David Sterba wrote: > > Then is explicit memset the only reliable way accross all compiler > > flavors and supported versions? > > > > The = { } initializer works. It's only when you start partially > initializing the struct that it doesn't initialize holes. No, partial works. It's when you _fully_ initialize the struct where the padding doesn't get initialized. *sob* struct foo { u8 flag; /* padding */ void *ptr; }; These are fine: struct foo ok1 = { }; struct foo ok2 = { .flag = 7 }; struct foo ok3 = { .ptr = NULL }; This is not: struct foo bad = { .flag = 7, .ptr = NULL }; (But, of course, it depends on padding size, compiler version, and architecture. i.e. things remain unreliable.) -- Kees Cook
Re: [PATCH 01/64] media: omap3isp: Extract struct group for memcpy() region
On Fri, Jul 30, 2021 at 9:44 AM Kees Cook wrote: > > On Fri, Jul 30, 2021 at 12:00:54PM +0300, Dan Carpenter wrote: > > On Fri, Jul 30, 2021 at 10:38:45AM +0200, David Sterba wrote: > > > Then is explicit memset the only reliable way accross all compiler > > > flavors and supported versions? > > > > > > > The = { } initializer works. It's only when you start partially > > initializing the struct that it doesn't initialize holes. > > No, partial works. It's when you _fully_ initialize the struct where the > padding doesn't get initialized. *sob* I'm pretty sure that this has more to do with whether or not the compiler applies SROA then observes uses of the individual members or not. > > struct foo { > u8 flag; > /* padding */ > void *ptr; > }; > > These are fine: > > struct foo ok1 = { }; > struct foo ok2 = { .flag = 7 }; > struct foo ok3 = { .ptr = NULL }; > > This is not: > > struct foo bad = { .flag = 7, .ptr = NULL }; > > (But, of course, it depends on padding size, compiler version, and > architecture. i.e. things remain unreliable.) > > -- -- Thanks, ~Nick Desaulniers
Re: [PATCH 0/2] locking/lockdep, drm: apply new lockdep assert in drm_auth.c
On 7/30/21 12:15 AM, Desmond Cheong Zhi Xi wrote: Hi, Following a discussion on the patch ("drm: use the lookup lock in drm_is_current_master") [1], Peter Zijlstra proposed new lockdep_assert helpers to make it convenient to compose lockdep checks together. This series includes the patch that introduces the new lockdep helpers, then utilizes these helpers in drm_is_current_master_locked in the following patch. Link: https://lore.kernel.org/lkml/20210722092929.244629-2-desmondcheon...@gmail.com/ [1] Best wishes, Desmond Desmond Cheong Zhi Xi (1): drm: add lockdep assert to drm_is_current_master_locked Peter Zijlstra (1): locking/lockdep: Provide lockdep_assert{,_once}() helpers drivers/gpu/drm/drm_auth.c | 6 +++--- include/linux/lockdep.h| 41 +++--- 2 files changed, 24 insertions(+), 23 deletions(-) This patch series looks good to me. Acked-by: Waiman Long Thanks!
Re: [Intel-gfx] [PATCH 1/1] drm/i915: Check if engine has heartbeat when closing a context
On 7/30/2021 02:49, Tvrtko Ursulin wrote: On 30/07/2021 01:13, John Harrison wrote: On 7/28/2021 17:34, Matthew Brost wrote: If an engine associated with a context does not have a heartbeat, ban it immediately. This is needed for GuC submission as a idle pulse doesn't kick the context off the hardware where it then can check for a heartbeat and ban the context. Pulse, that is a request with I915_PRIORITY_BARRIER, does not preempt a running normal priority context? Why does it matter then whether or not heartbeats are enabled - when heartbeat just ends up sending the same engine pulse (eventually, with raising priority)? The point is that the pulse is pointless. See the rest of my comments below, specifically "the context will get resubmitted to the hardware after the pulse completes". To re-iterate... Yes, it preempts the context. Yes, it does so whether heartbeats are enabled or not. But so what? Who cares? You have preempted a context. It is no longer running on the hardware. BUT IT IS STILL A VALID CONTEXT. The backend scheduler will just resubmit it to the hardware as soon as the pulse completes. The only reason this works at all is because of the horrid hack in the execlist scheduler's back end implementation (in __execlists_schedule_in): if (unlikely(intel_context_is_closed(ce) && !intel_engine_has_heartbeat(engine))) intel_context_set_banned(ce); The actual back end scheduler is saying "Is this a zombie context? Is the heartbeat disabled? Then ban it". No other scheduler backend is going to have knowledge of zombie context status or of the heartbeat status. Nor are they going to call back into the higher levels of the i915 driver to trigger a ban operation. Certainly a hardware implemented scheduler is not going to be looking at private i915 driver information to decide whether to submit a context or whether to tell the OS to kill it off instead. For persistence to work with a hardware scheduler (or a non-Intel specific scheduler such as the DRM one), the handling of zombie contexts, banning, etc. *must* be done entirely in the front end. It cannot rely on any backend hacks. That means you can't rely on any fancy behaviour of pulses. If you want to ban a context then you must explicitly ban that context. If you want to ban it at some later point then you need to track it at the top level as a zombie and then explicitly ban that zombie at whatever later point. It's worse than this. If the engine in question is an individual physical engine then sending a pulse (with sufficiently high priority) will pre-empt the engine and kick the context off. However, the GuC Why it is different for physical vs virtual, aren't both just schedulable contexts with different engine masks for what GuC is concerned? Oh, is it a matter of needing to send pulses to all engines which comprise a virtual one? It isn't different. It is totally broken for both. It is potentially more broken for virtual engines because of the question of which engine to pulse. But as stated above, the pulse is pointless anyway so the which engine question doesn't even matter. John. scheduler does not have hacks in it to check the state of the heartbeat or whether a context is actually a zombie or not. Thus, the context will get resubmitted to the hardware after the pulse completes and effectively nothing will have happened. I would assume that the DRM scheduler which we are meant to be switching to for execlist as well as GuC submission is also unlikely to have hacks for zombie contexts and tests for whether the i915 specific heartbeat has been disabled since the context became a zombie. So when that switch happens, this test will also fail in execlist mode as well as GuC mode. The choices I see here are to simply remove persistence completely (it is a basically a bug that became UAPI because it wasn't caught soon enough!) or to implement it in a way that does not require hacks in the back end scheduler. Apparently, the DRM scheduler is expected to allow zombie contexts to persist until the DRM file handle is closed. So presumably we will have to go with option two. That means flagging a context as being a zombie when it is closed but still active. The driver would then add it to a zombie list owned by the DRM client object. When that client object is closed, i915 would go through the list and genuinely kill all the contexts. No back end scheduler hacks required and no intimate knowledge of the i915 heartbeat mechanism required either. John. This patch also updates intel_engine_has_heartbeat to be a vfunc as we now need to call this function on execlists virtual engines too. Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 +++-- drivers/gpu/drm/i915/gt/intel_context_types.h | 2 ++ drivers/gpu/drm/i915/gt/intel_engine.h | 21 ++- .../drm/i9
Re: [Intel-gfx] [PATCH 1/1] drm/i915: Check if engine has heartbeat when closing a context
On Fri, Jul 30, 2021 at 10:49:01AM +0100, Tvrtko Ursulin wrote: > > On 30/07/2021 01:13, John Harrison wrote: > > On 7/28/2021 17:34, Matthew Brost wrote: > > > If an engine associated with a context does not have a heartbeat, ban it > > > immediately. This is needed for GuC submission as a idle pulse doesn't > > > kick the context off the hardware where it then can check for a > > > heartbeat and ban the context. > > Pulse, that is a request with I915_PRIORITY_BARRIER, does not preempt a > running normal priority context? > Yes, in both execlists and GuC submission the contexts gets preempted. With execlists the i915 see the preempt CSB while with GuC submission the GUC sees it. > Why does it matter then whether or not heartbeats are enabled - when > heartbeat just ends up sending the same engine pulse (eventually, with > raising priority)? > With execlists when the request gets resubmitted, there is check if the context is closed and the heartbeat is disabled. If this is true, the context gets banned. See __execlists_schedule_in. With the Guc sense it owns the CSB / resubmission, the heartbeat / closed check doesn't exist to ban the context. > > It's worse than this. If the engine in question is an individual > > physical engine then sending a pulse (with sufficiently high priority) > > will pre-empt the engine and kick the context off. However, the GuC > > Why it is different for physical vs virtual, aren't both just schedulable > contexts with different engine masks for what GuC is concerned? Oh, is it a > matter of needing to send pulses to all engines which comprise a virtual > one? Yes. The whole idle pulse thing is kinda junk. It really makes an assumption that the backend is execlists. We likely have a bit more work here. > > > scheduler does not have hacks in it to check the state of the heartbeat > > or whether a context is actually a zombie or not. Thus, the context will > > get resubmitted to the hardware after the pulse completes and > > effectively nothing will have happened. > > > > I would assume that the DRM scheduler which we are meant to be switching > > to for execlist as well as GuC submission is also unlikely to have hacks > > for zombie contexts and tests for whether the i915 specific heartbeat > > has been disabled since the context became a zombie. So when that switch > > happens, this test will also fail in execlist mode as well as GuC mode. > > > > The choices I see here are to simply remove persistence completely (it > > is a basically a bug that became UAPI because it wasn't caught soon > > enough!) or to implement it in a way that does not require hacks in the > > back end scheduler. Apparently, the DRM scheduler is expected to allow > > zombie contexts to persist until the DRM file handle is closed. So > > presumably we will have to go with option two. > > > > That means flagging a context as being a zombie when it is closed but > > still active. The driver would then add it to a zombie list owned by the > > DRM client object. When that client object is closed, i915 would go > > through the list and genuinely kill all the contexts. No back end > > scheduler hacks required and no intimate knowledge of the i915 heartbeat > > mechanism required either. > > > > John. > > > > > > > > > > This patch also updates intel_engine_has_heartbeat to be a vfunc as we > > > now need to call this function on execlists virtual engines too. > > > > > > Signed-off-by: Matthew Brost > > > --- > > > drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 +++-- > > > drivers/gpu/drm/i915/gt/intel_context_types.h | 2 ++ > > > drivers/gpu/drm/i915/gt/intel_engine.h | 21 ++- > > > .../drm/i915/gt/intel_execlists_submission.c | 14 + > > > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 +- > > > .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 2 -- > > > 6 files changed, 26 insertions(+), 24 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c > > > b/drivers/gpu/drm/i915/gem/i915_gem_context.c > > > index 9c3672bac0e2..b8e01c5ba9e5 100644 > > > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c > > > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c > > > @@ -1090,8 +1090,9 @@ static void kill_engines(struct > > > i915_gem_engines *engines, bool ban) > > > */ > > > for_each_gem_engine(ce, engines, it) { > > > struct intel_engine_cs *engine; > > > + bool local_ban = ban || !intel_engine_has_heartbeat(ce->engine); > > In any case (pending me understanding what's really going on there), why > would this check not be in kill_context with currently does this: > > bool ban = (!i915_gem_context_is_persistent(ctx) || > !ctx->i915->params.enable_hangcheck); > ... This gem_context level check, while the other check is per intel_context. We don't have the intel_context here. > kill_engines(pos, ban); > > So whether to ban decision would b
[PATCH v3 0/5] drm: Provide framebuffer vmap helpers
Add the new helpers drm_gem_fb_vmap() and drm_gem_fb_vunmap(), which provide vmap/vunmap for all BOs of a framebuffer. Convert shadow- plane helpers, gud and vkms. Callers of GEM vmap and vunmap functions used to do the minimum work or get some detail wrong. Therefore shadow-plane helpers were intro- duced to implement the details for all callers. The vmapping code in the shadow-plane helpers is also useful for gud and vkms. So it makes sense to provide rsp helpers. Simply call drm_gem_fb_vmap() to retrieve mappings of all of a framebuffer's BOs. Future work: besides the mapping's addresses, drm_gem_fb_vmap() should also return the mappings with the framebuffer data offset added. These are the addresses were the actual image data is located. A follow-up set of patches will implement this feature. v3: * free instances of struct vkms_writeback_job on cleanup or errors v2: * update commit message for first patch (Maxime) * fix error handling after DRM_FORMAT_MAX_PLANES changes (kernel test robot) * fix includes (kernel test robot) * use [static N] notations for array parameters Thomas Zimmermann (5): drm: Define DRM_FORMAT_MAX_PLANES drm/gem: Provide drm_gem_fb_{vmap,vunmap}() drm/gem: Clear mapping addresses for unused framebuffer planes drm/gud: Map framebuffer BOs with drm_gem_fb_vmap() drm/vkms: Map output framebuffer BOs with drm_gem_fb_vmap() drivers/gpu/drm/drm_gem_atomic_helper.c | 37 +--- drivers/gpu/drm/drm_gem_framebuffer_helper.c | 96 ++-- drivers/gpu/drm/gud/gud_pipe.c | 10 +- drivers/gpu/drm/vkms/vkms_composer.c | 2 +- drivers/gpu/drm/vkms/vkms_drv.h | 6 +- drivers/gpu/drm/vkms/vkms_writeback.c| 28 +++--- include/drm/drm_fourcc.h | 13 ++- include/drm/drm_framebuffer.h| 8 +- include/drm/drm_gem_atomic_helper.h | 3 +- include/drm/drm_gem_framebuffer_helper.h | 6 ++ 10 files changed, 139 insertions(+), 70 deletions(-) base-commit: 2bda1ca4d4acb4892556fec3a7ea1f02afcd40bb prerequisite-patch-id: c2b2f08f0eccc9f5df0c0da49fa1d36267deb11d prerequisite-patch-id: c67e5d886a47b7d0266d81100837557fda34cb24 -- 2.32.0
[PATCH v3 1/5] drm: Define DRM_FORMAT_MAX_PLANES
DRM uses a magic number of 4 for the maximum number of planes per color format. Declare this constant via DRM_FORMAT_MAX_PLANES and update the related code. Some code depends on the length of arrays that are now declared with DRM_FORMAT_MAX_PLANES. Convert it from '4' to ARRAY_SIZE. v2: * mention usage of ARRAY_SIZE() in the commit message (Maxime) * also fix error handling in drm_gem_fb_init_with_funcs() (kernel test robot) * include for DRM_FORMAT_MAX_PLANES Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg --- drivers/gpu/drm/drm_gem_framebuffer_helper.c | 19 +++ include/drm/drm_fourcc.h | 13 + include/drm/drm_framebuffer.h| 8 include/drm/drm_gem_atomic_helper.h | 3 ++- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index 67bc9edc1d98..421e029a6b3e 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -48,7 +48,7 @@ struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb, unsigned int plane) { - if (plane >= 4) + if (plane >= ARRAY_SIZE(fb->obj)) return NULL; return fb->obj[plane]; @@ -62,7 +62,8 @@ drm_gem_fb_init(struct drm_device *dev, struct drm_gem_object **obj, unsigned int num_planes, const struct drm_framebuffer_funcs *funcs) { - int ret, i; + unsigned int i; + int ret; drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd); @@ -86,9 +87,9 @@ drm_gem_fb_init(struct drm_device *dev, */ void drm_gem_fb_destroy(struct drm_framebuffer *fb) { - int i; + size_t i; - for (i = 0; i < 4; i++) + for (i = 0; i < ARRAY_SIZE(fb->obj); i++) drm_gem_object_put(fb->obj[i]); drm_framebuffer_cleanup(fb); @@ -145,8 +146,9 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev, const struct drm_framebuffer_funcs *funcs) { const struct drm_format_info *info; - struct drm_gem_object *objs[4]; - int ret, i; + struct drm_gem_object *objs[DRM_FORMAT_MAX_PLANES]; + unsigned int i; + int ret; info = drm_get_format_info(dev, mode_cmd); if (!info) { @@ -187,9 +189,10 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev, return 0; err_gem_object_put: - for (i--; i >= 0; i--) + while (i > 0) { + --i; drm_gem_object_put(objs[i]); - + } return ret; } EXPORT_SYMBOL_GPL(drm_gem_fb_init_with_funcs); diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 3b138d4ae67e..22aa64d07c79 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -25,6 +25,11 @@ #include #include +/** + * DRM_FORMAT_MAX_PLANES - maximum number of planes a DRM format can have + */ +#define DRM_FORMAT_MAX_PLANES 4u + /* * DRM formats are little endian. Define host endian variants for the * most common formats here, to reduce the #ifdefs needed in drivers. @@ -78,7 +83,7 @@ struct drm_format_info { * triplet @char_per_block, @block_w, @block_h for better * describing the pixel format. */ - u8 cpp[4]; + u8 cpp[DRM_FORMAT_MAX_PLANES]; /** * @char_per_block: @@ -104,7 +109,7 @@ struct drm_format_info { * information from their drm_mode_config.get_format_info hook * if they want the core to be validating the pitch. */ - u8 char_per_block[4]; + u8 char_per_block[DRM_FORMAT_MAX_PLANES]; }; /** @@ -113,7 +118,7 @@ struct drm_format_info { * Block width in pixels, this is intended to be accessed through * drm_format_info_block_width() */ - u8 block_w[4]; + u8 block_w[DRM_FORMAT_MAX_PLANES]; /** * @block_h: @@ -121,7 +126,7 @@ struct drm_format_info { * Block height in pixels, this is intended to be accessed through * drm_format_info_block_height() */ - u8 block_h[4]; + u8 block_h[DRM_FORMAT_MAX_PLANES]; /** @hsub: Horizontal chroma subsampling factor */ u8 hsub; diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index be658ebbec72..f67c5b7bcb68 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -27,12 +27,12 @@ #include #include +#include #include struct drm_clip_rect; struct drm_device; struct drm_file; -struct drm_format_info; struct drm_framebuffer; struct drm_gem_object; @@ -147,7 +147,7 @@ struct drm_framebuffer { * @pitches: Line stride per buffer. For
[PATCH v3 3/5] drm/gem: Clear mapping addresses for unused framebuffer planes
Set the returned mapping address to NULL if a framebuffer plane does not have a BO associated with it. Likewise, ignore mappings of NULL during framebuffer unmap operations. Allows users of the functions to perform unmap operations of certain BOs by themselfes. Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg --- drivers/gpu/drm/drm_gem_framebuffer_helper.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index 243affbad437..02928607a716 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -336,8 +336,10 @@ int drm_gem_fb_vmap(struct drm_framebuffer *fb, for (i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) { obj = drm_gem_fb_get_obj(fb, i); - if (!obj) + if (!obj) { + dma_buf_map_clear(&map[i]); continue; + } ret = drm_gem_vmap(obj, &map[i]); if (ret) goto err_drm_gem_vunmap; @@ -377,6 +379,8 @@ void drm_gem_fb_vunmap(struct drm_framebuffer *fb, obj = drm_gem_fb_get_obj(fb, i); if (!obj) continue; + if (dma_buf_map_is_null(&map[i])) + continue; drm_gem_vunmap(obj, &map[i]); } } -- 2.32.0
[PATCH v3 5/5] drm/vkms: Map output framebuffer BOs with drm_gem_fb_vmap()
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. v3: * free instances of struct vkms_writeback_job on cleanup or errors Signed-off-by: Thomas Zimmermann Reviewed-by: Rodrigo Siqueira Acked-by: Sam Ravnborg --- drivers/gpu/drm/vkms/vkms_composer.c | 2 +- drivers/gpu/drm/vkms/vkms_drv.h | 6 +- drivers/gpu/drm/vkms/vkms_writeback.c | 28 +++ 3 files changed, 22 insertions(+), 14 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(&vaddr_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..425b6c6b8cad 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -65,41 +65,45 @@ 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, &map); + 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; + goto err_kfree; } - job->priv = map.vaddr; + job->priv = vkmsjob; return 0; + +err_kfree: + kfree(vkmsjob); + return ret; } 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(&map, job->priv); - drm_gem_shmem_vunmap(gem_obj, &map); + 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(&vkmsdev->output, false); + kfree(vkmsjob); } static void vkms_wb_atomic_commit(struct drm_connector *conn, -- 2.32.0
[PATCH v3 2/5] drm/gem: Provide drm_gem_fb_{vmap,vunmap}()
Move framebuffer vmap code from shadow-buffered plane state into the new interfaces drm_gem_fb_vmap() and drm_gem_fb_vunmap(). These functions provide mappings of a framebuffer's BOs into kernel address space. No functional changes. v2: * using [static N] for array parameters enables compile-time checks * include for DRM_FORMAT_MAX_PLANES (kernel test robot) Signed-off-by: Thomas Zimmermann Reviewed-by: Sam Ravnborg --- drivers/gpu/drm/drm_gem_atomic_helper.c | 37 +- drivers/gpu/drm/drm_gem_framebuffer_helper.c | 73 include/drm/drm_gem_framebuffer_helper.h | 6 ++ 3 files changed, 82 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c index 26af09b959d4..b1cc19e47165 100644 --- a/drivers/gpu/drm/drm_gem_atomic_helper.c +++ b/drivers/gpu/drm/drm_gem_atomic_helper.c @@ -330,10 +330,7 @@ int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *p { struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); struct drm_framebuffer *fb = plane_state->fb; - struct drm_gem_object *obj; - struct dma_buf_map map; int ret; - size_t i; if (!fb) return 0; @@ -342,27 +339,7 @@ int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *p if (ret) return ret; - for (i = 0; i < ARRAY_SIZE(shadow_plane_state->map); ++i) { - obj = drm_gem_fb_get_obj(fb, i); - if (!obj) - continue; - ret = drm_gem_vmap(obj, &map); - if (ret) - goto err_drm_gem_vunmap; - shadow_plane_state->map[i] = map; - } - - return 0; - -err_drm_gem_vunmap: - while (i) { - --i; - obj = drm_gem_fb_get_obj(fb, i); - if (!obj) - continue; - drm_gem_vunmap(obj, &shadow_plane_state->map[i]); - } - return ret; + return drm_gem_fb_vmap(fb, shadow_plane_state->map); } EXPORT_SYMBOL(drm_gem_prepare_shadow_fb); @@ -374,25 +351,17 @@ EXPORT_SYMBOL(drm_gem_prepare_shadow_fb); * This function implements struct &drm_plane_helper_funcs.cleanup_fb. * This function unmaps all buffer objects of the plane's framebuffer. * - * See drm_gem_prepare_shadow_fb() for more inforamtion. + * See drm_gem_prepare_shadow_fb() for more information. */ void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state) { struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); struct drm_framebuffer *fb = plane_state->fb; - size_t i = ARRAY_SIZE(shadow_plane_state->map); - struct drm_gem_object *obj; if (!fb) return; - while (i) { - --i; - obj = drm_gem_fb_get_obj(fb, i); - if (!obj) - continue; - drm_gem_vunmap(obj, &shadow_plane_state->map[i]); - } + drm_gem_fb_vunmap(fb, shadow_plane_state->map); } EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb); diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index 421e029a6b3e..243affbad437 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -15,6 +15,8 @@ #include #include +#include "drm_internal.h" + #define AFBC_HEADER_SIZE 16 #define AFBC_TH_LAYOUT_ALIGNMENT 8 #define AFBC_HDR_ALIGN 64 @@ -309,6 +311,77 @@ drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file, } EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty); + +/** + * drm_gem_fb_vmap - maps all framebuffer BOs into kernel address space + * @fb: the framebuffer + * @map: returns the mapping's address for each BO + * + * This function maps all buffer objects of the given framebuffer into + * kernel address space and stores them in struct dma_buf_map. If the + * mapping operation fails for one of the BOs, the function unmaps the + * already established mappings automatically. + * + * See drm_gem_fb_vunmap() for unmapping. + * + * Returns: + * 0 on success, or a negative errno code otherwise. + */ +int drm_gem_fb_vmap(struct drm_framebuffer *fb, + struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES]) +{ + struct drm_gem_object *obj; + unsigned int i; + int ret; + + for (i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) { + obj = drm_gem_fb_get_obj(fb, i); + if (!obj) + continue; + ret = drm_gem_vmap(obj, &map[i]); + if (ret) + goto err_drm_gem_vunmap; + } + + return 0; + +err_drm_gem_vunmap: + while (
[PATCH v3 4/5] drm/gud: Map framebuffer BOs with drm_gem_fb_vmap()
Abstract the framebuffer details by mapping its BOs with a call to drm_gem_fb_vmap(). Unmap with drm_gem_fb_vunmap(). The call to drm_gem_fb_vmap() ensures that all BOs are mapped correctly. Gud still only supports single-plane formats. No functional changes. Signed-off-by: Thomas Zimmermann Acked-by: Noralf Trønnes Acked-by: Sam Ravnborg --- drivers/gpu/drm/gud/gud_pipe.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 4d7a26b68a2e..7e009f562b30 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -14,8 +14,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -152,7 +152,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, { struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach; u8 compression = gdrm->compression; - struct dma_buf_map map; + struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; void *vaddr, *buf; size_t pitch, len; int ret = 0; @@ -162,11 +162,11 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, if (len > gdrm->bulk_len) return -E2BIG; - ret = drm_gem_shmem_vmap(fb->obj[0], &map); + ret = drm_gem_fb_vmap(fb, map); if (ret) return ret; - vaddr = map.vaddr + fb->offsets[0]; + vaddr = map[0].vaddr + fb->offsets[0]; ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); if (ret) @@ -225,7 +225,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, end_cpu_access: drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); vunmap: - drm_gem_shmem_vunmap(fb->obj[0], &map); + drm_gem_fb_vunmap(fb, map); return ret; } -- 2.32.0
Re: [PATCH] drm/msm/dp: update is_connected status base on sink count at dp_pm_resume()
Quoting Kuogee Hsieh (2021-07-28 14:30:54) > Currently at dp_pm_resume() is_connected state is decided base on hpd > connection > status only. This will put is_connected in wrongly "true" state at the > scenario > that dongle attached to DUT but without hmdi cable connecting to it. Fix this > problem by adding read sink count from dongle and decided is_connected state > base > on both sink count and hpd connection status. > Please add a Fixes tag. > Signed-off-by: Kuogee Hsieh > --- > drivers/gpu/drm/msm/dp/dp_display.c | 23 +-- > 1 file changed, 21 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > b/drivers/gpu/drm/msm/dp/dp_display.c > index 2b660e9..9bcb261 100644 > --- a/drivers/gpu/drm/msm/dp/dp_display.c > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > @@ -1308,6 +1308,17 @@ static int dp_display_remove(struct platform_device > *pdev) > return 0; > } > > +static int dp_get_sink_count(struct dp_display_private *dp) > +{ > + u8 sink_count; > + > + sink_count = drm_dp_read_sink_count(dp->aux); drm_dp_read_sink_count() returns an int, not a u8. Comparing a u8 to less than zero doesn't make any sense as it isn't signed. > + if (sink_count < 0) > + return 0; > + > + return sink_count; > +} We can drop this function and just have an int count in dp_pm_resume() that is compared to < 0 and then ignored. > + > static int dp_pm_resume(struct device *dev) > { > struct platform_device *pdev = to_platform_device(dev); > @@ -1327,14 +1338,22 @@ static int dp_pm_resume(struct device *dev) > > dp_catalog_ctrl_hpd_config(dp->catalog); > > - status = dp_catalog_link_is_connected(dp->catalog); > + /* > +* set sink to normal operation mode -- D0 > +* before dpcd read > +*/ > + dp_link_psm_config(dp->link, &dp->panel->link_info, false); > > + if ((status = dp_catalog_link_is_connected(dp->catalog))) > + dp->link->sink_count = dp_get_sink_count(dp); Do we need to call drm_dp_read_sink_count_cap() as well? > + else > + dp->link->sink_count = 0; > /* > * can not declared display is connected unless > * HDMI cable is plugged in and sink_count of > * dongle become 1 > */ > - if (status && dp->link->sink_count) Is 'status' used anymore? If not, please remove it. > + if (dp->link->sink_count) > dp->dp_display.is_connected = true; > else > dp->dp_display.is_connected = false;
Re: [PATCH v3 0/8] Support DEVICE_GENERIC memory in migrate_vma_*
Am 2021-07-23 um 6:46 p.m. schrieb Sierra Guiza, Alejandro (Alex): > > On 7/17/2021 2:54 PM, Sierra Guiza, Alejandro (Alex) wrote: >> >> On 7/16/2021 5:14 PM, Felix Kuehling wrote: >>> Am 2021-07-16 um 11:07 a.m. schrieb Theodore Y. Ts'o: On Wed, Jun 23, 2021 at 05:49:55PM -0400, Felix Kuehling wrote: > I can think of two ways to test the changes for > MEMORY_DEVICE_GENERIC in > this patch series in a way that is reproducible without special > hardware and > firmware: > > For the reference counting changes we could use the dax driver > with hmem and > use efi_fake_mem on the kernel command line to create some > DEVICE_GENERIC > pages. I'm open to suggestions for good user mode tests to > exercise dax > functionality on this type of memory. Sorry for the thread necromancy, but now that the merge window is past >>> No worries. Alejandro should have a new version of this series in a few >>> days, with updates to hmm_test and some fixes. >> >> V4 patch series have been sent for review. >> https://marc.info/?l=dri-devel&m=162654971618911&w=2 >> >> Regards, >> Alex Sierra >> >>> >>> Today I test ext4's dax support, without having any $$$ DAX hardware, by using the kernel command line "memmap=4G!9G:memmap=9G!14G" which reserves memory so that creates two pmem device and then I run xfstests with DAX enabled using qemu or using a Google Compute Engine VM, using TEST_DEV=/dev/pmem0 and SCRATCH_DEV=/dev/pmem1. If you can give me a recipe for what kernel configs I should enable, and what magic kernel command line arguments to use, then I'd be able to test your patch set with ext4. >>> That would be great! >>> >>> Regarding kernel config options, it should be the same as what you're >>> using for DAX testing today. We're not changing or adding any Kconfig >>> options. But let me take a stab: >>> >>> ZONE_DEVICE >>> HMM_MIRROR >>> MMU_NOTIFIER >>> DEVICE_PRIVATE (maybe not needed for your test) >>> FS_DAX > Hi Theodore, > I wonder if you had chance to set the kernel configs from Felix to > enable DAX in xfstests. > > I've been trying to test FS DAX on my side using virtio-fs + QEMU. > Unfortunately, Im having some problems setting up the environment with > the guest kernel. Could you share your VM (QEMU or GCE) setup to run > it with xfstests? > > Regards, > Alex S. Hi Theodore, Sorry to keep bugging you. I'm wondering if you've had a chance to test FS DAX with Alex's last patch series? ([PATCH v4 00/13] Support DEVICE_GENERIC memory in migrate_vma_*) I think other than minor cosmetic fixes, this should be ready to merge, if it passes your tests. Thanks, Felix > >>> >>> I'm not sure what you're looking for in terms of kernel command line, >>> other than the memmap options you already found. There are some more >>> options to run hmm_test with fake SPM (DEVICE_GENERIC) memory, but >>> we're >>> already running that ourselves. That will also be in the next revision >>> of this patch series. >> >> In order to run hmm test with generic device type enabled, set the >> following: >> >> kernel config: >> EFI_FAKE_MEMMAP >> RUNTIME_TESTING_MENU >> TEST_HMM=m >> >> Kernel parameters to fake SP memory. The addresses set here are based >> on my system's usable memory enumerated by BIOS-e820 at boot. The >> test requires two SP devices of at least 256MB. >> efi_fake_mem=1G@0x1:0x4,1G@0x14000:0x4 >> >> To run the hmm_test in generic device type pass the SP addresses to >> the sh script. >> sudo ./test_hmm.sh smoke 0x1 0x14000 >> >>> >>> If you can run your xfstests with DAX on top of this patch series, that >>> would be very helpful. That's to make sure the ZONE_DEVICE page >>> refcount >>> changes don't break DAX. >>> >>> Regards, >>> Felix >>> >>> Cheers, - Ted
Re: [PATCH v4 10/13] lib: test_hmm add module param for zone device type
Am 2021-07-28 um 7:45 p.m. schrieb Sierra Guiza, Alejandro (Alex): > > On 7/22/2021 12:26 PM, Jason Gunthorpe wrote: >> On Thu, Jul 22, 2021 at 11:59:17AM -0500, Sierra Guiza, Alejandro >> (Alex) wrote: >>> On 7/22/2021 7:23 AM, Jason Gunthorpe wrote: On Sat, Jul 17, 2021 at 02:21:32PM -0500, Alex Sierra wrote: > In order to configure device generic in test_hmm, two > module parameters should be passed, which correspon to the > SP start address of each device (2) spm_addr_dev0 & > spm_addr_dev1. If no parameters are passed, private device > type is configured. I don't think tests should need configuration like this, is it really necessary? How can people with normal HW run this test? >>> Hi Jason, >>> The idea was to add an easy way to validate the codepaths touched by >>> this >>> patch series, which make modifications to the migration helpers for >>> device >>> generic type pages. We're using CONFIG_EFI_FAKE_MEMMAP to create >>> fake SPM >>> devices inside system memory. No special HW needed. And passing the >>> kernel >>> parameter efi_fake_mem. Ex. efi_fake_mem=1G@0x1:0x4. I >>> should >>> probably need to include a small example of how to set this in the >>> test_hmm.sh >>> usage(). >> I don't think anything about hmm is sensitive to how the pages are >> acquired - you can't create device generic pages without relying on >> FAKE_MEMMAP? > The reason we used fake SPM approach was to have a "special memory" > not managed by Linux (NOT registered as normal system memory). But > also accessible by the CPU. > > For device_generic we cannot allocate new physical addresses. > We need the physical address to match the actual system memory > physical address, so that CPU mappings work as expected. > > Would you recommend to use a different approach? Hi Jason, Sorry it took us so long to respond to your comment. I was on vacation for a week. Then I tried to brain-storm some ways with Alex to simplify hmm_test for device_generic memory, but couldn't really come up with anything simpler. The problem as I see it is, that DEVICE_GENERIC pages for hmm_test should be pages in physical system memory, but they should not be managed by the Linux page allocator. Unlike DEVICE_PRIVATE, we cannot allocate arbitrary physical addresses for these pages (request_free_mem_region). Otherwise we'd break all the assumptions that make those pages directly accessible in user mode virtual address spaces. We could maybe allocate contiguous memory from the page allocator and then register those as device generic pages. But that means, you'd now have two struct pages for the same physical page. I didn't think that would be a good idea. IMHO, reserving some memory for this test with efi_fake_mem is the best way to keep things sane. It does not require any special hardware or firmware. Regards, Felix > > Regards, > Alex Sierra > >> >> Jason
Re: [PATCH 01/64] media: omap3isp: Extract struct group for memcpy() region
On Fri, Jul 30, 2021 at 10:08:03AM -0700, Nick Desaulniers wrote: > On Fri, Jul 30, 2021 at 9:44 AM Kees Cook wrote: > > > > On Fri, Jul 30, 2021 at 12:00:54PM +0300, Dan Carpenter wrote: > > > On Fri, Jul 30, 2021 at 10:38:45AM +0200, David Sterba wrote: > > > > Then is explicit memset the only reliable way accross all compiler > > > > flavors and supported versions? > > > > > > > > > > The = { } initializer works. It's only when you start partially > > > initializing the struct that it doesn't initialize holes. > > > > No, partial works. It's when you _fully_ initialize the struct where the > > padding doesn't get initialized. *sob* > > I'm pretty sure that this has more to do with whether or not the > compiler applies SROA then observes uses of the individual members or > not. Ultimately, it's just not consistent, so thank goodness for -ftrivial-auto-var-init=zero. :) -- Kees Cook
Re: [PATCH 0/7] drm: Extend COMPILE_TEST support to some ARM drivers
Hi Sam, On Thu, Jul 29, 2021 at 06:53:33PM +0200, Sam Ravnborg wrote: > On Wed, Jul 28, 2021 at 06:37:29PM +0300, Laurent Pinchart wrote: > > Hello, > > > > This patch series stems from subsystem-wide changes I wanted to > > compile-test with an ARM64 cross-compiler. My laziness to fire a 32-bit > > ARM build probably resulted in more time being spent writing these > > patches, but hopefully they'll turn out to be useful for more people :-) > > > > Patches 1/7 and 2/7 are fixes for compilation warnings on 64-bit > > platforms in the omapdrm and sti-drm drivers. They are a dependency for > > the Kconfig changes that follow to avoid introducing build warnings, but > > could also be merged before. > > > > Patches 3/7 to 7/7 enable compilation of the imx-dcss, omapdrm, sti-drm, > > tegra-drm and tilcdc drivers on ARM64 with COMPILE_TEST. The patches are > > independent from each other, so they can be picked by their respective > > maintainers. > > > > We could also extend test compilation to more architecture, but I didn't > > want to remove all dependencies on ARM or ARM64 at this point for fear > > or triggering build warnings that I wouldn't be able to catch locally. > > If there's a consensus that fully relaxing the platform requirement is > > better, I can submit a new version that does so and rely on the 0day bot > > to catch issues. > > I have alpha, sparc64, and a few more so we can get pretty good coverage > before it hits -next. It seems that the consensus is to enable COMPILE_TEST on all platforms, so I'll do that. > If we enable more build coverage then please address all W=1 warnings > first. > > I for once always builds with W=1 these days, and I see more and more > warnings sneaking in again. > So lets try to keep the noise level down. H... I build my kernel with -Werror to make sure I catch all warnings. W=1 doesn't play well with that :-S I'll see if I can turn the additional warnings into non-errors, but that may become a game of whack-a-mole. -- Regards, Laurent Pinchart
[PATCH] drm/i915: Fix syncmap memory leak
A small race exists between intel_gt_retire_requests_timeout and intel_timeline_exit which could result in the syncmap not getting free'd. Rather than work to hard to seal this race, simply cleanup the syncmap on fini. unreferenced object 0x88813bc53b18 (size 96): comm "gem_close_race", pid 5410, jiffies 4294917818 (age 1105.600s) hex dump (first 32 bytes): 01 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 00 00 00 00 6b 6b 6b 6b 06 00 00 00 backtrace: [<120b863a>] __sync_alloc_leaf+0x1e/0x40 [i915] [<042f6959>] __sync_set+0x1bb/0x240 [i915] [<90f0e90f>] i915_request_await_dma_fence+0x1c7/0x400 [i915] [<56a48219>] i915_request_await_object+0x222/0x360 [i915] [] i915_gem_do_execbuffer+0x1bd0/0x2250 [i915] [<3c9d830f>] i915_gem_execbuffer2_ioctl+0x405/0xce0 [i915] [ ] drm_ioctl_kernel+0xb0/0xf0 [drm] [ ] drm_ioctl+0x305/0x3c0 [drm] [<8b0d8986>] __x64_sys_ioctl+0x71/0xb0 [<76c362a4>] do_syscall_64+0x33/0x80 [ ] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: Matthew Brost Fixes: 531958f6f357 ("drm/i915/gt: Track timeline activeness in enter/exit") Cc: --- drivers/gpu/drm/i915/gt/intel_timeline.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index c4a126c8caef..1257f4f11e66 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -127,6 +127,15 @@ static void intel_timeline_fini(struct rcu_head *rcu) i915_vma_put(timeline->hwsp_ggtt); i915_active_fini(&timeline->active); + + /* +* A small race exists between intel_gt_retire_requests_timeout and +* intel_timeline_exit which could result in the syncmap not getting +* free'd. Rather than work to hard to seal this race, simply cleanup +* the syncmap on fini. +*/ + i915_syncmap_free(&timeline->sync); + kfree(timeline); } -- 2.28.0
Re: [Intel-gfx] [PATCH 13/14] drm/i915/guc/slpc: Add SLPC selftest
On Thu, Jul 29, 2021 at 07:01:06PM -0700, Vinay Belgaumkar wrote: > 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 > v4: Remove unnecessary header file (Matthew Brost) > v5: checkpatch() and define const for 50/3 (Matthew Brost) > > Signed-off-by: Vinay Belgaumkar > --- > drivers/gpu/drm/i915/gt/intel_rps.c | 1 + > drivers/gpu/drm/i915/gt/selftest_slpc.c | 314 ++ > .../drm/i915/selftests/i915_live_selftests.h | 1 + > 3 files changed, 316 insertions(+) > create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c > > diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c > b/drivers/gpu/drm/i915/gt/intel_rps.c > index 847c6313c1e7..1dabe82d67a6 100644 > --- a/drivers/gpu/drm/i915/gt/intel_rps.c > +++ b/drivers/gpu/drm/i915/gt/intel_rps.c > @@ -2333,4 +2333,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 ..0d9f64461f5d > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c > @@ -0,0 +1,314 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2021 Intel Corporation > + */ > + > +#define NUM_STEPS 5 > +#define H2G_DELAY 5 > +#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 1) > +#define FREQUENCY_REQ_UNIT DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, \ > + GEN9_FREQ_SCALER) > + > +int live_slpc_clamp_min(void *arg); > +int live_slpc_clamp_max(void *arg); No needed. > + > +static int slpc_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 slpc_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) Should be static. > +{ > + struct drm_i915_private *i915 = arg; > + struct intel_gt *gt = &i915->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(&spin, gt)) > + return -ENOMEM; > + > + if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) { > + pr_err("Could not get SLPC max freq\n"); > + return -EIO; > + } > + > + if (intel_guc_slpc_get_min_freq(slpc, &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 = slpc_set_min_freq(slpc, min_freq); > + if (err) > + break; > + > + st_engine_heartbeat_disable(engine); > + > + rq = igt_spinner_create_request(&spin, > + engine->kernel_context, > + MI_NOOP); > + if (IS_ERR(rq)) { > + err = PTR_ERR(rq); > + st_engine_heartbeat_enabl
[PATCH v6 00/14] drm/i915/guc/slpc: Enable GuC based power management features
This series enables Single Loop Power Control (SLPC) feature in GuC. GuC implements various power management algorithms as part of it's operation. These need to be specifically enabled by KMD. They replace the legacy host based management of these features. With this series, we will enable two PM features - GTPerf and GuCRC. These are the Turbo and RC6 equivalents of the host based version. GuC provides various interfaces via host-to-guc messaging, which allows KMD to enable these features after GuC is loaded and GuC submission is enabled. We will specifically disable the IA/GT Balancer and Duty Cycle control features in SLPC. To enable GTPerf, KMD sends a specific h2g message after setting up some shared data structures. As part of this, we will gate host RPS as well. GuC takes over the duties of requesting frequencies by monitoring GPU busyness. We can influence what GuC requests by modifying the min and max frequencies setup by SLPC through the sysfs interfaces that have been exposed by legacy Turbo. SLPC typically requests efficient frequency instead of minimum frequency to optimize performance. It also does not necessarily stick to platform max, and can request frequencies that are much higher since pcode will ultimately grant the appropriate values. However, we will force it to adhere to platform min and max values so as to maintain legacy behavior. SLPC does not have the concept of waitboost, so the boost_freq sysfs will show a '0' value for now. There is a patch forthcoming to ensure the interface is not exposed when SLPC is enabled. GuCRC is enabled similarly through a h2g message. We still need to enable RC6 feature bit (GEN6_RC_CTL_RC6_ENABLE) before we send this out. Render/Media power gating still needs to be enabled by host as before. GuC will take care of setting up the hysterisis values for RC6, host does not need to set this up anymore. v2: Address review comments (Michal W) v3: More comments, optimizations (Michal W) v4: Address comments (Michal W, Matt Roper, Matthew Brost) v5: Address checkpatch issues and some more comments v6: Error checking in patch 11 (Michal W) Signed-off-by: Vinay Belgaumkar Vinay Belgaumkar (14): drm/i915/guc/slpc: Initial definitions for SLPC drm/i915/guc/slpc: Gate Host RPS when SLPC is enabled drm/i915/guc/slpc: Adding SLPC communication interfaces drm/i915/guc/slpc: Allocate, initialize and release SLPC drm/i915/guc/slpc: Enable SLPC and add related H2G events drm/i915/guc/slpc: Remove BUG_ON in guc_submission_disable drm/i915/guc/slpc: Add methods to set min/max frequency drm/i915/guc/slpc: Add get max/min freq hooks drm/i915/guc/slpc: Add debugfs for SLPC info drm/i915/guc/slpc: Enable ARAT timer interrupt drm/i915/guc/slpc: Cache platform frequency limits drm/i915/guc/slpc: Sysfs hooks for SLPC drm/i915/guc/slpc: Add SLPC selftest drm/i915/guc/rc: Setup and enable GuCRC feature drivers/gpu/drm/i915/Makefile | 2 + drivers/gpu/drm/i915/gt/intel_gt.c| 2 +- drivers/gpu/drm/i915/gt/intel_rc6.c | 47 +- drivers/gpu/drm/i915/gt/intel_rps.c | 201 ++ drivers/gpu/drm/i915/gt/intel_rps.h | 10 + drivers/gpu/drm/i915/gt/selftest_slpc.c | 311 + .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 7 +- .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 235 +++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 17 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 4 + .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c| 22 + drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 7 + 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_guc_slpc.c | 626 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 42 ++ .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 29 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 - drivers/gpu/drm/i915/gt/uc/intel_uc.c | 25 +- drivers/gpu/drm/i915/gt/uc/intel_uc.h | 4 + drivers/gpu/drm/i915/i915_pmu.c | 2 +- drivers/gpu/drm/i915/i915_reg.h | 5 + drivers/gpu/drm/i915/i915_sysfs.c | 83 +-- .../drm/i915/selftests/i915_live_selftests.h | 1 + 24 files changed, 1707 insertions(+), 90 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h 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 create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h -- 2.25.0
[PATCH 01/14] drm/i915/guc/slpc: Initial definitions for SLPC
Add macros to check for SLPC support. This feature is currently supported for Gen12+ and enabled whenever GuC submission is enabled/selected. Include templates for SLPC init/fini and enable. v2: Move SLPC helper functions to intel_guc_slpc.c/.h. Define basic template for SLPC structure in intel_guc_slpc_types.h. Fix copyright (Michal W) v3: Review comments (Michal W) v4: Include supported/selected inside slpc struct (Michal W) Reviewed-by: Michal Wajdeczko Signed-off-by: Vinay Belgaumkar Signed-off-by: Sundaresan Sujaritha Signed-off-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc.c| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 45 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 33 ++ .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 16 +++ drivers/gpu/drm/i915/gt/uc/intel_uc.c | 6 ++- drivers/gpu/drm/i915/gt/uc/intel_uc.h | 2 + 8 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index ab7679957623..d8eac4468df9 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_slpc.o \ gt/uc/intel_guc_submission.o \ gt/uc/intel_huc.o \ gt/uc/intel_huc_debugfs.o \ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 979128e28372..39bc3c16057b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -7,6 +7,7 @@ #include "gt/intel_gt_irq.h" #include "gt/intel_gt_pm_irq.h" #include "intel_guc.h" +#include "intel_guc_slpc.h" #include "intel_guc_ads.h" #include "intel_guc_submission.h" #include "i915_drv.h" @@ -157,6 +158,7 @@ void intel_guc_init_early(struct intel_guc *guc) intel_guc_ct_init_early(&guc->ct); intel_guc_log_init_early(&guc->log); intel_guc_submission_init_early(guc); + intel_guc_slpc_init_early(&guc->slpc); mutex_init(&guc->send_mutex); spin_lock_init(&guc->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 a9547069ee7e..7da11a0b6059 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_slpc_types.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_slpc slpc; /* 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_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c new file mode 100644 index ..40950f1bf05c --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021 Intel Corporation + */ + +#include "i915_drv.h" +#include "intel_guc_slpc.h" +#include "gt/intel_gt.h" + +static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc) +{ + return container_of(slpc, struct intel_guc, slpc); +} + +static bool __detect_slpc_supported(struct intel_guc *guc) +{ + /* GuC SLPC is unavailable for pre-Gen12 */ + return guc->submission_supported && + GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12; +} + +static bool __guc_slpc_selected(struct intel_guc *guc) +{ + if (!intel_guc_slpc_is_supported(guc)) + return false; + + return guc->submission_selected; +} + +void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) +{ + struct intel_guc *guc = slpc_to_guc(slpc); + + slpc->supported = __detect_slpc_supported(guc); + slpc->selected = __guc_slpc_selected(guc); +} + +int intel_guc_slpc_init(struct intel_guc_slpc *slpc) +{ + return 0; +} + +void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) +{ +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h new file mode 100644 index ..bc139682ad0f --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef _INTEL_GUC_SLPC_H_ +#define _INTEL_GUC_SLPC_H_ + +#include "intel_guc_
[PATCH 02/14] drm/i915/guc/slpc: Gate Host RPS when SLPC is enabled
Also ensure uc_init is called before we initialize RPS so that we can check for SLPC support. We do not need to enable up/down interrupts when SLPC is enabled. However, we still need the ARAT interrupt, which will be enabled separately later. v2: Explicitly return from intel_rps_enable with slpc check (Matthew B) Reviewed-by: Matthew Brost Signed-off-by: Vinay Belgaumkar Signed-off-by: Sundaresan Sujaritha --- drivers/gpu/drm/i915/gt/intel_gt.c | 2 +- drivers/gpu/drm/i915/gt/intel_rps.c | 23 +++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index a64aa43f7cd9..04dd69bcf6cb 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -41,8 +41,8 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) intel_gt_init_timelines(gt); intel_gt_pm_init_early(gt); - intel_rps_init_early(>->rps); intel_uc_init_early(>->uc); + intel_rps_init_early(>->rps); } int intel_gt_probe_lmem(struct intel_gt *gt) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 0c8e7f2b06f0..a92da4b3bd42 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -37,6 +37,13 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps *rps) return rps_to_gt(rps)->uncore; } +static bool rps_uses_slpc(struct intel_rps *rps) +{ + struct intel_gt *gt = rps_to_gt(rps); + + return intel_uc_uses_guc_slpc(>->uc); +} + static u32 rps_pm_sanitize_mask(struct intel_rps *rps, u32 mask) { return mask & ~rps->pm_intrmsk_mbz; @@ -167,6 +174,8 @@ static void rps_enable_interrupts(struct intel_rps *rps) { struct intel_gt *gt = rps_to_gt(rps); + GEM_BUG_ON(rps_uses_slpc(rps)); + GT_TRACE(gt, "interrupts:on rps->pm_events: %x, rps_pm_mask:%x\n", rps->pm_events, rps_pm_mask(rps, rps->last_freq)); @@ -771,6 +780,8 @@ static int gen6_rps_set(struct intel_rps *rps, u8 val) struct drm_i915_private *i915 = rps_to_i915(rps); u32 swreq; + GEM_BUG_ON(rps_uses_slpc(rps)); + if (GRAPHICS_VER(i915) >= 9) swreq = GEN9_FREQUENCY(val); else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) @@ -861,6 +872,9 @@ void intel_rps_park(struct intel_rps *rps) { int adj; + if (!intel_rps_is_enabled(rps)) + return; + GEM_BUG_ON(atomic_read(&rps->num_waiters)); if (!intel_rps_clear_active(rps)) @@ -1356,6 +1370,9 @@ void intel_rps_enable(struct intel_rps *rps) if (!HAS_RPS(i915)) return; + if (rps_uses_slpc(rps)) + return; + intel_gt_check_clock_frequency(rps_to_gt(rps)); intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); @@ -1829,6 +1846,9 @@ void intel_rps_init(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); + if (rps_uses_slpc(rps)) + return; + if (IS_CHERRYVIEW(i915)) chv_rps_init(rps); else if (IS_VALLEYVIEW(i915)) @@ -1885,6 +1905,9 @@ void intel_rps_init(struct intel_rps *rps) void intel_rps_sanitize(struct intel_rps *rps) { + if (rps_uses_slpc(rps)) + return; + if (GRAPHICS_VER(rps_to_i915(rps)) >= 6) rps_disable_interrupts(rps); } -- 2.25.0
[PATCH 03/14] drm/i915/guc/slpc: Adding SLPC communication interfaces
Add constants and params that are needed to configure SLPC. v2: Add a new abi header for SLPC. Replace bitfields with genmasks. Address other comments from Michal W. v3: Add slpc H2G format in abi, other review commments (Michal W) v4: Update status bits according to latest spec v5: checkpatch() Reviewed-by: Michal Wajdeczko Signed-off-by: Vinay Belgaumkar Signed-off-by: Sundaresan Sujaritha --- .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 1 - .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 235 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 3 + drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 7 + 4 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h 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 d832c8f11c11..ca538e5de940 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,7 +135,6 @@ 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_SLPC_REQUEST = 0x3003, INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502, INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503, diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h new file mode 100644 index ..7a8d4bfc5f6a --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef _GUC_ACTIONS_SLPC_ABI_H_ +#define _GUC_ACTIONS_SLPC_ABI_H_ + +#include +#include "i915_reg.h" + +/** + * DOC: SLPC SHARED DATA STRUCTURE + * + * ++--+--+ + * | CL | Bytes| Description | + * ++==+==+ + * | 1 | 0-3 | SHARED DATA SIZE | + * | +--+--+ + * || 4-7 | GLOBAL STATE | + * | +--+--+ + * || 8-11 | DISPLAY DATA ADDRESS | + * | +--+--+ + * || 12:63| PADDING | + * ++--+--+ + * || 0:63 | PADDING(PLATFORM INFO) | + * ++--+--+ + * | 3 | 0-3 | TASK STATE DATA | + * + +--+--+ + * || 4:63 | PADDING | + * ++--+--+ + * |4-21|0:1087| OVERRIDE PARAMS AND BIT FIELDS | + * ++--+--+ + * || | PADDING + EXTRA RESERVED PAGE | + * ++--+--+ + */ + +/* + * SLPC exposes certain parameters for global configuration by the host. + * These are referred to as override parameters, because in most cases + * the host will not need to modify the default values used by SLPC. + * SLPC remembers the default values which allows the host to easily restore + * them by simply unsetting the override. The host can set or unset override + * parameters during SLPC (re-)initialization using the SLPC Reset event. + * The host can also set or unset override parameters on the fly using the + * Parameter Set and Parameter Unset events + */ + +#define SLPC_MAX_OVERRIDE_PARAMETERS 256 +#define SLPC_OVERRIDE_BITFIELD_SIZE \ + (SLPC_MAX_OVERRIDE_PARAMETERS / 32) + +#define SLPC_PAGE_SIZE_BYTES 4096 +#define SLPC_CACHELINE_SIZE_BYTES 64 +#define SLPC_SHARED_DATA_SIZE_BYTE_HEADER SLPC_CACHELINE_SIZE_BYTES +#define SLPC_SHARED_DATA_SIZE_BYTE_PLATFORM_INFO SLPC_CACHELINE_SIZE_BYTES +#define SLPC_SHARED_DATA_SIZE_BYTE_TASK_STATE SLPC_CACHELINE_SIZE_BYTES +#define SLPC_SHARED_DATA_MODE_DEFN_TABLE_SIZE SLPC_PAGE_SIZE_BYTES +#define SLPC_SHARED_DATA_SIZE_BYTE_MAX (2 * SLPC_PAGE_SIZE_BYTES) + +/* + * Cacheline size aligned (Total size needed for + * SLPM
[PATCH 05/14] drm/i915/guc/slpc: Enable SLPC and add related H2G events
Add methods for interacting with GuC for enabling SLPC. Enable SLPC after GuC submission has been established. GuC load will fail if SLPC cannot be successfully initialized. Add various helper methods to set/unset the parameters for SLPC. They can be set using H2G calls or directly setting bits in the shared data structure. v2: Address several review comments, add new helpers for decoding the SLPC min/max frequencies. Use masks instead of hardcoded constants. (Michal W) v3: Split global_state_to_string function, and check for positive non-zero return value from intel_guc_send() (Michal W) v4: Optimize the stringify function and other comments (Michal W) v5: Enable slpc as well before declaring GuC submission status (Michal W) v6: Checkpatch() Reviewed-by: Michal Wajdeczko Signed-off-by: Vinay Belgaumkar Signed-off-by: Sundaresan Sujaritha --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 202 ++ .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 2 + drivers/gpu/drm/i915/gt/uc/intel_uc.c | 11 + 3 files changed, 215 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 377e09187e9f..f26cf07ec87b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -45,6 +45,40 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) slpc->selected = __guc_slpc_selected(guc); } +static void slpc_mem_set_param(struct slpc_shared_data *data, + u32 id, u32 value) +{ + GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS); + /* +* When the flag bit is set, corresponding value will be read +* and applied by SLPC. +*/ + data->override_params.bits[id >> 5] |= (1 << (id % 32)); + data->override_params.values[id] = value; +} + +static void slpc_mem_set_enabled(struct slpc_shared_data *data, +u8 enable_id, u8 disable_id) +{ + /* +* Enabling a param involves setting the enable_id +* to 1 and disable_id to 0. +*/ + slpc_mem_set_param(data, enable_id, 1); + slpc_mem_set_param(data, disable_id, 0); +} + +static void slpc_mem_set_disabled(struct slpc_shared_data *data, + u8 enable_id, u8 disable_id) +{ + /* +* Disabling a param involves setting the enable_id +* to 0 and disable_id to 1. +*/ + slpc_mem_set_param(data, disable_id, 1); + slpc_mem_set_param(data, enable_id, 0); +} + int intel_guc_slpc_init(struct intel_guc_slpc *slpc) { struct intel_guc *guc = slpc_to_guc(slpc); @@ -65,6 +99,174 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc) return err; } +static u32 slpc_get_state(struct intel_guc_slpc *slpc) +{ + struct slpc_shared_data *data; + + GEM_BUG_ON(!slpc->vma); + + drm_clflush_virt_range(slpc->vaddr, sizeof(u32)); + data = slpc->vaddr; + + return data->header.global_state; +} + +static bool slpc_is_running(struct intel_guc_slpc *slpc) +{ + return slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING; +} + +static int guc_action_slpc_query(struct intel_guc *guc, u32 offset) +{ + u32 request[] = { + GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST, + SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2), + offset, + 0, + }; + int ret; + + ret = intel_guc_send(guc, request, ARRAY_SIZE(request)); + + return ret > 0 ? -EPROTO : ret; +} + +static int slpc_query_task_state(struct intel_guc_slpc *slpc) +{ + struct intel_guc *guc = slpc_to_guc(slpc); + struct drm_i915_private *i915 = slpc_to_i915(slpc); + u32 offset = intel_guc_ggtt_offset(guc, slpc->vma); + int ret; + + ret = guc_action_slpc_query(guc, offset); + if (unlikely(ret)) + drm_err(&i915->drm, "Failed to query task state (%pe)\n", + ERR_PTR(ret)); + + drm_clflush_virt_range(slpc->vaddr, SLPC_PAGE_SIZE_BYTES); + + return ret; +} + +static const char *slpc_global_state_to_string(enum slpc_global_state state) +{ + switch (state) { + case SLPC_GLOBAL_STATE_NOT_RUNNING: + return "not running"; + case SLPC_GLOBAL_STATE_INITIALIZING: + return "initializing"; + case SLPC_GLOBAL_STATE_RESETTING: + return "resetting"; + case SLPC_GLOBAL_STATE_RUNNING: + return "running"; + case SLPC_GLOBAL_STATE_SHUTTING_DOWN: + return "shutting down"; + case SLPC_GLOBAL_STATE_ERROR: + return "error"; + default: + return "unknown"; + } +} + +static const char *slpc_get_state_string(struct intel_guc_slpc *slpc) +{ + return slpc_global_state_to_string(slpc_get_state(slpc)); +} + +static int guc_action_slpc_reset(struct intel_guc *guc, u32 offset) +{ +
[PATCH 06/14] drm/i915/guc/slpc: Remove BUG_ON in guc_submission_disable
The assumption when it was added was that GT would not be holding any gt_pm references. However, uc_init is called from gt_init_hw, which holds a forcewake ref. If SLPC enable fails, we will still be holding this ref, which will result in the BUG_ON. Reviewed-by: Matthew Brost Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 1 file changed, 4 deletions(-) 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 b6338742a594..48cbd800ca54 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2523,10 +2523,6 @@ void intel_guc_submission_enable(struct intel_guc *guc) void intel_guc_submission_disable(struct intel_guc *guc) { - struct intel_gt *gt = guc_to_gt(guc); - - GEM_BUG_ON(gt->awake); /* GT should be parked first */ - /* Note: By the time we're here, GuC may have already been reset */ } -- 2.25.0
[PATCH 04/14] drm/i915/guc/slpc: Allocate, initialize and release SLPC
Allocate data structures for SLPC and functions for initializing on host side. v2: Address review comments (Michal W) v3: Remove unnecessary header includes (Michal W) v4: Rebase v5: Move allocation of shared data into slpc_init() (Michal W) Reviewed-by: Michal Wajdeczko Signed-off-by: Vinay Belgaumkar Signed-off-by: Sundaresan Sujaritha --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 11 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 31 ++- .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 2 ++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 5b0f8c541b69..13d162353b1a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -336,6 +336,12 @@ int intel_guc_init(struct intel_guc *guc) goto err_ct; } + if (intel_guc_slpc_is_used(guc)) { + ret = intel_guc_slpc_init(&guc->slpc); + if (ret) + goto err_submission; + } + /* now that everything is perma-pinned, initialize the parameters */ guc_init_params(guc); @@ -346,6 +352,8 @@ int intel_guc_init(struct intel_guc *guc) return 0; +err_submission: + intel_guc_submission_fini(guc); err_ct: intel_guc_ct_fini(&guc->ct); err_ads: @@ -368,6 +376,9 @@ void intel_guc_fini(struct intel_guc *guc) i915_ggtt_disable_guc(gt->ggtt); + if (intel_guc_slpc_is_used(guc)) + intel_guc_slpc_fini(&guc->slpc); + if (intel_guc_submission_is_used(guc)) intel_guc_submission_fini(guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 40950f1bf05c..377e09187e9f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -12,6 +12,16 @@ static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc) return container_of(slpc, struct intel_guc, slpc); } +static inline struct intel_gt *slpc_to_gt(struct intel_guc_slpc *slpc) +{ + return guc_to_gt(slpc_to_guc(slpc)); +} + +static inline struct drm_i915_private *slpc_to_i915(struct intel_guc_slpc *slpc) +{ + return slpc_to_gt(slpc)->i915; +} + static bool __detect_slpc_supported(struct intel_guc *guc) { /* GuC SLPC is unavailable for pre-Gen12 */ @@ -37,9 +47,28 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc) int intel_guc_slpc_init(struct intel_guc_slpc *slpc) { - return 0; + struct intel_guc *guc = slpc_to_guc(slpc); + struct drm_i915_private *i915 = slpc_to_i915(slpc); + u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data)); + int err; + + GEM_BUG_ON(slpc->vma); + + err = intel_guc_allocate_and_map_vma(guc, size, &slpc->vma, (void **)&slpc->vaddr); + if (unlikely(err)) { + drm_err(&i915->drm, + "Failed to allocate SLPC struct (err=%pe)\n", + ERR_PTR(err)); + return err; + } + + return err; } void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) { + if (!slpc->vma) + return; + + i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h index 769c162305a0..8bd753167234 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h @@ -9,6 +9,8 @@ #include struct intel_guc_slpc { + struct i915_vma *vma; + struct slpc_shared_data *vaddr; bool supported; bool selected; }; -- 2.25.0
[PATCH 09/14] drm/i915/guc/slpc: Add debugfs for SLPC info
This prints out relevant SLPC info from the SLPC shared structure. We will send a H2G message which forces SLPC to update the shared data structure with latest information before reading it. v2: Address review comments (Michal W) v3: Remove unnecessary tasks from slpc_info (Michal W) v4: Rename function to intel_guc_slpc_print_info() (Michal W) v5: checkpatch() Reviewed-by: Michal Wajdeczko Signed-off-by: Vinay Belgaumkar Signed-off-by: Sundaresan Sujaritha --- .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c| 22 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 29 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 3 ++ 3 files changed, 54 insertions(+) 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 72ddfff42f7d..887c8c8f35db 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c @@ -12,6 +12,7 @@ #include "gt/uc/intel_guc_ct.h" #include "gt/uc/intel_guc_ads.h" #include "gt/uc/intel_guc_submission.h" +#include "gt/uc/intel_guc_slpc.h" static int guc_info_show(struct seq_file *m, void *data) { @@ -50,11 +51,32 @@ static int guc_registered_contexts_show(struct seq_file *m, void *data) } DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts); +static int guc_slpc_info_show(struct seq_file *m, void *unused) +{ + struct intel_guc *guc = m->private; + struct intel_guc_slpc *slpc = &guc->slpc; + struct drm_printer p = drm_seq_file_printer(m); + + if (!intel_guc_slpc_is_used(guc)) + return -ENODEV; + + return intel_guc_slpc_print_info(slpc, &p); +} +DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_slpc_info); + +static bool intel_eval_slpc_support(void *data) +{ + struct intel_guc *guc = (struct intel_guc *)data; + + return intel_guc_slpc_is_used(guc); +} + void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root) { static const struct debugfs_gt_file files[] = { { "guc_info", &guc_info_fops, NULL }, { "guc_registered_contexts", &guc_registered_contexts_fops, NULL }, + { "guc_slpc_info", &guc_slpc_info_fops, &intel_eval_slpc_support}, }; if (!intel_guc_is_supported(guc)) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 8bfd1880b2f5..4bf7c150330a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -432,6 +432,35 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) return 0; } +int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p) +{ + struct drm_i915_private *i915 = slpc_to_i915(slpc); + struct slpc_shared_data *data = slpc->vaddr; + struct slpc_task_state_data *slpc_tasks; + intel_wakeref_t wakeref; + int ret = 0; + + GEM_BUG_ON(!slpc->vma); + + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { + ret = slpc_query_task_state(slpc); + + if (!ret) { + slpc_tasks = &data->task_state_data; + + drm_printf(p, "\tSLPC state: %s\n", slpc_get_state_string(slpc)); + drm_printf(p, "\tGTPERF task active: %s\n", + yesno(slpc_tasks->status & SLPC_GTPERF_TASK_ENABLED)); + drm_printf(p, "\tMax freq: %u MHz\n", + slpc_decode_max_freq(slpc)); + drm_printf(p, "\tMin freq: %u MHz\n", + slpc_decode_min_freq(slpc)); + } + } + + return ret; +} + void intel_guc_slpc_fini(struct intel_guc_slpc *slpc) { if (!slpc->vma) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h index 78a7893ce489..3ffd4f2e3151 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h @@ -9,6 +9,8 @@ #include "intel_guc_submission.h" #include "intel_guc_slpc_types.h" +struct drm_printer; + static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc) { return guc->slpc.supported; @@ -33,5 +35,6 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val); int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val); int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val); +int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p); #endif -- 2.25.0
[PATCH 07/14] drm/i915/guc/slpc: Add methods to set min/max frequency
Add param set h2g helpers to set the min and max frequencies for use by SLPC. v2: Address review comments (Michal W) v3: Check for positive error code (Michal W) v4: Print generic error in set_param (Michal W) Reviewed-by: Michal Wajdeczko Signed-off-by: Sundaresan Sujaritha Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 89 + drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + 2 files changed, 91 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index f26cf07ec87b..2635feb59576 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -111,6 +111,21 @@ static u32 slpc_get_state(struct intel_guc_slpc *slpc) return data->header.global_state; } +static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value) +{ + u32 request[] = { + GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST, + SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2), + id, + value, + }; + int ret; + + ret = intel_guc_send(guc, request, ARRAY_SIZE(request)); + + return ret > 0 ? -EPROTO : ret; +} + static bool slpc_is_running(struct intel_guc_slpc *slpc) { return slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING; @@ -148,6 +163,22 @@ static int slpc_query_task_state(struct intel_guc_slpc *slpc) return ret; } +static int slpc_set_param(struct intel_guc_slpc *slpc, u8 id, u32 value) +{ + struct intel_guc *guc = slpc_to_guc(slpc); + struct drm_i915_private *i915 = slpc_to_i915(slpc); + int ret; + + GEM_BUG_ON(id >= SLPC_MAX_PARAM); + + ret = guc_action_slpc_set_param(guc, id, value); + if (ret) + drm_err(&i915->drm, "Failed to set param %d to %u (%pe)\n", + id, value, ERR_PTR(ret)); + + return ret; +} + static const char *slpc_global_state_to_string(enum slpc_global_state state) { switch (state) { @@ -231,6 +262,64 @@ static void slpc_shared_data_reset(struct slpc_shared_data *data) SLPC_PARAM_TASK_DISABLE_DCC); } +/** + * intel_guc_slpc_set_max_freq() - Set max frequency limit for SLPC. + * @slpc: pointer to intel_guc_slpc. + * @val: frequency (MHz) + * + * This function will invoke GuC SLPC action to update the max frequency + * limit for unslice. + * + * Return: 0 on success, non-zero error code on failure. + */ +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val) +{ + struct drm_i915_private *i915 = slpc_to_i915(slpc); + intel_wakeref_t wakeref; + int ret; + + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { + ret = slpc_set_param(slpc, +SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, +val); + + /* Return standardized err code for sysfs calls */ + if (ret) + ret = -EIO; + } + + return ret; +} + +/** + * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC. + * @slpc: pointer to intel_guc_slpc. + * @val: frequency (MHz) + * + * This function will invoke GuC SLPC action to update the min unslice + * frequency. + * + * Return: 0 on success, non-zero error code on failure. + */ +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val) +{ + struct drm_i915_private *i915 = slpc_to_i915(slpc); + intel_wakeref_t wakeref; + int ret; + + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { + ret = slpc_set_param(slpc, +SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, +val); + + /* Return standardized err code for sysfs calls */ + if (ret) + ret = -EIO; + } + + return ret; +} + /* * intel_guc_slpc_enable() - Start SLPC * @slpc: pointer to intel_guc_slpc. diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h index bc139682ad0f..788d87ff7b58 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h @@ -29,5 +29,7 @@ void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc); int intel_guc_slpc_init(struct intel_guc_slpc *slpc); int intel_guc_slpc_enable(struct intel_guc_slpc *slpc); void intel_guc_slpc_fini(struct intel_guc_slpc *slpc); +int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val); +int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); #endif -- 2.25.0
[PATCH 10/14] drm/i915/guc/slpc: Enable ARAT timer interrupt
This interrupt is enabled during RPS initialization, and now needs to be done by SLPC code. It allows ARAT timer expiry interrupts to get forwarded to GuC. v2: Fix comment (Matthew Brost) v3: checkpatch() Reviewed-by: Matthew Brost Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 17 + drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 ++ drivers/gpu/drm/i915/gt/uc/intel_uc.c | 8 3 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 4bf7c150330a..ebabc84d4e39 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -396,6 +396,21 @@ int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val) return ret; } +void intel_guc_pm_intrmsk_enable(struct intel_gt *gt) +{ + u32 pm_intrmsk_mbz = 0; + + /* +* Allow GuC to receive ARAT timer expiry event. +* This interrupt register is setup by RPS code +* when host based Turbo is enabled. +*/ + pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK; + + intel_uncore_rmw(gt->uncore, +GEN6_PMINTRMSK, pm_intrmsk_mbz, 0); +} + /* * intel_guc_slpc_enable() - Start SLPC * @slpc: pointer to intel_guc_slpc. @@ -429,6 +444,8 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) if (unlikely(ret < 0)) return ret; + intel_guc_pm_intrmsk_enable(&i915->gt); + return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h index 3ffd4f2e3151..e45054d5b9b4 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h @@ -9,6 +9,7 @@ #include "intel_guc_submission.h" #include "intel_guc_slpc_types.h" +struct intel_gt; struct drm_printer; static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc) @@ -36,5 +37,6 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val); int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val); int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p); +void intel_guc_pm_intrmsk_enable(struct intel_gt *gt); #endif diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 3e0cd1f05e3b..b104fb7607eb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -655,6 +655,7 @@ void intel_uc_suspend(struct intel_uc *uc) static int __uc_resume(struct intel_uc *uc, bool enable_communication) { struct intel_guc *guc = &uc->guc; + struct intel_gt *gt = guc_to_gt(guc); int err; if (!intel_guc_is_fw_running(guc)) @@ -666,6 +667,13 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication) if (enable_communication) guc_enable_communication(guc); + /* If we are only resuming GuC communication but not reloading +* GuC, we need to ensure the ARAT timer interrupt is enabled +* again. In case of GuC reload, it is enabled during SLPC enable. +*/ + if (enable_communication && intel_uc_uses_guc_slpc(uc)) + intel_guc_pm_intrmsk_enable(gt); + err = intel_guc_resume(guc); if (err) { DRM_DEBUG_DRIVER("Failed to resume GuC, err=%d", err); -- 2.25.0
[PATCH 08/14] drm/i915/guc/slpc: Add get max/min freq hooks
Add helpers to read the min/max frequency being used by SLPC. This is done by send a H2G command which forces SLPC to update the shared data struct which can then be read. These helpers will be used in a sysfs patch later on. v2: Address review comments (Michal W) v3: Return err in case of query failure (Michal W) v4: Move decode_min/max_freq to this patch Reviewed-by: Michal Wajdeczko Signed-off-by: Vinay Belgaumkar Signed-off-by: Sundaresan Sujaritha --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 76 + drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + 2 files changed, 78 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 2635feb59576..8bfd1880b2f5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -245,6 +245,28 @@ static int slpc_reset(struct intel_guc_slpc *slpc) return 0; } +static u32 slpc_decode_min_freq(struct intel_guc_slpc *slpc) +{ + struct slpc_shared_data *data = slpc->vaddr; + + GEM_BUG_ON(!slpc->vma); + + return DIV_ROUND_CLOSEST(REG_FIELD_GET(SLPC_MIN_UNSLICE_FREQ_MASK, + data->task_state_data.freq) * + GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER); +} + +static u32 slpc_decode_max_freq(struct intel_guc_slpc *slpc) +{ + struct slpc_shared_data *data = slpc->vaddr; + + GEM_BUG_ON(!slpc->vma); + + return DIV_ROUND_CLOSEST(REG_FIELD_GET(SLPC_MAX_UNSLICE_FREQ_MASK, + data->task_state_data.freq) * + GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER); +} + static void slpc_shared_data_reset(struct slpc_shared_data *data) { memset(data, 0, sizeof(struct slpc_shared_data)); @@ -291,6 +313,33 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val) return ret; } +/** + * intel_guc_slpc_get_max_freq() - Get max frequency limit for SLPC. + * @slpc: pointer to intel_guc_slpc. + * @val: pointer to val which will hold max frequency (MHz) + * + * This function will invoke GuC SLPC action to read the max frequency + * limit for unslice. + * + * Return: 0 on success, non-zero error code on failure. + */ +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val) +{ + struct drm_i915_private *i915 = slpc_to_i915(slpc); + intel_wakeref_t wakeref; + int ret = 0; + + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { + /* Force GuC to update task data */ + ret = slpc_query_task_state(slpc); + + if (!ret) + *val = slpc_decode_max_freq(slpc); + } + + return ret; +} + /** * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC. * @slpc: pointer to intel_guc_slpc. @@ -320,6 +369,33 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val) return ret; } +/** + * intel_guc_slpc_get_min_freq() - Get min frequency limit for SLPC. + * @slpc: pointer to intel_guc_slpc. + * @val: pointer to val which will hold min frequency (MHz) + * + * This function will invoke GuC SLPC action to read the min frequency + * limit for unslice. + * + * Return: 0 on success, non-zero error code on failure. + */ +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val) +{ + struct drm_i915_private *i915 = slpc_to_i915(slpc); + intel_wakeref_t wakeref; + int ret = 0; + + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { + /* Force GuC to update task data */ + ret = slpc_query_task_state(slpc); + + if (!ret) + *val = slpc_decode_min_freq(slpc); + } + + return ret; +} + /* * intel_guc_slpc_enable() - Start SLPC * @slpc: pointer to intel_guc_slpc. diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h index 788d87ff7b58..78a7893ce489 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h @@ -31,5 +31,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc); void intel_guc_slpc_fini(struct intel_guc_slpc *slpc); int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val); int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val); +int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val); +int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val); #endif -- 2.25.0
[PATCH 11/14] drm/i915/guc/slpc: Cache platform frequency limits
Cache rp0, rp1 and rpn platform limits into SLPC structure for range checking while setting min/max frequencies. Also add "soft" limits which keep track of frequency changes made from userland. These are initially set to platform min and max. v2: Address review comments (Michal W) v3: Formatting (Michal W) v4: Add separate function to parse rp values (Michal W) v5: Perform range checking for set min/max (Michal W) v6: checkpatch() and rename static functions (Michal W) v7: check ret code while setting SLPC limits (Michal W) Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 139 ++ .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 9 ++ drivers/gpu/drm/i915/i915_reg.h | 3 + 3 files changed, 151 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index ebabc84d4e39..65a3e7fdb2b2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -96,6 +96,9 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc) return err; } + slpc->max_freq_softlimit = 0; + slpc->min_freq_softlimit = 0; + return err; } @@ -126,6 +129,17 @@ static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value) return ret > 0 ? -EPROTO : ret; } +static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id) +{ + u32 request[] = { + GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST, + SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2), + id, + }; + + return intel_guc_send(guc, request, ARRAY_SIZE(request)); +} + static bool slpc_is_running(struct intel_guc_slpc *slpc) { return slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING; @@ -179,6 +193,16 @@ static int slpc_set_param(struct intel_guc_slpc *slpc, u8 id, u32 value) return ret; } +static int slpc_unset_param(struct intel_guc_slpc *slpc, + u8 id) +{ + struct intel_guc *guc = slpc_to_guc(slpc); + + GEM_BUG_ON(id >= SLPC_MAX_PARAM); + + return guc_action_slpc_unset_param(guc, id); +} + static const char *slpc_global_state_to_string(enum slpc_global_state state) { switch (state) { @@ -300,6 +324,11 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val) intel_wakeref_t wakeref; int ret; + if (val < slpc->min_freq || + val > slpc->rp0_freq || + val < slpc->min_freq_softlimit) + return -EINVAL; + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { ret = slpc_set_param(slpc, SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ, @@ -310,6 +339,9 @@ int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val) ret = -EIO; } + if (!ret) + slpc->max_freq_softlimit = val; + return ret; } @@ -356,6 +388,11 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val) intel_wakeref_t wakeref; int ret; + if (val < slpc->min_freq || + val > slpc->rp0_freq || + val > slpc->max_freq_softlimit) + return -EINVAL; + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { ret = slpc_set_param(slpc, SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, @@ -366,6 +403,9 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val) ret = -EIO; } + if (!ret) + slpc->min_freq_softlimit = val; + return ret; } @@ -411,6 +451,79 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt) GEN6_PMINTRMSK, pm_intrmsk_mbz, 0); } +static int slpc_set_softlimits(struct intel_guc_slpc *slpc) +{ + int ret = 0; + + /* +* Softlimits are initially equivalent to platform limits +* unless they have deviated from defaults, in which case, +* we retain the values and set min/max accordingly. +*/ + if (!slpc->max_freq_softlimit) + slpc->max_freq_softlimit = slpc->rp0_freq; + else if (slpc->max_freq_softlimit != slpc->rp0_freq) + ret = intel_guc_slpc_set_max_freq(slpc, + slpc->max_freq_softlimit); + + if (unlikely(ret)) + return ret; + + if (!slpc->min_freq_softlimit) + slpc->min_freq_softlimit = slpc->min_freq; + else if (slpc->min_freq_softlimit != slpc->min_freq) + return intel_guc_slpc_set_min_freq(slpc, + slpc->min_freq_softlimit); + + return 0; +} + +static int slpc_ignore_eff_freq(struct intel_guc_slpc *slpc, bool ignore) +{ + int ret = 0; + + if (ignore) { + ret = slpc_set_
[PATCH 12/14] drm/i915/guc/slpc: Sysfs hooks for SLPC
Update the get/set min/max freq hooks to work for SLPC case as well. Consolidate helpers for requested/min/max frequency get/set to intel_rps where the proper action can be taken depending on whether SLPC is enabled. v2: Add wrappers for getting rp0/1/n frequencies, update softlimits in set min/max SLPC functions. Also check for boundary conditions before setting them. v3: Address review comments (Michal W) v4: Add helper for host part of intel_rps_set_freq helpers (Michal W) v5: checkpatch() Reviewed-by: Michal Wajdeczko Acked-by: Michal Wajdeczko Signed-off-by: Vinay Belgaumkar Signed-off-by: Tvrtko Ursulin Signed-off-by: Sujaritha Sundaresan --- drivers/gpu/drm/i915/gt/intel_rps.c | 177 drivers/gpu/drm/i915/gt/intel_rps.h | 10 ++ drivers/gpu/drm/i915/i915_pmu.c | 2 +- drivers/gpu/drm/i915/i915_reg.h | 2 + drivers/gpu/drm/i915/i915_sysfs.c | 83 +++-- 5 files changed, 207 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index a92da4b3bd42..847c6313c1e7 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -37,6 +37,13 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps *rps) return rps_to_gt(rps)->uncore; } +static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps) +{ + struct intel_gt *gt = rps_to_gt(rps); + + return >->uc.guc.slpc; +} + static bool rps_uses_slpc(struct intel_rps *rps) { struct intel_gt *gt = rps_to_gt(rps); @@ -1963,6 +1970,176 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps) return freq; } +u32 intel_rps_read_punit_req(struct intel_rps *rps) +{ + struct intel_uncore *uncore = rps_to_uncore(rps); + + return intel_uncore_read(uncore, GEN6_RPNSWREQ); +} + +static u32 intel_rps_get_req(u32 pureq) +{ + u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT; + + return req; +} + +u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps) +{ + u32 freq = intel_rps_get_req(intel_rps_read_punit_req(rps)); + + return intel_gpu_freq(rps, freq); +} + +u32 intel_rps_get_requested_frequency(struct intel_rps *rps) +{ + if (rps_uses_slpc(rps)) + return intel_rps_read_punit_req_frequency(rps); + else + return intel_gpu_freq(rps, rps->cur_freq); +} + +u32 intel_rps_get_max_frequency(struct intel_rps *rps) +{ + struct intel_guc_slpc *slpc = rps_to_slpc(rps); + + if (rps_uses_slpc(rps)) + return slpc->max_freq_softlimit; + else + return intel_gpu_freq(rps, rps->max_freq_softlimit); +} + +u32 intel_rps_get_rp0_frequency(struct intel_rps *rps) +{ + struct intel_guc_slpc *slpc = rps_to_slpc(rps); + + if (rps_uses_slpc(rps)) + return slpc->rp0_freq; + else + return intel_gpu_freq(rps, rps->rp0_freq); +} + +u32 intel_rps_get_rp1_frequency(struct intel_rps *rps) +{ + struct intel_guc_slpc *slpc = rps_to_slpc(rps); + + if (rps_uses_slpc(rps)) + return slpc->rp1_freq; + else + return intel_gpu_freq(rps, rps->rp1_freq); +} + +u32 intel_rps_get_rpn_frequency(struct intel_rps *rps) +{ + struct intel_guc_slpc *slpc = rps_to_slpc(rps); + + if (rps_uses_slpc(rps)) + return slpc->min_freq; + else + return intel_gpu_freq(rps, rps->min_freq); +} + +static int set_max_freq(struct intel_rps *rps, u32 val) +{ + struct drm_i915_private *i915 = rps_to_i915(rps); + int ret = 0; + + mutex_lock(&rps->lock); + + val = intel_freq_opcode(rps, val); + if (val < rps->min_freq || + val > rps->max_freq || + val < rps->min_freq_softlimit) { + ret = -EINVAL; + goto unlock; + } + + if (val > rps->rp0_freq) + drm_dbg(&i915->drm, "User requested overclocking to %d\n", + intel_gpu_freq(rps, val)); + + rps->max_freq_softlimit = val; + + val = clamp_t(int, rps->cur_freq, + rps->min_freq_softlimit, + rps->max_freq_softlimit); + + /* +* We still need *_set_rps to process the new max_delay and +* update the interrupt limits and PMINTRMSK even though +* frequency request may be unchanged. +*/ + intel_rps_set(rps, val); + +unlock: + mutex_unlock(&rps->lock); + + return ret; +} + +int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val) +{ + struct intel_guc_slpc *slpc = rps_to_slpc(rps); + + if (rps_uses_slpc(rps)) + return intel_guc_slpc_set_max_freq(slpc, val); + else + return set_max_freq(rps, val); +} + +u32 intel_rps_get_min_frequency(struct intel_rps *rps) +{ + struct intel_guc_slpc *slpc = rps_to_slpc(rps); + + if (rps_uses_slpc(rps)) +
[PATCH 13/14] 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 v4: Remove unnecessary header file (Matthew Brost) v5: checkpatch() and define const for 50/3 (Matthew Brost) Reviewed-by: Matthew Brost Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rps.c | 1 + drivers/gpu/drm/i915/gt/selftest_slpc.c | 311 ++ .../drm/i915/selftests/i915_live_selftests.h | 1 + 3 files changed, 313 insertions(+) create mode 100644 drivers/gpu/drm/i915/gt/selftest_slpc.c diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 847c6313c1e7..1dabe82d67a6 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -2333,4 +2333,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 ..9334bad131a2 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021 Intel Corporation + */ + +#define NUM_STEPS 5 +#define H2G_DELAY 5 +#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 1) +#define FREQUENCY_REQ_UNIT DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, \ + GEN9_FREQ_SCALER) + +static int slpc_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 slpc_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; +} + +static int live_slpc_clamp_min(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_gt *gt = &i915->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(&spin, gt)) + return -ENOMEM; + + if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) { + pr_err("Could not get SLPC max freq\n"); + return -EIO; + } + + if (intel_guc_slpc_get_min_freq(slpc, &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 = slpc_set_min_freq(slpc, min_freq); + if (err) + break; + + st_engine_heartbeat_disable(engine); + + rq = igt_spinner_create_request(&spin, + 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(&spin, rq)) { + pr_err("%s: Spinner did not start\n", +
[PATCH 14/14] 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. KMD is still responsible for enabling everything related to Coarse Power Gating though. v2: Address comments (Michal W) v3: Don't set hysterisis values when GuCRC is used (Matt Roper) v4: checkpatch() Reviewed-by: Michal Wajdeczko Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/intel_rc6.c | 47 +++ .../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, 155 insertions(+), 15 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..f6b914438a0b 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -62,20 +62,25 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) u32 pg_enable; int i; - /* 2b: Program RC6 thresholds.*/ - set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85); - set(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150); + /* +* With GuCRC, these parameters are set by GuC +*/ + if (!intel_uc_uses_guc_rc(>->uc)) { + /* 2b: Program RC6 thresholds.*/ + set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85); + set(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150); - set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ - set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_engine(engine, rc6_to_gt(rc6), id) - set(uncore, RING_MAX_IDLE(engine->mmio_base), 10); + set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ + set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ + for_each_engine(engine, rc6_to_gt(rc6), id) + set(uncore, RING_MAX_IDLE(engine->mmio_base), 10); - set(uncore, GUC_MAX_IDLE_COUNT, 0xA); + set(uncore, GUC_MAX_IDLE_COUNT, 0xA); - set(uncore, GEN6_RC_SLEEP, 0); + set(uncore, GEN6_RC_SLEEP, 0); - set(uncore, GEN6_RC6_THRESHOLD, 5); /* 50/125ms per EI */ + set(uncore, GEN6_RC6_THRESHOLD, 5); /* 50/125ms per EI */ + } /* * 2c: Program Coarse Power Gating Policies. @@ -98,11 +103,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 +526,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/d
[RFC PATCH v3 0/6] A drm_plane API to support HDR planes
We are looking to enable HDR support for a couple of single-plane and multi-plane scenarios. To do this effectively we recommend new interfaces to drm_plane. The first patch gives a bit of background on HDR and why we propose these interfaces. This update is only changing the documentation, not the code. We feel that we are not close to anything resembling a consensus for the DRM/KMS API to support (multi-plane) HDR and would like to further the discussion on this. The most important bits in the RFC document are probably the sections on defining HW details and defining SW intentions. We are worried defining intricate HW details on the DRM/KMS level leads to a lot of complexity for compositors which can be avoided by rather defining SW intentions. I will be off for the entire month of August with little time to follow this thread but would like to get my updated thoughts out for discussion anyways. Shashank Sharma will help support this discussion. v3: * Only doc updates (patch 1) * Add sections on single-plane and multi-plane HDR * Describe approach to define HW details vs approach to define SW intentions * Link Jeremy Cline's excellent HDR summaries * Outline intention behind overly verbose doc * Describe FP16 use-case * Clean up links v2: * Moved RFC from cover letter to kernel doc (Daniel Vetter) * Created new color space property instead of abusing color_encoding property (Ville) * Elaborated on need for named transfer functions * Expanded on reason for SDR luminance definition * Dropped 'color' from transfer function naming * Added output_transfer_function on crtc Bhawanpreet Lakha (3): drm/color: Add transfer functions for HDR/SDR on drm_plane drm/color: Add sdr boost property drm/color: Add color space plane property Harry Wentland (3): drm/doc: Color Management and HDR10 RFC drm/color: Add output transfer function to crtc drm/amd/display: reformat YCbCr-RGB conversion matrix Documentation/gpu/rfc/color_intentions.drawio | 1 + Documentation/gpu/rfc/color_intentions.svg| 3 + Documentation/gpu/rfc/colorpipe | 1 + Documentation/gpu/rfc/colorpipe.svg | 3 + Documentation/gpu/rfc/hdr-wide-gamut.rst | 580 ++ Documentation/gpu/rfc/index.rst | 1 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 +- drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 28 +- .../gpu/drm/arm/display/komeda/komeda_crtc.c | 7 +- .../gpu/drm/arm/display/komeda/komeda_plane.c | 6 +- drivers/gpu/drm/arm/malidp_crtc.c | 7 +- drivers/gpu/drm/arm/malidp_planes.c | 6 +- drivers/gpu/drm/armada/armada_crtc.c | 5 +- drivers/gpu/drm/armada/armada_overlay.c | 6 +- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c| 7 +- drivers/gpu/drm/drm_atomic_uapi.c | 8 + drivers/gpu/drm/drm_color_mgmt.c | 177 +- drivers/gpu/drm/i915/display/intel_color.c| 11 +- drivers/gpu/drm/i915/display/intel_color.h| 2 +- drivers/gpu/drm/i915/display/intel_crtc.c | 4 +- drivers/gpu/drm/i915/display/intel_sprite.c | 6 +- .../drm/i915/display/skl_universal_plane.c| 6 +- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 9 +- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 8 +- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 9 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c| 6 +- drivers/gpu/drm/nouveau/dispnv50/head.c | 13 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +- drivers/gpu/drm/omapdrm/omap_plane.c | 6 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c| 7 +- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +- drivers/gpu/drm/stm/ltdc.c| 8 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c| 10 +- drivers/gpu/drm/tidss/tidss_crtc.c| 9 +- drivers/gpu/drm/tidss/tidss_plane.c | 10 +- drivers/gpu/drm/vc4/vc4_crtc.c| 16 +- include/drm/drm_color_mgmt.h | 49 +- include/drm/drm_crtc.h| 20 + include/drm/drm_plane.h | 47 +- 39 files changed, 1074 insertions(+), 60 deletions(-) create mode 100644 Documentation/gpu/rfc/color_intentions.drawio create mode 100644 Documentation/gpu/rfc/color_intentions.svg create mode 100644 Documentation/gpu/rfc/colorpipe create mode 100644 Documentation/gpu/rfc/colorpipe.svg create mode 100644 Documentation/gpu/rfc/hdr-wide-gamut.rst -- 2.32.0
[RFC PATCH v3 1/6] drm/doc: Color Management and HDR10 RFC
Use the new DRM RFC doc section to capture the RFC previously only described in the cover letter at https://patchwork.freedesktop.org/series/89506/ v3: * Add sections on single-plane and multi-plane HDR * Describe approach to define HW details vs approach to define SW intentions * Link Jeremy Cline's excellent HDR summaries * Outline intention behind overly verbose doc * Describe FP16 use-case * Clean up links v2: create this doc v1: n/a Signed-off-by: Harry Wentland --- Documentation/gpu/rfc/color_intentions.drawio | 1 + Documentation/gpu/rfc/color_intentions.svg| 3 + Documentation/gpu/rfc/colorpipe | 1 + Documentation/gpu/rfc/colorpipe.svg | 3 + Documentation/gpu/rfc/hdr-wide-gamut.rst | 580 ++ Documentation/gpu/rfc/index.rst | 1 + 6 files changed, 589 insertions(+) create mode 100644 Documentation/gpu/rfc/color_intentions.drawio create mode 100644 Documentation/gpu/rfc/color_intentions.svg create mode 100644 Documentation/gpu/rfc/colorpipe create mode 100644 Documentation/gpu/rfc/colorpipe.svg create mode 100644 Documentation/gpu/rfc/hdr-wide-gamut.rst diff --git a/Documentation/gpu/rfc/color_intentions.drawio b/Documentation/gpu/rfc/color_intentions.drawio new file mode 100644 index ..d62f3b24e1ec --- /dev/null +++ b/Documentation/gpu/rfc/color_intentions.drawio @@ -0,0 +1 @@ +7VhJl9owDP41OTIvC2E5DjDQvravtMybGY6GmMR9Tpw6Dkt/fZXEWUwgw1CWSy8QfbZkWfokBTRr6G8nHIXeN+Zgqpm6s9WskWaatt2HzwTYZYBhtK0McTlxJFYCM/IHS1CXaEwcHCkbBWNUkFAFlywI8FIoGOKcbdRtK0bVU0Pk4howWyJaR1+JI7z8GrpeLnzCxPXk0T1bLvgo3yyByEMO21Qg60mzhpwxkT352yGmSfDyuGR64yOrhWMcB+IUhcfJ5y/0ZUKC53AxfYnmr31j1TJkNtaIxvLG0luxy0OAHYiIFAMWwNeAszhwcGJYB4lx4TGXBYh+ZSwE0ADwFxZiJ/OJYsEA8oRP5Sr4zHdvif4DxCwH5gC09Ae9REZbeUYm7arSFHPiY4G5BDPHE2+PRkhCEYv5EjeFRTINcReLhn3dIo9QAJiBN3wHehxTJMha9QNJJrrFvkJ1ygh4aOqyavqSMXnN5AzKLWRuSaUy4/BQ8aKEUh58hBMHKNGhEIaBQ9YKNTq/44S9A4G3ooUocQPNekyKEQIOaSnW4cmV36mdKERBjo058vEiXq1SBZptG1d3VODUARU9AMV0H6GkyYWfk0Hv/bPrNpqtRmD2HKsA1i+wf/e9ElXrceMRgWchSim+gb6s1p5M1IjiVWlsjTlksblw6kSXCm2VsLm4qTTMvF961V6pH68MhdQfZbDVvk0T2xKR9TBbSvPKStm6EiHvXBdsUtdpPoatJrOWpSt3n26t+wwoDhwSuP/G+svT3OjVeV5M+yrPO9fiudG7+/Tudrv709vu3Ht69+86vot313vN736NFQeG7IKfNjZPGPfpIKkN+6mexOGd8Xm+9R/Xsz14NnWz2fe9IX3nxmR0zhvABXj5CWzXODgiUUhR4vX3WISxuBkR4T3sPxNvxUT9yNvDNagIYvnzOeue5Z8Q1tNf \ No newline at end of file diff --git a/Documentation/gpu/rfc/color_intentions.svg b/Documentation/gpu/rfc/color_intentions.svg new file mode 100644 index ..2f6b5f5813a3 --- /dev/null +++ b/Documentation/gpu/rfc/color_intentions.svg @@ -0,0 +1,3 @@ + +http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";> +http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink"; version="1.1" width="242px" height="362px" viewBox="-0.5 -0.5 242 362" content="" style="background-color: rgb(255, 255, 255);">http://www.w3.org/TR/SVG11/feature#Extensibility";>http://www.w3.org/1999/xhtml"; style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 98px; height: 1px; padding-top: 48px; margin-left: 10px;">FramebufferRGB8sRGBFramebuffer...http://www.w3.org/TR/SVG11/feature#Extensibility";>http://www.w3.org/1999/xhtml"; style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 178px; margin-left: 9px;">BlendingBlendinghttp://www.w3.org/TR/SVG11/feature#Extensibility";>http://www.w3.org/1999/xhtml"; style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 58px; margin-left: 129px;">FramebufferP010PQBT2020Framebuffer...http://www.w3.org/TR/SVG11/feature#Extensibili 7Vhbl5owEP41PLqHy+LlcdXV9rQ9td09u+tjlAjpCYSGoNhf3wHCJaKsa7289EWYL5nJMPPNDKhZIz+ZchR635iDqWbqTqJZY800bXsAvymwzYG+ZeeAy4mTQ0YFPJE/WIK6RGPi4EjZKBijgoQquGRBgJdCwRDnbKNuWzGqnhoiFzeApyWiTfSVOMKTqKHr1cInTFxPHt235YKPis0SiDzksE0Nsh41a8QZE/mdn4wwTWNXxCXXmxxYLR3jOBDHKDxMP3+hL1MSPIeL2Us0fx0Yq45h5WbWiMbyiaW3YluEADsQESkGLIDLkLM4cHBqWAeJceExlwWIfmUsBNAA8BcWYivziWLBAPKET+Uq+My3b6n+HcSsAOYAdPQ7vULGiTwjl7Z1aYY58bHAXIK546m3ByMkoYjFfInbwiKZhriLRcu+XplH4D9m4A3fgh7HFAmyVv1Akoluua9UnTECHpq6LJqBZIwsGaNgUGEhd0sqVRmHm5oXFZTx4COc2EOJLoUwDB2yVqjR/R2n7B0KnIgOosQNNOshLUYIOKSlXIc7V14zO1GIggKbcOTjRbxaZQo03zap76jBmQMqugeK6S5CSZsLP6fD/vtnN220W43A7ClWAWw+wO6z75SoWo8bjwj8FKKM4htoy2rtyUSNKV5VxtaYQxbbC6dJdKlwrxK2EDe1hln0S6/eK/XDlaGQ+qMMtu6v08QSIvIeZktpXlupWlcqFJ3rjE3qMs3HsNVkNrJ04e7Ta3SfIcWBQwL331h/fpob/SbPy2lf53n3Ujw3+jef3r1eb3d6291bT+/BTcd3+e56q/k9aLBiz5Bd8OPG5hHjPhskjWE/09M4vDM+T7f+43K2h8+mbrb7vjOkb9yYjO5pA7gEzz+B7QYHxyQKKUq9/h6LMBZXIyK8h/1n4rWYqB94e7gEFUGsPp/z7ln9B2E9/gU=
[RFC PATCH v3 3/6] drm/color: Add output transfer function to crtc
We currently have 1D LUTs to define output transfer function but using a 1D LUT is not always the best way to define a transfer function for HW that has ROMs for certain transfer functions, or for HW that has complex PWL definition for accurate LUT definitions. For this reason we're introducing named transfer functions. The original LUT behavior is preserved with the default "1D LUT" transfer function. Signed-off-by: Harry Wentland --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++- .../gpu/drm/arm/display/komeda/komeda_crtc.c | 7 ++- drivers/gpu/drm/arm/malidp_crtc.c | 7 ++- drivers/gpu/drm/armada/armada_crtc.c | 5 +- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c| 7 ++- drivers/gpu/drm/drm_color_mgmt.c | 54 --- drivers/gpu/drm/i915/display/intel_color.c| 11 ++-- drivers/gpu/drm/i915/display/intel_color.h| 2 +- drivers/gpu/drm/i915/display/intel_crtc.c | 4 +- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 9 +++- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 8 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 9 +++- drivers/gpu/drm/nouveau/dispnv50/head.c | 13 +++-- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +++- drivers/gpu/drm/rcar-du/rcar_du_crtc.c| 7 ++- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +- drivers/gpu/drm/stm/ltdc.c| 8 ++- drivers/gpu/drm/tidss/tidss_crtc.c| 9 +++- drivers/gpu/drm/vc4/vc4_crtc.c| 16 +- include/drm/drm_color_mgmt.h | 37 +++-- include/drm/drm_crtc.h| 20 +++ 21 files changed, 208 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 63ddae9c5abe..b6d072211bf9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7343,8 +7343,15 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, acrtc->otg_inst = -1; dm->adev->mode_info.crtcs[crtc_index] = acrtc; - drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES, - true, MAX_COLOR_LUT_ENTRIES); + + res = drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES, +true, MAX_COLOR_LUT_ENTRIES, +BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (res) { + drm_crtc_cleanup(&acrtc->base); + goto fail; + } + drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES); return 0; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 59172acb9738..f364d37232b5 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -626,7 +626,12 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms, crtc->port = kcrtc->master->of_output_port; - drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE); + err = drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE, +BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (err) { + drm_crtc_cleanup(crtc); + return err; + } return err; } diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 494075ddbef6..7af87002c375 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -552,7 +552,12 @@ int malidp_crtc_init(struct drm_device *drm) drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); /* No inverse-gamma: it is per-plane. */ - drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE); + ret = drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE, +BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + drm_crtc_cleanup(&malidp->crtc); + return ret; + } malidp_se_set_enh_coeffs(malidp->dev); diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index b7bb90ae787f..d44a1d4fa475 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -992,7 +992,10 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, if (ret) return ret; - drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256); + ret = drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, , +BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) + return ret; return armada_overlay_
[RFC PATCH v3 5/6] drm/color: Add color space plane property
From: Bhawanpreet Lakha Add color space definitions for BT601, BT709, BT2020, and DCI-P3. Default to BT709, the sRGB color space. Signed-off-by: Bhawanpreet Lakha Signed-off-by: Harry Wentland --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 + .../gpu/drm/arm/display/komeda/komeda_plane.c | 2 + drivers/gpu/drm/arm/malidp_planes.c | 4 +- drivers/gpu/drm/armada/armada_overlay.c | 2 + drivers/gpu/drm/drm_color_mgmt.c | 58 ++- drivers/gpu/drm/i915/display/intel_sprite.c | 2 + .../drm/i915/display/skl_universal_plane.c| 2 + drivers/gpu/drm/nouveau/dispnv04/overlay.c| 2 + drivers/gpu/drm/omapdrm/omap_plane.c | 2 + drivers/gpu/drm/sun4i/sun8i_vi_layer.c| 6 +- drivers/gpu/drm/tidss/tidss_plane.c | 4 ++ include/drm/drm_color_mgmt.h | 16 + include/drm/drm_plane.h | 16 + 13 files changed, 113 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b6d072211bf9..a6dbf1f26787 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7276,8 +7276,10 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, BIT(DRM_COLOR_YCBCR_BT2020), BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | BIT(DRM_COLOR_YCBCR_FULL_RANGE), + BIT(DRM_COLOR_SPACE_BT709), BIT(DRM_TF_SRGB), DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE, + DRM_COLOR_SPACE_BT709, DRM_TF_SRGB); } diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c index 811f79ab6d32..4fb3ad4c691e 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c @@ -302,9 +302,11 @@ static int komeda_plane_add(struct komeda_kms_dev *kms, BIT(DRM_COLOR_YCBCR_BT2020), BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | BIT(DRM_COLOR_YCBCR_FULL_RANGE), + BIT(DRM_COLOR_SPACE_BT709), BIT(DRM_TF_UNDEFINED), DRM_COLOR_YCBCR_BT601, DRM_COLOR_YCBCR_LIMITED_RANGE, + DRM_COLOR_SPACE_BT709, DRM_TF_UNDEFINED); if (err) goto cleanup; diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 98d308262880..0bc80943 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -1023,6 +1023,7 @@ int malidp_de_planes_init(struct drm_device *drm) /* default encoding for YUV->RGB is BT601 NARROW */ enum drm_color_encoding enc = DRM_COLOR_YCBCR_BT601; enum drm_color_range range = DRM_COLOR_YCBCR_LIMITED_RANGE; + enum drm_color_space space = DRM_COLOR_SPACE_BT709; ret = drm_plane_create_color_properties(&plane->base, BIT(DRM_COLOR_YCBCR_BT601) | \ @@ -1030,8 +1031,9 @@ int malidp_de_planes_init(struct drm_device *drm) BIT(DRM_COLOR_YCBCR_BT2020), BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \ BIT(DRM_COLOR_YCBCR_FULL_RANGE), + BIT(DRM_COLOR_SPACE_BT709), BIT(DRM_TF_UNDEFINED), - enc, range, + enc, range, space, DRM_TF_UNDEFINED); if (!ret) /* program the HW registers */ diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index f7792444cb73..e66f2fa72830 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -596,9 +596,11 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709), BIT(DRM_COLOR_YCBCR_LIMITED_RANGE), + BIT(DRM_COLOR_SPACE_BT709), BIT(DRM_TF_UNDEFINED), DEFAULT_ENCODING, DRM_COLOR_YCBCR_LIMITED_RANGE, + DRM_COLOR_SPA
[RFC PATCH v3 6/6] drm/amd/display: reformat YCbCr-RGB conversion matrix
Show the CSC matrixes in a 4x3 format. Signed-off-by: Harry Wentland --- drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 28 + 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index 00fc81431b43..345b3956425a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -55,22 +55,30 @@ struct dpp_input_csc_matrix { static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] = { {COLOR_SPACE_SRGB, - {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {0x2000, 0, 0, 0, + 0, 0x2000, 0, 0, + 0, 0, 0x2000, 0} }, {COLOR_SPACE_SRGB_LIMITED, - {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {0x2000, 0, 0, 0, + 0, 0x2000, 0, 0, + 0, 0, 0x2000, 0} }, {COLOR_SPACE_YCBCR601, - {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, - 0, 0x2000, 0x38b4, 0xe3a6} }, + {0x2cdd, 0x2000, 0, 0xe991, +0xe926, 0x2000, 0xf4fd, 0x10ef, + 0, 0x2000, 0x38b4, 0xe3a6} }, {COLOR_SPACE_YCBCR601_LIMITED, - {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, - 0, 0x2568, 0x40de, 0xdd3a} }, + {0x3353, 0x2568, 0, 0xe400, +0xe5dc, 0x2568, 0xf367, 0x1108, + 0, 0x2568, 0x40de, 0xdd3a} }, {COLOR_SPACE_YCBCR709, - {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, - 0x2000, 0x3b61, 0xe24f} }, + {0x3265, 0x2000, 0, 0xe6ce, +0xf105, 0x2000, 0xfa01, 0xa7d, + 0, 0x2000, 0x3b61, 0xe24f} }, {COLOR_SPACE_YCBCR709_LIMITED, - {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, - 0x2568, 0x43ee, 0xdbb2} } + {0x39a6, 0x2568, 0, 0xe0d6, +0xeedd, 0x2568, 0xf925, 0x9a8, + 0, 0x2568, 0x43ee, 0xdbb2} } }; struct dpp_grph_csc_adjustment { -- 2.32.0
[RFC PATCH v3 4/6] drm/color: Add sdr boost property
From: Bhawanpreet Lakha SDR is typically mastered at 200 nits and HDR is mastered at up to 10,000 nits. Due to this luminance range difference if we blend a SDR and HDR plane together, we can run into problems where the HDR plane is too bright or the SDR plane is too dim A common solution to this problem is to boost the SDR plane so that its not too dim. This patch introduces a "sdr_white_level" property, this property can be used by the userspace to boost the SDR content luminance. The boost value is an explicit luminance value in nits. This allows the userspace to set the maximum white level for the SDR plane. v2: - fix type in description Signed-off-by: Bhawanpreet Lakha Signed-off-by: Harry Wentland --- drivers/gpu/drm/drm_atomic_uapi.c | 4 drivers/gpu/drm/drm_color_mgmt.c | 17 + include/drm/drm_color_mgmt.h | 6 ++ include/drm/drm_plane.h | 15 ++- 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 9582515dd12e..e5a193657f7d 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -598,6 +598,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, state->color_range = val; } else if (property == plane->transfer_function_property) { state->transfer_function = val; + } else if (property == plane->sdr_white_level_property) { + state->sdr_white_level = val; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, &state->fb_damage_clips, @@ -666,6 +668,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->color_range; } else if (property == plane->transfer_function_property) { *val = state->transfer_function; + } else if (property == plane->sdr_white_level_property) { + *val = state->sdr_white_level; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 196544951ab7..44842ba0454d 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -556,6 +556,23 @@ const char *drm_get_color_range_name(enum drm_color_range range) return color_range_name[range]; } +int drm_plane_create_sdr_white_level_property(struct drm_plane *plane){ + + struct drm_property *prop; + + prop = drm_property_create_range(plane->dev, 0, "SDR_WHITE_LEVEL", 0, UINT_MAX); + + if (!prop) + return -ENOMEM; + + plane->sdr_white_level_property = prop; + drm_object_attach_property(&plane->base, prop, DRM_DEFAULT_SDR_WHITE_LEVEL); + + if (plane->state) + plane->state->sdr_white_level = DRM_DEFAULT_SDR_WHITE_LEVEL; + + return 0; +} /** * drm_get_transfer_function - return a string for transfer function * @tf: transfer function to compute name of diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index 408561acdb3d..2a356a9601df 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h @@ -26,6 +26,12 @@ #include #include +/** + * Default SDR white level in nits. Although there is no standard SDR nit level, 200 + * is chosen as the default since that is the generally accepted value. + */ +#define DRM_DEFAULT_SDR_WHITE_LEVEL 200 + struct drm_crtc; struct drm_plane; diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index cff56994513f..93ee308a46af 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -187,6 +187,11 @@ struct drm_plane_state { * format for a proper HDR color/luminance output. */ enum drm_transfer_function transfer_function; + /** +* @sdr_white_level: +* SDR white level boost for HDR+SDR multi plane usecases. max white level in nits +*/ + unsigned int sdr_white_level; /** * @fb_damage_clips: * @@ -757,7 +762,15 @@ struct drm_plane { * See drm_plane_create_color_properties(). */ struct drm_property *transfer_function_property; - + /** +* @sdr_white_level: +* +* Optional sdr_white_level. When HDR and SDR are combined in multi plane +* overlay cases, the sdr plane will be very dim. This property allows +* the driver to boost the sdr plane's white level. The value should be +* max white level in nits. +*/ + struct drm_property *sdr_white_level_property; /** * @scaling_filter_property: property to apply a particular filter while * scaling. -- 2.32.0
[RFC PATCH v3 2/6] drm/color: Add transfer functions for HDR/SDR on drm_plane
From: Bhawanpreet Lakha Due to the way displays and human vision work it is most effective to encode luminance information in a non-linear space. For SDR this non-linear mapping is assumed to roughly use a gamma 2.2 curve. This was due to the way CRTs worked and was fine for SDR content with a low luminance range. The large luminance range (0-10,000 nits) for HDR exposes some short-comings of a simple gamma curve that have been addressed through various Electro-Optical Transfer Functions (EOTFs). Rather than assuming how framebuffer content is encoded we want to make sure userspace presenting HDR content is explicit about the EOTF of the content, so a driver can decide whether the content can be supported or not. This Patch adds common transfer functions for SDR/HDR. These can be used to communicate with the driver regarding the transformation to use for a given plane. enums added: DRM_TF_UNDEFINED the legacy case where the TF in/out of blending space is undefined DRM_TF_SRGB roughly 2.4 gamma with initial linear section DRM_TF_BT709 Similar to Gamma 2.2-2.8 DRM_TF_PQ2084 most common tf used for HDR video (HDR10/Dolby). Can support up to 10,000 nits The usage is similar to color_encoding and color_range where the driver can specify the default and supported tfs and pass it into drm_plane_create_color_properties(). v2: - drop "color" from transfer function name (Harry) - add DRM_TF_UNDEFINED enum as legacy default (Harry) Signed-off-by: Bhawanpreet Lakha Signed-off-by: Harry Wentland --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- .../gpu/drm/arm/display/komeda/komeda_plane.c | 4 +- drivers/gpu/drm/arm/malidp_planes.c | 4 +- drivers/gpu/drm/armada/armada_overlay.c | 4 +- drivers/gpu/drm/drm_atomic_uapi.c | 4 ++ drivers/gpu/drm/drm_color_mgmt.c | 64 +-- drivers/gpu/drm/i915/display/intel_sprite.c | 4 +- .../drm/i915/display/skl_universal_plane.c| 4 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c| 4 +- drivers/gpu/drm/omapdrm/omap_plane.c | 4 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c| 4 +- drivers/gpu/drm/tidss/tidss_plane.c | 6 +- include/drm/drm_color_mgmt.h | 18 +- include/drm/drm_plane.h | 16 + 14 files changed, 128 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b5b5ccf0ed71..63ddae9c5abe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7276,7 +7276,9 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, BIT(DRM_COLOR_YCBCR_BT2020), BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | BIT(DRM_COLOR_YCBCR_FULL_RANGE), - DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE); + BIT(DRM_TF_SRGB), + DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE, + DRM_TF_SRGB); } supported_rotations = diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c index d63d83800a8a..811f79ab6d32 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c @@ -302,8 +302,10 @@ static int komeda_plane_add(struct komeda_kms_dev *kms, BIT(DRM_COLOR_YCBCR_BT2020), BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | BIT(DRM_COLOR_YCBCR_FULL_RANGE), + BIT(DRM_TF_UNDEFINED), DRM_COLOR_YCBCR_BT601, - DRM_COLOR_YCBCR_LIMITED_RANGE); + DRM_COLOR_YCBCR_LIMITED_RANGE, + DRM_TF_UNDEFINED); if (err) goto cleanup; diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 8c2ab3d653b7..98d308262880 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -1030,7 +1030,9 @@ int malidp_de_planes_init(struct drm_device *drm) BIT(DRM_COLOR_YCBCR_BT2020), BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \ BIT(DRM_COLOR_YCBCR_FULL_RANGE), - enc, range); + BIT(DRM_TF_UNDEFINED), + enc, range, + DRM_TF_UNDEFINED); if (!ret) /* program the HW registers */ malidp_de_set_
Re: [PATCH 3/3] dma-buf: nuke SW_SYNC debugfs files
On Thu, Jul 29, 2021 at 9:52 PM John Stultz wrote: > > On Thu, Jul 29, 2021 at 12:24 AM Daniel Vetter wrote: > > > > On Thu, Jul 29, 2021 at 09:03:30AM +0200, Christian König wrote: > > > As we now knew controlling dma_fence synchronization from userspace is > > > extremely dangerous and can not only deadlock drivers but trivially also > > > the > > > whole kernel memory management. > > > > > > Entirely remove this option. We now have in kernel unit tests to exercise > > > the > > > dma_fence framework and it's containers. > > > > > > Signed-off-by: Christian König > > > > There's also igts for this, and Android heavily uses this. So I'm not sure > > we can just nuke it. > > Eeeeh... I don't think that's actually the case anymore. As of > android12-5.10 CONFIG_SW_SYNC is not turned on. > Further, Android is disabling debugfs in their kernels as it exposes > too much to userland. > > That said, there still are some references to it: > > https://cs.android.com/android/platform/superproject/+/master:system/core/libsync/sync.c;l=416 Hello, Like John mentioned, CONFIG_SW_SYNC is not turned on for the *-5.4 and newer branches in the Android Common Kernel. The references in AOSP are only in place to support devices with older kernels upgrading to newer Android versions. Regards, Hridya > > But it looks like the actual users are only kselftest and igt? > > Adding Alistair, Hridya and Sandeep in case they have more context. > > thanks > -john
[PATCH v2 0/6] eDP: Support probing eDP panels dynamically instead of hardcoding
The goal of this patch series is to move away from hardcoding exact eDP panels in device tree files. As discussed in the various patches in this series (I'm not repeating everything here), most eDP panels are 99% probable and we can get that last 1% by allowing two "power up" delays to be specified in the device tree file and then using the panel ID (found in the EDID) to look up additional power sequencing delays for the panel. This patch series is the logical contiunation of a previous patch series where I proposed solving this problem by adding a board-specific compatible string [1]. In the discussion that followed it sounded like people were open to something like the solution proposed in this new series. In version 2 I got rid of the idea that we could have a "fallback" compatible string that we'd use if we didn't recognize the ID in the EDID. This simplifies the bindings a lot and the implementation somewhat. As a result of not having a "fallback", though, I'm not confident in transitioning any existing boards over to this since the panel will totally fail to work if we don't recognize the ID from the EDID and I can't guarantee that I've seen every panel that might have shipped on an existing product. The plan is to use "edp-panel" only on new boards or new revisions of old boards where we can guarantee that every EDID that ships out of the factory has an ID in the table. Version 2 of this series is also rebased upon my other series for the Samsung ATNA33XC20 panel [2] since they both touch the "delay" structure and it seems likely that the Samsung panel series will land first. [1] https://lore.kernel.org/r/yfkqaxomowyye...@google.com/ [2] https://lore.kernel.org/r/20210730154605.2843418-1-diand...@chromium.org/ Changes in v2: - No longer allow fallback to panel-simple. - Add "-ms" suffix to delays. - Rebased atop revert of delays between GPIO & regulator - Don't support a "fallback" panel. Probed panels must be probed. - Not based on patch to copy "desc"--just allocate for probed panels. - Add "-ms" suffix to delays. Douglas Anderson (6): dt-bindings: drm/panel-simple: Introduce generic eDP panels drm/edid: Break out reading block 0 of the EDID drm/edid: Allow the querying/working with the panel ID from the EDID drm/panel-simple: Don't re-read the EDID every time we power off the panel drm/panel-simple: Split the delay structure out of the panel description drm/panel-simple: Implement generic "edp-panel"s probed by EDID .../bindings/display/panel/panel-edp.yaml | 188 ++ drivers/gpu/drm/drm_edid.c| 113 +- drivers/gpu/drm/panel/panel-simple.c | 352 +- include/drm/drm_edid.h| 47 +++ 4 files changed, 586 insertions(+), 114 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/panel/panel-edp.yaml -- 2.32.0.554.ge1b32706d8-goog
[PATCH v2 1/6] dt-bindings: drm/panel-simple: Introduce generic eDP panels
eDP panels generally contain almost everything needed to control them in their EDID. This comes from their DP heritage were a computer needs to be able to properly control pretty much any DP display that's plugged into it. The one big issue with eDP panels and the reason that we need a panel driver for them is that the power sequencing can be different per panel. While it is true that eDP panel sequencing can be arbitrarily complex, in practice it turns out that many eDP panels are compatible with just some slightly different delays. See the contents of the bindings file introduced in this patch for some details. The fact that eDP panels are 99% probable and that the power sequencing (especially power up) can be compatible between many panels means that there's a constant desire to plug multiple different panels into the same board. This could be for second sourcing purposes or to support multiple SKUs (maybe a 11" and a 13", for instance). As discussed [1], it should be OK to support this by adding two properties to the device tree to specify the delays needed for powering up the panel the first time. We'll create a new "edp-panel" bindings file and define the two delays that might need to be specified. NOTE: in the vast majority of the cases (HPD is hooked up and isn't glitchy or is debounced) even these delays aren't needed. [1] https://lore.kernel.org/r/CAD=FV=vzyompwqzzwdhjgh5cjjww_ecm-wqveivz-bdgxjp...@mail.gmail.com Signed-off-by: Douglas Anderson --- Changes in v2: - No longer allow fallback to panel-simple. - Add "-ms" suffix to delays. .../bindings/display/panel/panel-edp.yaml | 188 ++ 1 file changed, 188 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/panel-edp.yaml diff --git a/Documentation/devicetree/bindings/display/panel/panel-edp.yaml b/Documentation/devicetree/bindings/display/panel/panel-edp.yaml new file mode 100644 index ..6a621376ff86 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/panel-edp.yaml @@ -0,0 +1,188 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/panel-edp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Probable (via DP AUX / EDID) eDP Panels with simple poweron sequences + +maintainers: + - Douglas Anderson + +description: | + This binding file can be used to indicate that an eDP panel is connected + to a Embedded DisplayPort AUX bus (see display/dp-aux-bus.yaml) without + actually specifying exactly what panel is connected. This is useful for + the case that more than one different panel could be connected to the + board, either for second-sourcing purposes or to support multiple SKUs + with different LCDs that hook up to a common board. + + As per above, a requirement for using this binding is that the panel is + represented under the DP AUX bus. This means that we can use any + information provided by the DP AUX bus (including the EDID) to identify + the panel. We can use this to identify display size, resolution, and + timings among other things. + + One piece of information about eDP panels that is typically _not_ + provided anywhere on the DP AUX bus is the power sequencing timings. + This is the reason why, historically, we've always had to explicitly + list eDP panels. We solve that here with two tricks. The "worst case" + power on timings for any panels expected to be connected to a board are + specified in these bindings. Once we've powered on, it's expected that + the operating system will lookup the panel in a table (based on EDID + information) to figure out other power sequencing timings. + + eDP panels in general can have somewhat arbitrary power sequencing + requirements. However, even though it's arbitrary in general, the + vast majority of panel datasheets have a power sequence diagram that + looks the exactly the same as every other panel. Each panel datasheet + cares about different timings in this diagram but the fact that the + diagram is so similar means we can come up with a single driver to + handle it. + + These diagrams all look roughly like this, sometimes labeled with + slightly different numbers / lines but all pretty much the same + sequence. This is because much of this diagram comes straight from + the eDP Standard. + +__ + Vdd ___/::\ / + _/:: \_/ + ::: :<--T10-->::: +:+---+-+-+ + eDP ---+ Black video | Src vid | Blk vid + + Display :+---+-+-+ +: ___:_:_: + HPD :|
[PATCH v2 4/6] drm/panel-simple: Don't re-read the EDID every time we power off the panel
The simple-panel driver is for panels that are not hot-pluggable at runtime. Let's keep our cached EDID around until driver unload. Signed-off-by: Douglas Anderson --- (no changes since v1) drivers/gpu/drm/panel/panel-simple.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index ff8b59471c71..b06bf30c65d0 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -350,9 +350,6 @@ static int panel_simple_suspend(struct device *dev) regulator_disable(p->supply); p->unprepared_time = ktime_get(); - kfree(p->edid); - p->edid = NULL; - return 0; } @@ -834,6 +831,9 @@ static int panel_simple_remove(struct device *dev) if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc)) put_device(&panel->ddc->dev); + kfree(panel->edid); + panel->edid = NULL; + return 0; } -- 2.32.0.554.ge1b32706d8-goog
[PATCH v2 3/6] drm/edid: Allow the querying/working with the panel ID from the EDID
EDIDs have 32-bits worth of data which is intended to be used to uniquely identify the make/model of a panel. This has historically been used only internally in the EDID processing code to identify quirks with panels. We'd like to use this panel ID in panel-simple to identify which panel is hooked up and from that information figure out power sequence timings. Let's expose this information from the EDID code and also allow it to be accessed early, before a connector has been created. To make matching in the panel-simple code easier, we'll return the panel ID as a 32-bit value. We'll provide some functions for converting this value back and forth to something more human readable. Signed-off-by: Douglas Anderson --- (no changes since v1) drivers/gpu/drm/drm_edid.c | 51 ++ include/drm/drm_edid.h | 47 +++ 2 files changed, 98 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a623a80f7edb..43633e083ecd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2086,6 +2086,57 @@ struct edid *drm_get_edid(struct drm_connector *connector, } EXPORT_SYMBOL(drm_get_edid); +/** + * drm_get_panel_id - Get a panel's ID through DDC + * @adapter: I2C adapter to use for DDC + * + * This function reads the first block of the EDID of a panel and (assuming + * that the EDID is valid) extracts the ID out of it. The ID is a 32-bit value + * (16 bits of manufacturer ID and 16 bits of per-manufacturer ID) that's + * supposed to be different for each different modem of panel. + * + * This function is intended to be used during early probing on devices where + * more than one panel might be present. Because of its intended use it must + * assume that the EDID of the panel is correct, at least as far as the ID + * is concerned (in other words, we don't process any overrides here). + * + * NOTE: it's expected that this function and drm_do_get_edid() will both + * be read the EDID, but there is no caching between them. Since we're only + * reading the first block, hopefully this extra overhead won't be too big. + * + * Return: A 32-bit ID that should be different for each make/model of panel. + * See the functions encode_edid_id() and decode_edid_id() for some + * details on the structure of this ID. + */ +u32 drm_get_panel_id(struct i2c_adapter *adapter) +{ + struct edid *edid; + u32 val; + + edid = drm_do_get_edid_blk0(drm_do_probe_ddc_edid, adapter, NULL, NULL); + + /* +* There are no manufacturer IDs of 0, so if there is a problem reading +* the EDID then we'll just return 0. +*/ + if (IS_ERR_OR_NULL(edid)) + return 0; + + /* +* In theory we could try to de-obfuscate this like edid_get_quirks() +* does, but it's easier to just deal with a 32-bit number. +*/ + val = (u32)edid->mfg_id[0] << 24 | + (u32)edid->mfg_id[1] << 16 | + (u32)edid->prod_code[0] << 8 | + (u32)edid->prod_code[1] << 0; + + kfree(edid); + + return val; +} +EXPORT_SYMBOL(drm_get_panel_id); + /** * drm_get_edid_switcheroo - get EDID data for a vga_switcheroo output * @connector: connector we're probing diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 759328a5eeb2..75a23caa7709 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -508,6 +508,52 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld) return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK; } +/** + * encode_edid_id - Encode an ID for matching against drm_get_panel_id() + * @vend_chr_0: First character of the vendor string. + * @vend_chr_2: Second character of the vendor string. + * @vend_chr_3: Third character of the vendor string. + * @product_id: The 16-bit product ID. + * + * This is a macro so that it can be calculated at compile time and used + * as an initializer. + * + * For instance: + * encode_edid_id('B', 'O', 'E', 0x2d08) => 0x09e52d08 + * + * Return: a 32-bit ID per panel. + */ +#define encode_edid_id(vend_chr_0, vend_chr_1, vend_chr_2, product_id) \ + u32)(vend_chr_0) - '@') & 0x1f) << 26 | \ +(((u32)(vend_chr_1) - '@') & 0x1f) << 21 | \ +(((u32)(vend_chr_2) - '@') & 0x1f) << 16 | \ +((product_id) & 0x)) + +/** + * decode_edid_id - Decode a panel ID from encode_edid_id() + * @panel_id: The panel ID to decode. + * @vend: A 4-byte buffer to store the 3-letter vendor string plus a '\0' + * termination + * @product_id: The product ID will be returned here. + * + * For instance, after: + * decode_edid_id(0x09e52d08, vend, &product_id) + * These will be true: + * vend[0] = 'B' + * vend[1] = 'O' + * vend[2] = 'E' + * vend[3] = '\0' + * product_id = 0x2d08 + */ +static inline void decode_edid_id(u32 panel_id, char vend[4], u16 *product_id) +{ + *product_id = (
[PATCH v2 2/6] drm/edid: Break out reading block 0 of the EDID
A future change wants to be able to read just block 0 of the EDID, so break it out of drm_do_get_edid() into a sub-function. This is intended to be a no-op change--just code movement. Signed-off-by: Douglas Anderson --- (no changes since v1) drivers/gpu/drm/drm_edid.c | 62 +++--- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 81d5f2524246..a623a80f7edb 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1905,6 +1905,43 @@ int drm_add_override_edid_modes(struct drm_connector *connector) } EXPORT_SYMBOL(drm_add_override_edid_modes); +static struct edid *drm_do_get_edid_blk0( + int (*get_edid_block)(void *data, u8 *buf, unsigned int block, + size_t len), + void *data, bool *edid_corrupt, int *null_edid_counter) +{ + int i; + u8 *edid; + + if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) + return NULL; + + /* base block fetch */ + for (i = 0; i < 4; i++) { + if (get_edid_block(data, edid, 0, EDID_LENGTH)) + goto out; + if (drm_edid_block_valid(edid, 0, false, edid_corrupt)) + break; + if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) { + if (null_edid_counter) + (*null_edid_counter)++; + goto carp; + } + } + if (i == 4) + goto carp; + + return (struct edid *)edid; + +carp: + kfree(edid); + return ERR_PTR(-EINVAL); + +out: + kfree(edid); + return NULL; +} + /** * drm_do_get_edid - get EDID data using a custom EDID block read function * @connector: connector we're probing @@ -1938,25 +1975,16 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, if (override) return override; - if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) + edid = (u8 *)drm_do_get_edid_blk0(get_edid_block, data, + &connector->edid_corrupt, + &connector->null_edid_counter); + if (IS_ERR_OR_NULL(edid)) { + if (IS_ERR(edid)) + connector_bad_edid(connector, edid, 1); return NULL; - - /* base block fetch */ - for (i = 0; i < 4; i++) { - if (get_edid_block(data, edid, 0, EDID_LENGTH)) - goto out; - if (drm_edid_block_valid(edid, 0, false, -&connector->edid_corrupt)) - break; - if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) { - connector->null_edid_counter++; - goto carp; - } } - if (i == 4) - goto carp; - /* if there's no extensions, we're done */ + /* if there's no extensions or no connector, we're done */ valid_extensions = edid[0x7e]; if (valid_extensions == 0) return (struct edid *)edid; @@ -2010,8 +2038,6 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, return (struct edid *)edid; -carp: - connector_bad_edid(connector, edid, 1); out: kfree(edid); return NULL; -- 2.32.0.554.ge1b32706d8-goog
[PATCH v2 6/6] drm/panel-simple: Implement generic "edp-panel"s probed by EDID
As discussed in the patch ("dt-bindings: drm/panel-simple: Introduce generic eDP panels") we can actually support probing eDP panels at runtime instead of hardcoding what panel is connected. Add support to the panel-simple driver for this. We'll implement a solution like this: * We'll read in two delays from the device tree that are used for powering up the panel the initial time (to read the EDID). * In the EDID we can find a 32-bit ID that identifies what panel we've found. From this ID we can look up the full set of delays. After this change we'll still need to add per-panel delays into the panel-simple driver but we will no longer need to specify exactly which panel is connected to which board in the device tree. Nicely, any panels that are only supported this way also don't need to hardcode mode data since it's guaranteed that we can get that through the EDID. This patch will seed the ID-to-delay table with a few panels that I have access to, many of which are on sc7180-trogdor devices. Signed-off-by: Douglas Anderson --- Changes in v2: - Don't support a "fallback" panel. Probed panels must be probed. - Not based on patch to copy "desc"--just allocate for probed panels. - Add "-ms" suffix to delays. drivers/gpu/drm/panel/panel-simple.c | 187 --- 1 file changed, 171 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 7d80bb20e6e0..c2a2168f9a13 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -178,6 +178,20 @@ struct panel_desc { int connector_type; }; +/** + * struct edp_panel_entry - Maps panel ID to delay / panel name. + */ +struct edp_panel_entry { + /** @panel_id: 32-bit ID for panel, encoded with encode_edid_id(). */ + u32 panel_id; + + /* @delay: The power sequencing delays needed for this panel. */ + const struct panel_delay *delay; + + /* @name: Name of this panel (for printing to logs). */ + const char *name; +}; + struct panel_simple { struct drm_panel base; bool enabled; @@ -532,8 +546,15 @@ static int panel_simple_get_modes(struct drm_panel *panel, pm_runtime_put_autosuspend(panel->dev); } - /* add hard-coded panel modes */ - num += panel_simple_get_non_edid_modes(p, connector); + /* +* Add hard-coded panel modes. Don't call this if there are no timings +* and no modes (the generic edp-panel case) because it will clobber +* the display_info that was already set by drm_add_edid_modes(). +*/ + if (p->desc->num_timings || p->desc->num_modes) + num += panel_simple_get_non_edid_modes(p, connector); + else if (!num) + dev_warn(p->base.dev, "No display modes\n"); /* set up connector's "panel orientation" property */ drm_connector_set_panel_orientation(connector, p->orientation); @@ -662,9 +683,79 @@ static void panel_simple_parse_panel_timing_node(struct device *dev, dev_err(dev, "Reject override mode: No display_timing found\n"); } +static const struct edp_panel_entry *find_edp_panel(u32 panel_id); + +static int generic_edp_panel_probe(struct device *dev, struct panel_simple *panel) +{ + const struct edp_panel_entry *edp_panel; + struct panel_desc *desc; + u32 panel_id; + char vend[4]; + u16 product_id; + u32 prepare_ms = 0; + u32 absent_ms = 0; + int ret; + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + desc->connector_type = DRM_MODE_CONNECTOR_eDP; + panel->desc = desc; + + /* +* Read the dts properties for the initial probe. These are used by +* the runtime resume code which will get called by the +* pm_runtime_get_sync() call below. +*/ + of_property_read_u32(dev->of_node, "hpd-reliable-delay-ms", &prepare_ms); + desc->delay.prepare = prepare_ms; + of_property_read_u32(dev->of_node, "hpd-absent-delay-ms", &absent_ms); + if (absent_ms && absent_ms <= prepare_ms) + dev_warn(dev, +"Ignoring hpd-absent-delay-ms <= hpd-reliable-delay-ms\n"); + else if (absent_ms) + /* +* hpd_absent_delay is added to prepare delay in prepare, +* so subtract since dts bindings are specified slightly +* that they overlap. +*/ + desc->delay.hpd_absent_delay = absent_ms - prepare_ms; + + /* Power the panel on so we can read the EDID */ + pm_runtime_get_sync(dev); + + panel_id = drm_get_panel_id(panel->ddc); + if (!panel_id) { + dev_err(dev, "Couldn't identify panel via EDID\n"); + ret = -EIO; + goto exit; + } + decode_edid_id(panel_id, vend, &product
[PATCH v2 5/6] drm/panel-simple: Split the delay structure out of the panel description
In the case where we can read an EDID for a panel the only part of the panel description that can't be found directly from the EDID is the description of the delays. Let's break the delay structure out so that we can specify just the delays for panels that are detected by EDID. This is simple code motion. No functional change is intended. Signed-off-by: Douglas Anderson --- Changes in v2: - Rebased atop revert of delays between GPIO & regulator drivers/gpu/drm/panel/panel-simple.c | 159 ++- 1 file changed, 82 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index b06bf30c65d0..7d80bb20e6e0 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -41,6 +41,87 @@ #include #include +/** + * struct panel_delay - Describes delays for a simple panel. + */ +struct panel_delay { + /** +* @prepare: Time for the panel to become ready. +* +* The time (in milliseconds) that it takes for the panel to +* become ready and start receiving video data +*/ + unsigned int prepare; + + /** +* @hpd_absent_delay: Time to wait if HPD isn't hooked up. +* +* Add this to the prepare delay if we know Hot Plug Detect +* isn't used. +*/ + unsigned int hpd_absent_delay; + + /** +* @prepare_to_enable: Time between prepare and enable. +* +* The minimum time, in milliseconds, that needs to have passed +* between when prepare finished and enable may begin. If at +* enable time less time has passed since prepare finished, +* the driver waits for the remaining time. +* +* If a fixed enable delay is also specified, we'll start +* counting before delaying for the fixed delay. +* +* If a fixed prepare delay is also specified, we won't start +* counting until after the fixed delay. We can't overlap this +* fixed delay with the min time because the fixed delay +* doesn't happen at the end of the function if a HPD GPIO was +* specified. +* +* In other words: +* prepare() +* ... +* // do fixed prepare delay +* // wait for HPD GPIO if applicable +* // start counting for prepare_to_enable +* +* enable() +* // do fixed enable delay +* // enforce prepare_to_enable min time +*/ + unsigned int prepare_to_enable; + + /** +* @enable: Time for the panel to display a valid frame. +* +* The time (in milliseconds) that it takes for the panel to +* display the first valid frame after starting to receive +* video data. +*/ + unsigned int enable; + + /** +* @disable: Time for the panel to turn the display off. +* +* The time (in milliseconds) that it takes for the panel to +* turn the display off (no content is visible). +*/ + unsigned int disable; + + /** +* @unprepare: Time to power down completely. +* +* The time (in milliseconds) that it takes for the panel +* to power itself down completely. +* +* This time is used to prevent a future "prepare" from +* starting until at least this many milliseconds has passed. +* If at prepare time less time has passed since unprepare +* finished, the driver waits for the remaining time. +*/ + unsigned int unprepare; +}; + /** * struct panel_desc - Describes a simple panel. */ @@ -85,83 +166,7 @@ struct panel_desc { } size; /** @delay: Structure containing various delay values for this panel. */ - struct { - /** -* @delay.prepare: Time for the panel to become ready. -* -* The time (in milliseconds) that it takes for the panel to -* become ready and start receiving video data -*/ - unsigned int prepare; - - /** -* @delay.hpd_absent_delay: Time to wait if HPD isn't hooked up. -* -* Add this to the prepare delay if we know Hot Plug Detect -* isn't used. -*/ - unsigned int hpd_absent_delay; - - /** -* @delay.prepare_to_enable: Time between prepare and enable. -* -* The minimum time, in milliseconds, that needs to have passed -* between when prepare finished and enable may begin. If at -* enable time less time has passed since prepare finished, -* the driver waits for the remaining time. -* -* If a fixed enable delay is also specified, we'll start -
Re: Re: [PATCH 03/14] drm/atmel-hlcdc: Convert to Linux IRQ interfaces
On 7/30/21 1:31 AM, Thomas Zimmermann wrote: > Hi Dan and Sam > > Am 29.07.21 um 21:55 schrieb dan.sned...@microchip.com: >> Hi Thomas and Sam, >> On 7/29/21 12:48 PM, Sam Ravnborg wrote: >>> EXTERNAL EMAIL: Do not click links or open attachments unless you >>> know the content is safe >>> >>> Hi Thomas, >>> Are you sure, you're testing with the latest drm-misc-next or drm-tip? Because using irq_enabled is deprecated and the flag was recently replaced by commit 1e4cd78ed493 ("drm: Don't test for IRQ support in VBLANK ioctls"). >> >> Ok, My fault for testing on the wrong branch. When I test this patch on >> drm-misc-next it works great. Sorry for the confusion! >> >>> >>> I was looking at drm-misc-fixes which did not have this commit :-( >>> Just my silly excuse why I was convinced this was the issue. > > Don't worry. > > I'll add Sam's R-b and a Tested-by from Dan to the patch. Is that ok? The tested-by works for me! Thanks! > > Best regards > Thomas > > >>> >>> Sam >>> >> >> Best regards, >> Dan >> >
Re: [PATCH 04/64] stddef: Introduce struct_group() helper macro
On Wed, 2021-07-28 at 14:59 -0700, Kees Cook wrote: > On Wed, Jul 28, 2021 at 12:54:18PM +0200, Rasmus Villemoes wrote: > > On 27/07/2021 22.57, Kees Cook wrote: > > > > > In order to have a regular programmatic way to describe a struct > > > region that can be used for references and sizing, can be examined for > > > bounds checking, avoids forcing the use of intermediate identifiers, > > > and avoids polluting the global namespace, introduce the struct_group() > > > macro. This macro wraps the member declarations to create an anonymous > > > union of an anonymous struct (no intermediate name) and a named struct > > > (for references and sizing): > > > > > > struct foo { > > > int one; > > > struct_group(thing, > > > int two, > > > int three, > > > ); > > > int four; > > > }; > > > > That example won't compile, the commas after two and three should be > > semicolons. > > Oops, yes, thanks. This is why I shouldn't write code that doesn't first > go through a compiler. ;) > > > And your implementation relies on MEMBERS not containing any comma > > tokens, but as > > > > int a, b, c, d; > > > > is a valid way to declare multiple members, consider making MEMBERS > > variadic > > > > #define struct_group(NAME, MEMBERS...) > > > > to have it slurp up every subsequent argument and make that work. > > Ah! Perfect, thank you. I totally forgot I could do it that way. This is great Kees. It just so happens it would clean-up what we are already doing in drivers/cxl/cxl.h for anonymous + named register block pointers. However in the cxl case it also needs the named structure to be typed. Any appetite for a typed version of this? Here is a rough idea of the cleanup it would induce in drivers/cxl/: diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 53927f9fa77e..a2308c995654 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -75,52 +75,19 @@ static inline int cxl_hdm_decoder_count(u32 cap_hdr) #define CXLDEV_MBOX_BG_CMD_STATUS_OFFSET 0x18 #define CXLDEV_MBOX_PAYLOAD_OFFSET 0x20 -#define CXL_COMPONENT_REGS() \ - void __iomem *hdm_decoder - -#define CXL_DEVICE_REGS() \ - void __iomem *status; \ - void __iomem *mbox; \ - void __iomem *memdev - -/* See note for 'struct cxl_regs' for the rationale of this organization */ /* - * CXL_COMPONENT_REGS - Common set of CXL Component register block base pointers * @hdm_decoder: CXL 2.0 8.2.5.12 CXL HDM Decoder Capability Structure - */ -struct cxl_component_regs { - CXL_COMPONENT_REGS(); -}; - -/* See note for 'struct cxl_regs' for the rationale of this organization */ -/* - * CXL_DEVICE_REGS - Common set of CXL Device register block base pointers * @status: CXL 2.0 8.2.8.3 Device Status Registers * @mbox: CXL 2.0 8.2.8.4 Mailbox Registers * @memdev: CXL 2.0 8.2.8.5 Memory Device Registers */ -struct cxl_device_regs { - CXL_DEVICE_REGS(); -}; - -/* - * Note, the anonymous union organization allows for per - * register-block-type helper routines, without requiring block-type - * agnostic code to include the prefix. - */ struct cxl_regs { - union { - struct { - CXL_COMPONENT_REGS(); - }; - struct cxl_component_regs component; - }; - union { - struct { - CXL_DEVICE_REGS(); - }; - struct cxl_device_regs device_regs; - }; + struct_group_typed(cxl_component_regs, component, + void __iomem *hdm_decoder; + ); + struct_group_typed(cxl_device_regs, device_regs, + void __iomem *status, *mbox, *memdev; + ); }; struct cxl_reg_map { diff --git a/include/linux/stddef.h b/include/linux/stddef.h index cf7f866944f9..84b7de24ffb5 100644 --- a/include/linux/stddef.h +++ b/include/linux/stddef.h @@ -49,12 +49,18 @@ enum { * @ATTRS: Any struct attributes (normally empty) * @MEMBERS: The member declarations for the mirrored structs */ -#define struct_group_attr(NAME, ATTRS, MEMBERS) \ +#define struct_group_attr(NAME, ATTRS, MEMBERS...) \ union { \ struct { MEMBERS } ATTRS; \ struct { MEMBERS } ATTRS NAME; \ } +#define struct_group_attr_typed(TYPE, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct TYPE { MEMBERS } ATTRS NAME; \ + } + /** * struct_group(NAME, MEMBERS) * @@ -67,7 +73,10 @@ enum { * @NAME: The name of the mirrored sub-struct * @MEMBERS: The member declarations for the mirrored structs */ -#define struct_group(NAME, MEMBERS)\ +#define struct_group(NAME, MEMBERS...) \ struct_group_attr(NAME, /* no attrs */, MEMBERS) +#define struct_group_typed(TYPE, NAME, MEMBERS...) \ + struct_group_attr_typed(TYPE, NAME, /* no attrs */, MEMBERS) +
Re: [PATCH v5 5/6] drm/mediatek: add DSC support for mt8195
Hi, Jason: jason-jh.lin 於 2021年7月30日 週五 上午1:07寫道: > > Add DSC into mtk_drm_ddp_comp to support for mt8195. > > DSC is designed for real-time systems with real-time compression, > transmission, decompression and display. > The DSC standard is a specification of the algorithms used for > compressing and decompressing image display streams, including > the specification of the syntax and semantics of the compressed > video bit stream. > > Signed-off-by: jason-jh.lin > --- > This patch is base on [1] > > [1]add mt8195 SoC DRM binding > - https://patchwork.kernel.org/project/linux-mediatek/list/?series=519597 > --- > drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 46 + > drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 1 + > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 + > 3 files changed, 49 insertions(+) > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c > b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c > index 75bc00e17fc4..6f4a9b8c9914 100644 > --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c > +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c > @@ -65,6 +65,12 @@ > #define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4) > #define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0) > > +#define DISP_REG_DSC_CON 0x > +#define DSC_EN BIT(0) > +#define DSC_DUAL_INOUT BIT(2) > +#define DSC_BYPASS BIT(4) > +#define DSC_UFOE_SEL BIT(16) > + > struct mtk_ddp_comp_dev { > struct clk *clk; > void __iomem *regs; > @@ -246,6 +252,35 @@ static void mtk_dither_stop(struct device *dev) > writel_relaxed(0x0, priv->regs + DISP_DITHER_EN); > } > > +static void mtk_dsc_config(struct device *dev, unsigned int w, > + unsigned int h, unsigned int vrefresh, > + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) > +{ > + struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev); > + > + /* dsc bypass mode */ > + mtk_ddp_write_mask(cmdq_pkt, DSC_BYPASS, &priv->cmdq_reg, priv->regs, > + DISP_REG_DSC_CON, DSC_BYPASS); > + mtk_ddp_write_mask(cmdq_pkt, DSC_UFOE_SEL, &priv->cmdq_reg, > priv->regs, > + DISP_REG_DSC_CON, DSC_UFOE_SEL); > + mtk_ddp_write_mask(cmdq_pkt, DSC_DUAL_INOUT, &priv->cmdq_reg, > priv->regs, > + DISP_REG_DSC_CON, DSC_DUAL_INOUT); > +} > + > +static void mtk_dsc_start(struct device *dev) > +{ > + struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev); > + > + writel_relaxed(DSC_EN, &priv->regs + DISP_REG_DSC_CON); > +} > + > +static void mtk_dsc_stop(struct device *dev) > +{ > + struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev); > + > + writel_relaxed(0x0, priv->regs + DISP_REG_DSC_CON); > +} > + > static const struct mtk_ddp_comp_funcs ddp_aal = { > .clk_enable = mtk_ddp_clk_enable, > .clk_disable = mtk_ddp_clk_disable, > @@ -284,6 +319,14 @@ static const struct mtk_ddp_comp_funcs ddp_dpi = { > .stop = mtk_dpi_stop, > }; > > +static const struct mtk_ddp_comp_funcs ddp_dsc = { > + .clk_enable = mtk_ddp_clk_enable, > + .clk_disable = mtk_ddp_clk_disable, > + .config = mtk_dsc_config, > + .start = mtk_dsc_start, > + .stop = mtk_dsc_stop, > +}; > + > static const struct mtk_ddp_comp_funcs ddp_dsi = { > .start = mtk_dsi_ddp_start, > .stop = mtk_dsi_ddp_stop, > @@ -356,6 +399,7 @@ static const char * const > mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = { > [MTK_DISP_MUTEX] = "mutex", > [MTK_DISP_OD] = "od", > [MTK_DISP_BLS] = "bls", > + [MTK_DISP_DSC] = "dsc", Would you please send a patch to make alphabetic order then apply this patch? > }; > > struct mtk_ddp_comp_match { > @@ -374,6 +418,8 @@ static const struct mtk_ddp_comp_match > mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { > [DDP_COMPONENT_DITHER] = { MTK_DISP_DITHER,0, &ddp_dither }, > [DDP_COMPONENT_DPI0]= { MTK_DPI,0, &ddp_dpi }, > [DDP_COMPONENT_DPI1]= { MTK_DPI,1, &ddp_dpi }, > + [DDP_COMPONENT_DSC0]= { MTK_DISP_DSC, 0, &ddp_dsc }, > + [DDP_COMPONENT_DSC1]= { MTK_DISP_DSC, 1, &ddp_dsc }, > [DDP_COMPONENT_DSI0]= { MTK_DSI,0, &ddp_dsi }, > [DDP_COMPONENT_DSI1]= { MTK_DSI,1, &ddp_dsi }, > [DDP_COMPONENT_DSI2]= { MTK_DSI,2, &ddp_dsi }, > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h > b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h > index bb914d976cf5..661fb620e266 100644 > --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h > +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h > @@ -34,6 +34,7 @@ enum mtk_ddp_comp_type { > MTK_DISP_MUTEX, > MTK_DISP_OD, > MTK_DISP_BLS, > + MTK_DISP_
Re: [Freedreno] [PATCH 1/5] drm/msm/dp: Remove global g_dp_display variable
On 2021-07-24 21:24, Bjorn Andersson wrote: 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 --- 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) { + DRM_ERROR("DP driver bind failed. Invalid driver data\n"); + return -EINVAL; + } dp->dp_display.drm_dev = drm; priv = drm->dev_private; @@ -240,12 +248,14 @@ static int dp_display_bind(struct device *dev, struct device *master, static void dp_display_unbind(struct device *dev, struct device *master, void *data) { - struct dp_display_private *dp; + struct dp_display_private *dp = dev_to_dp_display_private(dev); struct drm_device *drm = dev_get_drvdata(master); struct msm_drm_private *priv = drm->dev_private; - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + if (!dp) { + DRM_ERROR("Invalid DP driver data\n"); + return; + } dp_power_client_deinit(dp->power); dp_aux_unregister(dp->aux); @@ -376,17 +386,14 @@ static void dp_display_host_deinit(struct dp_display_private *dp) static int dp_display_usbpd_configure_cb(struct device *dev) { int rc = 0; - struct dp_display_private *dp; + struct dp_display_private *dp = dev_to_dp_display_private(dev); - if (!dev) { - DRM_ERROR("invalid dev\n"); - rc = -EINVAL; + if (!dp) { + DRM_ERROR("no driver data found\n"); + rc = -ENODEV; goto end; } - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); - dp_display_host_init(dp, false); rc = dp_display_process_hpd_high(dp); @@ -397,17 +404,14 @@ static int dp_display_usbpd_configure_cb(struct device *dev) static int dp_display_usbpd_disconnect_cb(struct device *dev) { int rc = 0; - struct dp_display_private *dp; + struct dp_display_private *dp = dev_to_dp_display_private(dev); - if (!dev) { - DRM_ERROR("invalid dev\n"); - rc = -EINVAL; + if (!dp) { + DRM_ERROR("no driver data found\n"); + rc = -ENODEV; return rc; } - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); - dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); return rc; @@ -466,15 +470,15 @@ static int dp_display_usbpd_attention_cb(struct device *dev) { int rc = 0; u32 sink_request; - struct dp_display_private *dp; + struct dp_display_private *dp = dev_to_dp_display_private(dev); + struct dp_usbpd *hpd; - if (!dev) { - DRM_ERROR("invalid dev\n"); - return -EINVAL; + if (!dp) { + DRM_ERROR("no driver data found\n"); + return -ENODEV; } - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + hpd = dp->usbpd; hpd is unused here. It was removed with https://patches.linaro.org/patch/416670/ /* check for any test request issued by sink */ rc = dp_link_process_request(dp->link); @@ -638,7 +642,7 @@ static int dp_hpd_unplug_handle(struct
Re: [PATCH 1/7] drm/omap: Cast pointer to integer safely
Hi Tomi, On Thu, Jul 29, 2021 at 09:13:17AM +0300, Tomi Valkeinen wrote: > On 28/07/2021 18:37, Laurent Pinchart wrote: > > On 64-bit platforms, the compiler complains that casting a void pointer > > to an unsigned int loses data. Cast the pointer to a uintptr_t unsigned > > to fix this. > > > > Signed-off-by: Laurent Pinchart > > --- > > drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c > > b/drivers/gpu/drm/omapdrm/omap_drv.c > > index f86e20578143..c05d3975cb31 100644 > > --- a/drivers/gpu/drm/omapdrm/omap_drv.c > > +++ b/drivers/gpu/drm/omapdrm/omap_drv.c > > @@ -572,7 +572,7 @@ static int omapdrm_init(struct omap_drm_private *priv, > > struct device *dev) > > priv->dss->mgr_ops_priv = priv; > > > > soc = soc_device_match(omapdrm_soc_devices); > > - priv->omaprev = soc ? (unsigned int)soc->data : 0; > > + priv->omaprev = soc ? (uintptr_t)soc->data : 0; > > priv->wq = alloc_ordered_workqueue("omapdrm", 0); > > > > mutex_init(&priv->list_lock); > > > > Looks fine, although the subject sounds odd. Why was the cast "unsafe" > before, and "safe" now? The result is indeed exactly the same. It was safe before, because we know the value won't exceed 32 bits. I'll s/safely/without generating a warning/. > There's also another bunch of warnings I see: I wonder how I missed those. Will fix. > drivers/gpu/drm/omapdrm/dss/dsi.c: In function ‘dsi_vc_send_long’: > drivers/gpu/drm/omapdrm/dss/dsi.c:7:25: warning: format ‘%d’ expects argument > of type ‘int’, but argument 3 has type ‘size_t’ {aka ‘const long unsigned > int’} [-Wformat=] > 7 | #define DSS_SUBSYS_NAME "DSI" >| ^ > drivers/gpu/drm/omapdrm/dss/dss.h:30:21: note: in expansion of macro > ‘DSS_SUBSYS_NAME’ > 30 | #define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt >| ^~~ > ./include/linux/dynamic_debug.h:134:15: note: in expansion of macro ‘pr_fmt’ >134 | func(&id, ##__VA_ARGS__); \ >| ^~~ > ./include/linux/dynamic_debug.h:152:2: note: in expansion of macro > ‘__dynamic_func_call’ >152 | __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__) >| ^~~ > ./include/linux/dynamic_debug.h:162:2: note: in expansion of macro > ‘_dynamic_func_call’ >162 | _dynamic_func_call(fmt, __dynamic_pr_debug, \ >| ^~ > ./include/linux/printk.h:471:2: note: in expansion of macro ‘dynamic_pr_debug’ >471 | dynamic_pr_debug(fmt, ##__VA_ARGS__) >| ^~~~ > drivers/gpu/drm/omapdrm/dss/dss.h:36:2: note: in expansion of macro ‘pr_debug’ > 36 | pr_debug(format, ## __VA_ARGS__) >| ^~~~ > drivers/gpu/drm/omapdrm/dss/dsi.c:2097:3: note: in expansion of macro ‘DSSDBG’ > 2097 | DSSDBG("dsi_vc_send_long, %d bytes\n", msg->tx_len); >| ^~ > In file included from ./include/linux/printk.h:7, > from ./include/linux/kernel.h:19, > from drivers/gpu/drm/omapdrm/dss/dsi.c:9: > drivers/gpu/drm/omapdrm/dss/dsi.c: In function ‘dsi_vc_generic_read’: > ./include/linux/kern_levels.h:5:18: warning: format ‘%d’ expects argument of > type ‘int’, but argument 4 has type ‘size_t’ {aka ‘const long unsigned int’} > [-Wformat=] > 5 | #define KERN_SOH "\001" /* ASCII Start Of Header */ >| ^~ > ./include/linux/kern_levels.h:11:18: note: in expansion of macro ‘KERN_SOH’ > 11 | #define KERN_ERR KERN_SOH "3" /* error conditions */ >| ^~~~ > ./include/linux/printk.h:390:9: note: in expansion of macro ‘KERN_ERR’ >390 | printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) >| ^~~~ > drivers/gpu/drm/omapdrm/dss/dss.h:40:2: note: in expansion of macro ‘pr_err’ > 40 | pr_err("omapdss " DSS_SUBSYS_NAME " error: " format, ##__VA_ARGS__) >| ^~ > drivers/gpu/drm/omapdrm/dss/dsi.c:2393:2: note: in expansion of macro ‘DSSERR’ > 2393 | DSSERR("%s(vc %d, reqlen %d) failed\n", __func__, vc, msg->tx_len); >| ^~ > -- Regards, Laurent Pinchart
Re: [Intel-gfx] [PATCH] drm/i915/xehp: Fix missing sentinel on mcr_ranges_xehp
I guess I forgot to Cc dri-devel. Doing it now. Lucas De Marchi On Fri, Jul 30, 2021 at 12:18:59PM -0700, Matt Roper wrote: On Fri, Jul 30, 2021 at 12:11:15PM -0700, Lucas De Marchi wrote: There's a missing sentinel since we are not using ARRAY_SIZE(), but rather checking that the .start is 0 to stop the iteration in mcr_range(). BUG: KASAN: global-out-of-bounds in mcr_range.isra.0+0x69/0xa0 [i915] Read of size 4 at addr a0889928 by task modprobe/3881 Fixes: d8905ba705ab ("drm/i915/xehp: Define multicast register ranges") Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 9173df59821a..053fa7251cd0 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -2000,6 +2000,7 @@ static const struct mcr_range mcr_ranges_xehp[] = { { .start = 0xdc00, .end = 0x }, { .start = 0x17000, .end = 0x17fff }, { .start = 0x24a00, .end = 0x24a7f }, + {}, }; static bool mcr_range(struct drm_i915_private *i915, u32 offset) -- 2.31.1 -- Matt Roper Graphics Software Engineer VTT-OSGC Platform Enablement Intel Corporation (916) 356-2795
Re: [PATCH 0/5] drm/msm/dp: Support multiple DP instances and add sc8180x
Hi Bjorn On 2021-07-24 21:24, Bjorn Andersson wrote: The current implementation supports a single DP instance and the DPU code will only match it against INTF_DP instance 0. These patches extends this to allow multiple DP instances and support for matching against DP instances beyond 0. This is based on v4 of Dmitry's work on multiple DSI interfaces: https://lore.kernel.org/linux-arm-msm/20210717124016.316020-1-dmitry.barysh...@linaro.org/ With that in place add SC8180x DP and eDP controllers. Thanks for posting the changes. I dont have major concerns on the series as such apart from minor comments which i will post in a day or two but I will check and get back if this has been validated on sc7280 without any concerns. One question i had is not directly related to this series but related to multi-DP in general. Does audio work fine across both the DPs when both are connected? The reason I ask this question is that, I dont know how two hdmi-codec instances are handled today. So we will register twice with hdmi-codec so there should be two audio streams. But I am not sure if this works correctly in todays design with hdmi-codec. Any chance you had validated this? Bjorn Andersson (5): drm/msm/dp: Remove global g_dp_display variable drm/msm/dp: Modify prototype of encoder based API drm/msm/dp: Support up to 3 DP controllers dt-bindings: msm/dp: Add SC8180x compatibles drm/msm/dp: Add sc8180x DP controllers .../bindings/display/msm/dp-controller.yaml | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 60 +++--- .../gpu/drm/msm/disp/msm_disp_snapshot_util.c | 8 +- drivers/gpu/drm/msm/dp/dp_display.c | 183 +- drivers/gpu/drm/msm/msm_drv.h | 33 ++-- 6 files changed, 200 insertions(+), 103 deletions(-)
Re: [PATCH 4/7] drm/omap: Enable COMPILE_TEST on all ARM and ARM64 platforms
Hi Laurent, I love your patch! Perhaps something to improve: [auto build test WARNING on tegra-drm/drm/tegra/for-next] [also build test WARNING on tegra/for-next drm-intel/for-linux-next drm-tip/drm-tip drm-exynos/exynos-drm-next linus/master v5.14-rc3 next-20210730] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Laurent-Pinchart/drm-Extend-COMPILE_TEST-support-to-some-ARM-drivers/20210728-234045 base: git://anongit.freedesktop.org/tegra/linux.git drm/tegra/for-next config: arm64-allyesconfig (attached as .config) compiler: aarch64-linux-gcc (GCC) 10.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/de95f9a00c85a831f2029e3bbbc59183e029cd8c git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Laurent-Pinchart/drm-Extend-COMPILE_TEST-support-to-some-ARM-drivers/20210728-234045 git checkout de95f9a00c85a831f2029e3bbbc59183e029cd8c # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-10.3.0 make.cross ARCH=arm64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All warnings (new ones prefixed by >>): drivers/gpu/drm/omapdrm/dss/dsi.c: In function 'dsi_vc_send_long': >> drivers/gpu/drm/omapdrm/dss/dsi.c:7:25: warning: format '%d' expects >> argument of type 'int', but argument 3 has type 'size_t' {aka 'const long >> unsigned int'} [-Wformat=] 7 | #define DSS_SUBSYS_NAME "DSI" | ^ drivers/gpu/drm/omapdrm/dss/dss.h:30:21: note: in expansion of macro 'DSS_SUBSYS_NAME' 30 | #define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt | ^~~ include/linux/dynamic_debug.h:134:15: note: in expansion of macro 'pr_fmt' 134 | func(&id, ##__VA_ARGS__); \ | ^~~ include/linux/dynamic_debug.h:152:2: note: in expansion of macro '__dynamic_func_call' 152 | __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__) | ^~~ include/linux/dynamic_debug.h:162:2: note: in expansion of macro '_dynamic_func_call' 162 | _dynamic_func_call(fmt, __dynamic_pr_debug, \ | ^~ include/linux/printk.h:471:2: note: in expansion of macro 'dynamic_pr_debug' 471 | dynamic_pr_debug(fmt, ##__VA_ARGS__) | ^~~~ drivers/gpu/drm/omapdrm/dss/dss.h:36:2: note: in expansion of macro 'pr_debug' 36 | pr_debug(format, ## __VA_ARGS__) | ^~~~ drivers/gpu/drm/omapdrm/dss/dsi.c:2097:3: note: in expansion of macro 'DSSDBG' 2097 | DSSDBG("dsi_vc_send_long, %d bytes\n", msg->tx_len); | ^~ In file included from include/linux/printk.h:7, from include/linux/kernel.h:19, from drivers/gpu/drm/omapdrm/dss/dsi.c:9: drivers/gpu/drm/omapdrm/dss/dsi.c: In function 'dsi_vc_generic_read': include/linux/kern_levels.h:5:18: warning: format '%d' expects argument of type 'int', but argument 4 has type 'size_t' {aka 'const long unsigned int'} [-Wformat=] 5 | #define KERN_SOH "\001" /* ASCII Start Of Header */ | ^~ include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH' 11 | #define KERN_ERR KERN_SOH "3" /* error conditions */ | ^~~~ include/linux/printk.h:390:9: note: in expansion of macro 'KERN_ERR' 390 | printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) | ^~~~ drivers/gpu/drm/omapdrm/dss/dss.h:40:2: note: in expansion of macro 'pr_err' 40 | pr_err("omapdss " DSS_SUBSYS_NAME " error: " format, ##__VA_ARGS__) | ^~ drivers/gpu/drm/omapdrm/dss/dsi.c:2393:2: note: in expansion of macro 'DSSERR' 2393 | DSSERR("%s(vc %d, reqlen %d) failed\n", __func__, vc, msg->tx_len); | ^~ vim +7 drivers/gpu/drm/omapdrm/dss/dsi.c 3de7a1dc0c9d29 drivers/video/omap2/dss/dsi.c Tomi Valkeinen 2009-10-28 @7 #define DSS_SUBSYS_NAME "DSI" 3de7a1dc0c9d29 drivers/video/omap2/dss/dsi.c Tomi Valkeinen 2009-10-28 8 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
[PATCH] drm: property: Replace strncpy() with strscpy_pad()
strncpy() is widely regarded as unsafe due to the fact that it may leave the destination string without a nul-termination when the source string size is too large. When compiling the kernel with W=1, the gcc warns about this: drivers/gpu/drm/drm_property.c: In function ‘drm_property_create’: drivers/gpu/drm/drm_property.c:130:2: warning: ‘strncpy’ specified bound 32 equals destination size [-Wstringop-truncation] 130 | strncpy(property->name, name, DRM_PROP_NAME_LEN); | ^~~~ There are three occurrences of strncpy() in drm_property.c. None of them are actually unsafe, as the very next line forces nul-termination of the destination buffer. The warning is thus a false positive, but adds noise to the kernel log. It can easily be silenced by using strscpy_pad() instead. Do so. One of the three occurrences, in drm_property_add_enum(), fills a char array that is later copied to userspace with copy_to_user() in drm_mode_getproperty_ioctl(). To avoid leaking kernel data, strscpy_pad() is required. Similarly, a second occurrence, in drm_mode_getproperty_ioctl(), copies the string to an ioctl data buffer that isn't previously zero'ed, to strscpy_pad() is also required. The last occurrence, in drm_property_create(), would be safe to replace with strscpy(), as the destination buffer is copied to userspace with strscpy_pad(). However, given that this isn't in a hot path, let's avoid future data leaks in case someone copies the whole char array blindly. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/drm_property.c | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index 27c824a6eb60..32404891446e 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -127,8 +127,7 @@ struct drm_property *drm_property_create(struct drm_device *dev, property->num_values = num_values; INIT_LIST_HEAD(&property->enum_list); - strncpy(property->name, name, DRM_PROP_NAME_LEN); - property->name[DRM_PROP_NAME_LEN-1] = '\0'; + strscpy_pad(property->name, name, DRM_PROP_NAME_LEN); list_add_tail(&property->head, &dev->mode_config.property_list); @@ -421,8 +420,7 @@ int drm_property_add_enum(struct drm_property *property, if (!prop_enum) return -ENOMEM; - strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); - prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; + strscpy_pad(prop_enum->name, name, DRM_PROP_NAME_LEN); prop_enum->value = value; property->values[index] = value; @@ -475,8 +473,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, if (!property) return -ENOENT; - strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); - out_resp->name[DRM_PROP_NAME_LEN-1] = 0; + strscpy_pad(out_resp->name, property->name, DRM_PROP_NAME_LEN); out_resp->flags = property->flags; value_count = property->num_values; -- Regards, Laurent Pinchart
[PATCH v2 4/9] drm/imx/dcss: Enable COMPILE_TEST on all architectures
To extend test coverage, relax the dependency on ARCH_MXC and ARM64 to also enable compilation when COMPILE_TEST is selected. Signed-off-by: Laurent Pinchart --- Changes since v1: - Enable COMPILE_TEST on all architectures --- drivers/gpu/drm/imx/dcss/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig index 2b17a964ff05..451ed05321cc 100644 --- a/drivers/gpu/drm/imx/dcss/Kconfig +++ b/drivers/gpu/drm/imx/dcss/Kconfig @@ -3,7 +3,8 @@ config DRM_IMX_DCSS select IMX_IRQSTEER select DRM_KMS_CMA_HELPER select VIDEOMODE_HELPERS - depends on DRM && ARCH_MXC && ARM64 + depends on DRM + depends on (ARCH_MXC && ARM64) || COMPILE_TEST help Choose this if you have a NXP i.MX8MQ based system and want to use the Display Controller Subsystem. This option enables DCSS support. -- Regards, Laurent Pinchart
[PATCH v2 0/9] drm: Extend COMPILE_TEST support to some ARM drivers
Hello, This patch series stems from subsystem-wide changes I wanted to compile-test with an ARM64 cross-compiler. My laziness to fire a 32-bit ARM build definitely resulted in more time being spent writing these patches, but hopefully they'll turn out to be useful for more people. Patches 1/9 to 3/7 are fixes for compilation warnings on 64-bit platforms in the omapdrm and sti-drm drivers. They are a dependency for the Kconfig changes that follow to avoid introducing build warnings, but could also be merged before. Patches 3/9 to 8/9 enable compilation of the imx-dcss, omapdrm, sti-drm and tegra-drm drivers on all architectures with COMPILE_TEST. I have tested compilation on arm64 and x86, with W=1. The patches are independent from each other, so they can be picked by their respective maintainers. The last patch, 9/9, extends COMPILE_TEST support for the tilcdc driver to ARM64. The driver doesn't compile on x86 due to a missing __iowmb(), and I haven't taken the time to investigate how to solve this properly. The main change since v1 is the extension of COMPILE_TEST to all platforms instead of only ARM and ARM64. Please feel free to pick patches individually for the driver(s) you maintain. Laurent Pinchart (9): drm/omap: Use correct printk format specifiers for size_t drm/omap: Cast pointer to integer without generating warning drm/sti: Use correct printk format specifiers for size_t drm/imx/dcss: Enable COMPILE_TEST on all architectures drm/omap: Enable COMPILE_TEST on all architectures drm/rcar-du: Enable COMPILE_TEST on all architectures drm/sti: Enable COMPILE_TEST on all architectures drm/tegra: Enable COMPILE_TEST on all architectures drm/tilcdc: Enable COMPILE_TEST on all ARM64 platforms drivers/gpu/drm/imx/dcss/Kconfig | 3 ++- drivers/gpu/drm/omapdrm/Kconfig| 2 +- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/rcar-du/Kconfig| 1 - drivers/gpu/drm/sti/Kconfig| 3 ++- drivers/gpu/drm/sti/sti_hqvdp.c| 4 ++-- drivers/gpu/drm/tegra/Kconfig | 2 +- drivers/gpu/drm/tilcdc/Kconfig | 3 ++- drivers/gpu/host1x/Kconfig | 2 +- 10 files changed, 14 insertions(+), 12 deletions(-) -- Regards, Laurent Pinchart
[PATCH v2 1/9] drm/omap: Use correct printk format specifiers for size_t
The correct format specifier for size_t is %zu. Using %d (or %u) generates a warning on 64-bit platforms. Fix it. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 5f1722b040f4..503b5d4bf2c2 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -2094,7 +2094,7 @@ static int dsi_vc_send_long(struct dsi_data *dsi, int vc, u8 b1, b2, b3, b4; if (dsi->debug_write) - DSSDBG("dsi_vc_send_long, %d bytes\n", msg->tx_len); + DSSDBG("dsi_vc_send_long, %zu bytes\n", msg->tx_len); /* len + header */ if (dsi->vc[vc].tx_fifo_size * 32 * 4 < msg->tx_len + 4) { @@ -2390,7 +2390,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int vc, return 0; err: - DSSERR("%s(vc %d, reqlen %d) failed\n", __func__, vc, msg->tx_len); + DSSERR("%s(vc %d, reqlen %zu) failed\n", __func__, vc, msg->tx_len); return r; } -- Regards, Laurent Pinchart
[PATCH v2 3/9] drm/sti: Use correct printk format specifiers for size_t
The correct format specifier for size_t is %zu. Using %d (or %u) generates a warning on 64-bit platforms. Fix it. Signed-off-by: Laurent Pinchart Reviewed-by: Philippe Cornu --- drivers/gpu/drm/sti/sti_hqvdp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index d09b08995b12..3c61ba8b43e0 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -927,12 +927,12 @@ static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp) header = (struct fw_header *)firmware->data; if (firmware->size < sizeof(*header)) { - DRM_ERROR("Invalid firmware size (%d)\n", firmware->size); + DRM_ERROR("Invalid firmware size (%zu)\n", firmware->size); goto out; } if ((sizeof(*header) + header->rd_size + header->wr_size + header->pmem_size + header->dmem_size) != firmware->size) { - DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n", + DRM_ERROR("Invalid fmw structure (%zu+%d+%d+%d+%d != %zu)\n", sizeof(*header), header->rd_size, header->wr_size, header->pmem_size, header->dmem_size, firmware->size); -- Regards, Laurent Pinchart