Re: [PATCH v5 3/7] drm: sun4i: dsi: Convert to bridge driver
Hi Dave, On 22/11/2021 18:19, Dave Stevenson wrote: > Hi > > On Mon, 22 Nov 2021 at 15:35, Neil Armstrong wrote: >> >> Hi, >> >> On 22/11/2021 14:16, Jagan Teki wrote: >>> Hi Neil, >>> >>> On Mon, Nov 22, 2021 at 6:22 PM Neil Armstrong >>> wrote: On 22/11/2021 07:52, Jagan Teki wrote: > Some display panels would come up with a non-DSI output, those > can have an option to connect the DSI host by means of interface > bridge converter. > > This DSI to non-DSI interface bridge converter would requires > DSI Host to handle drm bridge functionalities in order to DSI > Host to Interface bridge. > > This patch convert the existing to a drm bridge driver with a > built-in encoder support for compatibility with existing > component drivers. > > Signed-off-by: Jagan Teki > --- > Changes for v5: > - add atomic APIs > - find host and device variant DSI devices. > Changes for v4, v3: > - none > > drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 112 - > drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 7 ++ > 2 files changed, 96 insertions(+), 23 deletions(-) > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > index 43d9c9e5198d..a6a272b55f77 100644 > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > @@ -21,6 +21,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -713,10 +714,11 @@ static int sun6i_dsi_start(struct sun6i_dsi *dsi, > return 0; > } > > -static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder) > +static void sun6i_dsi_bridge_atomic_enable(struct drm_bridge *bridge, > +struct drm_bridge_state > *old_bridge_state) > { > - struct drm_display_mode *mode = > &encoder->crtc->state->adjusted_mode; > - struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder); > + struct sun6i_dsi *dsi = bridge_to_sun6i_dsi(bridge); > + struct drm_display_mode *mode = > &bridge->encoder->crtc->state->adjusted_mode; > struct mipi_dsi_device *device = dsi->device; > union phy_configure_opts opts = { }; > struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy; > @@ -772,6 +774,9 @@ static void sun6i_dsi_encoder_enable(struct > drm_encoder *encoder) > if (dsi->panel) > drm_panel_prepare(dsi->panel); > > + if (dsi->next_bridge) > + > dsi->next_bridge->funcs->atomic_pre_enable(dsi->next_bridge, > old_bridge_state); > + > /* >* FIXME: This should be moved after the switch to HS mode. >* > @@ -787,6 +792,9 @@ static void sun6i_dsi_encoder_enable(struct > drm_encoder *encoder) > if (dsi->panel) > drm_panel_enable(dsi->panel); > > + if (dsi->next_bridge) > + dsi->next_bridge->funcs->atomic_enable(dsi->next_bridge, > old_bridge_state); > + No need to call the next bridge atomic pre_enable/enable/disable/post_disable since they will be called automatically on the bridge chain. >>> >>> Correct, but the existing bridge chain (stack) is not compatible with >>> sun6i DSI start sequence. We cannot send any DCS once we start HS >>> mode. >>> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c#n775 >> >> It's a classical DSI sequence init issue, look at dw-mipi-dsi: >> https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c >> >> We setup the "command-mode" (low-speed) withing mode_set so when the next >> bridge dsi_pre_enable is called, >> low-speed DCS can be sent, then the bridge enable() sets video mode >> (high-speed). >> The disable still needs to call the next_bridge post_disable : >> https://elixir.bootlin.com/linux/v5.16-rc2/source/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c#L893 > > Doesn't that mean the post_disable gets called twice? Once by the > dw-mipi-dsi driver and once by the framework. Yes indeed > >> You can send any low-speed DCS once HS mode is started if the HW supports it >> and the driver handles it, look >> at the >> https://elixir.bootlin.com/linux/v5.16-rc2/source/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c#L397 >> The MIPI_DSI_MODE_LPM and MIPI_DSI_MSG_USE_LPM is used for that. > > This seems to be the same question as I was asking back in [1] and > continued in [2]. > > vc4 and Exynos break the chain apart so that they can initialise the > DSI host before the panel. > That doesn't work if the DSI host is an encoder, as the encoder > mode_valid call is missing the struct drm_display_info needed for > calling the bridge mode_valid function
Re: [PATCH v10 08/10] dyndbg: add print-to-tracefs, selftest with it - RFC
On Mon, 22 Nov 2021 15:42:38 -0700 jim.cro...@gmail.com wrote: > On Mon, Nov 22, 2021 at 2:02 AM Pekka Paalanen wrote: > > > > On Fri, 19 Nov 2021 11:21:36 -0500 > > Jason Baron wrote: > > > > > On 11/18/21 10:24 AM, Pekka Paalanen wrote: > > > > On Thu, 18 Nov 2021 09:29:27 -0500 > > > > Jason Baron wrote: > > > > > > > >> On 11/16/21 3:46 AM, Pekka Paalanen wrote: > > > >>> On Fri, 12 Nov 2021 10:08:41 -0500 > > > >>> Jason Baron wrote: > > > >>> > > > On 11/12/21 6:49 AM, Vincent Whitchurch wrote: > > > > On Thu, Nov 11, 2021 at 03:02:04PM -0700, Jim Cromie wrote: > > > >> Sean Paul proposed, in: > > > >> https://urldefense.com/v3/__https://patchwork.freedesktop.org/series/78133/__;!!GjvTz_vk!HcKnMRByYkIdyF1apqQjlN5aBIomzJR1an3YWXM6KXs0EftVMQdrewRA8Dki4A$ > > > >> drm/trace: Mirror DRM debug logs to tracefs > > > >> > > > >> His patchset's objective is to be able to independently steer some > > > >> of > > > >> the drm.debug stream to an alternate tracing destination, by > > > >> splitting > > > >> drm_debug_enabled() into syslog & trace flavors, and enabling them > > > >> separately. 2 advantages were identified: > > > >> > > > >> 1- syslog is heavyweight, tracefs is much lighter > > > >> 2- separate selection of enabled categories means less traffic > > > >> > > > >> Dynamic-Debug can do 2nd exceedingly well: > > > >> > > > >> A- all work is behind jump-label's NOOP, zero off cost. > > > >> B- exact site selectivity, precisely the useful traffic. > > > >>can tailor enabled set interactively, at shell. > > > >> > > > >> Since the tracefs interface is effective for drm (the threads > > > >> suggest > > > >> so), adding that interface to dynamic-debug has real potential for > > > >> everyone including drm. > > > >> > > > >> if CONFIG_TRACING: > > > >> > > > >> Grab Sean's trace_init/cleanup code, use it to provide tracefs > > > >> available by default to all pr_debugs. This will likely need some > > > >> further per-module treatment; perhaps something reflecting > > > >> hierarchy > > > >> of module,file,function,line, maybe with a tuned flattening. > > > >> > > > >> endif CONFIG_TRACING > > > >> > > > >> Add a new +T flag to enable tracing, independent of +p, and add and > > > >> use 3 macros: dyndbg_site_is_enabled/logging/tracing(), to > > > >> encapsulate > > > >> the flag checks. Existing code treats T like other flags. > > > > > > > > I posted a patchset a while ago to do something very similar, but > > > > that > > > > got stalled for some reason and I unfortunately didn't follow it up: > > > > > > > > > > > > https://urldefense.com/v3/__https://lore.kernel.org/lkml/20200825153338.17061-1-vincent.whitchu...@axis.com/__;!!GjvTz_vk!HcKnMRByYkIdyF1apqQjlN5aBIomzJR1an3YWXM6KXs0EftVMQdrewRGytKHPg$ > > > > > > > > A key difference between that patchset and this patch (besides that > > > > small fact that I used +x instead of +T) was that my patchset > > > > allowed > > > > the dyndbg trace to be emitted to the main buffer and did not force > > > > them > > > > to be in an instance-specific buffer. > > > > > > Yes, I agree I'd prefer that we print here to the 'main' buffer - it > > > seems to keep things simpler and easier to combine the output from > > > different sources as you mentioned. > > > >>> > > > >>> Hi, > > > >>> > > > >>> I'm not quite sure I understand this discussion, but I would like to > > > >>> remind you all of what Sean's original work is about: > > > >>> > > > >>> Userspace configures DRM tracing into a flight recorder buffer (I > > > >>> guess > > > >>> this is what you refer to "instance-specific buffer"). > > > >>> > > > >>> Userspace runs happily for months, and then hits a problem: a failure > > > >>> in the DRM sub-system most likely, e.g. an ioctl that should never > > > >>> fail, failed. Userspace handles that failure by dumping the flight > > > >>> recorder buffer into a file and saving or sending a bug report. The > > > >>> flight recorder contents give a log of all relevant DRM in-kernel > > > >>> actions leading to the unexpected failure to help developers debug it. > > > >>> > > > >>> I don't mind if one can additionally send the flight recorder stream > > > >>> to > > > >>> the main buffer, but I do want the separate flight recorder buffer to > > > >>> be an option so that a) unrelated things cannot flood the interesting > > > >>> bits out of it, and b) the scope of collected information is relevant. > > > >>> > > > >>> The very reason for this work is problems that are very difficult to > > > >>> reproduce in practice, either because the problem itself is triggered > > > >>> very rarely and randomly, or because the end users of the system have > > > >>> either no knowledge or no access to r
Re: [PATCH 3/3] drm/i915/gt: Improve "race-to-idle" at low frequencies
On 22/11/2021 18:44, Rodrigo Vivi wrote: On Wed, Nov 17, 2021 at 02:49:55PM -0800, Vinay Belgaumkar wrote: From: Chris Wilson While the power consumption is proportional to the frequency, there is also a static draw for active gates. The longer we are able to powergate (rc6), the lower the static draw. Thus there is a sweetspot in the frequency/power curve where we run at higher frequency in order to sleep longer, aka race-to-idle. This is more evident at lower frequencies, so let's look to bump the frequency if we think we will benefit by sleeping longer at the higher frequency and so conserving power. Signed-off-by: Chris Wilson Cc: Vinay Belgaumkar Cc: Tvrtko Ursulin Please let's not increase the complexity here, unless we have a very good and documented reason. Before trying to implement anything smart like this in the driver I'd like to see data, power and performance results in different platforms and with different workloads. Who has such test suite and test farm which isn't focused to workloads from a single customer? ;( Regards, Tvrtko
Re: [PATCH] drm/i915/gem: placate scripts/kernel-doc
On 23/11/2021 05:09, Randy Dunlap wrote: Correct kernel-doc warnings in i915_drm_object.c: i915_gem_object.c:103: warning: expecting prototype for i915_gem_object_fini(). Prototype was for __i915_gem_object_fini() instead i915_gem_object.c:110: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst * Mark up the object's coherency levels for a given cache_level i915_gem_object.c:110: warning: missing initial short description on line: * Mark up the object's coherency levels for a given cache_level i915_gem_object.c:457: warning: No description found for return value of 'i915_gem_object_read_from_page' Signed-off-by: Randy Dunlap Reported-by: kernel test robot Cc: Thomas Hellström Cc: Matthew Auld Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: intel-...@lists.freedesktop.org Reviewed-by: Matthew Auld
[Bug 211277] sometimes crash at s2ram-wake (Ryzen 3500U): amdgpu, drm, commit_tail, amdgpu_dm_atomic_commit_tail
https://bugzilla.kernel.org/show_bug.cgi?id=211277 --- Comment #74 from kolAflash (kolafl...@kolahilft.de) --- @James Zhu Tested 5.15.2 for over a week and more than 50 standby-wakeups. No problems! Thanks :-) I would be happy about a patch for the 5.10 longterm kernel. The bug became a problem with v5.10-rc3 (see comment 14), just before Debian made 5.10-longterm the Debian-11 kernel. So it would be great if I and probably other Debian-11 users could finally use that AMD GPU without workarounds. -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
Re: [PATCH v10 08/10] dyndbg: add print-to-tracefs, selftest with it - RFC
First off, let me reiterate that this feature would be invaluable as user-space developers. It's often pretty difficult to figure out the cause of an EINVAL, we have to ask users to follow complicated instructions [1] to grab DRM logs. Then have to skim through several megabytes of logs to find the error. I have a hack [2] which just calls system("sudo dmesg") after a failed atomic commit, it's been pretty handy. But it's really just a hack, a proper solution would be awesome. [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/wikis/DRM-Debugging [2]: https://gitlab.freedesktop.org/emersion/libliftoff/-/merge_requests/61 > > > > Having a subsystem specific trace buffer would allow subsystem specific > > > > trace log permissions depending on the sensitivity of the data. But > > > > doesn't drm output today go to the system log which is typically world > > > > readable today? dmesg isn't world-readable these days, it's been changed recently-ish (last year?) at least on my distribution (Arch). I need root to grab dmesg. (Maybe we can we just let the DRM master process grab the logs?) > > > Yes, and that is exactly the problem. The DRM debug output is so high > > > traffic it would make the system log both unusable due to cruft and > > > slow down the whole machine. The debug output is only useful when > > > something went wrong, and at that point it is too late to enable > > > debugging. That's why a flight recorder with an over-written circular > > > in-memory buffer is needed. > > > > Seans patch reuses enum drm_debug_category to split the tracing > > stream into 10 sub-streams > > - how much traffic from each ? > > - are some sub-streams more valuable for post-mortem ? > > - any value from further refinement of categories ? > > - drop irrelevant callsites individually to reduce clutter, extend > > buffer time/space ? > > I think it's hard to predict which sub-streams you are going to need > before you have a bug to debug. Hence I would err on the side of > enabling too much. This also means that better or more refined > categorisation might not be that much of help - or if it is, then are > the excluded debug messages worth having in the kernel to begin with. > Well, we're probably not that interested in GPU debugs but just > everything related to the KMS side, which on the existing categories > is... everything except half of CORE and DRIVER, maybe? Not sure. We've been recommending drm.debug=0x19F so far (see wiki linked above). KMS + PRIME + ATOMIC + LEASE is definitely something we want in, and CORE + DRIVER contains other useful info. We definitely don't want VBL. > My feeling is that that could mean in the order of hundreds of log > events at framerate (e.g. 60 times per second) per each enabled output > individually. And per DRM device, of course. This is with the > uninteresting GPU debugs already excluded. Indeed, successful KMS atomic commits already generate a lot of noise. On my machine, setting drm.debug=0x19F and running the following command: sudo dmesg -w | pv >/dev/null I get 400KiB/s when idling, and 850KiB/s when wiggling the cursor. > Still, I don't think the flight recorder buffer would need to be > massive. I suspect it would be enough to hold a few frames' worth which > is just a split second under active operation. When something happens, > the userspace stack is likely going to stop on its tracks immediately > to collect the debug information, which means the flooding should pause > and the relevant messages don't get overwritten before we get them. In > a multi-seat system where each device is controlled by a separate > display server instance, per-device logs would help with this. OTOH, > multi-seat is not a very common use case I suppose. There's also the case of multi-GPU where GPU B's logs could clutter GPU A's, making it harder to understand the cause of an atomic commit failure on GPU A. So per-device logs would be useful, but not a hard requirement for me, having *anything* at all would already be a big win. In my experiments linked above [2], system("sudo dmesg") after atomic commit failure worked pretty well, and the bottom of the log contained the cause of the failure. It was pretty useful to system("sudo dmesg -C") before performing an atomic commit, to be able to only collect the extract of the log relevant to the atomic commit. Having some kind of "marker" mechanism could be pretty cool. "Mark" the log stream before performing an atomic commit (ideally that'd just return e.g. an uint64 offset), then on failure request the logs collected after that mark.
Re: [PATCH 1/3] drm/i915/gt: Spread virtual engines over idle engines
On 17/11/2021 22:49, Vinay Belgaumkar wrote: From: Chris Wilson Everytime we come to the end of a virtual engine's context, re-randomise it's siblings[]. As we schedule the siblings' tasklets in the order they are in the array, earlier entries are executed first (when idle) and so will be preferred when scheduling the next virtual request. Currently, we only update the array when switching onto a new idle engine, so we prefer to stick on the last execute engine, keeping the work compact. However, it can be beneficial to spread the work out across idle engines, so choose another sibling as our preferred target at the end of the context's execution. This partially brings back, from a different angle, the more dynamic scheduling behavior which has been lost since bugfix 90a987205c6c ("drm/i915/gt: Only swap to a random sibling once upon creation"). One day we could experiment with using engine busyness as criteria (instead of random). Back in the day busyness was kind of the best strategy, although sampled at submit, not at the trailing edge like here, but it still may be able to settle down to engine configuration better in some scenarios. Only testing could say. Still, from memory random also wasn't that bad so this should be okay for now. Reviewed-by: Tvrtko Ursulin Regards, Tvrtko Signed-off-by: Chris Wilson Cc: Vinay Belgaumkar Cc: Tvrtko Ursulin --- .../drm/i915/gt/intel_execlists_submission.c | 80 --- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index ca03880fa7e4..b95bbc8fb91a 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -539,6 +539,41 @@ static void execlists_schedule_in(struct i915_request *rq, int idx) GEM_BUG_ON(intel_context_inflight(ce) != rq->engine); } +static void virtual_xfer_context(struct virtual_engine *ve, +struct intel_engine_cs *engine) +{ + unsigned int n; + + if (likely(engine == ve->siblings[0])) + return; + + if (!intel_engine_has_relative_mmio(engine)) + lrc_update_offsets(&ve->context, engine); + + /* +* Move the bound engine to the top of the list for +* future execution. We then kick this tasklet first +* before checking others, so that we preferentially +* reuse this set of bound registers. +*/ + for (n = 1; n < ve->num_siblings; n++) { + if (ve->siblings[n] == engine) { + swap(ve->siblings[n], ve->siblings[0]); + break; + } + } +} + +static int ve_random_sibling(struct virtual_engine *ve) +{ + return prandom_u32_max(ve->num_siblings); +} + +static int ve_random_other_sibling(struct virtual_engine *ve) +{ + return 1 + prandom_u32_max(ve->num_siblings - 1); +} + static void resubmit_virtual_request(struct i915_request *rq, struct virtual_engine *ve) { @@ -578,8 +613,23 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce) rq->execution_mask != engine->mask) resubmit_virtual_request(rq, ve); - if (READ_ONCE(ve->request)) + /* +* Reschedule with a new "preferred" sibling. +* +* The tasklets are executed in the order of ve->siblings[], so +* siblings[0] receives preferrential treatment of greedily checking +* for execution of the virtual engine. At this point, the virtual +* engine is no longer in the current GPU cache due to idleness or +* contention, so it can be executed on any without penalty. We +* re-randomise at this point in order to spread light loads across +* the system, heavy overlapping loads will continue to be greedily +* executed by the first available engine. +*/ + if (READ_ONCE(ve->request)) { + virtual_xfer_context(ve, +ve->siblings[ve_random_other_sibling(ve)]); tasklet_hi_schedule(&ve->base.sched_engine->tasklet); + } } static void __execlists_schedule_out(struct i915_request * const rq, @@ -1030,32 +1080,6 @@ first_virtual_engine(struct intel_engine_cs *engine) return NULL; } -static void virtual_xfer_context(struct virtual_engine *ve, -struct intel_engine_cs *engine) -{ - unsigned int n; - - if (likely(engine == ve->siblings[0])) - return; - - GEM_BUG_ON(READ_ONCE(ve->context.inflight)); - if (!intel_engine_has_relative_mmio(engine)) - lrc_update_offsets(&ve->context, engine); - - /* -* Move the bound engine to the top of the list for -* future execution. We then kick this tasklet first -* before checking
Re: [PATCH v2 04/11] mmc: bcm2835: stop setting chan_config->slave_id
On Mon, 22 Nov 2021 at 23:23, Arnd Bergmann wrote: > > From: Arnd Bergmann > > The field is not interpreted by the DMA engine driver, as all the data > is passed from devicetree instead. Remove the assignment so the field > can eventually be deleted. > > Reviewed-by: Nicolas Saenz Julienne > Signed-off-by: Arnd Bergmann I think I acked the previous version, but nevermind: Acked-by: Ulf Hansson Kind regards Uffe > --- > drivers/mmc/host/bcm2835.c | 2 -- > 1 file changed, 2 deletions(-) > > diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c > index 8c2361e66277..463b707d9e99 100644 > --- a/drivers/mmc/host/bcm2835.c > +++ b/drivers/mmc/host/bcm2835.c > @@ -1293,14 +1293,12 @@ static int bcm2835_add_host(struct bcm2835_host *host) > > host->dma_cfg_tx.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; > host->dma_cfg_tx.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; > - host->dma_cfg_tx.slave_id = 13; /* DREQ channel */ > host->dma_cfg_tx.direction = DMA_MEM_TO_DEV; > host->dma_cfg_tx.src_addr = 0; > host->dma_cfg_tx.dst_addr = host->phys_addr + SDDATA; > > host->dma_cfg_rx.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; > host->dma_cfg_rx.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; > - host->dma_cfg_rx.slave_id = 13; /* DREQ channel */ > host->dma_cfg_rx.direction = DMA_DEV_TO_MEM; > host->dma_cfg_rx.src_addr = host->phys_addr + SDDATA; > host->dma_cfg_rx.dst_addr = 0; > -- > 2.29.2 >
[PATCH v2] drm: document DRM_IOCTL_MODE_GETFB2
There are a few details specific to the GETFB2 IOCTL. It's not immediately clear how user-space should check for the number of planes. Suggest using the handles field or the pitches field. The modifier array is filled with zeroes, ie. DRM_FORMAT_MOD_LINEAR. So explicitly tell user-space to not look at it unless the flag is set. Changes in v2 (Daniel): - Mention that handles should be used to compute the number of planes, and only refer to pitches as a fallback. - Reword bit about undefined modifier. Signed-off-by: Simon Ser Cc: Daniel Vetter Acked-by: Pekka Paalanen Acked-by: Daniel Stone --- include/uapi/drm/drm.h | 18 ++ 1 file changed, 18 insertions(+) diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 3b810b53ba8b..642808520d92 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -1096,6 +1096,24 @@ extern "C" { #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer) #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array) +/** + * DRM_IOCTL_MODE_GETFB2 - Get framebuffer metadata. + * + * This queries metadata about a framebuffer. User-space fills + * &drm_mode_fb_cmd2.fb_id as the input, and the kernels fills the rest of the + * struct as the output. + * + * If the client is DRM master or has &CAP_SYS_ADMIN, &drm_mode_fb_cmd2.handles + * will be filled with GEM buffer handles. Planes are valid until one has a + * zero handle -- this can be used to compute the number of planes. + * + * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid + * until one has a zero &drm_mode_fb_cmd2.pitches. + * + * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set + * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the + * modifier. Otherwise, user-space must ignore &drm_mode_fb_cmd2.modifier. + */ #define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2) /* -- 2.34.0
Patch "drm/prime: Fix use after free in mmap with drm_gem_ttm_mmap" has been added to the 5.15-stable tree
This is a note to let you know that I've just added the patch titled drm/prime: Fix use after free in mmap with drm_gem_ttm_mmap to the 5.15-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: drm-prime-fix-use-after-free-in-mmap-with-drm_gem_ttm_mmap.patch and it can be found in the queue-5.15 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let know about it. >From 8244a3bc27b3efd057da154b8d7e414670d5044f Mon Sep 17 00:00:00 2001 From: Anand K Mistry Date: Thu, 30 Sep 2021 09:00:07 +1000 Subject: drm/prime: Fix use after free in mmap with drm_gem_ttm_mmap From: Anand K Mistry commit 8244a3bc27b3efd057da154b8d7e414670d5044f upstream. drm_gem_ttm_mmap() drops a reference to the gem object on success. If the gem object's refcount == 1 on entry to drm_gem_prime_mmap(), that drop will free the gem object, and the subsequent drm_gem_object_get() will be a UAF. Fix by grabbing a reference before calling the mmap helper. This issue was forseen when the reference dropping was adding in commit 9786b65bc61ac ("drm/ttm: fix mmap refcounting"): "For that to work properly the drm_gem_object_get() call in drm_gem_ttm_mmap() must be moved so it happens before calling obj->funcs->mmap(), otherwise the gem refcount would go down to zero." Signed-off-by: Anand K Mistry Fixes: 9786b65bc61a ("drm/ttm: fix mmap refcounting") Cc: Gerd Hoffmann Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Cc: # v5.5+ Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20210930085932.1.I8043d61cc238e0168e2f4ca5f4783223434aa587@changeid Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_prime.c |6 -- 1 file changed, 4 insertions(+), 2 deletions(-) --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -719,11 +719,13 @@ int drm_gem_prime_mmap(struct drm_gem_ob if (obj->funcs && obj->funcs->mmap) { vma->vm_ops = obj->funcs->vm_ops; + drm_gem_object_get(obj); ret = obj->funcs->mmap(obj, vma); - if (ret) + if (ret) { + drm_gem_object_put(obj); return ret; + } vma->vm_private_data = obj; - drm_gem_object_get(obj); return 0; } Patches currently in stable-queue which might be from amis...@google.com are queue-5.15/drm-prime-fix-use-after-free-in-mmap-with-drm_gem_ttm_mmap.patch
Re: [PATCH bpf] treewide: add missing includes masked by cgroup -> bpf dependency
On 21-11-20 07:26:02, Jakub Kicinski wrote: > On Sat, 20 Nov 2021 15:30:11 +0800 Peter Chen wrote: > > > diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c > > > index 84dadfa726aa..9643b905e2d8 100644 > > > --- a/drivers/usb/cdns3/host.c > > > +++ b/drivers/usb/cdns3/host.c > > > @@ -10,6 +10,7 @@ > > > */ > > > > > > #include > > > +#include > > > > Should be "#include "? > > Why? Different files are missing different includes, this one needs > slab.h: > > ../drivers/usb/cdns3/host.c: In function ‘__cdns_host_init’: > ../drivers/usb/cdns3/host.c:86:2: error: implicit declaration of function > ‘kfree’; did you mean ‘vfree’? [-Werror=implicit-function-declaration] > kfree(cdns->xhci_plat_data); > ^ > vfree Oh, my fault. Acked-by: Peter Chen -- Thanks, Peter Chen
Re: [PATCH v2 12/63] thermal: intel: int340x_thermal: Use struct_group() for memcpy() region
On Wed, Aug 18, 2021 at 8:08 AM Kees Cook wrote: > > In preparation for FORTIFY_SOURCE performing compile-time and run-time > field bounds checking for memcpy(), avoid intentionally writing across > neighboring fields. > > Use struct_group() in struct art around members weight, and ac[0-9]_max, > so they can be referenced together. This will allow memcpy() and sizeof() > to more easily reason about sizes, improve readability, and avoid future > warnings about writing beyond the end of weight. > > "pahole" shows no size nor member offset changes to struct art. > "objdump -d" shows no meaningful object code changes (i.e. only source > line number induced differences). > > Cc: Zhang Rui > Cc: Daniel Lezcano > Cc: Amit Kucheria > Cc: linux...@vger.kernel.org > Signed-off-by: Kees Cook Rui, Srinivas, any comments here? > --- > .../intel/int340x_thermal/acpi_thermal_rel.c | 5 +- > .../intel/int340x_thermal/acpi_thermal_rel.h | 48 ++- > 2 files changed, 29 insertions(+), 24 deletions(-) > > diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > index a478cff8162a..e90690a234c4 100644 > --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c > @@ -250,8 +250,9 @@ static int fill_art(char __user *ubuf) > get_single_name(arts[i].source, art_user[i].source_device); > get_single_name(arts[i].target, art_user[i].target_device); > /* copy the rest int data in addition to source and target */ > - memcpy(&art_user[i].weight, &arts[i].weight, > - sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2)); > + BUILD_BUG_ON(sizeof(art_user[i].data) != > +sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2)); > + memcpy(&art_user[i].data, &arts[i].data, > sizeof(art_user[i].data)); > } > > if (copy_to_user(ubuf, art_user, art_len)) > diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > index 58822575fd54..78d942477035 100644 > --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h > @@ -17,17 +17,19 @@ > struct art { > acpi_handle source; > acpi_handle target; > - u64 weight; > - u64 ac0_max; > - u64 ac1_max; > - u64 ac2_max; > - u64 ac3_max; > - u64 ac4_max; > - u64 ac5_max; > - u64 ac6_max; > - u64 ac7_max; > - u64 ac8_max; > - u64 ac9_max; > + struct_group(data, > + u64 weight; > + u64 ac0_max; > + u64 ac1_max; > + u64 ac2_max; > + u64 ac3_max; > + u64 ac4_max; > + u64 ac5_max; > + u64 ac6_max; > + u64 ac7_max; > + u64 ac8_max; > + u64 ac9_max; > + ); > } __packed; > > struct trt { > @@ -47,17 +49,19 @@ union art_object { > struct { > char source_device[8]; /* ACPI single name */ > char target_device[8]; /* ACPI single name */ > - u64 weight; > - u64 ac0_max_level; > - u64 ac1_max_level; > - u64 ac2_max_level; > - u64 ac3_max_level; > - u64 ac4_max_level; > - u64 ac5_max_level; > - u64 ac6_max_level; > - u64 ac7_max_level; > - u64 ac8_max_level; > - u64 ac9_max_level; > + struct_group(data, > + u64 weight; > + u64 ac0_max_level; > + u64 ac1_max_level; > + u64 ac2_max_level; > + u64 ac3_max_level; > + u64 ac4_max_level; > + u64 ac5_max_level; > + u64 ac6_max_level; > + u64 ac7_max_level; > + u64 ac8_max_level; > + u64 ac9_max_level; > + ); > }; > u64 __data[ACPI_NR_ART_ELEMENTS]; > }; > -- > 2.30.2 >
[Bug 211277] sometimes crash at s2ram-wake (Ryzen 3500U): amdgpu, drm, commit_tail, amdgpu_dm_atomic_commit_tail
https://bugzilla.kernel.org/show_bug.cgi?id=211277 --- Comment #75 from James Zhu (jam...@amd.com) --- (In reply to kolAflash from comment #74) > @James Zhu > > Tested 5.15.2 for over a week and more than 50 standby-wakeups. > No problems! > Thanks :-) > > I would be happy about a patch for the 5.10 longterm kernel. > The bug became a problem with v5.10-rc3 (see comment 14), just before Debian > made 5.10-longterm the Debian-11 kernel. So it would be great if I and > probably other Debian-11 users could finally use that AMD GPU without > workarounds. Hi @Alex Deucher, Can you help on this request? thanks! James -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
Re: [PATCH v2] i2c: tegra: Add ACPI support
Hi Akhil, Thank you for the patch! Yet something to improve: [auto build test ERROR on tegra/for-next] [also build test ERROR on v5.16-rc2 next-20211123] [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/Akhil-R/i2c-tegra-Add-ACPI-support/20211123-151636 base: https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git for-next config: m68k-randconfig-r011-20211123 (https://download.01.org/0day-ci/archive/20211123/202111232153.mpoejdrv-...@intel.com/config.gz) compiler: m68k-linux-gcc (GCC) 11.2.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/dec174be801f41a9e42f4381c59c2357c25e40fb git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Akhil-R/i2c-tegra-Add-ACPI-support/20211123-151636 git checkout dec174be801f41a9e42f4381c59c2357c25e40fb # save the config file to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=m68k If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All errors (new ones prefixed by >>): drivers/i2c/busses/i2c-tegra.c: In function 'tegra_i2c_init': >> drivers/i2c/busses/i2c-tegra.c:623:23: error: implicit declaration of >> function 'acpi_has_method'; did you mean 'acpi_has_watchdog'? >> [-Werror=implicit-function-declaration] 623 | if (handle && acpi_has_method(handle, "_RST")) | ^~~ | acpi_has_watchdog cc1: some warnings being treated as errors vim +623 drivers/i2c/busses/i2c-tegra.c 608 609 static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) 610 { 611 u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode; 612 acpi_handle handle = ACPI_HANDLE(i2c_dev->dev); 613 int err; 614 615 /* 616 * The reset shouldn't ever fail in practice. The failure will be a 617 * sign of a severe problem that needs to be resolved. Still we don't 618 * want to fail the initialization completely because this may break 619 * kernel boot up since voltage regulators use I2C. Hence, we will 620 * emit a noisy warning on error, which won't stay unnoticed and 621 * won't hose machine entirely. 622 */ > 623 if (handle && acpi_has_method(handle, "_RST")) 624 err = (acpi_evaluate_object(handle, "_RST", NULL, NULL)); 625 else 626 err = reset_control_reset(i2c_dev->rst); 627 628 WARN_ON_ONCE(err); 629 630 if (i2c_dev->is_dvc) 631 tegra_dvc_init(i2c_dev); 632 633 val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN | 634FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2); 635 636 if (i2c_dev->hw->has_multi_master_mode) 637 val |= I2C_CNFG_MULTI_MASTER_MODE; 638 639 i2c_writel(i2c_dev, val, I2C_CNFG); 640 i2c_writel(i2c_dev, 0, I2C_INT_MASK); 641 642 if (i2c_dev->is_vi) 643 tegra_i2c_vi_init(i2c_dev); 644 645 switch (i2c_dev->bus_clk_rate) { 646 case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ: 647 default: 648 tlow = i2c_dev->hw->tlow_fast_fastplus_mode; 649 thigh = i2c_dev->hw->thigh_fast_fastplus_mode; 650 tsu_thd = i2c_dev->hw->setup_hold_time_fast_fast_plus_mode; 651 652 if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ) 653 non_hs_mode = i2c_dev->hw->clk_divisor_fast_plus_mode; 654 else 655 non_hs_mode = i2c_dev->hw->clk_divisor_fast_mode; 656 break; 657 658 case 0 ... I2C_MAX_STANDARD_MODE_FREQ: 659 tlow = i2c_dev->hw->tlow_std_mode; 660 thigh = i2c_dev->hw->thigh_std_mode; 661 tsu_thd = i2c_dev->hw->setup_hold_time_std_mode; 662 non_hs_mode = i2c_dev->hw->clk_divisor_std_mode; 663 break; 664 } 665 666 /* make sure clock divisor programmed correctly */ 667 clk_d
[PATCH 1/9] gpu: host1x: Add missing DMA API include
Host1x seems to be relying on picking up dma-mapping.h transitively from iova.h, which has no reason to include it in the first place. Fix the former issue before we totally break things by fixing the latter one. CC: Thierry Reding CC: Mikko Perttunen CC: dri-devel@lists.freedesktop.org CC: linux-te...@vger.kernel.org Signed-off-by: Robin Murphy --- Feel free to pick this into drm-misc-next or drm-misc-fixes straight away if that suits - it's only to avoid a build breakage once the rest of the series gets queued. Robin. drivers/gpu/host1x/bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index 218e3718fd68..881fad5c3307 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include -- 2.28.0.dirty
completely rework the dma_resv semantic
Hi guys, as discussed before this set of patches completely rework the dma_resv semantic and spreads the new handling over all the existing drivers and users. First of all this drops the DAG approach because it requires that every single driver implements those relatively complicated rules correctly and any violation of that immediately leads to either corruption of freed memory or even more severe security problems. Instead we just keep all fences around all the time until they are signaled. Only fences with the same context are assumed to be signaled in the correct order since this is exercised elsewhere as well. Replacing fences is now only supported for hardware mechanism like VM page table updates where the hardware can guarantee that the resource can't be accessed any more. Then the concept of a single exclusive fence and multiple shared fences is dropped as well. Instead the dma_resv object is now just a container for dma_fence objects where each fence has associated usage flags. Those use flags describe how the operation represented by the dma_fence object is using the resource protected by the dma_resv object. This allows us to add multiple fences for each usage type. Additionally to the existing WRITE/READ usages this patch set also adds the new KERNEL and OTHER usages. The KERNEL usages is used in cases where the kernel needs to do some operation with the resource protected by the dma_resv object, like copies or clears. Those are mandatory to wait for when dynamic memory management is used. The OTHER usage is for cases where we don't want that the operation represented by the dma_fence object participate in any implicit sync but needs to be respected by the kernel memory management. Examples for those are VM page table updates and preemption fences. While doing this the new implementation cleans up existing workarounds all over the place, but especially amdgpu and TTM. Surprisingly I also found two use cases for the KERNEL/OTHER usage in i915 and Nouveau, those might need more thoughts. In general the existing functionality should been preserved, the only downside is that we now always need to reserve a slot before adding a fence. The newly added call to the reservation function can probably use some more cleanup. TODOs: Testing, testing, testing, doublechecking the newly added kerneldoc for any typos. Please review and/or comment, Christian.
[PATCH 01/26] drm/amdgpu: partially revert "svm bo enable_signal call condition"
Partially revert commit 5f319c5c21b5909abb43d8aadc92a8aa549ee443. First of all this is illegal use of RCU to call dma_fence_enable_sw_signaling() since we don't hold a reference to the fence in question and can crash badly. Then the code doesn't seem to have the intended effect since only the exclusive fence is handled, but the KFD fences are always added as shared fence. Only keep the handling to throw away the content of SVM BOs. Signed-off-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 9 - 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index eab4380f28e5..c15687ce67c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -116,17 +116,8 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, abo = ttm_to_amdgpu_bo(bo); if (abo->flags & AMDGPU_AMDKFD_CREATE_SVM_BO) { - struct dma_fence *fence; - struct dma_resv *resv = &bo->base._resv; - - rcu_read_lock(); - fence = rcu_dereference(resv->fence_excl); - if (fence && !fence->ops->signaled) - dma_fence_enable_sw_signaling(fence); - placement->num_placement = 0; placement->num_busy_placement = 0; - rcu_read_unlock(); return; } -- 2.25.1
[PATCH 03/26] dma-buf: make fence mandatory for dma_resv_add_excl_fence
Calling dma_resv_add_excl_fence() with the fence as NULL and expecting that that this frees up the fences is simply abuse of the internals of the dma_resv object. Rework how pruning fences works and make the fence parameter mandatory. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c | 39 ++ 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index f6499e87963c..e627a4274ff6 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -96,6 +96,34 @@ static void dma_resv_list_free(struct dma_resv_list *list) kfree_rcu(list, rcu); } +/** + * dma_resv_list_prune - drop all signaled fences + * @list: list to check for signaled fences + * @obj: dma_resv object for lockdep + * + * Replace all the signaled fences with the stub fence to free them up. + */ +static void dma_resv_list_prune(struct dma_resv_list *list, + struct dma_resv *obj) +{ + unsigned int i; + + if (!list) + return; + + for (i = 0; i < list->shared_count; ++i) { + struct dma_fence *fence; + + fence = rcu_dereference_protected(list->shared[i], + dma_resv_held(obj)); + if (!dma_fence_is_signaled(fence)) + continue; + + RCU_INIT_POINTER(list->shared[i], dma_fence_get_stub()); + dma_fence_put(fence); + } +} + /** * dma_resv_init - initialize a reservation object * @obj: the reservation object @@ -305,8 +333,7 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence) if (old) i = old->shared_count; - if (fence) - dma_fence_get(fence); + dma_fence_get(fence); write_seqcount_begin(&obj->seq); /* write_seqcount_begin provides the necessary memory barrier */ @@ -334,8 +361,12 @@ void dma_resv_prune(struct dma_resv *obj) { dma_resv_assert_held(obj); - if (dma_resv_test_signaled(obj, true)) - dma_resv_add_excl_fence(obj, NULL); + write_seqcount_begin(&obj->seq); + if (obj->fence_excl && dma_fence_is_signaled(obj->fence_excl)) + dma_fence_put(rcu_replace_pointer(obj->fence_excl, NULL, + dma_resv_held(obj))); + dma_resv_list_prune(dma_resv_shared_list(obj), obj); + write_seqcount_end(&obj->seq); } EXPORT_SYMBOL(dma_resv_prune_unlocked); -- 2.25.1
[PATCH 07/26] dma-buf: drop excl_fence parameter from dma_resv_get_fences
Returning the exclusive fence separately is no longer used. Instead add a write parameter to indicate the use case. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c | 48 drivers/dma-buf/st-dma-resv.c| 26 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 6 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 3 +- include/linux/dma-resv.h | 4 +- 6 files changed, 31 insertions(+), 58 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 611bba5528ad..0a69f4b7e6b5 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -675,57 +675,45 @@ EXPORT_SYMBOL(dma_resv_copy_fences); * dma_resv_get_fences - Get an object's shared and exclusive * fences without update side lock held * @obj: the reservation object - * @fence_excl: the returned exclusive fence (or NULL) - * @shared_count: the number of shared fences returned - * @shared: the array of shared fence ptrs returned (array is krealloc'd to - * the required size, and must be freed by caller) - * - * Retrieve all fences from the reservation object. If the pointer for the - * exclusive fence is not specified the fence is put into the array of the - * shared fences as well. Returns either zero or -ENOMEM. + * @write: true if we should return all fences + * @num_fences: the number of fences returned + * @fences: the array of fence ptrs returned (array is krealloc'd to the + * required size, and must be freed by caller) + * + * Retrieve all fences from the reservation object. + * Returns either zero or -ENOMEM. */ -int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **fence_excl, - unsigned int *shared_count, struct dma_fence ***shared) +int dma_resv_get_fences(struct dma_resv *obj, bool write, + unsigned int *num_fences, struct dma_fence ***fences) { struct dma_resv_iter cursor; struct dma_fence *fence; - *shared_count = 0; - *shared = NULL; - - if (fence_excl) - *fence_excl = NULL; + *num_fences = 0; + *fences = NULL; - dma_resv_iter_begin(&cursor, obj, true); + dma_resv_iter_begin(&cursor, obj, write); dma_resv_for_each_fence_unlocked(&cursor, fence) { if (dma_resv_iter_is_restarted(&cursor)) { unsigned int count; - while (*shared_count) - dma_fence_put((*shared)[--(*shared_count)]); + while (*num_fences) + dma_fence_put((*fences)[--(*num_fences)]); - if (fence_excl) - dma_fence_put(*fence_excl); - - count = cursor.shared_count; - count += fence_excl ? 0 : 1; + count = cursor.shared_count + 1; /* Eventually re-allocate the array */ - *shared = krealloc_array(*shared, count, + *fences = krealloc_array(*fences, count, sizeof(void *), GFP_KERNEL); - if (count && !*shared) { + if (count && !*fences) { dma_resv_iter_end(&cursor); return -ENOMEM; } } - dma_fence_get(fence); - if (dma_resv_iter_is_exclusive(&cursor) && fence_excl) - *fence_excl = fence; - else - (*shared)[(*shared_count)++] = fence; + (*fences)[(*num_fences)++] = dma_fence_get(fence); } dma_resv_iter_end(&cursor); diff --git a/drivers/dma-buf/st-dma-resv.c b/drivers/dma-buf/st-dma-resv.c index bc32b3eedcb6..cbe999c6e7a6 100644 --- a/drivers/dma-buf/st-dma-resv.c +++ b/drivers/dma-buf/st-dma-resv.c @@ -275,7 +275,7 @@ static int test_shared_for_each_unlocked(void *arg) static int test_get_fences(void *arg, bool shared) { - struct dma_fence *f, *excl = NULL, **fences = NULL; + struct dma_fence *f, **fences = NULL; struct dma_resv resv; int r, i; @@ -304,35 +304,19 @@ static int test_get_fences(void *arg, bool shared) } dma_resv_unlock(&resv); - r = dma_resv_get_fences(&resv, &excl, &i, &fences); + r = dma_resv_get_fences(&resv, shared, &i, &fences); if (r) { pr_err("get_fences failed\n"); goto err_free; } - if (shared) { - if (excl != NULL) { - pr_err("get_fences returned unexpected excl fence\n"); - goto err_free; - } - if (i != 1 || fences[0] != f) { -
[PATCH 02/26] dma-buf: cleanup pruning of dma_resv objects
The i915 driver implements a prune function which is called when it is very likely that the fences inside the dma_resv object can be removed because they are all signaled. TTM does something similar after waiting for the dma_resv to be idle. Move those functions into the dma-resv.c code since the behavior of pruning fences is something internal to the object. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c | 32 drivers/gpu/drm/i915/Makefile| 1 - drivers/gpu/drm/i915/dma_resv_utils.c| 17 --- drivers/gpu/drm/i915/dma_resv_utils.h| 13 drivers/gpu/drm/i915/gem/i915_gem_shrinker.c | 3 +- drivers/gpu/drm/i915/gem/i915_gem_wait.c | 3 +- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- include/linux/dma-resv.h | 2 ++ 8 files changed, 37 insertions(+), 36 deletions(-) delete mode 100644 drivers/gpu/drm/i915/dma_resv_utils.c delete mode 100644 drivers/gpu/drm/i915/dma_resv_utils.h diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index ff3c0558b3b8..f6499e87963c 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -324,6 +324,38 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence) } EXPORT_SYMBOL(dma_resv_add_excl_fence); +/** + * dma_resv_prune - remove signaled fences + * @obj: The dma_resv object to prune + * + * Remove all the signaled fences from the dma_resv object. + */ +void dma_resv_prune(struct dma_resv *obj) +{ + dma_resv_assert_held(obj); + + if (dma_resv_test_signaled(obj, true)) + dma_resv_add_excl_fence(obj, NULL); +} +EXPORT_SYMBOL(dma_resv_prune_unlocked); + +/** + * dma_resv_prune_unlocked - try to remove signaled fences + * @obj: The dma_resv object to prune + * + * Try to lock the object, test if it is signaled and if yes then remove all the + * signaled fences. + */ +void dma_resv_prune_unlocked(struct dma_resv *obj) +{ + if (!dma_resv_trylock(obj)) + return; + + dma_resv_prune(obj); + dma_resv_unlock(obj); +} +EXPORT_SYMBOL(dma_resv_prune); + /** * dma_resv_iter_restart_unlocked - restart the unlocked iterator * @cursor: The dma_resv_iter object to restart diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 660bb03de6fc..5c1af130cb6d 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -60,7 +60,6 @@ i915-y += i915_drv.o \ # core library code i915-y += \ - dma_resv_utils.o \ i915_memcpy.o \ i915_mm.o \ i915_sw_fence.o \ diff --git a/drivers/gpu/drm/i915/dma_resv_utils.c b/drivers/gpu/drm/i915/dma_resv_utils.c deleted file mode 100644 index 7df91b7e4ca8.. --- a/drivers/gpu/drm/i915/dma_resv_utils.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2020 Intel Corporation - */ - -#include - -#include "dma_resv_utils.h" - -void dma_resv_prune(struct dma_resv *resv) -{ - if (dma_resv_trylock(resv)) { - if (dma_resv_test_signaled(resv, true)) - dma_resv_add_excl_fence(resv, NULL); - dma_resv_unlock(resv); - } -} diff --git a/drivers/gpu/drm/i915/dma_resv_utils.h b/drivers/gpu/drm/i915/dma_resv_utils.h deleted file mode 100644 index b9d8fb5f8367.. --- a/drivers/gpu/drm/i915/dma_resv_utils.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2020 Intel Corporation - */ - -#ifndef DMA_RESV_UTILS_H -#define DMA_RESV_UTILS_H - -struct dma_resv; - -void dma_resv_prune(struct dma_resv *resv); - -#endif /* DMA_RESV_UTILS_H */ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c index 5ab136ffdeb2..48029bbda682 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c @@ -15,7 +15,6 @@ #include "gt/intel_gt_requests.h" -#include "dma_resv_utils.h" #include "i915_trace.h" static bool swap_available(void) @@ -229,7 +228,7 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww, i915_gem_object_unlock(obj); } - dma_resv_prune(obj->base.resv); + dma_resv_prune_unlocked(obj->base.resv); scanned += obj->base.size >> PAGE_SHIFT; skip: diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index f11325484110..75b58aa8d4a7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -10,7 +10,6 @@ #include "gt/intel_engine.h" -#include "dma_resv_utils.h" #include "i915_gem_ioctls.h" #include "i915_gem_object.h" @@ -57,7 +56,7 @@ i915_gem_object_wait_reservation(struct dma_resv *resv, * signaled. */ if (timeout > 0) - dma_re
[PATCH 04/26] drm/qxl: use iterator instead of dma_resv_shared_list
I'm not sure why it is useful to know the number of fences in the reservation object, but we try to avoid exposing the dma_resv_shared_list() function. So use the iterator instead. If more information is desired we could use dma_resv_describe() as well. Signed-off-by: Christian König --- drivers/gpu/drm/qxl/qxl_debugfs.c | 17 ++--- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c index 1f9a59601bb1..6a36b0fd845c 100644 --- a/drivers/gpu/drm/qxl/qxl_debugfs.c +++ b/drivers/gpu/drm/qxl/qxl_debugfs.c @@ -57,13 +57,16 @@ qxl_debugfs_buffers_info(struct seq_file *m, void *data) struct qxl_bo *bo; list_for_each_entry(bo, &qdev->gem.objects, list) { - struct dma_resv_list *fobj; - int rel; - - rcu_read_lock(); - fobj = dma_resv_shared_list(bo->tbo.base.resv); - rel = fobj ? fobj->shared_count : 0; - rcu_read_unlock(); + struct dma_resv_iter cursor; + struct dma_fence *fence; + int rel = 0; + + dma_resv_iter_begin(&cursor, bo->tbo.base.resv, true); + dma_resv_for_each_fence_unlocked(&cursor, fence) { + if (dma_resv_iter_is_restarted(&cursor)) + rel = 0; + ++rel; + } seq_printf(m, "size %ld, pc %d, num releases %d\n", (unsigned long)bo->tbo.base.size, -- 2.25.1
[PATCH 05/26] dma-buf: add dma_resv_replace_fences
This function allows to replace fences from the shared fence list when we can gurantee that the operation represented by the original fence has finished or no accesses to the resources protected by the dma_resv object any more when the new fence finishes. Then use this function in the amdkfd code when BOs are unmapped from the process. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c| 43 .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 49 +++ include/linux/dma-resv.h | 2 + 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index e627a4274ff6..0daed67cab0e 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -312,6 +312,49 @@ void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence) } EXPORT_SYMBOL(dma_resv_add_shared_fence); +/** + * dma_resv_replace_fences - replace fences in the dma_resv obj + * @obj: the reservation object + * @context: the context of the fences to replace + * @replacement: the new fence to use instead + * + * Replace fences with a specified context with a new fence. Only valid if the + * operation represented by the original fences is completed or has no longer + * access to the resources protected by the dma_resv object when the new fence + * completes. + */ +void dma_resv_replace_fences(struct dma_resv *obj, uint64_t context, +struct dma_fence *replacement) +{ + struct dma_resv_list *list; + struct dma_fence *old; + unsigned int i; + + dma_resv_assert_held(obj); + + write_seqcount_begin(&obj->seq); + + old = dma_resv_excl_fence(obj); + if (old->context == context) { + RCU_INIT_POINTER(obj->fence_excl, dma_fence_get(replacement)); + dma_fence_put(old); + } + + list = dma_resv_shared_list(obj); + for (i = 0; list && i < list->shared_count; ++i) { + old = rcu_dereference_protected(list->shared[i], + dma_resv_held(obj)); + if (old->context != context) + continue; + + rcu_assign_pointer(list->shared[i], dma_fence_get(replacement)); + dma_fence_put(old); + } + + write_seqcount_end(&obj->seq); +} +EXPORT_SYMBOL(dma_resv_replace_fences); + /** * dma_resv_add_excl_fence - Add an exclusive fence. * @obj: the reservation object diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 71acd577803e..b558ef0f8c4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -236,53 +236,18 @@ void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo) static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, struct amdgpu_amdkfd_fence *ef) { - struct dma_resv *resv = bo->tbo.base.resv; - struct dma_resv_list *old, *new; - unsigned int i, j, k; + struct dma_fence *replacement; if (!ef) return -EINVAL; - old = dma_resv_shared_list(resv); - if (!old) - return 0; - - new = kmalloc(struct_size(new, shared, old->shared_max), GFP_KERNEL); - if (!new) - return -ENOMEM; - - /* Go through all the shared fences in the resevation object and sort -* the interesting ones to the end of the list. + /* TODO: Instead of block before we should use the fence of the page +* table update and TLB flush here directly. */ - for (i = 0, j = old->shared_count, k = 0; i < old->shared_count; ++i) { - struct dma_fence *f; - - f = rcu_dereference_protected(old->shared[i], - dma_resv_held(resv)); - - if (f->context == ef->base.context) - RCU_INIT_POINTER(new->shared[--j], f); - else - RCU_INIT_POINTER(new->shared[k++], f); - } - new->shared_max = old->shared_max; - new->shared_count = k; - - /* Install the new fence list, seqcount provides the barriers */ - write_seqcount_begin(&resv->seq); - RCU_INIT_POINTER(resv->fence, new); - write_seqcount_end(&resv->seq); - - /* Drop the references to the removed fences or move them to ef_list */ - for (i = j; i < old->shared_count; ++i) { - struct dma_fence *f; - - f = rcu_dereference_protected(new->shared[i], - dma_resv_held(resv)); - dma_fence_put(f); - } - kfree_rcu(old, rcu); - + replacement = dma_fence_get_stub(); + dma_resv_replace_fences(bo->tbo.base.resv, ef->base.context, + rep
[PATCH 06/26] dma-buf: finally make the dma_resv_list private
Drivers should never touch this directly. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c | 26 ++ include/linux/dma-resv.h | 26 +- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 0daed67cab0e..611bba5528ad 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -56,6 +56,19 @@ DEFINE_WD_CLASS(reservation_ww_class); EXPORT_SYMBOL(reservation_ww_class); +/** + * struct dma_resv_list - a list of shared fences + * @rcu: for internal use + * @shared_count: table of shared fences + * @shared_max: for growing shared fence table + * @shared: shared fence table + */ +struct dma_resv_list { + struct rcu_head rcu; + u32 shared_count, shared_max; + struct dma_fence __rcu *shared[]; +}; + /** * dma_resv_list_alloc - allocate fence list * @shared_max: number of fences we need space for @@ -161,6 +174,19 @@ void dma_resv_fini(struct dma_resv *obj) } EXPORT_SYMBOL(dma_resv_fini); +/** + * dma_resv_shared_list - get the reservation object's shared fence list + * @obj: the reservation object + * + * Returns the shared fence list. Caller must either hold the objects + * through dma_resv_lock() or the RCU read side lock through rcu_read_lock(), + * or one of the variants of each + */ +static inline struct dma_resv_list *dma_resv_shared_list(struct dma_resv *obj) +{ + return rcu_dereference_check(obj->fence, dma_resv_held(obj)); +} + /** * dma_resv_reserve_shared - Reserve space to add shared fences to * a dma_resv. diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index 0eb0c08c51c9..e0cec3a57c08 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -47,18 +47,7 @@ extern struct ww_class reservation_ww_class; -/** - * struct dma_resv_list - a list of shared fences - * @rcu: for internal use - * @shared_count: table of shared fences - * @shared_max: for growing shared fence table - * @shared: shared fence table - */ -struct dma_resv_list { - struct rcu_head rcu; - u32 shared_count, shared_max; - struct dma_fence __rcu *shared[]; -}; +struct dma_resv_list; /** * struct dma_resv - a reservation object manages fences for a buffer @@ -440,19 +429,6 @@ dma_resv_excl_fence(struct dma_resv *obj) return rcu_dereference_check(obj->fence_excl, dma_resv_held(obj)); } -/** - * dma_resv_shared_list - get the reservation object's shared fence list - * @obj: the reservation object - * - * Returns the shared fence list. Caller must either hold the objects - * through dma_resv_lock() or the RCU read side lock through rcu_read_lock(), - * or one of the variants of each - */ -static inline struct dma_resv_list *dma_resv_shared_list(struct dma_resv *obj) -{ - return rcu_dereference_check(obj->fence, dma_resv_held(obj)); -} - void dma_resv_init(struct dma_resv *obj); void dma_resv_fini(struct dma_resv *obj); int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences); -- 2.25.1
[PATCH 12/26] drm/vmwgfx: stop using dma_resv_excl_fence
Instead use the new dma_resv_get_singleton function. Signed-off-by: Christian König --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 8d1e869cc196..23c3fc2cbf10 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1168,8 +1168,10 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, vmw_bo_fence_single(bo, NULL); if (bo->moving) dma_fence_put(bo->moving); - bo->moving = dma_fence_get - (dma_resv_excl_fence(bo->base.resv)); + + /* TODO: This is actually a memory management dependency */ + return dma_resv_get_singleton(bo->base.resv, false, + &bo->moving); } return 0; -- 2.25.1
[PATCH 13/26] drm/radeon: stop using dma_resv_excl_fence
Instead use the new dma_resv_get_singleton function. Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_display.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 573154268d43..a6f875118f01 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -533,7 +533,12 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, DRM_ERROR("failed to pin new rbo buffer before flip\n"); goto cleanup; } - work->fence = dma_fence_get(dma_resv_excl_fence(new_rbo->tbo.base.resv)); + r = dma_resv_get_singleton(new_rbo->tbo.base.resv, false, &work->fence); + if (r) { + radeon_bo_unreserve(new_rbo); + DRM_ERROR("failed to get new rbo buffer fences\n"); + goto cleanup; + } radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL); radeon_bo_unreserve(new_rbo); -- 2.25.1
[PATCH 09/26] RDMA: use dma_resv_wait() instead of extracting the fence
Use dma_resv_wait() instead of extracting the exclusive fence and waiting on it manually. Signed-off-by: Christian König --- drivers/infiniband/core/umem_dmabuf.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c index f0760741f281..d32cd7538835 100644 --- a/drivers/infiniband/core/umem_dmabuf.c +++ b/drivers/infiniband/core/umem_dmabuf.c @@ -16,7 +16,6 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) { struct sg_table *sgt; struct scatterlist *sg; - struct dma_fence *fence; unsigned long start, end, cur = 0; unsigned int nmap = 0; int i; @@ -68,11 +67,8 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) * may be not up-to-date. Wait for the exporter to finish * the migration. */ - fence = dma_resv_excl_fence(umem_dmabuf->attach->dmabuf->resv); - if (fence) - return dma_fence_wait(fence, false); - - return 0; + return dma_resv_wait_timeout(umem_dmabuf->attach->dmabuf->resv, false, +false, MAX_SCHEDULE_TIMEOUT); } EXPORT_SYMBOL(ib_umem_dmabuf_map_pages); -- 2.25.1
[PATCH 08/26] dma-buf: add dma_resv_get_singleton
Add a function to simplify getting a single fence for all the fences in the dma_resv object. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c | 50 ++ include/linux/dma-resv.h | 2 ++ 2 files changed, 52 insertions(+) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 0a69f4b7e6b5..f91ca023b550 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -34,6 +34,7 @@ */ #include +#include #include #include #include @@ -721,6 +722,55 @@ int dma_resv_get_fences(struct dma_resv *obj, bool write, } EXPORT_SYMBOL_GPL(dma_resv_get_fences); +/** + * dma_resv_get_singleton - Get a single fence for all the fences + * @obj: the reservation object + * @write: true if we should return all fences + * @fence: the resulting fence + * + * Get a single fence representing all the fences inside the resv object. + * Returns either 0 for success or -ENOMEM. + * + * Warning: This can't be used like this when adding the fence back to the resv + * object since that can lead to stack corruption when finalizing the + * dma_fence_array. + */ +int dma_resv_get_singleton(struct dma_resv *obj, bool write, + struct dma_fence **fence) +{ + struct dma_fence_array *array; + struct dma_fence **fences; + unsigned count; + int r; + + r = dma_resv_get_fences(obj, write, &count, &fences); +if (r) + return r; + + if (count == 0) { + *fence = NULL; + return 0; + } + + if (count == 1) { + *fence = fences[0]; + kfree(fences); + return 0; + } + + array = dma_fence_array_create(count, fences, + dma_fence_context_alloc(1), + 1, false); + if (!array) { + kfree(fences); + return -ENOMEM; + } + + *fence = &array->base; + return 0; +} +EXPORT_SYMBOL_GPL(dma_resv_get_singleton); + /** * dma_resv_wait_timeout - Wait on reservation's objects * shared and/or exclusive fences. diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index 09b676b87c35..082f77b7bc63 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -440,6 +440,8 @@ void dma_resv_prune(struct dma_resv *obj); void dma_resv_prune_unlocked(struct dma_resv *obj); int dma_resv_get_fences(struct dma_resv *obj, bool write, unsigned int *num_fences, struct dma_fence ***fences); +int dma_resv_get_singleton(struct dma_resv *obj, bool write, + struct dma_fence **fence); int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src); long dma_resv_wait_timeout(struct dma_resv *obj, bool wait_all, bool intr, unsigned long timeout); -- 2.25.1
[PATCH 10/26] drm/etnaviv: stop using dma_resv_excl_fence
We can get the excl fence together with the shared ones as well. Signed-off-by: Christian König --- drivers/gpu/drm/etnaviv/etnaviv_gem.h| 1 - drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 14 +- drivers/gpu/drm/etnaviv/etnaviv_sched.c | 10 -- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index 98e60df882b6..f596d743baa3 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -80,7 +80,6 @@ struct etnaviv_gem_submit_bo { u64 va; struct etnaviv_gem_object *obj; struct etnaviv_vram_mapping *mapping; - struct dma_fence *excl; unsigned int nr_shared; struct dma_fence **shared; }; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 64c90ff348f2..4286dc93fdaa 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -188,15 +188,11 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit) if (submit->flags & ETNA_SUBMIT_NO_IMPLICIT) continue; - if (bo->flags & ETNA_SUBMIT_BO_WRITE) { - ret = dma_resv_get_fences(robj, true, &bo->nr_shared, - &bo->shared); - if (ret) - return ret; - } else { - bo->excl = dma_fence_get(dma_resv_excl_fence(robj)); - } - + ret = dma_resv_get_fences(robj, + !!(bo->flags & ETNA_SUBMIT_BO_WRITE), + &bo->nr_shared, &bo->shared); + if (ret) + return ret; } return ret; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index 180bb633d5c5..8c038a363d15 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -39,16 +39,6 @@ etnaviv_sched_dependency(struct drm_sched_job *sched_job, struct etnaviv_gem_submit_bo *bo = &submit->bos[i]; int j; - if (bo->excl) { - fence = bo->excl; - bo->excl = NULL; - - if (!dma_fence_is_signaled(fence)) - return fence; - - dma_fence_put(fence); - } - for (j = 0; j < bo->nr_shared; j++) { if (!bo->shared[j]) continue; -- 2.25.1
[PATCH 15/26] drm/amdgpu: use dma_resv_for_each_fence for CS workaround
Get the write fence using dma_resv_for_each_fence instead of accessing it manually. Signed-off-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 53e407ea4c89..7facd614e50a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1268,6 +1268,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, amdgpu_bo_list_for_each_entry(e, p->bo_list) { struct dma_resv *resv = e->tv.bo->base.resv; struct dma_fence_chain *chain = e->chain; + struct dma_resv_iter cursor; + struct dma_fence *fence; if (!chain) continue; @@ -1277,9 +1279,10 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, * submission in a dma_fence_chain and add it as exclusive * fence. */ - dma_fence_chain_init(chain, dma_resv_excl_fence(resv), -dma_fence_get(p->fence), 1); - + dma_resv_for_each_fence(&cursor, resv, false, fence) { + break; + } + dma_fence_chain_init(chain, fence, dma_fence_get(p->fence), 1); rcu_assign_pointer(resv->fence_excl, &chain->base); e->chain = NULL; } -- 2.25.1
[PATCH 16/26] dma-buf: finally make dma_resv_excl_fence private
Drivers should never touch this directly. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c | 17 + include/linux/dma-resv.h | 17 - 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index f91ca023b550..539b9b1df640 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -175,6 +175,23 @@ void dma_resv_fini(struct dma_resv *obj) } EXPORT_SYMBOL(dma_resv_fini); +/** + * dma_resv_excl_fence - return the object's exclusive fence + * @obj: the reservation object + * + * Returns the exclusive fence (if any). Caller must either hold the objects + * through dma_resv_lock() or the RCU read side lock through rcu_read_lock(), + * or one of the variants of each + * + * RETURNS + * The exclusive fence or NULL + */ +static inline struct dma_fence * +dma_resv_excl_fence(struct dma_resv *obj) +{ + return rcu_dereference_check(obj->fence_excl, dma_resv_held(obj)); +} + /** * dma_resv_shared_list - get the reservation object's shared fence list * @obj: the reservation object diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index 082f77b7bc63..062571c04bca 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -412,23 +412,6 @@ static inline void dma_resv_unlock(struct dma_resv *obj) ww_mutex_unlock(&obj->lock); } -/** - * dma_resv_excl_fence - return the object's exclusive fence - * @obj: the reservation object - * - * Returns the exclusive fence (if any). Caller must either hold the objects - * through dma_resv_lock() or the RCU read side lock through rcu_read_lock(), - * or one of the variants of each - * - * RETURNS - * The exclusive fence or NULL - */ -static inline struct dma_fence * -dma_resv_excl_fence(struct dma_resv *obj) -{ - return rcu_dereference_check(obj->fence_excl, dma_resv_held(obj)); -} - void dma_resv_init(struct dma_resv *obj); void dma_resv_fini(struct dma_resv *obj); int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences); -- 2.25.1
[PATCH 11/26] drm/nouveau: stop using dma_resv_excl_fence
Instead use the new dma_resv_get_singleton function. Signed-off-by: Christian König --- drivers/gpu/drm/nouveau/nouveau_bo.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index fa73fe57f97b..74f8652d2bd3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -959,7 +959,14 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct drm_device *dev = drm->dev; - struct dma_fence *fence = dma_resv_excl_fence(bo->base.resv); + struct dma_fence *fence; + int ret; + + /* TODO: This is actually a memory management dependency */ + ret = dma_resv_get_singleton(bo->base.resv, false, &fence); + if (ret) + dma_resv_wait_timeout(bo->base.resv, false, false, + MAX_SCHEDULE_TIMEOUT); nv10_bo_put_tile_region(dev, *old_tile, fence); *old_tile = new_tile; -- 2.25.1
[PATCH 23/26] dma-buf: specify usage while adding fences to dma_resv obj
Instead of distingting between shared and exclusive fences specify the fence usage while adding fences. Rework all drivers to use this interface instead and deprecate the old one. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c| 389 -- drivers/dma-buf/st-dma-resv.c | 109 ++--- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c| 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c| 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c| 4 +- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 12 +- drivers/gpu/drm/i915/gem/i915_gem_busy.c | 13 +- drivers/gpu/drm/i915/gem/i915_gem_clflush.c | 5 +- .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 4 +- .../drm/i915/gem/selftests/i915_gem_migrate.c | 2 +- drivers/gpu/drm/i915/i915_vma.c | 10 +- .../drm/i915/selftests/intel_memory_region.c | 2 +- drivers/gpu/drm/lima/lima_gem.c | 4 +- drivers/gpu/drm/msm/msm_gem_submit.c | 4 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 9 +- drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +- drivers/gpu/drm/panfrost/panfrost_job.c | 2 +- drivers/gpu/drm/qxl/qxl_release.c | 5 +- drivers/gpu/drm/radeon/radeon_object.c| 6 +- drivers/gpu/drm/radeon/radeon_vm.c| 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 6 +- drivers/gpu/drm/ttm/ttm_bo_util.c | 7 +- drivers/gpu/drm/ttm/ttm_execbuf_util.c| 10 +- drivers/gpu/drm/v3d/v3d_gem.c | 6 +- drivers/gpu/drm/vc4/vc4_gem.c | 4 +- drivers/gpu/drm/vgem/vgem_fence.c | 11 +- drivers/gpu/drm/virtio/virtgpu_gem.c | 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c| 5 +- include/linux/dma-resv.h | 88 ++-- 31 files changed, 312 insertions(+), 434 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 7ef8182a4b59..c1e5372bac6f 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -44,12 +44,12 @@ /** * DOC: Reservation Object Overview * - * The reservation object provides a mechanism to manage shared and - * exclusive fences associated with a buffer. A reservation object - * can have attached one exclusive fence (normally associated with - * write operations) or N shared fences (read operations). The RCU - * mechanism is used to protect read access to fences from locked - * write-side updates. + * The reservation object provides a mechanism to manage a container of + * dma_fence object associated with a resource. A reservation object + * can have any number of fences attaches to it. Each fence carring an usage + * parameter determining how the operation represented by the fence is using the + * resource. The RCU mechanism is used to protect read access to fences from + * locked write-side updates. * * See struct dma_resv for more details. */ @@ -57,36 +57,80 @@ DEFINE_WD_CLASS(reservation_ww_class); EXPORT_SYMBOL(reservation_ww_class); +/* Mask for the lower fence pointer bits */ +#define DMA_RESV_LIST_MASK 0x3 + /** - * struct dma_resv_list - a list of shared fences + * struct dma_resv_list - an array of fences * @rcu: for internal use - * @shared_count: table of shared fences - * @shared_max: for growing shared fence table - * @shared: shared fence table + * @num_fences: table of fences + * @max_fences: for growing fence table + * @table: fence table */ struct dma_resv_list { struct rcu_head rcu; - u32 shared_count, shared_max; - struct dma_fence __rcu *shared[]; + u32 num_fences, max_fences; + struct dma_fence __rcu *table[]; }; +/** + * dma_resv_list_entry - extract fence and usage from a list entry + * @list: the list to extract and entry from + * @index: which entry we want + * @check: lockdep check that the access is allowed + * @fence: the resulting fence + * @usage: the resulting usage + * + * Extract the fence and usage flags from an RCU protected entry in the list. + */ +static void dma_resv_list_entry(struct dma_resv_list *list, unsigned int index, + bool check, struct dma_fence **fence, + enum dma_resv_usage *usage) +{ + long tmp; + + tmp = (long)rcu_dereference_check(list->table[index], check); + *fence = (struct dma_fence *)(tmp & ~DMA_RESV_LIST_MASK); + if (usage) + *usage = tmp & DMA_RESV_LIST_MASK; +} + +/** + * dma_resv_list_set - set fence and usage at a specific index + * @list: the list to modify + * @index: where to make the change + * @fence: the fence to set + * @usage: the usage to set + * + * Set the fence and usage flags at the specific index in the list. + */ +static void dma_resv_list_set(struct dma_resv_list *list, +
[PATCH 21/26] drm/amdgpu: use dma_resv_get_singleton in amdgpu_pasid_free_cb
Makes the code a bit more simpler. Signed-off-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 23 +++ 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c index be48487e2ca7..888d97143177 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c @@ -107,36 +107,19 @@ static void amdgpu_pasid_free_cb(struct dma_fence *fence, void amdgpu_pasid_free_delayed(struct dma_resv *resv, u32 pasid) { - struct dma_fence *fence, **fences; struct amdgpu_pasid_cb *cb; - unsigned count; + struct dma_fence *fence; int r; - r = dma_resv_get_fences(resv, true, &count, &fences); + r = dma_resv_get_singleton(resv, true, &fence); if (r) goto fallback; - if (count == 0) { + if (!fence) { amdgpu_pasid_free(pasid); return; } - if (count == 1) { - fence = fences[0]; - kfree(fences); - } else { - uint64_t context = dma_fence_context_alloc(1); - struct dma_fence_array *array; - - array = dma_fence_array_create(count, fences, context, - 1, false); - if (!array) { - kfree(fences); - goto fallback; - } - fence = &array->base; - } - cb = kmalloc(sizeof(*cb), GFP_KERNEL); if (!cb) { /* Last resort when we are OOM */ -- 2.25.1
[PATCH 17/26] dma-buf: drop the DAG approach for the dma_resv object
So far we had the approach of using a directed acyclic graph with the dma_resv obj. This turned out to have many downsides, especially it means that every single driver and user of this interface needs to be aware of this restriction when adding fences. If the rules for the DAG are not followed then we end up with potential hard to debug memory corruption, information leaks or even elephant big security holes because we allow userspace to access freed up memory. Since we already took a step back from that by always looking at all fences we now go a step further and stop dropping the shared fences when a new exclusive one is added. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c | 14 +- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 539b9b1df640..3b0001c5ff3a 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -411,29 +411,17 @@ EXPORT_SYMBOL(dma_resv_replace_fences); void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence) { struct dma_fence *old_fence = dma_resv_excl_fence(obj); - struct dma_resv_list *old; - u32 i = 0; dma_resv_assert_held(obj); - old = dma_resv_shared_list(obj); - if (old) - i = old->shared_count; - dma_fence_get(fence); write_seqcount_begin(&obj->seq); /* write_seqcount_begin provides the necessary memory barrier */ RCU_INIT_POINTER(obj->fence_excl, fence); - if (old) - old->shared_count = 0; + dma_resv_list_prune(dma_resv_shared_list(obj), obj); write_seqcount_end(&obj->seq); - /* inplace update, no shared fences */ - while (i--) - dma_fence_put(rcu_dereference_protected(old->shared[i], - dma_resv_held(obj))); - dma_fence_put(old_fence); } EXPORT_SYMBOL(dma_resv_add_excl_fence); -- 2.25.1
[PATCH 19/26] drm: support more than one write fence in drm_gem_plane_helper_prepare_fb
Use dma_resv_get_singleton() here to eventually get more than one write fence as single fence. Signed-off-by: Christian König --- drivers/gpu/drm/drm_gem_atomic_helper.c | 18 +++--- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c index c3189afe10cb..9338ddb7edff 100644 --- a/drivers/gpu/drm/drm_gem_atomic_helper.c +++ b/drivers/gpu/drm/drm_gem_atomic_helper.c @@ -143,25 +143,21 @@ */ int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) { - struct dma_resv_iter cursor; struct drm_gem_object *obj; struct dma_fence *fence; + int ret; if (!state->fb) return 0; obj = drm_gem_fb_get_obj(state->fb, 0); - dma_resv_iter_begin(&cursor, obj->resv, false); - dma_resv_for_each_fence_unlocked(&cursor, fence) { - /* TODO: Currently there should be only one write fence, so this -* here works fine. But drm_atomic_set_fence_for_plane() should -* be changed to be able to handle more fences in general for -* multiple BOs per fb anyway. */ - dma_fence_get(fence); - break; - } - dma_resv_iter_end(&cursor); + ret = dma_resv_get_singleton(obj->resv, false, &fence); + if (ret) + return ret; + /* TODO: drm_atomic_set_fence_for_plane() should be changed to be able +* to handle more fences in general for multiple BOs per fb. +*/ drm_atomic_set_fence_for_plane(state, fence); return 0; } -- 2.25.1
[PATCH 14/26] drm/amdgpu: remove excl as shared workarounds
This was added because of the now dropped shared on excl dependency. Signed-off-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 6 -- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 0311d799a010..53e407ea4c89 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1275,14 +1275,11 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, /* * Work around dma_resv shortcommings by wrapping up the * submission in a dma_fence_chain and add it as exclusive -* fence, but first add the submission as shared fence to make -* sure that shared fences never signal before the exclusive -* one. +* fence. */ dma_fence_chain_init(chain, dma_resv_excl_fence(resv), dma_fence_get(p->fence), 1); - dma_resv_add_shared_fence(resv, p->fence); rcu_assign_pointer(resv->fence_excl, &chain->base); e->chain = NULL; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index a1e63ba4c54a..85d31d85c384 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -226,12 +226,6 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, if (!amdgpu_vm_ready(vm)) goto out_unlock; - fence = dma_resv_excl_fence(bo->tbo.base.resv); - if (fence) { - amdgpu_bo_fence(bo, fence, true); - fence = NULL; - } - r = amdgpu_vm_clear_freed(adev, vm, &fence); if (r || !fence) goto out_unlock; -- 2.25.1
[PATCH 20/26] drm/nouveau: support more than one write fence in fenv50_wndw_prepare_fb
Use dma_resv_get_singleton() here to eventually get more than one write fence as single fence. Signed-off-by: Christian König --- drivers/gpu/drm/nouveau/dispnv50/wndw.c | 14 +- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 133c8736426a..b55a8a723581 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -536,8 +536,6 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) struct nouveau_bo *nvbo; struct nv50_head_atom *asyh; struct nv50_wndw_ctxdma *ctxdma; - struct dma_resv_iter cursor; - struct dma_fence *fence; int ret; NV_ATOMIC(drm, "%s prepare: %p\n", plane->name, fb); @@ -560,13 +558,11 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) asyw->image.handle[0] = ctxdma->object.handle; } - dma_resv_iter_begin(&cursor, nvbo->bo.base.resv, false); - dma_resv_for_each_fence_unlocked(&cursor, fence) { - /* TODO: We only use the first writer here */ - asyw->state.fence = dma_fence_get(fence); - break; - } - dma_resv_iter_end(&cursor); + ret = dma_resv_get_singleton(nvbo->bo.base.resv, false, +&asyw->state.fence); + if (ret) + return ret; + asyw->image.offset[0] = nvbo->offset; if (wndw->func->prepare) { -- 2.25.1
[PATCH 18/26] dma-buf/drivers: make reserving a shared slot mandatory
Audit all the users of dma_resv_add_excl_fence() and make sure they reserve a shared slot also when only trying to add an exclusive fence. This is the next step towards handling the exclusive fence like a shared one. Signed-off-by: Christian König --- drivers/dma-buf/st-dma-resv.c | 64 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c| 8 +++ drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 8 +-- drivers/gpu/drm/i915/gem/i915_gem_clflush.c | 3 +- .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 8 +-- .../drm/i915/gem/selftests/i915_gem_migrate.c | 5 +- drivers/gpu/drm/i915/i915_vma.c | 6 ++ .../drm/i915/selftests/intel_memory_region.c | 7 ++ drivers/gpu/drm/lima/lima_gem.c | 10 ++- drivers/gpu/drm/msm/msm_gem_submit.c | 18 +++--- drivers/gpu/drm/nouveau/nouveau_fence.c | 9 +-- drivers/gpu/drm/panfrost/panfrost_job.c | 4 ++ drivers/gpu/drm/ttm/ttm_bo_util.c | 12 +++- drivers/gpu/drm/ttm/ttm_execbuf_util.c| 11 ++-- drivers/gpu/drm/v3d/v3d_gem.c | 15 +++-- drivers/gpu/drm/vgem/vgem_fence.c | 12 ++-- drivers/gpu/drm/virtio/virtgpu_gem.c | 9 +++ drivers/gpu/drm/vmwgfx/vmwgfx_bo.c| 16 +++-- 18 files changed, 133 insertions(+), 92 deletions(-) diff --git a/drivers/dma-buf/st-dma-resv.c b/drivers/dma-buf/st-dma-resv.c index cbe999c6e7a6..f33bafc78693 100644 --- a/drivers/dma-buf/st-dma-resv.c +++ b/drivers/dma-buf/st-dma-resv.c @@ -75,17 +75,16 @@ static int test_signaling(void *arg, bool shared) goto err_free; } - if (shared) { - r = dma_resv_reserve_shared(&resv, 1); - if (r) { - pr_err("Resv shared slot allocation failed\n"); - goto err_unlock; - } + r = dma_resv_reserve_shared(&resv, 1); + if (r) { + pr_err("Resv shared slot allocation failed\n"); + goto err_unlock; + } + if (shared) dma_resv_add_shared_fence(&resv, f); - } else { + else dma_resv_add_excl_fence(&resv, f); - } if (dma_resv_test_signaled(&resv, shared)) { pr_err("Resv unexpectedly signaled\n"); @@ -134,17 +133,16 @@ static int test_for_each(void *arg, bool shared) goto err_free; } - if (shared) { - r = dma_resv_reserve_shared(&resv, 1); - if (r) { - pr_err("Resv shared slot allocation failed\n"); - goto err_unlock; - } + r = dma_resv_reserve_shared(&resv, 1); + if (r) { + pr_err("Resv shared slot allocation failed\n"); + goto err_unlock; + } + if (shared) dma_resv_add_shared_fence(&resv, f); - } else { + else dma_resv_add_excl_fence(&resv, f); - } r = -ENOENT; dma_resv_for_each_fence(&cursor, &resv, shared, fence) { @@ -206,18 +204,17 @@ static int test_for_each_unlocked(void *arg, bool shared) goto err_free; } - if (shared) { - r = dma_resv_reserve_shared(&resv, 1); - if (r) { - pr_err("Resv shared slot allocation failed\n"); - dma_resv_unlock(&resv); - goto err_free; - } + r = dma_resv_reserve_shared(&resv, 1); + if (r) { + pr_err("Resv shared slot allocation failed\n"); + dma_resv_unlock(&resv); + goto err_free; + } + if (shared) dma_resv_add_shared_fence(&resv, f); - } else { + else dma_resv_add_excl_fence(&resv, f); - } dma_resv_unlock(&resv); r = -ENOENT; @@ -290,18 +287,17 @@ static int test_get_fences(void *arg, bool shared) goto err_resv; } - if (shared) { - r = dma_resv_reserve_shared(&resv, 1); - if (r) { - pr_err("Resv shared slot allocation failed\n"); - dma_resv_unlock(&resv); - goto err_resv; - } + r = dma_resv_reserve_shared(&resv, 1); + if (r) { + pr_err("Resv shared slot allocation failed\n"); + dma_resv_unlock(&resv); + goto err_resv; + } + if (shared) dma_resv_add_shared_fence(&resv, f); - } else { + else dma_resv_add_excl_fence(&resv, f); - } dma_resv_unlock(&resv); r = dma_resv_get_fences(&resv, shared, &i, &fences); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 4fcfc2313b8c..1becd4e7e463 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/d
[PATCH 24/26] dma-buf: wait for map to complete for static attachments
We have previously done that in the individual drivers but it is more defensive to move that into the common code. Dynamic attachments should wait for map operations to complete by themselves. Signed-off-by: Christian König --- drivers/dma-buf/dma-buf.c | 18 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 14 +- drivers/gpu/drm/nouveau/nouveau_prime.c | 17 + drivers/gpu/drm/radeon/radeon_prime.c | 16 +++- 4 files changed, 20 insertions(+), 45 deletions(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 528983d3ba64..d3dd602c4753 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -660,12 +660,24 @@ static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach, enum dma_data_direction direction) { struct sg_table *sg_table; + signed long ret; sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); + if (IS_ERR_OR_NULL(sg_table)) + return sg_table; + + if (!dma_buf_attachment_is_dynamic(attach)) { + ret = dma_resv_wait_timeout(attach->dmabuf->resv, + DMA_RESV_USAGE_KERNEL, true, + MAX_SCHEDULE_TIMEOUT); + if (ret < 0) { + attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, + direction); + return ERR_PTR(ret); + } + } - if (!IS_ERR_OR_NULL(sg_table)) - mangle_sg_table(sg_table); - + mangle_sg_table(sg_table); return sg_table; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index ae6ab93c868b..57a7a603f987 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -105,21 +105,9 @@ static int amdgpu_dma_buf_pin(struct dma_buf_attachment *attach) { struct drm_gem_object *obj = attach->dmabuf->priv; struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - int r; /* pin buffer into GTT */ - r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT); - if (r) - return r; - - if (bo->tbo.moving) { - r = dma_fence_wait(bo->tbo.moving, true); - if (r) { - amdgpu_bo_unpin(bo); - return r; - } - } - return 0; + return amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT); } /** diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 60019d0532fc..347488685f74 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -93,22 +93,7 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj) if (ret) return -EINVAL; - ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); - if (ret) - goto error; - - if (nvbo->bo.moving) - ret = dma_fence_wait(nvbo->bo.moving, true); - - ttm_bo_unreserve(&nvbo->bo); - if (ret) - goto error; - - return ret; - -error: - nouveau_bo_unpin(nvbo); - return ret; + return 0; } void nouveau_gem_prime_unpin(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c index 4a90807351e7..42a87948e28c 100644 --- a/drivers/gpu/drm/radeon/radeon_prime.c +++ b/drivers/gpu/drm/radeon/radeon_prime.c @@ -77,19 +77,9 @@ int radeon_gem_prime_pin(struct drm_gem_object *obj) /* pin buffer into GTT */ ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL); - if (unlikely(ret)) - goto error; - - if (bo->tbo.moving) { - ret = dma_fence_wait(bo->tbo.moving, false); - if (unlikely(ret)) { - radeon_bo_unpin(bo); - goto error; - } - } - - bo->prime_shared_count++; -error: + if (likely(ret == 0)) + bo->prime_shared_count++; + radeon_bo_unreserve(bo); return ret; } -- 2.25.1
[PATCH 26/26] drm/ttm: remove bo->moving
This is now handled by the DMA-buf framework in the dma_resv obj. Signed-off-by: Christian König --- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 13 --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c| 7 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c| 11 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 11 -- drivers/gpu/drm/ttm/ttm_bo.c | 10 ++ drivers/gpu/drm/ttm/ttm_bo_util.c | 7 drivers/gpu/drm/ttm/ttm_bo_vm.c | 34 +++ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 6 include/drm/ttm/ttm_bo_api.h | 2 -- 9 files changed, 40 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 0201a44ff630..a32035297995 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -2330,6 +2330,8 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) struct amdgpu_bo *bo = mem->bo; uint32_t domain = mem->domain; struct kfd_mem_attachment *attachment; + struct dma_resv_iter cursor; + struct dma_fence *fence; total_size += amdgpu_bo_size(bo); @@ -2344,10 +2346,13 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) goto validate_map_fail; } } - ret = amdgpu_sync_fence(&sync_obj, bo->tbo.moving); - if (ret) { - pr_debug("Memory eviction: Sync BO fence failed. Try again\n"); - goto validate_map_fail; + dma_resv_for_each_fence(&cursor, bo->tbo.base.resv, + DMA_RESV_USAGE_KERNEL, fence) { + ret = amdgpu_sync_fence(&sync_obj, fence); + if (ret) { + pr_debug("Memory eviction: Sync BO fence failed. Try again\n"); + goto validate_map_fail; + } } list_for_each_entry(attachment, &mem->attachments, list) { if (!attachment->is_mapped) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index a40ede9bccd0..3881a503a7bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -608,9 +608,8 @@ int amdgpu_bo_create(struct amdgpu_device *adev, if (unlikely(r)) goto fail_unreserve; - amdgpu_bo_fence(bo, fence, false); - dma_fence_put(bo->tbo.moving); - bo->tbo.moving = dma_fence_get(fence); + dma_resv_add_fence(bo->tbo.base.resv, fence, + DMA_RESV_USAGE_KERNEL); dma_fence_put(fence); } if (!bp->resv) @@ -1290,7 +1289,7 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence); if (!WARN_ON(r)) { - amdgpu_bo_fence(abo, fence, false); + dma_resv_add_fence(bo->base.resv, fence, DMA_RESV_USAGE_KERNEL); dma_fence_put(fence); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c index e3fbf0f10add..31913ae86de6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c @@ -74,13 +74,12 @@ static int amdgpu_vm_cpu_update(struct amdgpu_vm_update_params *p, { unsigned int i; uint64_t value; - int r; + long r; - if (vmbo->bo.tbo.moving) { - r = dma_fence_wait(vmbo->bo.tbo.moving, true); - if (r) - return r; - } + r = dma_resv_wait_timeout(vmbo->bo.tbo.base.resv, DMA_RESV_USAGE_KERNEL, + true, MAX_SCHEDULE_TIMEOUT); + if (r < 0) + return r; pe += (unsigned long)amdgpu_bo_kptr(&vmbo->bo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c index dbb551762805..bdb44cee19d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c @@ -204,14 +204,19 @@ static int amdgpu_vm_sdma_update(struct amdgpu_vm_update_params *p, struct amdgpu_bo *bo = &vmbo->bo; enum amdgpu_ib_pool_type pool = p->immediate ? AMDGPU_IB_POOL_IMMEDIATE : AMDGPU_IB_POOL_DELAYED; + struct dma_resv_iter cursor; unsigned int i, ndw, nptes; + struct dma_fence *fence; uint64_t *pte; int r; /* Wait for PD/PT moves to be completed */ - r = amdgpu_sync_f
[PATCH 22/26] dma-buf: add enum dma_resv_usage
This change adds the dma_resv_usage enum and allows us to specify why a dma_resv object is queried for its containing fences. Additional to that a dma_resv_usage_rw() helper function is added to aid retrieving the fences for a read or write userspace submission. This is then deployed to the different query functions of the dma_resv object and all of their users. Signed-off-by: Christian König --- drivers/dma-buf/dma-buf.c | 3 +- drivers/dma-buf/dma-resv.c| 33 +++--- drivers/dma-buf/st-dma-resv.c | 48 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c| 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c| 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c| 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c| 7 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +- drivers/gpu/drm/drm_gem.c | 6 +- drivers/gpu/drm/drm_gem_atomic_helper.c | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 6 +- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 10 +- .../gpu/drm/i915/display/intel_atomic_plane.c | 3 +- drivers/gpu/drm/i915/gem/i915_gem_busy.c | 4 +- drivers/gpu/drm/i915/gem/i915_gem_lmem.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_wait.c | 6 +- .../drm/i915/gem/selftests/i915_gem_dmabuf.c | 3 +- drivers/gpu/drm/i915/i915_request.c | 3 +- drivers/gpu/drm/i915/i915_sw_fence.c | 2 +- drivers/gpu/drm/msm/msm_gem.c | 3 +- drivers/gpu/drm/nouveau/dispnv50/wndw.c | 3 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 8 +- drivers/gpu/drm/nouveau/nouveau_fence.c | 3 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 3 +- drivers/gpu/drm/panfrost/panfrost_drv.c | 3 +- drivers/gpu/drm/qxl/qxl_debugfs.c | 3 +- drivers/gpu/drm/radeon/radeon_display.c | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 9 +- drivers/gpu/drm/radeon/radeon_mn.c| 4 +- drivers/gpu/drm/radeon/radeon_sync.c | 2 +- drivers/gpu/drm/radeon/radeon_uvd.c | 4 +- drivers/gpu/drm/scheduler/sched_main.c| 3 +- drivers/gpu/drm/ttm/ttm_bo.c | 18 +-- drivers/gpu/drm/vgem/vgem_fence.c | 4 +- drivers/gpu/drm/virtio/virtgpu_ioctl.c| 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c| 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 4 +- drivers/infiniband/core/umem_dmabuf.c | 3 +- include/linux/dma-resv.h | 106 +++--- 46 files changed, 244 insertions(+), 126 deletions(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 602b12d7470d..528983d3ba64 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -1124,7 +1124,8 @@ static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf, long ret; /* Wait on any implicit rendering fences */ - ret = dma_resv_wait_timeout(resv, write, true, MAX_SCHEDULE_TIMEOUT); + ret = dma_resv_wait_timeout(resv, dma_resv_usage_rw(write), + true, MAX_SCHEDULE_TIMEOUT); if (ret < 0) return ret; diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 3b0001c5ff3a..7ef8182a4b59 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -473,7 +473,7 @@ static void dma_resv_iter_restart_unlocked(struct dma_resv_iter *cursor) cursor->seq = read_seqcount_begin(&cursor->obj->seq); cursor->index = -1; cursor->shared_count = 0; - if (cursor->all_fences) { + if (cursor->usage >= DMA_RESV_USAGE_READ) { cursor->fences = dma_resv_shared_list(cursor->obj); if (cursor->fences) cursor->shared_count = cursor->fences->shared_count; @@ -580,7 +580,7 @@ struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor) dma_resv_assert_held(cursor->obj); cursor->index = 0; - if (cursor->all_fences) + if (cursor->usage >= DMA_RESV_USAGE_READ) cursor->fences = dma_resv_shared_list(cursor->obj); else cursor->fences = NULL; @@ -635,7 +635,7 @@ int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src) list = NULL; excl = NULL; - dma_resv_iter_begin(&cursor, src, true); + dma_resv_iter_begin(&cursor, src, DMA_RESV_USAGE_OTHER); dma_resv_for_each_fence_unlocked(&cursor, f) { if
[PATCH 25/26] amdgpu: remove DMA-buf fence workaround
Not needed any more now we have that inside the framework. Signed-off-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 52 +++-- 2 files changed, 6 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h index 044b41f0bfd9..529d52a204cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h @@ -34,7 +34,6 @@ struct amdgpu_fpriv; struct amdgpu_bo_list_entry { struct ttm_validate_buffer tv; struct amdgpu_bo_va *bo_va; - struct dma_fence_chain *chain; uint32_tpriority; struct page **user_pages; booluser_invalidated; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 92091e800022..413606d10080 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -576,14 +576,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); e->bo_va = amdgpu_vm_bo_find(vm, bo); - - if (bo->tbo.base.dma_buf && !amdgpu_bo_explicit_sync(bo)) { - e->chain = dma_fence_chain_alloc(); - if (!e->chain) { - r = -ENOMEM; - goto error_validate; - } - } } amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold, @@ -634,13 +626,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, } error_validate: - if (r) { - amdgpu_bo_list_for_each_entry(e, p->bo_list) { - dma_fence_chain_free(e->chain); - e->chain = NULL; - } + if (r) ttm_eu_backoff_reservation(&p->ticket, &p->validated); - } out: return r; } @@ -680,17 +667,9 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, { unsigned i; - if (error && backoff) { - struct amdgpu_bo_list_entry *e; - - amdgpu_bo_list_for_each_entry(e, parser->bo_list) { - dma_fence_chain_free(e->chain); - e->chain = NULL; - } - + if (error && backoff) ttm_eu_backoff_reservation(&parser->ticket, &parser->validated); - } for (i = 0; i < parser->num_post_deps; i++) { drm_syncobj_put(parser->post_deps[i].syncobj); @@ -1265,29 +1244,10 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, amdgpu_vm_move_to_lru_tail(p->adev, &fpriv->vm); - amdgpu_bo_list_for_each_entry(e, p->bo_list) { - struct dma_resv *resv = e->tv.bo->base.resv; - struct dma_fence_chain *chain = e->chain; - struct dma_resv_iter cursor; - struct dma_fence *fence; - - if (!chain) - continue; - - /* -* Work around dma_resv shortcommings by wrapping up the -* submission in a dma_fence_chain and add it as exclusive -* fence. -*/ - dma_resv_for_each_fence(&cursor, resv, - DMA_RESV_USAGE_WRITE, - fence) { - break; - } - dma_fence_chain_init(chain, fence, dma_fence_get(p->fence), 1); - dma_resv_add_fence(resv, &chain->base, DMA_RESV_USAGE_WRITE); - e->chain = NULL; - } + /* For now manually add the resulting fence as writer as well */ + amdgpu_bo_list_for_each_entry(e, p->bo_list) + dma_resv_add_fence(e->tv.bo->base.resv, p->fence, + DMA_RESV_USAGE_WRITE); ttm_eu_fence_buffer_objects(&p->ticket, &p->validated, p->fence); mutex_unlock(&p->adev->notifier_lock); -- 2.25.1
Re: [PATCH v2] i2c: tegra: Add ACPI support
23.11.2021 10:15, Akhil R пишет: > Add support for ACPI based device registration so that the driver > can be also enabled through ACPI table. > > Signed-off-by: Akhil R > --- > drivers/i2c/busses/i2c-tegra.c | 52 > -- > 1 file changed, 40 insertions(+), 12 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c > index c883044..8e47889 100644 > --- a/drivers/i2c/busses/i2c-tegra.c > +++ b/drivers/i2c/busses/i2c-tegra.c > @@ -6,6 +6,7 @@ > * Author: Colin Cross > */ > > +#include > #include > #include > #include > @@ -608,6 +609,7 @@ static int tegra_i2c_wait_for_config_load(struct > tegra_i2c_dev *i2c_dev) > static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) > { > u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode; > + acpi_handle handle = ACPI_HANDLE(i2c_dev->dev); > int err; > > /* > @@ -618,7 +620,11 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) >* emit a noisy warning on error, which won't stay unnoticed and >* won't hose machine entirely. >*/ > - err = reset_control_reset(i2c_dev->rst); > + if (handle && acpi_has_method(handle, "_RST")) Which SoC version doesn't have "_RST" method? If neither, then please remove this check. > + err = (acpi_evaluate_object(handle, "_RST", NULL, NULL)); Please remove parens around acpi_evaluate_object(). Why you added them? > + else > + err = reset_control_reset(i2c_dev->rst); > + > WARN_ON_ONCE(err); > > if (i2c_dev->is_dvc) > @@ -1627,12 +1633,12 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev > *i2c_dev) > bool multi_mode; > int err; > > - err = of_property_read_u32(np, "clock-frequency", > -&i2c_dev->bus_clk_rate); > + err = device_property_read_u32(i2c_dev->dev, "clock-frequency", > +&i2c_dev->bus_clk_rate); > if (err) > i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; > > - multi_mode = of_property_read_bool(np, "multi-master"); > + multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master"); > i2c_dev->multimaster_mode = multi_mode; > > if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) > @@ -1642,10 +1648,25 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev > *i2c_dev) > i2c_dev->is_vi = true; > } How are you going to differentiate the VI I2C from a non-VI? This doesn't look right. > > +static int tegra_i2c_init_reset(struct tegra_i2c_dev *i2c_dev) > +{ > + if (has_acpi_companion(i2c_dev->dev)) > + return 0; > + > + i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c"); > + if (IS_ERR(i2c_dev->rst)) > + return PTR_ERR(i2c_dev->rst); > + > + return 0; > +} > + > static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev) > { > int err; > > + if (has_acpi_companion(i2c_dev->dev)) > + return 0; > + > i2c_dev->clocks[i2c_dev->nclocks++].id = "div-clk"; > > if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw) > @@ -1720,7 +1741,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) > init_completion(&i2c_dev->msg_complete); > init_completion(&i2c_dev->dma_complete); > > - i2c_dev->hw = of_device_get_match_data(&pdev->dev); > + i2c_dev->hw = device_get_match_data(&pdev->dev); > i2c_dev->cont_id = pdev->id; > i2c_dev->dev = &pdev->dev; > > @@ -1746,15 +1767,13 @@ static int tegra_i2c_probe(struct platform_device > *pdev) > if (err) > return err; > > - i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c"); > - if (IS_ERR(i2c_dev->rst)) { > - dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst), > - "failed to get reset control\n"); > - return PTR_ERR(i2c_dev->rst); > - } > - > tegra_i2c_parse_dt(i2c_dev); > > + err = tegra_i2c_init_reset(i2c_dev); > + if (err) > + return dev_err_probe(i2c_dev->dev, err, > + "failed to get reset control\n"); This is inconsistent with tegra_i2c_init_clocks() which returns err directly and prints error message within the function. Please move the dev_err_probe() into tegra_i2c_init_reset() to make it consistent, like I suggested before. Please don't reply with a new version of the patch to the old thread, always send a new version separately. Otherwise it's more difficult to follow patches. Lastly, each new version of a patch must contain changelog. I don't see changelog here, please add it to v3 after the " ---" separator of the commit message. Thanks! Example: Commit message. Signed-off-by: Akhil R --- drivers/i2c/busses/i2c-tegra.c | 52 -- 1 file c
Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
On 2021-11-12 03:37, Pekka Paalanen wrote: > On Thu, 11 Nov 2021 21:58:35 + > "Shankar, Uma" wrote: > >>> -Original Message- >>> From: Harry Wentland >>> Sent: Friday, November 12, 2021 2:41 AM >>> To: Shankar, Uma ; Ville Syrjälä >>> >>> Cc: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; >>> ppaala...@gmail.com; brian.star...@arm.com; sebast...@sebastianwick.net; >>> shashank.sha...@amd.com >>> Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct >>> for >>> HDR planes >>> >>> >>> >>> On 2021-11-11 15:42, Shankar, Uma wrote: > -Original Message- > From: Ville Syrjälä > Sent: Thursday, November 11, 2021 10:13 PM > To: Harry Wentland > Cc: Shankar, Uma ; > intel-...@lists.freedesktop.org; dri- de...@lists.freedesktop.org; > ppaala...@gmail.com; brian.star...@arm.com; > sebast...@sebastianwick.net; shashank.sha...@amd.com > Subject: Re: [RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range > struct for HDR planes > > On Thu, Nov 11, 2021 at 10:17:17AM -0500, Harry Wentland wrote: >> >> >> On 2021-09-06 17:38, Uma Shankar wrote: >>> Define the structure with XE_LPD degamma lut ranges. HDR and SDR >>> planes have different capabilities, implemented respective >>> structure for the HDR planes. >>> >>> Signed-off-by: Uma Shankar >>> --- >>> drivers/gpu/drm/i915/display/intel_color.c | 52 >>> ++ >>> 1 file changed, 52 insertions(+) >>> >>> diff --git a/drivers/gpu/drm/i915/display/intel_color.c >>> b/drivers/gpu/drm/i915/display/intel_color.c >>> index afcb4bf3826c..6403bd74324b 100644 >>> --- a/drivers/gpu/drm/i915/display/intel_color.c >>> +++ b/drivers/gpu/drm/i915/display/intel_color.c >>> @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct >>> intel_crtc_state > *crtc_state) >>> } >>> } >>> >>> + /* FIXME input bpc? */ >>> +__maybe_unused >>> +static const struct drm_color_lut_range d13_degamma_hdr[] = { >>> + /* segment 1 */ >>> + { >>> + .flags = (DRM_MODE_LUT_GAMMA | >>> + DRM_MODE_LUT_REFLECT_NEGATIVE | >>> + DRM_MODE_LUT_INTERPOLATE | >>> + DRM_MODE_LUT_NON_DECREASING), >>> + .count = 128, >>> + .input_bpc = 24, .output_bpc = 16, >>> + .start = 0, .end = (1 << 24) - 1, >>> + .min = 0, .max = (1 << 24) - 1, >>> + }, >>> + /* segment 2 */ >>> + { >>> + .flags = (DRM_MODE_LUT_GAMMA | >>> + DRM_MODE_LUT_REFLECT_NEGATIVE | >>> + DRM_MODE_LUT_INTERPOLATE | >>> + DRM_MODE_LUT_REUSE_LAST | >>> + DRM_MODE_LUT_NON_DECREASING), >>> + .count = 1, >>> + .input_bpc = 24, .output_bpc = 16, >>> + .start = (1 << 24) - 1, .end = 1 << 24, >>> + .min = 0, .max = (1 << 27) - 1, >>> + }, >>> + /* Segment 3 */ >>> + { >>> + .flags = (DRM_MODE_LUT_GAMMA | >>> + DRM_MODE_LUT_REFLECT_NEGATIVE | >>> + DRM_MODE_LUT_INTERPOLATE | >>> + DRM_MODE_LUT_REUSE_LAST | >>> + DRM_MODE_LUT_NON_DECREASING), >>> + .count = 1, >>> + .input_bpc = 24, .output_bpc = 16, >>> + .start = 1 << 24, .end = 3 << 24, >>> + .min = 0, .max = (1 << 27) - 1, >>> + }, >>> + /* Segment 4 */ >>> + { >>> + .flags = (DRM_MODE_LUT_GAMMA | >>> + DRM_MODE_LUT_REFLECT_NEGATIVE | >>> + DRM_MODE_LUT_INTERPOLATE | >>> + DRM_MODE_LUT_REUSE_LAST | >>> + DRM_MODE_LUT_NON_DECREASING), >>> + .count = 1, >>> + .input_bpc = 24, .output_bpc = 16, >>> + .start = 3 << 24, .end = 7 << 24, >>> + .min = 0, .max = (1 << 27) - 1, >>> + }, >>> +}; >> >> If I understand this right, userspace would need this definition in >> order to populate the degamma blob. Should this sit in a UAPI header? > > Are you asking whether 'struct drm_color_lut_range` is defined in any > userspace visible header? > > It seems to be in patch 2. > Hi Harry, Pekka and Ville, Sorry for being a bit late on the replies, got side tracked with various issues. I am back on this. Apologies for delay. > My original idea (not sure it's fully realized in this series) is to > have a new GAMMA_M
Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On 2021-09-06 17:38, Uma Shankar wrote: > This is a RFC proposal for plane color hardware blocks. > It exposes the property interface to userspace and calls > out the details or interfaces created and the intended > purpose. > > Credits: Ville Syrjälä > Signed-off-by: Uma Shankar > --- > Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++ > 1 file changed, 167 insertions(+) > create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst > > diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst > b/Documentation/gpu/rfc/drm_color_pipeline.rst > new file mode 100644 > index ..0d1ca858783b > --- /dev/null > +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst > @@ -0,0 +1,167 @@ > +== > +Display Color Pipeline: Proposed DRM Properties > +== > + > +This is how a typical display color hardware pipeline looks like: > + +---+ > + |RAM| > + | +--++-++-+ | > + | | FB 1 || FB 2 || FB N| | > + | +--++-++-+ | > + +---+ > + | Plane Color Hardware Block | > + ++ > + | +---v-+ +---v---+ +---v--+ | > + | | Plane A | | Plane B | | Plane N | | > + | | DeGamma | | Degamma | | Degamma | | > + | +---+-+ +---+---+ +---+--+ | > + | | | || > + | +---v-+ +---v---+ +---v--+ | > + | |Plane A | | Plane B | | Plane N | | > + | |CSC/CTM | | CSC/CTM | | CSC/CTM | | > + | +---+-+ ++--+ ++-+ | > + | | | | | > + | +---v-+ +v--+ +v-+ | > + | | Plane A | | Plane B | | Plane N | | > + | | Gamma | | Gamma | | Gamma| | > + | +---+-+ ++--+ ++-+ | > + | | | | | > + ++ > ++--v--v---v---| > +|| || > +|| Pipe Blender|| > ++++ > +||| > +|+---v--+ | > +|| Pipe DeGamma| | > +|| | | > +|+---+--+ | > +||Pipe Color | > +|+---v--+ Hardware| > +|| Pipe CSC/CTM| | > +|| | | > +|+---+--+ | > +||| > +|+---v--+ | > +|| Pipe Gamma | | > +|| | | > +|+---+--+ | > +||| > ++-+ > + | > + v > + Pipe Output > + This diagram defines what happens before and after the blending space but did where does scaling fit into it? Scaling can look different when performed in linear or non-linear space so I think it is important to define where in the pipeline it sits. In my view scaling would happen between plane degamma and plane CSC. Harry > +Proposal is to have below properties for a plane: > + > +* Plane Degamma or Pre-Curve: > + * This will be used to linearize the input framebuffer data. > + * It will apply the reverse of the color transfer function. > + * It can be a degamma curve or OETF for HDR. > + * This linear data can be further acted on by the following > + * color hardware blocks in the display hardware pipeline > + > +UAPI Name: PLANE_DEGAMMA_MODE > +Description: Enum property with values as blob_id's which advertizes the > + possible degamma modes and lut ranges supported by the platform. > + This allows userspace to query and get the plane degamma color > + caps and choose the appropriate degamma mode and create lut values > + accordingly. > + > +UAPI Name: PLANE_DEGAMMA_LUT > +Description: Blob property which allows a userspace to provide LUT values > + to apply degamma curve using the h/w plane degamma processing > + engine, thereby making the content as linear for further color > + processing. Userspace gets the size of LUT and precision etc > + from PLANE_DEGAMA_MODE_PROPERTY > + > +* Plane CTM > + * This is a Property to program the color transformation matrix. > + * This can be used to perform a color space conversion like > + *
Re: [PATCH] drm/bridge: megachips: Ensure both bridges are probed before registration
Hey Martyn, On Tue, 16 Nov 2021 at 13:28, Martyn Welch wrote: > > In the configuration used by the b850v3, the STDP2690 is used to read EDID > data whilst it's the STDP4028 which can detect when monitors are connected. > > This can result in problems at boot with monitors connected when the > STDP4028 is probed first, a monitor is detected and an attempt is made to > read the EDID data before the STDP2690 has probed: > > [3.795721] Unable to handle kernel NULL pointer dereference at virtual > address 0018 > [3.803845] pgd = (ptrval) > [3.806581] [0018] *pgd= > [3.810180] Internal error: Oops: 5 [#1] SMP ARM > [3.814813] Modules linked in: > [3.817879] CPU: 0 PID: 64 Comm: kworker/u4:1 Not tainted 5.15.0 #1 > [3.824161] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) > [3.830705] Workqueue: events_unbound deferred_probe_work_func > [3.836565] PC is at stdp2690_get_edid+0x44/0x19c > [3.841286] LR is at ge_b850v3_lvds_get_modes+0x2c/0x5c > [3.846526] pc : [<805eae10>]lr : [<805eb138>]psr: 8013 > [3.852802] sp : 81c359d0 ip : 7dbb550b fp : 81c35a1c > [3.858037] r10: 81c73840 r9 : 81c73894 r8 : 816d9800 > [3.863270] r7 : r6 : 81c34000 r5 : r4 : 810c35f0 > [3.869808] r3 : 80e3e294 r2 : 0080 r1 : 0cc0 r0 : 81401180 > [3.876349] Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment > none > [3.883499] Control: 10c5387d Table: 1000404a DAC: 0051 > [3.889254] Register r0 information: slab kmem_cache start 81401180 > pointer offset 0 > [3.897034] Register r1 information: non-paged memory > [3.902097] Register r2 information: non-paged memory > [3.907160] Register r3 information: non-slab/vmalloc memory > [3.912832] Register r4 information: non-slab/vmalloc memory > [3.918503] Register r5 information: NULL pointer > [3.923217] Register r6 information: non-slab/vmalloc memory > [3.928887] Register r7 information: NULL pointer > [3.933601] Register r8 information: slab kmalloc-1k start 816d9800 > pointer offset 0 size 1024 > [3.942244] Register r9 information: slab kmalloc-2k start 81c73800 > pointer offset 148 size 2048 > [3.951058] Register r10 information: slab kmalloc-2k start 81c73800 > pointer offset 64 size 2048 > [3.959873] Register r11 information: non-slab/vmalloc memory > [3.965632] Register r12 information: non-paged memory > [3.970781] Process kworker/u4:1 (pid: 64, stack limit = 0x(ptrval)) > [3.977148] Stack: (0x81c359d0 to 0x81c36000) > [3.981517] 59c0: 80b2b668 80b2b5bc > 02e2 034e > [3.989712] 59e0: 81c35a8c 816d98e8 81c35a14 7dbb550b 805bfcd0 810c35f0 > 81c73840 824addc0 > [3.997906] 5a00: 1000 816d9800 81c73894 81c73840 81c35a34 81c35a20 > 805eb138 805eadd8 > [4.006099] 5a20: 810c35f0 0045 81c35adc 81c35a38 80594188 805eb118 > 80d7c788 80dd1848 > [4.014292] 5a40: 81c35a50 80dca950 811194d3 80dca7c4 80dca944 > 80dca91c 816d9800 > [4.022485] 5a60: 81c34000 81c760a8 816d9800 80c58c98 810c35f0 816d98e8 > 1000 1000 > [4.030678] 5a80: 8017712c 81c6 0002 0001 > > [4.038870] 5aa0: 816d9900 816d9900 7dbb550b 805c700c 0008 > 826282c8 826282c8 > [4.047062] 5ac0: 1000 81e1ce40 1000 0002 81c35bf4 81c35ae0 > 805d9694 80593fc0 > [4.055255] 5ae0: 8017a970 80179ad8 0179 81c35bcc 81c35b00 > 80177108 8017a950 > [4.063447] 5b00: 81c35b10 81c34000 81004fd8 81010a38 > 0059 > [4.071639] 5b20: 816d98d4 81fbb718 0013 826282c8 8017a940 81c35b40 > 81134448 0400 > [4.079831] 5b40: 0178 e063b9c1 c249 0040 > 0008 > [4.088024] 5b60: 82628300 82628380 81c34000 > 81fbb700 82628340 > [4.096216] 5b80: 826283c0 1000 0010 816d9800 826282c0 > 801766f8 > [4.104408] 5ba0: 81004fd8 0049 0001 > 80dcf940 80178de4 > [4.112601] 5bc0: 81c35c0c 7dbb550b 80178de4 81fbb700 0010 0010 > 810c35f4 81e1ce40 > [4.120793] 5be0: 81c40908 000c 81c35c64 81c35bf8 805a7f18 805d94a0 > 81c35c3c 816d9800 > [4.128985] 5c00: 0010 81c34000 81c35c2c 81c35c18 8012fce0 805be90c > 81c35c3c 81c35c28 > [4.137178] 5c20: 805be90c 80173210 81fbb600 81fbb6b4 81c35c5c 7dbb550b > 81c35c64 81fbb700 > [4.145370] 5c40: 816d9800 0010 810c35f4 81e1ce40 81c40908 000c > 81c35c84 81c35c68 > [4.153565] 5c60: 805a8c78 805a7ed0 816d9800 81fbb700 0010 > 81c35cac 81c35c88 > [4.161758] 5c80: 805a8dc4 805a8b68 816d9800 816d9800 > 8179f810 810c42d0 > [4.169950] 5ca0: 81c35ccc 81c35cb0 805e47b0 805a8d18 824aa240 81e1ea80 > 81c40908 81126b60 > [4.178144] 5cc0: 81c35d14 81c35cd0 806
[PATCH] drm/msm/dpu: Add more of the INTF interrupt regions
In addition to the other 7xxx INTF interrupt regions, SM8350 has additional INTF regions at 0x0ae37000, 0x0ae38000 and 0x0ae39000, define these. The 7xxx naming scheme of the bits are kept for consistency. Signed-off-by: Bjorn Andersson --- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 18 ++ .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index d2b6dca487e3..a77a5eaa78ad 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -30,6 +30,9 @@ #define MDP_AD4_INTR_STATUS_OFF0x420 #define MDP_INTF_0_OFF_REV_7xxx 0x34000 #define MDP_INTF_1_OFF_REV_7xxx 0x35000 +#define MDP_INTF_2_OFF_REV_7xxx 0x36000 +#define MDP_INTF_3_OFF_REV_7xxx 0x37000 +#define MDP_INTF_4_OFF_REV_7xxx 0x38000 #define MDP_INTF_5_OFF_REV_7xxx 0x39000 /** @@ -110,6 +113,21 @@ static const struct dpu_intr_reg dpu_intr_set[] = { MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_EN, MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_STATUS }, + { + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_STATUS + }, + { + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_STATUS + }, + { + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_STATUS + }, { MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_CLEAR, MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_EN, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h index d50e78c9f148..1ab75cccd145 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -26,6 +26,9 @@ enum dpu_hw_intr_reg { MDP_AD4_1_INTR, MDP_INTF0_7xxx_INTR, MDP_INTF1_7xxx_INTR, + MDP_INTF2_7xxx_INTR, + MDP_INTF3_7xxx_INTR, + MDP_INTF4_7xxx_INTR, MDP_INTF5_7xxx_INTR, MDP_INTR_MAX, }; -- 2.33.1
Re: [PATCH 4/4] drm/msm/a6xx: Capture gmu log in devcoredump
On 11/23/2021 12:36 AM, Rob Clark wrote: On Mon, Nov 22, 2021 at 10:26 AM Rob Clark wrote: On Thu, Nov 18, 2021 at 2:21 AM Akhil P Oommen wrote: Capture gmu log in coredump to enhance debugging. Signed-off-by: Akhil P Oommen --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 41 + drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 2 ++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 7501849..9fa3fa6 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -42,6 +42,8 @@ struct a6xx_gpu_state { struct a6xx_gpu_state_obj *cx_debugbus; int nr_cx_debugbus; + struct msm_gpu_state_bo *gmu_log; + struct list_head objs; }; @@ -800,6 +802,30 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, &a6xx_state->gmu_registers[2], false); } +static void a6xx_get_gmu_log(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; + struct msm_gpu_state_bo *gmu_log; + + gmu_log = state_kcalloc(a6xx_state, + 1, sizeof(*a6xx_state->gmu_log)); + if (!gmu_log) + return; + + gmu_log->iova = gmu->log.iova; + gmu_log->size = gmu->log.size; + gmu_log->data = kvzalloc(gmu_log->size, GFP_KERNEL); + if (!gmu_log->data) + return; + + memcpy(gmu_log->data, gmu->log.virt, gmu->log.size); + + a6xx_state->gmu_log = gmu_log; +} + #define A6XX_GBIF_REGLIST_SIZE 1 static void a6xx_get_registers(struct msm_gpu *gpu, struct a6xx_gpu_state *a6xx_state, @@ -937,6 +963,8 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) a6xx_get_gmu_registers(gpu, a6xx_state); + a6xx_get_gmu_log(gpu, a6xx_state); + /* If GX isn't on the rest of the data isn't going to be accessible */ if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) return &a6xx_state->base; @@ -978,6 +1006,9 @@ static void a6xx_gpu_state_destroy(struct kref *kref) struct a6xx_gpu_state *a6xx_state = container_of(state, struct a6xx_gpu_state, base); + if (a6xx_state->gmu_log && a6xx_state->gmu_log->data) + kvfree(a6xx_state->gmu_log->data); + list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node) kfree(obj); @@ -1191,6 +1222,16 @@ void a6xx_show(struct msm_gpu *gpu, struct msm_gpu_state *state, adreno_show(gpu, state, p); + drm_puts(p, "gmu-log:\n"); + if (a6xx_state->gmu_log) { + struct msm_gpu_state_bo *gmu_log = a6xx_state->gmu_log; + + drm_printf(p, "iova: 0x%016llx\n", gmu_log->iova); + drm_printf(p, "size: %d\n", gmu_log->size); fwiw, that wants to be: + drm_printf(p, "size: %zu\n", gmu_log->size); with that fixed, r-b Hmm, actually, I seem to be getting an empty log.. is special gmu fw, or non-fused device needed for this to work? BR, -R No, there is no special fw. I tested this on 7c3 and it worked for me. a618/a630 has an old version of gmu firmware which is pretty different from the newer ones. Let me check. -Akhil. BR, -R + adreno_show_object(p, &gmu_log->data, gmu_log->size, + &gmu_log->encoded); + } + drm_puts(p, "registers:\n"); for (i = 0; i < a6xx_state->nr_registers; i++) { struct a6xx_gpu_state_obj *obj = &a6xx_state->registers[i]; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 7486652..7d1ff20 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -630,7 +630,7 @@ static char *adreno_gpu_ascii85_encode(u32 *src, size_t len) } /* len is expected to be in bytes */ -static void adreno_show_object(struct drm_printer *p, void **ptr, int len, +void adreno_show_object(struct drm_printer *p, void **ptr, int len, bool *encoded) { if (!*ptr || !len) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 225c277..6762308 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -306,6 +306,8 @@ void adreno_gpu_state_destroy(struct msm_gpu_state *state); int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state); int adreno_gpu_state_put(struct msm_gpu_state *state); +void adreno_show_object(struct drm_printer *p, void **ptr, int len, + bool *encoded); /* * Common helper function
[Bug 211807] [drm:drm_dp_mst_dpcd_read] *ERROR* mstb 000000004e6288dd port 3: DPCD read on addr 0x60 for 1 bytes NAKed
https://bugzilla.kernel.org/show_bug.cgi?id=211807 --- Comment #16 from zwer...@mail.de --- (In reply to Alex Deucher from comment #13) > (In reply to zwerg12 from comment #12) > > As mentioned before, I get the same error with a monitor connected with DP > > to a Lenovo ThinkPad USB-C Dock Gen2. My Laptop has an Intel i7 10510U no > > additional graphics card. I am using Debian testing with the provided > kernel. > > > > > > During this my notebook monitor is blinking. > > This setup worked for around four weeks when suddenly these errors > occurred. > > > Can you bisect? I have never done it yet. But as soon as I am at home I can try. (In reply to Michel Dänzer from comment #15) > (In reply to Daan from comment #14) > > I also had this in my logs yesterday, right before my system locked > > completely (had to do a hard reset). > > That's probably coincidence. I get these messages on a regular basis, > without any bad behaviour. Sometimes when I get this message there is no bad behavior but sometimes I also have to do a hard reset. Without the docking station I never had to make a hard reset. -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
Re: [PATCH] drm/msm/dpu: Add more of the INTF interrupt regions
On Tue, 23 Nov 2021 at 16:39, Bjorn Andersson wrote: > > In addition to the other 7xxx INTF interrupt regions, SM8350 has > additional INTF regions at 0x0ae37000, 0x0ae38000 and 0x0ae39000, define > these. The 7xxx naming scheme of the bits are kept for consistency. > > Signed-off-by: Bjorn Andersson > --- > .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 18 ++ > .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 3 +++ > 2 files changed, 21 insertions(+) > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c > b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c > index d2b6dca487e3..a77a5eaa78ad 100644 > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c > @@ -30,6 +30,9 @@ > #define MDP_AD4_INTR_STATUS_OFF0x420 > #define MDP_INTF_0_OFF_REV_7xxx 0x34000 > #define MDP_INTF_1_OFF_REV_7xxx 0x35000 > +#define MDP_INTF_2_OFF_REV_7xxx 0x36000 > +#define MDP_INTF_3_OFF_REV_7xxx 0x37000 > +#define MDP_INTF_4_OFF_REV_7xxx 0x38000 > #define MDP_INTF_5_OFF_REV_7xxx 0x39000 > > /** > @@ -110,6 +113,21 @@ static const struct dpu_intr_reg dpu_intr_set[] = { > MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_EN, > MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_STATUS > }, > + { > + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_CLEAR, > + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_EN, > + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_STATUS > + }, > + { > + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_CLEAR, > + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_EN, > + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_STATUS > + }, > + { > + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_CLEAR, > + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_EN, > + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_STATUS > + }, > { > MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_CLEAR, > MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_EN, > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h > b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h > index d50e78c9f148..1ab75cccd145 100644 > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h > @@ -26,6 +26,9 @@ enum dpu_hw_intr_reg { > MDP_AD4_1_INTR, > MDP_INTF0_7xxx_INTR, > MDP_INTF1_7xxx_INTR, > + MDP_INTF2_7xxx_INTR, > + MDP_INTF3_7xxx_INTR, > + MDP_INTF4_7xxx_INTR, > MDP_INTF5_7xxx_INTR, > MDP_INTR_MAX, > }; Reviewed-by: Robert Foss
Re: [PATCH v1 1/1] drm: Replace kernel.h with the necessary inclusions
On Mon, Nov 15, 2021 at 01:35:47PM +0200, Andy Shevchenko wrote: > On Wed, Nov 10, 2021 at 05:39:33PM +0100, Thomas Zimmermann wrote: > > Am 10.11.21 um 17:34 schrieb Andy Shevchenko: > > > On Wed, Nov 10, 2021 at 3:55 PM Thomas Zimmermann > > > wrote: > > > > Am 10.11.21 um 11:24 schrieb Andy Shevchenko: > > ... > > > > > > +#include > > > > > > > > I built this patch on a recent drm-misc-next, but there's no > > > > linux/container_of.h > > > > > > Thank you for trying. It's in the upstream, whenever drm-misc-next > > > switches to newer/newest upstream it will be there. I assume it will > > > happen after v5.16-rc1? > > > > Yes, we'll certainly backmerge soon after rc1 has been released. If I forget > > to add the patch then, please send a reminder. > > > > Once the necessary headers are available, > > $ git log --oneline v5.16-rc1 -- include/linux/container_of.h > e1edc277e6f6 linux/container_of.h: switch to static_assert > d2a8ebbf8192 kernel.h: split out container_of() and typeof_member() macros > > > the patch is > > Acked-by: Thomas Zimmermann > > Thanks! Maybe I misunderstood something, I thought that DRM people may apply this, is it incorrect assumption? -- With Best Regards, Andy Shevchenko
Re: [PATCH 3/3] drm/i915/gt: Improve "race-to-idle" at low frequencies
On Tue, 2021-11-23 at 09:17 +, Tvrtko Ursulin wrote: > > On 22/11/2021 18:44, Rodrigo Vivi wrote: > > On Wed, Nov 17, 2021 at 02:49:55PM -0800, Vinay Belgaumkar wrote: > > > From: Chris Wilson > > > > > > While the power consumption is proportional to the frequency, > > > there is > > > also a static draw for active gates. The longer we are able to > > > powergate > > > (rc6), the lower the static draw. Thus there is a sweetspot in > > > the > > > frequency/power curve where we run at higher frequency in order > > > to sleep > > > longer, aka race-to-idle. This is more evident at lower > > > frequencies, so > > > let's look to bump the frequency if we think we will benefit by > > > sleeping > > > longer at the higher frequency and so conserving power. > > > > > > Signed-off-by: Chris Wilson > > > Cc: Vinay Belgaumkar > > > Cc: Tvrtko Ursulin > > > > Please let's not increase the complexity here, unless we have a > > very good > > and documented reason. > > > > Before trying to implement anything smart like this in the driver > > I'd like > > to see data, power and performance results in different platforms > > and with > > different workloads. > > Who has such test suite and test farm which isn't focused to > workloads > from a single customer? ;( Okay, maybe we don't need to cover the world here. But without seen any data at all it is hard to make this call. > > Regards, > > Tvrtko
Re: [PATCH v2] i2c: tegra: Add ACPI support
Hi Akhil, Thank you for the patch! Yet something to improve: [auto build test ERROR on tegra/for-next] [also build test ERROR on v5.16-rc2 next-20211123] [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/Akhil-R/i2c-tegra-Add-ACPI-support/20211123-151636 base: https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git for-next config: riscv-buildonly-randconfig-r005-20211123 (https://download.01.org/0day-ci/archive/20211124/202111240017.byyz7knz-...@intel.com/config.gz) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 49e3838145dff1ec91c2e67a2cb562775c8d2a08) 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 # install riscv cross compiling tool for clang build # apt-get install binutils-riscv64-linux-gnu # https://github.com/0day-ci/linux/commit/dec174be801f41a9e42f4381c59c2357c25e40fb git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Akhil-R/i2c-tegra-Add-ACPI-support/20211123-151636 git checkout dec174be801f41a9e42f4381c59c2357c25e40fb # save the config file to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=riscv If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All errors (new ones prefixed by >>): In file included from drivers/i2c/busses/i2c-tegra.c:13: In file included from include/linux/dmaengine.h:12: In file included from include/linux/scatterlist.h:9: In file included from arch/riscv/include/asm/io.h:136: include/asm-generic/io.h:464:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] val = __raw_readb(PCI_IOBASE + addr); ~~ ^ include/asm-generic/io.h:477:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr)); ~~ ^ include/uapi/linux/byteorder/little_endian.h:36:51: note: expanded from macro '__le16_to_cpu' #define __le16_to_cpu(x) ((__force __u16)(__le16)(x)) ^ In file included from drivers/i2c/busses/i2c-tegra.c:13: In file included from include/linux/dmaengine.h:12: In file included from include/linux/scatterlist.h:9: In file included from arch/riscv/include/asm/io.h:136: include/asm-generic/io.h:490:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr)); ~~ ^ include/uapi/linux/byteorder/little_endian.h:34:51: note: expanded from macro '__le32_to_cpu' #define __le32_to_cpu(x) ((__force __u32)(__le32)(x)) ^ In file included from drivers/i2c/busses/i2c-tegra.c:13: In file included from include/linux/dmaengine.h:12: In file included from include/linux/scatterlist.h:9: In file included from arch/riscv/include/asm/io.h:136: include/asm-generic/io.h:501:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] __raw_writeb(value, PCI_IOBASE + addr); ~~ ^ include/asm-generic/io.h:511:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr); ~~ ^ include/asm-generic/io.h:521:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr); ~~ ^ include/asm-generic/io.h:1024:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port; ~~ ^ >> drivers/i2c/busses/i2c-tegra.c:623:16: error: implicit declaration of >> function 'acpi_has_method' [-Werror,-Wimplicit-function-declaration] if (handle && acpi_has_method(handle, "_RST"))
[PATCH] drm: rcar-du: do not restart rcar-du groups on gen3
Restarting a display unit group can cause a visible flicker on the display. Particularly when a LVDS display is connected to a Salvator board and an HDMI display is (re)connected, then there will be 2 visible flickers on the LVDS display: 1. during atomic_flush (The need_restart flag is set in this case by rcar_du_vsp_enable.): rcar_du_crtc_atomic_flush rcar_du_crtc_update_planes ... ... /* Restart the group if plane sources have changed. */ if (rcrtc->group->need_restart) rcar_du_group_restart(rcrtc->group); 2. during atomic_enable: rcar_du_crtc_atomic_enable rcar_du_crtc_start rcar_du_group_start_stop(rcrtc->group, true); To avoid flickers in all use cases, do not restart DU groups on the Gen3 SoCs at all, since it is not required any more. Signed-off-by: Michael Rodin --- drivers/gpu/drm/rcar-du/rcar_du_group.c | 5 - drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 8665a1d..ff0a1c8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -250,7 +250,7 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) * when the display controller will have to be restarted. */ if (start) { - if (rgrp->used_crtcs++ != 0) + if (rgrp->used_crtcs++ != 0 && rgrp->dev->info->gen != 3) __rcar_du_group_start_stop(rgrp, false); __rcar_du_group_start_stop(rgrp, true); } else { @@ -263,6 +263,9 @@ void rcar_du_group_restart(struct rcar_du_group *rgrp) { rgrp->need_restart = false; + if (rgrp->dev->info->gen == 3) + return; + __rcar_du_group_start_stop(rgrp, false); __rcar_du_group_start_stop(rgrp, true); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index b7fc5b0..a652c06 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -88,8 +88,6 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) * Ensure that the plane source configuration takes effect by requesting * a restart of the group. See rcar_du_plane_atomic_update() for a more * detailed explanation. -* -* TODO: Check whether this is still needed on Gen3. */ crtc->group->need_restart = true; -- 2.7.4
[PATCH] drm/doc: Fix TTM acronym
The TTM acronym is defined for the first time in the documentation as "Translation Table Maps". Afterwards, "Translation Table Manager" is used as definition. Fix the first definition to avoid confusion. Signed-off-by: José Expósito --- Documentation/gpu/drm-mm.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index e0538083a2c0..198bcc1affa1 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -8,7 +8,7 @@ the very dynamic nature of many of that data, managing graphics memory efficiently is thus crucial for the graphics stack and plays a central role in the DRM infrastructure. -The DRM core includes two memory managers, namely Translation Table Maps +The DRM core includes two memory managers, namely Translation Table Manager (TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory manager to be developed and tried to be a one-size-fits-them all solution. It provides a single userspace API to accommodate the need of -- 2.25.1
[PATCH v7 1/8] drm/ingenic: prepare ingenic drm for later addition of JZ4780
This changes the way the regmap is allocated to prepare for the later addition of the JZ4780 which has more registers and bits than the others. Therefore we make the regmap as big as the reg property in the device tree tells. Suggested-by: Paul Cercueil Signed-off-by: H. Nikolaus Schaller --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 462bc0f35f1bf..0bb590c3910d9 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -173,7 +173,6 @@ static const struct regmap_config ingenic_drm_regmap_config = { .val_bits = 32, .reg_stride = 4, - .max_register = JZ_REG_LCD_SIZE1, .writeable_reg = ingenic_drm_writeable_reg, }; @@ -1011,6 +1010,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) struct ingenic_drm_bridge *ib; struct drm_device *drm; void __iomem *base; + struct resource *res; + struct regmap_config regmap_config; long parent_rate; unsigned int i, clone_mask = 0; int ret, irq; @@ -1056,14 +1057,16 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) drm->mode_config.funcs = &ingenic_drm_mode_config_funcs; drm->mode_config.helper_private = &ingenic_drm_mode_config_helpers; - base = devm_platform_ioremap_resource(pdev, 0); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(base)) { dev_err(dev, "Failed to get memory resource\n"); return PTR_ERR(base); } + regmap_config = ingenic_drm_regmap_config; + regmap_config.max_register = res->end - res->start; priv->map = devm_regmap_init_mmio(dev, base, - &ingenic_drm_regmap_config); + ®map_config); if (IS_ERR(priv->map)) { dev_err(dev, "Failed to create regmap\n"); return PTR_ERR(priv->map); -- 2.33.0
[PATCH v7 0/8] MIPS: JZ4780 and CI20 HDMI
PATCH V7 2021-11-23 18:46:23: - changed gpio polarity of hdmi_power to 0 (suggested by p...@crapouillou.net) - fixed LCD1 irq number (bug found by p...@crapouillou.net) - removed "- 4" for calculating max_register (suggested by p...@crapouillou.net) - use unevaluatedPropertes instead of additionalProperties (suggested by r...@kernel.org) - moved and renamed ingenic,jz4780-hdmi.yaml (suggested by r...@kernel.org) - adjusted assigned-clocks changes to upstream which added some for SSI (by h...@goldelico.com) - rebased and tested with v5.16-rc2 + patch set drm/ingenic by p...@crapouillou.net (by h...@goldelico.com) PATCH V6 2021-11-10 20:43:33: - changed CONFIG_DRM_INGENIC_DW_HDMI to "m" (by h...@goldelico.com) - made ingenic-dw-hdmi an independent platform driver which can be compiled as module and removed error patch fixes for IPU (suggested by p...@crapouillou.net) - moved assigned-clocks from jz4780.dtsi to ci20.dts (suggested by p...@crapouillou.net) - fixed reg property in jz4780.dtsi to cover all registers incl. gamma and vee (by h...@goldelico.com) - added a base patch to calculate regmap size from DTS reg property (requested by p...@crapouillou.net) - restored resetting all bits except one in LCDOSDC (requested by p...@crapouillou.net) - clarified setting of cpos (suggested by p...@crapouillou.net) - moved bindings definition for ddc-i2c-bus (suggested by p...@crapouillou.net) - simplified mask definitions for JZ_LCD_DESSIZE (requested by p...@crapouillou.net) - removed setting alpha premultiplication (suggested by p...@crapouillou.net) - removed some comments (suggested by p...@crapouillou.net) PATCH V5 2021-10-05 14:28:44: - dropped mode_fixup and timings support in dw-hdmi as it is no longer needed in this V5 (by h...@goldelico.com) - dropped "drm/ingenic: add some jz4780 specific features" (stimulated by p...@crapouillou.net) - fixed typo in commit subject: "synopsis" -> "synopsys" (by h...@goldelico.com) - swapped clocks in jz4780.dtsi to match synopsys,dw-hdmi.yaml (by h...@goldelico.com) - improved, simplified, fixed, dtbschecked ingenic-jz4780-hdmi.yaml and made dependent of bridge/synopsys,dw-hdmi.yaml (based on suggestions by max...@cerno.tech) - fixed binding vs. driver&DTS use of hdmi-5v regulator (suggested by max...@cerno.tech) - dropped "drm/bridge: synopsis: Fix to properly handle HPD" - was a no longer needed workaround for a previous version (suggested by max...@cerno.tech) PATCH V4 2021-09-27 18:44:38: - fix setting output_port = 1 (issue found by p...@crapouillou.net) - ci20.dts: convert to use hdmi-connector (by h...@goldelico.com) - add a hdmi-regulator to control +5V power (by h...@goldelico.com) - added a fix to dw-hdmi to call drm_kms_helper_hotplug_event on plugin event detection (by h...@goldelico.com) - always allocate extended descriptor but initialize only for jz4780 (by h...@goldelico.com) - updated to work on top of "[PATCH v3 0/6] drm/ingenic: Various improvements v3" (by p...@crapouillou.net) - rebased to v5.13-rc3 PATCH V3 2021-08-08 07:10:50: This series adds HDMI support for JZ4780 and CI20 board (and fixes one IPU related issue in registration error path) - [patch 1/8] switched from mode_fixup to atomic_check (suggested by robert.f...@linaro.org) - the call to the dw-hdmi specialization is still called mode_fixup - [patch 3/8] diverse fixes for ingenic-drm-drv (suggested by p...@crapouillou.net) - factor out some non-HDMI features of the jz4780 into a separate patch - multiple fixes around max height - do not change regmap config but a copy on stack - define some constants - factor out fixing of drm_init error path for IPU into separate patch - use FIELD_PREP() - [patch 8/8] conversion to component framework dropped (suggested by laurent.pinch...@ideasonboard.com and p...@crapouillou.net) PATCH V2 2021-08-05 16:08:05: - code and commit messages revisited for checkpatch warnings - rebased on v5.14-rc4 - include (failed, hence RFC 8/8) attempt to convert to component framework (was suggested by Paul Cercueil a while ago) This series adds HDMI support for JZ4780 and CI20 board H. Nikolaus Schaller (3): drm/ingenic: prepare ingenic drm for later addition of JZ4780 MIPS: defconfig: CI20: configure for DRM_DW_HDMI_JZ4780 [RFC] MIPS: DTS: Ingenic: adjust register size to available registers Paul Boddie (4): drm/ingenic: Add support for JZ4780 and HDMI output drm/ingenic: Add dw-hdmi driver for jz4780 MIPS: DTS: jz4780: Account for Synopsys HDMI driver and LCD controllers MIPS: DTS: CI20: Add DT nodes for HDMI setup Sam Ravnborg (1): dt-bindings: display: Add ingenic,jz4780-dw-hdmi DT Schema .../display/bridge/ingenic,jz4780-hdmi.yaml | 76 +++ .../display/bridge/synopsys,dw-hdmi.yaml | 3 + arch/mips/boot/dts/ingenic/ci20.dts | 83 ++- arch/mips/boot/dts/ingenic/jz4725b.dtsi | 2 +- arch/mips/boot/dts/ingenic/jz4740.dtsi| 2 +- arch/mips/bo
[PATCH v7 4/8] drm/ingenic: Add dw-hdmi driver for jz4780
From: Paul Boddie A specialisation of the generic Synopsys HDMI driver is employed for JZ4780 HDMI support. This requires a new driver, plus device tree and configuration modifications. Here we add Kconfig DRM_INGENIC_DW_HDMI, Makefile and driver code. Signed-off-by: Paul Boddie Signed-off-by: Ezequiel Garcia Signed-off-by: H. Nikolaus Schaller --- drivers/gpu/drm/ingenic/Kconfig | 9 ++ drivers/gpu/drm/ingenic/Makefile | 1 + drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c | 129 ++ 3 files changed, 139 insertions(+) create mode 100644 drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig index 3b57f8be007c4..4efc709d77b0a 100644 --- a/drivers/gpu/drm/ingenic/Kconfig +++ b/drivers/gpu/drm/ingenic/Kconfig @@ -25,4 +25,13 @@ config DRM_INGENIC_IPU The Image Processing Unit (IPU) will appear as a second primary plane. +config DRM_INGENIC_DW_HDMI + tristate "Ingenic specific support for Synopsys DW HDMI" + depends on MACH_JZ4780 + select DRM_DW_HDMI + help + Choose this option to enable Synopsys DesignWare HDMI based driver. + If you want to enable HDMI on Ingenic JZ4780 based SoC, you should + select this option.. + endif diff --git a/drivers/gpu/drm/ingenic/Makefile b/drivers/gpu/drm/ingenic/Makefile index d313326bdddbb..f10cc1c5a5f22 100644 --- a/drivers/gpu/drm/ingenic/Makefile +++ b/drivers/gpu/drm/ingenic/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_DRM_INGENIC) += ingenic-drm.o ingenic-drm-y = ingenic-drm-drv.o ingenic-drm-$(CONFIG_DRM_INGENIC_IPU) += ingenic-ipu.o +obj-$(CONFIG_DRM_INGENIC_DW_HDMI) += ingenic-dw-hdmi.o diff --git a/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c b/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c new file mode 100644 index 0..c14890d6b9826 --- /dev/null +++ b/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2011-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2019, 2020 Paul Boddie + * + * Derived from dw_hdmi-imx.c with i.MX portions removed. + * Probe and remove operations derived from rcar_dw_hdmi.c. + */ + +#include +#include +#include + +#include +#include +#include + +static const struct dw_hdmi_mpll_config ingenic_mpll_cfg[] = { + { 4525, { { 0x01e0, 0x }, { 0x21e1, 0x }, { 0x41e2, 0x } } }, + { 9250, { { 0x0140, 0x0005 }, { 0x2141, 0x0005 }, { 0x4142, 0x0005 } } }, + { 14850, { { 0x00a0, 0x000a }, { 0x20a1, 0x000a }, { 0x40a2, 0x000a } } }, + { 21600, { { 0x00a0, 0x000a }, { 0x2001, 0x000f }, { 0x4002, 0x000f } } }, + { ~0UL, { { 0x, 0x }, { 0x, 0x }, { 0x, 0x } } } +}; + +static const struct dw_hdmi_curr_ctrl ingenic_cur_ctr[] = { + /*pixelclk bpp8bpp10 bpp12 */ + { 5400, { 0x091c, 0x091c, 0x06dc } }, + { 5840, { 0x091c, 0x06dc, 0x06dc } }, + { 7200, { 0x06dc, 0x06dc, 0x091c } }, + { 7425, { 0x06dc, 0x0b5c, 0x091c } }, + { 11880, { 0x091c, 0x091c, 0x06dc } }, + { 21600, { 0x06dc, 0x0b5c, 0x091c } }, + { ~0UL, { 0x, 0x, 0x } }, +}; + +/* + * Resistance term 133Ohm Cfg + * PREEMP config 0.00 + * TX/CK level 10 + */ +static const struct dw_hdmi_phy_config ingenic_phy_config[] = { + /*pixelclk symbol term vlev */ + { 21600, 0x800d, 0x0005, 0x01ad}, + { ~0UL, 0x, 0x, 0x} +}; + +static enum drm_mode_status +ingenic_dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + if (mode->clock < 13500) + return MODE_CLOCK_LOW; + /* FIXME: Hardware is capable of 270MHz, but setup data is missing. */ + if (mode->clock > 216000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static struct dw_hdmi_plat_data ingenic_dw_hdmi_plat_data = { + .mpll_cfg = ingenic_mpll_cfg, + .cur_ctr= ingenic_cur_ctr, + .phy_config = ingenic_phy_config, + .mode_valid = ingenic_dw_hdmi_mode_valid, + .output_port= 1, +}; + +static const struct of_device_id ingenic_dw_hdmi_dt_ids[] = { + { .compatible = "ingenic,jz4780-dw-hdmi" }, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ingenic_dw_hdmi_dt_ids); + +static int ingenic_dw_hdmi_probe(struct platform_device *pdev) +{ + struct dw_hdmi *hdmi; + struct regulator *regulator; + int ret; + + hdmi = dw_hdmi_probe(pdev, &ingenic_dw_hdmi_plat_data); + if (IS_ERR(hdmi)) + return PTR_ERR(hdmi); + + platform_set_drvdata(pdev, hdmi); + + regulator = devm_regulator_get_optional(&pdev->dev, "hdmi-5v"); + + if (IS_ERR(regulator)) { + ret = PTR_ERR(regulator); + +
[PATCH v7 5/8] MIPS: DTS: jz4780: Account for Synopsys HDMI driver and LCD controllers
From: Paul Boddie A specialisation of the generic Synopsys HDMI driver is employed for JZ4780 HDMI support. This requires a new driver, plus device tree and configuration modifications. Here we add jz4780 device tree setup. Signed-off-by: Paul Boddie Signed-off-by: H. Nikolaus Schaller --- arch/mips/boot/dts/ingenic/jz4780.dtsi | 40 ++ 1 file changed, 40 insertions(+) diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi index b0a4e2e019c36..3f9ea47a10cd2 100644 --- a/arch/mips/boot/dts/ingenic/jz4780.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi @@ -444,6 +444,46 @@ i2c4: i2c@10054000 { status = "disabled"; }; + hdmi: hdmi@1018 { + compatible = "ingenic,jz4780-dw-hdmi"; + reg = <0x1018 0x8000>; + reg-io-width = <4>; + + clocks = <&cgu JZ4780_CLK_AHB0>, <&cgu JZ4780_CLK_HDMI>; + clock-names = "iahb", "isfr"; + + interrupt-parent = <&intc>; + interrupts = <3>; + + status = "disabled"; + }; + + lcdc0: lcdc0@1305 { + compatible = "ingenic,jz4780-lcd"; + reg = <0x1305 0x1800>; + + clocks = <&cgu JZ4780_CLK_TVE>, <&cgu JZ4780_CLK_LCD0PIXCLK>; + clock-names = "lcd", "lcd_pclk"; + + interrupt-parent = <&intc>; + interrupts = <31>; + + status = "disabled"; + }; + + lcdc1: lcdc1@130a { + compatible = "ingenic,jz4780-lcd"; + reg = <0x130a 0x1800>; + + clocks = <&cgu JZ4780_CLK_TVE>, <&cgu JZ4780_CLK_LCD1PIXCLK>; + clock-names = "lcd", "lcd_pclk"; + + interrupt-parent = <&intc>; + interrupts = <23>; + + status = "disabled"; + }; + nemc: nemc@1341 { compatible = "ingenic,jz4780-nemc", "simple-mfd"; reg = <0x1341 0x1>; -- 2.33.0
[PATCH v7 6/8] MIPS: DTS: CI20: Add DT nodes for HDMI setup
From: Paul Boddie We need to hook up * HDMI connector * HDMI power regulator * JZ4780_CLK_HDMI @ 27 MHz * DDC pinmux * HDMI and LCDC endpoint connections Signed-off-by: Paul Boddie Signed-off-by: H. Nikolaus Schaller --- arch/mips/boot/dts/ingenic/ci20.dts | 83 +++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts index b249a4f0f6b62..15cf03670693f 100644 --- a/arch/mips/boot/dts/ingenic/ci20.dts +++ b/arch/mips/boot/dts/ingenic/ci20.dts @@ -78,6 +78,18 @@ eth0_power: fixedregulator@0 { enable-active-high; }; + hdmi_out: connector { + compatible = "hdmi-connector"; + label = "HDMI OUT"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&dw_hdmi_out>; + }; + }; + }; + ir: ir { compatible = "gpio-ir-receiver"; gpios = <&gpe 3 GPIO_ACTIVE_LOW>; @@ -102,6 +114,17 @@ otg_power: fixedregulator@2 { gpio = <&gpf 14 GPIO_ACTIVE_LOW>; enable-active-high; }; + + hdmi_power: fixedregulator@3 { + compatible = "regulator-fixed"; + + regulator-name = "hdmi_power"; + regulator-min-microvolt = <500>; + regulator-max-microvolt = <500>; + + gpio = <&gpa 25 0>; + enable-active-high; + }; }; &ext { @@ -114,11 +137,13 @@ &cgu { * precision. */ assigned-clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_RTC>, - <&cgu JZ4780_CLK_SSIPLL>, <&cgu JZ4780_CLK_SSI>; + <&cgu JZ4780_CLK_SSIPLL>, <&cgu JZ4780_CLK_SSI>, + <&cgu JZ4780_CLK_HDMI>; assigned-clock-parents = <0>, <&cgu JZ4780_CLK_RTCLK>, <&cgu JZ4780_CLK_MPLL>, -<&cgu JZ4780_CLK_SSIPLL>; - assigned-clock-rates = <4800>, <0>, <5400>; +<&cgu JZ4780_CLK_SSIPLL>, +<0>; + assigned-clock-rates = <4800>, <0>, <5400>, <0>, <2700>; }; &tcu { @@ -509,6 +534,19 @@ pins_i2c4: i2c4 { bias-disable; }; + pins_hdmi_ddc: hdmi_ddc { + function = "hdmi-ddc"; + groups = "hdmi-ddc"; + bias-disable; + }; + + /* switch to PF25 as gpio driving DDC_SDA low */ + pins_hdmi_ddc_unwedge: hdmi_ddc { + function = "hdmi-ddc"; + groups = "hdmi-ddc"; + bias-disable; + }; + pins_nemc: nemc { function = "nemc"; groups = "nemc-data", "nemc-cle-ale", "nemc-rd-we", "nemc-frd-fwe"; @@ -539,3 +577,42 @@ pins_mmc1: mmc1 { bias-disable; }; }; + +&hdmi { + status = "okay"; + + pinctrl-names = "default", "unwedge"; + pinctrl-0 = <&pins_hdmi_ddc>; + pinctrl-1 = <&pins_hdmi_ddc_unwedge>; + + hdmi-5v-supply = <&hdmi_power>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dw_hdmi_in: endpoint { + remote-endpoint = <&lcd_out>; + }; + }; + + port@1 { + reg = <1>; + dw_hdmi_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; +}; + +&lcdc0 { + status = "okay"; + + port { + lcd_out: endpoint { + remote-endpoint = <&dw_hdmi_in>; + }; + }; +}; -- 2.33.0
[PATCH v7 3/8] dt-bindings: display: Add ingenic, jz4780-dw-hdmi DT Schema
From: Sam Ravnborg Add DT bindings for the hdmi driver for the Ingenic JZ4780 SoC. Based on .txt binding from Zubair Lutfullah Kakakhel We also add generic ddc-i2c-bus to synopsys,dw-hdmi.yaml Signed-off-by: Sam Ravnborg Signed-off-by: H. Nikolaus Schaller Cc: Rob Herring Cc: devicet...@vger.kernel.org --- .../display/bridge/ingenic,jz4780-hdmi.yaml | 76 +++ .../display/bridge/synopsys,dw-hdmi.yaml | 3 + 2 files changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml diff --git a/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml b/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml new file mode 100644 index 0..190ca4521b1d0 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bridge/ingenic,jz4780-hdmi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bindings for Ingenic JZ4780 HDMI Transmitter + +maintainers: + - H. Nikolaus Schaller + +description: | + The HDMI Transmitter in the Ingenic JZ4780 is a Synopsys DesignWare HDMI 1.4 + TX controller IP with accompanying PHY IP. + +allOf: + - $ref: bridge/synopsys,dw-hdmi.yaml# + +properties: + compatible: +const: ingenic,jz4780-dw-hdmi + + reg-io-width: +const: 4 + + clocks: +maxItems: 2 + + hdmi-5v-supply: +description: Optional regulator to provide +5V at the connector + + ports: +$ref: /schemas/graph.yaml#/properties/ports + +required: +- compatible +- clocks +- clock-names +- ports +- reg-io-width + +unevaluatedPropertes: false + +examples: + - | +#include + +hdmi: hdmi@1018 { +compatible = "ingenic,jz4780-dw-hdmi"; +reg = <0x1018 0x8000>; +reg-io-width = <4>; +ddc-i2c-bus = <&i2c4>; +interrupt-parent = <&intc>; +interrupts = <3>; +clocks = <&cgu JZ4780_CLK_AHB0>, <&cgu JZ4780_CLK_HDMI>; +clock-names = "iahb", "isfr"; + +ports { +#address-cells = <1>; +#size-cells = <0>; +hdmi_in: port@0 { +reg = <0>; +dw_hdmi_in: endpoint { +remote-endpoint = <&jz4780_lcd_out>; +}; +}; +hdmi_out: port@1 { +reg = <1>; +dw_hdmi_out: endpoint { +remote-endpoint = <&hdmi_con>; +}; +}; +}; +}; + +... diff --git a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml index 9be44a682e67a..9cbeabaee0968 100644 --- a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml @@ -50,6 +50,9 @@ properties: interrupts: maxItems: 1 + ddc-i2c-bus: +description: An I2C interface if the internal DDC I2C driver is not to be used + additionalProperties: true ... -- 2.33.0
[PATCH v7 2/8] drm/ingenic: Add support for JZ4780 and HDMI output
From: Paul Boddie Add support for the LCD controller present on JZ4780 SoCs. This SoC uses 8-byte descriptors which extend the current 4-byte descriptors used for other Ingenic SoCs. Tested on MIPS Creator CI20 board. Signed-off-by: Paul Boddie Signed-off-by: Ezequiel Garcia Signed-off-by: H. Nikolaus Schaller --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 55 ++- drivers/gpu/drm/ingenic/ingenic-drm.h | 38 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 0bb590c3910d9..5ff97a4bbcfe5 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -6,6 +6,7 @@ #include "ingenic-drm.h" +#include #include #include #include @@ -49,6 +50,11 @@ struct ingenic_dma_hwdesc { u32 addr; u32 id; u32 cmd; + /* extended hw descriptor for jz4780 */ + u32 offsize; + u32 pagewidth; + u32 cpos; + u32 dessize; } __aligned(16); struct ingenic_dma_hwdescs { @@ -60,6 +66,7 @@ struct jz_soc_info { bool needs_dev_clk; bool has_osd; bool map_noncoherent; + bool use_extended_hwdesc; unsigned int max_width, max_height; const u32 *formats_f0, *formats_f1; unsigned int num_formats_f0, num_formats_f1; @@ -446,6 +453,9 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, if (!crtc) return 0; + if (plane == &priv->f0) + return -EINVAL; + crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); if (WARN_ON(!crtc_state)) @@ -662,6 +672,33 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); hwdesc->next = dma_hwdesc_addr(priv, next_id); + if (priv->soc_info->use_extended_hwdesc) { + hwdesc->cmd |= JZ_LCD_CMD_FRM_ENABLE; + + /* Extended 8-byte descriptor */ + hwdesc->cpos = 0; + hwdesc->offsize = 0; + hwdesc->pagewidth = 0; + + switch (newstate->fb->format->format) { + case DRM_FORMAT_XRGB1555: + hwdesc->cpos |= JZ_LCD_CPOS_RGB555; + fallthrough; + case DRM_FORMAT_RGB565: + hwdesc->cpos |= JZ_LCD_CPOS_BPP_15_16; + break; + case DRM_FORMAT_XRGB: + hwdesc->cpos |= JZ_LCD_CPOS_BPP_18_24; + break; + } + hwdesc->cpos |= (JZ_LCD_CPOS_COEFFICIENT_1 << +JZ_LCD_CPOS_COEFFICIENT_OFFSET); + hwdesc->dessize = + (0xff << JZ_LCD_DESSIZE_ALPHA_OFFSET) | + FIELD_PREP(JZ_LCD_DESSIZE_HEIGHT_MASK, height - 1) | + FIELD_PREP(JZ_LCD_DESSIZE_WIDTH_MASK, width - 1); + } + if (drm_atomic_crtc_needs_modeset(crtc_state)) { fourcc = newstate->fb->format->format; @@ -693,6 +730,9 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE; } + if (priv->soc_info->use_extended_hwdesc) + cfg |= JZ_LCD_CFG_DESCRIPTOR_8; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; if (mode->flags & DRM_MODE_FLAG_NVSYNC) @@ -1064,7 +1104,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) } regmap_config = ingenic_drm_regmap_config; - regmap_config.max_register = res->end - res->start; + regmap_config.max_register = res->end - res->start - 4; priv->map = devm_regmap_init_mmio(dev, base, ®map_config); if (IS_ERR(priv->map)) { @@ -1468,10 +1508,23 @@ static const struct jz_soc_info jz4770_soc_info = { .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), }; +static const struct jz_soc_info jz4780_soc_info = { + .needs_dev_clk = true, + .has_osd = true, + .use_extended_hwdesc = true, + .max_width = 4096, + .max_height = 2048, + .formats_f1 = jz4770_formats_f1, + .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1), + .formats_f0 = jz4770_formats_f0, + .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), +}; + static const struct of_device_id ingenic_drm_of_match[] = { { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info },
[PATCH v7 8/8] [RFC] MIPS: DTS: Ingenic: adjust register size to available registers
After getting the regmap size from the device tree we should reduce the ranges to the really available registers. This allows to read only existing registers from the debug fs and makes the regmap check out-of-bounds access. For the jz4780 we have done this already. Suggested-for: Paul Cercueil Signed-off-by: H. Nikolaus Schaller --- arch/mips/boot/dts/ingenic/jz4725b.dtsi | 2 +- arch/mips/boot/dts/ingenic/jz4740.dtsi | 2 +- arch/mips/boot/dts/ingenic/jz4770.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/boot/dts/ingenic/jz4725b.dtsi b/arch/mips/boot/dts/ingenic/jz4725b.dtsi index 0c6a5a4266f43..e9e48022f6316 100644 --- a/arch/mips/boot/dts/ingenic/jz4725b.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4725b.dtsi @@ -321,7 +321,7 @@ udc: usb@1304 { lcd: lcd-controller@1305 { compatible = "ingenic,jz4725b-lcd"; - reg = <0x1305 0x1000>; + reg = <0x1305 0x130>; /* tbc */ interrupt-parent = <&intc>; interrupts = <31>; diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi index 772542e1f266a..7f76cba03a089 100644 --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -323,7 +323,7 @@ udc: usb@1304 { lcd: lcd-controller@1305 { compatible = "ingenic,jz4740-lcd"; - reg = <0x1305 0x1000>; + reg = <0x1305 0x60>; /* LCDCMD1+4 */ interrupt-parent = <&intc>; interrupts = <30>; diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi index dfe74328ae5dc..bda0a3a86ed5f 100644 --- a/arch/mips/boot/dts/ingenic/jz4770.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi @@ -399,7 +399,7 @@ gpu: gpu@1304 { lcd: lcd-controller@1305 { compatible = "ingenic,jz4770-lcd"; - reg = <0x1305 0x300>; + reg = <0x1305 0x130>; /* tbc */ interrupt-parent = <&intc>; interrupts = <31>; -- 2.33.0
[PATCH v7 7/8] MIPS: defconfig: CI20: configure for DRM_DW_HDMI_JZ4780
Enable CONFIG options as modules. Signed-off-by: Ezequiel Garcia Signed-off-by: H. Nikolaus Schaller --- arch/mips/configs/ci20_defconfig | 6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig index ab7ebb0668340..cc69b215854ea 100644 --- a/arch/mips/configs/ci20_defconfig +++ b/arch/mips/configs/ci20_defconfig @@ -98,7 +98,13 @@ CONFIG_RC_DEVICES=y CONFIG_IR_GPIO_CIR=m CONFIG_IR_GPIO_TX=m CONFIG_MEDIA_SUPPORT=m +CONFIG_DRM=m +CONFIG_DRM_INGENIC=m +CONFIG_DRM_INGENIC_DW_HDMI=m +CONFIG_DRM_DISPLAY_CONNECTOR=m # CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y +CONFIG_FRAMEBUFFER_CONSOLE=y # CONFIG_HID is not set CONFIG_USB=y CONFIG_USB_STORAGE=y -- 2.33.0
Re: [PATCH 2/3] drm/i915/gt: Compare average group occupancy for RPS evaluation
On 11/17/2021 2:49 PM, Vinay Belgaumkar wrote: From: Chris Wilson Currently, we inspect each engine individually and measure the occupancy of that engine over the last evaluation interval. If that exceeds our busyness thresholds, we decide to increase the GPU frequency. However, under a load balancer, we should consider the occupancy of entire engine groups, as work may be spread out across the group. In doing so, we prefer wide over fast, power consumption is approximately proportional to the square of the frequency. However, since the load balancer is greedy, the first idle engine gets all the work, and preferrentially reuses the last active engine, under light loads all work is assigned to one engine, and so that engine appears very busy. But if the work happened to overlap slightly, the workload would spread across multiple engines, reducing each individual engine's runtime, and so reducing the rps contribution, keeping the frequency low. Instead, when considering the contribution, consider the contribution over the entire engine group (capacity). Signed-off-by: Chris Wilson Cc: Vinay Belgaumkar Cc: Tvrtko Ursulin Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rps.c | 48 - 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 07ff7ba7b2b7..3675ac93ded0 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -7,6 +7,7 @@ #include "i915_drv.h" #include "intel_breadcrumbs.h" +#include "intel_engine_pm.h" #include "intel_gt.h" #include "intel_gt_clock_utils.h" #include "intel_gt_irq.h" @@ -65,26 +66,45 @@ static void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val) static void rps_timer(struct timer_list *t) { struct intel_rps *rps = from_timer(rps, t, timer); - struct intel_engine_cs *engine; - ktime_t dt, last, timestamp; - enum intel_engine_id id; + struct intel_gt *gt = rps_to_gt(rps); + ktime_t dt, last, timestamp = 0; s64 max_busy[3] = {}; + int i, j; - timestamp = 0; - for_each_engine(engine, rps_to_gt(rps), id) { - s64 busy; - int i; + /* Compare average occupancy over each engine group */ + for (i = 0; i < ARRAY_SIZE(gt->engine_class); i++) { + s64 busy = 0; + int count = 0; + + for (j = 0; j < ARRAY_SIZE(gt->engine_class[i]); j++) { + struct intel_engine_cs *engine; - dt = intel_engine_get_busy_time(engine, ×tamp); - last = engine->stats.rps; - engine->stats.rps = dt; + engine = gt->engine_class[i][j]; + if (!engine) + continue; - busy = ktime_to_ns(ktime_sub(dt, last)); - for (i = 0; i < ARRAY_SIZE(max_busy); i++) { - if (busy > max_busy[i]) - swap(busy, max_busy[i]); + dt = intel_engine_get_busy_time(engine, ×tamp); + last = engine->stats.rps; + engine->stats.rps = dt; + + if (!intel_engine_pm_is_awake(engine)) + continue; + + busy += ktime_to_ns(ktime_sub(dt, last)); + count++; + } + + if (count > 1) + busy = div_u64(busy, count); + if (busy <= max_busy[ARRAY_SIZE(max_busy) - 1]) + continue; + + for (j = 0; j < ARRAY_SIZE(max_busy); j++) { + if (busy > max_busy[j]) + swap(busy, max_busy[j]); } } + last = rps->pm_timestamp; rps->pm_timestamp = timestamp;
Re: [PATCH 3/3] drm/i915/gt: Improve "race-to-idle" at low frequencies
On 11/17/2021 2:49 PM, Vinay Belgaumkar wrote: From: Chris Wilson While the power consumption is proportional to the frequency, there is also a static draw for active gates. The longer we are able to powergate (rc6), the lower the static draw. Thus there is a sweetspot in the frequency/power curve where we run at higher frequency in order to sleep longer, aka race-to-idle. This is more evident at lower frequencies, so let's look to bump the frequency if we think we will benefit by sleeping longer at the higher frequency and so conserving power. Signed-off-by: Chris Wilson Cc: Vinay Belgaumkar Cc: Tvrtko Ursulin Data collected does show some power savings. Reviewed-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rps.c | 31 - 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 3675ac93ded0..6af3231982af 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -63,6 +63,22 @@ static void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val) intel_uncore_write_fw(uncore, reg, val); } +static bool race_to_idle(struct intel_rps *rps, u64 busy, u64 dt) +{ + unsigned int this = rps->cur_freq; + unsigned int next = rps->cur_freq + 1; + u64 next_dt = next * max(busy, dt); + + /* +* Compare estimated time spent in rc6 at the next power bin. If +* we expect to sleep longer than the estimated increased power +* cost of running at a higher frequency, it will be reduced power +* consumption overall. +*/ + return (((next_dt - this * busy) >> 10) * this * this > + ((next_dt - next * busy) >> 10) * next * next); +} + static void rps_timer(struct timer_list *t) { struct intel_rps *rps = from_timer(rps, t, timer); @@ -133,7 +149,7 @@ static void rps_timer(struct timer_list *t) if (!max_busy[i]) break; - busy += div_u64(max_busy[i], 1 << i); + busy += max_busy[i] >> i; } GT_TRACE(rps_to_gt(rps), "busy:%lld [%d%%], max:[%lld, %lld, %lld], interval:%d\n", @@ -141,13 +157,18 @@ static void rps_timer(struct timer_list *t) max_busy[0], max_busy[1], max_busy[2], rps->pm_interval); - if (100 * busy > rps->power.up_threshold * dt && - rps->cur_freq < rps->max_freq_softlimit) { + if (rps->cur_freq < rps->max_freq_softlimit && + race_to_idle(rps, max_busy[0], dt)) { + rps->pm_iir |= GEN6_PM_RP_UP_THRESHOLD; + rps->pm_interval = 1; + schedule_work(&rps->work); + } else if (rps->cur_freq < rps->max_freq_softlimit && + 100 * busy > rps->power.up_threshold * dt) { rps->pm_iir |= GEN6_PM_RP_UP_THRESHOLD; rps->pm_interval = 1; schedule_work(&rps->work); - } else if (100 * busy < rps->power.down_threshold * dt && - rps->cur_freq > rps->min_freq_softlimit) { + } else if (rps->cur_freq > rps->min_freq_softlimit && + 100 * busy < rps->power.down_threshold * dt) { rps->pm_iir |= GEN6_PM_RP_DOWN_THRESHOLD; rps->pm_interval = 1; schedule_work(&rps->work);
Re: [PATCH v7 2/8] drm/ingenic: Add support for JZ4780 and HDMI output
Hi Nikolaus, Le mar., nov. 23 2021 at 18:46:17 +0100, H. Nikolaus Schaller a écrit : From: Paul Boddie Add support for the LCD controller present on JZ4780 SoCs. This SoC uses 8-byte descriptors which extend the current 4-byte descriptors used for other Ingenic SoCs. Tested on MIPS Creator CI20 board. Signed-off-by: Paul Boddie Signed-off-by: Ezequiel Garcia Signed-off-by: H. Nikolaus Schaller --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 55 ++- drivers/gpu/drm/ingenic/ingenic-drm.h | 38 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 0bb590c3910d9..5ff97a4bbcfe5 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -6,6 +6,7 @@ #include "ingenic-drm.h" +#include #include #include #include @@ -49,6 +50,11 @@ struct ingenic_dma_hwdesc { u32 addr; u32 id; u32 cmd; + /* extended hw descriptor for jz4780 */ + u32 offsize; + u32 pagewidth; + u32 cpos; + u32 dessize; } __aligned(16); struct ingenic_dma_hwdescs { @@ -60,6 +66,7 @@ struct jz_soc_info { bool needs_dev_clk; bool has_osd; bool map_noncoherent; + bool use_extended_hwdesc; unsigned int max_width, max_height; const u32 *formats_f0, *formats_f1; unsigned int num_formats_f0, num_formats_f1; @@ -446,6 +453,9 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, if (!crtc) return 0; + if (plane == &priv->f0) + return -EINVAL; + crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); if (WARN_ON(!crtc_state)) @@ -662,6 +672,33 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); hwdesc->next = dma_hwdesc_addr(priv, next_id); + if (priv->soc_info->use_extended_hwdesc) { + hwdesc->cmd |= JZ_LCD_CMD_FRM_ENABLE; + + /* Extended 8-byte descriptor */ + hwdesc->cpos = 0; + hwdesc->offsize = 0; + hwdesc->pagewidth = 0; + + switch (newstate->fb->format->format) { + case DRM_FORMAT_XRGB1555: + hwdesc->cpos |= JZ_LCD_CPOS_RGB555; + fallthrough; + case DRM_FORMAT_RGB565: + hwdesc->cpos |= JZ_LCD_CPOS_BPP_15_16; + break; + case DRM_FORMAT_XRGB: + hwdesc->cpos |= JZ_LCD_CPOS_BPP_18_24; + break; + } + hwdesc->cpos |= (JZ_LCD_CPOS_COEFFICIENT_1 << +JZ_LCD_CPOS_COEFFICIENT_OFFSET); + hwdesc->dessize = + (0xff << JZ_LCD_DESSIZE_ALPHA_OFFSET) | + FIELD_PREP(JZ_LCD_DESSIZE_HEIGHT_MASK, height - 1) | + FIELD_PREP(JZ_LCD_DESSIZE_WIDTH_MASK, width - 1); + } + if (drm_atomic_crtc_needs_modeset(crtc_state)) { fourcc = newstate->fb->format->format; @@ -693,6 +730,9 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE; } + if (priv->soc_info->use_extended_hwdesc) + cfg |= JZ_LCD_CFG_DESCRIPTOR_8; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; if (mode->flags & DRM_MODE_FLAG_NVSYNC) @@ -1064,7 +1104,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) } regmap_config = ingenic_drm_regmap_config; - regmap_config.max_register = res->end - res->start; + regmap_config.max_register = res->end - res->start - 4; I think this is wrong :) Cheers, -Paul priv->map = devm_regmap_init_mmio(dev, base, ®map_config); if (IS_ERR(priv->map)) { @@ -1468,10 +1508,23 @@ static const struct jz_soc_info jz4770_soc_info = { .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), }; +static const struct jz_soc_info jz4780_soc_info = { + .needs_dev_clk = true, + .has_osd = true, + .use_extended_hwdesc = true, + .max_width = 4096, + .max_height = 2048, + .formats_f1 = jz4770_formats_f1, + .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1), + .formats_f0 = jz4770_formats_f0, + .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), +}; + s
Re: [PATCH v7 2/8] drm/ingenic: Add support for JZ4780 and HDMI output
> Am 23.11.2021 um 19:06 schrieb Paul Cercueil : > > Hi Nikolaus, > > Le mar., nov. 23 2021 at 18:46:17 +0100, H. Nikolaus Schaller > a écrit : >> From: Paul Boddie >> Add support for the LCD controller present on JZ4780 SoCs. >> This SoC uses 8-byte descriptors which extend the current >> 4-byte descriptors used for other Ingenic SoCs. >> Tested on MIPS Creator CI20 board. >> Signed-off-by: Paul Boddie >> Signed-off-by: Ezequiel Garcia >> Signed-off-by: H. Nikolaus Schaller >> --- >> drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 55 ++- >> drivers/gpu/drm/ingenic/ingenic-drm.h | 38 >> 2 files changed, 92 insertions(+), 1 deletion(-) >> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c >> b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c >> index 0bb590c3910d9..5ff97a4bbcfe5 100644 >> --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c >> +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c >> @@ -6,6 +6,7 @@ >> #include "ingenic-drm.h" >> +#include >> #include >> #include >> #include >> @@ -49,6 +50,11 @@ struct ingenic_dma_hwdesc { >> u32 addr; >> u32 id; >> u32 cmd; >> +/* extended hw descriptor for jz4780 */ >> +u32 offsize; >> +u32 pagewidth; >> +u32 cpos; >> +u32 dessize; >> } __aligned(16); >> struct ingenic_dma_hwdescs { >> @@ -60,6 +66,7 @@ struct jz_soc_info { >> bool needs_dev_clk; >> bool has_osd; >> bool map_noncoherent; >> +bool use_extended_hwdesc; >> unsigned int max_width, max_height; >> const u32 *formats_f0, *formats_f1; >> unsigned int num_formats_f0, num_formats_f1; >> @@ -446,6 +453,9 @@ static int ingenic_drm_plane_atomic_check(struct >> drm_plane *plane, >> if (!crtc) >> return 0; >> +if (plane == &priv->f0) >> +return -EINVAL; >> + >> crtc_state = drm_atomic_get_existing_crtc_state(state, >> crtc); >> if (WARN_ON(!crtc_state)) >> @@ -662,6 +672,33 @@ static void ingenic_drm_plane_atomic_update(struct >> drm_plane *plane, >> hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); >> hwdesc->next = dma_hwdesc_addr(priv, next_id); >> +if (priv->soc_info->use_extended_hwdesc) { >> +hwdesc->cmd |= JZ_LCD_CMD_FRM_ENABLE; >> + >> +/* Extended 8-byte descriptor */ >> +hwdesc->cpos = 0; >> +hwdesc->offsize = 0; >> +hwdesc->pagewidth = 0; >> + >> +switch (newstate->fb->format->format) { >> +case DRM_FORMAT_XRGB1555: >> +hwdesc->cpos |= JZ_LCD_CPOS_RGB555; >> +fallthrough; >> +case DRM_FORMAT_RGB565: >> +hwdesc->cpos |= JZ_LCD_CPOS_BPP_15_16; >> +break; >> +case DRM_FORMAT_XRGB: >> +hwdesc->cpos |= JZ_LCD_CPOS_BPP_18_24; >> +break; >> +} >> +hwdesc->cpos |= (JZ_LCD_CPOS_COEFFICIENT_1 << >> + JZ_LCD_CPOS_COEFFICIENT_OFFSET); >> +hwdesc->dessize = >> +(0xff << JZ_LCD_DESSIZE_ALPHA_OFFSET) | >> +FIELD_PREP(JZ_LCD_DESSIZE_HEIGHT_MASK, height - >> 1) | >> +FIELD_PREP(JZ_LCD_DESSIZE_WIDTH_MASK, width - >> 1); >> +} >> + >> if (drm_atomic_crtc_needs_modeset(crtc_state)) { >> fourcc = newstate->fb->format->format; >> @@ -693,6 +730,9 @@ static void ingenic_drm_encoder_atomic_mode_set(struct >> drm_encoder *encoder, >> | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE; >> } >> +if (priv->soc_info->use_extended_hwdesc) >> +cfg |= JZ_LCD_CFG_DESCRIPTOR_8; >> + >> if (mode->flags & DRM_MODE_FLAG_NHSYNC) >> cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; >> if (mode->flags & DRM_MODE_FLAG_NVSYNC) >> @@ -1064,7 +1104,7 @@ static int ingenic_drm_bind(struct device *dev, bool >> has_components) >> } >> regmap_config = ingenic_drm_regmap_config; >> -regmap_config.max_register = res->end - res->start; >> +regmap_config.max_register = res->end - res->start - 4; > > I think this is wrong :) Oops, that is a side-effect of my patch series editing tool. It sometimes reverts changes of a previous commit if both affect the same file. Sorry for that and I should fix it... I'll send v8. BR and thanks, Nikolaus > > Cheers, > -Paul > >> priv->map = devm_regmap_init_mmio(dev, base, >>®map_config); >> if (IS_ERR(priv->map)) { >> @@ -1468,10 +1508,23 @@ static const struct jz_soc_info jz4770_soc_info = { >> .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), >> }; >> +static c
[PATCH v8 0/8] MIPS: JZ4780 and CI20 HDMI
PATCH V8 2021-11-23 19:14:00: - fix a bad editing result from patch 2/8 (found by p...@crapouillou.net) PATCH V7 2021-11-23 18:46:23: - changed gpio polarity of hdmi_power to 0 (suggested by p...@crapouillou.net) - fixed LCD1 irq number (bug found by p...@crapouillou.net) - removed "- 4" for calculating max_register (suggested by p...@crapouillou.net) - use unevaluatedPropertes instead of additionalProperties (suggested by r...@kernel.org) - moved and renamed ingenic,jz4780-hdmi.yaml (suggested by r...@kernel.org) - adjusted assigned-clocks changes to upstream which added some for SSI (by h...@goldelico.com) - rebased and tested with v5.16-rc2 + patch set drm/ingenic by p...@crapouillou.net (by h...@goldelico.com) PATCH V6 2021-11-10 20:43:33: - changed CONFIG_DRM_INGENIC_DW_HDMI to "m" (by h...@goldelico.com) - made ingenic-dw-hdmi an independent platform driver which can be compiled as module and removed error patch fixes for IPU (suggested by p...@crapouillou.net) - moved assigned-clocks from jz4780.dtsi to ci20.dts (suggested by p...@crapouillou.net) - fixed reg property in jz4780.dtsi to cover all registers incl. gamma and vee (by h...@goldelico.com) - added a base patch to calculate regmap size from DTS reg property (requested by p...@crapouillou.net) - restored resetting all bits except one in LCDOSDC (requested by p...@crapouillou.net) - clarified setting of cpos (suggested by p...@crapouillou.net) - moved bindings definition for ddc-i2c-bus (suggested by p...@crapouillou.net) - simplified mask definitions for JZ_LCD_DESSIZE (requested by p...@crapouillou.net) - removed setting alpha premultiplication (suggested by p...@crapouillou.net) - removed some comments (suggested by p...@crapouillou.net) PATCH V5 2021-10-05 14:28:44: - dropped mode_fixup and timings support in dw-hdmi as it is no longer needed in this V5 (by h...@goldelico.com) - dropped "drm/ingenic: add some jz4780 specific features" (stimulated by p...@crapouillou.net) - fixed typo in commit subject: "synopsis" -> "synopsys" (by h...@goldelico.com) - swapped clocks in jz4780.dtsi to match synopsys,dw-hdmi.yaml (by h...@goldelico.com) - improved, simplified, fixed, dtbschecked ingenic-jz4780-hdmi.yaml and made dependent of bridge/synopsys,dw-hdmi.yaml (based on suggestions by max...@cerno.tech) - fixed binding vs. driver&DTS use of hdmi-5v regulator (suggested by max...@cerno.tech) - dropped "drm/bridge: synopsis: Fix to properly handle HPD" - was a no longer needed workaround for a previous version (suggested by max...@cerno.tech) PATCH V4 2021-09-27 18:44:38: - fix setting output_port = 1 (issue found by p...@crapouillou.net) - ci20.dts: convert to use hdmi-connector (by h...@goldelico.com) - add a hdmi-regulator to control +5V power (by h...@goldelico.com) - added a fix to dw-hdmi to call drm_kms_helper_hotplug_event on plugin event detection (by h...@goldelico.com) - always allocate extended descriptor but initialize only for jz4780 (by h...@goldelico.com) - updated to work on top of "[PATCH v3 0/6] drm/ingenic: Various improvements v3" (by p...@crapouillou.net) - rebased to v5.13-rc3 PATCH V3 2021-08-08 07:10:50: This series adds HDMI support for JZ4780 and CI20 board (and fixes one IPU related issue in registration error path) - [patch 1/8] switched from mode_fixup to atomic_check (suggested by robert.f...@linaro.org) - the call to the dw-hdmi specialization is still called mode_fixup - [patch 3/8] diverse fixes for ingenic-drm-drv (suggested by p...@crapouillou.net) - factor out some non-HDMI features of the jz4780 into a separate patch - multiple fixes around max height - do not change regmap config but a copy on stack - define some constants - factor out fixing of drm_init error path for IPU into separate patch - use FIELD_PREP() - [patch 8/8] conversion to component framework dropped (suggested by laurent.pinch...@ideasonboard.com and p...@crapouillou.net) PATCH V2 2021-08-05 16:08:05: - code and commit messages revisited for checkpatch warnings - rebased on v5.14-rc4 - include (failed, hence RFC 8/8) attempt to convert to component framework (was suggested by Paul Cercueil a while ago) This series adds HDMI support for JZ4780 and CI20 board H. Nikolaus Schaller (3): drm/ingenic: prepare ingenic drm for later addition of JZ4780 MIPS: defconfig: CI20: configure for DRM_DW_HDMI_JZ4780 [RFC] MIPS: DTS: Ingenic: adjust register size to available registers Paul Boddie (4): drm/ingenic: Add support for JZ4780 and HDMI output drm/ingenic: Add dw-hdmi driver for jz4780 MIPS: DTS: jz4780: Account for Synopsys HDMI driver and LCD controllers MIPS: DTS: CI20: Add DT nodes for HDMI setup Sam Ravnborg (1): dt-bindings: display: Add ingenic,jz4780-dw-hdmi DT Schema .../display/bridge/ingenic,jz4780-hdmi.yaml | 76 +++ .../display/bridge/synopsys,dw-hdmi.yaml | 3 + arch/mips/boot/dts/ingenic/ci20.dts | 83 ++- arch/mips/boot/dts/
[PATCH v8 1/8] drm/ingenic: prepare ingenic drm for later addition of JZ4780
This changes the way the regmap is allocated to prepare for the later addition of the JZ4780 which has more registers and bits than the others. Therefore we make the regmap as big as the reg property in the device tree tells. Suggested-by: Paul Cercueil Signed-off-by: H. Nikolaus Schaller --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 462bc0f35f1bf..0bb590c3910d9 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -173,7 +173,6 @@ static const struct regmap_config ingenic_drm_regmap_config = { .val_bits = 32, .reg_stride = 4, - .max_register = JZ_REG_LCD_SIZE1, .writeable_reg = ingenic_drm_writeable_reg, }; @@ -1011,6 +1010,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) struct ingenic_drm_bridge *ib; struct drm_device *drm; void __iomem *base; + struct resource *res; + struct regmap_config regmap_config; long parent_rate; unsigned int i, clone_mask = 0; int ret, irq; @@ -1056,14 +1057,16 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) drm->mode_config.funcs = &ingenic_drm_mode_config_funcs; drm->mode_config.helper_private = &ingenic_drm_mode_config_helpers; - base = devm_platform_ioremap_resource(pdev, 0); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(base)) { dev_err(dev, "Failed to get memory resource\n"); return PTR_ERR(base); } + regmap_config = ingenic_drm_regmap_config; + regmap_config.max_register = res->end - res->start; priv->map = devm_regmap_init_mmio(dev, base, - &ingenic_drm_regmap_config); + ®map_config); if (IS_ERR(priv->map)) { dev_err(dev, "Failed to create regmap\n"); return PTR_ERR(priv->map); -- 2.33.0
[PATCH v8 7/8] MIPS: defconfig: CI20: configure for DRM_DW_HDMI_JZ4780
Enable CONFIG options as modules. Signed-off-by: Ezequiel Garcia Signed-off-by: H. Nikolaus Schaller --- arch/mips/configs/ci20_defconfig | 6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig index ab7ebb0668340..cc69b215854ea 100644 --- a/arch/mips/configs/ci20_defconfig +++ b/arch/mips/configs/ci20_defconfig @@ -98,7 +98,13 @@ CONFIG_RC_DEVICES=y CONFIG_IR_GPIO_CIR=m CONFIG_IR_GPIO_TX=m CONFIG_MEDIA_SUPPORT=m +CONFIG_DRM=m +CONFIG_DRM_INGENIC=m +CONFIG_DRM_INGENIC_DW_HDMI=m +CONFIG_DRM_DISPLAY_CONNECTOR=m # CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y +CONFIG_FRAMEBUFFER_CONSOLE=y # CONFIG_HID is not set CONFIG_USB=y CONFIG_USB_STORAGE=y -- 2.33.0
[PATCH v8 3/8] dt-bindings: display: Add ingenic, jz4780-dw-hdmi DT Schema
From: Sam Ravnborg Add DT bindings for the hdmi driver for the Ingenic JZ4780 SoC. Based on .txt binding from Zubair Lutfullah Kakakhel We also add generic ddc-i2c-bus to synopsys,dw-hdmi.yaml Signed-off-by: Sam Ravnborg Signed-off-by: H. Nikolaus Schaller Cc: Rob Herring Cc: devicet...@vger.kernel.org --- .../display/bridge/ingenic,jz4780-hdmi.yaml | 76 +++ .../display/bridge/synopsys,dw-hdmi.yaml | 3 + 2 files changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml diff --git a/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml b/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml new file mode 100644 index 0..190ca4521b1d0 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/ingenic,jz4780-hdmi.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bridge/ingenic,jz4780-hdmi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bindings for Ingenic JZ4780 HDMI Transmitter + +maintainers: + - H. Nikolaus Schaller + +description: | + The HDMI Transmitter in the Ingenic JZ4780 is a Synopsys DesignWare HDMI 1.4 + TX controller IP with accompanying PHY IP. + +allOf: + - $ref: bridge/synopsys,dw-hdmi.yaml# + +properties: + compatible: +const: ingenic,jz4780-dw-hdmi + + reg-io-width: +const: 4 + + clocks: +maxItems: 2 + + hdmi-5v-supply: +description: Optional regulator to provide +5V at the connector + + ports: +$ref: /schemas/graph.yaml#/properties/ports + +required: +- compatible +- clocks +- clock-names +- ports +- reg-io-width + +unevaluatedPropertes: false + +examples: + - | +#include + +hdmi: hdmi@1018 { +compatible = "ingenic,jz4780-dw-hdmi"; +reg = <0x1018 0x8000>; +reg-io-width = <4>; +ddc-i2c-bus = <&i2c4>; +interrupt-parent = <&intc>; +interrupts = <3>; +clocks = <&cgu JZ4780_CLK_AHB0>, <&cgu JZ4780_CLK_HDMI>; +clock-names = "iahb", "isfr"; + +ports { +#address-cells = <1>; +#size-cells = <0>; +hdmi_in: port@0 { +reg = <0>; +dw_hdmi_in: endpoint { +remote-endpoint = <&jz4780_lcd_out>; +}; +}; +hdmi_out: port@1 { +reg = <1>; +dw_hdmi_out: endpoint { +remote-endpoint = <&hdmi_con>; +}; +}; +}; +}; + +... diff --git a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml index 9be44a682e67a..9cbeabaee0968 100644 --- a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml @@ -50,6 +50,9 @@ properties: interrupts: maxItems: 1 + ddc-i2c-bus: +description: An I2C interface if the internal DDC I2C driver is not to be used + additionalProperties: true ... -- 2.33.0
[PATCH v8 8/8] [RFC] MIPS: DTS: Ingenic: adjust register size to available registers
After getting the regmap size from the device tree we should reduce the ranges to the really available registers. This allows to read only existing registers from the debug fs and makes the regmap check out-of-bounds access. For the jz4780 we have done this already. Suggested-for: Paul Cercueil Signed-off-by: H. Nikolaus Schaller --- arch/mips/boot/dts/ingenic/jz4725b.dtsi | 2 +- arch/mips/boot/dts/ingenic/jz4740.dtsi | 2 +- arch/mips/boot/dts/ingenic/jz4770.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/boot/dts/ingenic/jz4725b.dtsi b/arch/mips/boot/dts/ingenic/jz4725b.dtsi index 0c6a5a4266f43..e9e48022f6316 100644 --- a/arch/mips/boot/dts/ingenic/jz4725b.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4725b.dtsi @@ -321,7 +321,7 @@ udc: usb@1304 { lcd: lcd-controller@1305 { compatible = "ingenic,jz4725b-lcd"; - reg = <0x1305 0x1000>; + reg = <0x1305 0x130>; /* tbc */ interrupt-parent = <&intc>; interrupts = <31>; diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi index 772542e1f266a..7f76cba03a089 100644 --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -323,7 +323,7 @@ udc: usb@1304 { lcd: lcd-controller@1305 { compatible = "ingenic,jz4740-lcd"; - reg = <0x1305 0x1000>; + reg = <0x1305 0x60>; /* LCDCMD1+4 */ interrupt-parent = <&intc>; interrupts = <30>; diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi index dfe74328ae5dc..bda0a3a86ed5f 100644 --- a/arch/mips/boot/dts/ingenic/jz4770.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi @@ -399,7 +399,7 @@ gpu: gpu@1304 { lcd: lcd-controller@1305 { compatible = "ingenic,jz4770-lcd"; - reg = <0x1305 0x300>; + reg = <0x1305 0x130>; /* tbc */ interrupt-parent = <&intc>; interrupts = <31>; -- 2.33.0
[PATCH v8 5/8] MIPS: DTS: jz4780: Account for Synopsys HDMI driver and LCD controllers
From: Paul Boddie A specialisation of the generic Synopsys HDMI driver is employed for JZ4780 HDMI support. This requires a new driver, plus device tree and configuration modifications. Here we add jz4780 device tree setup. Signed-off-by: Paul Boddie Signed-off-by: H. Nikolaus Schaller --- arch/mips/boot/dts/ingenic/jz4780.dtsi | 40 ++ 1 file changed, 40 insertions(+) diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi index b0a4e2e019c36..3f9ea47a10cd2 100644 --- a/arch/mips/boot/dts/ingenic/jz4780.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi @@ -444,6 +444,46 @@ i2c4: i2c@10054000 { status = "disabled"; }; + hdmi: hdmi@1018 { + compatible = "ingenic,jz4780-dw-hdmi"; + reg = <0x1018 0x8000>; + reg-io-width = <4>; + + clocks = <&cgu JZ4780_CLK_AHB0>, <&cgu JZ4780_CLK_HDMI>; + clock-names = "iahb", "isfr"; + + interrupt-parent = <&intc>; + interrupts = <3>; + + status = "disabled"; + }; + + lcdc0: lcdc0@1305 { + compatible = "ingenic,jz4780-lcd"; + reg = <0x1305 0x1800>; + + clocks = <&cgu JZ4780_CLK_TVE>, <&cgu JZ4780_CLK_LCD0PIXCLK>; + clock-names = "lcd", "lcd_pclk"; + + interrupt-parent = <&intc>; + interrupts = <31>; + + status = "disabled"; + }; + + lcdc1: lcdc1@130a { + compatible = "ingenic,jz4780-lcd"; + reg = <0x130a 0x1800>; + + clocks = <&cgu JZ4780_CLK_TVE>, <&cgu JZ4780_CLK_LCD1PIXCLK>; + clock-names = "lcd", "lcd_pclk"; + + interrupt-parent = <&intc>; + interrupts = <23>; + + status = "disabled"; + }; + nemc: nemc@1341 { compatible = "ingenic,jz4780-nemc", "simple-mfd"; reg = <0x1341 0x1>; -- 2.33.0
[PATCH v8 6/8] MIPS: DTS: CI20: Add DT nodes for HDMI setup
From: Paul Boddie We need to hook up * HDMI connector * HDMI power regulator * JZ4780_CLK_HDMI @ 27 MHz * DDC pinmux * HDMI and LCDC endpoint connections Signed-off-by: Paul Boddie Signed-off-by: H. Nikolaus Schaller --- arch/mips/boot/dts/ingenic/ci20.dts | 83 +++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts index b249a4f0f6b62..15cf03670693f 100644 --- a/arch/mips/boot/dts/ingenic/ci20.dts +++ b/arch/mips/boot/dts/ingenic/ci20.dts @@ -78,6 +78,18 @@ eth0_power: fixedregulator@0 { enable-active-high; }; + hdmi_out: connector { + compatible = "hdmi-connector"; + label = "HDMI OUT"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&dw_hdmi_out>; + }; + }; + }; + ir: ir { compatible = "gpio-ir-receiver"; gpios = <&gpe 3 GPIO_ACTIVE_LOW>; @@ -102,6 +114,17 @@ otg_power: fixedregulator@2 { gpio = <&gpf 14 GPIO_ACTIVE_LOW>; enable-active-high; }; + + hdmi_power: fixedregulator@3 { + compatible = "regulator-fixed"; + + regulator-name = "hdmi_power"; + regulator-min-microvolt = <500>; + regulator-max-microvolt = <500>; + + gpio = <&gpa 25 0>; + enable-active-high; + }; }; &ext { @@ -114,11 +137,13 @@ &cgu { * precision. */ assigned-clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_RTC>, - <&cgu JZ4780_CLK_SSIPLL>, <&cgu JZ4780_CLK_SSI>; + <&cgu JZ4780_CLK_SSIPLL>, <&cgu JZ4780_CLK_SSI>, + <&cgu JZ4780_CLK_HDMI>; assigned-clock-parents = <0>, <&cgu JZ4780_CLK_RTCLK>, <&cgu JZ4780_CLK_MPLL>, -<&cgu JZ4780_CLK_SSIPLL>; - assigned-clock-rates = <4800>, <0>, <5400>; +<&cgu JZ4780_CLK_SSIPLL>, +<0>; + assigned-clock-rates = <4800>, <0>, <5400>, <0>, <2700>; }; &tcu { @@ -509,6 +534,19 @@ pins_i2c4: i2c4 { bias-disable; }; + pins_hdmi_ddc: hdmi_ddc { + function = "hdmi-ddc"; + groups = "hdmi-ddc"; + bias-disable; + }; + + /* switch to PF25 as gpio driving DDC_SDA low */ + pins_hdmi_ddc_unwedge: hdmi_ddc { + function = "hdmi-ddc"; + groups = "hdmi-ddc"; + bias-disable; + }; + pins_nemc: nemc { function = "nemc"; groups = "nemc-data", "nemc-cle-ale", "nemc-rd-we", "nemc-frd-fwe"; @@ -539,3 +577,42 @@ pins_mmc1: mmc1 { bias-disable; }; }; + +&hdmi { + status = "okay"; + + pinctrl-names = "default", "unwedge"; + pinctrl-0 = <&pins_hdmi_ddc>; + pinctrl-1 = <&pins_hdmi_ddc_unwedge>; + + hdmi-5v-supply = <&hdmi_power>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dw_hdmi_in: endpoint { + remote-endpoint = <&lcd_out>; + }; + }; + + port@1 { + reg = <1>; + dw_hdmi_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; +}; + +&lcdc0 { + status = "okay"; + + port { + lcd_out: endpoint { + remote-endpoint = <&dw_hdmi_in>; + }; + }; +}; -- 2.33.0
[PATCH v8 4/8] drm/ingenic: Add dw-hdmi driver for jz4780
From: Paul Boddie A specialisation of the generic Synopsys HDMI driver is employed for JZ4780 HDMI support. This requires a new driver, plus device tree and configuration modifications. Here we add Kconfig DRM_INGENIC_DW_HDMI, Makefile and driver code. Signed-off-by: Paul Boddie Signed-off-by: Ezequiel Garcia Signed-off-by: H. Nikolaus Schaller --- drivers/gpu/drm/ingenic/Kconfig | 9 ++ drivers/gpu/drm/ingenic/Makefile | 1 + drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c | 129 ++ 3 files changed, 139 insertions(+) create mode 100644 drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig index 3b57f8be007c4..4efc709d77b0a 100644 --- a/drivers/gpu/drm/ingenic/Kconfig +++ b/drivers/gpu/drm/ingenic/Kconfig @@ -25,4 +25,13 @@ config DRM_INGENIC_IPU The Image Processing Unit (IPU) will appear as a second primary plane. +config DRM_INGENIC_DW_HDMI + tristate "Ingenic specific support for Synopsys DW HDMI" + depends on MACH_JZ4780 + select DRM_DW_HDMI + help + Choose this option to enable Synopsys DesignWare HDMI based driver. + If you want to enable HDMI on Ingenic JZ4780 based SoC, you should + select this option.. + endif diff --git a/drivers/gpu/drm/ingenic/Makefile b/drivers/gpu/drm/ingenic/Makefile index d313326bdddbb..f10cc1c5a5f22 100644 --- a/drivers/gpu/drm/ingenic/Makefile +++ b/drivers/gpu/drm/ingenic/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_DRM_INGENIC) += ingenic-drm.o ingenic-drm-y = ingenic-drm-drv.o ingenic-drm-$(CONFIG_DRM_INGENIC_IPU) += ingenic-ipu.o +obj-$(CONFIG_DRM_INGENIC_DW_HDMI) += ingenic-dw-hdmi.o diff --git a/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c b/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c new file mode 100644 index 0..c14890d6b9826 --- /dev/null +++ b/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2011-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2019, 2020 Paul Boddie + * + * Derived from dw_hdmi-imx.c with i.MX portions removed. + * Probe and remove operations derived from rcar_dw_hdmi.c. + */ + +#include +#include +#include + +#include +#include +#include + +static const struct dw_hdmi_mpll_config ingenic_mpll_cfg[] = { + { 4525, { { 0x01e0, 0x }, { 0x21e1, 0x }, { 0x41e2, 0x } } }, + { 9250, { { 0x0140, 0x0005 }, { 0x2141, 0x0005 }, { 0x4142, 0x0005 } } }, + { 14850, { { 0x00a0, 0x000a }, { 0x20a1, 0x000a }, { 0x40a2, 0x000a } } }, + { 21600, { { 0x00a0, 0x000a }, { 0x2001, 0x000f }, { 0x4002, 0x000f } } }, + { ~0UL, { { 0x, 0x }, { 0x, 0x }, { 0x, 0x } } } +}; + +static const struct dw_hdmi_curr_ctrl ingenic_cur_ctr[] = { + /*pixelclk bpp8bpp10 bpp12 */ + { 5400, { 0x091c, 0x091c, 0x06dc } }, + { 5840, { 0x091c, 0x06dc, 0x06dc } }, + { 7200, { 0x06dc, 0x06dc, 0x091c } }, + { 7425, { 0x06dc, 0x0b5c, 0x091c } }, + { 11880, { 0x091c, 0x091c, 0x06dc } }, + { 21600, { 0x06dc, 0x0b5c, 0x091c } }, + { ~0UL, { 0x, 0x, 0x } }, +}; + +/* + * Resistance term 133Ohm Cfg + * PREEMP config 0.00 + * TX/CK level 10 + */ +static const struct dw_hdmi_phy_config ingenic_phy_config[] = { + /*pixelclk symbol term vlev */ + { 21600, 0x800d, 0x0005, 0x01ad}, + { ~0UL, 0x, 0x, 0x} +}; + +static enum drm_mode_status +ingenic_dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + if (mode->clock < 13500) + return MODE_CLOCK_LOW; + /* FIXME: Hardware is capable of 270MHz, but setup data is missing. */ + if (mode->clock > 216000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static struct dw_hdmi_plat_data ingenic_dw_hdmi_plat_data = { + .mpll_cfg = ingenic_mpll_cfg, + .cur_ctr= ingenic_cur_ctr, + .phy_config = ingenic_phy_config, + .mode_valid = ingenic_dw_hdmi_mode_valid, + .output_port= 1, +}; + +static const struct of_device_id ingenic_dw_hdmi_dt_ids[] = { + { .compatible = "ingenic,jz4780-dw-hdmi" }, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ingenic_dw_hdmi_dt_ids); + +static int ingenic_dw_hdmi_probe(struct platform_device *pdev) +{ + struct dw_hdmi *hdmi; + struct regulator *regulator; + int ret; + + hdmi = dw_hdmi_probe(pdev, &ingenic_dw_hdmi_plat_data); + if (IS_ERR(hdmi)) + return PTR_ERR(hdmi); + + platform_set_drvdata(pdev, hdmi); + + regulator = devm_regulator_get_optional(&pdev->dev, "hdmi-5v"); + + if (IS_ERR(regulator)) { + ret = PTR_ERR(regulator); + +
[PATCH v8 2/8] drm/ingenic: Add support for JZ4780 and HDMI output
From: Paul Boddie Add support for the LCD controller present on JZ4780 SoCs. This SoC uses 8-byte descriptors which extend the current 4-byte descriptors used for other Ingenic SoCs. Tested on MIPS Creator CI20 board. Signed-off-by: Paul Boddie Signed-off-by: Ezequiel Garcia Signed-off-by: H. Nikolaus Schaller --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 53 +++ drivers/gpu/drm/ingenic/ingenic-drm.h | 38 2 files changed, 91 insertions(+) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 0bb590c3910d9..34089bc6e0fcd 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -6,6 +6,7 @@ #include "ingenic-drm.h" +#include #include #include #include @@ -49,6 +50,11 @@ struct ingenic_dma_hwdesc { u32 addr; u32 id; u32 cmd; + /* extended hw descriptor for jz4780 */ + u32 offsize; + u32 pagewidth; + u32 cpos; + u32 dessize; } __aligned(16); struct ingenic_dma_hwdescs { @@ -60,6 +66,7 @@ struct jz_soc_info { bool needs_dev_clk; bool has_osd; bool map_noncoherent; + bool use_extended_hwdesc; unsigned int max_width, max_height; const u32 *formats_f0, *formats_f1; unsigned int num_formats_f0, num_formats_f1; @@ -446,6 +453,9 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, if (!crtc) return 0; + if (plane == &priv->f0) + return -EINVAL; + crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); if (WARN_ON(!crtc_state)) @@ -662,6 +672,33 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); hwdesc->next = dma_hwdesc_addr(priv, next_id); + if (priv->soc_info->use_extended_hwdesc) { + hwdesc->cmd |= JZ_LCD_CMD_FRM_ENABLE; + + /* Extended 8-byte descriptor */ + hwdesc->cpos = 0; + hwdesc->offsize = 0; + hwdesc->pagewidth = 0; + + switch (newstate->fb->format->format) { + case DRM_FORMAT_XRGB1555: + hwdesc->cpos |= JZ_LCD_CPOS_RGB555; + fallthrough; + case DRM_FORMAT_RGB565: + hwdesc->cpos |= JZ_LCD_CPOS_BPP_15_16; + break; + case DRM_FORMAT_XRGB: + hwdesc->cpos |= JZ_LCD_CPOS_BPP_18_24; + break; + } + hwdesc->cpos |= (JZ_LCD_CPOS_COEFFICIENT_1 << +JZ_LCD_CPOS_COEFFICIENT_OFFSET); + hwdesc->dessize = + (0xff << JZ_LCD_DESSIZE_ALPHA_OFFSET) | + FIELD_PREP(JZ_LCD_DESSIZE_HEIGHT_MASK, height - 1) | + FIELD_PREP(JZ_LCD_DESSIZE_WIDTH_MASK, width - 1); + } + if (drm_atomic_crtc_needs_modeset(crtc_state)) { fourcc = newstate->fb->format->format; @@ -693,6 +730,9 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE; } + if (priv->soc_info->use_extended_hwdesc) + cfg |= JZ_LCD_CFG_DESCRIPTOR_8; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; if (mode->flags & DRM_MODE_FLAG_NVSYNC) @@ -1468,10 +1508,23 @@ static const struct jz_soc_info jz4770_soc_info = { .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), }; +static const struct jz_soc_info jz4780_soc_info = { + .needs_dev_clk = true, + .has_osd = true, + .use_extended_hwdesc = true, + .max_width = 4096, + .max_height = 2048, + .formats_f1 = jz4770_formats_f1, + .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1), + .formats_f0 = jz4770_formats_f0, + .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), +}; + static const struct of_device_id ingenic_drm_of_match[] = { { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info }, { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info }, { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info }, + { .compatible = "ingenic,jz4780-lcd", .data = &jz4780_soc_info }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, ingenic_drm_of_match); diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.h b/drivers/gpu/drm/ingenic/ingenic-drm.h index 22654ac1dde1c..cb1d09b625881 100644
Re: [PATCH v5 3/7] drm: sun4i: dsi: Convert to bridge driver
Hi Maxime, On Mon, Nov 22, 2021 at 7:49 PM Jagan Teki wrote: > > Hi Maxime, > > On Mon, Nov 22, 2021 at 7:35 PM Maxime Ripard wrote: > > > > On Mon, Nov 22, 2021 at 07:18:13PM +0530, Jagan Teki wrote: > > > Hi Maxime, > > > > > > On Mon, Nov 22, 2021 at 3:37 PM Maxime Ripard wrote: > > > > > > > > On Mon, Nov 22, 2021 at 12:22:19PM +0530, Jagan Teki wrote: > > > > > Some display panels would come up with a non-DSI output, those > > > > > can have an option to connect the DSI host by means of interface > > > > > bridge converter. > > > > > > > > > > This DSI to non-DSI interface bridge converter would requires > > > > > DSI Host to handle drm bridge functionalities in order to DSI > > > > > Host to Interface bridge. > > > > > > > > In order to do this you would need to use the DRM bridge API... > > > > > > Sorry, which bridge API do you mean? > > > > Any variant of of_drm_find_bridge, and drm_bridge_attach. Just like > > we're doing in sun4i_rgb.c > > Yes, we have drm_bridge_attach in bind and bridge_function.attach > calls in this patch and of_drm_find_bridge in sun6i_mipi_dsi_attach. > Not sure which API's I've missed. > > > > > > > > This patch convert the existing to a drm bridge driver with a > > > > > built-in encoder support for compatibility with existing > > > > > component drivers. > > > > > > > > ... but changing the encoder driver to a bridge is completely > > > > unnecessary to do so. Why did you need to make that change? > > > > > > Idea of this series is to convert the driver to bridge and use the > > > latest bridge function from the v1 series. > > > > Ok, but it's not at all what you mention in your commit log? You don't > > need any of that in order to support a bridge downstream. > > I've mentioned "Converting to bridge driver" and thought it has > meaning of converting encoder related function to bridge functions as > well. Not think about specific description to describe on commit > message. Will update this. > > > > > > > > > > > > Signed-off-by: Jagan Teki > > > > > > > > > > --- > > > > > Changes for v5: > > > > > - add atomic APIs > > > > > - find host and device variant DSI devices. > > > > > Changes for v4, v3: > > > > > - none > > > > > > > > > > drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 112 > > > > > - > > > > > drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 7 ++ > > > > > 2 files changed, 96 insertions(+), 23 deletions(-) > > > > > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > > > > > index 43d9c9e5198d..a6a272b55f77 100644 > > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > > > > > @@ -21,6 +21,7 @@ > > > > > > > > > > #include > > > > > #include > > > > > +#include > > > > > #include > > > > > #include > > > > > #include > > > > > @@ -713,10 +714,11 @@ static int sun6i_dsi_start(struct sun6i_dsi > > > > > *dsi, > > > > > return 0; > > > > > } > > > > > > > > > > -static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder) > > > > > +static void sun6i_dsi_bridge_atomic_enable(struct drm_bridge *bridge, > > > > > +struct drm_bridge_state > > > > > *old_bridge_state) > > > > > { > > > > > - struct drm_display_mode *mode = > > > > > &encoder->crtc->state->adjusted_mode; > > > > > - struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder); > > > > > + struct sun6i_dsi *dsi = bridge_to_sun6i_dsi(bridge); > > > > > + struct drm_display_mode *mode = > > > > > &bridge->encoder->crtc->state->adjusted_mode; > > > > > struct mipi_dsi_device *device = dsi->device; > > > > > union phy_configure_opts opts = { }; > > > > > struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy; > > > > > @@ -772,6 +774,9 @@ static void sun6i_dsi_encoder_enable(struct > > > > > drm_encoder *encoder) > > > > > if (dsi->panel) > > > > > drm_panel_prepare(dsi->panel); > > > > > > > > > > + if (dsi->next_bridge) > > > > > + > > > > > dsi->next_bridge->funcs->atomic_pre_enable(dsi->next_bridge, > > > > > old_bridge_state); > > > > > + > > > > > > > > Please use the proper helpers. > > > > > > If we use bridge_functions we need to take atomic functions as > > > precedence as the next bridge functions might convert atomic calls. > > > > We've had this discussion over and over again, but this is something > > that needs to be documented and / or in your commit log. > > > > You must not deviate from the standard (and expected) behavior without > > any kind of justification. > > Not exactly sure about what you mean, sorry. All these atomic bridge > functions are already documented if I'm not wrong and Laurent have > patches to switch the normal functions to atomic. Not sure what else > need to document here and need justification for it if the driver is > converting to bridge. > > > > > > > > > > > > /* > > > > >
[PATCH v2] drm: change logs to print connectors in the form [CONNECTOR:id:name]
The preferred way to log connectors is [CONNECTOR:id:name]. Change it in drm core programs. Also replace obsolete log calls (like DRM_DEBUG_*) to the new ones (like drm_dbg_*) Suggested-by: Ville Syrjälä Signed-off-by: Claudio Suarez --- drivers/gpu/drm/drm_client_modeset.c | 66 +--- drivers/gpu/drm/drm_connector.c | 24 +- drivers/gpu/drm/drm_edid.c | 45 +++ drivers/gpu/drm/drm_edid_load.c | 21 + drivers/gpu/drm/drm_mode_config.c| 3 +- 5 files changed, 95 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index ced09c7c06f9..8df53b6e7687 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -240,8 +240,9 @@ static void drm_client_connectors_enabled(struct drm_connector **connectors, for (i = 0; i < connector_count; i++) { connector = connectors[i]; enabled[i] = drm_connector_enabled(connector, true); - DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, - connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no"); + drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] enabled? %s\n", + connector->base.id, connector->name, + connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no"); any_enabled |= enabled[i]; } @@ -350,8 +351,9 @@ static int drm_client_get_tile_offsets(struct drm_connector **connectors, continue; if (!modes[i] && (h_idx || v_idx)) { - DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i, - connector->base.id); + drm_dbg_kms(connector->dev, + "[CONNECTOR:%d:%s]: no modes tiled %d\n", + connector->base.id, connector->name, i); continue; } if (connector->tile_h_loc < h_idx) @@ -419,14 +421,17 @@ static bool drm_client_target_preferred(struct drm_connector **connectors, drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i, connector->tile_h_loc, connector->tile_v_loc); } - DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", - connector->base.id); + drm_dbg_kms(connector->dev, + "[CONNECTOR:%d:%s]: looking for cmdline mode\n", + connector->base.id, connector->name); /* got for command line mode first */ modes[i] = drm_connector_pick_cmdline_mode(connector); if (!modes[i]) { - DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", - connector->base.id, connector->tile_group ? connector->tile_group->id : 0); + drm_dbg_kms(connector->dev, + "[CONNECTOR:%d:%s]: looking for preferred mode %d\n", + connector->base.id, connector->name, + connector->tile_group ? connector->tile_group->id : 0); modes[i] = drm_connector_has_preferred_mode(connector, width, height); } /* No preferred modes, pick one off the list */ @@ -448,8 +453,8 @@ static bool drm_client_target_preferred(struct drm_connector **connectors, (connector->tile_h_loc == 0 && connector->tile_v_loc == 0 && !drm_connector_get_tiled_mode(connector))) { - DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", - connector->base.id); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]: falling back to non tiled mode\n", + connector->base.id, connector->name); modes[i] = drm_connector_fallback_non_tiled_mode(connector); } else { modes[i] = drm_connector_get_tiled_mode(connector); @@ -617,15 +622,17 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, num_connectors_detected++; if (!enabled[i]) { - DRM_DEBUG_KMS("connector %s not enabled, skipping\n", - connector->name); + drm_dbg_kms(connector->dev, + "[CONNECTOR:%d:%s] not enabled, skipping\n", +
Re: [PATCH v2] drm/virtio: Fix an NULL vs IS_ERR() bug in virtio_gpu_object_shmem_init()
On Thu, Nov 18, 2021 at 3:16 AM Dan Carpenter wrote: > > The drm_gem_shmem_get_sg_table() function never returns NULL. It returns > error pointers on error. > > Fixes: c66df701e783 ("drm/virtio: switch from ttm to gem shmem helpers") > Signed-off-by: Dan Carpenter > --- > v2: I originally sent this patch on 19 Jun 2020 but it was somehow > not applied. As I review it now, I see that the bug is actually > older than I originally thought and so I have updated the Fixes > tag. Reviewed-by: Chia-I Wu
Re: [PATCH] drm/nouveau/acr: fix a couple NULL vs IS_ERR() checks
Reviewed-by: Lyude Paul Will push this to drm-misc in a bit On Thu, 2021-11-18 at 14:13 +0300, Dan Carpenter wrote: > The nvkm_acr_lsfw_add() function never returns NULL. It returns error > pointers on error. > > Fixes: 22dcda45a3d1 ("drm/nouveau/acr: implement new subdev to replace > "secure boot"") > Signed-off-by: Dan Carpenter > --- > drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c | 6 -- > drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c | 6 -- > 2 files changed, 8 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c > b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c > index cdb1ead26d84..82b4c8e1457c 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c > @@ -207,11 +207,13 @@ int > gm200_acr_wpr_parse(struct nvkm_acr *acr) > { > const struct wpr_header *hdr = (void *)acr->wpr_fw->data; > + struct nvkm_acr_lsfw *lsfw; > > while (hdr->falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID) { > wpr_header_dump(&acr->subdev, hdr); > - if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id)) > - return -ENOMEM; > + lsfw = nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)- > >falcon_id); > + if (IS_ERR(lsfw)) > + return PTR_ERR(lsfw); > } > > return 0; > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c > b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c > index fb9132a39bb1..fd97a935a380 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c > @@ -161,11 +161,13 @@ int > gp102_acr_wpr_parse(struct nvkm_acr *acr) > { > const struct wpr_header_v1 *hdr = (void *)acr->wpr_fw->data; > + struct nvkm_acr_lsfw *lsfw; > > while (hdr->falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID) { > wpr_header_v1_dump(&acr->subdev, hdr); > - if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id)) > - return -ENOMEM; > + lsfw = nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)- > >falcon_id); > + if (IS_ERR(lsfw)) > + return PTR_ERR(lsfw); > } > > return 0; -- Cheers, Lyude Paul (she/her) Software Engineer at Red Hat
Re: [PATCH v3 1/5] drm/i915/panelreplay: dpcd register definition for panelreplay
On Sun, 2021-10-10 at 17:40 +0530, Animesh Manna wrote: > DPCD register definition added to check and enable panel replay > capability of the sink. > > Signed-off-by: Animesh Manna > --- > include/drm/drm_dp_helper.h | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h > index b52df4db3e8f..8a2b929c3f88 100644 > --- a/include/drm/drm_dp_helper.h > +++ b/include/drm/drm_dp_helper.h > @@ -541,6 +541,9 @@ struct drm_panel; > /* DFP Capability Extension */ > #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0a3 /* 2.0 */ > > +#define DP_PANEL_REPLAY_CAP 0x0b0 > +# define PANEL_REPLAY_SUPPORT (1 << 0) Missing bit 1, that is very important when panel do not support selective update panel replay needs to act like PSR1 when it is sets it needs to act like PSR2. > + > /* Link Configuration */ > #define DP_LINK_BW_SET 0x100 > # define DP_LINK_RATE_TABLE 0x00/* eDP 1.4 */ > @@ -709,6 +712,9 @@ struct drm_panel; > #define DP_BRANCH_DEVICE_CTRL0x1a1 > # define DP_BRANCH_DEVICE_IRQ_HPD(1 << 0) > > +#define PANEL_REPLAY_CONFIG 0x1b0 > +# define PANEL_REPLAY_ENABLE(1 << 0) All other bits are also important, for the errors ones we have PSR counter parts and your are missing the error status register. > + > #define DP_PAYLOAD_ALLOCATE_SET 0x1c0 > #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1 > #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2
Re: [PATCH v3 3/5] drm/i915/panelreplay: Initializaton and compute config for panel replay
On Sun, 2021-10-10 at 17:40 +0530, Animesh Manna wrote: > As panel replay feature similar to PSR feature of EDP panel, so currently > utilized existing psr framework for panel replay. > > v1: RFC version. > v2: optimized code, pr_enabled and pr_dpcd variable removed. [Jose] > v3: > - code comments improved. [Jani] > - dpcd_readb used instead of dpcd_read. [Jani] > - panel-repaplay init/compute functions moved inside respective psr > function. [Jani] > > Signed-off-by: Animesh Manna > --- > .../drm/i915/display/intel_display_types.h| 2 + > drivers/gpu/drm/i915/display/intel_dp.c | 43 + > drivers/gpu/drm/i915/display/intel_psr.c | 48 +++ > drivers/gpu/drm/i915/display/intel_psr.h | 3 ++ > 4 files changed, 87 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h > b/drivers/gpu/drm/i915/display/intel_display_types.h > index 39e11eaec1a3..48f7d676ed2c 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_types.h > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h > @@ -1070,6 +1070,7 @@ struct intel_crtc_state { > bool req_psr2_sdp_prior_scanline; > u32 dc3co_exitline; > u16 su_y_granularity; > + bool has_panel_replay; We can drop this and reuse current ones ones, see bellow. > struct drm_dp_vsc_sdp psr_vsc; > > /* > @@ -1531,6 +1532,7 @@ struct intel_psr { > bool irq_aux_error; > u16 su_w_granularity; > u16 su_y_granularity; > + bool sink_panel_replay_support; move this closer to has_psr and set both when it is panel replay. otherwise psr functions will not be executed for panel replay, see CAN_PSR(). > u32 dc3co_exitline; > u32 dc3co_exit_delay; > struct delayed_work dc3co_work; > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c > b/drivers/gpu/drm/i915/display/intel_dp.c > index 10fda20a5bd8..f58a7b72be14 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp.c > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > @@ -1587,12 +1587,22 @@ static void intel_dp_compute_vsc_colorimetry(const > struct intel_crtc_state *crtc > struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); > struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > > - /* > - * Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118 > - * VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/ > - * Colorimetry Format indication. > - */ > - vsc->revision = 0x5; > + if (crtc_state->has_panel_replay) { > + /* > + * Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223 > + * VSC SDP supporting 3D stereo, Panel Replay, and Pixel > + * Encoding/Colorimetry Format indication. > + */ > + vsc->revision = 0x7; > + } else { > + /* > + * Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118 > + * VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/ > + * Colorimetry Format indication. > + */ > + vsc->revision = 0x5; > + } > + > vsc->length = 0x13; > > /* DP 1.4a spec, Table 2-120 */ > @@ -1701,6 +1711,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp > *intel_dp, > vsc->revision = 0x4; > vsc->length = 0xe; > } > + } else if (intel_dp->psr.enabled && !intel_dp_is_edp(intel_dp)) { > + if (intel_dp->psr.colorimetry_support && > + intel_dp_needs_vsc_sdp(crtc_state, conn_state)) { > + /* [Panel Replay with colorimetry info] */ > + intel_dp_compute_vsc_colorimetry(crtc_state, conn_state, > + vsc); > + } else { > + /* > + * [Panel Replay without colorimetry info] > + * Prepare VSC Header for SU as per DP 2.0 spec, Table > 2-223 > + * VSC SDP supporting 3D stereo + Panel Replay. > + */ > + vsc->revision = 0x6; > + vsc->length = 0x10; > + } > } else { > /* >* [PSR1] > @@ -2749,10 +2774,10 @@ static ssize_t intel_dp_vsc_sdp_pack(const struct > drm_dp_vsc_sdp *vsc, > sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */ > > /* > - * Only revision 0x5 supports Pixel Encoding/Colorimetry Format as > - * per DP 1.4a spec. > + * Revision 0x5 and 0x7 supports Pixel Encoding/Colorimetry Format as > + * per DP 1.4a spec and DP 2.0 spec respectively. >*/ > - if (vsc->revision != 0x5) > + if (vsc->revision != 0x5 || vsc->revision != 0x7) > goto out; > > /* VSC SDP Payload for DB16 through DB18 */ > diff --git a/drivers/gpu/drm/i915/display/intel_psr.c > b/dr
Re: [Intel-gfx] [PATCH 1/3] drm/i915/gt: Spread virtual engines over idle engines
On Tue, Nov 23, 2021 at 09:39:25AM +, Tvrtko Ursulin wrote: > > On 17/11/2021 22:49, Vinay Belgaumkar wrote: > > From: Chris Wilson > > > > Everytime we come to the end of a virtual engine's context, re-randomise > > it's siblings[]. As we schedule the siblings' tasklets in the order they > > are in the array, earlier entries are executed first (when idle) and so > > will be preferred when scheduling the next virtual request. Currently, > > we only update the array when switching onto a new idle engine, so we > > prefer to stick on the last execute engine, keeping the work compact. > > However, it can be beneficial to spread the work out across idle > > engines, so choose another sibling as our preferred target at the end of > > the context's execution. > > This partially brings back, from a different angle, the more dynamic > scheduling behavior which has been lost since bugfix 90a987205c6c > ("drm/i915/gt: Only swap to a random sibling once upon creation"). Shouldn't we use the Fixes tag here since this is targeting to fix one of the performance regressions of this patch? > > One day we could experiment with using engine busyness as criteria (instead > of random). Back in the day busyness was kind of the best strategy, although > sampled at submit, not at the trailing edge like here, but it still may be > able to settle down to engine configuration better in some scenarios. Only > testing could say. > > Still, from memory random also wasn't that bad so this should be okay for > now. > > Reviewed-by: Tvrtko Ursulin Since you reviewed and it looks to be a middle ground point in terms of when to balancing (always like in the initial implementation vs only once like the in 90a987205c6c). If this one is really fixing the regression by itself: Acked-by: Rodrigo Vivi on this patch here. But I still don't want to take the risk with touching the freq with race to idle, until not convinced that it is absolutely needed and that we are not breaking the world out there. > > Regards, > > Tvrtko > > > Signed-off-by: Chris Wilson > > Cc: Vinay Belgaumkar > > Cc: Tvrtko Ursulin > > --- > > .../drm/i915/gt/intel_execlists_submission.c | 80 --- > > 1 file changed, 52 insertions(+), 28 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > > b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > > index ca03880fa7e4..b95bbc8fb91a 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > > +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > > @@ -539,6 +539,41 @@ static void execlists_schedule_in(struct i915_request > > *rq, int idx) > > GEM_BUG_ON(intel_context_inflight(ce) != rq->engine); > > } > > +static void virtual_xfer_context(struct virtual_engine *ve, > > +struct intel_engine_cs *engine) > > +{ > > + unsigned int n; > > + > > + if (likely(engine == ve->siblings[0])) > > + return; > > + > > + if (!intel_engine_has_relative_mmio(engine)) > > + lrc_update_offsets(&ve->context, engine); > > + > > + /* > > +* Move the bound engine to the top of the list for > > +* future execution. We then kick this tasklet first > > +* before checking others, so that we preferentially > > +* reuse this set of bound registers. > > +*/ > > + for (n = 1; n < ve->num_siblings; n++) { > > + if (ve->siblings[n] == engine) { > > + swap(ve->siblings[n], ve->siblings[0]); > > + break; > > + } > > + } > > +} > > + > > +static int ve_random_sibling(struct virtual_engine *ve) > > +{ > > + return prandom_u32_max(ve->num_siblings); > > +} > > + > > +static int ve_random_other_sibling(struct virtual_engine *ve) > > +{ > > + return 1 + prandom_u32_max(ve->num_siblings - 1); > > +} > > + > > static void > > resubmit_virtual_request(struct i915_request *rq, struct virtual_engine > > *ve) > > { > > @@ -578,8 +613,23 @@ static void kick_siblings(struct i915_request *rq, > > struct intel_context *ce) > > rq->execution_mask != engine->mask) > > resubmit_virtual_request(rq, ve); > > - if (READ_ONCE(ve->request)) > > + /* > > +* Reschedule with a new "preferred" sibling. > > +* > > +* The tasklets are executed in the order of ve->siblings[], so > > +* siblings[0] receives preferrential treatment of greedily checking > > +* for execution of the virtual engine. At this point, the virtual > > +* engine is no longer in the current GPU cache due to idleness or > > +* contention, so it can be executed on any without penalty. We > > +* re-randomise at this point in order to spread light loads across > > +* the system, heavy overlapping loads will continue to be greedily > > +* executed by the first available engine. > > +*/ > > + if (READ_ONCE(ve->request)) { > > + virtual_xfer_context(ve, > > +ve->s
Re: [PATCH v8 4/8] drm/ingenic: Add dw-hdmi driver for jz4780
Hi Nikolaus, I keep seeing a few things, sorry. Le mar., nov. 23 2021 at 19:13:57 +0100, H. Nikolaus Schaller a écrit : From: Paul Boddie A specialisation of the generic Synopsys HDMI driver is employed for JZ4780 HDMI support. This requires a new driver, plus device tree and configuration modifications. Here we add Kconfig DRM_INGENIC_DW_HDMI, Makefile and driver code. Signed-off-by: Paul Boddie Signed-off-by: Ezequiel Garcia Signed-off-by: H. Nikolaus Schaller --- drivers/gpu/drm/ingenic/Kconfig | 9 ++ drivers/gpu/drm/ingenic/Makefile | 1 + drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c | 129 ++ 3 files changed, 139 insertions(+) create mode 100644 drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig index 3b57f8be007c4..4efc709d77b0a 100644 --- a/drivers/gpu/drm/ingenic/Kconfig +++ b/drivers/gpu/drm/ingenic/Kconfig @@ -25,4 +25,13 @@ config DRM_INGENIC_IPU The Image Processing Unit (IPU) will appear as a second primary plane. +config DRM_INGENIC_DW_HDMI + tristate "Ingenic specific support for Synopsys DW HDMI" + depends on MACH_JZ4780 + select DRM_DW_HDMI + help + Choose this option to enable Synopsys DesignWare HDMI based driver. + If you want to enable HDMI on Ingenic JZ4780 based SoC, you should + select this option.. + endif diff --git a/drivers/gpu/drm/ingenic/Makefile b/drivers/gpu/drm/ingenic/Makefile index d313326bdddbb..f10cc1c5a5f22 100644 --- a/drivers/gpu/drm/ingenic/Makefile +++ b/drivers/gpu/drm/ingenic/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_DRM_INGENIC) += ingenic-drm.o ingenic-drm-y = ingenic-drm-drv.o ingenic-drm-$(CONFIG_DRM_INGENIC_IPU) += ingenic-ipu.o +obj-$(CONFIG_DRM_INGENIC_DW_HDMI) += ingenic-dw-hdmi.o diff --git a/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c b/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c new file mode 100644 index 0..c14890d6b9826 --- /dev/null +++ b/drivers/gpu/drm/ingenic/ingenic-dw-hdmi.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2011-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2019, 2020 Paul Boddie + * + * Derived from dw_hdmi-imx.c with i.MX portions removed. + * Probe and remove operations derived from rcar_dw_hdmi.c. + */ + +#include +#include +#include + +#include +#include +#include + +static const struct dw_hdmi_mpll_config ingenic_mpll_cfg[] = { + { 4525, { { 0x01e0, 0x }, { 0x21e1, 0x }, { 0x41e2, 0x } } }, + { 9250, { { 0x0140, 0x0005 }, { 0x2141, 0x0005 }, { 0x4142, 0x0005 } } }, + { 14850, { { 0x00a0, 0x000a }, { 0x20a1, 0x000a }, { 0x40a2, 0x000a } } }, + { 21600, { { 0x00a0, 0x000a }, { 0x2001, 0x000f }, { 0x4002, 0x000f } } }, + { ~0UL, { { 0x, 0x }, { 0x, 0x }, { 0x, 0x } } } +}; + +static const struct dw_hdmi_curr_ctrl ingenic_cur_ctr[] = { + /*pixelclk bpp8bpp10 bpp12 */ + { 5400, { 0x091c, 0x091c, 0x06dc } }, + { 5840, { 0x091c, 0x06dc, 0x06dc } }, + { 7200, { 0x06dc, 0x06dc, 0x091c } }, + { 7425, { 0x06dc, 0x0b5c, 0x091c } }, + { 11880, { 0x091c, 0x091c, 0x06dc } }, + { 21600, { 0x06dc, 0x0b5c, 0x091c } }, + { ~0UL, { 0x, 0x, 0x } }, +}; + +/* + * Resistance term 133Ohm Cfg + * PREEMP config 0.00 + * TX/CK level 10 + */ +static const struct dw_hdmi_phy_config ingenic_phy_config[] = { + /*pixelclk symbol term vlev */ + { 21600, 0x800d, 0x0005, 0x01ad}, + { ~0UL, 0x, 0x, 0x} +}; + +static enum drm_mode_status +ingenic_dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + if (mode->clock < 13500) + return MODE_CLOCK_LOW; + /* FIXME: Hardware is capable of 270MHz, but setup data is missing. */ + if (mode->clock > 216000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static struct dw_hdmi_plat_data ingenic_dw_hdmi_plat_data = { + .mpll_cfg = ingenic_mpll_cfg, + .cur_ctr= ingenic_cur_ctr, + .phy_config = ingenic_phy_config, + .mode_valid = ingenic_dw_hdmi_mode_valid, + .output_port= 1, +}; + +static const struct of_device_id ingenic_dw_hdmi_dt_ids[] = { + { .compatible = "ingenic,jz4780-dw-hdmi" }, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ingenic_dw_hdmi_dt_ids); + +static int ingenic_dw_hdmi_probe(struct platform_device *pdev) +{ + struct dw_hdmi *hdmi; + struct regulator *regulator; + int ret; + + hdmi = dw_hdmi_probe(pdev, &ingenic_dw_hdmi_plat_data); + if (IS_ERR(hdmi)) + return PTR_ERR(hdmi); + + platform_set_drvdata(pdev, hdmi); + + regulator = devm_regulator_get_optional(&pdev->dev, "hdmi-5v
Re: [PATCH v8 6/8] MIPS: DTS: CI20: Add DT nodes for HDMI setup
Hi Nikolaus, Le mar., nov. 23 2021 at 19:13:59 +0100, H. Nikolaus Schaller a écrit : From: Paul Boddie We need to hook up * HDMI connector * HDMI power regulator * JZ4780_CLK_HDMI @ 27 MHz * DDC pinmux * HDMI and LCDC endpoint connections Signed-off-by: Paul Boddie Signed-off-by: H. Nikolaus Schaller --- arch/mips/boot/dts/ingenic/ci20.dts | 83 +++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts index b249a4f0f6b62..15cf03670693f 100644 --- a/arch/mips/boot/dts/ingenic/ci20.dts +++ b/arch/mips/boot/dts/ingenic/ci20.dts @@ -78,6 +78,18 @@ eth0_power: fixedregulator@0 { enable-active-high; }; + hdmi_out: connector { + compatible = "hdmi-connector"; + label = "HDMI OUT"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&dw_hdmi_out>; + }; + }; + }; + ir: ir { compatible = "gpio-ir-receiver"; gpios = <&gpe 3 GPIO_ACTIVE_LOW>; @@ -102,6 +114,17 @@ otg_power: fixedregulator@2 { gpio = <&gpf 14 GPIO_ACTIVE_LOW>; enable-active-high; }; + + hdmi_power: fixedregulator@3 { + compatible = "regulator-fixed"; + + regulator-name = "hdmi_power"; + regulator-min-microvolt = <500>; + regulator-max-microvolt = <500>; + + gpio = <&gpa 25 0>; + enable-active-high; + }; }; &ext { @@ -114,11 +137,13 @@ &cgu { * precision. */ assigned-clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_RTC>, - <&cgu JZ4780_CLK_SSIPLL>, <&cgu JZ4780_CLK_SSI>; + <&cgu JZ4780_CLK_SSIPLL>, <&cgu JZ4780_CLK_SSI>, + <&cgu JZ4780_CLK_HDMI>; assigned-clock-parents = <0>, <&cgu JZ4780_CLK_RTCLK>, <&cgu JZ4780_CLK_MPLL>, -<&cgu JZ4780_CLK_SSIPLL>; - assigned-clock-rates = <4800>, <0>, <5400>; +<&cgu JZ4780_CLK_SSIPLL>, +<0>; Nit - you can remove the last <0>, it will be the default. + assigned-clock-rates = <4800>, <0>, <5400>, <0>, <2700>; }; &tcu { @@ -509,6 +534,19 @@ pins_i2c4: i2c4 { bias-disable; }; + pins_hdmi_ddc: hdmi_ddc { + function = "hdmi-ddc"; + groups = "hdmi-ddc"; + bias-disable; + }; + + /* switch to PF25 as gpio driving DDC_SDA low */ + pins_hdmi_ddc_unwedge: hdmi_ddc { + function = "hdmi-ddc"; + groups = "hdmi-ddc"; + bias-disable; + }; Your pins_hdmi_ddc and pins_hdmi_ddc_unwedge are the exact same? You could just use the former and pass it to both pinctrl-0 and pinctrl-1. Cheers, -Paul + pins_nemc: nemc { function = "nemc"; groups = "nemc-data", "nemc-cle-ale", "nemc-rd-we", "nemc-frd-fwe"; @@ -539,3 +577,42 @@ pins_mmc1: mmc1 { bias-disable; }; }; + +&hdmi { + status = "okay"; + + pinctrl-names = "default", "unwedge"; + pinctrl-0 = <&pins_hdmi_ddc>; + pinctrl-1 = <&pins_hdmi_ddc_unwedge>; + + hdmi-5v-supply = <&hdmi_power>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dw_hdmi_in: endpoint { + remote-endpoint = <&lcd_out>; + }; + }; + + port@1 { + reg = <1>; + dw_hdmi_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; +}; + +&lcdc0 { + status = "okay"; + + port { + lcd_out: endpoint { + remote-endpoint = <&dw_hdmi_in>; + }; + }; +}; -- 2.33.0
Re: [PATCH v8 0/8] MIPS: JZ4780 and CI20 HDMI
Hi Nikolaus, I think if you can fix the last few things I commented on, and I get an ACK from Rob for the Device Tree related patches, then it will be ready to merge. Cheers, -Paul Le mar., nov. 23 2021 at 19:13:53 +0100, H. Nikolaus Schaller a écrit : PATCH V8 2021-11-23 19:14:00: - fix a bad editing result from patch 2/8 (found by p...@crapouillou.net) PATCH V7 2021-11-23 18:46:23: - changed gpio polarity of hdmi_power to 0 (suggested by p...@crapouillou.net) - fixed LCD1 irq number (bug found by p...@crapouillou.net) - removed "- 4" for calculating max_register (suggested by p...@crapouillou.net) - use unevaluatedPropertes instead of additionalProperties (suggested by r...@kernel.org) - moved and renamed ingenic,jz4780-hdmi.yaml (suggested by r...@kernel.org) - adjusted assigned-clocks changes to upstream which added some for SSI (by h...@goldelico.com) - rebased and tested with v5.16-rc2 + patch set drm/ingenic by p...@crapouillou.net (by h...@goldelico.com) PATCH V6 2021-11-10 20:43:33: - changed CONFIG_DRM_INGENIC_DW_HDMI to "m" (by h...@goldelico.com) - made ingenic-dw-hdmi an independent platform driver which can be compiled as module and removed error patch fixes for IPU (suggested by p...@crapouillou.net) - moved assigned-clocks from jz4780.dtsi to ci20.dts (suggested by p...@crapouillou.net) - fixed reg property in jz4780.dtsi to cover all registers incl. gamma and vee (by h...@goldelico.com) - added a base patch to calculate regmap size from DTS reg property (requested by p...@crapouillou.net) - restored resetting all bits except one in LCDOSDC (requested by p...@crapouillou.net) - clarified setting of cpos (suggested by p...@crapouillou.net) - moved bindings definition for ddc-i2c-bus (suggested by p...@crapouillou.net) - simplified mask definitions for JZ_LCD_DESSIZE (requested by p...@crapouillou.net) - removed setting alpha premultiplication (suggested by p...@crapouillou.net) - removed some comments (suggested by p...@crapouillou.net) PATCH V5 2021-10-05 14:28:44: - dropped mode_fixup and timings support in dw-hdmi as it is no longer needed in this V5 (by h...@goldelico.com) - dropped "drm/ingenic: add some jz4780 specific features" (stimulated by p...@crapouillou.net) - fixed typo in commit subject: "synopsis" -> "synopsys" (by h...@goldelico.com) - swapped clocks in jz4780.dtsi to match synopsys,dw-hdmi.yaml (by h...@goldelico.com) - improved, simplified, fixed, dtbschecked ingenic-jz4780-hdmi.yaml and made dependent of bridge/synopsys,dw-hdmi.yaml (based on suggestions by max...@cerno.tech) - fixed binding vs. driver&DTS use of hdmi-5v regulator (suggested by max...@cerno.tech) - dropped "drm/bridge: synopsis: Fix to properly handle HPD" - was a no longer needed workaround for a previous version (suggested by max...@cerno.tech) PATCH V4 2021-09-27 18:44:38: - fix setting output_port = 1 (issue found by p...@crapouillou.net) - ci20.dts: convert to use hdmi-connector (by h...@goldelico.com) - add a hdmi-regulator to control +5V power (by h...@goldelico.com) - added a fix to dw-hdmi to call drm_kms_helper_hotplug_event on plugin event detection (by h...@goldelico.com) - always allocate extended descriptor but initialize only for jz4780 (by h...@goldelico.com) - updated to work on top of "[PATCH v3 0/6] drm/ingenic: Various improvements v3" (by p...@crapouillou.net) - rebased to v5.13-rc3 PATCH V3 2021-08-08 07:10:50: This series adds HDMI support for JZ4780 and CI20 board (and fixes one IPU related issue in registration error path) - [patch 1/8] switched from mode_fixup to atomic_check (suggested by robert.f...@linaro.org) - the call to the dw-hdmi specialization is still called mode_fixup - [patch 3/8] diverse fixes for ingenic-drm-drv (suggested by p...@crapouillou.net) - factor out some non-HDMI features of the jz4780 into a separate patch - multiple fixes around max height - do not change regmap config but a copy on stack - define some constants - factor out fixing of drm_init error path for IPU into separate patch - use FIELD_PREP() - [patch 8/8] conversion to component framework dropped (suggested by laurent.pinch...@ideasonboard.com and p...@crapouillou.net) PATCH V2 2021-08-05 16:08:05: - code and commit messages revisited for checkpatch warnings - rebased on v5.14-rc4 - include (failed, hence RFC 8/8) attempt to convert to component framework (was suggested by Paul Cercueil a while ago) This series adds HDMI support for JZ4780 and CI20 board H. Nikolaus Schaller (3): drm/ingenic: prepare ingenic drm for later addition of JZ4780 MIPS: defconfig: CI20: configure for DRM_DW_HDMI_JZ4780 [RFC] MIPS: DTS: Ingenic: adjust register size to available registers Paul Boddie (4): drm/ingenic: Add support for JZ4780 and HDMI output drm/ingenic: Add dw-hdmi driver for jz4780 MIPS: DTS: jz4780: Account for Synopsys HDMI driver and LCD controllers MIPS: DTS: CI20: Add DT nodes for HDMI set
Re: [WARN][AMDGPU] Linux 5.15.4 with AMD Bonaire GPU
On Sun, Nov 21, 2021 at 9:47 AM Chris Rankin wrote: > > Hi, > > i have found this warning in my vanilla 5.15.4 kernel's dmesg log: > > [ 87.687139] [ cut here ] > [ 87.710799] WARNING: CPU: 1 PID: 1 at > drivers/gpu/drm/ttm/ttm_bo.c:409 ttm_bo_release+0x1c/0x266 [ttm] > [ 87.718965] Modules linked in: nf_nat_ftp nf_conntrack_ftp cfg80211 > af_packet nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib > nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct > nft_chain_nat nf_tables ebtable_nat ebtable_broute ip6table_nat > ip6table_mangle ip6table_raw ip6table_security iptable_nat nf_nat > nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c iptable_mangle > iptable_raw iptable_security nfnetlink ebtable_filter ebtables > ip6table_filter ip6_tables iptable_filter bnep it87 hwmon_vid dm_mod > dax snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio > snd_hda_codec_hdmi snd_hda_intel uvcvideo videobuf2_vmalloc > videobuf2_memops snd_intel_dspcfg snd_hda_codec snd_usb_audio > snd_usbmidi_lib snd_hwdep videobuf2_v4l2 snd_virtuoso snd_oxygen_lib > videobuf2_common btusb snd_mpu401_uart input_leds snd_hda_core > videodev btbcm snd_rawmidi btintel joydev snd_seq mc led_class > bluetooth ecdh_generic rfkill snd_seq_device ecc snd_pcm r8169 > coretemp snd_hrtimer i2c_i801 psmouse > [ 87.719024] i2c_smbus pcspkr kvm_intel realtek kvm snd_timer > gpio_ich mdio_devres iTCO_wdt snd libphy mxm_wmi irqbypass soundcore > tiny_power_button lpc_ich i7core_edac acpi_cpufreq button wmi nfsd > auth_rpcgss nfs_acl lockd grace sunrpc binfmt_misc fuse configfs zram > zsmalloc ip_tables x_tables ext4 crc32c_generic crc16 mbcache jbd2 > hid_microsoft usbhid sr_mod cdrom sd_mod amdgpu uhci_hcd > drm_ttm_helper ehci_pci ttm mfd_core ehci_hcd gpu_sched xhci_pci > xhci_hcd i2c_algo_bit crc32c_intel serio_raw drm_kms_helper > firewire_ohci ahci libahci pata_jmicron firewire_core libata crc_itu_t > cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops > cfbcopyarea cec rc_core scsi_mod usbcore drm bsg scsi_common > usb_common drm_panel_orientation_quirks ipmi_devintf ipmi_msghandler > msr sha256_ssse3 sha256_generic ipv6 crc_ccitt > [ 87.876267] CPU: 1 PID: 1 Comm: systemd Tainted: G I 5.15.4 > #1 > [ 87.882109] Hardware name: Gigabyte Technology Co., Ltd. > EX58-UD3R/EX58-UD3R, BIOS FB 05/04/2009 > [ 87.889800] RIP: 0010:ttm_bo_release+0x1c/0x266 [ttm] > [ 87.893615] Code: 44 89 e0 5b 5d 41 5c 41 5d 41 5e 41 5f c3 41 56 > 41 55 41 54 4c 8d a7 90 fe ff ff 55 53 83 7f 4c 00 48 89 fb 48 8b 6f > e8 74 02 <0f> 0b 80 7b 18 00 48 8b 43 88 0f 85 ac 00 00 00 4c 8d 6b 90 > 49 39 > [ 87.911829] RSP: 0018:c9023e00 EFLAGS: 00010202 > [ 87.915886] RAX: 0001 RBX: 888123a449c8 RCX: > 004c > [ 87.921825] RDX: 01f3 RSI: a02ee0e5 RDI: > 888123a449c8 > [ 87.927750] RBP: 88810d6652f0 R08: 0001 R09: > 0003 > [ 87.933869] R10: 4000 R11: 888109970600 R12: > 888123a44858 > [ 87.939767] R13: 888146e35ad0 R14: 888146dad6c0 R15: > > [ 87.945604] FS: 7f901262ab40() GS:888343c4() > knlGS: > [ 87.952390] CS: 0010 DS: ES: CR0: 80050033 > [ 87.956837] CR2: 55d9edfa8fa0 CR3: 00010218 CR4: > 06e0 > [ 87.962704] Call Trace: > [ 87.963876] > [ 87.964742] amdgpu_bo_unref+0x15/0x1e [amdgpu] > [ 87.968219] amdgpu_gem_object_free+0x2b/0x45 [amdgpu] > [ 87.972135] drm_gem_dmabuf_release+0x11/0x1a [drm] > [ 87.975792] dma_buf_release+0x36/0x7d > [ 87.978363] __dentry_kill+0xf5/0x12f > [ 87.980749] dput+0xfc/0x136 > [ 87.982386] __fput+0x17a/0x1cc > [ 87.984234] task_work_run+0x64/0x75 > [ 87.986615] exit_to_user_mode_prepare+0x88/0x112 > [ 87.990111] syscall_exit_to_user_mode+0x14/0x1f > [ 87.993513] do_syscall_64+0x7a/0x80 > [ 87.995873] entry_SYSCALL_64_after_hwframe+0x44/0xae > [ 87.999798] RIP: 0033:0x7f9013160fdb > [ 88.002129] Code: 03 00 00 00 0f 05 48 3d 00 f0 ff ff 77 41 c3 48 > 83 ec 18 89 7c 24 0c e8 33 81 f8 ff 8b 7c 24 0c 41 89 c0 b8 03 00 00 > 00 0f 05 <48> 3d 00 f0 ff ff 77 35 44 89 c7 89 44 24 0c e8 81 81 f8 ff > 8b 44 > [ 88.020215] RSP: 002b:7ffda9891d20 EFLAGS: 0293 ORIG_RAX: > 0003 > [ 88.026698] RAX: RBX: 7f901262a8f0 RCX: > 7f9013160fdb > [ 88.032789] RDX: RSI: 00055d9edfc6 RDI: > 0069 > [ 88.038864] RBP: 0069 R08: R09: > 007f > [ 88.045044] R10: R11: 0293 R12: > > [ 88.051033] R13: 55d9ecadd680 R14: 55d9eca96719 R15: > 55d9edf412f0 > [ 88.056868] > [ 88.057758] ---[ end trace bf3184763fd2083a ]--- > > I have seen a warning like this one in every dmesg log from 5.14.x > onwards, and it is clearly still
[PATCH v2 0/8] sysctl: second set of kernel/sysctl cleanups
This is the 2nd set of kernel/sysctl.c cleanups. The diff stat should reflect how this is a much better way to deal with theses. Fortunately coccinelle can be used to ensure correctness for most of these and/or future merge conflicts. Note that since this is part of a larger effort to cleanup kernel/sysctl.c I think we have no other option but to go with merging these patches in either Andrew's tree or keep them staged in a separate tree and send a merge request later. Otherwise kernel/sysctl.c will end up becoming a sore spot for the next merge window. Changes in this v2: * As suggested by Eric W. Biederman I dropped the subdir new call and just used the register_sysctl() by specifying the parent directory. * 0-day cleanups, commit log enhancements * Updated the coccinelle patch with register_sysctl() Luis Chamberlain (6): hpet: simplify subdirectory registration with register_sysctl() i915: simplify subdirectory registration with register_sysctl() macintosh/mac_hid.c: simplify subdirectory registration with register_sysctl() ocfs2: simplify subdirectory registration with register_sysctl() test_sysctl: simplify subdirectory registration with register_sysctl() cdrom: simplify subdirectory registration with register_sysctl() Xiaoming Ni (2): inotify: simplify subdirectory registration with register_sysctl() eventpoll: simplify sysctl declaration with register_sysctl() drivers/cdrom/cdrom.c| 23 +-- drivers/char/hpet.c | 22 +- drivers/gpu/drm/i915/i915_perf.c | 22 +- drivers/macintosh/mac_hid.c | 24 +--- fs/eventpoll.c | 10 +- fs/notify/inotify/inotify_user.c | 11 ++- fs/ocfs2/stackglue.c | 25 + include/linux/inotify.h | 3 --- include/linux/poll.h | 2 -- include/linux/sysctl.h | 1 - kernel/sysctl.c | 28 lib/test_sysctl.c| 22 +- 12 files changed, 25 insertions(+), 168 deletions(-) -- 2.33.0
[PATCH v2 5/8] test_sysctl: simplify subdirectory registration with register_sysctl()
There is no need to user boiler plate code to specify a set of base directories we're going to stuff sysctls under. Simplify this by using register_sysctl() and specifying the directory path directly. // pycocci sysctl-subdir-register-sysctl-simplify.cocci lib/test_sysctl.c @c1@ expression E1; identifier subdir, sysctls; @@ static struct ctl_table subdir[] = { { .procname = E1, .maxlen = 0, .mode = 0555, .child = sysctls, }, { } }; @c2@ identifier c1.subdir; expression E2; identifier base; @@ static struct ctl_table base[] = { { .procname = E2, .maxlen = 0, .mode = 0555, .child = subdir, }, { } }; @c3@ identifier c2.base; identifier header; @@ header = register_sysctl_table(base); @r1 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.subdir, c1.sysctls; @@ -static struct ctl_table subdir[] = { - { - .procname = E1, - .maxlen = 0, - .mode = 0555, - .child = sysctls, - }, - { } -}; @r2 depends on c1 && c2 && c3@ identifier c1.subdir; expression c2.E2; identifier c2.base; @@ -static struct ctl_table base[] = { - { - .procname = E2, - .maxlen = 0, - .mode = 0555, - .child = subdir, - }, - { } -}; @initialize:python@ @@ def make_my_fresh_expression(s1, s2): return '"' + s1.strip('"') + "/" + s2.strip('"') + '"' @r3 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.sysctls; expression c2.E2; identifier c2.base; identifier c3.header; fresh identifier E3 = script:python(E2, E1) { make_my_fresh_expression(E2, E1) }; @@ header = -register_sysctl_table(base); +register_sysctl(E3, sysctls); Generated-by: Coccinelle SmPL Signed-off-by: Luis Chamberlain --- lib/test_sysctl.c | 22 +- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/lib/test_sysctl.c b/lib/test_sysctl.c index 3750323973f4..a5a3d6c27e1f 100644 --- a/lib/test_sysctl.c +++ b/lib/test_sysctl.c @@ -128,26 +128,6 @@ static struct ctl_table test_table[] = { { } }; -static struct ctl_table test_sysctl_table[] = { - { - .procname = "test_sysctl", - .maxlen = 0, - .mode = 0555, - .child = test_table, - }, - { } -}; - -static struct ctl_table test_sysctl_root_table[] = { - { - .procname = "debug", - .maxlen = 0, - .mode = 0555, - .child = test_sysctl_table, - }, - { } -}; - static struct ctl_table_header *test_sysctl_header; static int __init test_sysctl_init(void) @@ -155,7 +135,7 @@ static int __init test_sysctl_init(void) test_data.bitmap_0001 = kzalloc(SYSCTL_TEST_BITMAP_SIZE/8, GFP_KERNEL); if (!test_data.bitmap_0001) return -ENOMEM; - test_sysctl_header = register_sysctl_table(test_sysctl_root_table); + test_sysctl_header = register_sysctl("debug/test_sysctl", test_table); if (!test_sysctl_header) { kfree(test_data.bitmap_0001); return -ENOMEM; -- 2.33.0
[PATCH v2 2/8] i915: simplify subdirectory registration with register_sysctl()
There is no need to user boiler plate code to specify a set of base directories we're going to stuff sysctls under. Simplify this by using register_sysctl() and specifying the directory path directly. // pycocci sysctl-subdir-register-sysctl-simplify.cocci PATH @c1@ expression E1; identifier subdir, sysctls; @@ static struct ctl_table subdir[] = { { .procname = E1, .maxlen = 0, .mode = 0555, .child = sysctls, }, { } }; @c2@ identifier c1.subdir; expression E2; identifier base; @@ static struct ctl_table base[] = { { .procname = E2, .maxlen = 0, .mode = 0555, .child = subdir, }, { } }; @c3@ identifier c2.base; identifier header; @@ header = register_sysctl_table(base); @r1 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.subdir, c1.sysctls; @@ -static struct ctl_table subdir[] = { - { - .procname = E1, - .maxlen = 0, - .mode = 0555, - .child = sysctls, - }, - { } -}; @r2 depends on c1 && c2 && c3@ identifier c1.subdir; expression c2.E2; identifier c2.base; @@ -static struct ctl_table base[] = { - { - .procname = E2, - .maxlen = 0, - .mode = 0555, - .child = subdir, - }, - { } -}; @initialize:python@ @@ def make_my_fresh_expression(s1, s2): return '"' + s1.strip('"') + "/" + s2.strip('"') + '"' @r3 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.sysctls; expression c2.E2; identifier c2.base; identifier c3.header; fresh identifier E3 = script:python(E2, E1) { make_my_fresh_expression(E2, E1) }; @@ header = -register_sysctl_table(base); +register_sysctl(E3, sysctls); Generated-by: Coccinelle SmPL Signed-off-by: Luis Chamberlain --- drivers/gpu/drm/i915/i915_perf.c | 22 +- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 2f01b8c0284c..5979e3258647 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -4273,26 +4273,6 @@ static struct ctl_table oa_table[] = { {} }; -static struct ctl_table i915_root[] = { - { -.procname = "i915", -.maxlen = 0, -.mode = 0555, -.child = oa_table, -}, - {} -}; - -static struct ctl_table dev_root[] = { - { -.procname = "dev", -.maxlen = 0, -.mode = 0555, -.child = i915_root, -}, - {} -}; - static void oa_init_supported_formats(struct i915_perf *perf) { struct drm_i915_private *i915 = perf->i915; @@ -4488,7 +4468,7 @@ static int destroy_config(int id, void *p, void *data) int i915_perf_sysctl_register(void) { - sysctl_header = register_sysctl_table(dev_root); + sysctl_header = register_sysctl("dev/i915", oa_table); return 0; } -- 2.33.0
[PATCH v2 4/8] ocfs2: simplify subdirectory registration with register_sysctl()
There is no need to user boiler plate code to specify a set of base directories we're going to stuff sysctls under. Simplify this by using register_sysctl() and specifying the directory path directly. // pycocci sysctl-subdir-register-sysctl-simplify.cocci PATH @c1@ expression E1; identifier subdir, sysctls; @@ static struct ctl_table subdir[] = { { .procname = E1, .maxlen = 0, .mode = 0555, .child = sysctls, }, { } }; @c2@ identifier c1.subdir; expression E2; identifier base; @@ static struct ctl_table base[] = { { .procname = E2, .maxlen = 0, .mode = 0555, .child = subdir, }, { } }; @c3@ identifier c2.base; identifier header; @@ header = register_sysctl_table(base); @r1 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.subdir, c1.sysctls; @@ -static struct ctl_table subdir[] = { - { - .procname = E1, - .maxlen = 0, - .mode = 0555, - .child = sysctls, - }, - { } -}; @r2 depends on c1 && c2 && c3@ identifier c1.subdir; expression c2.E2; identifier c2.base; @@ -static struct ctl_table base[] = { - { - .procname = E2, - .maxlen = 0, - .mode = 0555, - .child = subdir, - }, - { } -}; @initialize:python@ @@ def make_my_fresh_expression(s1, s2): return '"' + s1.strip('"') + "/" + s2.strip('"') + '"' @r3 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.sysctls; expression c2.E2; identifier c2.base; identifier c3.header; fresh identifier E3 = script:python(E2, E1) { make_my_fresh_expression(E2, E1) }; @@ header = -register_sysctl_table(base); +register_sysctl(E3, sysctls); Generated-by: Coccinelle SmPL Signed-off-by: Luis Chamberlain --- fs/ocfs2/stackglue.c | 25 + 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index 16f1bfc407f2..731558a6f27d 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c @@ -672,31 +672,8 @@ static struct ctl_table ocfs2_mod_table[] = { { } }; -static struct ctl_table ocfs2_kern_table[] = { - { - .procname = "ocfs2", - .data = NULL, - .maxlen = 0, - .mode = 0555, - .child = ocfs2_mod_table - }, - { } -}; - -static struct ctl_table ocfs2_root_table[] = { - { - .procname = "fs", - .data = NULL, - .maxlen = 0, - .mode = 0555, - .child = ocfs2_kern_table - }, - { } -}; - static struct ctl_table_header *ocfs2_table_header; - /* * Initialization */ @@ -705,7 +682,7 @@ static int __init ocfs2_stack_glue_init(void) { strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB); - ocfs2_table_header = register_sysctl_table(ocfs2_root_table); + ocfs2_table_header = register_sysctl("fs/ocfs2", ocfs2_mod_table); if (!ocfs2_table_header) { printk(KERN_ERR "ocfs2 stack glue: unable to register sysctl\n"); -- 2.33.0
[PATCH v2 8/8] eventpoll: simplify sysctl declaration with register_sysctl()
From: Xiaoming Ni The kernel/sysctl.c is a kitchen sink where everyone leaves their dirty dishes, this makes it very difficult to maintain. To help with this maintenance let's start by moving sysctls to places where they actually belong. The proc sysctl maintainers do not want to know what sysctl knobs you wish to add for your own piece of code, we just care about the core logic. So move the epoll_table sysctl to fs/eventpoll.c and use use register_sysctl(). Signed-off-by: Xiaoming Ni Signed-off-by: Luis Chamberlain --- fs/eventpoll.c | 10 +- include/linux/poll.h | 2 -- include/linux/sysctl.h | 1 - kernel/sysctl.c| 7 --- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 06f4c5ae1451..e2daa940ebce 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -307,7 +307,7 @@ static void unlist_file(struct epitems_head *head) static long long_zero; static long long_max = LONG_MAX; -struct ctl_table epoll_table[] = { +static struct ctl_table epoll_table[] = { { .procname = "max_user_watches", .data = &max_user_watches, @@ -319,6 +319,13 @@ struct ctl_table epoll_table[] = { }, { } }; + +static void __init epoll_sysctls_init(void) +{ + register_sysctl("fs/epoll", epoll_table); +} +#else +#define epoll_sysctls_init() do { } while (0) #endif /* CONFIG_SYSCTL */ static const struct file_operations eventpoll_fops; @@ -2378,6 +2385,7 @@ static int __init eventpoll_init(void) /* Allocates slab cache used to allocate "struct eppoll_entry" */ pwq_cache = kmem_cache_create("eventpoll_pwq", sizeof(struct eppoll_entry), 0, SLAB_PANIC|SLAB_ACCOUNT, NULL); + epoll_sysctls_init(); ephead_cache = kmem_cache_create("ep_head", sizeof(struct epitems_head), 0, SLAB_PANIC|SLAB_ACCOUNT, NULL); diff --git a/include/linux/poll.h b/include/linux/poll.h index 1cdc32b1f1b0..a9e0e1c2d1f2 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -8,12 +8,10 @@ #include #include #include -#include #include #include #include -extern struct ctl_table epoll_table[]; /* for sysctl */ /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating additional memory. */ #ifdef __clang__ diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 718492057c70..5e0428a71899 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -218,7 +218,6 @@ extern int no_unaligned_warning; extern struct ctl_table sysctl_mount_point[]; extern struct ctl_table random_table[]; extern struct ctl_table firmware_config_table[]; -extern struct ctl_table epoll_table[]; #else /* CONFIG_SYSCTL */ static inline struct ctl_table_header *register_sysctl_table(struct ctl_table * table) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 6aa67c737e4e..b09ff41720e3 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -3092,13 +3092,6 @@ static struct ctl_table fs_table[] = { .proc_handler = proc_dointvec, }, #endif -#ifdef CONFIG_EPOLL - { - .procname = "epoll", - .mode = 0555, - .child = epoll_table, - }, -#endif #endif { .procname = "protected_symlinks", -- 2.33.0
[PATCH v2 7/8] cdrom: simplify subdirectory registration with register_sysctl()
There is no need to user boiler plate code to specify a set of base directories we're going to stuff sysctls under. Simplify this by using register_sysctl() and specifying the directory path directly. // pycocci sysctl-subdir-register-sysctl-simplify.cocci PATH @c1@ expression E1; identifier subdir, sysctls; @@ static struct ctl_table subdir[] = { { .procname = E1, .maxlen = 0, .mode = 0555, .child = sysctls, }, { } }; @c2@ identifier c1.subdir; expression E2; identifier base; @@ static struct ctl_table base[] = { { .procname = E2, .maxlen = 0, .mode = 0555, .child = subdir, }, { } }; @c3@ identifier c2.base; identifier header; @@ header = register_sysctl_table(base); @r1 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.subdir, c1.sysctls; @@ -static struct ctl_table subdir[] = { - { - .procname = E1, - .maxlen = 0, - .mode = 0555, - .child = sysctls, - }, - { } -}; @r2 depends on c1 && c2 && c3@ identifier c1.subdir; expression c2.E2; identifier c2.base; @@ -static struct ctl_table base[] = { - { - .procname = E2, - .maxlen = 0, - .mode = 0555, - .child = subdir, - }, - { } -}; @initialize:python@ @@ def make_my_fresh_expression(s1, s2): return '"' + s1.strip('"') + "/" + s2.strip('"') + '"' @r3 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.sysctls; expression c2.E2; identifier c2.base; identifier c3.header; fresh identifier E3 = script:python(E2, E1) { make_my_fresh_expression(E2, E1) }; @@ header = -register_sysctl_table(base); +register_sysctl(E3, sysctls); Generated-by: Coccinelle SmPL Signed-off-by: Luis Chamberlain --- drivers/cdrom/cdrom.c | 23 +-- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 9877e413fce3..1b57d4666e43 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -3691,27 +3691,6 @@ static struct ctl_table cdrom_table[] = { }, { } }; - -static struct ctl_table cdrom_cdrom_table[] = { - { - .procname = "cdrom", - .maxlen = 0, - .mode = 0555, - .child = cdrom_table, - }, - { } -}; - -/* Make sure that /proc/sys/dev is there */ -static struct ctl_table cdrom_root_table[] = { - { - .procname = "dev", - .maxlen = 0, - .mode = 0555, - .child = cdrom_cdrom_table, - }, - { } -}; static struct ctl_table_header *cdrom_sysctl_header; static void cdrom_sysctl_register(void) @@ -3721,7 +3700,7 @@ static void cdrom_sysctl_register(void) if (!atomic_add_unless(&initialized, 1, 1)) return; - cdrom_sysctl_header = register_sysctl_table(cdrom_root_table); + cdrom_sysctl_header = register_sysctl("dev/cdrom", cdrom_table); /* set the defaults */ cdrom_sysctl_settings.autoclose = autoclose; -- 2.33.0
[PATCH v2 1/8] hpet: simplify subdirectory registration with register_sysctl()
There is no need to user boiler plate code to specify a set of base directories we're going to stuff sysctls under. Simplify this by using register_sysctl() and specifying the directory path directly. // pycocci sysctl-subdir-register-sysctl-simplify.cocci drivers/char/hpet.c @c1@ expression E1; identifier subdir, sysctls; @@ static struct ctl_table subdir[] = { { .procname = E1, .maxlen = 0, .mode = 0555, .child = sysctls, }, { } }; @c2@ identifier c1.subdir; expression E2; identifier base; @@ static struct ctl_table base[] = { { .procname = E2, .maxlen = 0, .mode = 0555, .child = subdir, }, { } }; @c3@ identifier c2.base; identifier header; @@ header = register_sysctl_table(base); @r1 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.subdir, c1.sysctls; @@ -static struct ctl_table subdir[] = { - { - .procname = E1, - .maxlen = 0, - .mode = 0555, - .child = sysctls, - }, - { } -}; @r2 depends on c1 && c2 && c3@ identifier c1.subdir; expression c2.E2; identifier c2.base; @@ -static struct ctl_table base[] = { - { - .procname = E2, - .maxlen = 0, - .mode = 0555, - .child = subdir, - }, - { } -}; @initialize:python@ @@ def make_my_fresh_expression(s1, s2): return '"' + s1.strip('"') + "/" + s2.strip('"') + '"' @r3 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.sysctls; expression c2.E2; identifier c2.base; identifier c3.header; fresh identifier E3 = script:python(E2, E1) { make_my_fresh_expression(E2, E1) }; @@ header = -register_sysctl_table(base); +register_sysctl(E3, sysctls); Generated-by: Coccinelle SmPL Signed-off-by: Luis Chamberlain --- drivers/char/hpet.c | 22 +- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 4e5431f01450..563dfae3b8da 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -746,26 +746,6 @@ static struct ctl_table hpet_table[] = { {} }; -static struct ctl_table hpet_root[] = { - { -.procname = "hpet", -.maxlen = 0, -.mode = 0555, -.child = hpet_table, -}, - {} -}; - -static struct ctl_table dev_root[] = { - { -.procname = "dev", -.maxlen = 0, -.mode = 0555, -.child = hpet_root, -}, - {} -}; - static struct ctl_table_header *sysctl_header; /* @@ -1061,7 +1041,7 @@ static int __init hpet_init(void) if (result < 0) return -ENODEV; - sysctl_header = register_sysctl_table(dev_root); + sysctl_header = register_sysctl("dev/hpet", hpet_table); result = acpi_bus_register_driver(&hpet_acpi_driver); if (result < 0) { -- 2.33.0
[PATCH v2 6/8] inotify: simplify subdirectory registration with register_sysctl()
From: Xiaoming Ni There is no need to user boiler plate code to specify a set of base directories we're going to stuff sysctls under. Simplify this by using register_sysctl() and specifying the directory path directly. Move inotify_user sysctl to inotify_user.c while at it to remove clutter from kernel/sysctl.c. Signed-off-by: Xiaoming Ni [mcgrof: update commit log to reflect new path we decided to take] Signed-off-by: Luis Chamberlain --- fs/notify/inotify/inotify_user.c | 11 ++- include/linux/inotify.h | 3 --- kernel/sysctl.c | 21 - 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 29fca3284bb5..54583f62dc44 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -58,7 +58,7 @@ struct kmem_cache *inotify_inode_mark_cachep __read_mostly; static long it_zero = 0; static long it_int_max = INT_MAX; -struct ctl_table inotify_table[] = { +static struct ctl_table inotify_table[] = { { .procname = "max_user_instances", .data = &init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES], @@ -87,6 +87,14 @@ struct ctl_table inotify_table[] = { }, { } }; + +static void __init inotify_sysctls_init(void) +{ + register_sysctl("fs/inotify", inotify_table); +} + +#else +#define inotify_sysctls_init() do { } while (0) #endif /* CONFIG_SYSCTL */ static inline __u32 inotify_arg_to_mask(struct inode *inode, u32 arg) @@ -849,6 +857,7 @@ static int __init inotify_user_setup(void) inotify_max_queued_events = 16384; init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES] = 128; init_user_ns.ucount_max[UCOUNT_INOTIFY_WATCHES] = watches_max; + inotify_sysctls_init(); return 0; } diff --git a/include/linux/inotify.h b/include/linux/inotify.h index 6a24905f6e1e..8d20caa1b268 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h @@ -7,11 +7,8 @@ #ifndef _LINUX_INOTIFY_H #define _LINUX_INOTIFY_H -#include #include -extern struct ctl_table inotify_table[]; /* for sysctl */ - #define ALL_INOTIFY_BITS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \ IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \ IN_MOVED_TO | IN_CREATE | IN_DELETE | \ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 7a90a12b9ea4..6aa67c737e4e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -125,13 +125,6 @@ static const int maxolduid = 65535; static const int ngroups_max = NGROUPS_MAX; static const int cap_last_cap = CAP_LAST_CAP; -#ifdef CONFIG_INOTIFY_USER -#include -#endif -#ifdef CONFIG_FANOTIFY -#include -#endif - #ifdef CONFIG_PROC_SYSCTL /** @@ -3099,20 +3092,6 @@ static struct ctl_table fs_table[] = { .proc_handler = proc_dointvec, }, #endif -#ifdef CONFIG_INOTIFY_USER - { - .procname = "inotify", - .mode = 0555, - .child = inotify_table, - }, -#endif -#ifdef CONFIG_FANOTIFY - { - .procname = "fanotify", - .mode = 0555, - .child = fanotify_table, - }, -#endif #ifdef CONFIG_EPOLL { .procname = "epoll", -- 2.33.0
[PATCH v2 3/8] macintosh/mac_hid.c: simplify subdirectory registration with register_sysctl()
There is no need to user boiler plate code to specify a set of base directories we're going to stuff sysctls under. Simplify this by using register_sysctl() and specifying the directory path directly. // pycocci sysctl-subdir-register-sysctl-simplify.cocci PATH @c1@ expression E1; identifier subdir, sysctls; @@ static struct ctl_table subdir[] = { { .procname = E1, .maxlen = 0, .mode = 0555, .child = sysctls, }, { } }; @c2@ identifier c1.subdir; expression E2; identifier base; @@ static struct ctl_table base[] = { { .procname = E2, .maxlen = 0, .mode = 0555, .child = subdir, }, { } }; @c3@ identifier c2.base; identifier header; @@ header = register_sysctl_table(base); @r1 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.subdir, c1.sysctls; @@ -static struct ctl_table subdir[] = { - { - .procname = E1, - .maxlen = 0, - .mode = 0555, - .child = sysctls, - }, - { } -}; @r2 depends on c1 && c2 && c3@ identifier c1.subdir; expression c2.E2; identifier c2.base; @@ -static struct ctl_table base[] = { - { - .procname = E2, - .maxlen = 0, - .mode = 0555, - .child = subdir, - }, - { } -}; @initialize:python@ @@ def make_my_fresh_expression(s1, s2): return '"' + s1.strip('"') + "/" + s2.strip('"') + '"' @r3 depends on c1 && c2 && c3@ expression c1.E1; identifier c1.sysctls; expression c2.E2; identifier c2.base; identifier c3.header; fresh identifier E3 = script:python(E2, E1) { make_my_fresh_expression(E2, E1) }; @@ header = -register_sysctl_table(base); +register_sysctl(E3, sysctls); Generated-by: Coccinelle SmPL Signed-off-by: Luis Chamberlain --- drivers/macintosh/mac_hid.c | 24 +--- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c index 28b8581b44dd..d8c4d5664145 100644 --- a/drivers/macintosh/mac_hid.c +++ b/drivers/macintosh/mac_hid.c @@ -239,33 +239,11 @@ static struct ctl_table mac_hid_files[] = { { } }; -/* dir in /proc/sys/dev */ -static struct ctl_table mac_hid_dir[] = { - { - .procname = "mac_hid", - .maxlen = 0, - .mode = 0555, - .child = mac_hid_files, - }, - { } -}; - -/* /proc/sys/dev itself, in case that is not there yet */ -static struct ctl_table mac_hid_root_dir[] = { - { - .procname = "dev", - .maxlen = 0, - .mode = 0555, - .child = mac_hid_dir, - }, - { } -}; - static struct ctl_table_header *mac_hid_sysctl_header; static int __init mac_hid_init(void) { - mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir); + mac_hid_sysctl_header = register_sysctl("dev/mac_hid", mac_hid_files); if (!mac_hid_sysctl_header) return -ENOMEM; -- 2.33.0
Re: [PATCH 0/5] xen: cleanup detection of non-essential pv devices
On 11/22/21 3:20 AM, Juergen Gross wrote: On 22.10.21 08:47, Juergen Gross wrote: Today the non-essential pv devices are hard coded in the xenbus driver and this list is lacking multiple entries. This series reworks the detection logic of non-essential devices by adding a flag for that purpose to struct xenbus_driver. Juergen Gross (5): xen: add "not_essential" flag to struct xenbus_driver xen: flag xen_drm_front to be not essential for system boot xen: flag hvc_xen to be not essential for system boot xen: flag pvcalls-front to be not essential for system boot xen: flag xen_snd_front to be not essential for system boot drivers/gpu/drm/xen/xen_drm_front.c | 1 + drivers/input/misc/xen-kbdfront.c | 1 + drivers/tty/hvc/hvc_xen.c | 1 + drivers/video/fbdev/xen-fbfront.c | 1 + drivers/xen/pvcalls-front.c | 1 + drivers/xen/xenbus/xenbus_probe_frontend.c | 14 +++--- include/xen/xenbus.h | 1 + sound/xen/xen_snd_front.c | 1 + 8 files changed, 10 insertions(+), 11 deletions(-) Any further comments? Reviewed-by: Boris Ostrovsky (I'll fix the semicolon typo in the last patch, no need to resend)
[Bug 211277] sometimes crash at s2ram-wake (Ryzen 3500U): amdgpu, drm, commit_tail, amdgpu_dm_atomic_commit_tail
https://bugzilla.kernel.org/show_bug.cgi?id=211277 --- Comment #76 from Alex Deucher (alexdeuc...@gmail.com) --- (In reply to James Zhu from comment #75) > (In reply to kolAflash from comment #74) > > @James Zhu > > > > Tested 5.15.2 for over a week and more than 50 standby-wakeups. > > No problems! > > Thanks :-) > > > > I would be happy about a patch for the 5.10 longterm kernel. > > The bug became a problem with v5.10-rc3 (see comment 14), just before > Debian > > made 5.10-longterm the Debian-11 kernel. So it would be great if I and > > probably other Debian-11 users could finally use that AMD GPU without > > workarounds. > > Hi @Alex Deucher, Can you help on this request? thanks! James I cc'ed stable with the patches so they should show up in 5.10 assuming they apply cleanly. If not, can you look at what it would take to backport them? -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
Re: [PATCH v8 0/8] MIPS: JZ4780 and CI20 HDMI
Hi Paul, > Am 23.11.2021 um 21:12 schrieb Paul Cercueil : > > Hi Nikolaus, > > I think if you can fix the last few things I commented on, and I get an ACK > from Rob for the Device Tree related patches, then it will be ready to merge. Fine! Especially for finding the NULL regulator risk. Will do in the next days. For the unwedge pinmux I have to check if we need it at all. BR and thanks, Nikolaus > > Cheers, > -Paul > > > Le mar., nov. 23 2021 at 19:13:53 +0100, H. Nikolaus Schaller > a écrit : >> PATCH V8 2021-11-23 19:14:00: >> - fix a bad editing result from patch 2/8 (found by p...@crapouillou.net) >> PATCH V7 2021-11-23 18:46:23: >> - changed gpio polarity of hdmi_power to 0 (suggested by >> p...@crapouillou.net) >> - fixed LCD1 irq number (bug found by p...@crapouillou.net) >> - removed "- 4" for calculating max_register (suggested by >> p...@crapouillou.net) >> - use unevaluatedPropertes instead of additionalProperties (suggested by >> r...@kernel.org) >> - moved and renamed ingenic,jz4780-hdmi.yaml (suggested by r...@kernel.org) >> - adjusted assigned-clocks changes to upstream which added some for SSI (by >> h...@goldelico.com) >> - rebased and tested with v5.16-rc2 + patch set drm/ingenic by >> p...@crapouillou.net (by h...@goldelico.com) >> PATCH V6 2021-11-10 20:43:33: >> - changed CONFIG_DRM_INGENIC_DW_HDMI to "m" (by h...@goldelico.com) >> - made ingenic-dw-hdmi an independent platform driver which can be compiled >> as module >> and removed error patch fixes for IPU (suggested by p...@crapouillou.net) >> - moved assigned-clocks from jz4780.dtsi to ci20.dts (suggested by >> p...@crapouillou.net) >> - fixed reg property in jz4780.dtsi to cover all registers incl. gamma and >> vee (by h...@goldelico.com) >> - added a base patch to calculate regmap size from DTS reg property >> (requested by p...@crapouillou.net) >> - restored resetting all bits except one in LCDOSDC (requested by >> p...@crapouillou.net) >> - clarified setting of cpos (suggested by p...@crapouillou.net) >> - moved bindings definition for ddc-i2c-bus (suggested by >> p...@crapouillou.net) >> - simplified mask definitions for JZ_LCD_DESSIZE (requested by >> p...@crapouillou.net) >> - removed setting alpha premultiplication (suggested by p...@crapouillou.net) >> - removed some comments (suggested by p...@crapouillou.net) >> PATCH V5 2021-10-05 14:28:44: >> - dropped mode_fixup and timings support in dw-hdmi as it is no longer >> needed in this V5 (by h...@goldelico.com) >> - dropped "drm/ingenic: add some jz4780 specific features" (stimulated by >> p...@crapouillou.net) >> - fixed typo in commit subject: "synopsis" -> "synopsys" (by >> h...@goldelico.com) >> - swapped clocks in jz4780.dtsi to match synopsys,dw-hdmi.yaml (by >> h...@goldelico.com) >> - improved, simplified, fixed, dtbschecked ingenic-jz4780-hdmi.yaml and made >> dependent of bridge/synopsys,dw-hdmi.yaml (based on suggestions by >> max...@cerno.tech) >> - fixed binding vs. driver&DTS use of hdmi-5v regulator (suggested by >> max...@cerno.tech) >> - dropped "drm/bridge: synopsis: Fix to properly handle HPD" - was a no >> longer needed workaround for a previous version >> (suggested by max...@cerno.tech) >> PATCH V4 2021-09-27 18:44:38: >> - fix setting output_port = 1 (issue found by p...@crapouillou.net) >> - ci20.dts: convert to use hdmi-connector (by h...@goldelico.com) >> - add a hdmi-regulator to control +5V power (by h...@goldelico.com) >> - added a fix to dw-hdmi to call drm_kms_helper_hotplug_event on plugin >> event detection (by h...@goldelico.com) >> - always allocate extended descriptor but initialize only for jz4780 (by >> h...@goldelico.com) >> - updated to work on top of "[PATCH v3 0/6] drm/ingenic: Various >> improvements v3" (by p...@crapouillou.net) >> - rebased to v5.13-rc3 >> PATCH V3 2021-08-08 07:10:50: >> This series adds HDMI support for JZ4780 and CI20 board (and fixes one IPU >> related issue in registration error path) >> - [patch 1/8] switched from mode_fixup to atomic_check (suggested by >> robert.f...@linaro.org) >> - the call to the dw-hdmi specialization is still called mode_fixup >> - [patch 3/8] diverse fixes for ingenic-drm-drv (suggested by >> p...@crapouillou.net) >> - factor out some non-HDMI features of the jz4780 into a separate patch >> - multiple fixes around max height >> - do not change regmap config but a copy on stack >> - define some constants >> - factor out fixing of drm_init error path for IPU into separate patch >> - use FIELD_PREP() >> - [patch 8/8] conversion to component framework dropped (suggested by >> laurent.pinch...@ideasonboard.com and p...@crapouillou.net) >> PATCH V2 2021-08-05 16:08:05: >> - code and commit messages revisited for checkpatch warnings >> - rebased on v5.14-rc4 >> - include (failed, hence RFC 8/8) attempt to convert to component framework >> (was suggested by Paul Cercueil a while ago) >> This series adds HDMI support for JZ4780 and CI20 bo