Re: [Intel-gfx] [PATCH 0/2] drm: link status property and DP link training failure handling
On Fri, 2016-12-16 at 16:47 +0200, Jani Nikula wrote: > On Fri, 16 Dec 2016, Daniel Vetterwrote: > > On Fri, Dec 16, 2016 at 12:29:05PM +0200, Jani Nikula wrote: > >> The two remaining patches from [1], rebased. > >> > >> BR, > >> Jani. > >> > >> > >> [1] > >> 1480984058-552-1-git-send-email-manasi.d.navare@intel.com">http://mid.mail-archive.com/1480984058-552-1-git-send-email-manasi.d.navare@intel.com > > > > Just for the record, I think the only thing missing here is the Xorg > > review on the -modesetting patch. As soon as we have that I can vacuum > > this up (probably best through drm-misc, but not sure). > > Yeah I rebased this (and provided a debug hack privately) so Martin can > test the modesetting changes. > > BR, > Jani. > > I tested the -modesetting patch, which Martin had provided to Manasi, with a compliance testing device (DPR-120) that can simulate link training failure. The link rate correctly lowered after the link_status property was set to BAD by the kernel and the userspace responded with a modeset. One thing that was not straight forward to figure out was I had to boot with i915.nuclear_pageflip=1. Is it documented somewhere that the property needs DRIVER_ATOMIC to be set, or is it implicit? The other thing I had trouble with -modesetting was, there was no modeset following a long pulse from the sink at the begging of the test. I had to force a modeset by changing the resolution so that the link training path is executed. However, the link training failure induced a modeset without any intervention. -DK > > -Daniel > > > >> > >> > >> Manasi Navare (2): > >> drm: Add a new connector atomic property for link status > >> drm/i915: Implement Link Rate fallback on Link training failure > >> > >> drivers/gpu/drm/drm_atomic.c | 16 + > >> drivers/gpu/drm/drm_atomic_helper.c | 15 > >> drivers/gpu/drm/drm_connector.c | 52 > >> +++ > >> drivers/gpu/drm/i915/intel_dp.c | 27 ++ > >> drivers/gpu/drm/i915/intel_dp_link_training.c | 22 ++-- > >> drivers/gpu/drm/i915/intel_drv.h | 3 ++ > >> include/drm/drm_connector.h | 19 ++ > >> include/drm/drm_mode_config.h | 5 +++ > >> include/uapi/drm/drm_mode.h | 4 +++ > >> 9 files changed, 161 insertions(+), 2 deletions(-) > >> > >> -- > >> 2.1.4 > >> > >> ___ > >> dri-devel mailing list > >> dri-de...@lists.freedesktop.org > >> https://lists.freedesktop.org/mailman/listinfo/dri-devel > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v2 i-g-t] tools: Add intel_dp_compliance for DisplayPort 1.2 compliance automation
On Wed, Dec 07, 2016 at 02:04:52PM -0800, Manasi Navare wrote: > This is the userspace component of the Displayport Compliance > testing software required for compliance testing of the I915 > Display Port driver. This must be running in order to successfully > complete Display Port compliance testing. This app and the kernel > code that accompanies it has been written to satify the requirements > of the Displayport Link CTS 1.2 rev1.1 specification from VESA. > Note that this application does not support eDP compliance testing. > This utility has an automation support for the Link training tests > (4.3.1.1. - 4.3.2.3), EDID tests (4.2.2.3 > - 4.2.2.6) and Video Pattern generation tests (4.3.3.1) from CTS > specification 1.2 Rev 1.1. > > This tool has the support for responding to the hotplug uevents > sent by compliance testting unit after each test. > > The Linux DUT running this utility must be in text (console) mode > and cannot have any other display manager running. Since this uses > sysfs nodes for kernel interaction, this utility should be run as > Root. Once this user application is up and running, waiting for > test requests, the test appliance software on the windows host > can now be used to execute the compliance tests. > > This app is based on some prior work done in April 2015 (by > Todd Previte) > > v2: > * Add mode unset on hotplug uevent on disconnect (Manasi Navare) > > Cc: Petri Latvala > Cc: Marius Vlad > Cc: Daniel Vetter > Signed-off-by: Manasi Navare Some general suggestions (more inline as well): * Please audit all output messages for proper spelling, grammar, caps, etc. * Many of the lines are quite long. It would be nice to keep the line lengths short (under 100 chars for sure, but IMHO under 78 is even better.) * Many of the functions only return '0'; consider changing them to void. * Perhaps this is excess paranoia, but I would check the validity of any pointer passed into a function before dereferencing it. This isn't done in several cases. * Make sure and check out Petri's feedback, all of which I agree with. Jim > --- > tools/Makefile.am |3 +- > tools/Makefile.sources |7 + > tools/intel_dp_compliance.c | 1060 > +++ > tools/intel_dp_compliance.h | 35 ++ > tools/intel_dp_compliance_hotplug.c | 123 > 5 files changed, 1227 insertions(+), 1 deletion(-) > create mode 100644 tools/intel_dp_compliance.c > create mode 100644 tools/intel_dp_compliance.h > create mode 100644 tools/intel_dp_compliance_hotplug.c > > diff --git a/tools/Makefile.am b/tools/Makefile.am > index 18f86f6..eac6d64 100644 > --- a/tools/Makefile.am > +++ b/tools/Makefile.am > @@ -13,7 +13,7 @@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib > AM_CFLAGS = $(DEBUG_CFLAGS) $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) \ > $(CAIRO_CFLAGS) $(LIBUNWIND_CFLAGS) -DPKGDATADIR=\"$(pkgdatadir)\" \ > $(WERROR_CFLAGS) > -LDADD = $(top_builddir)/lib/libintel_tools.la > +LDADD = $(top_builddir)/lib/libintel_tools.la $(GLIB_LIBS) > AM_LDFLAGS = -Wl,--as-needed > > > @@ -24,6 +24,7 @@ moduledir = $(libdir) > intel_aubdump_la_LDFLAGS = -module -avoid-version -no-undefined > intel_aubdump_la_SOURCES = aubdump.c > intel_aubdump_la_LIBADD = $(top_builddir)/lib/libintel_tools.la -ldl > +intel_dp_compliance_la_LIBADD = $(LDADD) > > bin_SCRIPTS = intel_aubdump > CLEANFILES = $(bin_SCRIPTS) > diff --git a/tools/Makefile.sources b/tools/Makefile.sources > index be58871..09c0667 100644 > --- a/tools/Makefile.sources > +++ b/tools/Makefile.sources > @@ -13,6 +13,7 @@ tools_prog_lists = \ > intel_bios_reader \ > intel_display_crc \ > intel_display_poller\ > + intel_dp_compliance \ > intel_forcewaked\ > intel_gpu_frequency \ > intel_firmware_decode \ > @@ -55,3 +56,9 @@ intel_l3_parity_SOURCES = \ > intel_l3_parity.h \ > intel_l3_udev_listener.c > > +intel_dp_compliance_SOURCES = \ > +intel_dp_compliance.c \ > +intel_dp_compliance.h \ > +intel_dp_compliance_hotplug.c \ > +$(NULL) > + > diff --git a/tools/intel_dp_compliance.c b/tools/intel_dp_compliance.c > new file mode 100644 > index 000..807d3f4 > --- /dev/null > +++ b/tools/intel_dp_compliance.c > @@ -0,0 +1,1060 @@ > +/* > + * Copyright ? 2014-2015 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + *
Re: [Intel-gfx] [PATCH 1/9] drm/i915: Keep i915_handle_error kerneldoc parameters together
On Fri, Dec 16, 2016 at 12:20:02PM -0800, Michel Thierry wrote: > And before the function description. > Tidy up from commit 14bb2c11796d70b ("drm/i915: Fix a buch of kerneldoc > warnings"), all others kerneldoc blocks look ok. > > Cc: Tvrtko Ursulin> Signed-off-by: Michel Thierry Reviewed-by: Chris Wilson -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] ✓ Fi.CI.BAT: success for series starting with [1/4] drm/i915: introduce GEM_WARN_ON
On Tue, Dec 13, 2016 at 09:15:35PM -, Patchwork wrote: > == Series Details == > > Series: series starting with [1/4] drm/i915: introduce GEM_WARN_ON > URL : https://patchwork.freedesktop.org/series/16758/ > State : success > > == Summary == > > Series 16758v1 Series without cover letter > https://patchwork.freedesktop.org/api/1.0/series/16758/revisions/1/mbox/ > > > fi-bdw-5557u total:247 pass:233 dwarn:0 dfail:0 fail:0 skip:14 > fi-bsw-n3050 total:247 pass:208 dwarn:0 dfail:0 fail:0 skip:39 > fi-bxt-t5700 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 > fi-byt-j1900 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 > fi-byt-n2820 total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 > fi-hsw-4770 total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 > fi-hsw-4770r total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 > fi-ilk-650 total:247 pass:195 dwarn:0 dfail:0 fail:0 skip:52 > fi-ivb-3520m total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 > fi-ivb-3770 total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 > fi-kbl-7500u total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 > fi-skl-6260u total:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 > fi-skl-6700hqtotal:247 pass:227 dwarn:0 dfail:0 fail:0 skip:20 > fi-skl-6700k total:247 pass:224 dwarn:3 dfail:0 fail:0 skip:20 > fi-skl-6770hqtotal:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 > fi-snb-2520m total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 > fi-snb-2600 total:247 pass:215 dwarn:0 dfail:0 fail:0 skip:32 > > 57b72b4a6d7b787aedeb7b776ab35c3b2d7f58e9 drm-tip: 2016y-12m-13d-17h-59m-26s > UTC integration manifest > ec9dba0 drm/i915: convert to using range_overflows > 2e82cdf drm/i915: introduce range_overflows utility macros > b2b8e00 drm/i915: move vma sanity checking into i915_vma_bind > 16aef35 drm/i915: introduce GEM_WARN_ON And pushed. Thanks, -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/9] drm/i915/tdr: Add engine reset count to error state
On 16/12/16 12:37, Chris Wilson wrote: On Fri, Dec 16, 2016 at 12:20:07PM -0800, Michel Thierry wrote: From: Arun SiluveryDriver maintains count of how many times a given engine is reset, useful to capture this in error state also. It gives an idea of how engine is coping up with the workloads it is executing before this error state. Also i915_engine_info(). I'll add it there too. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry --- drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 9 + drivers/gpu/drm/i915/i915_gpu_error.c | 3 +++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a034793bc246..1c706a082d60 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1877,6 +1877,7 @@ int i915_reset_engine(struct intel_engine_cs *engine) intel_engine_reset_cancel(engine); intel_execlists_restart_submission(engine); + dev_priv->gpu_error.engine_reset_count[engine->id]++; intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a97cc8f50ade..25183762ed94 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -937,6 +937,7 @@ struct drm_i915_error_state { enum intel_engine_hangcheck_action hangcheck_action; struct i915_address_space *vm; int num_requests; + u32 reset_count; /* position of active request inside the ring */ u32 rq_head, rq_post, rq_tail; @@ -1629,6 +1630,8 @@ struct i915_gpu_error { #define I915_RESET_IN_PROGRESS 0 #define I915_WEDGED(BITS_PER_LONG - 1) + unsigned long engine_reset_count[I915_NUM_ENGINES]; + /** * Waitqueue to signal when a hang is detected. Used to for waiters * to release the struct_mutex for the reset to procede. @@ -3397,6 +3400,12 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error) return READ_ONCE(error->reset_count); } +static inline u32 i915_engine_reset_count(struct i915_gpu_error *error, That's a weird hodgepodge. We first think of intel_engine and are confused, then we spot the reset. i915_reset_engine_count? Agreed i915_reset_engine_count is better (plus it's called from i915_reset_info). + struct intel_engine_cs *engine) +{ + return READ_ONCE(error->engine_reset_count[engine->id]); +} + Then the same rename here, reset_engine_count[]. Thanks void i915_gem_reset(struct drm_i915_private *dev_priv); void i915_gem_set_wedged(struct drm_i915_private *dev_priv); void i915_gem_reset_engine(struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index e16037d1b0ba..f168ad873521 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -453,6 +453,7 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, err_printf(m, " hangcheck action timestamp: %lu, %u ms ago\n", ee->hangcheck_timestamp, jiffies_to_msecs(jiffies - ee->hangcheck_timestamp)); + err_printf(m, " engine reset count: %u\n", ee->reset_count); error_print_request(m, " ELSP[0]: ", >execlist[0]); error_print_request(m, " ELSP[1]: ", >execlist[1]); @@ -1170,6 +1171,8 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->hangcheck_timestamp = engine->hangcheck.action_timestamp; ee->hangcheck_action = engine->hangcheck.action; ee->hangcheck_stalled = engine->hangcheck.stalled; + ee->reset_count = i915_engine_reset_count(_priv->gpu_error, + engine); if (USES_PPGTT(dev_priv)) { int i; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] ✗ Fi.CI.BAT: warning for Execlist based engine-reset
== Series Details == Series: Execlist based engine-reset URL : https://patchwork.freedesktop.org/series/16936/ State : warning == Summary == Series 16936v1 Execlist based engine-reset https://patchwork.freedesktop.org/api/1.0/series/16936/revisions/1/mbox/ Test kms_pipe_crc_basic: Subgroup suspend-read-crc-pipe-b: pass -> SKIP (fi-bxt-j4205) fi-bdw-5557u total:247 pass:233 dwarn:0 dfail:0 fail:0 skip:14 fi-bsw-n3050 total:247 pass:208 dwarn:0 dfail:0 fail:0 skip:39 fi-bxt-j4205 total:247 pass:222 dwarn:0 dfail:0 fail:0 skip:25 fi-bxt-t5700 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-j1900 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-n2820 total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-hsw-4770 total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-hsw-4770r total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-ilk-650 total:247 pass:195 dwarn:0 dfail:0 fail:0 skip:52 fi-ivb-3520m total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-ivb-3770 total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-kbl-7500u total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-skl-6260u total:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-skl-6700hqtotal:247 pass:227 dwarn:0 dfail:0 fail:0 skip:20 fi-skl-6700k total:247 pass:224 dwarn:3 dfail:0 fail:0 skip:20 fi-skl-6770hqtotal:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-snb-2520m total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-snb-2600 total:247 pass:215 dwarn:0 dfail:0 fail:0 skip:32 705f1e8fef81d504f0032df8e21bdc2e74850b3a drm-tip: 2016y-12m-16d-15h-40m-02s UTC integration manifest 9a591cb drm/i915: Add engine reset count in get-reset-stats ioctl 709af8f drm/i915/tdr: Enable Engine reset and recovery support f37aa42 drm/i915/tdr: Export per-engine reset count info to debugfs 4c1e046 drm/i915/tdr: Add engine reset count to error state 41e96eb drm/i915: Skip reset request if there is one already d3b2dc8f4 drm/i915/tdr: Add support for per engine reset recovery d654f09 drm/i915/tdr: Modify error handler for per engine hang recovery db8e495 drm/i915: Update i915.reset to handle engine resets b94f5b6 drm/i915: Keep i915_handle_error kerneldoc parameters together == Logs == For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3313/ ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 4/9] drm/i915/tdr: Add support for per engine reset recovery
On Fri, Dec 16, 2016 at 12:20:05PM -0800, Michel Thierry wrote: > From: Arun Siluvery> > This change implements support for per-engine reset as an initial, less > intrusive hang recovery option to be attempted before falling back to the > legacy full GPU reset recovery mode if necessary. This is only supported > from Gen8 onwards. > > Hangchecker determines which engines are hung and invokes error handler to > recover from it. Error handler schedules recovery for each of those engines > that are hung. The recovery procedure is as follows, > - identifies the request that caused the hang and it is dropped > - force engine to idle: this is done by issuing a reset request > - reset and re-init engine > - restart submissions to the engine > > If engine reset fails then we fall back to heavy weight full gpu reset > which resets all engines and reinitiazes complete state of HW and SW. > > v2: Rebase. > > Cc: Chris Wilson > Cc: Mika Kuoppala > Signed-off-by: Tomas Elf > Signed-off-by: Arun Siluvery > Signed-off-by: Michel Thierry > --- > drivers/gpu/drm/i915/i915_drv.c | 56 > +++-- > drivers/gpu/drm/i915/i915_drv.h | 3 ++ > drivers/gpu/drm/i915/i915_gem.c | 2 +- > drivers/gpu/drm/i915/intel_lrc.c| 12 > drivers/gpu/drm/i915/intel_lrc.h| 1 + > drivers/gpu/drm/i915/intel_uncore.c | 41 --- > 6 files changed, 108 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c > index e5688edd62cd..a034793bc246 100644 > --- a/drivers/gpu/drm/i915/i915_drv.c > +++ b/drivers/gpu/drm/i915/i915_drv.c > @@ -1830,18 +1830,70 @@ void i915_reset(struct drm_i915_private *dev_priv) > * > * Reset a specific GPU engine. Useful if a hang is detected. > * Returns zero on successful reset or otherwise an error code. > + * > + * Procedure is fairly simple: > + * - identifies the request that caused the hang and it is dropped > + * - force engine to idle: this is done by issuing a reset request > + * - reset engine > + * - restart submissions to the engine > */ > int i915_reset_engine(struct intel_engine_cs *engine) What's the serialisation between potential callers of i915_reset_engine()? > { > int ret; > struct drm_i915_private *dev_priv = engine->i915; > > - /* FIXME: replace me with engine reset sequence */ > - ret = -ENODEV; > + /* > + * We need to first idle the engine by issuing a reset request, > + * then perform soft reset and re-initialize hw state, for all of > + * this GT power need to be awake so ensure it does throughout the > + * process > + */ > + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); > + > + /* > + * the request that caused the hang is stuck on elsp, identify the > + * active request and drop it, adjust head to skip the offending > + * request to resume executing remaining requests in the queue. > + */ > + i915_gem_reset_engine(engine); Must freeze the engine and irqs first, before calling i915_gem_reset_engine() (i.e. something like disable_engines_irq, cancelling tasklet) Eeek note that the current i915_gem_reset_engine() is lacking a spinlock. > + > + ret = intel_engine_reset_begin(engine); > + if (ret) { > + DRM_ERROR("Failed to disable %s\n", engine->name); > + goto error; > + } > + > + ret = intel_gpu_reset(dev_priv, intel_engine_flag(engine)); > + if (ret) { > + DRM_ERROR("Failed to reset %s, ret=%d\n", engine->name, ret); > + intel_engine_reset_cancel(engine); > + goto error; > + } > + > + ret = engine->init_hw(engine); > + if (ret) > + goto error; > > + intel_engine_reset_cancel(engine); > + intel_execlists_restart_submission(engine); engine->init_hw(engine) *is* intel_execlists_restart_submission. > + > + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); > + return 0; > + > +error: > /* use full gpu reset to recover on error */ > set_bit(I915_RESET_IN_PROGRESS, _priv->gpu_error.flags); > > + /* Engine reset is performed without taking struct_mutex, since it > + * failed we now fallback to full gpu reset. Wakeup any waiters > + * which should now see the reset_in_progress and release > + * struct_mutex for us to continue recovery. > + */ > + rcu_read_lock(); > + intel_engine_wakeup(engine); > + rcu_read_unlock(); > + > + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); > return ret; > } -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org
Re: [Intel-gfx] [PATCH 6/9] drm/i915/tdr: Add engine reset count to error state
On Fri, Dec 16, 2016 at 12:20:07PM -0800, Michel Thierry wrote: > From: Arun Siluvery> > Driver maintains count of how many times a given engine is reset, useful to > capture this in error state also. It gives an idea of how engine is coping > up with the workloads it is executing before this error state. Also i915_engine_info(). > Cc: Chris Wilson > Cc: Mika Kuoppala > Signed-off-by: Arun Siluvery > Signed-off-by: Michel Thierry > --- > drivers/gpu/drm/i915/i915_drv.c | 1 + > drivers/gpu/drm/i915/i915_drv.h | 9 + > drivers/gpu/drm/i915/i915_gpu_error.c | 3 +++ > 3 files changed, 13 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c > index a034793bc246..1c706a082d60 100644 > --- a/drivers/gpu/drm/i915/i915_drv.c > +++ b/drivers/gpu/drm/i915/i915_drv.c > @@ -1877,6 +1877,7 @@ int i915_reset_engine(struct intel_engine_cs *engine) > intel_engine_reset_cancel(engine); > intel_execlists_restart_submission(engine); > > + dev_priv->gpu_error.engine_reset_count[engine->id]++; > intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); > return 0; > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index a97cc8f50ade..25183762ed94 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -937,6 +937,7 @@ struct drm_i915_error_state { > enum intel_engine_hangcheck_action hangcheck_action; > struct i915_address_space *vm; > int num_requests; > + u32 reset_count; > > /* position of active request inside the ring */ > u32 rq_head, rq_post, rq_tail; > @@ -1629,6 +1630,8 @@ struct i915_gpu_error { > #define I915_RESET_IN_PROGRESS 0 > #define I915_WEDGED (BITS_PER_LONG - 1) > > + unsigned long engine_reset_count[I915_NUM_ENGINES]; > + > /** >* Waitqueue to signal when a hang is detected. Used to for waiters >* to release the struct_mutex for the reset to procede. > @@ -3397,6 +3400,12 @@ static inline u32 i915_reset_count(struct > i915_gpu_error *error) > return READ_ONCE(error->reset_count); > } > > +static inline u32 i915_engine_reset_count(struct i915_gpu_error *error, That's a weird hodgepodge. We first think of intel_engine and are confused, then we spot the reset. i915_reset_engine_count? > + struct intel_engine_cs *engine) > +{ > + return READ_ONCE(error->engine_reset_count[engine->id]); > +} > + > void i915_gem_reset(struct drm_i915_private *dev_priv); > void i915_gem_set_wedged(struct drm_i915_private *dev_priv); > void i915_gem_reset_engine(struct intel_engine_cs *engine); > diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c > b/drivers/gpu/drm/i915/i915_gpu_error.c > index e16037d1b0ba..f168ad873521 100644 > --- a/drivers/gpu/drm/i915/i915_gpu_error.c > +++ b/drivers/gpu/drm/i915/i915_gpu_error.c > @@ -453,6 +453,7 @@ static void error_print_engine(struct > drm_i915_error_state_buf *m, > err_printf(m, " hangcheck action timestamp: %lu, %u ms ago\n", > ee->hangcheck_timestamp, > jiffies_to_msecs(jiffies - ee->hangcheck_timestamp)); > + err_printf(m, " engine reset count: %u\n", ee->reset_count); > > error_print_request(m, " ELSP[0]: ", >execlist[0]); > error_print_request(m, " ELSP[1]: ", >execlist[1]); > @@ -1170,6 +1171,8 @@ static void error_record_engine_registers(struct > drm_i915_error_state *error, > ee->hangcheck_timestamp = engine->hangcheck.action_timestamp; > ee->hangcheck_action = engine->hangcheck.action; > ee->hangcheck_stalled = engine->hangcheck.stalled; > + ee->reset_count = i915_engine_reset_count(_priv->gpu_error, > + engine); > > if (USES_PPGTT(dev_priv)) { > int i; > -- > 2.11.0 > -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH i-g-t] igt_kms: Use const parameters for igt_assert_crc_equal
Since we're not modifying these anywhere, let's make them const so as to not break code doing comparisons against compile-time CRCs. Signed-off-by: Lyude--- lib/igt_debugfs.c | 2 +- lib/igt_debugfs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 3d92c6a..f8c8727 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -270,7 +270,7 @@ bool igt_debugfs_search(const char *filename, const char *substring) * be random testcase failures when different screen contents end up with the * same CRC by chance. */ -void igt_assert_crc_equal(igt_crc_t *a, igt_crc_t *b) +void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b) { int i; diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4c6572c..86c25dd 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -113,7 +113,7 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_MAX, }; -void igt_assert_crc_equal(igt_crc_t *a, igt_crc_t *b); +void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b); char *igt_crc_to_string(igt_crc_t *crc); void igt_require_pipe_crc(void); -- 2.9.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/9] drm/i915/tdr: Modify error handler for per engine hang recovery
From: Arun SiluveryThis is a preparatory patch which modifies error handler to do per engine hang recovery. The actual patch which implements this sequence follows later in the series. The aim is to prepare existing recovery function to adapt to this new function where applicable (which fails at this point because core implementation is lacking) and continue recovery using legacy full gpu reset. A helper function is also added to query the availability of engine reset. The error events behaviour that are used to notify user of reset are adapted to engine reset such that it doesn't break users listening to these events. In legacy we report an error event, a reset event before resetting the gpu and a reset done event marking the completion of reset. The same behaviour is adapted but reset event is only dispatched once even when multiple engines are hung. Finally once reset is complete we send reset done event as usual. Note that this implementation of engine reset is for i915 directly submitting to the ELSP, where the driver manages the hang detection, recovery and resubmission. With GuC submission these tasks are shared between driver and firmware; i915 will still responsible for detecting a hang, and when it does it will have to request GuC to reset that Engine and remind the firmware about the outstanding submissions. v2: rebase, advertise engine reset availability in platform definition, add note about GuC submission. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Ian Lister Signed-off-by: Tomas Elf Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry --- drivers/gpu/drm/i915/i915_drv.c | 21 + drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/i915_irq.c | 88 +++-- drivers/gpu/drm/i915/i915_pci.c | 5 ++- drivers/gpu/drm/i915/intel_uncore.c | 11 + 5 files changed, 103 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6428588518aa..e5688edd62cd 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1824,6 +1824,27 @@ void i915_reset(struct drm_i915_private *dev_priv) goto wakeup; } +/** + * i915_reset_engine - reset GPU engine to recover from a hang + * @engine: engine to reset + * + * Reset a specific GPU engine. Useful if a hang is detected. + * Returns zero on successful reset or otherwise an error code. + */ +int i915_reset_engine(struct intel_engine_cs *engine) +{ + int ret; + struct drm_i915_private *dev_priv = engine->i915; + + /* FIXME: replace me with engine reset sequence */ + ret = -ENODEV; + + /* use full gpu reset to recover on error */ + set_bit(I915_RESET_IN_PROGRESS, _priv->gpu_error.flags); + + return ret; +} + static int i915_pm_suspend(struct device *kdev) { struct pci_dev *pdev = to_pci_dev(kdev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fb3c88144aa8..6b4e8ee19905 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -781,6 +781,7 @@ struct intel_csr { func(has_ddi); \ func(has_decoupled_mmio); \ func(has_dp_mst); \ + func(has_engine_reset); \ func(has_fbc); \ func(has_fpga_dbg); \ func(has_full_ppgtt); \ @@ -3007,6 +3008,8 @@ extern void i915_driver_unload(struct drm_device *dev); extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); extern void i915_reset(struct drm_i915_private *dev_priv); +extern bool intel_has_engine_reset(struct drm_i915_private *dev_priv); +extern int i915_reset_engine(struct intel_engine_cs *engine); extern int intel_guc_reset(struct drm_i915_private *dev_priv); extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine); extern void intel_hangcheck_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 77caeeb5ee55..da619810f59e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2594,7 +2594,8 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv) * Fire an error uevent so userspace can see that a hang or error * was detected. */ -static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) +static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv, + u32 engine_mask) { struct kobject *kobj = _priv->drm.primary->kdev->kobj; char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; @@ -2603,7 +2604,15 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
[Intel-gfx] [RFC 9/9] drm/i915: Add engine reset count in get-reset-stats ioctl
Users/tests relying on the total reset count will start seeing a smaller number since most of the hangs can be handled by engine reset. Note that if reset engine x, context a running on engine y will be unaware and unaffected. To start the discussion, include just a total engine reset count. If it is deemed useful, it can be extended to report each engine separately. Cc: Chris WilsonCc: Mika Kuoppala Cc: mesa-...@lists.freedesktop.org Signed-off-by: Michel Thierry --- drivers/gpu/drm/i915/i915_gem_context.c | 14 +++--- include/uapi/drm/i915_drm.h | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 1822d338c7aa..7f89ff21e2e5 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -1339,9 +1339,11 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_reset_stats *args = data; struct i915_gem_context *ctx; + struct intel_engine_cs *engine; + enum intel_engine_id id; int ret; - if (args->flags || args->pad) + if (args->flags) return -EINVAL; if (args->ctx_id == DEFAULT_CONTEXT_HANDLE && !capable(CAP_SYS_ADMIN)) @@ -1357,10 +1359,16 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, return PTR_ERR(ctx); } - if (capable(CAP_SYS_ADMIN)) + if (capable(CAP_SYS_ADMIN)) { args->reset_count = i915_reset_count(_priv->gpu_error); - else + for_each_engine(engine, dev_priv, id) + args->engine_reset_count += + i915_engine_reset_count(_priv->gpu_error, + engine); + } else { args->reset_count = 0; + args->engine_reset_count = 0; + } args->batch_active = ctx->guilty_count; args->batch_pending = ctx->active_count; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 1110e628c239..172ce188a8cb 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1201,7 +1201,8 @@ struct drm_i915_reset_stats { /* Number of batches lost pending for execution, for this context */ __u32 batch_pending; - __u32 pad; + /* Number of engine resets since boot/module reload, for all contexts */ + __u32 engine_reset_count; }; struct drm_i915_gem_userptr { -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] ✗ Fi.CI.BAT: warning for series starting with [v3,01/38] drm/i915: Use the MRU stack search after evicting
== Series Details == Series: series starting with [v3,01/38] drm/i915: Use the MRU stack search after evicting URL : https://patchwork.freedesktop.org/series/16934/ State : warning == Summary == Series 16934v1 Series without cover letter https://patchwork.freedesktop.org/api/1.0/series/16934/revisions/1/mbox/ Test kms_pipe_crc_basic: Subgroup suspend-read-crc-pipe-b: pass -> SKIP (fi-bxt-j4205) fi-bdw-5557u total:247 pass:233 dwarn:0 dfail:0 fail:0 skip:14 fi-bsw-n3050 total:247 pass:208 dwarn:0 dfail:0 fail:0 skip:39 fi-bxt-j4205 total:247 pass:222 dwarn:0 dfail:0 fail:0 skip:25 fi-bxt-t5700 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-j1900 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-n2820 total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-hsw-4770 total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-hsw-4770r total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-ilk-650 total:247 pass:195 dwarn:0 dfail:0 fail:0 skip:52 fi-ivb-3520m total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-ivb-3770 total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-kbl-7500u total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-skl-6260u total:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-skl-6700hqtotal:247 pass:227 dwarn:0 dfail:0 fail:0 skip:20 fi-skl-6700k total:247 pass:224 dwarn:3 dfail:0 fail:0 skip:20 fi-skl-6770hqtotal:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-snb-2520m total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-snb-2600 total:247 pass:215 dwarn:0 dfail:0 fail:0 skip:32 705f1e8fef81d504f0032df8e21bdc2e74850b3a drm-tip: 2016y-12m-16d-15h-40m-02s UTC integration manifest 7c45ab9 drm: kselftest for drm_mm and bottom-up allocation f0dc10e drm: Improve drm_mm search (and fix topdown allocation) with rbtrees 9d67b2a drm: Use drm_mm_insert_node_in_range_generic() for everyone 7c31969 drm: Apply range restriction after color adjustment when allocation a389ffb drm: Wrap drm_mm_node.hole_follows 8f3d65a drm: Apply tight eviction scanning to color_adjust 713e51e drm: Simplify drm_mm scan-list manipulation 3f23d58 drm: Optimise power-of-two alignments in drm_mm_scan_add_block() 4b7fe06 drm: Compute tight evictions for drm_mm_scan 7b43f39 drm: Fix application of color vs range restriction when scanning drm_mm 46ca14a drm: Unconditionally do the range check in drm_mm_scan_add_block() 52d3c07 drm: Rename prev_node to hole in drm_mm_scan_add_block() 843ed0b drm: Extract struct drm_mm_scan from struct drm_mm bd683ec drm: Add asserts to catch overflow in drm_mm_init() and drm_mm_init_scan() 54b09d7 drm: Simplify drm_mm_clean() 5d0b310 drm: Detect overflow in drm_mm_reserve_node() 68a3fad drm: Fix kerneldoc for drm_mm_scan_remove_block() 58b86fb drm: Promote drm_mm alignment to u64 200a726 drm/i915: Build DRM range manager selftests for CI 8b85ea3 drm: kselftest for drm_mm and restricted color eviction bc18224 drm: kselftest for drm_mm and color eviction aecad93 drm: kselftest for drm_mm and color adjustment 72de4a2 drm: kselftest for drm_mm and top-down allocation 79acff5 drm: kselftest for drm_mm and range restricted eviction de7a869 drm: kselftest for drm_mm and eviction 7c2f995 drm: kselftest for drm_mm and alignment a45196d drm: kselftest for drm_mm_insert_node_in_range() 63e7304 drm: kselftest for drm_mm_replace_node() f859694 drm: kselftest for drm_mm_insert_node() 2f810a4 drm: kselftest for drm_mm_reserve_node() 203008d drm: kselftest for drm_mm_debug() fd28f93 drm: kselftest for drm_mm_init() a23ba8f drm: Add some kselftests for the DRM range manager (struct drm_mm) d742b04 drm: Add a simple generator of random permutations 95765bd lib: Add a simple prime number generator 80ec238 drm: Compile time enabling for asserts in drm_mm a451708 drm: Use drm_mm_nodes() as shorthand for the list of nodes under struct drm_mm a4063bcc drm/i915: Use the MRU stack search after evicting == Logs == For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3312/ ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 5/9] drm/i915: Skip reset request if there is one already
From: Mika KuoppalaTo perform engine reset we first disable engine to capture its state. This is done by issuing a reset request. Because we are reusing existing infrastructure, again when we actually reset an engine, reset function checks engine mask and issues reset request again which is unnecessary. To avoid this we check if the engine is already prepared, if so we just exit from that point. Cc: Chris Wilson Signed-off-by: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry --- drivers/gpu/drm/i915/intel_uncore.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 9105c166a6d5..cd3102d841a4 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1761,10 +1761,15 @@ int intel_wait_for_register(struct drm_i915_private *dev_priv, static int gen8_engine_reset_begin(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; + const i915_reg_t reset_ctrl = RING_RESET_CTL(engine->mmio_base); + const u32 ready = RESET_CTL_REQUEST_RESET | RESET_CTL_READY_TO_RESET; int ret; - I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base), - _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); + /* If engine has been already prepared, we can shortcut here */ + if ((I915_READ_FW(reset_ctrl) & ready) == ready) + return 0; + + I915_WRITE_FW(reset_ctrl, _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); ret = intel_wait_for_register_fw(dev_priv, RING_RESET_CTL(engine->mmio_base), -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 7/9] drm/i915/tdr: Export per-engine reset count info to debugfs
From: Arun SiluveryA new variable is added to export the reset counts to debugfs, this includes full gpu reset and engine reset count. This is useful for tests where they are expected to trigger reset; these counts are checked before and after the test to ensure the same. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry --- drivers/gpu/drm/i915/i915_debugfs.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 54e196d9d83e..b2a3c31ba95c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1370,6 +1370,23 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) return 0; } +static int i915_reset_info(struct seq_file *m, void *unused) +{ + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct i915_gpu_error *error = _priv->gpu_error; + struct intel_engine_cs *engine; + enum intel_engine_id id; + + seq_printf(m, "full gpu reset = %u\n", i915_reset_count(error)); + + for_each_engine(engine, dev_priv, id) { + seq_printf(m, "%s = %u\n", engine->name, + i915_engine_reset_count(error, engine)); + } + + return 0; +} + static int ironlake_drpc_info(struct seq_file *m) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -5408,6 +5425,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_guc_log_dump", i915_guc_log_dump, 0}, {"i915_frequency_info", i915_frequency_info, 0}, {"i915_hangcheck_info", i915_hangcheck_info, 0}, + {"i915_reset_info", i915_reset_info, 0}, {"i915_drpc_info", i915_drpc_info, 0}, {"i915_emon_status", i915_emon_status, 0}, {"i915_ring_freq_table", i915_ring_freq_table, 0}, -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 6/9] drm/i915/tdr: Add engine reset count to error state
From: Arun SiluveryDriver maintains count of how many times a given engine is reset, useful to capture this in error state also. It gives an idea of how engine is coping up with the workloads it is executing before this error state. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry --- drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 9 + drivers/gpu/drm/i915/i915_gpu_error.c | 3 +++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a034793bc246..1c706a082d60 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1877,6 +1877,7 @@ int i915_reset_engine(struct intel_engine_cs *engine) intel_engine_reset_cancel(engine); intel_execlists_restart_submission(engine); + dev_priv->gpu_error.engine_reset_count[engine->id]++; intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a97cc8f50ade..25183762ed94 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -937,6 +937,7 @@ struct drm_i915_error_state { enum intel_engine_hangcheck_action hangcheck_action; struct i915_address_space *vm; int num_requests; + u32 reset_count; /* position of active request inside the ring */ u32 rq_head, rq_post, rq_tail; @@ -1629,6 +1630,8 @@ struct i915_gpu_error { #define I915_RESET_IN_PROGRESS 0 #define I915_WEDGED(BITS_PER_LONG - 1) + unsigned long engine_reset_count[I915_NUM_ENGINES]; + /** * Waitqueue to signal when a hang is detected. Used to for waiters * to release the struct_mutex for the reset to procede. @@ -3397,6 +3400,12 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error) return READ_ONCE(error->reset_count); } +static inline u32 i915_engine_reset_count(struct i915_gpu_error *error, + struct intel_engine_cs *engine) +{ + return READ_ONCE(error->engine_reset_count[engine->id]); +} + void i915_gem_reset(struct drm_i915_private *dev_priv); void i915_gem_set_wedged(struct drm_i915_private *dev_priv); void i915_gem_reset_engine(struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index e16037d1b0ba..f168ad873521 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -453,6 +453,7 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, err_printf(m, " hangcheck action timestamp: %lu, %u ms ago\n", ee->hangcheck_timestamp, jiffies_to_msecs(jiffies - ee->hangcheck_timestamp)); + err_printf(m, " engine reset count: %u\n", ee->reset_count); error_print_request(m, " ELSP[0]: ", >execlist[0]); error_print_request(m, " ELSP[1]: ", >execlist[1]); @@ -1170,6 +1171,8 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->hangcheck_timestamp = engine->hangcheck.action_timestamp; ee->hangcheck_action = engine->hangcheck.action; ee->hangcheck_stalled = engine->hangcheck.stalled; + ee->reset_count = i915_engine_reset_count(_priv->gpu_error, + engine); if (USES_PPGTT(dev_priv)) { int i; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 0/9] Execlist based engine-reset
These patches are to add engine reset feature from Gen8. This is also referred to as Timeout detection and recovery (TDR). This complements to the full gpu reset feature available in i915 but it only allows to reset a particular engine instead of all engines thus providing a light weight engine reset and recovery mechanism. This implementation is for execlist based submission only hence limited from Gen8 onwards. For GuC based submission, additional changes can be added later on. Timeout detection relies on the existing hangcheck which remains the same, main changes are to the recovery mechanism. Once we detect a hang on a particular engine we identify the request that caused the hang, skip the request and adjust head pointers to allow the execution to proceed normally. After some cleanup, submissions are restarted to process remaining work queued to that engine. If engine reset fails to recover engine correctly then we fallback to full gpu reset. v2: ELSP queue request tracking and reset path changes to handle incomplete requests during reset. Thanks to Chris Wilson for providing these patches. v3: Let the waiter keep handling the full gpu reset if it already has the lock; point out that GuC submission needs a different method to restart workloads after the engine reset completes. Arun Siluvery (6): drm/i915: Update i915.reset to handle engine resets drm/i915/tdr: Modify error handler for per engine hang recovery drm/i915/tdr: Add support for per engine reset recovery drm/i915/tdr: Add engine reset count to error state drm/i915/tdr: Export per-engine reset count info to debugfs drm/i915/tdr: Enable Engine reset and recovery support Michel Thierry (2): drm/i915: Keep i915_handle_error kerneldoc parameters together drm/i915: Add engine reset count in get-reset-stats ioctl Mika Kuoppala (1): drm/i915: Skip reset request if there is one already drivers/gpu/drm/i915/i915_debugfs.c | 18 +++ drivers/gpu/drm/i915/i915_drv.c | 74 +++ drivers/gpu/drm/i915/i915_drv.h | 15 ++ drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_context.c | 14 +++-- drivers/gpu/drm/i915/i915_gpu_error.c | 3 ++ drivers/gpu/drm/i915/i915_irq.c | 91 - drivers/gpu/drm/i915/i915_params.c | 6 +-- drivers/gpu/drm/i915/i915_params.h | 2 +- drivers/gpu/drm/i915/i915_pci.c | 5 +- drivers/gpu/drm/i915/intel_lrc.c| 12 + drivers/gpu/drm/i915/intel_lrc.h| 1 + drivers/gpu/drm/i915/intel_uncore.c | 61 +++--- include/uapi/drm/i915_drm.h | 3 +- 14 files changed, 266 insertions(+), 41 deletions(-) Cc: Chris WilsonCc: Mika Kuoppala -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/9] drm/i915: Keep i915_handle_error kerneldoc parameters together
And before the function description. Tidy up from commit 14bb2c11796d70b ("drm/i915: Fix a buch of kerneldoc warnings"), all others kerneldoc blocks look ok. Cc: Tvrtko UrsulinSigned-off-by: Michel Thierry --- drivers/gpu/drm/i915/i915_irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a0e70f5b3aad..77caeeb5ee55 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2703,12 +2703,13 @@ static void i915_clear_error_registers(struct drm_i915_private *dev_priv) * i915_handle_error - handle a gpu error * @dev_priv: i915 device private * @engine_mask: mask representing engines that are hung + * @fmt: Error message format string + * * Do some basic checking of register state at error time and * dump it to the syslog. Also call i915_capture_error_state() to make * sure we get a record and make it available in debugfs. Fire a uevent * so userspace knows something bad happened (should trigger collection * of a ring dump etc.). - * @fmt: Error message format string */ void i915_handle_error(struct drm_i915_private *dev_priv, u32 engine_mask, -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 8/9] drm/i915/tdr: Enable Engine reset and recovery support
From: Arun SiluveryThis feature is made available only from Gen8, for previous gen devices driver uses legacy full gpu reset. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Tomas Elf Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry --- drivers/gpu/drm/i915/i915_params.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index c858c4d50491..fe1cc54e82e3 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -46,7 +46,7 @@ struct i915_params i915 __read_mostly = { .prefault_disable = 0, .load_detect_test = 0, .force_reset_modeset_test = 0, - .reset = 1, + .reset = 2, .error_capture = true, .invert_brightness = 0, .disable_display = 0, @@ -114,7 +114,7 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type, "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); module_param_named_unsafe(reset, i915.reset, int, 0600); -MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset [default], 2=engine reset)"); +MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset, 2=engine reset [default])"); #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) module_param_named(error_capture, i915.error_capture, bool, 0600); -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/9] drm/i915: Update i915.reset to handle engine resets
From: Arun SiluveryIn preparation for engine reset work update this parameter to handle more than one type of reset. Default at the moment is still full gpu reset. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry --- drivers/gpu/drm/i915/i915_params.c | 6 +++--- drivers/gpu/drm/i915/i915_params.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 0e280fbd52f1..c858c4d50491 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -46,7 +46,7 @@ struct i915_params i915 __read_mostly = { .prefault_disable = 0, .load_detect_test = 0, .force_reset_modeset_test = 0, - .reset = true, + .reset = 1, .error_capture = true, .invert_brightness = 0, .disable_display = 0, @@ -113,8 +113,8 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type, "Override/Ignore selection of SDVO panel mode in the VBT " "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); -module_param_named_unsafe(reset, i915.reset, bool, 0600); -MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)"); +module_param_named_unsafe(reset, i915.reset, int, 0600); +MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset [default], 2=engine reset)"); #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) module_param_named(error_capture, i915.error_capture, bool, 0600); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 8e433de04679..da569e20bbec 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -34,6 +34,7 @@ struct i915_params { int lvds_channel_mode; int panel_use_ssc; int vbt_sdvo_panel_type; + int reset; int enable_rc6; int enable_dc; int enable_fbc; @@ -58,7 +59,6 @@ struct i915_params { bool prefault_disable; bool load_detect_test; bool force_reset_modeset_test; - bool reset; bool error_capture; bool disable_display; bool verbose_state_checks; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v3 04/38] lib: Add a simple prime number generator
On Fri, Dec 16, 2016 at 07:25:16PM +, Chris Wilson wrote: > +static void __exit primes_exit(void) > +{ > + const struct primes *p; > + > + mutex_lock(); > + p = rcu_dereference_protected(primes, lockdep_is_held()); > + if (p != _primes) { > + kfree_rcu((struct primes *)p, rcu); > + rcu_assign_pointer(p, _primes); Too much sparse appleasing, too little thinking. It's only the module shutdown path, but we might as well be correct: s/p/primes here. -Chris > -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 09/38] drm: kselftest for drm_mm_reserve_node()
Exercise drm_mm_reserve_node(), check that we can't reserve an already occupied range and that the lists are correct after reserving/removing. v2: Check for invalid node reservation. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 275 +++ 2 files changed, 276 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 0265f09e92fa..693d85677e7f 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -8,3 +8,4 @@ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */ selftest(init, igt_init) selftest(debug, igt_debug) +selftest(reserve, igt_reserve) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 434320061d9e..673519cf41e1 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -80,6 +80,57 @@ static bool assert_one_hole(const struct drm_mm *mm, u64 start, u64 end) return ok; } +static bool assert_continuous(const struct drm_mm *mm, u64 size) +{ + struct drm_mm_node *node, *check, *found; + unsigned long n; + u64 addr; + + if (!assert_no_holes(mm)) + return false; + + n = 0; + addr = 0; + drm_mm_for_each_node(node, mm) { + if (node->start != addr) { + pr_err("node[%ld] list out of order, expected %llx found %llx\n", + n, addr, node->start); + return false; + } + + if (node->size != size) { + pr_err("node[%ld].size incorrect, expected %llx, found %llx\n", + n, size, node->size); + return false; + } + + if (node->hole_follows) { + pr_err("node[%ld] is followed by a hole!\n", n); + return false; + } + + found = NULL; + drm_mm_for_each_node_in_range(check, mm, addr, addr + size) { + if (node != check) { + pr_err("lookup return wrong node, expected start %llx, found %llx\n", + node->start, check->start); + return false; + } + found = check; + } + if (!found) { + pr_err("lookup failed for node %llx + %llx\n", + addr, size); + return false; + } + + addr += size; + n++; + } + + return true; +} + static int igt_init(void *ignored) { const unsigned int size = 4096; @@ -176,6 +227,230 @@ static int igt_debug(void *ignored) return 0; } +static struct drm_mm_node *set_node(struct drm_mm_node *node, + u64 start, u64 size) +{ + node->start = start; + node->size = size; + return node; +} + +static bool expect_reserve_fail(struct drm_mm *mm, struct drm_mm_node *node) +{ + int err; + + err = drm_mm_reserve_node(mm, node); + if (likely(err == -ENOSPC)) + return true; + + if (!err) { + pr_err("impossible reserve succeeded, node %llu + %llu\n", + node->start, node->size); + drm_mm_remove_node(node); + } else { + pr_err("impossible reserve failed with wrong error %d [expected %d], node %llu + %llu\n", + err, -ENOSPC, node->start, node->size); + } + return false; +} + +static bool check_reserve_boundaries(struct drm_mm *mm, +unsigned int count, +u64 size) +{ + const struct boundary { + u64 start, size; + const char *name; + } boundaries[] = { +#define B(st, sz) { (st), (sz), "{ " #st ", " #sz "}" } + B(0, 0), + B(-size, 0), + B(size, 0), + B(size * count, 0), + B(-size, size), + B(-size, -size), + B(-size, 2*size), + B(0, -size), + B(size, -size), + B(count*size, size), + B(count*size, -size), + B(count*size, count*size), + B(count*size, -count*size), + B(count*size, -(count+1)*size), + B((count+1)*size, size), + B((count+1)*size, -size), + B((count+1)*size, -2*size), +#undef B + }; + struct drm_mm_node tmp = {}; + int n; + + for (n
[Intel-gfx] [PATCH v3 37/38] drm: Improve drm_mm search (and fix topdown allocation) with rbtrees
The drm_mm range manager claimed to support top-down insertion, but it was neither searching for the top-most hole that could fit the allocation request nor fitting the request to the hole correctly. In order to search the range efficiently, we create a secondary index for the holes using either their size or their address. This index allows us to find the smallest hole or the hole at the bottom or top of the range efficiently, whilst keeping the hole stack to rapidly service evictions. v2: Search for holes both high and low. Rename flags to mode. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 16 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 20 +- drivers/gpu/drm/armada/armada_gem.c | 4 +- drivers/gpu/drm/drm_mm.c | 511 +++ drivers/gpu/drm/drm_vma_manager.c| 3 +- drivers/gpu/drm/etnaviv/etnaviv_mmu.c| 8 +- drivers/gpu/drm/i915/i915_gem.c | 10 +- drivers/gpu/drm/i915/i915_gem_evict.c| 9 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 39 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 6 +- drivers/gpu/drm/msm/msm_gem.c| 3 +- drivers/gpu/drm/msm/msm_gem_vma.c| 3 +- drivers/gpu/drm/selftests/test-drm_mm.c | 58 ++- drivers/gpu/drm/sis/sis_mm.c | 6 +- drivers/gpu/drm/tegra/gem.c | 4 +- drivers/gpu/drm/ttm/ttm_bo_manager.c | 18 +- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- drivers/gpu/drm/vc4/vc4_hvs.c| 3 +- drivers/gpu/drm/vc4/vc4_plane.c | 6 +- drivers/gpu/drm/via/via_mm.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 10 +- include/drm/drm_mm.h | 135 +++ 23 files changed, 434 insertions(+), 449 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 00f46b0e076d..d841fcb2e709 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -97,8 +97,7 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, { struct amdgpu_gtt_mgr *mgr = man->priv; struct drm_mm_node *node = mem->mm_node; - enum drm_mm_search_flags sflags = DRM_MM_SEARCH_BEST; - enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT; + enum drm_mm_insert_mode mode; unsigned long fpfn, lpfn; int r; @@ -115,15 +114,14 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, else lpfn = man->size; - if (place && place->flags & TTM_PL_FLAG_TOPDOWN) { - sflags = DRM_MM_SEARCH_BELOW; - aflags = DRM_MM_CREATE_TOP; - } + mode = DRM_MM_INSERT_BEST; + if (place && place->mode & TTM_PL_FLAG_TOPDOWN) + mode = DRM_MM_INSERT_HIGH; spin_lock(>lock); - r = drm_mm_insert_node_in_range_generic(>mm, node, mem->num_pages, - mem->page_alignment, 0, - fpfn, lpfn, sflags, aflags); + r = drm_mm_insert_node_in_range(>mm, node, + mem->num_pages, mem->page_alignment, 0, + fpfn, lpfn, mode); spin_unlock(>lock); if (!r) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index d710226a0fff..5f106ad815ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -97,8 +97,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, struct amdgpu_vram_mgr *mgr = man->priv; struct drm_mm *mm = >mm; struct drm_mm_node *nodes; - enum drm_mm_search_flags sflags = DRM_MM_SEARCH_DEFAULT; - enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT; + enum drm_mm_insert_mode mode; unsigned long lpfn, num_nodes, pages_per_node, pages_left; unsigned i; int r; @@ -121,10 +120,9 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, if (!nodes) return -ENOMEM; - if (place->flags & TTM_PL_FLAG_TOPDOWN) { - sflags = DRM_MM_SEARCH_BELOW; - aflags = DRM_MM_CREATE_TOP; - } + mode = DRM_MM_INSERT_BEST; + if (place->flags & TTM_PL_FLAG_TOPDOWN) + mode = DRM_MM_INSERT_HIGH; pages_left = mem->num_pages; @@ -135,13 +133,11 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, if (pages == pages_per_node) alignment = pages_per_node; - else -
[Intel-gfx] [PATCH v3 23/38] drm: Detect overflow in drm_mm_reserve_node()
Protect ourselves from a caller passing in node.start + node.size that will overflow and trick us into reserving that node. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 767cfd05c628..370cb8ee91c9 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -308,10 +308,9 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) u64 hole_start, hole_end; u64 adj_start, adj_end; - if (WARN_ON(node->size == 0)) - return -EINVAL; - end = node->start + node->size; + if (unlikely(end <= node->start)) + return -ENOSPC; /* Find the relevant hole to add our node to */ hole = drm_mm_interval_tree_iter_first(>interval_tree, -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 17/38] drm: kselftest for drm_mm and color adjustment
Check that after applying the driver's color adjustment, fitting of the node and its alignment are still correct. v2: s/no_color_touching/separate_adjacent_colors/ Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 183 +++ 2 files changed, 184 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index cd508e3d6538..ff44f39a1826 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -18,3 +18,4 @@ selftest(align64, igt_align64) selftest(evict, igt_evict) selftest(evict_range, igt_evict_range) selftest(topdown, igt_topdown) +selftest(color, igt_color) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index a499895a76c4..71520a21de8d 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1666,6 +1666,189 @@ static int igt_topdown(void *ignored) return ret; } +static void separate_adjacent_colors(const struct drm_mm_node *node, +unsigned long color, +u64 *start, +u64 *end) +{ + if (node->allocated && node->color != color) + ++*start; + + node = list_next_entry(node, node_list); + if (node->allocated && node->color != color) + --*end; +} + +static bool colors_abutt(const struct drm_mm_node *node) +{ + if (!node->hole_follows && + list_next_entry(node, node_list)->allocated) { + pr_err("colors abutt; %ld [%llx + %llx] is next to %ld [%llx + %llx]!\n", + node->color, node->start, node->size, + list_next_entry(node, node_list)->color, + list_next_entry(node, node_list)->start, + list_next_entry(node, node_list)->size); + return true; + } + + return false; +} + +static int igt_color(void *ignored) +{ + const unsigned int count = min(4096u, max_iterations); + const struct insert_mode *mode; + struct drm_mm mm; + struct drm_mm_node *node, *nn; + unsigned int n; + int ret = -EINVAL, err; + + /* Color adjustment complicates everything. First we just check +* that when we insert a node we apply any color_adjustment callback. +* The callback we use should ensure that there is a gap between +* any two nodes, and so after each insertion we check that those +* holes are inserted and that they are preserved. +*/ + + drm_mm_init(, 0, U64_MAX); + + for (n = 1; n <= count; n++) { + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) { + ret = -ENOMEM; + goto out; + } + + if (!expect_insert(, node, + n, 0, n, + _modes[0])) { + pr_err("insert failed, step %d\n", n); + kfree(node); + goto out; + } + } + + drm_mm_for_each_node_safe(node, nn, ) { + if (node->color != node->size) { + pr_err("invalid color stored: expected %lld, found %ld\n", + node->size, node->color); + + goto out; + } + + drm_mm_remove_node(node); + kfree(node); + } + + /* Now, let's start experimenting with applying a color callback */ + mm.color_adjust = separate_adjacent_colors; + for (mode = insert_modes; mode->name; mode++) { + u64 last; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) { + ret = -ENOMEM; + goto out; + } + + node->size = 1 + 2*count; + node->color = node->size; + + err = drm_mm_reserve_node(, node); + if (err) { + pr_err("initial reserve failed!\n"); + ret = err; + goto out; + } + + last = node->start + node->size; + + for (n = 1; n <= count; n++) { + int rem; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) { + ret = -ENOMEM; + goto out; + } + + node->start = last; + node->size = n + count; + node->color = node->size; + +
[Intel-gfx] [PATCH v3 24/38] drm: Simplify drm_mm_clean()
Since commit ea7b1dd44867 ("drm: mm: track free areas implicitly"), to test whether there are any nodes allocated within the range manager, we merely have to ask whether the node_list is empty. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 19 +-- include/drm/drm_mm.h | 14 +- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 370cb8ee91c9..e0419cf09bbb 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -873,22 +873,6 @@ bool drm_mm_scan_remove_block(struct drm_mm_node *node) EXPORT_SYMBOL(drm_mm_scan_remove_block); /** - * drm_mm_clean - checks whether an allocator is clean - * @mm: drm_mm allocator to check - * - * Returns: - * True if the allocator is completely free, false if there's still a node - * allocated in it. - */ -bool drm_mm_clean(const struct drm_mm *mm) -{ - const struct list_head *head = drm_mm_nodes(mm); - - return (head->next->next == head); -} -EXPORT_SYMBOL(drm_mm_clean); - -/** * drm_mm_init - initialize a drm-mm allocator * @mm: the drm_mm structure to initialize * @start: start of the range managed by @mm @@ -928,10 +912,9 @@ EXPORT_SYMBOL(drm_mm_init); */ void drm_mm_takedown(struct drm_mm *mm) { - if (WARN(!list_empty(drm_mm_nodes(mm)), + if (WARN(!drm_mm_clean(mm), "Memory manager not clean during takedown.\n")) show_leaks(mm); - } EXPORT_SYMBOL(drm_mm_takedown); diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 7eeb98b5bf70..72e0c0ddf8d0 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -342,7 +342,19 @@ void drm_mm_remove_node(struct drm_mm_node *node); void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); void drm_mm_init(struct drm_mm *mm, u64 start, u64 size); void drm_mm_takedown(struct drm_mm *mm); -bool drm_mm_clean(const struct drm_mm *mm); + +/** + * drm_mm_clean - checks whether an allocator is clean + * @mm: drm_mm allocator to check + * + * Returns: + * True if the allocator is completely free, false if there's still a node + * allocated in it. + */ +static inline bool drm_mm_clean(const struct drm_mm *mm) +{ + return list_empty(drm_mm_nodes(mm)); +} struct drm_mm_node * __drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last); -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 25/38] drm: Add asserts to catch overflow in drm_mm_init() and drm_mm_init_scan()
A simple assert to ensure that we don't overflow start + size when initialising the drm_mm, or its scanner. In future, we may want to switch to tracking the value of ranges (rather than size) so that we can cover the full u64, for example like resource tracking. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index e0419cf09bbb..b80305484124 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -729,6 +729,8 @@ void drm_mm_init_scan(struct drm_mm *mm, u64 alignment, unsigned long color) { + DRM_MM_BUG_ON(!size); + mm->scan_color = color; mm->scan_alignment = alignment; mm->scan_size = size; @@ -764,6 +766,9 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, u64 start, u64 end) { + DRM_MM_BUG_ON(start >= end); + DRM_MM_BUG_ON(!size || size > end - start); + mm->scan_color = color; mm->scan_alignment = alignment; mm->scan_size = size; @@ -882,6 +887,8 @@ EXPORT_SYMBOL(drm_mm_scan_remove_block); */ void drm_mm_init(struct drm_mm *mm, u64 start, u64 size) { + DRM_MM_BUG_ON(start + size <= start); + INIT_LIST_HEAD(>hole_stack); mm->scanned_blocks = 0; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 28/38] drm: Unconditionally do the range check in drm_mm_scan_add_block()
Doing the check is trivial (low cost in comparison to overall eviction) and helps simplify the code. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 53 +++ drivers/gpu/drm/i915/i915_gem_evict.c | 10 ++- include/drm/drm_mm.h | 33 ++ 3 files changed, 34 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 459f10ca5714..c68f79149b9a 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -710,46 +710,6 @@ EXPORT_SYMBOL(drm_mm_replace_node); */ /** - * drm_mm_scan_init - initialize lru scanning - * @scan: scan state - * @mm: drm_mm to scan - * @size: size of the allocation - * @alignment: alignment of the allocation - * @color: opaque tag value to use for the allocation - * - * This simply sets up the scanning routines with the parameters for the desired - * hole. Note that there's no need to specify allocation flags, since they only - * change the place a node is allocated from within a suitable hole. - * - * Warning: - * As long as the scan list is non-empty, no other operations than - * adding/removing nodes to/from the scan list are allowed. - */ -void drm_mm_scan_init(struct drm_mm_scan *scan, - struct drm_mm *mm, - u64 size, - u64 alignment, - unsigned long color) -{ - DRM_MM_BUG_ON(!size); - DRM_MM_BUG_ON(mm->scan_active); - - scan->mm = mm; - - scan->color = color; - scan->alignment = alignment; - scan->size = size; - - scan->check_range = 0; - - scan->hit_start = U64_MAX; - scan->hit_end = 0; - - scan->prev_scanned_node = NULL; -} -EXPORT_SYMBOL(drm_mm_scan_init); - -/** * drm_mm_scan_init_with_range - initialize range-restricted lru scanning * @scan: scan state * @mm: drm_mm to scan @@ -788,7 +748,6 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, DRM_MM_BUG_ON(end <= start); scan->range_start = start; scan->range_end = end; - scan->check_range = 1; scan->hit_start = U64_MAX; scan->hit_end = 0; @@ -830,15 +789,11 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, node->node_list.next = >prev_scanned_node->node_list; scan->prev_scanned_node = node; - adj_start = hole_start = drm_mm_hole_node_start(hole); - adj_end = hole_end = drm_mm_hole_node_end(hole); + hole_start = drm_mm_hole_node_start(hole); + hole_end = drm_mm_hole_node_end(hole); - if (scan->check_range) { - if (adj_start < scan->range_start) - adj_start = scan->range_start; - if (adj_end > scan->range_end) - adj_end = scan->range_end; - } + adj_start = max(hole_start, scan->range_start); + adj_end = min(hole_end, scan->range_end); if (mm->color_adjust) mm->color_adjust(hole, scan->color, _start, _end); diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 6db0d73c0aa7..77ded288534b 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -126,13 +126,9 @@ i915_gem_evict_something(struct i915_address_space *vm, * On each list, the oldest objects lie at the HEAD with the freshest * object on the TAIL. */ - if (start != 0 || end != vm->total) { - drm_mm_scan_init_with_range(, >mm, min_size, - alignment, cache_level, - start, end); - } else - drm_mm_scan_init(, >mm, min_size, -alignment, cache_level); + drm_mm_scan_init_with_range(, >mm, + min_size, alignment, cache_level, + start, end); /* Retire before we search the active list. Although we have * reasonable accuracy in our retirement lists, we may have diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index fcad718c5fb4..bae0f10da8e3 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -120,7 +120,6 @@ struct drm_mm_scan { struct drm_mm_node *prev_scanned_node; unsigned long color; - bool check_range : 1; }; /** @@ -387,11 +386,6 @@ __drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last); node__ && node__->start < (end__); \ node__ = list_next_entry(node__, node_list)) -void drm_mm_scan_init(struct drm_mm_scan *scan, - struct drm_mm *mm, - u64 size, - u64 alignment, - unsigned long color); void
[Intel-gfx] [PATCH v3 30/38] drm: Compute tight evictions for drm_mm_scan
Compute the minimal required hole during scan and only evict those nodes that overlap. This enables us to reduce the number of nodes we need to evict to the bare minimum. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c| 60 +++-- drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 2 +- drivers/gpu/drm/i915/i915_gem_evict.c | 3 +- drivers/gpu/drm/selftests/test-drm_mm.c | 10 +++--- include/drm/drm_mm.h| 22 ++-- 5 files changed, 71 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 1b5613bcb35e..189ab84c5a59 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -718,10 +718,10 @@ EXPORT_SYMBOL(drm_mm_replace_node); * @color: opaque tag value to use for the allocation * @start: start of the allowed range for the allocation * @end: end of the allowed range for the allocation + * @flags: flags to specify how the allocation will be performed afterwards * * This simply sets up the scanning routines with the parameters for the desired - * hole. Note that there's no need to specify allocation flags, since they only - * change the place a node is allocated from within a suitable hole. + * hole. * * Warning: * As long as the scan list is non-empty, no other operations than @@ -733,7 +733,8 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, u64 alignment, unsigned long color, u64 start, -u64 end) +u64 end, +unsigned int flags) { DRM_MM_BUG_ON(start >= end); DRM_MM_BUG_ON(!size || size > end - start); @@ -744,6 +745,7 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, scan->color = color; scan->alignment = alignment; scan->size = size; + scan->flags = flags; DRM_MM_BUG_ON(end <= start); scan->range_start = start; @@ -778,7 +780,7 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, DRM_MM_BUG_ON(node->mm != mm); DRM_MM_BUG_ON(!node->allocated); DRM_MM_BUG_ON(node->scanned_block); - node->scanned_block = 1; + node->scanned_block = true; mm->scan_active++; hole = list_prev_entry(node, node_list); @@ -800,15 +802,53 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, adj_start = max(col_start, scan->range_start); adj_end = min(col_end, scan->range_end); + if (adj_end <= adj_start || adj_end - adj_start < scan->size) + return false; + + if (scan->flags == DRM_MM_CREATE_TOP) + adj_start = adj_end - scan->size; + + if (scan->alignment) { + u64 rem; + + div64_u64_rem(adj_start, scan->alignment, ); + if (rem) { + adj_start -= rem; + if (scan->flags != DRM_MM_CREATE_TOP) + adj_start += scan->alignment; + if (adj_start < max(col_start, scan->range_start) || + min(col_end, scan->range_end) - adj_start < scan->size) + return false; + + if (adj_end <= adj_start || + adj_end - adj_start < scan->size) + return false; + } + } - if (check_free_hole(adj_start, adj_end, - scan->size, scan->alignment)) { + if (mm->color_adjust) { + /* If allocations need adjusting due to neighbouring colours, +* we do not have enough information to decide if we need +* to evict nodes on either side of [adj_start, adj_end]. +* What almost works is +* hit_start = adj_start + (hole_start - col_start); +* hit_end = adj_start + scan->size + (hole_end - col_end); +* but because the decision is only made on the final hole, +* we may underestimate the required adjustments for an +* interior allocation. +*/ scan->hit_start = hole_start; scan->hit_end = hole_end; - return true; + } else { + scan->hit_start = adj_start; + scan->hit_end = adj_start + scan->size; } - return false; + DRM_MM_BUG_ON(scan->hit_start >= scan->hit_end); + DRM_MM_BUG_ON(scan->hit_start < hole_start); + DRM_MM_BUG_ON(scan->hit_end > hole_end); + + return true; } EXPORT_SYMBOL(drm_mm_scan_add_block); @@ -836,7 +876,7 @@ bool drm_mm_scan_remove_block(struct drm_mm_scan *scan, DRM_MM_BUG_ON(node->mm != scan->mm);
[Intel-gfx] [PATCH v3 26/38] drm: Extract struct drm_mm_scan from struct drm_mm
The scan state occupies a large proportion of the struct drm_mm and is rarely used and only contains temporary state. That makes it suitable to moving to its struct and onto the stack of the callers. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c| 124 ++-- drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 7 +- drivers/gpu/drm/i915/i915_gem_evict.c | 19 +++-- drivers/gpu/drm/selftests/test-drm_mm.c | 45 ++-- include/drm/drm_mm.h| 43 +++ 5 files changed, 138 insertions(+), 100 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index b80305484124..21bd2e13738b 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -574,7 +574,7 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, u64 adj_end; u64 best_size; - DRM_MM_BUG_ON(mm->scanned_blocks); + DRM_MM_BUG_ON(mm->scan_active); best = NULL; best_size = ~0UL; @@ -618,7 +618,7 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_ u64 adj_end; u64 best_size; - DRM_MM_BUG_ON(mm->scanned_blocks); + DRM_MM_BUG_ON(mm->scan_active); best = NULL; best_size = ~0UL; @@ -693,7 +693,7 @@ EXPORT_SYMBOL(drm_mm_replace_node); * * The DRM range allocator supports this use-case through the scanning * interfaces. First a scan operation needs to be initialized with - * drm_mm_init_scan() or drm_mm_init_scan_with_range(). The driver adds + * drm_mm_scan_init() or drm_mm_scan_init_with_range(). The driver adds * objects to the roaster (probably by walking an LRU list, but this can be * freely implemented) until a suitable hole is found or there's no further * evictable object. @@ -710,7 +710,8 @@ EXPORT_SYMBOL(drm_mm_replace_node); */ /** - * drm_mm_init_scan - initialize lru scanning + * drm_mm_scan_init - initialize lru scanning + * @scan: scan state * @mm: drm_mm to scan * @size: size of the allocation * @alignment: alignment of the allocation @@ -724,26 +725,33 @@ EXPORT_SYMBOL(drm_mm_replace_node); * As long as the scan list is non-empty, no other operations than * adding/removing nodes to/from the scan list are allowed. */ -void drm_mm_init_scan(struct drm_mm *mm, +void drm_mm_scan_init(struct drm_mm_scan *scan, + struct drm_mm *mm, u64 size, u64 alignment, unsigned long color) { DRM_MM_BUG_ON(!size); + DRM_MM_BUG_ON(mm->scan_active); - mm->scan_color = color; - mm->scan_alignment = alignment; - mm->scan_size = size; - mm->scanned_blocks = 0; - mm->scan_hit_start = 0; - mm->scan_hit_end = 0; - mm->scan_check_range = 0; - mm->prev_scanned_node = NULL; + scan->mm = mm; + + scan->color = color; + scan->alignment = alignment; + scan->size = size; + + scan->check_range = 0; + + scan->hit_start = U64_MAX; + scan->hit_end = 0; + + scan->prev_scanned_node = NULL; } -EXPORT_SYMBOL(drm_mm_init_scan); +EXPORT_SYMBOL(drm_mm_scan_init); /** - * drm_mm_init_scan - initialize range-restricted lru scanning + * drm_mm_scan_init_with_range - initialize range-restricted lru scanning + * @scan: scan state * @mm: drm_mm to scan * @size: size of the allocation * @alignment: alignment of the allocation @@ -759,7 +767,8 @@ EXPORT_SYMBOL(drm_mm_init_scan); * As long as the scan list is non-empty, no other operations than * adding/removing nodes to/from the scan list are allowed. */ -void drm_mm_init_scan_with_range(struct drm_mm *mm, +void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, +struct drm_mm *mm, u64 size, u64 alignment, unsigned long color, @@ -768,19 +777,25 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, { DRM_MM_BUG_ON(start >= end); DRM_MM_BUG_ON(!size || size > end - start); + DRM_MM_BUG_ON(mm->scan_active); + + scan->mm = mm; + + scan->color = color; + scan->alignment = alignment; + scan->size = size; + + DRM_MM_BUG_ON(end <= start); + scan->range_start = start; + scan->range_end = end; + scan->check_range = 1; - mm->scan_color = color; - mm->scan_alignment = alignment; - mm->scan_size = size; - mm->scanned_blocks = 0; - mm->scan_hit_start = 0; - mm->scan_hit_end = 0; - mm->scan_start = start; - mm->scan_end = end; - mm->scan_check_range = 1; - mm->prev_scanned_node = NULL; + scan->hit_start = U64_MAX; + scan->hit_end = 0; + + scan->prev_scanned_node = NULL; }
[Intel-gfx] [PATCH v3 32/38] drm: Simplify drm_mm scan-list manipulation
Since we mandate a strict reverse-order of drm_mm_scan_remove_block() after drm_mm_scan_add_block() we can further simplify the list manipulations when generating the temporary scan-hole. v2: Highlight the games being played with the lists to track the scan holes without allocation. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 35 ++- include/drm/drm_mm.h | 7 +-- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 0441d84fba74..ccca8dafb7fc 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -518,9 +518,7 @@ void drm_mm_remove_node(struct drm_mm_node *node) struct drm_mm_node *prev_node; DRM_MM_BUG_ON(!node->allocated); - DRM_MM_BUG_ON(node->scanned_block || - node->scanned_prev_free || - node->scanned_next_free); + DRM_MM_BUG_ON(node->scanned_block); prev_node = list_entry(node->node_list.prev, struct drm_mm_node, node_list); @@ -757,8 +755,6 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, scan->hit_start = U64_MAX; scan->hit_end = 0; - - scan->prev_scanned_node = NULL; } EXPORT_SYMBOL(drm_mm_scan_init_with_range); @@ -787,14 +783,14 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, node->scanned_block = true; mm->scan_active++; + /* Remove this block from the node_list so that we enlarge the hole +* (distance between the end of our previous node and the start of +* or next), without poisoning the link so that we can restore it +* later in drm_mm_scan_remove_block(). +*/ hole = list_prev_entry(node, node_list); - - node->scanned_preceeds_hole = hole->hole_follows; - hole->hole_follows = 1; - list_del(>node_list); - node->node_list.prev = >node_list; - node->node_list.next = >prev_scanned_node->node_list; - scan->prev_scanned_node = node; + DRM_MM_BUG_ON(list_next_entry(hole, node_list) != node); + __list_del_entry(>node_list); hole_start = __drm_mm_hole_node_start(hole); hole_end = __drm_mm_hole_node_end(hole); @@ -888,9 +884,17 @@ bool drm_mm_scan_remove_block(struct drm_mm_scan *scan, DRM_MM_BUG_ON(!node->mm->scan_active); node->mm->scan_active--; + /* During drm_mm_scan_add_block() we decoupled this node leaving +* its pointers intact. Now that the caller is walking back along +* the eviction list we can restore this block into its rightful +* place on the full node_list. To confirm that the caller is walking +* backwards correctly we check that prev_node->next == node->next, +* i.e. both believe the same node should be on the other side of the +* hole. +*/ prev_node = list_prev_entry(node, node_list); - - prev_node->hole_follows = node->scanned_preceeds_hole; + DRM_MM_BUG_ON(list_next_entry(prev_node, node_list) != + list_next_entry(node, node_list)); list_add(>node_list, _node->node_list); return (node->start + node->size > scan->hit_start && @@ -917,9 +921,6 @@ void drm_mm_init(struct drm_mm *mm, u64 start, u64 size) INIT_LIST_HEAD(>head_node.node_list); mm->head_node.allocated = 0; mm->head_node.hole_follows = 1; - mm->head_node.scanned_block = 0; - mm->head_node.scanned_prev_free = 0; - mm->head_node.scanned_next_free = 0; mm->head_node.mm = mm; mm->head_node.start = start + size; mm->head_node.size = start - mm->head_node.start; diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index d6701d56ea74..ff120b7d0f85 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -74,11 +74,8 @@ struct drm_mm_node { struct list_head hole_stack; struct rb_node rb; unsigned hole_follows : 1; - unsigned scanned_block : 1; - unsigned scanned_prev_free : 1; - unsigned scanned_next_free : 1; - unsigned scanned_preceeds_hole : 1; unsigned allocated : 1; + bool scanned_block : 1; unsigned long color; u64 start; u64 size; @@ -118,8 +115,6 @@ struct drm_mm_scan { u64 hit_start; u64 hit_end; - struct drm_mm_node *prev_scanned_node; - unsigned long color; unsigned int flags; }; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 35/38] drm: Apply range restriction after color adjustment when allocation
mm->color_adjust() compares the hole with its neighbouring nodes. They only abutt before we restrict the hole, so we have to apply color_adjust before we apply the range restriction. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 16 ++-- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index c0024719f32b..e279ac7c7aaf 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -410,14 +410,12 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, DRM_MM_BUG_ON(!drm_mm_hole_follows(hole_node) || node->allocated); - if (adj_start < start) - adj_start = start; - if (adj_end > end) - adj_end = end; - if (mm->color_adjust) mm->color_adjust(hole_node, color, _start, _end); + adj_start = max(adj_start, start); + adj_end = min(adj_end, end); + if (flags & DRM_MM_CREATE_TOP) adj_start = adj_end - size; @@ -625,17 +623,15 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_ flags & DRM_MM_SEARCH_BELOW) { u64 hole_size = adj_end - adj_start; - if (adj_start < start) - adj_start = start; - if (adj_end > end) - adj_end = end; - if (mm->color_adjust) { mm->color_adjust(entry, color, _start, _end); if (adj_end <= adj_start) continue; } + adj_start = max(adj_start, start); + adj_end = min(adj_end, end); + if (!check_free_hole(adj_start, adj_end, size, alignment)) continue; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 12/38] drm: kselftest for drm_mm_insert_node_in_range()
Exercise drm_mm_insert_node_in_range(), check that we only allocate from the specified range. v2: Use all allocation flags Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 264 +++ 2 files changed, 265 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index dca726baa65d..92b2c1cb10fa 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -11,3 +11,4 @@ selftest(debug, igt_debug) selftest(reserve, igt_reserve) selftest(insert, igt_insert) selftest(replace, igt_replace) +selftest(insert_range, igt_insert_range) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index fa5b12c57161..cbd4f09e6b2f 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -738,6 +738,270 @@ static int igt_replace(void *ignored) return 0; } +static bool expect_insert_in_range(struct drm_mm *mm, struct drm_mm_node *node, + u64 size, u64 alignment, unsigned long color, + u64 range_start, u64 range_end, + const struct insert_mode *mode) +{ + int err; + + err = drm_mm_insert_node_in_range_generic(mm, node, + size, alignment, color, + range_start, range_end, + mode->search_flags, + mode->create_flags); + if (err) { + pr_err("insert (size=%llu, alignment=%llu, color=%lu, mode=%s) nto range [%llx, %llx] failed with err=%d\n", + size, alignment, color, mode->name, + range_start, range_end, err); + return false; + } + + if (!assert_node(node, mm, size, alignment, color)) { + drm_mm_remove_node(node); + return false; + } + + return true; +} + +static bool expect_insert_in_range_fail(struct drm_mm *mm, + u64 size, + u64 range_start, + u64 range_end) +{ + struct drm_mm_node tmp = {}; + int err; + + err = drm_mm_insert_node_in_range_generic(mm, , + size, 0, 0, + range_start, range_end, + DRM_MM_SEARCH_DEFAULT, + DRM_MM_CREATE_DEFAULT); + if (likely(err == -ENOSPC)) + return true; + + if (!err) { + pr_err("impossible insert succeeded, node %llx + %llu, range [%llx, %llx]\n", + tmp.start, tmp.size, range_start, range_end); + drm_mm_remove_node(); + } else { + pr_err("impossible insert failed with wrong error %d [expected %d], size %llu, range [%llx, %llx]\n", + err, -ENOSPC, size, range_start, range_end); + } + + return false; +} + +static bool assert_contiguous_in_range(struct drm_mm *mm, + u64 size, + u64 start, + u64 end) +{ + struct drm_mm_node *node; + unsigned int n; + + if (!expect_insert_in_range_fail(mm, size, start, end)) + return false; + + n = div64_u64(start + size - 1, size); + drm_mm_for_each_node(node, mm) { + if (node->start < start || node->start + node->size > end) { + pr_err("node %d out of range, address [%llx + %llu], range [%llx, %llx]\n", + n, node->start, node->start + node->size, start, end); + return false; + } + + if (node->start != n * size) { + pr_err("node %d out of order, expected start %llx, found %llx\n", + n, n * size, node->start); + return false; + } + + if (node->size != size) { + pr_err("node %d has wrong size, expected size %llx, found %llx\n", + n, size, node->size); + return false; + } + + if (node->hole_follows && drm_mm_hole_node_end(node) < end) { + pr_err("node %d is followed by a hole!\n", n); + return false; + } + + n++; + } + +
[Intel-gfx] [PATCH v3 16/38] drm: kselftest for drm_mm and top-down allocation
Check that if we request top-down allocation from drm_mm_insert_node() we receive the next available hole from the top. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 119 +++ 2 files changed, 120 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 965aca65c160..cd508e3d6538 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -17,3 +17,4 @@ selftest(align32, igt_align32) selftest(align64, igt_align64) selftest(evict, igt_evict) selftest(evict_range, igt_evict_range) +selftest(topdown, igt_topdown) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index f662d98177ee..a499895a76c4 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1547,6 +1547,125 @@ static int igt_evict_range(void *ignored) return ret; } +static unsigned int node_index(const struct drm_mm_node *node) +{ + return div64_u64(node->start, node->size); +} + +static int igt_topdown(void *ignored) +{ + const struct insert_mode *topdown = _modes[TOPDOWN]; + DRM_RND_STATE(prng, random_seed); + const unsigned int count = 8192; + unsigned int size; + unsigned long *bitmap = NULL; + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int *order, n, m, o = 0; + int ret; + + /* When allocating top-down, we expect to be returned a node +* from a suitable hole at the top of the drm_mm. We check that +* the returned node does match the highest available slot. +*/ + + ret = -ENOMEM; + nodes = vzalloc(count * sizeof(*nodes)); + if (!nodes) + goto err; + + bitmap = kzalloc(count / BITS_PER_LONG * sizeof(unsigned long), +GFP_TEMPORARY); + if (!bitmap) + goto err_nodes; + + order = drm_random_order(count, ); + if (!order) + goto err_bitmap; + + ret = -EINVAL; + for (size = 1; size <= 64; size <<= 1) { + drm_mm_init(, 0, size*count); + for (n = 0; n < count; n++) { + if (!expect_insert(, [n], + size, 0, n, + topdown)) { + pr_err("insert failed, size %u step %d\n", size, n); + goto out; + } + + if (nodes[n].hole_follows) { + pr_err("hole after topdown insert %d, start=%llx\n, size=%u", + n, nodes[n].start, size); + goto out; + } + + if (!assert_one_hole(, 0, size*(count - n - 1))) + goto out; + } + + if (!assert_continuous(, size)) + goto out; + + drm_random_reorder(order, count, ); + for_each_prime_number(n, min(count, max_prime)) { + for (m = 0; m < n; m++) { + node = [order[(o + m) % count]]; + drm_mm_remove_node(node); + __set_bit(node_index(node), bitmap); + } + + for (m = 0; m < n; m++) { + unsigned int last; + + node = [order[(o + m) % count]]; + if (!expect_insert(, node, + size, 0, 0, + topdown)) { + pr_err("insert failed, step %d/%d\n", m, n); + goto out; + } + + if (node->hole_follows) { + pr_err("hole after topdown insert %d/%d, start=%llx\n", + m, n, node->start); + goto out; + } + + last = find_last_bit(bitmap, count); + if (node_index(node) != last) { + pr_err("node %d/%d, size %d, not inserted into upmost hole, expected %d, found %d\n", + m, n, size, last, node_index(node)); + goto out; + } + + __clear_bit(last, bitmap); +
[Intel-gfx] [PATCH v3 07/38] drm: kselftest for drm_mm_init()
Simple first test to just exercise initialisation of struct drm_mm. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 114 +++ 2 files changed, 115 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 1610e0a63a5b..844dd29db540 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -6,3 +6,4 @@ * Tests are executed in order by igt/drm_mm */ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */ +selftest(init, igt_init) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 682f5f86f465..87ad147670da 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -27,6 +27,120 @@ static int igt_sanitycheck(void *ignored) return 0; } +static bool assert_no_holes(const struct drm_mm *mm) +{ + struct drm_mm_node *hole; + u64 hole_start, hole_end; + unsigned long count; + + count = 0; + drm_mm_for_each_hole(hole, mm, hole_start, hole_end) + count++; + if (count) { + pr_err("Expected to find no holes (after reserve), found %lu instead\n", count); + return false; + } + + drm_mm_for_each_node(hole, mm) { + if (hole->hole_follows) { + pr_err("Hole follows node, expected none!\n"); + return false; + } + } + + return true; +} + +static bool assert_one_hole(const struct drm_mm *mm, u64 start, u64 end) +{ + struct drm_mm_node *hole; + u64 hole_start, hole_end; + unsigned long count; + bool ok = true; + + if (end <= start) + return true; + + count = 0; + drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { + if (start != hole_start || end != hole_end) { + if (ok) + pr_err("empty mm has incorrect hole, found (%llx, %llx), expect (%llx, %llx)\n", + hole_start, hole_end, + start, end); + ok = false; + } + count++; + } + if (count != 1) { + pr_err("Expected to find one hole, found %lu instead\n", count); + ok = false; + } + + return ok; +} + +static int igt_init(void *ignored) +{ + const unsigned int size = 4096; + struct drm_mm mm; + struct drm_mm_node tmp; + int ret = -EINVAL; + + /* Start with some simple checks on initialising the struct drm_mm */ + memset(, 0, sizeof(mm)); + if (drm_mm_initialized()) { + pr_err("zeroed mm claims to be initialized\n"); + return ret; + } + + memset(, 0xff, sizeof(mm)); + drm_mm_init(, 0, size); + if (!drm_mm_initialized()) { + pr_err("mm claims not to be initialized\n"); + goto out; + } + + if (!drm_mm_clean()) { + pr_err("mm not empty on creation\n"); + goto out; + } + + /* After creation, it should all be one massive hole */ + if (!assert_one_hole(, 0, size)) { + ret = -EINVAL; + goto out; + } + + memset(, 0, sizeof(tmp)); + tmp.start = 0; + tmp.size = size; + ret = drm_mm_reserve_node(, ); + if (ret) { + pr_err("failed to reserve whole drm_mm\n"); + goto out; + } + + /* After filling the range entirely, there should be no holes */ + if (!assert_no_holes()) { + ret = -EINVAL; + goto out; + } + + /* And then after emptying it again, the massive hole should be back */ + drm_mm_remove_node(); + if (!assert_one_hole(, 0, size)) { + ret = -EINVAL; + goto out; + } + +out: + if (ret) + drm_mm_debug_table(, __func__); + drm_mm_takedown(); + return ret; +} + #include "drm_selftest.c" static int __init test_drm_mm_init(void) -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 21/38] drm: Promote drm_mm alignment to u64
In places (e.g. i915.ko), the alignment is exported to userspace as u64 and there now exists hardware for which we can indeed utilize a u64 alignment. As such, we need to keep 64bit integers throughout when handling alignment. Testcase: igt/drm_mm/align64 Testcase: igt/gem_exec_alignment Signed-off-by: Chris WilsonCc: Joonas Lahtinen Cc: Christian König Reviewed-by: Christian König --- drivers/gpu/drm/drm_mm.c| 37 +++-- drivers/gpu/drm/selftests/test-drm_mm.c | 4 ++-- include/drm/drm_mm.h| 16 +++--- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 9756542abe4c..fd2667052c73 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -93,12 +93,12 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, u64 size, - unsigned alignment, + u64 alignment, unsigned long color, enum drm_mm_search_flags flags); static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, u64 size, - unsigned alignment, + u64 alignment, unsigned long color, u64 start, u64 end, @@ -227,7 +227,7 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node, static void drm_mm_insert_helper(struct drm_mm_node *hole_node, struct drm_mm_node *node, -u64 size, unsigned alignment, +u64 size, u64 alignment, unsigned long color, enum drm_mm_allocator_flags flags) { @@ -246,10 +246,9 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, adj_start = adj_end - size; if (alignment) { - u64 tmp = adj_start; - unsigned rem; + u64 rem; - rem = do_div(tmp, alignment); + div64_u64_rem(adj_start, alignment, ); if (rem) { if (flags & DRM_MM_CREATE_TOP) adj_start -= rem; @@ -376,7 +375,7 @@ EXPORT_SYMBOL(drm_mm_reserve_node); * 0 on success, -ENOSPC if there's no suitable hole. */ int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node, - u64 size, unsigned alignment, + u64 size, u64 alignment, unsigned long color, enum drm_mm_search_flags sflags, enum drm_mm_allocator_flags aflags) @@ -398,7 +397,7 @@ EXPORT_SYMBOL(drm_mm_insert_node_generic); static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, struct drm_mm_node *node, - u64 size, unsigned alignment, + u64 size, u64 alignment, unsigned long color, u64 start, u64 end, enum drm_mm_allocator_flags flags) @@ -423,10 +422,9 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, adj_start = adj_end - size; if (alignment) { - u64 tmp = adj_start; - unsigned rem; + u64 rem; - rem = do_div(tmp, alignment); + div64_u64_rem(adj_start, alignment, ); if (rem) { if (flags & DRM_MM_CREATE_TOP) adj_start -= rem; @@ -482,7 +480,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, * 0 on success, -ENOSPC if there's no suitable hole. */ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node, - u64 size, unsigned alignment, + u64 size, u64 alignment, unsigned long color, u64 start, u64 end, enum drm_mm_search_flags sflags, @@ -548,16 +546,15 @@ void drm_mm_remove_node(struct drm_mm_node *node) } EXPORT_SYMBOL(drm_mm_remove_node); -static int check_free_hole(u64
[Intel-gfx] [PATCH v3 33/38] drm: Apply tight eviction scanning to color_adjust
Using mm->color_adjust makes the eviction scanner much tricker since we don't know the actual neighbours of the target hole until after it is created (after scanning is complete). To work out whether we need to evict the neighbours because they impact upon the hole, we have to then check the hole afterwards - requiring an extra step in the user of the eviction scanner when they apply color_adjust. v2: Massage kerneldoc. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c| 76 ++--- drivers/gpu/drm/i915/i915_gem_evict.c | 7 +++ drivers/gpu/drm/selftests/test-drm_mm.c | 20 - include/drm/drm_mm.h| 1 + 4 files changed, 77 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index ccca8dafb7fc..b59978fe4c6e 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -692,19 +692,21 @@ EXPORT_SYMBOL(drm_mm_replace_node); * The DRM range allocator supports this use-case through the scanning * interfaces. First a scan operation needs to be initialized with * drm_mm_scan_init() or drm_mm_scan_init_with_range(). The driver adds - * objects to the roaster (probably by walking an LRU list, but this can be - * freely implemented) until a suitable hole is found or there's no further - * evictable object. + * objects to the roster (probably by walking an LRU list, but this can be + * freely implemented) (using drm_mm_scan_add_block()) until a suitable hole + * is found or there are no further evictable objects. * * The driver must walk through all objects again in exactly the reverse * order to restore the allocator state. Note that while the allocator is used * in the scan mode no other operation is allowed. * - * Finally the driver evicts all objects selected in the scan. Adding and - * removing an object is O(1), and since freeing a node is also O(1) the overall - * complexity is O(scanned_objects). So like the free stack which needs to be - * walked before a scan operation even begins this is linear in the number of - * objects. It doesn't seem to hurt badly. + * Finally the driver evicts all objects selected (drm_mm_scan_remove_block() + * reported true) in the scan, and any overlapping nodes after color adjustment + * (drm_mm_scan_evict_color()). Adding and removing an object is O(1), and + * since freeing a node is also O(1) the overall complexity is + * O(scanned_objects). So like the free stack which needs to be walked before a + * scan operation even begins this is linear in the number of objects. It + * doesn't seem to hurt too badly. */ /** @@ -829,23 +831,8 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, } } - if (mm->color_adjust) { - /* If allocations need adjusting due to neighbouring colours, -* we do not have enough information to decide if we need -* to evict nodes on either side of [adj_start, adj_end]. -* What almost works is -* hit_start = adj_start + (hole_start - col_start); -* hit_end = adj_start + scan->size + (hole_end - col_end); -* but because the decision is only made on the final hole, -* we may underestimate the required adjustments for an -* interior allocation. -*/ - scan->hit_start = hole_start; - scan->hit_end = hole_end; - } else { - scan->hit_start = adj_start; - scan->hit_end = adj_start + scan->size; - } + scan->hit_start = adj_start; + scan->hit_end = adj_start + scan->size; DRM_MM_BUG_ON(scan->hit_start >= scan->hit_end); DRM_MM_BUG_ON(scan->hit_start < hole_start); @@ -903,6 +890,45 @@ bool drm_mm_scan_remove_block(struct drm_mm_scan *scan, EXPORT_SYMBOL(drm_mm_scan_remove_block); /** + * drm_mm_scan_color_evict - evict overlapping nodes on either side of hole + * @scan: drm_mm scan with target hole + * + * After completing an eviction scan and removing the selected nodes, we may + * need to remove a few more nodes from either side of the target hole if + * mm.color_adjust is being used. + * + * Returns: + * A node to evict, or NULL if there are no overlapping nodes. + */ +struct drm_mm_node *drm_mm_scan_color_evict(struct drm_mm_scan *scan) +{ + struct drm_mm *mm = scan->mm; + struct drm_mm_node *hole; + u64 hole_start, hole_end; + + DRM_MM_BUG_ON(list_empty(>hole_stack)); + + if (!mm->color_adjust) + return NULL; + + hole = list_first_entry(>hole_stack, typeof(*hole), hole_stack); + hole_start = __drm_mm_hole_node_start(hole); + hole_end = __drm_mm_hole_node_end(hole); + + DRM_MM_BUG_ON(hole_start > scan->hit_start); + DRM_MM_BUG_ON(hole_end < scan->hit_end);
[Intel-gfx] [PATCH v3 29/38] drm: Fix application of color vs range restriction when scanning drm_mm
The range restriction should be applied after the color adjustment, or else we may inadvertently apply the color adjustment to the restricted hole (and not against its neighbours). Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index c68f79149b9a..1b5613bcb35e 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -772,6 +772,7 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, struct drm_mm *mm = scan->mm; struct drm_mm_node *hole; u64 hole_start, hole_end; + u64 col_start, col_end; u64 adj_start, adj_end; DRM_MM_BUG_ON(node->mm != mm); @@ -789,14 +790,16 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, node->node_list.next = >prev_scanned_node->node_list; scan->prev_scanned_node = node; - hole_start = drm_mm_hole_node_start(hole); - hole_end = drm_mm_hole_node_end(hole); - - adj_start = max(hole_start, scan->range_start); - adj_end = min(hole_end, scan->range_end); + hole_start = __drm_mm_hole_node_start(hole); + hole_end = __drm_mm_hole_node_end(hole); + col_start = hole_start; + col_end = hole_end; if (mm->color_adjust) - mm->color_adjust(hole, scan->color, _start, _end); + mm->color_adjust(hole, scan->color, _start, _end); + + adj_start = max(col_start, scan->range_start); + adj_end = min(col_end, scan->range_end); if (check_free_hole(adj_start, adj_end, scan->size, scan->alignment)) { -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 13/38] drm: kselftest for drm_mm and alignment
Check that we can request alignment to any power-of-two or prime using a plain drm_mm_node_insert(), and also handle a reasonable selection of primes. v2: Exercise all allocation flags Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 3 + drivers/gpu/drm/selftests/test-drm_mm.c | 103 +++ 2 files changed, 106 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 92b2c1cb10fa..a7a3763f8b20 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -12,3 +12,6 @@ selftest(reserve, igt_reserve) selftest(insert, igt_insert) selftest(replace, igt_replace) selftest(insert_range, igt_insert_range) +selftest(align, igt_align) +selftest(align32, igt_align32) +selftest(align64, igt_align64) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index cbd4f09e6b2f..e1c034ea7e73 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1002,6 +1002,109 @@ static int igt_insert_range(void *ignored) return 0; } +static int igt_align(void *ignored) +{ + const struct insert_mode *mode; + const unsigned int max_count = min(8192u, max_prime); + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int prime; + int ret = -EINVAL; + + /* For each of the possible insertion modes, we pick a few +* arbitrary alignments and check that the inserted node +* meets our requirements. +*/ + + nodes = vzalloc(max_count * sizeof(*nodes)); + if (!nodes) + goto err; + + drm_mm_init(, 1, U64_MAX - 2); + + for (mode = insert_modes; mode->name; mode++) { + unsigned int i = 0; + + for_each_prime_number(prime, max_count) { + u64 size = next_prime_number(prime); + + if (!expect_insert(, [i], + size, prime, i, + mode)) { + pr_err("%s insert failed with alignment=%d", + mode->name, prime); + goto out; + } + + i++; + } + + drm_mm_for_each_node_safe(node, next, ) + drm_mm_remove_node(node); + DRM_MM_BUG_ON(!drm_mm_clean()); + } + + ret = 0; +out: + drm_mm_for_each_node_safe(node, next, ) + drm_mm_remove_node(node); + drm_mm_takedown(); + vfree(nodes); +err: + return ret; +} + +static int igt_align_pot(int max) +{ + struct drm_mm mm; + struct drm_mm_node *node, *next; + int bit; + int ret = -EINVAL; + + /* Check that we can align to the full u64 address space */ + + drm_mm_init(, 1, U64_MAX - 1); + + for (bit = max - 1; bit; bit--) { + u64 align, size; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) { + ret = -ENOMEM; + goto out; + } + + align = BIT_ULL(bit); + size = BIT_ULL(bit-1) + 1; + if (!expect_insert(, node, + size, align, bit, + _modes[0])) { + pr_err("insert failed with alignment=%llx [%d]", + align, bit); + goto out; + } + } + + ret = 0; +out: + drm_mm_for_each_node_safe(node, next, ) { + drm_mm_remove_node(node); + kfree(node); + } + drm_mm_takedown(); + return ret; +} + +static int igt_align32(void *ignored) +{ + return igt_align_pot(32); +} + +static int igt_align64(void *ignored) +{ + return igt_align_pot(64); +} + #include "drm_selftest.c" static int __init test_drm_mm_init(void) -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 19/38] drm: kselftest for drm_mm and restricted color eviction
Check that after applying the driver's color adjustment, restricted eviction scanning find a suitable hole. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 116 ++- 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 0a3a7e32e5f7..6a4575fdc1c0 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -20,3 +20,4 @@ selftest(evict_range, igt_evict_range) selftest(topdown, igt_topdown) selftest(color, igt_color) selftest(color_evict, igt_color_evict) +selftest(color_evict_range, igt_color_evict_range) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 9dd94da15bd5..7e90886f5558 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1850,6 +1850,7 @@ static int igt_color(void *ignored) } static int evict_color(struct drm_mm *mm, + u64 range_start, u64 range_end, struct evict_node *nodes, unsigned int *order, unsigned int count, @@ -1863,7 +1864,9 @@ static int evict_color(struct drm_mm *mm, struct drm_mm_node tmp; int err; - drm_mm_init_scan(mm, size, alignment, color); + drm_mm_init_scan_with_range(mm, + size, alignment, color, + range_start, range_end); if (!evict_nodes(mm, nodes, order, count, _list)) @@ -1881,6 +1884,12 @@ static int evict_color(struct drm_mm *mm, return err; } + if (tmp.start < range_start || tmp.start + tmp.size > range_end) { + pr_err("Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", + tmp.start, tmp.size, range_start, range_end); + err = -EINVAL; + } + if (colors_abutt()) err = -EINVAL; @@ -1949,7 +1958,7 @@ static int igt_color_evict(void *ignored) for (mode = evict_modes; mode->name; mode++) { for (n = 1; n <= total_size; n <<= 1) { drm_random_reorder(order, total_size, ); - err = evict_color(, + err = evict_color(, 0, U64_MAX, nodes, order, total_size, n, 1, color++, mode); @@ -1962,7 +1971,7 @@ static int igt_color_evict(void *ignored) for (n = 1; n < total_size; n <<= 1) { drm_random_reorder(order, total_size, ); - err = evict_color(, + err = evict_color(, 0, U64_MAX, nodes, order, total_size, total_size/2, n, color++, mode); @@ -1979,7 +1988,7 @@ static int igt_color_evict(void *ignored) DRM_MM_BUG_ON(!nsize); drm_random_reorder(order, total_size, ); - err = evict_color(, + err = evict_color(, 0, U64_MAX, nodes, order, total_size, nsize, n, color++, mode); @@ -2005,6 +2014,105 @@ static int igt_color_evict(void *ignored) return ret; } +static int igt_color_evict_range(void *ignored) +{ + DRM_RND_STATE(prng, random_seed); + const unsigned int total_size = 8192; + const unsigned int range_size = total_size / 2; + const unsigned int range_start = total_size / 4; + const unsigned int range_end = range_start + range_size; + const struct insert_mode *mode; + unsigned long color = 0; + struct drm_mm mm; + struct evict_node *nodes; + struct drm_mm_node *node, *next; + unsigned int *order, n; + int ret, err; + + /* Like igt_color_evict(), but limited to small portion of the full +* drm_mm range. +*/ + + ret = -ENOMEM; + nodes = vzalloc(total_size * sizeof(*nodes)); + if (!nodes) + goto err; + + order = drm_random_order(total_size, ); + if (!order) + goto err_nodes; + + ret = -EINVAL; + drm_mm_init(, 0, 2*total_size - 1); + mm.color_adjust = separate_adjacent_colors; + for (n = 0; n < total_size; n++) { + if (!expect_insert(, [n].node, + 1, 0, color++, +
[Intel-gfx] [PATCH v3 31/38] drm: Optimise power-of-two alignments in drm_mm_scan_add_block()
For power-of-two alignments, we can avoid the 64bit divide and do a simple bitwise add instead. v2: s/alignment_mask/remainder_mask/ Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 9 - include/drm/drm_mm.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 189ab84c5a59..0441d84fba74 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -742,8 +742,12 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, scan->mm = mm; + if (alignment <= 1) + alignment = 0; + scan->color = color; scan->alignment = alignment; + scan->remainder_mask = is_power_of_2(alignment) ? alignment - 1 : 0; scan->size = size; scan->flags = flags; @@ -811,7 +815,10 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, if (scan->alignment) { u64 rem; - div64_u64_rem(adj_start, scan->alignment, ); + if (likely(scan->remainder_mask)) + rem = adj_start & scan->remainder_mask; + else + div64_u64_rem(adj_start, scan->alignment, ); if (rem) { adj_start -= rem; if (scan->flags != DRM_MM_CREATE_TOP) diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 606336fc229a..d6701d56ea74 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -110,6 +110,7 @@ struct drm_mm_scan { u64 size; u64 alignment; + u64 remainder_mask; u64 range_start; u64 range_end; -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 14/38] drm: kselftest for drm_mm and eviction
Check that we add arbitrary blocks to the eviction scanner in order to find the first minimal hole that matches our request. v2: Refactor out some common eviction code for later Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 337 +++ 2 files changed, 338 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index a7a3763f8b20..a31b4458c7eb 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -15,3 +15,4 @@ selftest(insert_range, igt_insert_range) selftest(align, igt_align) selftest(align32, igt_align32) selftest(align64, igt_align64) +selftest(evict, igt_evict) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index e1c034ea7e73..10142bc4e07e 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -36,6 +36,10 @@ static const struct insert_mode { [TOPDOWN] = { "top-down", DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP }, [BEST] = { "best", DRM_MM_SEARCH_BEST, DRM_MM_CREATE_DEFAULT }, {} +}, evict_modes[] = { + { "default", DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT }, + { "top-down", DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP }, + {} }; static int igt_sanitycheck(void *ignored) @@ -1105,6 +1109,339 @@ static int igt_align64(void *ignored) return igt_align_pot(64); } +static void show_scan(const struct drm_mm *scan) +{ + pr_info("scan: hit [%llx, %llx], size=%lld, align=%d, color=%ld\n", + scan->scan_hit_start, scan->scan_hit_end, + scan->scan_size, scan->scan_alignment, scan->scan_color); +} + +static void show_holes(const struct drm_mm *mm, int count) +{ + u64 hole_start, hole_end; + struct drm_mm_node *hole; + + drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { + struct drm_mm_node *next = list_next_entry(hole, node_list); + const char *node1 = NULL, *node2 = NULL; + + if (hole->allocated) + node1 = kasprintf(GFP_KERNEL, + "[%llx + %lld, color=%ld], ", + hole->start, hole->size, hole->color); + + if (next->allocated) + node2 = kasprintf(GFP_KERNEL, + ", [%llx + %lld, color=%ld]", + next->start, next->size, next->color); + + pr_info("%sHole [%llx - %llx, size %lld]%s\n", + node1, + hole_start, hole_end, hole_end - hole_start, + node2); + + kfree(node2); + kfree(node1); + + if (!--count) + break; + } +} + +struct evict_node { + struct drm_mm_node node; + struct list_head link; +}; + +static bool evict_nodes(struct drm_mm *mm, + struct evict_node *nodes, + unsigned int *order, + unsigned int count, + struct list_head *evict_list) +{ + struct evict_node *e, *en; + unsigned int i; + + for (i = 0; i < count; i++) { + e = [order ? order[i] : i]; + list_add(>link, evict_list); + if (drm_mm_scan_add_block(>node)) + break; + } + list_for_each_entry_safe(e, en, evict_list, link) { + if (!drm_mm_scan_remove_block(>node)) + list_del(>link); + } + if (list_empty(evict_list)) { + pr_err("Failed to find eviction: size=%lld [avail=%d], align=%d (color=%lu)\n", + mm->scan_size, count, + mm->scan_alignment, + mm->scan_color); + return false; + } + + list_for_each_entry(e, evict_list, link) + drm_mm_remove_node(>node); + + return true; +} + +static bool evict_nothing(struct drm_mm *mm, + unsigned int total_size, + struct evict_node *nodes) +{ + LIST_HEAD(evict_list); + struct evict_node *e; + struct drm_mm_node *node; + unsigned int n; + + drm_mm_init_scan(mm, 1, 0, 0); + for (n = 0; n < total_size; n++) { + e = [n]; + list_add(>link, _list); + drm_mm_scan_add_block(>node); + } + list_for_each_entry(e, _list, link) + drm_mm_scan_remove_block(>node); + + for (n = 0; n < total_size; n++) { + e = [n]; + + if (!drm_mm_node_allocated(>node)) { +
[Intel-gfx] [PATCH v3 15/38] drm: kselftest for drm_mm and range restricted eviction
Check that we add arbitrary blocks to a restrited eviction scanner in order to find the first minimal hole that matches our request. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 113 ++- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index a31b4458c7eb..965aca65c160 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -16,3 +16,4 @@ selftest(align, igt_align) selftest(align32, igt_align32) selftest(align64, igt_align64) selftest(evict, igt_evict) +selftest(evict_range, igt_evict_range) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 10142bc4e07e..f662d98177ee 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1274,6 +1274,7 @@ static bool evict_everything(struct drm_mm *mm, } static int evict_something(struct drm_mm *mm, + u64 range_start, u64 range_end, struct evict_node *nodes, unsigned int *order, unsigned int count, @@ -1286,7 +1287,9 @@ static int evict_something(struct drm_mm *mm, struct drm_mm_node tmp; int err; - drm_mm_init_scan(mm, size, alignment, 0); + drm_mm_init_scan_with_range(mm, + size, alignment, 0, + range_start, range_end); if (!evict_nodes(mm, nodes, order, count, _list)) @@ -1304,6 +1307,12 @@ static int evict_something(struct drm_mm *mm, return err; } + if (tmp.start < range_start || tmp.start + tmp.size > range_end) { + pr_err("Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", + tmp.start, tmp.size, range_start, range_end); + err = -EINVAL; + } + if (!assert_node(, mm, size, alignment, 0) || tmp.hole_follows) { pr_err("Inserted did not fill the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx, hole-follows?=%d\n", tmp.size, size, @@ -1385,7 +1394,7 @@ static int igt_evict(void *ignored) for (mode = evict_modes; mode->name; mode++) { for (n = 1; n <= size; n <<= 1) { drm_random_reorder(order, size, ); - err = evict_something(, + err = evict_something(, 0, U64_MAX, nodes, order, size, n, 1, mode); @@ -1399,7 +1408,7 @@ static int igt_evict(void *ignored) for (n = 1; n < size; n <<= 1) { drm_random_reorder(order, size, ); - err = evict_something(, + err = evict_something(, 0, U64_MAX, nodes, order, size, size/2, n, mode); @@ -1417,7 +1426,7 @@ static int igt_evict(void *ignored) DRM_MM_BUG_ON(!nsize); drm_random_reorder(order, size, ); - err = evict_something(, + err = evict_something(, 0, U64_MAX, nodes, order, size, nsize, n, mode); @@ -1442,6 +1451,102 @@ static int igt_evict(void *ignored) return ret; } +static int igt_evict_range(void *ignored) +{ + DRM_RND_STATE(prng, random_seed); + const unsigned int size = 8192; + const unsigned int range_size = size / 2; + const unsigned int range_start = size / 4; + const unsigned int range_end = range_start + range_size; + const struct insert_mode *mode; + struct drm_mm mm; + struct evict_node *nodes; + struct drm_mm_node *node, *next; + unsigned int *order, n; + int ret, err; + + /* Like igt_evict() but now we are limiting the search to a +* small portion of the full drm_mm. +*/ + + ret = -ENOMEM; + nodes = vzalloc(size * sizeof(*nodes)); + if (!nodes) + goto err; + + order = drm_random_order(size, ); + if (!order) + goto err_nodes; + + ret = -EINVAL; + drm_mm_init(, 0, size); + for (n = 0; n < size; n++) { + err = drm_mm_insert_node(, [n].node, 1, 0, +
[Intel-gfx] [PATCH v3 18/38] drm: kselftest for drm_mm and color eviction
Check that after applying the driver's color adjustment, eviction scanning find a suitable hole. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 156 +++ 2 files changed, 157 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index ff44f39a1826..0a3a7e32e5f7 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -19,3 +19,4 @@ selftest(evict, igt_evict) selftest(evict_range, igt_evict_range) selftest(topdown, igt_topdown) selftest(color, igt_color) +selftest(color_evict, igt_color_evict) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 71520a21de8d..9dd94da15bd5 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1849,6 +1849,162 @@ static int igt_color(void *ignored) return ret; } +static int evict_color(struct drm_mm *mm, + struct evict_node *nodes, + unsigned int *order, + unsigned int count, + unsigned int size, + unsigned int alignment, + unsigned long color, + const struct insert_mode *mode) +{ + LIST_HEAD(evict_list); + struct evict_node *e; + struct drm_mm_node tmp; + int err; + + drm_mm_init_scan(mm, size, alignment, color); + if (!evict_nodes(mm, +nodes, order, count, +_list)) + return -EINVAL; + + memset(, 0, sizeof(tmp)); + err = drm_mm_insert_node_generic(mm, , size, alignment, color, +mode->search_flags, +mode->create_flags); + if (err) { + pr_err("Failed to insert into eviction hole: size=%d, align=%d, color=%lu, err=%d\n", + size, alignment, color, err); + show_scan(mm); + show_holes(mm, 3); + return err; + } + + if (colors_abutt()) + err = -EINVAL; + + if (!assert_node(, mm, size, alignment, color)) { + pr_err("Inserted did not fit the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx\n", + tmp.size, size, + alignment, misalignment(, alignment), tmp.start); + err = -EINVAL; + } + + drm_mm_remove_node(); + if (err) + return err; + + list_for_each_entry(e, _list, link) { + err = drm_mm_reserve_node(mm, >node); + if (err) { + pr_err("Failed to reinsert node after eviction: start=%llx\n", + e->node.start); + return err; + } + } + + return 0; +} + +static int igt_color_evict(void *ignored) +{ + DRM_RND_STATE(prng, random_seed); + const unsigned int total_size = min(8192u, max_iterations); + const struct insert_mode *mode; + unsigned long color = 0; + struct drm_mm mm; + struct evict_node *nodes; + struct drm_mm_node *node, *next; + unsigned int *order, n; + int ret, err; + + /* Check that the drm_mm_scan also honours color adjustment when +* choosing its victims to create a hole. Our color_adjust does not +* allow two nodes to be placed together without an intervening hole +* enlarging the set of victims that must be evicted. +*/ + + ret = -ENOMEM; + nodes = vzalloc(total_size * sizeof(*nodes)); + if (!nodes) + goto err; + + order = drm_random_order(total_size, ); + if (!order) + goto err_nodes; + + ret = -EINVAL; + drm_mm_init(, 0, 2*total_size - 1); + mm.color_adjust = separate_adjacent_colors; + for (n = 0; n < total_size; n++) { + if (!expect_insert(, [n].node, + 1, 0, color++, + _modes[0])) { + pr_err("insert failed, step %d\n", n); + goto out; + } + } + + for (mode = evict_modes; mode->name; mode++) { + for (n = 1; n <= total_size; n <<= 1) { + drm_random_reorder(order, total_size, ); + err = evict_color(, + nodes, order, total_size, + n, 1, color++, + mode); + if (err) { + pr_err("%s evict_color(size=%u) failed\n", +
[Intel-gfx] [PATCH v3 34/38] drm: Wrap drm_mm_node.hole_follows
Insulate users from changed to the internal hole tracking within struct drm_mm_node by using an accessor for hole_follows. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c| 12 ++-- drivers/gpu/drm/i915/i915_vma.c | 4 ++-- drivers/gpu/drm/selftests/test-drm_mm.c | 18 ++ include/drm/drm_mm.h| 22 +++--- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index b59978fe4c6e..c0024719f32b 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -323,7 +323,7 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) } hole = list_last_entry(>node_list, typeof(*hole), node_list); - if (!hole->hole_follows) + if (!drm_mm_hole_follows(hole)) return -ENOSPC; adj_start = hole_start = __drm_mm_hole_node_start(hole); @@ -408,7 +408,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, u64 adj_start = hole_start; u64 adj_end = hole_end; - DRM_MM_BUG_ON(!hole_node->hole_follows || node->allocated); + DRM_MM_BUG_ON(!drm_mm_hole_follows(hole_node) || node->allocated); if (adj_start < start) adj_start = start; @@ -523,16 +523,16 @@ void drm_mm_remove_node(struct drm_mm_node *node) prev_node = list_entry(node->node_list.prev, struct drm_mm_node, node_list); - if (node->hole_follows) { + if (drm_mm_hole_follows(node)) { DRM_MM_BUG_ON(__drm_mm_hole_node_start(node) == __drm_mm_hole_node_end(node)); list_del(>hole_stack); - } else + } else { DRM_MM_BUG_ON(__drm_mm_hole_node_start(node) != __drm_mm_hole_node_end(node)); + } - - if (!prev_node->hole_follows) { + if (!drm_mm_hole_follows(prev_node)) { prev_node->hole_follows = 1; list_add(_node->hole_stack, >hole_stack); } else diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index f709c9b76358..34374c4133b5 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -322,11 +322,11 @@ bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level) GEM_BUG_ON(list_empty(>node_list)); other = list_prev_entry(node, node_list); - if (color_differs(other, cache_level) && !other->hole_follows) + if (color_differs(other, cache_level) && !drm_mm_hole_follows(other)) return false; other = list_next_entry(node, node_list); - if (color_differs(other, cache_level) && !node->hole_follows) + if (color_differs(other, cache_level) && !drm_mm_hole_follows(node)) return false; return true; diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 8b9d8956fb51..989e49e49f1c 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -63,7 +63,7 @@ static bool assert_no_holes(const struct drm_mm *mm) } drm_mm_for_each_node(hole, mm) { - if (hole->hole_follows) { + if (drm_mm_hole_follows(hole)) { pr_err("Hole follows node, expected none!\n"); return false; } @@ -125,7 +125,7 @@ static bool assert_continuous(const struct drm_mm *mm, u64 size) return false; } - if (node->hole_follows) { + if (drm_mm_hole_follows(node)) { pr_err("node[%ld] is followed by a hole!\n", n); return false; } @@ -828,7 +828,8 @@ static bool assert_contiguous_in_range(struct drm_mm *mm, return false; } - if (node->hole_follows && drm_mm_hole_node_end(node) < end) { + if (drm_mm_hole_follows(node) && + drm_mm_hole_node_end(node) < end) { pr_err("node %d is followed by a hole!\n", n); return false; } @@ -1332,11 +1333,12 @@ static int evict_something(struct drm_mm *mm, err = -EINVAL; } - if (!assert_node(, mm, size, alignment, 0) || tmp.hole_follows) { + if (!assert_node(, mm, size, alignment, 0) || + drm_mm_hole_follows()) { pr_err("Inserted did not fill the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx, hole-follows?=%d\n", tmp.size, size, alignment, misalignment(, alignment), - tmp.start, tmp.hole_follows); +
[Intel-gfx] [PATCH v3 36/38] drm: Use drm_mm_insert_node_in_range_generic() for everyone
Remove a superfluous helper as drm_mm_insert_node is equivalent to insert_node_in_range with a range of (0, U64_MAX). Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 166 --- include/drm/drm_mm.h | 90 +++-- 2 files changed, 67 insertions(+), 189 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index e279ac7c7aaf..58a7e3bbe130 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -92,11 +92,6 @@ * some basic allocator dumpers for debugging. */ -static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, - u64 size, - u64 alignment, - unsigned long color, - enum drm_mm_search_flags flags); static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, u64 size, u64 alignment, @@ -230,6 +225,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, struct drm_mm_node *node, u64 size, u64 alignment, unsigned long color, +u64 range_start, u64 range_end, enum drm_mm_allocator_flags flags) { struct drm_mm *mm = hole_node->mm; @@ -238,11 +234,14 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, u64 adj_start = hole_start; u64 adj_end = hole_end; - DRM_MM_BUG_ON(node->allocated); + DRM_MM_BUG_ON(!drm_mm_hole_follows(hole_node) || node->allocated); if (mm->color_adjust) mm->color_adjust(hole_node, color, _start, _end); + adj_start = max(adj_start, range_start); + adj_end = min(adj_end, range_end); + if (flags & DRM_MM_CREATE_TOP) adj_start = adj_end - size; @@ -258,9 +257,6 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, } } - DRM_MM_BUG_ON(adj_start < hole_start); - DRM_MM_BUG_ON(adj_end > hole_end); - if (adj_start == hole_start) { hole_node->hole_follows = 0; list_del(_node->hole_stack); @@ -276,7 +272,10 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, drm_mm_interval_tree_add_node(hole_node, node); + DRM_MM_BUG_ON(node->start < range_start); + DRM_MM_BUG_ON(node->start < adj_start); DRM_MM_BUG_ON(node->start + node->size > adj_end); + DRM_MM_BUG_ON(node->start + node->size > range_end); node->hole_follows = 0; if (__drm_mm_hole_node_start(node) < hole_end) { @@ -360,107 +359,6 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) EXPORT_SYMBOL(drm_mm_reserve_node); /** - * drm_mm_insert_node_generic - search for space and insert @node - * @mm: drm_mm to allocate from - * @node: preallocate node to insert - * @size: size of the allocation - * @alignment: alignment of the allocation - * @color: opaque tag value to use for this node - * @sflags: flags to fine-tune the allocation search - * @aflags: flags to fine-tune the allocation behavior - * - * The preallocated node must be cleared to 0. - * - * Returns: - * 0 on success, -ENOSPC if there's no suitable hole. - */ -int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node, - u64 size, u64 alignment, - unsigned long color, - enum drm_mm_search_flags sflags, - enum drm_mm_allocator_flags aflags) -{ - struct drm_mm_node *hole_node; - - if (WARN_ON(size == 0)) - return -EINVAL; - - hole_node = drm_mm_search_free_generic(mm, size, alignment, - color, sflags); - if (!hole_node) - return -ENOSPC; - - drm_mm_insert_helper(hole_node, node, size, alignment, color, aflags); - return 0; -} -EXPORT_SYMBOL(drm_mm_insert_node_generic); - -static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, - struct drm_mm_node *node, - u64 size, u64 alignment, - unsigned long color, - u64 start, u64 end, - enum drm_mm_allocator_flags flags) -{ - struct drm_mm *mm = hole_node->mm; - u64 hole_start = drm_mm_hole_node_start(hole_node); - u64 hole_end = drm_mm_hole_node_end(hole_node); - u64 adj_start =
[Intel-gfx] [PATCH v3 04/38] lib: Add a simple prime number generator
Prime numbers are interesting for testing components that use multiplies and divides, such as testing DRM's struct drm_mm alignment computations. v2: Move to lib/, add selftest v3: Fix initial constants (exclude 0/1 from being primes) v4: More RCU markup to keep 0day/sparse happy Signed-off-by: Chris WilsonCc: Lukas Wunner --- include/linux/prime_numbers.h | 13 +++ lib/Kconfig | 7 ++ lib/Makefile | 2 + lib/prime_numbers.c | 238 ++ 4 files changed, 260 insertions(+) create mode 100644 include/linux/prime_numbers.h create mode 100644 lib/prime_numbers.c diff --git a/include/linux/prime_numbers.h b/include/linux/prime_numbers.h new file mode 100644 index ..877f6acbd0b6 --- /dev/null +++ b/include/linux/prime_numbers.h @@ -0,0 +1,13 @@ +#ifndef __LINUX_PRIME_NUMBERS_H +#define __LINUX_PRIME_NUMBERS_H + +#include + +bool is_prime_number(unsigned long x); +unsigned long next_prime_number(unsigned long x); + +/* A useful white-lie here is that 1 is prime. */ +#define for_each_prime_number(prime, max) \ + for (prime = 1; prime < (max); prime = next_prime_number(prime)) + +#endif /* !__LINUX_PRIME_NUMBERS_H */ diff --git a/lib/Kconfig b/lib/Kconfig index 260a80e313b9..1788a1f50d28 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -550,4 +550,11 @@ config STACKDEPOT config SBITMAP bool +config PRIME_NUMBERS + tristate "Prime number generator" + default n + help + Provides a helper module to generate prime numbers. Useful for writing + test code, especially when checking multiplication and divison. + endmenu diff --git a/lib/Makefile b/lib/Makefile index 50144a3aeebd..c664143fd917 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -197,6 +197,8 @@ obj-$(CONFIG_ASN1) += asn1_decoder.o obj-$(CONFIG_FONT_SUPPORT) += fonts/ +obj-$(CONFIG_PRIME_NUMBERS) += prime_numbers.o + hostprogs-y:= gen_crc32table clean-files:= crc32table.h diff --git a/lib/prime_numbers.c b/lib/prime_numbers.c new file mode 100644 index ..ec2959520653 --- /dev/null +++ b/lib/prime_numbers.c @@ -0,0 +1,238 @@ +#define pr_fmt(fmt) "prime numbers: " fmt "\n" + +#include +#include +#include +#include + +struct primes { + struct rcu_head rcu; + unsigned long last, sz; + unsigned long primes[]; +}; + +#if BITS_PER_LONG == 64 +static const struct primes small_primes = { + .last = 61, + .sz = 64, + .primes = { 0x28208a20a08a28acUL } +}; +#elif BITS_PER_LONG == 32 +static const struct primes small_primes = { + .last = 31, + .sz = 32, + .primes = { 0xa08a28acUL } +}; +#else +#error "unhandled BITS_PER_LONG" +#endif + +static DEFINE_MUTEX(lock); +static const struct primes __rcu *primes = RCU_INITIALIZER(_primes); + +static unsigned long selftest_max; + +static bool slow_is_prime_number(unsigned long x) +{ + unsigned long y = int_sqrt(x); + + while (y > 1) { + if ((x % y) == 0) + break; + y--; + } + + return y == 1; +} + +static unsigned long slow_next_prime_number(unsigned long x) +{ + for (;;) { + if (slow_is_prime_number(++x)) + return x; + } +} + +static unsigned long mark_multiples(unsigned long x, + unsigned long *p, + unsigned long start, + unsigned long end) +{ + unsigned long m; + + m = 2 * x; + if (m < start) + m = roundup(start, x); + + while (m < end) { + __clear_bit(m, p); + m += x; + } + + return x; +} + +static const struct primes *expand_to_next(unsigned long x) +{ + const struct primes *p; + struct primes *new; + unsigned long sz, y; + + rcu_read_unlock(); + + /* Betrand's Theorem states: +* For all n > 1, there exists a prime p: n < p <= 2*n. +*/ + sz = 2 * x + 1; + if (sz < x) + return NULL; + + sz = round_up(sz, BITS_PER_LONG); + new = kmalloc(sizeof(*new) + sz / sizeof(long), GFP_KERNEL); + if (!new) + return NULL; + + mutex_lock(); + p = rcu_dereference_protected(primes, lockdep_is_held()); + if (x < p->last) { + kfree(new); + goto relock; + } + + /* Where memory permits, track the primes using the +* Sieve of Eratosthenes. +*/ + memcpy(new->primes, p->primes, p->sz / BITS_PER_LONG * sizeof(long)); + memset(new->primes + p->sz / BITS_PER_LONG, + 0xff, (sz - p->sz) / BITS_PER_LONG * sizeof(long)); + for (y = 2UL; y < sz; y = find_next_bit(new->primes, sz, y + 1)) + new->last = mark_multiples(y, new->primes, p->sz, sz); +
[Intel-gfx] [PATCH v3 22/38] drm: Fix kerneldoc for drm_mm_scan_remove_block()
The nodes must be removed in the *reverse* order. This is correct in the overview, but backwards in the function description. Whilst here add Intel's copyright statement and tweak some formatting. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 34 ++ include/drm/drm_mm.h | 19 +-- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index fd2667052c73..767cfd05c628 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -1,6 +1,7 @@ /** * * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA. + * Copyright 2016 Intel Corporation * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -31,9 +32,9 @@ * class implementation for more advanced memory managers. * * Note that the algorithm used is quite simple and there might be substantial - * performance gains if a smarter free list is implemented. Currently it is just an - * unordered stack of free regions. This could easily be improved if an RB-tree - * is used instead. At least if we expect heavy fragmentation. + * performance gains if a smarter free list is implemented. Currently it is + * just an unordered stack of free regions. This could easily be improved if + * an RB-tree is used instead. At least if we expect heavy fragmentation. * * Aligned allocations can also see improvement. * @@ -67,7 +68,7 @@ * where an object needs to be created which exactly matches the firmware's * scanout target. As long as the range is still free it can be inserted anytime * after the allocator is initialized, which helps with avoiding looped - * depencies in the driver load sequence. + * dependencies in the driver load sequence. * * drm_mm maintains a stack of most recently freed holes, which of all * simplistic datastructures seems to be a fairly decent approach to clustering @@ -78,14 +79,14 @@ * * drm_mm supports a few features: Alignment and range restrictions can be * supplied. Further more every _mm_node has a color value (which is just an - * opaqua unsigned long) which in conjunction with a driver callback can be used + * opaque unsigned long) which in conjunction with a driver callback can be used * to implement sophisticated placement restrictions. The i915 DRM driver uses * this to implement guard pages between incompatible caching domains in the * graphics TT. * - * Two behaviors are supported for searching and allocating: bottom-up and top-down. - * The default is bottom-up. Top-down allocation can be used if the memory area - * has different restrictions, or just to reduce fragmentation. + * Two behaviors are supported for searching and allocating: bottom-up and + * top-down. The default is bottom-up. Top-down allocation can be used if the + * memory area has different restrictions, or just to reduce fragmentation. * * Finally iteration helpers to walk all nodes and all holes are provided as are * some basic allocator dumpers for debugging. @@ -510,7 +511,7 @@ EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic); * * This just removes a node from its drm_mm allocator. The node does not need to * be cleared again before it can be re-inserted into this or any other drm_mm - * allocator. It is a bug to call this function on a un-allocated node. + * allocator. It is a bug to call this function on a unallocated node. */ void drm_mm_remove_node(struct drm_mm_node *node) { @@ -689,16 +690,16 @@ EXPORT_SYMBOL(drm_mm_replace_node); * efficient when we simply start to select all objects from the tail of an LRU * until there's a suitable hole: Especially for big objects or nodes that * otherwise have special allocation constraints there's a good chance we evict - * lots of (smaller) objects unecessarily. + * lots of (smaller) objects unnecessarily. * * The DRM range allocator supports this use-case through the scanning * interfaces. First a scan operation needs to be initialized with - * drm_mm_init_scan() or drm_mm_init_scan_with_range(). The the driver adds + * drm_mm_init_scan() or drm_mm_init_scan_with_range(). The driver adds * objects to the roaster (probably by walking an LRU list, but this can be * freely implemented) until a suitable hole is found or there's no further - * evitable object. + * evictable object. * - * The the driver must walk through all objects again in exactly the reverse + * The driver must walk through all objects again in exactly the reverse * order to restore the allocator state. Note that while the allocator is used * in the scan mode no other operation is allowed. * @@ -838,9 +839,10 @@ EXPORT_SYMBOL(drm_mm_scan_add_block); * drm_mm_scan_remove_block - remove a node from the scan list
[Intel-gfx] [PATCH v3 02/38] drm: Use drm_mm_nodes() as shorthand for the list of nodes under struct drm_mm
Fairly commonly we want to inspect the node list on the struct drm_mm, which is buried within an embedded node. Bring it to the surface with a bit of syntatic sugar. Note this was intended to be split from commit ad579002c8ec ("drm: Add drm_mm_for_each_node_safe()") before being applied, but my timing sucks. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen Cc: Daniel Vetter --- drivers/gpu/drm/drm_mm.c | 8 include/drm/drm_mm.h | 18 +++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 7573661302a4..4257c86cc305 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -138,7 +138,7 @@ static void show_leaks(struct drm_mm *mm) if (!buf) return; - list_for_each_entry(node, __drm_mm_nodes(mm), node_list) { + list_for_each_entry(node, drm_mm_nodes(mm), node_list) { struct stack_trace trace = { .entries = entries, .max_entries = STACKDEPTH @@ -320,7 +320,7 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) if (hole->start < end) return -ENOSPC; } else { - hole = list_entry(__drm_mm_nodes(mm), typeof(*hole), node_list); + hole = list_entry(drm_mm_nodes(mm), typeof(*hole), node_list); } hole = list_last_entry(>node_list, typeof(*hole), node_list); @@ -883,7 +883,7 @@ EXPORT_SYMBOL(drm_mm_scan_remove_block); */ bool drm_mm_clean(const struct drm_mm *mm) { - const struct list_head *head = __drm_mm_nodes(mm); + const struct list_head *head = drm_mm_nodes(mm); return (head->next->next == head); } @@ -929,7 +929,7 @@ EXPORT_SYMBOL(drm_mm_init); */ void drm_mm_takedown(struct drm_mm *mm) { - if (WARN(!list_empty(__drm_mm_nodes(mm)), + if (WARN(!list_empty(drm_mm_nodes(mm)), "Memory manager not clean during takedown.\n")) show_leaks(mm); diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 5c7f15875b6a..f6a68ed5ecaf 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -180,7 +180,19 @@ static inline u64 drm_mm_hole_node_end(const struct drm_mm_node *hole_node) return __drm_mm_hole_node_end(hole_node); } -#define __drm_mm_nodes(mm) (&(mm)->head_node.node_list) +/** + * drm_mm_nodes - list of nodes under the drm_mm range manager + * @mm: the struct drm_mm range manger + * + * As the drm_mm range manager hides its node_list deep with its + * structure, extracting it looks painful and repetitive. This is + * not expected to be used outside of the drm_mm_for_each_node() + * macros and similar internal functions. + * + * Returns: + * The node list, may be empty. + */ +#define drm_mm_nodes(mm) (&(mm)->head_node.node_list) /** * drm_mm_for_each_node - iterator to walk over all allocated nodes @@ -191,7 +203,7 @@ static inline u64 drm_mm_hole_node_end(const struct drm_mm_node *hole_node) * with list_for_each, so not save against removal of elements. */ #define drm_mm_for_each_node(entry, mm) \ - list_for_each_entry(entry, __drm_mm_nodes(mm), node_list) + list_for_each_entry(entry, drm_mm_nodes(mm), node_list) /** * drm_mm_for_each_node_safe - iterator to walk over all allocated nodes @@ -203,7 +215,7 @@ static inline u64 drm_mm_hole_node_end(const struct drm_mm_node *hole_node) * with list_for_each_safe, so save against removal of elements. */ #define drm_mm_for_each_node_safe(entry, next, mm) \ - list_for_each_entry_safe(entry, next, __drm_mm_nodes(mm), node_list) + list_for_each_entry_safe(entry, next, drm_mm_nodes(mm), node_list) #define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \ for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \ -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 11/38] drm: kselftest for drm_mm_replace_node()
Reuse drm_mm_insert_node() with a temporary node to exercise drm_mm_replace_node(). We use the previous test in order to exercise the various lists following replacement. v2: Check that we copy across the important (user) details of the node. The internal details (such as lists and hole tracking) we hope to detect errors by exercise. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 65 +--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 727c6d7255e0..dca726baa65d 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -10,3 +10,4 @@ selftest(init, igt_init) selftest(debug, igt_debug) selftest(reserve, igt_reserve) selftest(insert, igt_insert) +selftest(replace, igt_replace) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 2d78a5a0f98c..fa5b12c57161 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -554,7 +554,7 @@ static bool expect_insert_fail(struct drm_mm *mm, u64 size) return false; } -static int __igt_insert(unsigned int count, u64 size) +static int __igt_insert(unsigned int count, u64 size, bool replace) { DRM_RND_STATE(prng, random_seed); const struct insert_mode *mode; @@ -569,7 +569,7 @@ static int __igt_insert(unsigned int count, u64 size) DRM_MM_BUG_ON(!size); ret = -ENOMEM; - nodes = vzalloc(count * sizeof(*nodes)); + nodes = vmalloc(count * sizeof(*nodes)); if (!nodes) goto err; @@ -582,11 +582,37 @@ static int __igt_insert(unsigned int count, u64 size) for (mode = insert_modes; mode->name; mode++) { for (n = 0; n < count; n++) { - if (!expect_insert(, [n], size, 0, n, mode)) { + struct drm_mm_node tmp; + + node = replace ? : [n]; + memset(node, 0, sizeof(*node)); + if (!expect_insert(, node, size, 0, n, mode)) { pr_err("%s insert failed, size %llu step %d\n", mode->name, size, n); goto out; } + + if (replace) { + drm_mm_replace_node(, [n]); + if (drm_mm_node_allocated()) { + pr_err("replaced old-node still allocated! step %d\n", + n); + goto out; + } + + if (!assert_node([n], , size, 0, n)) { + pr_err("replaced node did not inherit parameters, size %llu step %d\n", + size, n); + goto out; + } + + if (tmp.start != nodes[n].start) { + pr_err("replaced node mismatch location expected [%llx + %llx], found [%llx + %llx]\n", + tmp.start, size, + nodes[n].start, nodes[n].size); + goto out; + } + } } /* After random insertion the nodes should be in order */ @@ -669,17 +695,44 @@ static int igt_insert(void *ignored) for_each_prime_number(n, 54) { u64 size = BIT_ULL(n); - ret = __igt_insert(count, size - 1); + ret = __igt_insert(count, size - 1, false); if (ret) return ret; - ret = __igt_insert(count, size); + ret = __igt_insert(count, size, false); if (ret) return ret; - ret = __igt_insert(count, size + 1); + ret = __igt_insert(count, size + 1, false); + } + + return 0; +} + +static int igt_replace(void *ignored) +{ + const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); + unsigned int n; + int ret; + + /* Reuse igt_insert to exercise replacement by inserting a dummy node, +* then replacing it with the intended node. We want to check that +* the tree is intact and all the information we need is carried +* across to the target node. +*/ + + for_each_prime_number(n, 54) { + u64 size = BIT_ULL(n); + +
[Intel-gfx] [PATCH v3 20/38] drm/i915: Build DRM range manager selftests for CI
Build the struct drm_mm selftests so that we can trivially run them within our CI. "Enable debug, become developer." - Joonas Lahtinen Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/Kconfig.debug | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 597648c7a645..598551dbf62c 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -24,6 +24,7 @@ config DRM_I915_DEBUG select X86_MSR # used by igt/pm_rpm select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks) select DRM_DEBUG_MM if DRM=y + select DRM_DEBUG_MM_SELFTEST select DRM_I915_SW_FENCE_DEBUG_OBJECTS default n help -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 10/38] drm: kselftest for drm_mm_insert_node()
Exercise drm_mm_insert_node(), check that we can't overfill a range and that the lists are correct after reserving/removing. v2: Extract helpers for the repeated tests v3: Iterate over all allocation flags Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 234 +++ 2 files changed, 235 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 693d85677e7f..727c6d7255e0 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -9,3 +9,4 @@ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */ selftest(init, igt_init) selftest(debug, igt_debug) selftest(reserve, igt_reserve) +selftest(insert, igt_insert) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 673519cf41e1..2d78a5a0f98c 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -21,6 +21,23 @@ static unsigned int random_seed; static unsigned int max_iterations = 8192; static unsigned int max_prime = 128; +enum { + DEFAULT, + TOPDOWN, + BEST, +}; + +static const struct insert_mode { + const char *name; + unsigned int search_flags; + unsigned int create_flags; +} insert_modes[] = { + [DEFAULT] = { "default", DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT }, + [TOPDOWN] = { "top-down", DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP }, + [BEST] = { "best", DRM_MM_SEARCH_BEST, DRM_MM_CREATE_DEFAULT }, + {} +}; + static int igt_sanitycheck(void *ignored) { pr_info("%s - ok!\n", __func__); @@ -131,6 +148,48 @@ static bool assert_continuous(const struct drm_mm *mm, u64 size) return true; } +static u64 misalignment(struct drm_mm_node *node, u64 alignment) +{ + u64 rem; + + if (!alignment) + return 0; + + div64_u64_rem(node->start, alignment, ); + return rem; +} + +static bool assert_node(struct drm_mm_node *node, struct drm_mm *mm, + u64 size, u64 alignment, unsigned long color) +{ + bool ok = true; + + if (!drm_mm_node_allocated(node) || node->mm != mm) { + pr_err("node not allocated\n"); + ok = false; + } + + if (node->size != size) { + pr_err("node has wrong size, found %llu, expected %llu\n", + node->size, size); + ok = false; + } + + if (misalignment(node, alignment)) { + pr_err("node is misalinged, start %llx rem %llu, expected alignment %llu\n", + node->start, misalignment(node, alignment), alignment); + ok = false; + } + + if (node->color != color) { + pr_err("node has wrong color, found %lu, expected %lu\n", + node->color, color); + ok = false; + } + + return ok; +} + static int igt_init(void *ignored) { const unsigned int size = 4096; @@ -451,6 +510,181 @@ static int igt_reserve(void *ignored) return 0; } +static bool expect_insert(struct drm_mm *mm, struct drm_mm_node *node, + u64 size, u64 alignment, unsigned long color, + const struct insert_mode *mode) +{ + int err; + + err = drm_mm_insert_node_generic(mm, node, +size, alignment, color, +mode->search_flags, +mode->create_flags); + if (err) { + pr_err("insert (size=%llu, alignment=%llu, color=%lu, mode=%s) failed with err=%d\n", + size, alignment, color, mode->name, err); + return false; + } + + if (!assert_node(node, mm, size, alignment, color)) { + drm_mm_remove_node(node); + return false; + } + + return true; +} + +static bool expect_insert_fail(struct drm_mm *mm, u64 size) +{ + struct drm_mm_node tmp = {}; + int err; + + err = drm_mm_insert_node(mm, , size, 0, DRM_MM_SEARCH_DEFAULT); + if (likely(err == -ENOSPC)) + return true; + + if (!err) { + pr_err("impossible insert succeeded, node %llu + %llu\n", + tmp.start, tmp.size); + drm_mm_remove_node(); + } else { + pr_err("impossible insert failed with wrong error %d [expected %d], size %llu\n", + err, -ENOSPC, size); + } + return false; +} + +static int __igt_insert(unsigned int count, u64 size) +{ + DRM_RND_STATE(prng, random_seed); + const struct insert_mode *mode; + struct
[Intel-gfx] [PATCH v3 06/38] drm: Add some kselftests for the DRM range manager (struct drm_mm)
First we introduce a smattering of infrastructure for writing selftests. The idea is that we have a test module that exercises a particular portion of the exported API, and that module provides a set of tests that can either be run as an ensemble via kselftest or individually via an igt harness (in this case igt/drm_mm). To accommodate selecting individual tests, we export a boolean parameter to control selection of each test - that is hidden inside a bunch of reusable boilerplate macros to keep writing the tests simple. v2: Choose a random random_seed unless one is specified by the user. v3: More parameters to control max_iterations and max_prime of the tests. Testcase: igt/drm_mm Signed-off-by: Chris WilsonAcked-by: Christian König Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/Kconfig | 15 drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/selftests/drm_mm_selftests.h | 8 ++ drivers/gpu/drm/selftests/drm_selftest.c | 109 ++ drivers/gpu/drm/selftests/drm_selftest.h | 41 ++ drivers/gpu/drm/selftests/test-drm_mm.c | 58 ++ tools/testing/selftests/drivers/gpu/drm_mm.sh | 15 7 files changed, 247 insertions(+) create mode 100644 drivers/gpu/drm/selftests/drm_mm_selftests.h create mode 100644 drivers/gpu/drm/selftests/drm_selftest.c create mode 100644 drivers/gpu/drm/selftests/drm_selftest.h create mode 100644 drivers/gpu/drm/selftests/test-drm_mm.c create mode 100755 tools/testing/selftests/drivers/gpu/drm_mm.sh diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 45a1c7468e88..29146fa83001 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -48,6 +48,21 @@ config DRM_DEBUG_MM If in doubt, say "N". +config DRM_DEBUG_MM_SELFTEST + tristate "kselftests for DRM range manager (struct drm_mm)" + depends on DRM + depends on DEBUG_KERNEL + select PRIME_NUMBERS + select DRM_LIB_RANDOM + default n + help + This option provides a kernel module that can be used to test + the DRM range manager (drm_mm) and its API. This option is not + useful for distributions or general kernels, but only for kernel + developers working on DRM and associated drivers. + + If in doubt, say "N". + config DRM_KMS_HELPER tristate depends on DRM diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 6bb416360ae4..c0d1aed8588b 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -38,6 +38,7 @@ drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o +obj-$(CONFIG_DRM_DEBUG_MM_SELFTEST) += selftests/test-drm_mm.o CFLAGS_drm_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h new file mode 100644 index ..1610e0a63a5b --- /dev/null +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -0,0 +1,8 @@ +/* List each unit test as selftest(name, function) + * + * The name is used as both an enum and expanded as igt__name to create + * a module parameter. It must be unique and legal for a C identifier. + * + * Tests are executed in order by igt/drm_mm + */ +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */ diff --git a/drivers/gpu/drm/selftests/drm_selftest.c b/drivers/gpu/drm/selftests/drm_selftest.c new file mode 100644 index ..e29ed9faef5b --- /dev/null +++ b/drivers/gpu/drm/selftests/drm_selftest.c @@ -0,0 +1,109 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +
[Intel-gfx] [PATCH v3 05/38] drm: Add a simple generator of random permutations
When testing, we want a random but yet reproducible order in which to process elements. Here we create an array which is a random (using the Tausworthe PRNG) permutation of the order in which to execute. Note these are simple helpers intended to be merged upstream in lib/ v2: Tidier code by David Herrmann v3: Add reminder that this code is intended to be temporary, with at least the bulk of the prandom changes going to lib/ Signed-off-by: Chris WilsonCc: Joonas Lahtinen Cc: David Herrmann Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/Kconfig | 4 drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/lib/drm_random.c | 41 drivers/gpu/drm/lib/drm_random.h | 25 4 files changed, 71 insertions(+) create mode 100644 drivers/gpu/drm/lib/drm_random.c create mode 100644 drivers/gpu/drm/lib/drm_random.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ebfe8404c25f..45a1c7468e88 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -321,3 +321,7 @@ config DRM_SAVAGE chipset. If M is selected the module will be called savage. endif # DRM_LEGACY + +config DRM_LIB_RANDOM + bool + default n diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index b9ae4280de9d..6bb416360ae4 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -18,6 +18,7 @@ drm-y :=drm_auth.o drm_bufs.o drm_cache.o \ drm_plane.o drm_color_mgmt.o drm_print.o \ drm_dumb_buffers.o drm_mode_config.o +drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o drm-$(CONFIG_PCI) += ati_pcigart.o diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c new file mode 100644 index ..7b12a68c3b54 --- /dev/null +++ b/drivers/gpu/drm/lib/drm_random.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +#include "drm_random.h" + +static inline u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state) +{ + return upper_32_bits((u64)prandom_u32_state(state) * ep_ro); +} + +void drm_random_reorder(unsigned int *order, unsigned int count, + struct rnd_state *state) +{ + unsigned int i, j; + + for (i = 0; i < count; ++i) { + BUILD_BUG_ON(sizeof(unsigned int) > sizeof(u32)); + j = drm_prandom_u32_max_state(count, state); + swap(order[i], order[j]); + } +} +EXPORT_SYMBOL(drm_random_reorder); + +unsigned int *drm_random_order(unsigned int count, struct rnd_state *state) +{ + unsigned int *order, i; + + order = kmalloc_array(count, sizeof(*order), GFP_TEMPORARY); + if (!order) + return order; + + for (i = 0; i < count; i++) + order[i] = i; + + drm_random_reorder(order, count, state); + return order; +} +EXPORT_SYMBOL(drm_random_order); diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/drm/lib/drm_random.h new file mode 100644 index ..a78644bea7f9 --- /dev/null +++ b/drivers/gpu/drm/lib/drm_random.h @@ -0,0 +1,25 @@ +#ifndef __DRM_RANDOM_H__ +#define __DRM_RANDOM_H__ + +/* This is a temporary home for a couple of utility functions that should + * be transposed to lib/ at the earliest convenience. + */ + +#include + +#define DRM_RND_STATE_INITIALIZER(seed__) ({ \ + struct rnd_state state__; \ + prandom_seed_state(__, (seed__)); \ + state__;\ +}) + +#define DRM_RND_STATE(name__, seed__) \ + struct rnd_state name__ = DRM_RND_STATE_INITIALIZER(seed__) + +unsigned int *drm_random_order(unsigned int count, + struct rnd_state *state); +void drm_random_reorder(unsigned int *order, + unsigned int count, + struct rnd_state *state); + +#endif /* !__DRM_RANDOM_H__ */ -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 38/38] drm: kselftest for drm_mm and bottom-up allocation
Check that if we request bottom-up allocation from drm_mm_insert_node() we receive the next available hole from the bottom. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 100 +++ 2 files changed, 101 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 6a4575fdc1c0..37bbdac52896 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -17,6 +17,7 @@ selftest(align32, igt_align32) selftest(align64, igt_align64) selftest(evict, igt_evict) selftest(evict_range, igt_evict_range) +selftest(bottomup, igt_bottomup) selftest(topdown, igt_topdown) selftest(color, igt_color) selftest(color_evict, igt_color_evict) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 26e7001c846d..52a1a1d0ba7c 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -1682,6 +1682,106 @@ static int igt_topdown(void *ignored) return ret; } +static int igt_bottomup(void *ignored) +{ + const struct insert_mode *bottomup = _modes[BOTTOMUP]; + DRM_RND_STATE(prng, random_seed); + const unsigned int count = 8192; + unsigned int size; + unsigned long *bitmap; + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int *order, n, m, o = 0; + int ret; + + /* Like igt_topdown, but instead of searching for the last hole, +* we search for the first. +*/ + + ret = -ENOMEM; + nodes = vzalloc(count * sizeof(*nodes)); + if (!nodes) + goto err; + + bitmap = kzalloc(count / BITS_PER_LONG * sizeof(unsigned long), +GFP_TEMPORARY); + if (!bitmap) + goto err_nodes; + + order = drm_random_order(count, ); + if (!order) + goto err_bitmap; + + ret = -EINVAL; + for (size = 1; size <= 64; size <<= 1) { + drm_mm_init(, 0, size*count); + for (n = 0; n < count; n++) { + if (!expect_insert(, [n], + size, 0, n, + bottomup)) { + pr_err("bottomup insert failed, size %u step %d\n", size, n); + goto out; + } + + if (!assert_one_hole(, size*(n + 1), size*count)) + goto out; + } + + if (!assert_continuous(, size)) + goto out; + + drm_random_reorder(order, count, ); + for_each_prime_number(n, min(count, max_prime)) { + for (m = 0; m < n; m++) { + node = [order[(o + m) % count]]; + drm_mm_remove_node(node); + __set_bit(node_index(node), bitmap); + } + + for (m = 0; m < n; m++) { + unsigned int first; + + node = [order[(o + m) % count]]; + if (!expect_insert(, node, + size, 0, 0, + bottomup)) { + pr_err("insert failed, step %d/%d\n", m, n); + goto out; + } + + first = find_first_bit(bitmap, count); + if (node_index(node) != first) { + pr_err("node %d/%d not inserted into bottom hole, expected %d, found %d\n", + m, n, first, node_index(node)); + goto out; + } + __clear_bit(first, bitmap); + } + + DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count); + + o += n; + } + + drm_mm_for_each_node_safe(node, next, ) + drm_mm_remove_node(node); + DRM_MM_BUG_ON(!drm_mm_clean()); + } + + ret = 0; +out: + drm_mm_for_each_node_safe(node, next, ) + drm_mm_remove_node(node); + drm_mm_takedown(); + kfree(order); +err_bitmap: + kfree(bitmap); +err_nodes: + vfree(nodes); +err: + return ret; +} + static void separate_adjacent_colors(const struct drm_mm_node *node, unsigned long color,
[Intel-gfx] [PATCH v3 01/38] drm/i915: Use the MRU stack search after evicting
When we evict from the GTT to make room for an object, the hole we create is put onto the MRU stack inside the drm_mm range manager. On the next search pass, we can speed up a PIN_HIGH allocation by referencing that stack for the new hole. v2: Pull together the 3 identical implements (ahem, a couple were outdated) into a common routine for allocating a node and evicting as necessary. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gvt/aperture_gm.c | 33 +--- drivers/gpu/drm/i915/i915_gem_gtt.c| 72 -- drivers/gpu/drm/i915/i915_gem_gtt.h| 5 +++ drivers/gpu/drm/i915/i915_vma.c| 40 ++- 4 files changed, 70 insertions(+), 80 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index 7d33b607bc89..1bb7a5b80d47 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -48,47 +48,34 @@ static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm) { struct intel_gvt *gvt = vgpu->gvt; struct drm_i915_private *dev_priv = gvt->dev_priv; - u32 alloc_flag, search_flag; + unsigned int flags; u64 start, end, size; struct drm_mm_node *node; - int retried = 0; int ret; if (high_gm) { - search_flag = DRM_MM_SEARCH_BELOW; - alloc_flag = DRM_MM_CREATE_TOP; node = >gm.high_gm_node; size = vgpu_hidden_sz(vgpu); start = gvt_hidden_gmadr_base(gvt); end = gvt_hidden_gmadr_end(gvt); + flags = PIN_HIGH; } else { - search_flag = DRM_MM_SEARCH_DEFAULT; - alloc_flag = DRM_MM_CREATE_DEFAULT; node = >gm.low_gm_node; size = vgpu_aperture_sz(vgpu); start = gvt_aperture_gmadr_base(gvt); end = gvt_aperture_gmadr_end(gvt); + flags = PIN_MAPPABLE; } mutex_lock(_priv->drm.struct_mutex); -search_again: - ret = drm_mm_insert_node_in_range_generic(_priv->ggtt.base.mm, - node, size, 4096, - I915_COLOR_UNEVICTABLE, - start, end, search_flag, - alloc_flag); - if (ret) { - ret = i915_gem_evict_something(_priv->ggtt.base, - size, 4096, - I915_COLOR_UNEVICTABLE, - start, end, 0); - if (ret == 0 && ++retried < 3) - goto search_again; - - gvt_err("fail to alloc %s gm space from host, retried %d\n", - high_gm ? "high" : "low", retried); - } + ret = i915_gem_gtt_insert(_priv->ggtt.base, node, + size, 4096, I915_COLOR_UNEVICTABLE, + start, end, flags); mutex_unlock(_priv->drm.struct_mutex); + if (ret) + gvt_err("fail to alloc %s gm space from host\n", + high_gm ? "high" : "low"); + return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2083c899ab78..97fd66e4e3d0 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2056,7 +2056,6 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt) struct i915_address_space *vm = >base; struct drm_i915_private *dev_priv = ppgtt->base.i915; struct i915_ggtt *ggtt = _priv->ggtt; - bool retried = false; int ret; /* PPGTT PDEs reside in the GGTT and consists of 512 entries. The @@ -2069,29 +2068,14 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt) if (ret) return ret; -alloc: - ret = drm_mm_insert_node_in_range_generic(>base.mm, >node, - GEN6_PD_SIZE, GEN6_PD_ALIGN, - I915_COLOR_UNEVICTABLE, - 0, ggtt->base.total, - DRM_MM_TOPDOWN); - if (ret == -ENOSPC && !retried) { - ret = i915_gem_evict_something(>base, - GEN6_PD_SIZE, GEN6_PD_ALIGN, - I915_COLOR_UNEVICTABLE, - 0, ggtt->base.total, - 0); - if (ret) - goto err_out; - - retried = true; -
[Intel-gfx] [PATCH v3 08/38] drm: kselftest for drm_mm_debug()
Simple test to just exercise calling the debug dumper on the drm_mm. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/selftests/drm_mm_selftests.h | 1 + drivers/gpu/drm/selftests/test-drm_mm.c | 35 2 files changed, 36 insertions(+) diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h index 844dd29db540..0265f09e92fa 100644 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ b/drivers/gpu/drm/selftests/drm_mm_selftests.h @@ -7,3 +7,4 @@ */ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */ selftest(init, igt_init) +selftest(debug, igt_debug) diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 87ad147670da..434320061d9e 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -141,6 +141,41 @@ static int igt_init(void *ignored) return ret; } +static int igt_debug(void *ignored) +{ + struct drm_mm mm; + struct drm_mm_node nodes[2]; + int ret; + + /* Create a small drm_mm with a couple of nodes and a few holes, and +* check that the debug iterator doesn't explode over a trivial drm_mm. +*/ + + drm_mm_init(, 0, 4096); + + memset(nodes, 0, sizeof(nodes)); + nodes[0].start = 512; + nodes[0].size = 1024; + ret = drm_mm_reserve_node(, [0]); + if (ret) { + pr_err("failed to reserve node[0] {start=%lld, size=%lld)\n", + nodes[0].start, nodes[0].size); + return ret; + } + + nodes[1].size = 1024; + nodes[1].start = 4096 - 512 - nodes[1].size; + ret = drm_mm_reserve_node(, [1]); + if (ret) { + pr_err("failed to reserve node[1] {start=%lld, size=%lld)\n", + nodes[1].start, nodes[1].size); + return ret; + } + + drm_mm_debug_table(, __func__); + return 0; +} + #include "drm_selftest.c" static int __init test_drm_mm_init(void) -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 03/38] drm: Compile time enabling for asserts in drm_mm
Use CONFIG_DRM_DEBUG_MM to conditionally enable the internal and validation checking using BUG_ON. Ideally these paths should all be exercised by CI selftests (with the asserts enabled). Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 45 +++-- include/drm/drm_mm.h | 8 +++- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 4257c86cc305..9756542abe4c 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -237,7 +237,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, u64 adj_start = hole_start; u64 adj_end = hole_end; - BUG_ON(node->allocated); + DRM_MM_BUG_ON(node->allocated); if (mm->color_adjust) mm->color_adjust(hole_node, color, _start, _end); @@ -258,8 +258,8 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, } } - BUG_ON(adj_start < hole_start); - BUG_ON(adj_end > hole_end); + DRM_MM_BUG_ON(adj_start < hole_start); + DRM_MM_BUG_ON(adj_end > hole_end); if (adj_start == hole_start) { hole_node->hole_follows = 0; @@ -276,7 +276,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, drm_mm_interval_tree_add_node(hole_node, node); - BUG_ON(node->start + node->size > adj_end); + DRM_MM_BUG_ON(node->start + node->size > adj_end); node->hole_follows = 0; if (__drm_mm_hole_node_start(node) < hole_end) { @@ -409,7 +409,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, u64 adj_start = hole_start; u64 adj_end = hole_end; - BUG_ON(!hole_node->hole_follows || node->allocated); + DRM_MM_BUG_ON(!hole_node->hole_follows || node->allocated); if (adj_start < start) adj_start = start; @@ -450,10 +450,10 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, drm_mm_interval_tree_add_node(hole_node, node); - BUG_ON(node->start < start); - BUG_ON(node->start < adj_start); - BUG_ON(node->start + node->size > adj_end); - BUG_ON(node->start + node->size > end); + DRM_MM_BUG_ON(node->start < start); + DRM_MM_BUG_ON(node->start < adj_start); + DRM_MM_BUG_ON(node->start + node->size > adj_end); + DRM_MM_BUG_ON(node->start + node->size > end); node->hole_follows = 0; if (__drm_mm_hole_node_start(node) < hole_end) { @@ -519,22 +519,21 @@ void drm_mm_remove_node(struct drm_mm_node *node) struct drm_mm *mm = node->mm; struct drm_mm_node *prev_node; - if (WARN_ON(!node->allocated)) - return; - - BUG_ON(node->scanned_block || node->scanned_prev_free - || node->scanned_next_free); + DRM_MM_BUG_ON(!node->allocated); + DRM_MM_BUG_ON(node->scanned_block || + node->scanned_prev_free || + node->scanned_next_free); prev_node = list_entry(node->node_list.prev, struct drm_mm_node, node_list); if (node->hole_follows) { - BUG_ON(__drm_mm_hole_node_start(node) == - __drm_mm_hole_node_end(node)); + DRM_MM_BUG_ON(__drm_mm_hole_node_start(node) == + __drm_mm_hole_node_end(node)); list_del(>hole_stack); } else - BUG_ON(__drm_mm_hole_node_start(node) != - __drm_mm_hole_node_end(node)); + DRM_MM_BUG_ON(__drm_mm_hole_node_start(node) != + __drm_mm_hole_node_end(node)); if (!prev_node->hole_follows) { @@ -578,7 +577,7 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, u64 adj_end; u64 best_size; - BUG_ON(mm->scanned_blocks); + DRM_MM_BUG_ON(mm->scanned_blocks); best = NULL; best_size = ~0UL; @@ -622,7 +621,7 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_ u64 adj_end; u64 best_size; - BUG_ON(mm->scanned_blocks); + DRM_MM_BUG_ON(mm->scanned_blocks); best = NULL; best_size = ~0UL; @@ -668,6 +667,8 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_ */ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) { + DRM_MM_BUG_ON(!old->allocated); + list_replace(>node_list, >node_list); list_replace(>hole_stack, >hole_stack); rb_replace_node(>rb, >rb, >mm->interval_tree); @@ -798,7 +799,7 @@ bool drm_mm_scan_add_block(struct drm_mm_node *node) mm->scanned_blocks++; - BUG_ON(node->scanned_block); +
[Intel-gfx] [PATCH v3 27/38] drm: Rename prev_node to hole in drm_mm_scan_add_block()
Acknowledging that we were building up the hole was more useful to me when reading the code, than knowing the relationship between this node and the previous node. Signed-off-by: Chris WilsonReviewed-by: Joonas Lahtinen --- drivers/gpu/drm/drm_mm.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 21bd2e13738b..459f10ca5714 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -811,7 +811,7 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, struct drm_mm_node *node) { struct drm_mm *mm = scan->mm; - struct drm_mm_node *prev_node; + struct drm_mm_node *hole; u64 hole_start, hole_end; u64 adj_start, adj_end; @@ -821,17 +821,17 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, node->scanned_block = 1; mm->scan_active++; - prev_node = list_prev_entry(node, node_list); + hole = list_prev_entry(node, node_list); - node->scanned_preceeds_hole = prev_node->hole_follows; - prev_node->hole_follows = 1; + node->scanned_preceeds_hole = hole->hole_follows; + hole->hole_follows = 1; list_del(>node_list); - node->node_list.prev = _node->node_list; + node->node_list.prev = >node_list; node->node_list.next = >prev_scanned_node->node_list; scan->prev_scanned_node = node; - adj_start = hole_start = drm_mm_hole_node_start(prev_node); - adj_end = hole_end = drm_mm_hole_node_end(prev_node); + adj_start = hole_start = drm_mm_hole_node_start(hole); + adj_end = hole_end = drm_mm_hole_node_end(hole); if (scan->check_range) { if (adj_start < scan->range_start) @@ -841,7 +841,7 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, } if (mm->color_adjust) - mm->color_adjust(prev_node, scan->color, _start, _end); + mm->color_adjust(hole, scan->color, _start, _end); if (check_free_hole(adj_start, adj_end, scan->size, scan->alignment)) { -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] drm_mm fixes, take 3, final?
With a lot of polish applied, Joonas has reviewed the series - all but for [04/38] "lib: Add a simple prime number generator" [lib/prime_numbers.c]. Anyone feel like poking around at a bit of number theory? Other than it would appear to be ready for Daniel to sort out the merge between drm-misc/i915... Please do take a look and see if you can spot anything else that needs fixing/improving. -Chris ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t v2 10/12] tests/kms_atomic_transition: add out_fences tests
On Fri, Dec 16, 2016 at 03:59:00AM -0500, Robert Foss wrote: On 2016-12-14 11:57 AM, Brian Starkey wrote: On Wed, Dec 14, 2016 at 04:05:07AM -0500, Robert Foss wrote: From: Gustavo PadovanSigned-off-by: Gustavo Padovan Signed-off-by: Robert Foss --- lib/igt_kms.c | 22 ++ tests/kms_atomic_transition.c | 32 ++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/igt_kms.c b/lib/igt_kms.c index fe1b356d..eb59ab36 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -49,6 +49,7 @@ #include "intel_chipset.h" #include "igt_debugfs.h" #include "igt_sysfs.h" +#include "sw_sync.h" /** * SECTION:igt_kms @@ -2184,6 +2185,27 @@ static int igt_atomic_commit(igt_display_t *display, uint32_t flags, void *user_ } ret = drmModeAtomicCommit(display->drm_fd, req, flags, user_data); +if (!ret) { +int64_t *fence_ptr; + +for_each_pipe(display, pipe) { +igt_pipe_t *pipe_obj = >pipes[pipe]; + +fence_ptr = pipe_obj->out_fence_ptr; +if (!fence_ptr) +continue; + +if (flags & DRM_MODE_ATOMIC_TEST_ONLY) { +igt_assert(*fence_ptr == -1); +} else { +igt_assert(*fence_ptr >= 0); +ret = sw_sync_wait(*fence_ptr, 1000); +igt_assert(ret == 0); +close(*fence_ptr); +} +} +} + drmModeAtomicFree(req); return ret; diff --git a/tests/kms_atomic_transition.c b/tests/kms_atomic_transition.c index b7d99975..08f9499f 100644 --- a/tests/kms_atomic_transition.c +++ b/tests/kms_atomic_transition.c @@ -132,6 +132,7 @@ run_transition_test(igt_display_t *display, enum pipe pipe, igt_output_t *output struct plane_parms parms[IGT_MAX_PLANES]; bool skip_test = false; unsigned flags = DRM_MODE_PAGE_FLIP_EVENT; +int out_fence, ret; out_fence needs to be 64-bit. Ack, fixed in v3. if (nonblocking) flags |= DRM_MODE_ATOMIC_NONBLOCK; @@ -198,9 +199,11 @@ run_transition_test(igt_display_t *display, enum pipe pipe, igt_output_t *output * planes to fix this */ while (1) { -int ret; - wm_setup_plane(display, pipe, iter_max - 1, parms); + +if (fencing) +igt_pipe_set_out_fence_ptr(>pipes[pipe], +(int64_t *) _fence); ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); if (ret != -EINVAL || n_planes < 3) @@ -231,6 +234,9 @@ run_transition_test(igt_display_t *display, enum pipe pipe, igt_output_t *output wm_setup_plane(display, pipe, i, parms); +if (fencing) +igt_pipe_set_out_fence_ptr(>pipes[pipe], _fence); + igt_display_commit_atomic(display, flags, (void *)(unsigned long)i); drmHandleEvent(display->drm_fd, _events); @@ -239,6 +245,10 @@ run_transition_test(igt_display_t *display, enum pipe pipe, igt_output_t *output wm_setup_plane(display, pipe, 0, parms); +if (fencing) +igt_pipe_set_out_fence_ptr(>pipes[pipe], +(int64_t *) _fence); + igt_display_commit_atomic(display, flags, (void *)0UL); drmHandleEvent(display->drm_fd, _events); @@ -252,6 +262,9 @@ run_transition_test(igt_display_t *display, enum pipe pipe, igt_output_t *output if (type == TRANSITION_MODESET) igt_output_override_mode(output, _mode); +if (fencing) +igt_pipe_set_out_fence_ptr(>pipes[pipe], _fence); + igt_display_commit_atomic(display, flags, (void *)(unsigned long)j); drmHandleEvent(display->drm_fd, _events); @@ -259,6 +272,9 @@ run_transition_test(igt_display_t *display, enum pipe pipe, igt_output_t *output if (type == TRANSITION_MODESET) igt_output_override_mode(output, NULL); +if (fencing) +igt_pipe_set_out_fence_ptr(>pipes[pipe], _fence); + igt_display_commit_atomic(display, flags, (void *)(unsigned long)i); drmHandleEvent(display->drm_fd, _events); } @@ -588,14 +604,26 @@ igt_main for_each_pipe_with_valid_output(, pipe, output) run_transition_test(, pipe, output, TRANSITION_PLANES, false, false); +igt_subtest("plane-all-transition-fencing") +for_each_pipe_with_valid_output(, pipe, output) +run_transition_test(, pipe, output, TRANSITION_PLANES, false, true); + igt_subtest("plane-all-transition-nonblocking") for_each_pipe_with_valid_output(, pipe, output) run_transition_test(, pipe, output, TRANSITION_PLANES, true, false); +igt_subtest("plane-all-transition-nonblocking-fencing") +for_each_pipe_with_valid_output(, pipe, output) +
Re: [Intel-gfx] [PATCH i-g-t v2 08/12] tests/kms_atomic: stress possible fence settings
On Fri, Dec 16, 2016 at 03:35:36AM -0500, Robert Foss wrote: On 2016-12-14 11:39 AM, Brian Starkey wrote: Hi, On Wed, Dec 14, 2016 at 04:05:05AM -0500, Robert Foss wrote: From: Gustavo PadovanSigned-off-by: Gustavo Padovan Signed-off-by: Robert Foss --- tests/kms_atomic.c | 186 ++--- 1 file changed, 176 insertions(+), 10 deletions(-) diff --git a/tests/kms_atomic.c b/tests/kms_atomic.c index 8b648eba..a557ac60 100644 --- a/tests/kms_atomic.c +++ b/tests/kms_atomic.c @@ -44,6 +44,7 @@ #include "drmtest.h" #include "igt.h" #include "igt_aux.h" +#include "sw_sync.h" #ifndef DRM_CLIENT_CAP_ATOMIC #define DRM_CLIENT_CAP_ATOMIC 3 @@ -126,6 +127,7 @@ struct kms_atomic_plane_state { uint32_t fb_id; /* 0 to disable */ uint32_t src_x, src_y, src_w, src_h; /* 16.16 fixed-point */ uint32_t crtc_x, crtc_y, crtc_w, crtc_h; /* normal integers */ +int32_t fence_fd; }; struct kms_atomic_crtc_state { @@ -133,6 +135,7 @@ struct kms_atomic_crtc_state { uint32_t obj; int idx; bool active; +uint64_t out_fence_ptr; struct kms_atomic_blob mode; }; @@ -190,11 +193,13 @@ static uint32_t blob_duplicate(int fd, uint32_t id_orig) crtc_populate_req(crtc, req); \ plane_populate_req(plane, req); \ do_atomic_commit((crtc)->state->desc->fd, req, flags); \ -crtc_check_current_state(crtc, plane, relax); \ -plane_check_current_state(plane, relax); \ +if (!(flags & DRM_MODE_ATOMIC_TEST_ONLY)) { \ +crtc_check_current_state(crtc, plane, relax); \ +plane_check_current_state(plane, relax); \ +} \ } -#define crtc_commit_atomic_err(crtc, plane, crtc_old, plane_old, req, relax, e) { \ +#define crtc_commit_atomic_err(crtc, plane, crtc_old, plane_old, req, flags, relax, e) { \ drmModeAtomicSetCursor(req, 0); \ crtc_populate_req(crtc, req); \ plane_populate_req(plane, req); \ @@ -299,6 +304,9 @@ find_connector(struct kms_atomic_state *state, static void plane_populate_req(struct kms_atomic_plane_state *plane, drmModeAtomicReq *req) { +if (plane->fence_fd) +plane_set_prop(req, plane, IGT_PLANE_IN_FENCE_FD, plane->fence_fd); + plane_set_prop(req, plane, IGT_PLANE_CRTC_ID, plane->crtc_id); plane_set_prop(req, plane, IGT_PLANE_FB_ID, plane->fb_id); plane_set_prop(req, plane, IGT_PLANE_SRC_X, plane->src_x); @@ -424,6 +432,10 @@ find_plane(struct kms_atomic_state *state, enum plane_type type, static void crtc_populate_req(struct kms_atomic_crtc_state *crtc, drmModeAtomicReq *req) { +if (crtc->out_fence_ptr) +crtc_set_prop(req, crtc, IGT_CRTC_OUT_FENCE_PTR, + crtc->out_fence_ptr); + crtc_set_prop(req, crtc, IGT_CRTC_MODE_ID, crtc->mode.id); crtc_set_prop(req, crtc, IGT_CRTC_ACTIVE, crtc->active); } @@ -1052,6 +1064,37 @@ static void plane_invalid_params(struct kms_atomic_crtc_state *crtc, drmModeAtomicFree(req); } +static void plane_invalid_params_fence(struct kms_atomic_crtc_state *crtc, +struct kms_atomic_plane_state *plane_old, +struct kms_atomic_connector_state *conn) +{ +struct kms_atomic_plane_state plane = *plane_old; +drmModeAtomicReq *req = drmModeAtomicAlloc(); +int timeline, fence_fd; + +igt_require_sw_sync(); + +/* invalid fence fd */ +plane.fence_fd = plane.state->desc->fd; +plane.crtc_id = plane_old->crtc_id; +plane_commit_atomic_err(, plane_old, req, +ATOMIC_RELAX_NONE, EINVAL); + +/* Valid fence_fd but invalid CRTC */ +timeline = sw_sync_timeline_create(); +fence_fd = sw_sync_fence_create(timeline, 1); +plane.fence_fd = fence_fd; +plane.crtc_id = ~0U; +plane_commit_atomic_err(, plane_old, req, +ATOMIC_RELAX_NONE, EINVAL); + +plane.fence_fd = -1; +close(fence_fd); +close(timeline); + +drmModeAtomicFree(req); +} + static void crtc_invalid_params(struct kms_atomic_crtc_state *crtc_old, struct kms_atomic_plane_state *plane, struct kms_atomic_connector_state *conn) @@ -1063,30 +1106,32 @@ static void crtc_invalid_params(struct kms_atomic_crtc_state *crtc_old, /* Pass a series of invalid object IDs for the mode ID. */ crtc.mode.id = plane->obj; -crtc_commit_atomic_err(, plane, crtc_old, plane, req, +crtc_commit_atomic_err(, plane, crtc_old, plane, req, 0, ATOMIC_RELAX_NONE, EINVAL); crtc.mode.id = crtc.obj; -crtc_commit_atomic_err(, plane, crtc_old, plane, req, +crtc_commit_atomic_err(, plane, crtc_old, plane, req, 0, ATOMIC_RELAX_NONE, EINVAL); crtc.mode.id = conn->obj; -crtc_commit_atomic_err(, plane, crtc_old, plane, req, +crtc_commit_atomic_err(, plane, crtc_old, plane, req, 0, ATOMIC_RELAX_NONE, EINVAL);
Re: [Intel-gfx] [PATCH i-g-t v2 07/12] lib/igt_kms: Add support for the OUT_FENCE_PTR property
On Fri, Dec 16, 2016 at 03:21:45AM -0500, Robert Foss wrote: On 2016-12-14 11:13 AM, Brian Starkey wrote: Hi, On Wed, Dec 14, 2016 at 04:05:04AM -0500, Robert Foss wrote: From: Gustavo PadovanAdd support for the OUT_FENCE_PTR property to enable setting out fences for atomic commits. Signed-off-by: Gustavo Padovan Signed-off-by: Robert Foss --- lib/igt_kms.c | 21 - lib/igt_kms.h | 3 +++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/igt_kms.c b/lib/igt_kms.c index 8ca49d86..fe1b356d 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -175,7 +175,8 @@ const char *igt_crtc_prop_names[IGT_NUM_CRTC_PROPS] = { "DEGAMMA_LUT", "GAMMA_LUT", "MODE_ID", -"ACTIVE" +"ACTIVE", +"OUT_FENCE_PTR" }; const char *igt_connector_prop_names[IGT_NUM_CONNECTOR_PROPS] = { @@ -2103,6 +2104,10 @@ static void igt_atomic_prepare_crtc_commit(igt_pipe_t *pipe_obj, drmModeAtomicRe igt_atomic_populate_crtc_req(req, pipe_obj, IGT_CRTC_ACTIVE, !!output); } +if (pipe_obj->out_fence_ptr) +igt_atomic_populate_crtc_req(req, pipe_obj, IGT_CRTC_OUT_FENCE_PTR, +(uint64_t)(uintptr_t) pipe_obj->out_fence_ptr); + /* *TODO: Add all crtc level properties here */ @@ -2683,6 +2688,20 @@ igt_pipe_set_gamma_lut(igt_pipe_t *pipe, void *ptr, size_t length) } /** + * igt_pipe_set_out_fence_ptr: + * @pipe: pipe pointer to which background color to be set + * @fence_ptr: out fence pointer + * + * Sets the out fence pointer that will be passed to the kernel in + * the atomic ioctl. When the kernel returns the out fence pointer + * will contain the fd number of the out fence created by KMS. + */ +void igt_pipe_set_out_fence_ptr(igt_pipe_t *pipe, int64_t *fence_ptr) +{ +pipe->out_fence_ptr = fence_ptr; +} + +/** * igt_crtc_set_background: * @pipe: pipe pointer to which background color to be set * @background: background color value in BGR 16bpc diff --git a/lib/igt_kms.h b/lib/igt_kms.h index 9766807c..8eb611c0 100644 --- a/lib/igt_kms.h +++ b/lib/igt_kms.h @@ -110,6 +110,7 @@ enum igt_atomic_crtc_properties { IGT_CRTC_GAMMA_LUT, IGT_CRTC_MODE_ID, IGT_CRTC_ACTIVE, + IGT_CRTC_OUT_FENCE_PTR, IGT_NUM_CRTC_PROPS }; @@ -316,6 +317,7 @@ struct igt_pipe { uint64_t mode_blob; bool mode_changed; +int64_t *out_fence_ptr; I prefer the interface that got suggested before - igt_pipe gets an "int64_t out_fence;" member which tests can query to get the fence value: int igt_pipe_get_last_out_fence(igt_pipe_t *pipe); ..and the kernel only ever receives a pointer to pipe->out_fence. The only reason I can see for a test to want to provide its own fence pointer is to test invalid pointer values - and I think it's OK for that test to set the property directly instead of making setting a custom fence pointer the common case for all users. If we don't want to get a fence for every commit then I guess there could be a way for a test to request an out-fence for just the next commit on a pipe (or the inverse - disable fencing for a particular commit): void igt_pipe_request_out_fence(igt_pipe_t *pipe); -Brian Now I see what you meant in the v1 discussion, I'll amend the implementation in v3 to be the one mentioned above. Partly... my main point on v1 was just to make sure the pointer was to a 64-bit type. The only question I have is about igt_pipe_get_last_out_fence(), is it really necessary? I don't foresee a function like that ever doing more than just returning a struct member. Is it not a bit redundant? I see two reasons for it: - It means tests only deal with plain ints, which I think Chris was fairly adamant about on v1. - The getter can set pipe->out_fence to -1 when its called, making the ownership of the fd obvious. In this case I guess before each commit out_fence needs to be checked, close()'d if it looks valid, and set to -1 too. Cheers, Brian Rob. }; typedef struct { @@ -369,6 +371,7 @@ static inline bool igt_plane_supports_rotation(igt_plane_t *plane) void igt_pipe_set_degamma_lut(igt_pipe_t *pipe, void *ptr, size_t length); void igt_pipe_set_ctm_matrix(igt_pipe_t *pipe, void *ptr, size_t length); void igt_pipe_set_gamma_lut(igt_pipe_t *pipe, void *ptr, size_t length); +void igt_pipe_set_out_fence_ptr(igt_pipe_t *pipe, int64_t *fence_ptr); void igt_plane_set_fb(igt_plane_t *plane, struct igt_fb *fb); void igt_plane_set_fence_fd(igt_plane_t *plane, uint32_t fence_fd); -- 2.11.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to getparams
>-Original Message- >From: Chris Wilson [mailto:ch...@chris-wilson.co.uk] >Sent: Friday, December 16, 2016 10:47 AM >To: Srivatsa, Anusha>Cc: Hiler, Arkadiusz ; >intel-gfx@lists.freedesktop.org >Subject: Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to >getparams > >On Fri, Dec 16, 2016 at 06:31:46PM +, Srivatsa, Anusha wrote: >> >> >> >-Original Message- >> >From: Chris Wilson [mailto:ch...@chris-wilson.co.uk] >> >Sent: Friday, December 16, 2016 8:31 AM >> >To: Hiler, Arkadiusz >> >Cc: Srivatsa, Anusha ; intel- >> >g...@lists.freedesktop.org >> >Subject: Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC >> >status to getparams >> > >> >On Fri, Dec 16, 2016 at 05:21:38PM +0100, Arkadiusz Hiler wrote: >> >> On Fri, Dec 16, 2016 at 04:12:36PM +, Chris Wilson wrote: >> >> > On Fri, Dec 16, 2016 at 03:43:46PM +0100, Arkadiusz Hiler wrote: >> >> > > On Thu, Dec 15, 2016 at 10:42:53PM +, Chris Wilson wrote: >> >> > > > On Thu, Dec 15, 2016 at 02:29:50PM -0800, anushasr wrote: >> >> > > > > From: Peter Antoine >> >> > > > > >> >> > > > > This patch will allow for getparams to return the status of the >> >> > > > > HuC. >> >> > > > > As the HuC has to be validated by the GuC this patch uses >> >> > > > > the validated status to show when the HuC is loaded and >> >> > > > > ready for use. You cannot use the loaded status as with the >> >> > > > > GuC as the HuC is verified after it is loaded and is not usable >> >> > > > > until it is >verified. >> >> > > > > >> >> > > > > v2: removed the forewakes as the registers are already >> >> > > > > force-woken. >> >> > > > > (T.Ursulin) >> >> > > > > v4: rebased. >> >> > > > > v5: rebased on top of drm-tip. >> >> > > > > v6: rebased. Removed any reference to intel_huc.h >> >> > > > > v7: rebased. Rename I915_PARAM_HAS_HUC to >> >I915_PARAM_HUC_STATUS. >> >> > > > > Remove intel_is_huc_valid() since it is used only in one place. >> >> > > > > Put the case of I915_PARAM_HAS_HUC() in the right place. >> >> > > > > >> >> > > > > Signed-off-by: Peter Antoine >> >> > > > > Reviewed-by: Arkadiusz Hiler >> >> > > > > --- >> >> > > > > drivers/gpu/drm/i915/i915_drv.c | 4 >> >> > > > > drivers/gpu/drm/i915/intel_huc_loader.c | 1 - >> >> > > > > include/uapi/drm/i915_drm.h | 1 + >> >> > > > > 3 files changed, 5 insertions(+), 1 deletion(-) >> >> > > > > >> >> > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.c >> >> > > > > b/drivers/gpu/drm/i915/i915_drv.c index 85a47c2..0bc016d >> >> > > > > 100644 >> >> > > > > --- a/drivers/gpu/drm/i915/i915_drv.c >> >> > > > > +++ b/drivers/gpu/drm/i915/i915_drv.c >> >> > > > > @@ -49,6 +49,7 @@ >> >> > > > > #include "i915_trace.h" >> >> > > > > #include "i915_vgpu.h" >> >> > > > > #include "intel_drv.h" >> >> > > > > +#include "intel_uc.h" >> >> > > > > >> >> > > > > static struct drm_driver driver; >> >> > > > > >> >> > > > > @@ -315,6 +316,9 @@ static int i915_getparam(struct >> >> > > > > drm_device >> >*dev, void *data, >> >> > > > > case I915_PARAM_MIN_EU_IN_POOL: >> >> > > > > value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; >> >> > > > > break; >> >> > > > > + case I915_PARAM_HUC_STATUS: >> >> > > > > + value = I915_READ(HUC_STATUS2) & >> >HUC_FW_VERIFIED; >> >> > > > >> >> > > > Same question as last time: does the device need to be awake? >> >> > > > We know is one of the GT power wells, so presumably we need >> >> > > > an rpm_get/rpm_put as well to access the register. >> >> > > > -Chris >> >> > > >> >> > > I get: >> >> > > >> >> > > [ 1588.570174] [drm:i915_huc_load_status_info [i915]] >> >> > > HUC_STATUS2 PRE 24704 [ 1588.571285] >> >> > > [drm:intel_runtime_suspend [i915]] Suspending device [ >> >> > > 1588.575768] [drm:intel_runtime_suspend [i915]] Device >> >> > > suspended [ 1588.577156] [drm:i915_huc_load_status_info [i915]] >> >> > > HUC_STATUS2 POST 24704 [ 1588.578259] [drm:intel_runtime_resume >> >> > > [i915]] Resuming device >> >> > > >> >> > > consistently from: >> >> > > >> >> > > value = I915_READ(HUC_STATUS2); >> >> > > DRM_DEBUG_DRIVER("HUC_STATUS2 PRE %d\n", value); >> >> > > i915_pm_ops.runtime_suspend(dev_priv->drm.dev); >> >> > > >> >> > > value = I915_READ(HUC_STATUS2); >> >> > > DRM_DEBUG_DRIVER("HUC_STATUS2 POST %d\n", value); >> >> > > i915_pm_ops.runtime_resume(dev_priv->drm.dev); >> >> > >> >> > Also do the test with i915.mmio_debug= -Chris >> >> >> >> Same effect. Works. >> Thanks Arek for confirming. >> >> >Ok, then just mark up that we don't need rpm here so that we don't >> >freak out in future scans for mmio access outside of rpm. >> >-Chris >> Chris, v2 as changed by Tvrtko suggests that forcewakes are removed since the >register is force waken. Are you suggesting that adding
Re: [Intel-gfx] [PATCH v3] lib: Add a simple prime number generator
Hi Chris, [auto build test WARNING on linus/master] [also build test WARNING on v4.9 next-20161216] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Chris-Wilson/lib-Add-a-simple-prime-number-generator/20161217-013805 reproduce: # apt-get install sparse make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) include/linux/compiler.h:253:8: sparse: attribute 'no_sanitize_address': unknown attribute >> lib/prime_numbers.c:220:20: sparse: incompatible types in comparison >> expression (different address spaces) vim +220 lib/prime_numbers.c 204 return -EINVAL; 205 } 206 last = x; 207 } 208 209 pr_info("selftest(%lu) passed, last prime was %lu", x, last); 210 return 0; 211 } 212 213 static int __init primes_init(void) 214 { 215 return selftest(selftest_max); 216 } 217 218 static void __exit primes_exit(void) 219 { > 220 if (primes != _primes) 221 kfree_rcu((struct primes *)primes, rcu); 222 } 223 224 module_init(primes_init); 225 module_exit(primes_exit); 226 227 module_param_named(selftest, selftest_max, ulong, 0400); 228 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to getparams
On Fri, Dec 16, 2016 at 06:31:46PM +, Srivatsa, Anusha wrote: > > > >-Original Message- > >From: Chris Wilson [mailto:ch...@chris-wilson.co.uk] > >Sent: Friday, December 16, 2016 8:31 AM > >To: Hiler, Arkadiusz> >Cc: Srivatsa, Anusha ; intel- > >g...@lists.freedesktop.org > >Subject: Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to > >getparams > > > >On Fri, Dec 16, 2016 at 05:21:38PM +0100, Arkadiusz Hiler wrote: > >> On Fri, Dec 16, 2016 at 04:12:36PM +, Chris Wilson wrote: > >> > On Fri, Dec 16, 2016 at 03:43:46PM +0100, Arkadiusz Hiler wrote: > >> > > On Thu, Dec 15, 2016 at 10:42:53PM +, Chris Wilson wrote: > >> > > > On Thu, Dec 15, 2016 at 02:29:50PM -0800, anushasr wrote: > >> > > > > From: Peter Antoine > >> > > > > > >> > > > > This patch will allow for getparams to return the status of the > >> > > > > HuC. > >> > > > > As the HuC has to be validated by the GuC this patch uses the > >> > > > > validated status to show when the HuC is loaded and ready for > >> > > > > use. You cannot use the loaded status as with the GuC as the > >> > > > > HuC is verified after it is loaded and is not usable until it is > >> > > > > verified. > >> > > > > > >> > > > > v2: removed the forewakes as the registers are already force-woken. > >> > > > > (T.Ursulin) > >> > > > > v4: rebased. > >> > > > > v5: rebased on top of drm-tip. > >> > > > > v6: rebased. Removed any reference to intel_huc.h > >> > > > > v7: rebased. Rename I915_PARAM_HAS_HUC to > >I915_PARAM_HUC_STATUS. > >> > > > > Remove intel_is_huc_valid() since it is used only in one place. > >> > > > > Put the case of I915_PARAM_HAS_HUC() in the right place. > >> > > > > > >> > > > > Signed-off-by: Peter Antoine > >> > > > > Reviewed-by: Arkadiusz Hiler > >> > > > > --- > >> > > > > drivers/gpu/drm/i915/i915_drv.c | 4 > >> > > > > drivers/gpu/drm/i915/intel_huc_loader.c | 1 - > >> > > > > include/uapi/drm/i915_drm.h | 1 + > >> > > > > 3 files changed, 5 insertions(+), 1 deletion(-) > >> > > > > > >> > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.c > >> > > > > b/drivers/gpu/drm/i915/i915_drv.c index 85a47c2..0bc016d > >> > > > > 100644 > >> > > > > --- a/drivers/gpu/drm/i915/i915_drv.c > >> > > > > +++ b/drivers/gpu/drm/i915/i915_drv.c > >> > > > > @@ -49,6 +49,7 @@ > >> > > > > #include "i915_trace.h" > >> > > > > #include "i915_vgpu.h" > >> > > > > #include "intel_drv.h" > >> > > > > +#include "intel_uc.h" > >> > > > > > >> > > > > static struct drm_driver driver; > >> > > > > > >> > > > > @@ -315,6 +316,9 @@ static int i915_getparam(struct drm_device > >*dev, void *data, > >> > > > >case I915_PARAM_MIN_EU_IN_POOL: > >> > > > >value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; > >> > > > >break; > >> > > > > + case I915_PARAM_HUC_STATUS: > >> > > > > + value = I915_READ(HUC_STATUS2) & > >HUC_FW_VERIFIED; > >> > > > > >> > > > Same question as last time: does the device need to be awake? We > >> > > > know is one of the GT power wells, so presumably we need an > >> > > > rpm_get/rpm_put as well to access the register. > >> > > > -Chris > >> > > > >> > > I get: > >> > > > >> > > [ 1588.570174] [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 > >> > > PRE 24704 [ 1588.571285] [drm:intel_runtime_suspend [i915]] > >> > > Suspending device [ 1588.575768] [drm:intel_runtime_suspend > >> > > [i915]] Device suspended [ 1588.577156] > >> > > [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 POST 24704 [ > >> > > 1588.578259] [drm:intel_runtime_resume [i915]] Resuming device > >> > > > >> > > consistently from: > >> > > > >> > > value = I915_READ(HUC_STATUS2); > >> > > DRM_DEBUG_DRIVER("HUC_STATUS2 PRE %d\n", value); > >> > > i915_pm_ops.runtime_suspend(dev_priv->drm.dev); > >> > > > >> > > value = I915_READ(HUC_STATUS2); > >> > > DRM_DEBUG_DRIVER("HUC_STATUS2 POST %d\n", value); > >> > > i915_pm_ops.runtime_resume(dev_priv->drm.dev); > >> > > >> > Also do the test with i915.mmio_debug= -Chris > >> > >> Same effect. Works. > Thanks Arek for confirming. > > >Ok, then just mark up that we don't need rpm here so that we don't freak out > >in > >future scans for mmio access outside of rpm. > >-Chris > Chris, v2 as changed by Tvrtko suggests that forcewakes are removed since the > register is force waken. Are you suggesting that adding that rpm not being > required in the commit message will make things much more clearer? No, if you are eschewing taking rpm around mmio access, I want that commented upon in the code so that it is visible the next time we do an audit for rpm abuse/misuse. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org
Re: [Intel-gfx] [PATCH 4/8] drm/i915/huc: Add BXT HuC Loading Support
>-Original Message- >From: Tvrtko Ursulin [mailto:tvrtko.ursu...@linux.intel.com] >Sent: Friday, December 16, 2016 8:16 AM >To: Srivatsa, Anusha; intel- >g...@lists.freedesktop.org >Subject: Re: [Intel-gfx] [PATCH 4/8] drm/i915/huc: Add BXT HuC Loading Support > > >On 15/12/2016 22:29, anushasr wrote: >> From: Anusha Srivatsa >> >> This patch adds the HuC Loading for the BXT by using the updated file >> construction. >> >> Version 1.7 of the HuC firmware. >> >> v2: rebased. >> v3: rebased on top of drm-tip >> v4: rebased. >> v5: rebased. Rename BXT_FW_MAJOR to BXT_HUC_FW_ >> >> Cc: Jeff Mcgee >> Signed-off-by: Anusha Srivatsa >> Reviewed-by: Jeff McGee >> --- >> drivers/gpu/drm/i915/intel_huc_loader.c | 11 +++ >> 1 file changed, 11 insertions(+) >> >> diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c >> b/drivers/gpu/drm/i915/intel_huc_loader.c >> index 0f929cc..f36efd4 100644 >> --- a/drivers/gpu/drm/i915/intel_huc_loader.c >> +++ b/drivers/gpu/drm/i915/intel_huc_loader.c >> @@ -40,6 +40,10 @@ >> * Note that HuC firmware loading must be done before GuC loading. >> */ >> >> +#define BXT_HUC_FW_MAJOR 01 >> +#define BXT_HUC_FW_MINOR 07 >> +#define BXT_BLD_NUM 1398 >> + >> #define SKL_HUC_FW_MAJOR 01 >> #define SKL_HUC_FW_MINOR 07 >> #define SKL_BLD_NUM 1398 >> @@ -52,6 +56,9 @@ >> SKL_HUC_FW_MINOR, SKL_BLD_NUM) >> MODULE_FIRMWARE(I915_SKL_HUC_UCODE); >> >> +#define I915_BXT_HUC_UCODE HUC_FW_PATH(bxt, BXT_HUC_FW_MAJOR, \ >> +BXT_HUC_FW_MINOR, BXT_BLD_NUM) >> +MODULE_FIRMWARE(I915_BXT_HUC_UCODE); > >More curiosity - given the versions between SKL and BXT are identical - is it >actually the same binary file in both cases? Hi Tvrtko its different binary file. Cheers, Anusha >Regards, >Tvrtko > >> /** >> * huc_ucode_xfer() - DMA's the firmware >> * @dev_priv: the drm device >> @@ -157,6 +164,10 @@ void intel_huc_init(struct drm_i915_private *dev_priv) >> fw_path = I915_SKL_HUC_UCODE; >> huc_fw->major_ver_wanted = SKL_HUC_FW_MAJOR; >> huc_fw->minor_ver_wanted = SKL_HUC_FW_MINOR; >> +} else if (IS_BROXTON(dev_priv)) { >> +fw_path = I915_BXT_HUC_UCODE; >> +huc_fw->major_ver_wanted = BXT_HUC_FW_MAJOR; >> +huc_fw->minor_ver_wanted = BXT_HUC_FW_MINOR; >> } >> >> huc_fw->uc_fw_path = fw_path; >> ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to getparams
>-Original Message- >From: Chris Wilson [mailto:ch...@chris-wilson.co.uk] >Sent: Friday, December 16, 2016 8:31 AM >To: Hiler, Arkadiusz>Cc: Srivatsa, Anusha ; intel- >g...@lists.freedesktop.org >Subject: Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to >getparams > >On Fri, Dec 16, 2016 at 05:21:38PM +0100, Arkadiusz Hiler wrote: >> On Fri, Dec 16, 2016 at 04:12:36PM +, Chris Wilson wrote: >> > On Fri, Dec 16, 2016 at 03:43:46PM +0100, Arkadiusz Hiler wrote: >> > > On Thu, Dec 15, 2016 at 10:42:53PM +, Chris Wilson wrote: >> > > > On Thu, Dec 15, 2016 at 02:29:50PM -0800, anushasr wrote: >> > > > > From: Peter Antoine >> > > > > >> > > > > This patch will allow for getparams to return the status of the HuC. >> > > > > As the HuC has to be validated by the GuC this patch uses the >> > > > > validated status to show when the HuC is loaded and ready for >> > > > > use. You cannot use the loaded status as with the GuC as the >> > > > > HuC is verified after it is loaded and is not usable until it is >> > > > > verified. >> > > > > >> > > > > v2: removed the forewakes as the registers are already force-woken. >> > > > > (T.Ursulin) >> > > > > v4: rebased. >> > > > > v5: rebased on top of drm-tip. >> > > > > v6: rebased. Removed any reference to intel_huc.h >> > > > > v7: rebased. Rename I915_PARAM_HAS_HUC to >I915_PARAM_HUC_STATUS. >> > > > > Remove intel_is_huc_valid() since it is used only in one place. >> > > > > Put the case of I915_PARAM_HAS_HUC() in the right place. >> > > > > >> > > > > Signed-off-by: Peter Antoine >> > > > > Reviewed-by: Arkadiusz Hiler >> > > > > --- >> > > > > drivers/gpu/drm/i915/i915_drv.c | 4 >> > > > > drivers/gpu/drm/i915/intel_huc_loader.c | 1 - >> > > > > include/uapi/drm/i915_drm.h | 1 + >> > > > > 3 files changed, 5 insertions(+), 1 deletion(-) >> > > > > >> > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.c >> > > > > b/drivers/gpu/drm/i915/i915_drv.c index 85a47c2..0bc016d >> > > > > 100644 >> > > > > --- a/drivers/gpu/drm/i915/i915_drv.c >> > > > > +++ b/drivers/gpu/drm/i915/i915_drv.c >> > > > > @@ -49,6 +49,7 @@ >> > > > > #include "i915_trace.h" >> > > > > #include "i915_vgpu.h" >> > > > > #include "intel_drv.h" >> > > > > +#include "intel_uc.h" >> > > > > >> > > > > static struct drm_driver driver; >> > > > > >> > > > > @@ -315,6 +316,9 @@ static int i915_getparam(struct drm_device >*dev, void *data, >> > > > > case I915_PARAM_MIN_EU_IN_POOL: >> > > > > value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; >> > > > > break; >> > > > > +case I915_PARAM_HUC_STATUS: >> > > > > +value = I915_READ(HUC_STATUS2) & >HUC_FW_VERIFIED; >> > > > >> > > > Same question as last time: does the device need to be awake? We >> > > > know is one of the GT power wells, so presumably we need an >> > > > rpm_get/rpm_put as well to access the register. >> > > > -Chris >> > > >> > > I get: >> > > >> > > [ 1588.570174] [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 >> > > PRE 24704 [ 1588.571285] [drm:intel_runtime_suspend [i915]] >> > > Suspending device [ 1588.575768] [drm:intel_runtime_suspend >> > > [i915]] Device suspended [ 1588.577156] >> > > [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 POST 24704 [ >> > > 1588.578259] [drm:intel_runtime_resume [i915]] Resuming device >> > > >> > > consistently from: >> > > >> > > value = I915_READ(HUC_STATUS2); >> > > DRM_DEBUG_DRIVER("HUC_STATUS2 PRE %d\n", value); >> > > i915_pm_ops.runtime_suspend(dev_priv->drm.dev); >> > > >> > > value = I915_READ(HUC_STATUS2); >> > > DRM_DEBUG_DRIVER("HUC_STATUS2 POST %d\n", value); >> > > i915_pm_ops.runtime_resume(dev_priv->drm.dev); >> > >> > Also do the test with i915.mmio_debug= -Chris >> >> Same effect. Works. Thanks Arek for confirming. >Ok, then just mark up that we don't need rpm here so that we don't freak out in >future scans for mmio access outside of rpm. >-Chris Chris, v2 as changed by Tvrtko suggests that forcewakes are removed since the register is force waken. Are you suggesting that adding that rpm not being required in the commit message will make things much more clearer? Anusha > >-- >Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/5] drm/i915/guc: Simplify intel_guc_load()
+ +fail: + /* +* We've failed to load the firmware :( +* +* Decide whether to disable GuC submission and fall back to +* execlist mode, and whether to hide the error by returning +* zero or to return -EIO, which the caller will treat as a +* nonfatal error (i.e. it doesn't prevent driver load, but +* marks the GPU as wedged until reset). +*/ + if (i915.enable_guc_loading > 1 || i915.enable_guc_submission > 1) + ret = -EIO; + else + ret = 0; + + if (i915.enable_guc_submission) { + i915.enable_guc_submission = 0; + DRM_INFO("GuC submission without firmware not supported\n"); + DRM_NOTE("Falling back from GuC submission to execlist mode\n"); If i915.enable_guc_submission > 1 we will mark the GPU as wedged so it might be worth retaining an error level message here in that scenario. If we are wedging the GPU you do not really care about the fallback, so theres no real use in having that promoted + those are the original levels that were already here. Anyway, it seems like the `enable_guc_* > 1` are likely to be gone. I've discussed that on IRC yesterday and no one seems to really remember why we've got it in the first place. Anusha posted similar concern here with her HuC series as well. Just to clarify (because as you said the case will probably go away), what I meant was an extra log for the > 1 case like we had in the original code, i.e: DRM_ERROR("GuC init failed: %d\n", ret); as otherwise we would have declared the GPU wedged without printing any error-level message to explain why. Daniele ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] ✗ Fi.CI.BAT: failure for series starting with [1/3] drm/i915/DMC/GLK: Load DMC on GLK
== Series Details == Series: series starting with [1/3] drm/i915/DMC/GLK: Load DMC on GLK URL : https://patchwork.freedesktop.org/series/16926/ State : failure == Summary == Series 16926v1 Series without cover letter https://patchwork.freedesktop.org/api/1.0/series/16926/revisions/1/mbox/ Test drv_module_reload: Subgroup basic-reload-inject: pass -> INCOMPLETE (fi-kbl-7500u) Test kms_pipe_crc_basic: Subgroup suspend-read-crc-pipe-b: pass -> SKIP (fi-bxt-j4205) fi-bdw-5557u total:247 pass:233 dwarn:0 dfail:0 fail:0 skip:14 fi-bsw-n3050 total:247 pass:208 dwarn:0 dfail:0 fail:0 skip:39 fi-bxt-j4205 total:247 pass:222 dwarn:0 dfail:0 fail:0 skip:25 fi-bxt-t5700 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-j1900 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-n2820 total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-hsw-4770 total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-hsw-4770r total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-ilk-650 total:247 pass:195 dwarn:0 dfail:0 fail:0 skip:52 fi-ivb-3520m total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-ivb-3770 total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-kbl-7500u total:7pass:6dwarn:0 dfail:0 fail:0 skip:0 fi-skl-6260u total:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-skl-6700hqtotal:247 pass:227 dwarn:0 dfail:0 fail:0 skip:20 fi-skl-6700k total:247 pass:224 dwarn:3 dfail:0 fail:0 skip:20 fi-skl-6770hqtotal:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-snb-2520m total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-snb-2600 total:247 pass:215 dwarn:0 dfail:0 fail:0 skip:32 705f1e8fef81d504f0032df8e21bdc2e74850b3a drm-tip: 2016y-12m-16d-15h-40m-02s UTC integration manifest 376d7cf drm/i915/glk: Convert a few more IS_BROXTON() to IS_GEN9_LP() 8c9049c drm/i915/glk: Add missing bits to allow runtime pm suspend on GLK. 2a48676 drm/i915/DMC/GLK: Load DMC on GLK == Logs == For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3311/ ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/2] drm/i915: Dump more configuration information for DSI
On Wed, Dec 14, 2016 at 07:14:05PM +0200, ville.syrj...@linux.intel.com wrote: > From: Ville Syrjälä> > Dump out more of the DSI configuration details during init. > This includes pclk, burst_mode_ratio, lane_count, pixel_overlap, > video_mode_format and reset_timer_val. > > v2: Dump more info (Chris) dphy_reg? No idea what it is, just another one I couldn't find printed. > Cc: Chris Wilson > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 9 + > 1 file changed, 9 insertions(+) > > diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c > b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c > index 3fd3bac5fccc..d2e3aa9c5022 100644 > --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c > +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c > @@ -808,6 +808,15 @@ struct drm_panel *vbt_panel_init(struct intel_dsi > *intel_dsi, u16 panel_id) > 8); > intel_dsi->clk_hs_to_lp_count += extra_byte_count; > > + DRM_DEBUG_KMS("Pclk %d\n", intel_dsi->pclk); > + DRM_DEBUG_KMS("Pixel overlap %d\n", intel_dsi->pixel_overlap); > + DRM_DEBUG_KMS("Lane count %d\n", intel_dsi->lane_count); > + DRM_DEBUG_KMS("Video mode format %s\n", > + intel_dsi->video_mode_format == NON_BURST_SYNC_PULSE ? > "non-burst with sync pulse" : > + intel_dsi->video_mode_format == NON_BURST_SYNC_EVENTS ? > "non-burst with sync events" : > + intel_dsi->video_mode_format == BURST_MODE ? "burst" : > ""); Argh. The mipi_config.video_transfer_mode:2 has #define NON_BURST_SYNC_PULSE0x1 #define NON_BURST_SYNC_EVENTS 0x2 #define BURST_MODE 0x3 but intel_dist.video_mode_format is #define VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE (1 << 0) #define VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS (2 << 0) #define VIDEO_MODE_BURST (3 << 0) They match just usage is consistent. However you want to resolve that, Reviewed-by: Chris Wilson -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] ✗ Fi.CI.BAT: failure for drm: Use drm_mm_nodes() as shorthand for the list of nodes under struct drm_mm
== Series Details == Series: drm: Use drm_mm_nodes() as shorthand for the list of nodes under struct drm_mm URL : https://patchwork.freedesktop.org/series/16920/ State : failure == Summary == Series 16920v1 drm: Use drm_mm_nodes() as shorthand for the list of nodes under struct drm_mm https://patchwork.freedesktop.org/api/1.0/series/16920/revisions/1/mbox/ Test gem_ctx_switch: Subgroup basic-default: pass -> INCOMPLETE (fi-byt-j1900) Test kms_pipe_crc_basic: Subgroup suspend-read-crc-pipe-b: pass -> SKIP (fi-bxt-j4205) fi-bdw-5557u total:247 pass:233 dwarn:0 dfail:0 fail:0 skip:14 fi-bsw-n3050 total:247 pass:208 dwarn:0 dfail:0 fail:0 skip:39 fi-bxt-j4205 total:247 pass:222 dwarn:0 dfail:0 fail:0 skip:25 fi-bxt-t5700 total:247 pass:220 dwarn:0 dfail:0 fail:0 skip:27 fi-byt-j1900 total:24 pass:23 dwarn:0 dfail:0 fail:0 skip:0 fi-byt-n2820 total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-hsw-4770 total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-hsw-4770r total:247 pass:228 dwarn:0 dfail:0 fail:0 skip:19 fi-ilk-650 total:247 pass:195 dwarn:0 dfail:0 fail:0 skip:52 fi-ivb-3520m total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-ivb-3770 total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-kbl-7500u total:247 pass:226 dwarn:0 dfail:0 fail:0 skip:21 fi-skl-6260u total:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-skl-6700hqtotal:247 pass:227 dwarn:0 dfail:0 fail:0 skip:20 fi-skl-6700k total:247 pass:224 dwarn:3 dfail:0 fail:0 skip:20 fi-skl-6770hqtotal:247 pass:234 dwarn:0 dfail:0 fail:0 skip:13 fi-snb-2520m total:247 pass:216 dwarn:0 dfail:0 fail:0 skip:31 fi-snb-2600 total:247 pass:215 dwarn:0 dfail:0 fail:0 skip:32 705f1e8fef81d504f0032df8e21bdc2e74850b3a drm-tip: 2016y-12m-16d-15h-40m-02s UTC integration manifest 4a8cc5a drm: Use drm_mm_nodes() as shorthand for the list of nodes under struct drm_mm == Logs == For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3310/ ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/8] drm/i915/huc: Add HuC fw loading support
On 16/12/2016 16:29, Arkadiusz Hiler wrote: On Fri, Dec 16, 2016 at 04:13:14PM +, Tvrtko Ursulin wrote: On 15/12/2016 22:29, anushasr wrote: From: Anusha SrivatsaThe HuC loading process is similar to GuC. The intel_uc_fw_fetch() is used for both cases. HuC loading needs to be before GuC loading. The WOPCM setting must be done early before loading any of them. v2: rebased on-top of drm-intel-nightly. removed if(HAS_GUC()) before the guc call. (D.Gordon) update huc_version number of format. v3: rebased to drm-intel-nightly, changed the file name format to match the one in the huc package. Changed dev->dev_private to to_i915() v4: moved function back to where it was. change wait_for_atomic to wait_for. v5: rebased + comment changes. v7: rebased. v8: rebased. v9: rebased. Changed the year in the copyright message to reflect the right year.Correct the comments,remove the unwanted WARN message, replace drm_gem_object_unreference() with i915_gem_object_put().Make the prototypes in intel_huc.h non-extern. v10: rebased. Update the file construction done by HuC. It is similar to GuC.Adopted the approach used in- https://patchwork.freedesktop.org/patch/104355/ v11: Fix warnings remove old declaration v12: Change dev to dev_priv in macro definition. Corrected comments. v13: rebased. v14: rebased on top of drm-tip v15: rebased. Updated functions intel_huc_load(),intel_huc_init() and intel_uc_fw_fetch() to accept dev_priv instead of dev. Moved contents of intel_huc.h to intel_uc.h v16: change SKL_FW_ to SKL_HUC_FW_. Add intel_ prefix to guc_wopcm_size(). Remove unwanted checks in intel_uc.h. Rename huc_fw in struct intel_huc to simply fw to avoid redundency. Cc: Tvrtko Ursulin Tested-by: Xiang Haihao Signed-off-by: Anusha Srivatsa Signed-off-by: Alex Dai Signed-off-by: Peter Antoine --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_guc_reg.h | 3 + drivers/gpu/drm/i915/intel_guc_loader.c | 11 +- drivers/gpu/drm/i915/intel_huc_loader.c | 264 drivers/gpu/drm/i915/intel_uc.h | 18 +++ 7 files changed, 297 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 5196509..45ae124 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -57,6 +57,7 @@ i915-y += i915_cmd_parser.o \ # general-purpose microcontroller (GuC) support i915-y += intel_uc.o \ intel_guc_loader.o \ + intel_huc_loader.o \ i915_guc_submission.o # autogenerated null render state diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6428588..85a47c2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -600,6 +600,7 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) goto cleanup_irq; + intel_huc_init(dev_priv); intel_guc_init(dev_priv); ret = i915_gem_init(dev_priv); @@ -627,6 +628,7 @@ static int i915_load_modeset_init(struct drm_device *dev) DRM_ERROR("failed to idle hardware; continuing to unload!\n"); i915_gem_fini(dev_priv); cleanup_irq: + intel_huc_fini(dev); intel_guc_fini(dev_priv); drm_irq_uninstall(dev); intel_teardown_gmbus(dev_priv); @@ -1313,7 +1315,7 @@ void i915_driver_unload(struct drm_device *dev) /* Flush any outstanding unpin_work. */ drain_workqueue(dev_priv->wq); - + intel_huc_fini(dev); intel_guc_fini(dev_priv); i915_gem_fini(dev_priv); intel_fbc_cleanup_cfb(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4199d26..bd5f235 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2134,6 +2134,7 @@ struct drm_i915_private { struct intel_gvt *gvt; + struct intel_huc huc; struct intel_guc guc; struct intel_csr csr; @@ -2908,7 +2909,7 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_GUC(dev_priv) ((dev_priv)->info.has_guc) #define HAS_GUC_UCODE(dev_priv)(HAS_GUC(dev_priv)) #define HAS_GUC_SCHED(dev_priv)(HAS_GUC(dev_priv)) - +#define HAS_HUC_UCODE(dev_priv)(HAS_GUC(dev_priv)) #define HAS_RESOURCE_STREAMER(dev_priv) ((dev_priv)->info.has_resource_streamer) #define HAS_POOLED_EU(dev_priv)((dev_priv)->info.has_pooled_eu) diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index 5e638fc..f9829f6 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++
[Intel-gfx] ✗ Fi.CI.BAT: failure for series starting with [v2,01/40] drm/i915: Use the MRU stack search after evicting (rev3)
== Series Details == Series: series starting with [v2,01/40] drm/i915: Use the MRU stack search after evicting (rev3) URL : https://patchwork.freedesktop.org/series/16906/ State : failure == Summary == CC net/ipv4/tcp_cubic.o CC net/ipv4/xfrm4_policy.o LD drivers/net/phy/built-in.o CC net/ipv4/xfrm4_state.o CC net/ipv4/xfrm4_input.o CC net/ipv4/xfrm4_output.o CC net/ipv4/xfrm4_protocol.o CC net/ipv6/exthdrs_offload.o CC net/ipv6/inet6_hashtables.o CC net/ipv6/mcast_snoop.o LD drivers/rtc/built-in.o LD drivers/pci/pcie/pcieportdrv.o LD [M] drivers/net/ethernet/intel/igbvf/igbvf.o LD drivers/acpi/acpica/acpi.o LD kernel/events/built-in.o LD net/netlink/built-in.o LD net/unix/unix_diag.o LD kernel/sched/built-in.o LD drivers/acpi/acpica/built-in.o LD drivers/pci/pcie/aer/aerdriver.o LD kernel/built-in.o LD drivers/pci/pcie/aer/built-in.o LD drivers/usb/gadget/libcomposite.o LD drivers/usb/storage/usb-storage.o LD drivers/pci/pcie/built-in.o LD drivers/acpi/built-in.o LD drivers/usb/storage/built-in.o LD net/key/built-in.o LD drivers/tty/serial/8250/8250.o LD [M] drivers/usb/serial/usbserial.o LD drivers/thermal/thermal_sys.o LD mm/built-in.o LD drivers/thermal/built-in.o LD [M] drivers/misc/mei/mei-me.o LD lib/raid6/raid6_pq.o LD drivers/misc/built-in.o LD lib/raid6/built-in.o LD drivers/spi/built-in.o LD drivers/iommu/built-in.o LD drivers/usb/gadget/udc/udc-core.o LD drivers/usb/gadget/udc/built-in.o LD drivers/usb/gadget/built-in.o scripts/Makefile.build:544: recipe for target 'drivers/gpu/drm' failed make[2]: *** [drivers/gpu/drm] Error 2 scripts/Makefile.build:544: recipe for target 'drivers/gpu' failed make[1]: *** [drivers/gpu] Error 2 make[1]: *** Waiting for unfinished jobs LD net/packet/built-in.o LD drivers/video/fbdev/core/fb.o LD drivers/video/fbdev/core/built-in.o LD [M] sound/pci/hda/snd-hda-codec-generic.o LD drivers/video/fbdev/built-in.o LD [M] drivers/net/ethernet/intel/e1000/e1000.o LD sound/pci/built-in.o LD net/unix/unix.o LD net/unix/built-in.o LD drivers/scsi/scsi_mod.o LD drivers/video/console/built-in.o LD drivers/video/built-in.o LD sound/built-in.o LD [M] drivers/net/ethernet/broadcom/genet/genet.o LD drivers/tty/serial/8250/8250_base.o LD drivers/tty/serial/8250/built-in.o LD drivers/tty/serial/built-in.o LD drivers/pci/built-in.o LD drivers/scsi/sd_mod.o LD drivers/scsi/built-in.o LD [M] drivers/net/ethernet/intel/igb/igb.o LD drivers/md/md-mod.o AR lib/lib.a LD drivers/md/built-in.o EXPORTS lib/lib-ksyms.o CC arch/x86/kernel/cpu/capflags.o LD arch/x86/kernel/cpu/built-in.o LD drivers/usb/core/usbcore.o LD arch/x86/kernel/built-in.o LD drivers/usb/core/built-in.o LD drivers/usb/host/xhci-hcd.o LD arch/x86/built-in.o LD drivers/tty/vt/built-in.o LD net/xfrm/built-in.o LD drivers/tty/built-in.o LD net/ipv6/ipv6.o LD fs/btrfs/btrfs.o LD net/ipv6/built-in.o LD lib/built-in.o LD fs/btrfs/built-in.o LD fs/ext4/ext4.o LD fs/ext4/built-in.o LD drivers/usb/host/built-in.o LD drivers/usb/built-in.o LD fs/built-in.o LD net/ipv4/built-in.o LD [M] drivers/net/ethernet/intel/e1000e/e1000e.o LD net/core/built-in.o LD net/built-in.o LD drivers/net/ethernet/built-in.o LD drivers/net/built-in.o Makefile:988: recipe for target 'drivers' failed make: *** [drivers] Error 2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to getparams
On Fri, Dec 16, 2016 at 05:21:38PM +0100, Arkadiusz Hiler wrote: > On Fri, Dec 16, 2016 at 04:12:36PM +, Chris Wilson wrote: > > On Fri, Dec 16, 2016 at 03:43:46PM +0100, Arkadiusz Hiler wrote: > > > On Thu, Dec 15, 2016 at 10:42:53PM +, Chris Wilson wrote: > > > > On Thu, Dec 15, 2016 at 02:29:50PM -0800, anushasr wrote: > > > > > From: Peter Antoine> > > > > > > > > > This patch will allow for getparams to return the status of the HuC. > > > > > As the HuC has to be validated by the GuC this patch uses the > > > > > validated > > > > > status to show when the HuC is loaded and ready for use. You cannot > > > > > use > > > > > the loaded status as with the GuC as the HuC is verified after it is > > > > > loaded and is not usable until it is verified. > > > > > > > > > > v2: removed the forewakes as the registers are already force-woken. > > > > > (T.Ursulin) > > > > > v4: rebased. > > > > > v5: rebased on top of drm-tip. > > > > > v6: rebased. Removed any reference to intel_huc.h > > > > > v7: rebased. Rename I915_PARAM_HAS_HUC to I915_PARAM_HUC_STATUS. > > > > > Remove intel_is_huc_valid() since it is used only in one place. > > > > > Put the case of I915_PARAM_HAS_HUC() in the right place. > > > > > > > > > > Signed-off-by: Peter Antoine > > > > > Reviewed-by: Arkadiusz Hiler > > > > > --- > > > > > drivers/gpu/drm/i915/i915_drv.c | 4 > > > > > drivers/gpu/drm/i915/intel_huc_loader.c | 1 - > > > > > include/uapi/drm/i915_drm.h | 1 + > > > > > 3 files changed, 5 insertions(+), 1 deletion(-) > > > > > > > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.c > > > > > b/drivers/gpu/drm/i915/i915_drv.c > > > > > index 85a47c2..0bc016d 100644 > > > > > --- a/drivers/gpu/drm/i915/i915_drv.c > > > > > +++ b/drivers/gpu/drm/i915/i915_drv.c > > > > > @@ -49,6 +49,7 @@ > > > > > #include "i915_trace.h" > > > > > #include "i915_vgpu.h" > > > > > #include "intel_drv.h" > > > > > +#include "intel_uc.h" > > > > > > > > > > static struct drm_driver driver; > > > > > > > > > > @@ -315,6 +316,9 @@ static int i915_getparam(struct drm_device *dev, > > > > > void *data, > > > > > case I915_PARAM_MIN_EU_IN_POOL: > > > > > value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; > > > > > break; > > > > > + case I915_PARAM_HUC_STATUS: > > > > > + value = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED; > > > > > > > > Same question as last time: does the device need to be awake? We know is > > > > one of the GT power wells, so presumably we need an rpm_get/rpm_put as > > > > well to access the register. > > > > -Chris > > > > > > I get: > > > > > > [ 1588.570174] [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 PRE > > > 24704 > > > [ 1588.571285] [drm:intel_runtime_suspend [i915]] Suspending device > > > [ 1588.575768] [drm:intel_runtime_suspend [i915]] Device suspended > > > [ 1588.577156] [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 POST > > > 24704 > > > [ 1588.578259] [drm:intel_runtime_resume [i915]] Resuming device > > > > > > consistently from: > > > > > > value = I915_READ(HUC_STATUS2); > > > DRM_DEBUG_DRIVER("HUC_STATUS2 PRE %d\n", value); > > > i915_pm_ops.runtime_suspend(dev_priv->drm.dev); > > > > > > value = I915_READ(HUC_STATUS2); > > > DRM_DEBUG_DRIVER("HUC_STATUS2 POST %d\n", value); > > > i915_pm_ops.runtime_resume(dev_priv->drm.dev); > > > > Also do the test with i915.mmio_debug= > > -Chris > > Same effect. Works. Ok, then just mark up that we don't need rpm here so that we don't freak out in future scans for mmio access outside of rpm. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/8] drm/i915/huc: Add HuC fw loading support
On Fri, Dec 16, 2016 at 04:13:14PM +, Tvrtko Ursulin wrote: > > On 15/12/2016 22:29, anushasr wrote: > > From: Anusha Srivatsa> > > > The HuC loading process is similar to GuC. The intel_uc_fw_fetch() > > is used for both cases. > > > > HuC loading needs to be before GuC loading. The WOPCM setting must > > be done early before loading any of them. > > > > v2: rebased on-top of drm-intel-nightly. > > removed if(HAS_GUC()) before the guc call. (D.Gordon) > > update huc_version number of format. > > v3: rebased to drm-intel-nightly, changed the file name format to > > match the one in the huc package. > > Changed dev->dev_private to to_i915() > > v4: moved function back to where it was. > > change wait_for_atomic to wait_for. > > v5: rebased + comment changes. > > v7: rebased. > > v8: rebased. > > v9: rebased. Changed the year in the copyright message to reflect > > the right year.Correct the comments,remove the unwanted WARN message, > > replace drm_gem_object_unreference() with i915_gem_object_put().Make the > > prototypes in intel_huc.h non-extern. > > v10: rebased. Update the file construction done by HuC. It is similar to > > GuC.Adopted the approach used in- > > https://patchwork.freedesktop.org/patch/104355/ > > v11: Fix warnings remove old declaration > > v12: Change dev to dev_priv in macro definition. > > Corrected comments. > > v13: rebased. > > v14: rebased on top of drm-tip > > v15: rebased. Updated functions intel_huc_load(),intel_huc_init() and > > intel_uc_fw_fetch() to accept dev_priv instead of dev. Moved contents > > of intel_huc.h to intel_uc.h > > v16: change SKL_FW_ to SKL_HUC_FW_. Add intel_ prefix to guc_wopcm_size(). > > Remove unwanted checks in intel_uc.h. Rename huc_fw in struct intel_huc to > > simply fw to avoid redundency. > > > > Cc: Tvrtko Ursulin > > Tested-by: Xiang Haihao > > Signed-off-by: Anusha Srivatsa > > Signed-off-by: Alex Dai > > Signed-off-by: Peter Antoine > > --- > > drivers/gpu/drm/i915/Makefile | 1 + > > drivers/gpu/drm/i915/i915_drv.c | 4 +- > > drivers/gpu/drm/i915/i915_drv.h | 3 +- > > drivers/gpu/drm/i915/i915_guc_reg.h | 3 + > > drivers/gpu/drm/i915/intel_guc_loader.c | 11 +- > > drivers/gpu/drm/i915/intel_huc_loader.c | 264 > > > > drivers/gpu/drm/i915/intel_uc.h | 18 +++ > > 7 files changed, 297 insertions(+), 7 deletions(-) > > create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c > > > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > > index 5196509..45ae124 100644 > > --- a/drivers/gpu/drm/i915/Makefile > > +++ b/drivers/gpu/drm/i915/Makefile > > @@ -57,6 +57,7 @@ i915-y += i915_cmd_parser.o \ > > # general-purpose microcontroller (GuC) support > > i915-y += intel_uc.o \ > > intel_guc_loader.o \ > > + intel_huc_loader.o \ > > i915_guc_submission.o > > > > # autogenerated null render state > > diff --git a/drivers/gpu/drm/i915/i915_drv.c > > b/drivers/gpu/drm/i915/i915_drv.c > > index 6428588..85a47c2 100644 > > --- a/drivers/gpu/drm/i915/i915_drv.c > > +++ b/drivers/gpu/drm/i915/i915_drv.c > > @@ -600,6 +600,7 @@ static int i915_load_modeset_init(struct drm_device > > *dev) > > if (ret) > > goto cleanup_irq; > > > > + intel_huc_init(dev_priv); > > intel_guc_init(dev_priv); > > > > ret = i915_gem_init(dev_priv); > > @@ -627,6 +628,7 @@ static int i915_load_modeset_init(struct drm_device > > *dev) > > DRM_ERROR("failed to idle hardware; continuing to unload!\n"); > > i915_gem_fini(dev_priv); > > cleanup_irq: > > + intel_huc_fini(dev); > > intel_guc_fini(dev_priv); > > drm_irq_uninstall(dev); > > intel_teardown_gmbus(dev_priv); > > @@ -1313,7 +1315,7 @@ void i915_driver_unload(struct drm_device *dev) > > > > /* Flush any outstanding unpin_work. */ > > drain_workqueue(dev_priv->wq); > > - > > + intel_huc_fini(dev); > > intel_guc_fini(dev_priv); > > i915_gem_fini(dev_priv); > > intel_fbc_cleanup_cfb(dev_priv); > > diff --git a/drivers/gpu/drm/i915/i915_drv.h > > b/drivers/gpu/drm/i915/i915_drv.h > > index 4199d26..bd5f235 100644 > > --- a/drivers/gpu/drm/i915/i915_drv.h > > +++ b/drivers/gpu/drm/i915/i915_drv.h > > @@ -2134,6 +2134,7 @@ struct drm_i915_private { > > > > struct intel_gvt *gvt; > > > > + struct intel_huc huc; > > struct intel_guc guc; > > > > struct intel_csr csr; > > @@ -2908,7 +2909,7 @@ intel_info(const struct drm_i915_private *dev_priv) > > #define HAS_GUC(dev_priv) ((dev_priv)->info.has_guc) > > #define HAS_GUC_UCODE(dev_priv)(HAS_GUC(dev_priv)) > > #define HAS_GUC_SCHED(dev_priv)(HAS_GUC(dev_priv)) > > - > > +#define HAS_HUC_UCODE(dev_priv)(HAS_GUC(dev_priv)) > > #define
Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to getparams
On Fri, Dec 16, 2016 at 04:12:36PM +, Chris Wilson wrote: > On Fri, Dec 16, 2016 at 03:43:46PM +0100, Arkadiusz Hiler wrote: > > On Thu, Dec 15, 2016 at 10:42:53PM +, Chris Wilson wrote: > > > On Thu, Dec 15, 2016 at 02:29:50PM -0800, anushasr wrote: > > > > From: Peter Antoine> > > > > > > > This patch will allow for getparams to return the status of the HuC. > > > > As the HuC has to be validated by the GuC this patch uses the validated > > > > status to show when the HuC is loaded and ready for use. You cannot use > > > > the loaded status as with the GuC as the HuC is verified after it is > > > > loaded and is not usable until it is verified. > > > > > > > > v2: removed the forewakes as the registers are already force-woken. > > > > (T.Ursulin) > > > > v4: rebased. > > > > v5: rebased on top of drm-tip. > > > > v6: rebased. Removed any reference to intel_huc.h > > > > v7: rebased. Rename I915_PARAM_HAS_HUC to I915_PARAM_HUC_STATUS. > > > > Remove intel_is_huc_valid() since it is used only in one place. > > > > Put the case of I915_PARAM_HAS_HUC() in the right place. > > > > > > > > Signed-off-by: Peter Antoine > > > > Reviewed-by: Arkadiusz Hiler > > > > --- > > > > drivers/gpu/drm/i915/i915_drv.c | 4 > > > > drivers/gpu/drm/i915/intel_huc_loader.c | 1 - > > > > include/uapi/drm/i915_drm.h | 1 + > > > > 3 files changed, 5 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.c > > > > b/drivers/gpu/drm/i915/i915_drv.c > > > > index 85a47c2..0bc016d 100644 > > > > --- a/drivers/gpu/drm/i915/i915_drv.c > > > > +++ b/drivers/gpu/drm/i915/i915_drv.c > > > > @@ -49,6 +49,7 @@ > > > > #include "i915_trace.h" > > > > #include "i915_vgpu.h" > > > > #include "intel_drv.h" > > > > +#include "intel_uc.h" > > > > > > > > static struct drm_driver driver; > > > > > > > > @@ -315,6 +316,9 @@ static int i915_getparam(struct drm_device *dev, > > > > void *data, > > > > case I915_PARAM_MIN_EU_IN_POOL: > > > > value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; > > > > break; > > > > + case I915_PARAM_HUC_STATUS: > > > > + value = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED; > > > > > > Same question as last time: does the device need to be awake? We know is > > > one of the GT power wells, so presumably we need an rpm_get/rpm_put as > > > well to access the register. > > > -Chris > > > > I get: > > > > [ 1588.570174] [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 PRE 24704 > > [ 1588.571285] [drm:intel_runtime_suspend [i915]] Suspending device > > [ 1588.575768] [drm:intel_runtime_suspend [i915]] Device suspended > > [ 1588.577156] [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 POST 24704 > > [ 1588.578259] [drm:intel_runtime_resume [i915]] Resuming device > > > > consistently from: > > > > value = I915_READ(HUC_STATUS2); > > DRM_DEBUG_DRIVER("HUC_STATUS2 PRE %d\n", value); > > i915_pm_ops.runtime_suspend(dev_priv->drm.dev); > > > > value = I915_READ(HUC_STATUS2); > > DRM_DEBUG_DRIVER("HUC_STATUS2 POST %d\n", value); > > i915_pm_ops.runtime_resume(dev_priv->drm.dev); > > Also do the test with i915.mmio_debug= > -Chris Same effect. Works. -- Cheers, Arek ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 5/8] drm/i915/HuC: Add KBL huC loading Support
On 15/12/2016 22:29, anushasr wrote: From: Anusha SrivatsaThis patch adds the support to load HuC on KBL Version 2.0 v2: rebased. v3: rebased on top of drm-tip v4: rebased. v5: rebased. Rename KBL_FW_ to KBL_HUC_FW_ Cc: Jeff Mcgee Signed-off-by: Anusha Srivatsa Reviewed-by: Jeff McGee --- drivers/gpu/drm/i915/intel_huc_loader.c | 16 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c index f36efd4..d8c5266 100644 --- a/drivers/gpu/drm/i915/intel_huc_loader.c +++ b/drivers/gpu/drm/i915/intel_huc_loader.c @@ -48,6 +48,10 @@ #define SKL_HUC_FW_MINOR 07 #define SKL_BLD_NUM 1398 +#define KBL_HUC_FW_MAJOR 02 +#define KBL_HUC_FW_MINOR 00 +#define KBL_BLD_NUM 1810 + #define HUC_FW_PATH(platform, major, minor, bld_num) \ "i915/" __stringify(platform) "_huc_ver" __stringify(major) "_" \ __stringify(minor) "_" __stringify(bld_num) ".bin" @@ -59,6 +63,11 @@ MODULE_FIRMWARE(I915_SKL_HUC_UCODE); #define I915_BXT_HUC_UCODE HUC_FW_PATH(bxt, BXT_HUC_FW_MAJOR, \ BXT_HUC_FW_MINOR, BXT_BLD_NUM) MODULE_FIRMWARE(I915_BXT_HUC_UCODE); + +#define I915_KBL_HUC_UCODE HUC_FW_PATH(kbl, KBL_HUC_FW_MAJOR, \ + KBL_HUC_FW_MINOR, KBL_BLD_NUM) +MODULE_FIRMWARE(I915_KBL_HUC_UCODE); + /** * huc_ucode_xfer() - DMA's the firmware * @dev_priv: the drm device @@ -168,8 +177,15 @@ void intel_huc_init(struct drm_i915_private *dev_priv) fw_path = I915_BXT_HUC_UCODE; huc_fw->major_ver_wanted = BXT_HUC_FW_MAJOR; huc_fw->minor_ver_wanted = BXT_HUC_FW_MINOR; + } else if (IS_KABYLAKE(dev_priv)) { + fw_path = I915_KBL_HUC_UCODE; + huc_fw->major_ver_wanted = KBL_HUC_FW_MAJOR; + huc_fw->minor_ver_wanted = KBL_HUC_FW_MINOR; } + if (fw_path == NULL) + return; + This looks suspiciously out of place in this patch. What's the reason for it? Regards, Tvrtko huc_fw->uc_fw_path = fw_path; huc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 7/8] drm/i915/huc: Support HuC authentication
On Thu, Dec 15, 2016 at 02:29:49PM -0800, anushasr wrote: > From: Peter Antoine> > The HuC authentication is done by host2guc call. The HuC RSA keys > are sent to GuC for authentication. > > v2: rebased on top of drm-intel-nightly. > changed name format and upped version 1.7. > v3: rebased on top of drm-intel-nightly. > v4: changed wait_for_automic to wait_for > v5: rebased. > v7: rebased. > v8: rebased. > v9: rebased. Rename intel_huc_auh() to intel_guc_auth_huc() > and place the prototype in intel_guc.h,correct the comments. > v10: rebased. > v11: rebased. > v12: rebased on top of drm-tip > v13: rebased. Moved intel_guc_auth_huc from i915_guc_submission.c > to intel_uc.c.Update dev to dev_priv in intel_guc_auth_huc(). > Renamed HOST2GUC_ACTION_AUTHENTICATE_HUC TO INTEL_GUC_ACTION_ > AUTHENTICATE_HUC > v14: rebased. > > Tested-by: Xiang Haihao > Signed-off-by: Anusha Srivatsa > Signed-off-by: Alex Dai > Signed-off-by: Peter Antoine > --- > drivers/gpu/drm/i915/intel_guc_fwif.h | 1 + > drivers/gpu/drm/i915/intel_guc_loader.c | 2 ++ > drivers/gpu/drm/i915/intel_uc.c | 62 > + > drivers/gpu/drm/i915/intel_uc.h | 1 + > 4 files changed, 66 insertions(+) > > diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h > b/drivers/gpu/drm/i915/intel_guc_fwif.h > index ed1ab40..ce4e05e 100644 > --- a/drivers/gpu/drm/i915/intel_guc_fwif.h > +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h > @@ -506,6 +506,7 @@ enum intel_guc_action { > INTEL_GUC_ACTION_EXIT_S_STATE = 0x502, > INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003, > INTEL_GUC_ACTION_UK_LOG_ENABLE_LOGGING = 0x0E000, > + INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, > INTEL_GUC_ACTION_LIMIT > }; > > diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c > b/drivers/gpu/drm/i915/intel_guc_loader.c > index 2257495..7605f36 100644 > --- a/drivers/gpu/drm/i915/intel_guc_loader.c > +++ b/drivers/gpu/drm/i915/intel_guc_loader.c > @@ -529,6 +529,8 @@ int intel_guc_setup(struct drm_i915_private *dev_priv) > intel_uc_fw_status_repr(guc_fw->fetch_status), > intel_uc_fw_status_repr(guc_fw->load_status)); > > + intel_guc_auth_huc(dev_priv); > + > if (i915.enable_guc_submission) { > if (i915.guc_log_level >= 0) > gen9_enable_guc_interrupts(dev_priv); > diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c > index 8ae6795..b90ac57 100644 > --- a/drivers/gpu/drm/i915/intel_uc.c > +++ b/drivers/gpu/drm/i915/intel_uc.c > @@ -138,3 +138,65 @@ int intel_guc_log_control(struct intel_guc *guc, u32 > control_val) > > return intel_guc_send(guc, action, ARRAY_SIZE(action)); > } > + > +/** > + * intel_guc_auth_huc() - authenticate ucode > + * @dev_priv: the drm_i915_device > + * > + * Triggers a HuC fw authentication request to the GuC via intel_guc_action_ > + * authenticate_huc interface. > + * interface. > + */ > +void intel_guc_auth_huc(struct drm_i915_private *dev_priv) > +{ > + struct intel_guc *guc = _priv->guc; > + struct intel_huc *huc = _priv->huc; > + struct i915_vma *vma; > + int ret; > + u32 data[2]; > + > + /* Bypass the case where there is no HuC firmware */ > + if (huc->fw.fetch_status == INTEL_UC_FIRMWARE_NONE || > + huc->fw.load_status == INTEL_UC_FIRMWARE_NONE) > + return; > + > + if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) { > + DRM_ERROR("HuC: GuC fw wasn't loaded. Can't authenticate"); Why this DRM_ERROR does not have tailing "\n"? Same goes for couple more in here. > + return; > + } > + > + if (huc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) { > + DRM_ERROR("HuC: fw wasn't loaded. Nothing to authenticate"); > + return; > + } > + > + vma = i915_gem_object_ggtt_pin(huc->fw.uc_fw_obj, NULL, 0, 0, 0); > + if (IS_ERR(vma)) { > + DRM_DEBUG_DRIVER("pin failed %d\n", (int)PTR_ERR(vma)); > + return; > + } > + > + > + /* Invalidate GuC TLB to let GuC take the latest updates to GTT. */ > + I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); > + > + /* Specify auth action and where public signature is. */ > + data[0] = INTEL_GUC_ACTION_AUTHENTICATE_HUC; > + data[1] = i915_ggtt_offset(vma) + huc->fw.rsa_offset; > + > + ret = intel_guc_send(guc, data, ARRAY_SIZE(data)); > + if (ret) { > + DRM_ERROR("HuC: GuC did not ack Auth request\n"); > + goto out; > + } > + > + /* Check authentication status, it should be done by now */ > + ret = wait_for((I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED) > 0, 50); > + if (ret) { > + DRM_ERROR("HuC: Authentication failed\n"); > + goto out; > + } > + > +out: > + i915_vma_unpin(vma); > +}
Re: [Intel-gfx] [PATCH 4/8] drm/i915/huc: Add BXT HuC Loading Support
On 15/12/2016 22:29, anushasr wrote: From: Anusha SrivatsaThis patch adds the HuC Loading for the BXT by using the updated file construction. Version 1.7 of the HuC firmware. v2: rebased. v3: rebased on top of drm-tip v4: rebased. v5: rebased. Rename BXT_FW_MAJOR to BXT_HUC_FW_ Cc: Jeff Mcgee Signed-off-by: Anusha Srivatsa Reviewed-by: Jeff McGee --- drivers/gpu/drm/i915/intel_huc_loader.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c b/drivers/gpu/drm/i915/intel_huc_loader.c index 0f929cc..f36efd4 100644 --- a/drivers/gpu/drm/i915/intel_huc_loader.c +++ b/drivers/gpu/drm/i915/intel_huc_loader.c @@ -40,6 +40,10 @@ * Note that HuC firmware loading must be done before GuC loading. */ +#define BXT_HUC_FW_MAJOR 01 +#define BXT_HUC_FW_MINOR 07 +#define BXT_BLD_NUM 1398 + #define SKL_HUC_FW_MAJOR 01 #define SKL_HUC_FW_MINOR 07 #define SKL_BLD_NUM 1398 @@ -52,6 +56,9 @@ SKL_HUC_FW_MINOR, SKL_BLD_NUM) MODULE_FIRMWARE(I915_SKL_HUC_UCODE); +#define I915_BXT_HUC_UCODE HUC_FW_PATH(bxt, BXT_HUC_FW_MAJOR, \ + BXT_HUC_FW_MINOR, BXT_BLD_NUM) +MODULE_FIRMWARE(I915_BXT_HUC_UCODE); More curiosity - given the versions between SKL and BXT are identical - is it actually the same binary file in both cases? Regards, Tvrtko /** * huc_ucode_xfer() - DMA's the firmware * @dev_priv: the drm device @@ -157,6 +164,10 @@ void intel_huc_init(struct drm_i915_private *dev_priv) fw_path = I915_SKL_HUC_UCODE; huc_fw->major_ver_wanted = SKL_HUC_FW_MAJOR; huc_fw->minor_ver_wanted = SKL_HUC_FW_MINOR; + } else if (IS_BROXTON(dev_priv)) { + fw_path = I915_BXT_HUC_UCODE; + huc_fw->major_ver_wanted = BXT_HUC_FW_MAJOR; + huc_fw->minor_ver_wanted = BXT_HUC_FW_MINOR; } huc_fw->uc_fw_path = fw_path; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/8] drm/i915/huc: Add HuC fw loading support
On 15/12/2016 22:29, anushasr wrote: From: Anusha SrivatsaThe HuC loading process is similar to GuC. The intel_uc_fw_fetch() is used for both cases. HuC loading needs to be before GuC loading. The WOPCM setting must be done early before loading any of them. v2: rebased on-top of drm-intel-nightly. removed if(HAS_GUC()) before the guc call. (D.Gordon) update huc_version number of format. v3: rebased to drm-intel-nightly, changed the file name format to match the one in the huc package. Changed dev->dev_private to to_i915() v4: moved function back to where it was. change wait_for_atomic to wait_for. v5: rebased + comment changes. v7: rebased. v8: rebased. v9: rebased. Changed the year in the copyright message to reflect the right year.Correct the comments,remove the unwanted WARN message, replace drm_gem_object_unreference() with i915_gem_object_put().Make the prototypes in intel_huc.h non-extern. v10: rebased. Update the file construction done by HuC. It is similar to GuC.Adopted the approach used in- https://patchwork.freedesktop.org/patch/104355/ v11: Fix warnings remove old declaration v12: Change dev to dev_priv in macro definition. Corrected comments. v13: rebased. v14: rebased on top of drm-tip v15: rebased. Updated functions intel_huc_load(),intel_huc_init() and intel_uc_fw_fetch() to accept dev_priv instead of dev. Moved contents of intel_huc.h to intel_uc.h v16: change SKL_FW_ to SKL_HUC_FW_. Add intel_ prefix to guc_wopcm_size(). Remove unwanted checks in intel_uc.h. Rename huc_fw in struct intel_huc to simply fw to avoid redundency. Cc: Tvrtko Ursulin Tested-by: Xiang Haihao Signed-off-by: Anusha Srivatsa Signed-off-by: Alex Dai Signed-off-by: Peter Antoine --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_guc_reg.h | 3 + drivers/gpu/drm/i915/intel_guc_loader.c | 11 +- drivers/gpu/drm/i915/intel_huc_loader.c | 264 drivers/gpu/drm/i915/intel_uc.h | 18 +++ 7 files changed, 297 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/i915/intel_huc_loader.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 5196509..45ae124 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -57,6 +57,7 @@ i915-y += i915_cmd_parser.o \ # general-purpose microcontroller (GuC) support i915-y += intel_uc.o \ intel_guc_loader.o \ + intel_huc_loader.o \ i915_guc_submission.o # autogenerated null render state diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6428588..85a47c2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -600,6 +600,7 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) goto cleanup_irq; + intel_huc_init(dev_priv); intel_guc_init(dev_priv); ret = i915_gem_init(dev_priv); @@ -627,6 +628,7 @@ static int i915_load_modeset_init(struct drm_device *dev) DRM_ERROR("failed to idle hardware; continuing to unload!\n"); i915_gem_fini(dev_priv); cleanup_irq: + intel_huc_fini(dev); intel_guc_fini(dev_priv); drm_irq_uninstall(dev); intel_teardown_gmbus(dev_priv); @@ -1313,7 +1315,7 @@ void i915_driver_unload(struct drm_device *dev) /* Flush any outstanding unpin_work. */ drain_workqueue(dev_priv->wq); - + intel_huc_fini(dev); intel_guc_fini(dev_priv); i915_gem_fini(dev_priv); intel_fbc_cleanup_cfb(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4199d26..bd5f235 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2134,6 +2134,7 @@ struct drm_i915_private { struct intel_gvt *gvt; + struct intel_huc huc; struct intel_guc guc; struct intel_csr csr; @@ -2908,7 +2909,7 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_GUC(dev_priv) ((dev_priv)->info.has_guc) #define HAS_GUC_UCODE(dev_priv)(HAS_GUC(dev_priv)) #define HAS_GUC_SCHED(dev_priv)(HAS_GUC(dev_priv)) - +#define HAS_HUC_UCODE(dev_priv)(HAS_GUC(dev_priv)) #define HAS_RESOURCE_STREAMER(dev_priv) ((dev_priv)->info.has_resource_streamer) #define HAS_POOLED_EU(dev_priv)((dev_priv)->info.has_pooled_eu) diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index 5e638fc..f9829f6 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ b/drivers/gpu/drm/i915/i915_guc_reg.h @@ -61,9 +61,12 @@ #define DMA_ADDRESS_SPACE_GTT (8 << 16) #define DMA_COPY_SIZE
Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to getparams
On Fri, Dec 16, 2016 at 03:43:46PM +0100, Arkadiusz Hiler wrote: > On Thu, Dec 15, 2016 at 10:42:53PM +, Chris Wilson wrote: > > On Thu, Dec 15, 2016 at 02:29:50PM -0800, anushasr wrote: > > > From: Peter Antoine> > > > > > This patch will allow for getparams to return the status of the HuC. > > > As the HuC has to be validated by the GuC this patch uses the validated > > > status to show when the HuC is loaded and ready for use. You cannot use > > > the loaded status as with the GuC as the HuC is verified after it is > > > loaded and is not usable until it is verified. > > > > > > v2: removed the forewakes as the registers are already force-woken. > > > (T.Ursulin) > > > v4: rebased. > > > v5: rebased on top of drm-tip. > > > v6: rebased. Removed any reference to intel_huc.h > > > v7: rebased. Rename I915_PARAM_HAS_HUC to I915_PARAM_HUC_STATUS. > > > Remove intel_is_huc_valid() since it is used only in one place. > > > Put the case of I915_PARAM_HAS_HUC() in the right place. > > > > > > Signed-off-by: Peter Antoine > > > Reviewed-by: Arkadiusz Hiler > > > --- > > > drivers/gpu/drm/i915/i915_drv.c | 4 > > > drivers/gpu/drm/i915/intel_huc_loader.c | 1 - > > > include/uapi/drm/i915_drm.h | 1 + > > > 3 files changed, 5 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.c > > > b/drivers/gpu/drm/i915/i915_drv.c > > > index 85a47c2..0bc016d 100644 > > > --- a/drivers/gpu/drm/i915/i915_drv.c > > > +++ b/drivers/gpu/drm/i915/i915_drv.c > > > @@ -49,6 +49,7 @@ > > > #include "i915_trace.h" > > > #include "i915_vgpu.h" > > > #include "intel_drv.h" > > > +#include "intel_uc.h" > > > > > > static struct drm_driver driver; > > > > > > @@ -315,6 +316,9 @@ static int i915_getparam(struct drm_device *dev, void > > > *data, > > > case I915_PARAM_MIN_EU_IN_POOL: > > > value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; > > > break; > > > + case I915_PARAM_HUC_STATUS: > > > + value = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED; > > > > Same question as last time: does the device need to be awake? We know is > > one of the GT power wells, so presumably we need an rpm_get/rpm_put as > > well to access the register. > > -Chris > > I get: > > [ 1588.570174] [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 PRE 24704 > [ 1588.571285] [drm:intel_runtime_suspend [i915]] Suspending device > [ 1588.575768] [drm:intel_runtime_suspend [i915]] Device suspended > [ 1588.577156] [drm:i915_huc_load_status_info [i915]] HUC_STATUS2 POST 24704 > [ 1588.578259] [drm:intel_runtime_resume [i915]] Resuming device > > consistently from: > > value = I915_READ(HUC_STATUS2); > DRM_DEBUG_DRIVER("HUC_STATUS2 PRE %d\n", value); > i915_pm_ops.runtime_suspend(dev_priv->drm.dev); > > value = I915_READ(HUC_STATUS2); > DRM_DEBUG_DRIVER("HUC_STATUS2 POST %d\n", value); > i915_pm_ops.runtime_resume(dev_priv->drm.dev); Also do the test with i915.mmio_debug= -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] Guc parameter Handling
On Thu, Dec 15, 2016 at 10:36:40PM +, Srivatsa, Anusha wrote: > Hi All, > > I was wondering if we intend to keep -1 and 2 for the > enable_guc_submission parameter. Since now we are gating guc loads if > either guc_submission or enable_huc parameter is set, why have a > -1(platform default) and 2(forcefully load) option? We anyway do not > have any special default set per platform. For now the default is 0 on > all platforms. Moving forward if GuC gets more stable and we want to > set a default to a certain platform, we can add -1 then. > > Also, why have a 2? We can use enable_guc_submission=1 in order to > make sure the guc is loaded and guc_submission is enabled and set > enable_guc_submission=0 to make sure guc submission is not used. I've asked around on IRC yesterday for the exact same thing, and it seems that no one realy does remembery why the "2" was introduced in the first place. We not simplifying it, if we do not have real use case for having 1 and 2 separate? > Any thought on this? > Cheers, > Anusha -- Cheers, Arek ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/8] drm/i915/guc: Make the GuC fw loading helper functions general
On 15/12/2016 22:29, anushasr wrote: From: Peter AntoineRename some of the GuC fw loading code to make them more general. We will utilise them for HuC loading as well. s/intel_guc_fw/intel_uc_fw/g s/GUC_FIRMWARE/UC_FIRMWARE/g Struct intel_guc_fw is renamed to intel_uc_fw. Prefix of tts members, such as 'guc' or 'guc_fw' either is renamed to 'uc' or removed for same purpose. v2: rebased on top of nightly. reapplied the search/replace as upstream code as changed. v3: rebased again on drm-nightly. v4: removed G from messages in shared fw fetch function. v5: rebased. v7: rebased. v8: rebased. v9: rebased. v10: rebased. v11: rebased. v12: rebased on top of drm-tip v13: rebased.Updated dev to dev_priv in intel_guc_setup(), guc_fw_getch() and intel_guc_init(). v14: rebased. Remove uint32_t fw_type to patch 2. Add INTEL_ prefix for fields in enum intel_uc_fw_status. Remove uc_dev field since its never used.Rename uc_fw to just fw and guc_fw to fw to avoid redundency. Signed-off-by: Anusha Srivatsa Signed-off-by: Alex Dai Signed-off-by: Peter Antoine --- drivers/gpu/drm/i915/i915_debugfs.c| 12 +-- drivers/gpu/drm/i915/i915_guc_submission.c | 4 +- drivers/gpu/drm/i915/intel_guc_loader.c| 157 +++-- drivers/gpu/drm/i915/intel_uc.h| 36 +++ 4 files changed, 105 insertions(+), 104 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 15deb2b..008afe6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2328,7 +2328,7 @@ static int i915_llc(struct seq_file *m, void *data) static int i915_guc_load_status_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct intel_guc_fw *guc_fw = _priv->guc.guc_fw; + struct intel_uc_fw *guc_fw = _priv->guc.fw; u32 tmp, i; if (!HAS_GUC_UCODE(dev_priv)) @@ -2336,15 +2336,15 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data) seq_printf(m, "GuC firmware status:\n"); seq_printf(m, "\tpath: %s\n", - guc_fw->guc_fw_path); + guc_fw->uc_fw_path); seq_printf(m, "\tfetch: %s\n", - intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status)); + intel_uc_fw_status_repr(guc_fw->fetch_status)); seq_printf(m, "\tload: %s\n", - intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + intel_uc_fw_status_repr(guc_fw->load_status)); seq_printf(m, "\tversion wanted: %d.%d\n", - guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted); + guc_fw->major_ver_wanted, guc_fw->minor_ver_wanted); seq_printf(m, "\tversion found: %d.%d\n", - guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found); + guc_fw->major_ver_found, guc_fw->minor_ver_found); seq_printf(m, "\theader: offset is %d; size = %d\n", guc_fw->header_offset, guc_fw->header_size); seq_printf(m, "\tuCode: offset is %d; size = %d\n", diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 7fa4e74..b8ad8ff 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1493,7 +1493,7 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv) struct i915_gem_context *ctx; u32 data[3]; - if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS) + if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) return 0; gen9_disable_guc_interrupts(dev_priv); @@ -1520,7 +1520,7 @@ int intel_guc_resume(struct drm_i915_private *dev_priv) struct i915_gem_context *ctx; u32 data[3]; - if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS) + if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) return 0; if (i915.guc_log_level >= 0) diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 21db697..9b3dbea 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -81,16 +81,16 @@ MODULE_FIRMWARE(I915_BXT_GUC_UCODE); MODULE_FIRMWARE(I915_KBL_GUC_UCODE); /* User-friendly representation of an enum */ -const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) +const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status) { switch (status) { - case GUC_FIRMWARE_FAIL: + case INTEL_UC_FIRMWARE_FAIL: return "FAIL"; - case GUC_FIRMWARE_NONE: + case INTEL_UC_FIRMWARE_NONE: return "NONE"; - case GUC_FIRMWARE_PENDING: + case INTEL_UC_FIRMWARE_PENDING: return "PENDING"; - case
Re: [Intel-gfx] [PATCH 5/5] drm/i915/guc: Simplify guc_fw_path
On 15/12/2016 15:47, Arkadiusz Hiler wrote: Currently guc_fw_path values can represent one of three possible states: 1) NULL - device without GuC 2) '\0' - device with GuC but no known firmware 3) else - device with GuC and known firmware Second case is used only to WARN at the later stage. We can WARN right away and merge cases 1 and 2 for later handling. Cc: Anusha SrivatsaCc: Jeff McGee Cc: Michal Winiarski Signed-off-by: Arkadiusz Hiler --- drivers/gpu/drm/i915/intel_guc_loader.c | 22 +++--- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 0bb5fd1..075a103 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -460,12 +460,8 @@ int intel_guc_load(struct drm_i915_private *dev_priv) intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); if (fw_path == NULL) { - /* Device is known to have no uCode (e.g. no GuC) */ + /* We do not have uCode for the device */ return -ENXIO; - } else if (*fw_path == '\0') { - /* Device has a GuC but we don't know what f/w to load? */ - WARN(1, "No GuC firmware known for this platform!\n"); - return -ENODEV; } /* Fetch failed, or already fetched but failed to load? */ @@ -628,11 +624,9 @@ static void guc_fw_fetch(struct drm_i915_private *dev_priv, void intel_guc_init(struct drm_i915_private *dev_priv) { struct intel_guc_fw *guc_fw = _priv->guc.guc_fw; - const char *fw_path; + const char *fw_path = NULL; - if (!HAS_GUC_UCODE(dev_priv)) { - fw_path = NULL; - } else if (IS_SKYLAKE(dev_priv)) { + if (IS_SKYLAKE(dev_priv)) { fw_path = I915_SKL_GUC_UCODE; guc_fw->guc_fw_major_wanted = SKL_FW_MAJOR; guc_fw->guc_fw_minor_wanted = SKL_FW_MINOR; @@ -644,24 +638,22 @@ void intel_guc_init(struct drm_i915_private *dev_priv) fw_path = I915_KBL_GUC_UCODE; guc_fw->guc_fw_major_wanted = KBL_FW_MAJOR; guc_fw->guc_fw_minor_wanted = KBL_FW_MINOR; - } else { - fw_path = ""; /* unknown device */ + } else if (HAS_GUC_UCODE(dev_priv)) { + WARN(1, "No GuC firmware known for platform with GuC!\n"); I think you should also set i915.enable_guc_loading to zero here to avoid the later stages bothering with partial setup and cleanup. intel_uc_load specifically I think would with this patch run some setup then immediately fail and have to unwind. Regards, Tvrtko } guc_fw->guc_fw_path = fw_path; guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE; guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE; - /* Early (and silent) return if GuC loading is disabled */ + /* Early return if we do not have firmware to fetch */ if (fw_path == NULL) return; - if (*fw_path == '\0') - return; guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING; DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path); + guc_fw_fetch(dev_priv, guc_fw); - /* status must now be FAIL or SUCCESS */ } /** ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 8/8] drm/i915/get_params: Add HuC status to getparams
On Thu, Dec 15, 2016 at 02:29:50PM -0800, anushasr wrote: > From: Peter Antoine> > This patch will allow for getparams to return the status of the HuC. > As the HuC has to be validated by the GuC this patch uses the validated > status to show when the HuC is loaded and ready for use. You cannot use > the loaded status as with the GuC as the HuC is verified after it is > loaded and is not usable until it is verified. > > v2: removed the forewakes as the registers are already force-woken. > (T.Ursulin) > v4: rebased. > v5: rebased on top of drm-tip. > v6: rebased. Removed any reference to intel_huc.h > v7: rebased. Rename I915_PARAM_HAS_HUC to I915_PARAM_HUC_STATUS. > Remove intel_is_huc_valid() since it is used only in one place. > Put the case of I915_PARAM_HAS_HUC() in the right place. > > Signed-off-by: Peter Antoine > Reviewed-by: Arkadiusz Hiler You've retained my rb without asking me. With the changes you've made and confirmation that MEDIA FW that I915_READ() assumes: Reviewed-by: Arkadiusz Hiler > --- > drivers/gpu/drm/i915/i915_drv.c | 4 > drivers/gpu/drm/i915/intel_huc_loader.c | 1 - > include/uapi/drm/i915_drm.h | 1 + > 3 files changed, 5 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c > index 85a47c2..0bc016d 100644 > --- a/drivers/gpu/drm/i915/i915_drv.c > +++ b/drivers/gpu/drm/i915/i915_drv.c > @@ -49,6 +49,7 @@ > #include "i915_trace.h" > #include "i915_vgpu.h" > #include "intel_drv.h" > +#include "intel_uc.h" > > static struct drm_driver driver; > > @@ -315,6 +316,9 @@ static int i915_getparam(struct drm_device *dev, void > *data, > case I915_PARAM_MIN_EU_IN_POOL: > value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; > break; > + case I915_PARAM_HUC_STATUS: > + value = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED; > + break; > case I915_PARAM_MMAP_GTT_VERSION: > /* Though we've started our numbering from 1, and so class all >* earlier versions as 0, in effect their value is undefined as > diff --git a/drivers/gpu/drm/i915/intel_huc_loader.c > b/drivers/gpu/drm/i915/intel_huc_loader.c > index d8c5266..b06a613 100644 > --- a/drivers/gpu/drm/i915/intel_huc_loader.c > +++ b/drivers/gpu/drm/i915/intel_huc_loader.c > @@ -288,4 +288,3 @@ void intel_huc_fini(struct drm_device *dev) > > huc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE; > } > - > diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h > index da32c2f..57093b4 100644 > --- a/include/uapi/drm/i915_drm.h > +++ b/include/uapi/drm/i915_drm.h > @@ -395,6 +395,7 @@ typedef struct drm_i915_irq_wait { > * priorities and the driver will attempt to execute batches in priority > order. > */ > #define I915_PARAM_HAS_SCHEDULER 41 > +#define I915_PARAM_HUC_STATUS 42 > > typedef struct drm_i915_getparam { > __s32 param; > -- > 2.7.4 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Cheers, Arek ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/5] drm/i915/guc: Simplify intel_guc_load()
On 15/12/2016 15:47, Arkadiusz Hiler wrote: Current version of intel_guc_load() does a lot: - cares about submission - loads huc Not yet, no? So instead you could say that you are preparing the groundworks to make adding in the HuC fit better. - implement WA This change offloads some of the logic to intel_uc_load(), which now cares about the above. Cc: Anusha SrivatsaCc: Jeff McGee Cc: Michal Winiarski Signed-off-by: Arkadiusz Hiler --- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/intel_guc_loader.c | 126 +--- drivers/gpu/drm/i915/intel_uc.c | 83 + drivers/gpu/drm/i915/intel_uc.h | 8 ++ 4 files changed, 110 insertions(+), 109 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6af4e85..76b52c6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4412,7 +4412,7 @@ i915_gem_init_hw(struct drm_i915_private *dev_priv) intel_mocs_init_l3cc_table(dev_priv); /* We can't enable contexts until all firmware is loaded */ - ret = intel_guc_load(dev_priv); + ret = intel_uc_load(dev_priv); if (ret) goto out; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index f8b28b1..b76b556 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -97,7 +97,7 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) } }; -static void guc_interrupts_release(struct drm_i915_private *dev_priv) +void guc_interrupts_release(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -115,7 +115,7 @@ static void guc_interrupts_release(struct drm_i915_private *dev_priv) I915_WRITE(GUC_WD_VECS_IER, 0); } -static void guc_interrupts_capture(struct drm_i915_private *dev_priv) +void guc_interrupts_capture(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -334,7 +334,7 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv, return ret; } -static u32 guc_wopcm_size(struct drm_i915_private *dev_priv) +u32 guc_wopcm_size(struct drm_i915_private *dev_priv) { u32 wopcm_size = GUC_WOPCM_TOP; @@ -417,7 +417,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) return ret; } -static int guc_hw_reset(struct drm_i915_private *dev_priv) +int guc_hw_reset(struct drm_i915_private *dev_priv) { int ret; u32 guc_status; @@ -452,75 +452,37 @@ int intel_guc_load(struct drm_i915_private *dev_priv) { struct intel_guc_fw *guc_fw = _priv->guc.guc_fw; const char *fw_path = guc_fw->guc_fw_path; - int retries, ret, err; + int ret; DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n", fw_path, intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); - /* Loading forbidden, or no firmware to load? */ - if (!i915.enable_guc_loading) { - err = 0; - goto fail; - } else if (fw_path == NULL) { + if (fw_path == NULL) { /* Device is known to have no uCode (e.g. no GuC) */ - err = -ENXIO; - goto fail; + return -ENXIO; } else if (*fw_path == '\0') { /* Device has a GuC but we don't know what f/w to load? */ WARN(1, "No GuC firmware known for this platform!\n"); - err = -ENODEV; - goto fail; + return -ENODEV; } /* Fetch failed, or already fetched but failed to load? */ if (guc_fw->guc_fw_fetch_status != GUC_FIRMWARE_SUCCESS) { - err = -EIO; - goto fail; + return -EIO; } else if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL) { - err = -ENOEXEC; - goto fail; + return -ENOEXEC; } - guc_interrupts_release(dev_priv); - gen9_reset_guc_interrupts(dev_priv); - guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING; - DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n", - intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), - intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); - - err = i915_guc_submission_init(dev_priv); - if (err) - goto fail; - - /* -* WaEnableuKernelHeaderValidFix:skl,bxt -* For BXT, this is only upto B0 but below WA is required for later -* steppings also so this is extended as well. -*/ /*
[Intel-gfx] [drm-intel:drm-intel-nightly 922/930] include/linux/list.h:385:29: error: initialization discards 'const' qualifier from pointer target type
tree: git://anongit.freedesktop.org/drm-intel drm-intel-nightly head: ca1c03136b168816ac65c5945776908e464fca6b commit: 45b186f111f1623b257d183920cd4aab16a1acd5 [922/930] drm: Constify the drm_mm API config: x86_64-randconfig-x008-201650 (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: git checkout 45b186f111f1623b257d183920cd4aab16a1acd5 # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): In file included from include/linux/mutex.h:14:0, from include/linux/seq_file.h:7, from drivers/gpu/drm/i915/i915_gem_gtt.c:26: drivers/gpu/drm/i915/i915_gem_gtt.c: In function 'i915_gtt_color_adjust': >> include/linux/list.h:385:29: error: initialization discards 'const' >> qualifier from pointer target type [-Werror=discarded-qualifiers] struct list_head *head__ = (ptr); \ ^ drivers/gpu/drm/i915/i915_gem_gtt.c:2732:9: note: in expansion of macro 'list_first_entry_or_null' node = list_first_entry_or_null(>node_list, ^~~~ cc1: all warnings being treated as errors vim +/const +385 include/linux/list.h 3943f42c Andrey Utkin 2014-11-14 369 * @member: the name of the list_head within the struct. 93be3c2e Oleg Nesterov 2013-11-12 370 * 93be3c2e Oleg Nesterov 2013-11-12 371 * Note, that list is expected to be not empty. 93be3c2e Oleg Nesterov 2013-11-12 372 */ 93be3c2e Oleg Nesterov 2013-11-12 373 #define list_last_entry(ptr, type, member) \ 93be3c2e Oleg Nesterov 2013-11-12 374 list_entry((ptr)->prev, type, member) 93be3c2e Oleg Nesterov 2013-11-12 375 93be3c2e Oleg Nesterov 2013-11-12 376 /** 6d7581e6 Jiri Pirko2013-05-29 377 * list_first_entry_or_null - get the first element from a list 6d7581e6 Jiri Pirko2013-05-29 378 * @ptr:the list head to take the element from. 6d7581e6 Jiri Pirko2013-05-29 379 * @type: the type of the struct this is embedded in. 3943f42c Andrey Utkin 2014-11-14 380 * @member: the name of the list_head within the struct. 6d7581e6 Jiri Pirko2013-05-29 381 * 6d7581e6 Jiri Pirko2013-05-29 382 * Note that if the list is empty, it returns NULL. 6d7581e6 Jiri Pirko2013-05-29 383 */ 12adfd88 Chris Wilson 2016-07-23 384 #define list_first_entry_or_null(ptr, type, member) ({ \ 12adfd88 Chris Wilson 2016-07-23 @385 struct list_head *head__ = (ptr); \ 12adfd88 Chris Wilson 2016-07-23 386 struct list_head *pos__ = READ_ONCE(head__->next); \ 12adfd88 Chris Wilson 2016-07-23 387 pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ 12adfd88 Chris Wilson 2016-07-23 388 }) 6d7581e6 Jiri Pirko2013-05-29 389 6d7581e6 Jiri Pirko2013-05-29 390 /** 008208c6 Oleg Nesterov 2013-11-12 391 * list_next_entry - get the next element in list 008208c6 Oleg Nesterov 2013-11-12 392 * @pos:the type * to cursor 3943f42c Andrey Utkin 2014-11-14 393 * @member: the name of the list_head within the struct. :: The code at line 385 was first introduced by commit :: 12adfd882c5f37548acaba4f043a158b3c54468b list: Expand list_first_entry_or_null() :: TO: Chris Wilson:: CC: Paul E. McKenney --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/3] drm/i915/glk: Add missing bits to allow runtime pm suspend on GLK.
From: Rodrigo ViviBesides having the DMC firmware in place and loaded let's handle runtime suspend and dc9 as we do for Broxton. Cc: Ander Conselvan de Oliveira Signed-off-by: Rodrigo Vivi Reviewed-by: Ander Conselvan de Oliveira --- drivers/gpu/drm/i915/i915_drv.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6428588..034de9a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1472,7 +1472,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) intel_display_set_init_power(dev_priv, false); - fw_csr = !IS_BROXTON(dev_priv) && + fw_csr = !IS_GEN9_LP(dev_priv) && suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; /* * In case of firmware assisted context save/restore don't manually @@ -1485,7 +1485,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) intel_power_domains_suspend(dev_priv); ret = 0; - if (IS_BROXTON(dev_priv)) + if (IS_GEN9_LP(dev_priv)) bxt_enable_dc9(dev_priv); else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_enable_pc8(dev_priv); @@ -1693,7 +1693,7 @@ static int i915_drm_resume_early(struct drm_device *dev) intel_uncore_early_sanitize(dev_priv, true); - if (IS_BROXTON(dev_priv)) { + if (IS_GEN9_LP(dev_priv)) { if (!dev_priv->suspended_to_idle) gen9_sanitize_dc_state(dev_priv); bxt_disable_dc9(dev_priv); @@ -1703,7 +1703,7 @@ static int i915_drm_resume_early(struct drm_device *dev) intel_uncore_sanitize(dev_priv); - if (IS_BROXTON(dev_priv) || + if (IS_GEN9_LP(dev_priv) || !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload)) intel_power_domains_init_hw(dev_priv, true); @@ -2326,7 +2326,7 @@ static int intel_runtime_suspend(struct device *kdev) intel_runtime_pm_disable_interrupts(dev_priv); ret = 0; - if (IS_BROXTON(dev_priv)) { + if (IS_GEN9_LP(dev_priv)) { bxt_display_core_uninit(dev_priv); bxt_enable_dc9(dev_priv); } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { @@ -2411,7 +2411,7 @@ static int intel_runtime_resume(struct device *kdev) if (IS_GEN6(dev_priv)) intel_init_pch_refclk(dev_priv); - if (IS_BROXTON(dev_priv)) { + if (IS_GEN9_LP(dev_priv)) { bxt_disable_dc9(dev_priv); bxt_display_core_init(dev_priv, true); if (dev_priv->csr.dmc_payload && -- 2.5.5 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/3] drm/i915/DMC/GLK: Load DMC on GLK
From: Anusha SrivatsaThis patch loads the DMC on GLK. There is a single firmware image for all steppings on a GLK. Cc: Rodrigo Vivi Signed-off-by: Anusha Srivatsa Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_csr.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 9cbb8d8..0085bc7 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -34,6 +34,10 @@ * low-power state and comes back to normal. */ +#define I915_CSR_GLK "i915/glk_dmc_ver1_01.bin" +MODULE_FIRMWARE(I915_CSR_GLK); +#define GLK_CSR_VERSION_REQUIRED CSR_VERSION(1, 1) + #define I915_CSR_KBL "i915/kbl_dmc_ver1_01.bin" MODULE_FIRMWARE(I915_CSR_KBL); #define KBL_CSR_VERSION_REQUIRED CSR_VERSION(1, 1) @@ -286,7 +290,9 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, csr->version = css_header->version; - if (IS_KABYLAKE(dev_priv)) { + if (IS_GEMINILAKE(dev_priv)) { + required_version = GLK_CSR_VERSION_REQUIRED; + } else if (IS_KABYLAKE(dev_priv)) { required_version = KBL_CSR_VERSION_REQUIRED; } else if (IS_SKYLAKE(dev_priv)) { required_version = SKL_CSR_VERSION_REQUIRED; @@ -435,7 +441,9 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) if (!HAS_CSR(dev_priv)) return; - if (IS_KABYLAKE(dev_priv)) + if (IS_GEMINILAKE(dev_priv)) + csr->fw_path = I915_CSR_GLK; + else if (IS_KABYLAKE(dev_priv)) csr->fw_path = I915_CSR_KBL; else if (IS_SKYLAKE(dev_priv)) csr->fw_path = I915_CSR_SKL; -- 2.5.5 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/3] drm/i915/glk: Convert a few more IS_BROXTON() to IS_GEN9_LP()
From: Michel ThierryCommit 89b3c3c7ee9d ("drm/i915/glk: Reuse broxton's cdclk code for GLK") missed a few of occurences of IS_BROXTON() that should have been coverted to IS_GEN9_LP(). Fixes: 89b3c3c7ee9d ("drm/i915/glk: Reuse broxton's cdclk code for GLK") Cc: Ander Conselvan de Oliveira Cc: Rodrigo Vivi Cc: Daniel Vetter Cc: Jani Nikula Cc: intel-gfx@lists.freedesktop.org Signed-off-by: Michel Thierry Signed-off-by: Tomasz Lis Signed-off-by: Ander Conselvan de Oliveira --- drivers/gpu/drm/i915/i915_sysfs.c| 2 +- drivers/gpu/drm/i915/intel_device_info.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_guc_loader.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 40c0ac7..376ac95 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -58,7 +58,7 @@ static u32 calc_residency(struct drm_i915_private *dev_priv, if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) units <<= 8; - } else if (IS_BROXTON(dev_priv)) { + } else if (IS_GEN9_LP(dev_priv)) { units = 1; div = 1200; /* 833.33ns */ } diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index c46415b..6aeb1ed 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -192,7 +192,7 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && hweight8(sseu->slice_mask) > 1; sseu->has_subslice_pg = - IS_BROXTON(dev_priv) && sseu_subslice_total(sseu) > 1; + IS_GEN9_LP(dev_priv) && sseu_subslice_total(sseu) > 1; sseu->has_eu_pg = sseu->eu_per_subslice > 2; if (IS_BROXTON(dev_priv)) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 45ebc96..ae08c19 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3375,7 +3375,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) if (HAS_DDI(dev_priv)) { signal_levels = ddi_signal_levels(intel_dp); - if (IS_BROXTON(dev_priv)) + if (IS_GEN9_LP(dev_priv)) signal_levels = 0; else mask = DDI_BUF_EMP_MASK; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 21db697..8b74525 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -339,7 +339,7 @@ static u32 guc_wopcm_size(struct drm_i915_private *dev_priv) u32 wopcm_size = GUC_WOPCM_TOP; /* On BXT, the top of WOPCM is reserved for RC6 context */ - if (IS_BROXTON(dev_priv)) + if (IS_GEN9_LP(dev_priv)) wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED; return wopcm_size; @@ -388,7 +388,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); - if (IS_BROXTON(dev_priv)) + if (IS_GEN9_LP(dev_priv)) I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE); else I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); -- 2.5.5 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [drm-intel:drm-intel-nightly 922/930] drivers/gpu/drm/i915/i915_gem_gtt.c:2732:9: note: in expansion of macro 'list_first_entry_or_null'
tree: git://anongit.freedesktop.org/drm-intel drm-intel-nightly head: ca1c03136b168816ac65c5945776908e464fca6b commit: 45b186f111f1623b257d183920cd4aab16a1acd5 [922/930] drm: Constify the drm_mm API config: i386-randconfig-x005-201650 (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: git checkout 45b186f111f1623b257d183920cd4aab16a1acd5 # save the attached .config to linux build tree make ARCH=i386 All warnings (new ones prefixed by >>): In file included from include/linux/mutex.h:14:0, from include/linux/seq_file.h:7, from drivers/gpu/drm/i915/i915_gem_gtt.c:26: drivers/gpu/drm/i915/i915_gem_gtt.c: In function 'i915_gtt_color_adjust': >> include/linux/list.h:385:29: warning: initialization discards 'const' >> qualifier from pointer target type [-Wdiscarded-qualifiers] struct list_head *head__ = (ptr); \ ^ >> drivers/gpu/drm/i915/i915_gem_gtt.c:2732:9: note: in expansion of macro >> 'list_first_entry_or_null' node = list_first_entry_or_null(>node_list, ^~~~ vim +/list_first_entry_or_null +2732 drivers/gpu/drm/i915/i915_gem_gtt.c 307dc25b Chris Wilson 2016-08-05 2716/* Wait a bit, in hopes it avoids the hang */ 307dc25b Chris Wilson 2016-08-05 2717udelay(10); 307dc25b Chris Wilson 2016-08-05 2718} 307dc25b Chris Wilson 2016-08-05 2719} 5c042287 Ben Widawsky 2011-10-17 2720 03ac84f1 Chris Wilson 2016-10-28 2721dma_unmap_sg(kdev, pages->sgl, pages->nents, PCI_DMA_BIDIRECTIONAL); 7c2e6fdf Daniel Vetter 2010-11-06 2722 } 644ec02b Daniel Vetter 2012-03-26 2723 45b186f1 Chris Wilson 2016-12-16 2724 static void i915_gtt_color_adjust(const struct drm_mm_node *node, 42d6ab48 Chris Wilson 2012-07-26 2725 unsigned long color, 440fd528 Thierry Reding 2015-01-23 2726 u64 *start, 440fd528 Thierry Reding 2015-01-23 2727 u64 *end) 42d6ab48 Chris Wilson 2012-07-26 2728 { 42d6ab48 Chris Wilson 2012-07-26 2729if (node->color != color) 42d6ab48 Chris Wilson 2012-07-26 2730*start += 4096; 42d6ab48 Chris Wilson 2012-07-26 2731 2a1d7752 Chris Wilson 2016-07-26 @2732node = list_first_entry_or_null(>node_list, 42d6ab48 Chris Wilson 2012-07-26 2733 struct drm_mm_node, 42d6ab48 Chris Wilson 2012-07-26 2734 node_list); 2a1d7752 Chris Wilson 2016-07-26 2735if (node && node->allocated && node->color != color) 42d6ab48 Chris Wilson 2012-07-26 2736*end -= 4096; 42d6ab48 Chris Wilson 2012-07-26 2737 } fbe5d36e Ben Widawsky 2013-11-04 2738 f6b9d5ca Chris Wilson 2016-08-04 2739 int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) 644ec02b Daniel Vetter 2012-03-26 2740 { :: The code at line 2732 was first introduced by commit :: 2a1d775201081c400d7e60ceb8e5ac887d11b1f7 drm/i915: Prefer list_first_entry_or_null :: TO: Chris Wilson:: CC: Chris Wilson --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 09/13] drm: Tighten locking in drm_mode_getconnector
On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetterwrote: > - Modeset state needs mode_config->connection mutex, that covers > figuring out the encoder, and reading properties (since in the > atomic case those need to look at connector->state). > > - Don't hold any locks for stuff that's invariant (i.e. possible > connectors). > > - Same for connector lookup and unref, those don't need any locks. > > - And finally the probe stuff is only protected by mode_config->mutex. > > While at it updated the kerneldoc for these fields in drm_connector > and add docs explaining what's protected by which locks. > Reviewed-by: Sean Paul > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/drm_connector.c | 92 > - > include/drm/drm_connector.h | 23 +-- > 2 files changed, 63 insertions(+), 52 deletions(-) > > diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c > index 0d4728704099..44b556d5d40c 100644 > --- a/drivers/gpu/drm/drm_connector.c > +++ b/drivers/gpu/drm/drm_connector.c > @@ -1160,43 +1160,65 @@ int drm_mode_getconnector(struct drm_device *dev, > void *data, > > memset(_mode, 0, sizeof(struct drm_mode_modeinfo)); > > - mutex_lock(>mode_config.mutex); > - > connector = drm_connector_lookup(dev, out_resp->connector_id); > - if (!connector) { > - ret = -ENOENT; > - goto out_unlock; > - } > + if (!connector) > + return -ENOENT; > + > + drm_modeset_lock(>mode_config.connection_mutex, NULL); > + encoder = drm_connector_get_encoder(connector); > + if (encoder) > + out_resp->encoder_id = encoder->base.id; > + else > + out_resp->encoder_id = 0; > + > + ret = drm_mode_object_get_properties(>base, > file_priv->atomic, > + (uint32_t __user *)(unsigned > long)(out_resp->props_ptr), > + (uint64_t __user *)(unsigned > long)(out_resp->prop_values_ptr), > + _resp->count_props); > + drm_modeset_unlock(>mode_config.connection_mutex); > + if (ret) > + goto out_unref; > > for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) > if (connector->encoder_ids[i] != 0) > encoders_count++; > > + if ((out_resp->count_encoders >= encoders_count) && encoders_count) { > + copied = 0; > + encoder_ptr = (uint32_t __user *)(unsigned > long)(out_resp->encoders_ptr); > + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { > + if (connector->encoder_ids[i] != 0) { > + if (put_user(connector->encoder_ids[i], > +encoder_ptr + copied)) { > + ret = -EFAULT; > + goto out_unref; > + } > + copied++; > + } > + } > + } > + out_resp->count_encoders = encoders_count; > + > + out_resp->connector_id = connector->base.id; > + out_resp->connector_type = connector->connector_type; > + out_resp->connector_type_id = connector->connector_type_id; > + > + mutex_lock(>mode_config.mutex); > if (out_resp->count_modes == 0) { > connector->funcs->fill_modes(connector, > dev->mode_config.max_width, > dev->mode_config.max_height); > } > > - /* delayed so we get modes regardless of pre-fill_modes state */ > - list_for_each_entry(mode, >modes, head) > - if (drm_mode_expose_to_userspace(mode, file_priv)) > - mode_count++; > - > - out_resp->connector_id = connector->base.id; > - out_resp->connector_type = connector->connector_type; > - out_resp->connector_type_id = connector->connector_type_id; > out_resp->mm_width = connector->display_info.width_mm; > out_resp->mm_height = connector->display_info.height_mm; > out_resp->subpixel = connector->display_info.subpixel_order; > out_resp->connection = connector->status; > > - drm_modeset_lock(>mode_config.connection_mutex, NULL); > - encoder = drm_connector_get_encoder(connector); > - if (encoder) > - out_resp->encoder_id = encoder->base.id; > - else > - out_resp->encoder_id = 0; > + /* delayed so we get modes regardless of pre-fill_modes state */ > + list_for_each_entry(mode, >modes, head) > + if (drm_mode_expose_to_userspace(mode, file_priv)) > + mode_count++; > > /* > * This ioctl is called twice, once to determine how much
Re: [Intel-gfx] [PATCH 07/13] drm: Clean up connectors by unreferencing them
On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetterwrote: > Only static connectors should be left at this point, and we should be > able to clean them out by simply dropping that last reference still > around from drm_connector_init. > > If that leaves anything behind then we have a driver bug. > > Doing the final cleanup this way also allows us to use > drm_connector_iter, removing the very last place where we walk > connector_list explicitly in drm core > > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/drm_mode_config.c | 15 +++ > 1 file changed, 11 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/drm_mode_config.c > b/drivers/gpu/drm/drm_mode_config.c > index 747a26df0e90..a942536abd60 100644 > --- a/drivers/gpu/drm/drm_mode_config.c > +++ b/drivers/gpu/drm/drm_mode_config.c > @@ -397,7 +397,8 @@ EXPORT_SYMBOL(drm_mode_config_init); > */ > void drm_mode_config_cleanup(struct drm_device *dev) > { > - struct drm_connector *connector, *ot; > + struct drm_connector *connector; > + struct drm_connector_list_iter conn_iter; > struct drm_crtc *crtc, *ct; > struct drm_encoder *encoder, *enct; > struct drm_framebuffer *fb, *fbt; > @@ -410,10 +411,16 @@ void drm_mode_config_cleanup(struct drm_device *dev) > encoder->funcs->destroy(encoder); > } > > - list_for_each_entry_safe(connector, ot, > ->mode_config.connector_list, head) { > - connector->funcs->destroy(connector); > + drm_connector_list_iter_get(dev, _iter); > + drm_for_each_connector_iter(connector, _iter) { > + /* drm_connector_list_iter holds an full reference to the > +* current connector itself, which means it is inherently safe > +* against unreferencing the current connector - but not > against > +* deleting it right away. */ pedantic nit: doesn't conform to CodingStyle Reviewed-by: Sean Paul > + drm_connector_unreference(connector); > } > + drm_connector_list_iter_put(_iter); > + WARN_ON(!list_empty(>mode_config.connector_list)); > > list_for_each_entry_safe(property, pt, > >mode_config.property_list, > head) { > -- > 2.11.0 > > ___ > dri-devel mailing list > dri-de...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Sean Paul, Software Engineer, Google / Chromium OS ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 08/13] drm: prevent double-(un)registration for connectors
On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetterwrote: > If we're unlucky then the registration from a hotplugged connector > might race with the final registration step on driver load. And since > MST topology discover is asynchronous that's even somewhat likely. > > v2: Also update the kerneldoc for @registered! > > Cc: Chris Wilson > Reported-by: Chris Wilson With Chris' suggested improvements Reviewed-by: Sean Paul > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/drm_connector.c | 18 +- > include/drm/drm_connector.h | 12 +++- > 2 files changed, 24 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c > index b4e09b00..0d4728704099 100644 > --- a/drivers/gpu/drm/drm_connector.c > +++ b/drivers/gpu/drm/drm_connector.c > @@ -223,6 +223,7 @@ int drm_connector_init(struct drm_device *dev, > > INIT_LIST_HEAD(>probed_modes); > INIT_LIST_HEAD(>modes); > + mutex_init(>mutex); > connector->edid_blob_ptr = NULL; > connector->status = connector_status_unknown; > > @@ -373,14 +374,15 @@ EXPORT_SYMBOL(drm_connector_cleanup); > */ > int drm_connector_register(struct drm_connector *connector) > { > - int ret; > + int ret = 0; > > + mutex_lock(>mutex); > if (connector->registered) > - return 0; > + goto unlock; > > ret = drm_sysfs_connector_add(connector); > if (ret) > - return ret; > + goto unlock; > > ret = drm_debugfs_connector_add(connector); > if (ret) { > @@ -396,12 +398,14 @@ int drm_connector_register(struct drm_connector > *connector) > drm_mode_object_register(connector->dev, >base); > > connector->registered = true; > - return 0; > + goto unlock; > > err_debugfs: > drm_debugfs_connector_remove(connector); > err_sysfs: > drm_sysfs_connector_remove(connector); > +unlock: > + mutex_unlock(>mutex); > return ret; > } > EXPORT_SYMBOL(drm_connector_register); > @@ -414,8 +418,11 @@ EXPORT_SYMBOL(drm_connector_register); > */ > void drm_connector_unregister(struct drm_connector *connector) > { > - if (!connector->registered) > + mutex_lock(>mutex); > + if (!connector->registered) { > + mutex_unlock(>mutex); > return; > + } > > if (connector->funcs->early_unregister) > connector->funcs->early_unregister(connector); > @@ -424,6 +431,7 @@ void drm_connector_unregister(struct drm_connector > *connector) > drm_debugfs_connector_remove(connector); > > connector->registered = false; > + mutex_unlock(>mutex); > } > EXPORT_SYMBOL(drm_connector_unregister); > > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h > index 0e41a2e184a9..a24559ef8bb7 100644 > --- a/include/drm/drm_connector.h > +++ b/include/drm/drm_connector.h > @@ -559,7 +559,6 @@ struct drm_cmdline_mode { > * @interlace_allowed: can this connector handle interlaced modes? > * @doublescan_allowed: can this connector handle doublescan? > * @stereo_allowed: can this connector handle stereo modes? > - * @registered: is this connector exposed (registered) with userspace? > * @modes: modes available on this connector (from fill_modes() + user) > * @status: one of the drm_connector_status enums (connected, not, or > unknown) > * @probed_modes: list of modes derived directly from the display > @@ -608,6 +607,13 @@ struct drm_connector { > char *name; > > /** > +* @mutex: Lock for general connector state, but currently only > protects > +* @registered. Most of the connector state is still protected by the > +* mutex in _mode_config. > +*/ > + struct mutex mutex; > + > + /** > * @index: Compacted connector index, which matches the position > inside > * the mode_config.list for drivers not supporting hot-add/removing. > Can > * be used as an array index. It is invariant over the lifetime of the > @@ -620,6 +626,10 @@ struct drm_connector { > bool interlace_allowed; > bool doublescan_allowed; > bool stereo_allowed; > + /** > +* @registered: Is this connector exposed (registered) with userspace? > +* Protected by @mutex. > +*/ > bool registered; > struct list_head modes; /* list of modes on this connector */ > > -- > 2.11.0 > > ___ > dri-devel mailing list > dri-de...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Sean Paul, Software Engineer, Google / Chromium OS ___ Intel-gfx mailing list
Re: [Intel-gfx] [PATCH] drm: Convert all helpers to drm_connector_list_iter
On Thu, Dec 15, 2016 at 10:58 AM, Daniel Vetterwrote: > Mostly nothing special (except making sure that really all error paths > and friends call iter_put). > > v2: Don't forget the raw connector_list walking in > drm_helper_move_panel_connectors_to_head. That one unfortunately can't > be converted to the iterator helpers, but since it's just some list > splicing best to just wrap the entire thing up in one critical > section. > > v3: Bail out after iter_put (Harry). > > Cc: Harry Wentland Reviewed-by: Sean Paul > Reviewed-by: Harry Wentland > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/drm_atomic_helper.c | 39 > drivers/gpu/drm/drm_crtc_helper.c| 49 > > drivers/gpu/drm/drm_fb_helper.c | 12 ++--- > drivers/gpu/drm/drm_modeset_helper.c | 2 ++ > drivers/gpu/drm/drm_plane_helper.c | 5 +++- > drivers/gpu/drm/drm_probe_helper.c | 18 - > 6 files changed, 92 insertions(+), 33 deletions(-) > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > b/drivers/gpu/drm/drm_atomic_helper.c > index 23767df72615..e2e15a9903a9 100644 > --- a/drivers/gpu/drm/drm_atomic_helper.c > +++ b/drivers/gpu/drm/drm_atomic_helper.c > @@ -94,9 +94,10 @@ static int handle_conflicting_encoders(struct > drm_atomic_state *state, > { > struct drm_connector_state *conn_state; > struct drm_connector *connector; > + struct drm_connector_list_iter conn_iter; > struct drm_encoder *encoder; > unsigned encoder_mask = 0; > - int i, ret; > + int i, ret = 0; > > /* > * First loop, find all newly assigned encoders from the connectors > @@ -144,7 +145,8 @@ static int handle_conflicting_encoders(struct > drm_atomic_state *state, > * and the crtc is disabled if no encoder is left. This preserves > * compatibility with the legacy set_config behavior. > */ > - drm_for_each_connector(connector, state->dev) { > + drm_connector_list_iter_get(state->dev, _iter); > + drm_for_each_connector_iter(connector, _iter) { > struct drm_crtc_state *crtc_state; > > if (drm_atomic_get_existing_connector_state(state, connector)) > @@ -160,12 +162,15 @@ static int handle_conflicting_encoders(struct > drm_atomic_state *state, > connector->state->crtc->base.id, > connector->state->crtc->name, > connector->base.id, connector->name); > - return -EINVAL; > + ret = -EINVAL; > + goto out; > } > > conn_state = drm_atomic_get_connector_state(state, connector); > - if (IS_ERR(conn_state)) > - return PTR_ERR(conn_state); > + if (IS_ERR(conn_state)) { > + ret = PTR_ERR(conn_state); > + goto out; > + } > > DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], > disabling [CONNECTOR:%d:%s]\n", > encoder->base.id, encoder->name, > @@ -176,19 +181,21 @@ static int handle_conflicting_encoders(struct > drm_atomic_state *state, > > ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); > if (ret) > - return ret; > + goto out; > > if (!crtc_state->connector_mask) { > ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, > NULL); > if (ret < 0) > - return ret; > + goto out; > > crtc_state->active = false; > } > } > +out: > + drm_connector_list_iter_put(_iter); > > - return 0; > + return ret; > } > > static void > @@ -2442,6 +2449,7 @@ int drm_atomic_helper_disable_all(struct drm_device > *dev, > { > struct drm_atomic_state *state; > struct drm_connector *conn; > + struct drm_connector_list_iter conn_iter; > int err; > > state = drm_atomic_state_alloc(dev); > @@ -2450,7 +2458,8 @@ int drm_atomic_helper_disable_all(struct drm_device > *dev, > > state->acquire_ctx = ctx; > > - drm_for_each_connector(conn, dev) { > + drm_connector_list_iter_get(dev, _iter); > + drm_for_each_connector_iter(conn, _iter) { > struct drm_crtc *crtc = conn->state->crtc; > struct drm_crtc_state *crtc_state; > > @@ -2468,6 +2477,7 @@ int drm_atomic_helper_disable_all(struct drm_device > *dev, > > err = drm_atomic_commit(state); >
Re: [Intel-gfx] [PATCH 04/13] drm: Drop locking cargo-cult from drm_mode_config_init
On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetterwrote: > This is single-threaded setup code, no need for locks. And anyway, > all properties need to be set up before the driver is registered > anyway, they can't be hot-added. > Reviewed-by: Sean Paul > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/drm_mode_config.c | 2 -- > 1 file changed, 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_mode_config.c > b/drivers/gpu/drm/drm_mode_config.c > index b1e8bbceaf39..85a25fd9eff8 100644 > --- a/drivers/gpu/drm/drm_mode_config.c > +++ b/drivers/gpu/drm/drm_mode_config.c > @@ -374,9 +374,7 @@ void drm_mode_config_init(struct drm_device *dev) > idr_init(>mode_config.tile_idr); > ida_init(>mode_config.connector_ida); > > - drm_modeset_lock_all(dev); > drm_mode_create_standard_properties(dev); > - drm_modeset_unlock_all(dev); > > /* Just to be sure */ > dev->mode_config.num_fb = 0; > -- > 2.11.0 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Sean Paul, Software Engineer, Google / Chromium OS ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 05/13] drm: locking iterators for connector_list
On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetterwrote: > The requirements for connector_list locking are a bit tricky: > - We need to be able to jump over zombie conectors (i.e. with refcount > == 0, but not yet removed from the list). If instead we require that > there's no zombies on the list then the final kref_put must happen > under the list protection lock, which means that locking context > leaks all over the place. Not pretty - better to deal with zombies > and wrap the locking just around the list_del in the destructor. > > - When we walk the list we must _not_ hold the connector list lock. We > walk the connector list at an absolutely massive amounts of places, > if all those places can't ever call drm_connector_unreference the > code would get unecessarily complicated. > > - connector_list needs it own lock, again too many places that walk it > that we could reuse e.g. mode_config.mutex without resulting in > inversions. > > - Lots of code uses these loops to look-up a connector, i.e. they want > to be able to call drm_connector_reference. But on the other hand we > want connectors to stay on that list until they're dead (i.e. > connector_list can't hold a full reference), which means despite the > "can't hold lock for the loop body" rule we need to make sure a > connector doesn't suddenly become a zombie. > > At first Dave discussed various horror-show approaches using srcu, > but turns out it's fairly easy: > > - For the loop body we always hold an additional reference to the > current connector. That means it can't zombify, and it also means > it'll stay on the list, which means we can use it as our iterator to > find the next connector. > > - When we try to find the next connector we only have to jump over > zombies. To make sure we don't chase bad pointers that entire loop > is protected with the new connect_list_lock spinlock. And because we > know that we're starting out with a non-zombie (need to drop our > reference for the old connector only after we have our new one), > we're guranteed to still be on the connector_list and either find > the next non-zombie or complete the iteration. > > - Only downside is that we need to make sure that the temporary > reference for the loop body doesn't leak. iter_get/put() functions + > lockdep make sure that's the case. > > - To avoid a flag day the new iterator macro has an _iter postfix. We > can rename it back once all the users of the unsafe version are gone > (there's about 100 list walkers for the connector_list). > > For now this patch only converts all the list walking in the core, > leaving helpers and drivers for later patches. The nice thing is that > we can now finally remove 2 FIXME comments from the > register/unregister functions. > > v2: > - use irqsafe spinlocks, so that we can use this in drm_state_dump > too. > - nuke drm_modeset_lock_all from drm_connector_init, now entirely > cargo-culted nonsense. > > v3: > - do {} while (!kref_get_unless_zero), makes for a tidier loop (Dave). > - pretty kerneldoc > - add EXPORT_SYMBOL, helpers are supposed to use this. > > v4: Change lockdep annotations to only check whether we release the > iter fake lock again (i.e. make sure that iter_put is called), but > not check any locking dependecies itself. That seams to require a > recursive read lock in trylock mode. > > Cc: Dave Airlie > Cc: Chris Wilson Reviewed-by: Sean Paul > Signed-off-by: Daniel Vetter ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 02/13] drm: Move atomic debugfs functions into drm_crtc_internal.h
On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetterwrote: > This is not driver interface stuff. > Reviewed-by: Sean Paul > Fixes: 6559c901cb48 ("drm/atomic: add debugfs file to dump out atomic state") > Cc: Rob Clark > Cc: Sean Paul > Cc: Daniel Vetter > Cc: Jani Nikula > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/drm_crtc_internal.h | 6 ++ > drivers/gpu/drm/drm_debugfs.c | 1 + > include/drm/drm_atomic.h| 6 -- > 3 files changed, 7 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/drm_crtc_internal.h > b/drivers/gpu/drm/drm_crtc_internal.h > index cdf6860c9d22..0b8454c7dc00 100644 > --- a/drivers/gpu/drm/drm_crtc_internal.h > +++ b/drivers/gpu/drm/drm_crtc_internal.h > @@ -174,6 +174,12 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, >void *data, struct drm_file *file_priv); > > /* drm_atomic.c */ > +#ifdef CONFIG_DEBUG_FS > +struct drm_minor; > +int drm_atomic_debugfs_init(struct drm_minor *minor); > +int drm_atomic_debugfs_cleanup(struct drm_minor *minor); > +#endif > + > int drm_atomic_get_property(struct drm_mode_object *obj, > struct drm_property *property, uint64_t *val); > int drm_mode_atomic_ioctl(struct drm_device *dev, > diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c > index 2e3e46a53805..37fd612d57a6 100644 > --- a/drivers/gpu/drm/drm_debugfs.c > +++ b/drivers/gpu/drm/drm_debugfs.c > @@ -38,6 +38,7 @@ > #include > #include > #include "drm_internal.h" > +#include "drm_crtc_internal.h" > > #if defined(CONFIG_DEBUG_FS) > > diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h > index 01d02e1935b1..c35b4aba36b6 100644 > --- a/include/drm/drm_atomic.h > +++ b/include/drm/drm_atomic.h > @@ -379,12 +379,6 @@ int __must_check drm_atomic_nonblocking_commit(struct > drm_atomic_state *state); > > void drm_state_dump(struct drm_device *dev, struct drm_printer *p); > > -#ifdef CONFIG_DEBUG_FS > -struct drm_minor; > -int drm_atomic_debugfs_init(struct drm_minor *minor); > -int drm_atomic_debugfs_cleanup(struct drm_minor *minor); > -#endif > - > #define for_each_connector_in_state(__state, connector, connector_state, > __i) \ > for ((__i) = 0; \ > (__i) < (__state)->num_connector && > \ > -- > 2.11.0 > -- Sean Paul, Software Engineer, Google / Chromium OS ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 01/13] drm/irq: drm_legacy_ prefix for legacy ioctls
On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetterwrote: > Spotted while auditing our ioctl table. Also nuke the > not-really-kerneldoc comments, we don't document internals and > definitely don't want to mislead people with the old dragons. > > I think with this all the legacy ioctls now have proper drm_legacy_ > prefixes. > Reviewed-by: Sean Paul > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/drm_internal.h | 8 > drivers/gpu/drm/drm_ioctl.c| 4 ++-- > drivers/gpu/drm/drm_irq.c | 30 -- > 3 files changed, 10 insertions(+), 32 deletions(-) > > diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h > index db80ec860e33..a6213f814345 100644 > --- a/drivers/gpu/drm/drm_internal.h > +++ b/drivers/gpu/drm/drm_internal.h > @@ -58,10 +58,10 @@ extern unsigned int drm_timestamp_monotonic; > /* IOCTLS */ > int drm_wait_vblank(struct drm_device *dev, void *data, > struct drm_file *filp); > -int drm_control(struct drm_device *dev, void *data, > - struct drm_file *file_priv); > -int drm_modeset_ctl(struct drm_device *dev, void *data, > - struct drm_file *file_priv); > +int drm_legacy_irq_control(struct drm_device *dev, void *data, > + struct drm_file *file_priv); > +int drm_legacy_modeset_ctl(struct drm_device *dev, void *data, > + struct drm_file *file_priv); > > /* drm_auth.c */ > int drm_getmagic(struct drm_device *dev, void *data, > diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c > index e21a18ac968e..a16b6fbd1004 100644 > --- a/drivers/gpu/drm/drm_ioctl.c > +++ b/drivers/gpu/drm/drm_ioctl.c > @@ -581,7 +581,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { > DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_legacy_freebufs, DRM_AUTH), > DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_legacy_dma_ioctl, DRM_AUTH), > > - DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, > DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), > + DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_legacy_irq_control, > DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), > > #if IS_ENABLED(CONFIG_AGP) > DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, > DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), > @@ -599,7 +599,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { > > DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, > DRM_MASTER|DRM_UNLOCKED), > > - DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), > + DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_legacy_modeset_ctl, 0), > > DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, > DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), > > diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c > index 273625a85036..feb091310ffe 100644 > --- a/drivers/gpu/drm/drm_irq.c > +++ b/drivers/gpu/drm/drm_irq.c > @@ -579,19 +579,8 @@ int drm_irq_uninstall(struct drm_device *dev) > } > EXPORT_SYMBOL(drm_irq_uninstall); > > -/* > - * IRQ control ioctl. > - * > - * \param inode device inode. > - * \param file_priv DRM file private. > - * \param cmd command. > - * \param arg user argument, pointing to a drm_control structure. > - * \return zero on success or a negative number on failure. > - * > - * Calls irq_install() or irq_uninstall() according to \p arg. > - */ > -int drm_control(struct drm_device *dev, void *data, > - struct drm_file *file_priv) > +int drm_legacy_irq_control(struct drm_device *dev, void *data, > + struct drm_file *file_priv) > { > struct drm_control *ctl = data; > int ret = 0, irq; > @@ -1442,19 +1431,8 @@ static void drm_legacy_vblank_post_modeset(struct > drm_device *dev, > } > } > > -/* > - * drm_modeset_ctl - handle vblank event counter changes across mode switch > - * @DRM_IOCTL_ARGS: standard ioctl arguments > - * > - * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET > - * ioctls around modesetting so that any lost vblank events are accounted > for. > - * > - * Generally the counter will reset across mode sets. If interrupts are > - * enabled around this call, we don't have to do anything since the counter > - * will have already been incremented. > - */ > -int drm_modeset_ctl(struct drm_device *dev, void *data, > - struct drm_file *file_priv) > +int drm_legacy_modeset_ctl(struct drm_device *dev, void *data, > + struct drm_file *file_priv) > { > struct drm_modeset_ctl *modeset = data; > unsigned int pipe; > -- > 2.11.0 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Sean Paul, Software Engineer, Google / Chromium OS ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org
Re: [Intel-gfx] [PATCH v2 12/40] drm: kselftest for drm_mm_insert_node()
On Fri, Dec 16, 2016 at 04:02:12PM +0200, Joonas Lahtinen wrote: > On pe, 2016-12-16 at 07:46 +, Chris Wilson wrote: > > Exercise drm_mm_insert_node(), check that we can't overfill a range and > > that the lists are correct after reserving/removing. > > > > v2: Extract helpers for the repeated tests > > v3: Iterate over all allocation flags > > > > Signed-off-by: Chris Wilson> > > > > +static u64 misaligned(struct drm_mm_node *node, u64 alignment) > > I'm not sure if 'misalignment' would be better name or not. This makes > me think of bool returning one. > > > +static bool expect_insert_fail(struct drm_mm *mm, u64 size) > > +{ > > + struct drm_mm_node tmp = {}; > > + int err; > > + > > + err = drm_mm_insert_node(mm, , size, 0, DRM_MM_SEARCH_DEFAULT); > > + if (err != -ENOSPC) { > > For speed (this function gets called a lot); > > if (likely(err == -ENOSPC)) > return true; > > > +static int __igt_insert(unsigned int count, u64 size) > > +{ > > > > > > > + for (mode = insert_modes; mode->name; mode++) { > > + for (n = 0; n < count; n++) { > > + node = [n]; > > + err = drm_mm_insert_node_generic(, node, size, 0, n, > > + mode->search_flags, > > + mode->create_flags); > > + if (err || !assert_node(node, , size, 0, n)) { > > + pr_err("%s insert failed, size %llu step %d\n", > > + mode->name, size, n); > > + ret = err ?: -EINVAL; > > + goto out; > > + } > > This construct is three times in this patch; Could be > expect_insert_generic? In this patch alone, indeed it gets used again and again. I resisted making it an insert and check function simply because I didn't want to fall into the trap of using it everywhere and so missing out exercising drm_mm_insert_node and friends. However, 3 occurences of the same in one patch... -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx