Re: [Intel-gfx] [PATCH 2/2] drm/i915: Enable DPLL VGA mode before P1/P2 divider write
On Thu, Oct 08, 2015 at 10:19:14AM +0200, Daniel Vetter wrote: > On Wed, Oct 07, 2015 at 10:08:25PM +0300, ville.syrj...@linux.intel.com wrote: > > From: Ville Syrjälä> > > > Apparently writing the DPLL register P1/P2 divider fields won't trigger > > an actual change in the DPLL output unless VGA mode is enabled for > > prior to the register write that changes the P1/P2 dividers. The write > > with the new P1/P2 divider can itself disable VGA mode again without > > problems. > > > > I tested the behaviour on my 946GZ, and when manually frobbing the > > register with the display on, the behaviour is very clear. However I > > can't explain why this machine actually works. The P1/P2 divider > > changes caused by normal modesets do seem to make it through to the > > hardware somehow since I get a stable picture on the monitor with > > any resolution. Maybe it's the "three times for luck" stuff that > > somehow masks the problem, or something. > > > > But apparently there are machines (eg. Nick Bowler's G45) where that > > isn't the case and we fail to get the correct clock from the DPLL. > > > > Things used to work because we enabled VGA mode for disabled DPLLs, > > so when re-enabling the DPLL VGA mode was enabled just prior to the > > first register write, and hence the P1/P2 change went through without > > a hitch. That got changed in > > > > b8afb9113c51 drm/i915: Keep GMCH DPLL VGA mode always disabled > > > > in the name of consistency. In order to keep the consistency part, > > leave VGA mode disabled for disabled DPLLs, but turn it on just prior > > to updating the P1/P2 dividers to make sure the hardware picks up > > on the new values. > > > > Cc: Nick Bowler > > Reported-by: Nick Bowler > > Tested-by: Nick Bowler > > Signed-off-by: Ville Syrjälä > > --- > > drivers/gpu/drm/i915/intel_display.c | 7 +++ > > 1 file changed, 7 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c > > b/drivers/gpu/drm/i915/intel_display.c > > index f4fdff9..ce51dbc 100644 > > --- a/drivers/gpu/drm/i915/intel_display.c > > +++ b/drivers/gpu/drm/i915/intel_display.c > > @@ -1743,6 +1743,13 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) > >I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE); > > } > > > > + /* > > +* Apparently we need to have VGA mode enabled prior to changing > > +* the P1/P2 dividers. Otherwise the DPLL will keep using the old > > +* dividers, even though the register value does change. > > +*/ > > + I915_WRITE(reg, 0); > > Again POSTING_READ for ordering? Otherwise Reviewed-by: Daniel Vetter > > Not that there's a lot to review since Bspec is silent ... One option is to start using mmiowb() for documenting the write ordering (which is a no-op on x86 and so heaven forbid we get to use WC ever.) -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping
On Wed, Oct 07, 2015 at 11:34:17AM -0700, Wayne Boyer wrote: > From: Chris Wilson> > A long time ago (before 3.14) we relied on a permanent pinning of the > ifbdev to lock the fb in place inside the GGTT. However, the > introduction of stealing the BIOS framebuffer and reusing its address in > the GGTT for the fbdev has muddied waters and we use an inherited fb. > However, the inherited fb is only pinned whilst it is active and we no > longer have an explicit pin for the info->system_base mmapping used by > the fbdev. The result is that after some aperture pressure the fbdev may > be evicted, but we continue to write the fbcon into the same GGTT > address - overwriting anything else that may be put into that offset. > The effect is most pronounced across suspend/resume as > intel_fbdev_set_suspend() does a full clear over the whole scanout. > > v2: rebased on latest nightly (Wayne) > > Signed-off-by: Chris Wilson > Cc: "Goel, Akash" > Cc: Daniel Vetter > Cc: Jesse Barnes > Cc: sta...@vger.kernel.org > Reviewed-by: Deepak S > Signed-off-by: Wayne Boyer > --- > drivers/gpu/drm/i915/intel_fbdev.c | 15 +++ > 1 file changed, 15 insertions(+) > > diff --git a/drivers/gpu/drm/i915/intel_fbdev.c > b/drivers/gpu/drm/i915/intel_fbdev.c > index 6532912..c6aa4f9 100644 > --- a/drivers/gpu/drm/i915/intel_fbdev.c > +++ b/drivers/gpu/drm/i915/intel_fbdev.c > @@ -215,6 +215,16 @@ static int intelfb_create(struct drm_fb_helper *helper, > obj = intel_fb->obj; > size = obj->base.size; > > + /* The fb constructor will have already pinned us (or inherited a > + * GGTT region from the BIOS) suitable for a scanout, so > + * this should just be a no-op and increment the pin count for the > + * fbdev mmapping. It does have a useful side-effect of validating > + * the pin for fbdev's use via a GGTT mmapping. > + */ > + ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PIN_MAPPABLE); This should be i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE); At which point I just rage quit. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/9] drm/i915: driver based PASID handling
On Wed, Oct 07, 2015 at 10:26:20AM -0700, Jesse Barnes wrote: > On 10/07/2015 10:17 AM, David Woodhouse wrote: > > On Wed, 2015-10-07 at 09:28 -0700, Jesse Barnes wrote: > >> On 10/07/2015 09:14 AM, Daniel Vetter wrote: > >>> On Wed, Oct 07, 2015 at 08:16:42AM -0700, Jesse Barnes wrote: > On 10/07/2015 06:00 AM, David Woodhouse wrote: > > On Fri, 2015-09-04 at 09:59 -0700, Jesse Barnes wrote: > >> + > >> + ret = handle_mm_fault(mm, vma, address, > >> + desc.wr_req ? FAULT_FLAG_WRITE : 0); > >> + if (ret & VM_FAULT_ERROR) { > >> + gpu_mm_segv(tsk, address, SEGV_ACCERR); /* ? */ > >> + goto out_unlock; > >> + } > >> + > > > > Hm, do you need to force the SEGV there, in what ought to be generic > > IOMMU code? > > > > Can you instead just let the fault handler return an appropriate > > failure code to the IOMMU request queue and then deal with the > > resulting error on the i915 device side? > > I'm not sure if we get enough info on the i915 side to handle it > reasonably, we'll have to test that out. > >>> > >>> We do know precisely which context blew up, but without the TDR work we > >>> can't yet just kill the offender selective without affecting the other > >>> active gpu contexts. > >> > >> How? The notification from the IOMMU queue is asynchronous... > > > > The page request, and the response, include 'private data' which an > > endpoint can use to carry that kind of information. > > > > In $7.5.1.1 of the VT-d specification it tells us: > > > > "Private Data: The Private Data field can be used by > > Root-Complex integrated endpoints to uniquely identify > > device-specific private information associated with an > > individual page request. > > > > "For Intel ® Processor Graphics device, the Private Data field > > specifies the identity of the GPU advanced-context (see > > Section 3.10) sending the page request." > > Ah right so we could put our private context ID in there if the PASID > doesn't end up being per-context. That would work fine (though as > Daniel said we still need fancier reset to handle things more > gracefully). I'd hope we can be even more lazy: If we complete the page request with a failure then hopefully the gpu read/write transaction never completes in the EU/ff-unit which means it'll be stuck forever and our hangcheck will get around to clean up the mess. That should work with 0 code changes (but needs a testcase ofc). Later on we can get fancy and try to immediate preempt the ctx and kill it if it faults. But there's a bit of infrastructure missing for that, and I think it'd be better to not stall svm on that. > >>> But besides that I really don't see a reason why we need to kill the > >>> process if the gpu faults. After all if a thread sigfaults then signal > >>> goes to that thread and not some random one (or the one thread that forked > >>> the thread that blew up). And we do have interfaces to tell userspace that > >>> something bad happened with the gpu work it submitted. > > > > I certainly don't want the core IOMMU code killing things. I really > > want to just complete the page request with an appropriate failure > > code, and let the endpoint device deal with it from there. > > I think that will work, but I want to test and make sure. In the driver > mode version I took advantage of the fact that I got an unambiguous page > request failure from the IOMMU along with a unique PASID to send the > signal. Getting it on the GPU side means looking at some of our > existing error state bits, which is something I've been avoiding... gem_reset_stats does this for your already, including test coverage and all. What might be missing is getting reset events from a pollable fd, since the current needs explicit polling. It works that way since that's all arb_robustness wants. And with an fd we can always use the generic SIG_IO stuff for userspace that wants a signal, but by default I don't think we should use signals at all for gpu page faults: The current SIG_SEGV can't be used (since it's clearly for thread-local faults only), same for SIG_BUS, SIG_IO is for fd polling and there's nothing else available. But even the pollable fd is probably best done in a follow-up series, if we even have a need for it. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/irq: Fix misspelled word register in kernel-doc
There is a typo in the function i915_handle_error() kernel-doc and the word register is spelled wrongly. Signed-off-by: Javier Martinez Canillas--- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0344a9181dac..38dadd23684d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2571,7 +2571,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) * i915_handle_error - handle a gpu error * @dev: drm device * - * Do some basic checking of regsiter state at error time and + * 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 -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/irq: Fix kernel-doc warnings
Add the dev parameter for the functions i915_enable_asle_pipestat() and i915_reset_and_wakeup() to the kernel-doc to fix the following warnings: .//drivers/gpu/drm/i915/i915_irq.c:586: warning: No description found for parameter 'dev' .//drivers/gpu/drm/i915/i915_irq.c:2400: warning: No description found for parameter 'dev' Signed-off-by: Javier Martinez Canillas--- drivers/gpu/drm/i915/i915_irq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8ca772deabdb..0344a9181dac 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -581,6 +581,7 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, /** * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion + * @dev: drm device */ static void i915_enable_asle_pipestat(struct drm_device *dev) { @@ -2392,6 +2393,7 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv, /** * i915_reset_and_wakeup - do process context error handling work + * @dev: drm device * * Fire an error uevent so userspace can see that a hang or error * was detected. -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/2] drm/i915: Restore lost DPLL register write on gen2-4
On Wed, Oct 07, 2015 at 10:08:24PM +0300, ville.syrj...@linux.intel.com wrote: > From: Ville Syrjälä> > We accidentally lost the initial DPLL register write in > 1c4e02746147 drm/i915: Fix DVO 2x clock enable on 830M > > The "three times for luck" hack probably saved us from a total > disaster. But anyway, bring the initial write back so that the > code actually makes some sense. > > Cc: sta...@vger.kernel.org > Cc: Nick Bowler Reported-and-tested-by: Nick Bowler References: http://lists.freedesktop.org/archives/intel-gfx/2015-October/077463.html > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/i915/intel_display.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index 147e700..f4fdff9 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -1743,6 +1743,8 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) > I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE); Don't we also need a POSTING_READ here to make sure the two-step 2x mode sequence is still followed? With that addressed Reviewed-by: Daniel Vetter > } > > + I915_WRITE(reg, dpll); > + > /* Wait for the clocks to stabilize. */ > POSTING_READ(reg); > udelay(150); > -- > 2.4.9 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/2] drm/i915: Enable DPLL VGA mode before P1/P2 divider write
On Wed, Oct 07, 2015 at 10:08:25PM +0300, ville.syrj...@linux.intel.com wrote: > From: Ville Syrjälä> > Apparently writing the DPLL register P1/P2 divider fields won't trigger > an actual change in the DPLL output unless VGA mode is enabled for > prior to the register write that changes the P1/P2 dividers. The write > with the new P1/P2 divider can itself disable VGA mode again without > problems. > > I tested the behaviour on my 946GZ, and when manually frobbing the > register with the display on, the behaviour is very clear. However I > can't explain why this machine actually works. The P1/P2 divider > changes caused by normal modesets do seem to make it through to the > hardware somehow since I get a stable picture on the monitor with > any resolution. Maybe it's the "three times for luck" stuff that > somehow masks the problem, or something. > > But apparently there are machines (eg. Nick Bowler's G45) where that > isn't the case and we fail to get the correct clock from the DPLL. > > Things used to work because we enabled VGA mode for disabled DPLLs, > so when re-enabling the DPLL VGA mode was enabled just prior to the > first register write, and hence the P1/P2 change went through without > a hitch. That got changed in > > b8afb9113c51 drm/i915: Keep GMCH DPLL VGA mode always disabled > > in the name of consistency. In order to keep the consistency part, > leave VGA mode disabled for disabled DPLLs, but turn it on just prior > to updating the P1/P2 dividers to make sure the hardware picks up > on the new values. > > Cc: Nick Bowler > Reported-by: Nick Bowler > Tested-by: Nick Bowler > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/i915/intel_display.c | 7 +++ > 1 file changed, 7 insertions(+) > > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index f4fdff9..ce51dbc 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -1743,6 +1743,13 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) > I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE); > } > > + /* > + * Apparently we need to have VGA mode enabled prior to changing > + * the P1/P2 dividers. Otherwise the DPLL will keep using the old > + * dividers, even though the register value does change. > + */ > + I915_WRITE(reg, 0); Again POSTING_READ for ordering? Otherwise Reviewed-by: Daniel Vetter Not that there's a lot to review since Bspec is silent ... -Daniel > + > I915_WRITE(reg, dpll); > > /* Wait for the clocks to stabilize. */ > -- > 2.4.9 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915/irq: Fix misspelled word register in kernel-doc
On Thu, Oct 08, 2015 at 09:57:49AM +0200, Javier Martinez Canillas wrote: > There is a typo in the function i915_handle_error() > kernel-doc and the word register is spelled wrongly. > > Signed-off-by: Javier Martinez CanillasBoth kerneldoc patches applied, thanks. -Daniel > --- > > drivers/gpu/drm/i915/i915_irq.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index 0344a9181dac..38dadd23684d 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -2571,7 +2571,7 @@ static void i915_report_and_clear_eir(struct drm_device > *dev) > * i915_handle_error - handle a gpu error > * @dev: drm device > * > - * Do some basic checking of regsiter state at error time and > + * 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 > -- > 2.4.3 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/2] drm/i915: Restore lost DPLL register write on gen2-4
On Thu, Oct 08, 2015 at 10:17:30AM +0200, Daniel Vetter wrote: > On Wed, Oct 07, 2015 at 10:08:24PM +0300, ville.syrj...@linux.intel.com wrote: > > From: Ville Syrjälä> > > > We accidentally lost the initial DPLL register write in > > 1c4e02746147 drm/i915: Fix DVO 2x clock enable on 830M > > > > The "three times for luck" hack probably saved us from a total > > disaster. But anyway, bring the initial write back so that the > > code actually makes some sense. > > > > Cc: sta...@vger.kernel.org > > Cc: Nick Bowler > Reported-and-tested-by: Nick Bowler > References: > http://lists.freedesktop.org/archives/intel-gfx/2015-October/077463.html > > > Signed-off-by: Ville Syrjälä > > --- > > drivers/gpu/drm/i915/intel_display.c | 2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c > > b/drivers/gpu/drm/i915/intel_display.c > > index 147e700..f4fdff9 100644 > > --- a/drivers/gpu/drm/i915/intel_display.c > > +++ b/drivers/gpu/drm/i915/intel_display.c > > @@ -1743,6 +1743,8 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) > >I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE); > > Don't we also need a POSTING_READ here to make sure the two-step 2x mode > sequence is still followed? We don't do write combining on registers, and there are no shadow register type of things to consider in this case either. > > With that addressed Reviewed-by: Daniel Vetter > > } > > > > + I915_WRITE(reg, dpll); > > + > > /* Wait for the clocks to stabilize. */ > > POSTING_READ(reg); > > udelay(150); > > -- > > 2.4.9 > > > > ___ > > Intel-gfx mailing list > > Intel-gfx@lists.freedesktop.org > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/6] drm/i915: Implement L3 partitioning set-up from the workaround list.
On Wed, Oct 07, 2015 at 04:30:35PM +0300, Francisco Jerez wrote: > Chris Wilsonwrites: > > > On Wed, Oct 07, 2015 at 02:44:00PM +0300, Francisco Jerez wrote: > >> This programs the L3 configuration based on the sizes given for each > >> partition as arguments. The relevant register writes are added to the > >> workaround list so that they are re-applied to each context while it's > >> initialized, preventing state leaks from other userspace processes > >> which may have modified the L3 partitioning from its boot-up state, > >> since all relevant registers are part of the software and hardware > >> command checker whitelists. > >> > >> Some userspace clients (DDX and current versions of Mesa not patched > >> with my L3 partitioning series [1]) assume that the L3 configuration, > >> in particular the URB size, comes up in certain state when a context > >> is created, but nothing in the kernel guarantees this assumption, the > >> registers that control the partitioning of the L3 cache were being > >> left untouched. > >> > >> Note that the VLV_L3SQCREG1_SQGHPCI_DEFAULT macro defined here has the > >> same value as the previously defined VLV_B0_WA_L3SQCREG1_VALUE, but > >> the latter will be removed in a future commit. > >> > >> [1] > >> http://lists.freedesktop.org/archives/mesa-dev/2015-September/093550.html > > > > Merge this with 1 + 5 (or was it 4?)- not only does it introduce a > > temporary unused function, but we have to jump between patches to see > > whether the function is safe (especially given those BUGs), and you add > > all w/a in the same patch so bisection is not improved. > > > What do you want me to merge it with? This *is* PATCH 1, and PATCH 5 is > largely unrelated. I wouldn't have any objection to squashing PATCH 4 > into this commit though. 1+4. That just highlights the issue of having two very tightly coupled patches arbitrary split - the split here doesn't even improve bisection. > > Looking at the function itself, I am not convinced that it actually adds > > anything over calling setting up the WA from the vfuncs - at least the > > bdw/gen7 split is redundant (we split at the vfunc then call one > > function where we replit again, but with nasty constraints on the > > interface of the function for different gen, it's not a function for the > > faint of heart). > > > The constraints are just the hardware's constraints on the L3 > partitioning. The function is meant to implement the details of > programming the L3 configuration, which is different for different gens > even though the overall structure of the L3 partitioning is the same. > Of course the constraints set by specific hardware on the partition > sizes cannot be abstracted out. > > I guess that splitting this out into two functions (one for gen7 and > another for gen8) wouldn't hurt much, but open-coding the function in > all its uses (5) would involve duplicating quite some code. Having slept on it, and I think a gen7/gen8 split is best. My issue with the current combined function is that the interface is different based on generation, which says to me that it is multiple functions. It scores very low on the hard-to-misuse ranking http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html And instead of the multiline multiple ternary operators, just have an if-else-chain for hsw/vlv/ivb (for setting the cmd value). > Assuming I split the function into gen7 and gen8 variants, would you > like them to implement a common consistent interface (i.e. the same > prototype that my init_l3_partitioning_workarounds() implements), or > would you like the variant for each gen to implement an ad-hoc interface > according to the partition configs actually needed on each gen? I > suspect the former would be cleaner. No, the BUGs tell me that the registers do not have a consistent interface. > >> +static int init_l3_partitioning_workarounds(struct intel_engine_cs *ring, > >> + unsigned int n_urb, > >> + unsigned int n_ro, > >> + unsigned int n_dc, > >> + unsigned int n_all) > >> +{ > >> + struct drm_device *dev = ring->dev; > >> + struct drm_i915_private *dev_priv = dev->dev_private; > >> + > >> + if (INTEL_INFO(dev)->gen >= 8) { > > > > Why use dev here? You already have dev_priv, so why chase the pointer > > again? > > Sorry? Does INTEL_INFO() take a drm_device or a drm_i915_private > pointer as argument? The two types don't seem to be related by an > inheritance relationship or anything similar AFAICT, and most other uses > in this file seem to pass a drm_device as argument even where a > drm_i915_private is available. drm_i915_private is our primary internal pointer. We can shave over 8KiB of object code by removing the pointer dance we have from still passing around drm_device and jumping to drm_i915_private. New code is supposed to be
[Intel-gfx] [PATCH v4] drm/i915: Determine the stolen memory base address on gen2
From: Ville SyrjäläThere isn't an explicit stolen memory base register on gen2. Some old comment in the i915 code suggests we should get it via max_low_pfn_mapped, but that's clearly a bad idea on my MGM. The e820 map in said machine looks like this: [0.00] BIOS-e820: [mem 0x-0x0009f7ff] usable [0.00] BIOS-e820: [mem 0x0009f800-0x0009] reserved [0.00] BIOS-e820: [mem 0x000ce000-0x000c] reserved [0.00] BIOS-e820: [mem 0x000dc000-0x000f] reserved [0.00] BIOS-e820: [mem 0x0010-0x1f6e] usable [0.00] BIOS-e820: [mem 0x1f6f-0x1f6f7fff] ACPI data [0.00] BIOS-e820: [mem 0x1f6f8000-0x1f6f] ACPI NVS [0.00] BIOS-e820: [mem 0x1f70-0x1fff] reserved [0.00] BIOS-e820: [mem 0xfec1-0xfec1] reserved [0.00] BIOS-e820: [mem 0xffb0-0xffbf] reserved [0.00] BIOS-e820: [mem 0xfff0-0x] reserved That makes max_low_pfn_mapped = 1f6f, so assuming our stolen memory would start there would place it on top of some ACPI memory regions. So not a good idea as already stated. The 9MB region after the ACPI regions at 0x1f70 however looks promising given that the macine reports the stolen memory size to be 8MB. Looking at the PGTBL_CTL register, the GTT entries are at offset 0x1fee0, and given that the GTT entries occupy 128KB, it looks like the stolen memory could start at 0x1f70 and the GTT entries would occupy the last 128KB of the stolen memory. After some more digging through chipset documentation, I've determined the BIOS first allocates space for something called TSEG (something to do with SMM) from the top of memory, and then it allocates the graphics stolen memory below that. Accordind to the chipset documentation TSEG has a fixed size of 1MB on 855. So that explains the top 1MB in the e820 region. And it also confirms that the GTT entries are in fact at the end of the the stolen memory region. Derive the stolen memory base address on gen2 the same as the BIOS does (TOM-TSEG_SIZE-stolen_size). There are a few differences between the registers on various gen2 chipsets, so a few different codepaths are required. 865G is again bit more special since it seems to support enough memory to hit 4GB address space issues. This means the PCI allocations will also affect the location of the stolen memory. Fortunately there appears to be the TOUD register which may give us the correct answer directly. But the chipset docs are a bit unclear, so I'm not 100% sure that the graphics stolen memory is always the last thing the BIOS steals. Someone would need to verify it on a real system. I tested this on the my 830 and 855 machines, and so far everything looks peachy. v2: Rewrite to use the TOM-TSEG_SIZE-stolen_size and TOUD methods v3: Fix TSEG size for 830 v4: Add missing 'else' (Chris) Tested-by: Chris Wilson Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_gem_stolen.c | 92 ++ 1 file changed, 81 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 69eebc6..cdacf3f 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -30,6 +30,9 @@ #include #include "i915_drv.h" +#define KB(x) ((x) * 1024) +#define MB(x) (KB(x) * 1024) + /* * The BIOS typically reserves some of the system's memory for the exclusive * use of the integrated graphics. This memory is no longer available for @@ -91,24 +94,91 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) /* Almost universally we can find the Graphics Base of Stolen Memory * at offset 0x5c in the igfx configuration space. On a few (desktop) * machines this is also mirrored in the bridge device at different -* locations, or in the MCHBAR. On gen2, the layout is again slightly -* different with the Graphics Segment immediately following Top of -* Memory (or Top of Usable DRAM). Note it appears that TOUD is only -* reported by 865g, so we just use the top of memory as determined -* by the e820 probe. +* locations, or in the MCHBAR. +* +* On 865 we just check the TOUD register. +* +* On 830/845/85x the stolen memory base isn't available in any +* register. We need to calculate it as TOM-TSEG_SIZE-stolen_size. * -* XXX However gen2 requires an unavailable symbol. */ base = 0; if (INTEL_INFO(dev)->gen >= 3) { /* Read Graphics Base of Stolen Memory directly */ pci_read_config_dword(dev->pdev,
[Intel-gfx] [PATCH 3/6] drm/i915: Propagating correct error codes to the userspace
From: Ankitprasad SharmaPropagating correct error codes to userspace by using ERR_PTR and PTR_ERR macros for stolen memory based object allocation. We generally return -ENOMEM to the user whenever there is a failure in object allocation. This patch helps user to identify the correct reason for the failure and not just -ENOMEM each time. v2: Moved the patch up in the series, added error propagation for i915_gem_alloc_object too (Chris) Signed-off-by: Ankitprasad Sharma --- drivers/gpu/drm/i915/i915_gem.c | 15 +- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 4 +-- drivers/gpu/drm/i915/i915_gem_context.c | 4 +-- drivers/gpu/drm/i915/i915_gem_render_state.c | 4 +-- drivers/gpu/drm/i915/i915_gem_stolen.c | 43 drivers/gpu/drm/i915/i915_guc_submission.c | 4 +-- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_fbdev.c | 6 ++-- drivers/gpu/drm/i915/intel_lrc.c | 8 +++--- drivers/gpu/drm/i915/intel_overlay.c | 4 +-- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++--- 12 files changed, 61 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d3f4321..54f7df1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -393,9 +393,9 @@ i915_gem_create(struct drm_file *file, if (flags & I915_CREATE_PLACEMENT_STOLEN) { mutex_lock(>struct_mutex); obj = i915_gem_object_create_stolen(dev, size); - if (!obj) { + if (IS_ERR(obj)) { mutex_unlock(>struct_mutex); - return -ENOMEM; + return PTR_ERR(obj); } /* Always clear fresh buffers before handing to userspace */ @@ -411,8 +411,8 @@ i915_gem_create(struct drm_file *file, obj = i915_gem_alloc_object(dev, size); } - if (obj == NULL) - return -ENOMEM; + if (IS_ERR(obj)) + return PTR_ERR(obj); ret = drm_gem_handle_create(file, >base, ); /* drop reference from allocate - handle holds it now */ @@ -4273,14 +4273,15 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, struct drm_i915_gem_object *obj; struct address_space *mapping; gfp_t mask; + int ret = 0; obj = i915_gem_object_alloc(dev); if (obj == NULL) - return NULL; + return ERR_PTR(-ENOMEM); - if (drm_gem_object_init(dev, >base, size) != 0) { + if ((ret = drm_gem_object_init(dev, >base, size)) != 0) { i915_gem_object_free(obj); - return NULL; + return ERR_PTR(ret); } mask = GFP_HIGHUSER | __GFP_RECLAIMABLE; diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index 7bf2f3f..d79caa2 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -135,8 +135,8 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, int ret; obj = i915_gem_alloc_object(pool->dev, size); - if (obj == NULL) - return ERR_PTR(-ENOMEM); + if (IS_ERR(obj)) + return obj; ret = i915_gem_object_get_pages(obj); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 74aa0c9..603600c 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -157,8 +157,8 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) int ret; obj = i915_gem_alloc_object(dev, size); - if (obj == NULL) - return ERR_PTR(-ENOMEM); + if (IS_ERR(obj)) + return obj; /* * Try to make the context utilize L3 as well as LLC. diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 5026a62..50d010e 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -58,8 +58,8 @@ static int render_state_init(struct render_state *so, struct drm_device *dev) return -EINVAL; so->obj = i915_gem_alloc_object(dev, 4096); - if (so->obj == NULL) - return -ENOMEM; + if (IS_ERR(so->obj)) + return PTR_ERR(so->obj); ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 5ec2190..d3e6813 100644 ---
[Intel-gfx] [PATCH 2/6] drm/i915: Support for creating Stolen memory backed objects
From: Ankitprasad SharmaExtend the drm_i915_gem_create structure to add support for creating Stolen memory backed objects. Added a new flag through which user can specify the preference to allocate the object from stolen memory, which if set, an attempt will be made to allocate the object from stolen memory subject to the availability of free space in the stolen region. v2: Rebased to the latest drm-intel-nightly (Ankit) v3: Changed versioning of GEM_CREATE param, added new comments (Tvrtko) v4: Changed size from 32b to 64b to prevent userspace overflow (Tvrtko) Corrected function arguments ordering (Chris) Testcase: igt/gem_stolen Signed-off-by: Ankitprasad Sharma Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_dma.c| 3 +++ drivers/gpu/drm/i915/i915_drv.h| 2 +- drivers/gpu/drm/i915/i915_gem.c| 30 +++--- drivers/gpu/drm/i915/i915_gem_stolen.c | 4 ++-- include/uapi/drm/i915_drm.h| 16 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 817b05c..0a25f23 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -170,6 +170,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_RESOURCE_STREAMER: value = HAS_RESOURCE_STREAMER(dev); break; + case I915_PARAM_CREATE_VERSION: + value = 2; + break; default: DRM_DEBUG("Unknown parameter %d\n", param->param); return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f962425..bca1572 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3191,7 +3191,7 @@ void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, int i915_gem_init_stolen(struct drm_device *dev); void i915_gem_cleanup_stolen(struct drm_device *dev); struct drm_i915_gem_object * -i915_gem_object_create_stolen(struct drm_device *dev, u32 size); +i915_gem_object_create_stolen(struct drm_device *dev, u64 size); struct drm_i915_gem_object * i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, u32 stolen_offset, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e6b3bc7..d3f4321 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -375,6 +375,7 @@ static int i915_gem_create(struct drm_file *file, struct drm_device *dev, uint64_t size, + uint32_t flags, uint32_t *handle_p) { struct drm_i915_gem_object *obj; @@ -385,8 +386,31 @@ i915_gem_create(struct drm_file *file, if (size == 0) return -EINVAL; + if (flags & __I915_CREATE_UNKNOWN_FLAGS) + return -EINVAL; + /* Allocate the new object */ - obj = i915_gem_alloc_object(dev, size); + if (flags & I915_CREATE_PLACEMENT_STOLEN) { + mutex_lock(>struct_mutex); + obj = i915_gem_object_create_stolen(dev, size); + if (!obj) { + mutex_unlock(>struct_mutex); + return -ENOMEM; + } + + /* Always clear fresh buffers before handing to userspace */ + ret = i915_gem_clear_object(obj); + if (ret) { + drm_gem_object_unreference(>base); + mutex_unlock(>struct_mutex); + return ret; + } + + mutex_unlock(>struct_mutex); + } else { + obj = i915_gem_alloc_object(dev, size); + } + if (obj == NULL) return -ENOMEM; @@ -409,7 +433,7 @@ i915_gem_dumb_create(struct drm_file *file, args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); args->size = args->pitch * args->height; return i915_gem_create(file, dev, - args->size, >handle); + args->size, 0, >handle); } /** @@ -422,7 +446,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_create *args = data; return i915_gem_create(file, dev, - args->size, >handle); + args->size, args->flags, >handle); } static inline int diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 1520779..5ec2190 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -497,7 +497,7 @@ cleanup: } struct drm_i915_gem_object * -i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
[Intel-gfx] [PATCH 5/6] drm/i915: Support for pread/pwrite from/to non shmem backed objects
From: Ankitprasad SharmaThis patch adds support for extending the pread/pwrite functionality for objects not backed by shmem. The access will be made through gtt interface. This will cover prime objects as well as stolen memory backed objects but for userptr objects it is still forbidden. v2: Drop locks around slow_user_access, prefault the pages before access (Chris) v3: Rebased to the latest drm-intel-nightly (Ankit) v4: Moved page base & offset calculations outside the copy loop, corrected data types for size and offset variables, corrected if-else braces format (Tvrtko/kerneldocs) v5: Enabled pread/pwrite for all non-shmem backed objects including without tiling restrictions (Ankit) v6: Using pwrite_fast for non-shmem backed objects as well (Chris) Testcase: igt/gem_stolen Signed-off-by: Ankitprasad Sharma --- drivers/gpu/drm/i915/i915_gem.c | 125 +--- 1 file changed, 104 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 91a2e97..2c94e22 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -614,6 +614,99 @@ shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length, return ret ? - EFAULT : 0; } +static inline uint64_t +slow_user_access(struct io_mapping *mapping, +uint64_t page_base, int page_offset, +char __user *user_data, +int length, bool pwrite) +{ + void __iomem *vaddr_inatomic; + void *vaddr; + uint64_t unwritten; + + vaddr_inatomic = io_mapping_map_wc(mapping, page_base); + /* We can use the cpu mem copy function because this is X86. */ + vaddr = (void __force *)vaddr_inatomic + page_offset; + if (pwrite) + unwritten = __copy_from_user(vaddr, user_data, length); + else + unwritten = __copy_to_user(user_data, vaddr, length); + + io_mapping_unmap(vaddr_inatomic); + return unwritten; +} + +static int +i915_gem_gtt_pread(struct drm_device *dev, + struct drm_i915_gem_object *obj, uint64_t size, + uint64_t data_offset, uint64_t data_ptr) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + char __user *user_data; + uint64_t remain; + uint64_t offset, page_base; + int page_offset, page_length, ret = 0; + + ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE); + if (ret) + goto out; + + ret = i915_gem_object_set_to_gtt_domain(obj, false); + if (ret) + goto out_unpin; + + ret = i915_gem_object_put_fence(obj); + if (ret) + goto out_unpin; + + user_data = to_user_ptr(data_ptr); + remain = size; + offset = i915_gem_obj_ggtt_offset(obj) + data_offset; + + mutex_unlock(>struct_mutex); + if (likely(!i915.prefault_disable)) + ret = fault_in_multipages_writeable(user_data, remain); + + /* +* page_offset = offset within page +* page_base = page offset within aperture +*/ + page_offset = offset_in_page(offset); + page_base = offset & PAGE_MASK; + + while (remain > 0) { + /* page_length = bytes to copy for this page */ + page_length = remain; + if ((page_offset + remain) > PAGE_SIZE) + page_length = PAGE_SIZE - page_offset; + + /* This is a slow read/write as it tries to read from +* and write to user memory which may result into page +* faults +*/ + ret = slow_user_access(dev_priv->gtt.mappable, page_base, + page_offset, user_data, + page_length, false); + + if (ret) { + ret = -EFAULT; + break; + } + + remain -= page_length; + user_data += page_length; + page_base += page_length; + page_offset = 0; + } + + mutex_lock(>struct_mutex); + +out_unpin: + i915_gem_object_ggtt_unpin(obj); +out: + return ret; +} + static int i915_gem_shmem_pread(struct drm_device *dev, struct drm_i915_gem_object *obj, @@ -737,17 +830,14 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, goto out; } - /* prime objects have no backing filp to GEM pread/pwrite -* pages from. -*/ - if (!obj->base.filp) { - ret = -EINVAL; - goto out; - } - trace_i915_gem_object_pread(obj, args->offset, args->size); - ret = i915_gem_shmem_pread(dev, obj, args, file); + /* pread for non shmem backed objects */ + if (!obj->base.filp && obj->tiling_mode
[Intel-gfx] [PATCH 1/6] drm/i915: Clearing buffer objects via CPU/GTT
From: Ankitprasad SharmaThis patch adds support for clearing buffer objects via CPU/GTT. This is particularly useful for clearing out the non shmem backed objects. Currently intend to use this only for buffers allocated from stolen region. v2: Added kernel doc for i915_gem_clear_object(), corrected/removed variable assignments (Tvrtko) Testcase: igt/gem_stolen Signed-off-by: Ankitprasad Sharma Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 39 +++ 2 files changed, 40 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2b5d587..f962425 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2848,6 +2848,7 @@ int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj, int *needs_clflush); int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj); +int i915_gem_clear_object(struct drm_i915_gem_object *obj); static inline int __sg_page_count(struct scatterlist *sg) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index bf5ef7a..e6b3bc7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5143,3 +5143,42 @@ fail: drm_gem_object_unreference(>base); return ERR_PTR(ret); } + +/** + * i915_gem_clear_object() - Clear buffer object via CPU/GTT + * @obj: Buffer object to be cleared + * + * Return: 0 - success, non-zero - failure + */ +int i915_gem_clear_object(struct drm_i915_gem_object *obj) +{ + int ret; + char __iomem *base; + size_t size = obj->base.size; + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + + WARN_ON(!mutex_is_locked(>base.dev->struct_mutex)); + ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE); + if (ret) + return ret; + + ret = i915_gem_object_put_fence(obj); + if (ret) + goto unpin; + + /* Get the CPU virtual address of the buffer */ + base = ioremap_wc(dev_priv->gtt.mappable_base + + i915_gem_obj_ggtt_offset(obj), size); + if (base == NULL) { + DRM_ERROR("Mapping of gem object to CPU failed!\n"); + ret = -ENOSPC; + goto unpin; + } + + memset_io(base, 0, size); + + iounmap(base); +unpin: + i915_gem_object_ggtt_unpin(obj); + return ret; +} -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 4/6] drm/i915: Add support for stealing purgable stolen pages
From: Chris Wilson If we run out of stolen memory when trying to allocate an object, see if we can reap enough purgeable objects to free up enough contiguous free space for the allocation. This is in principle very much like evicting objects to free up enough contiguous space in the vma when binding a new object - and you will be forgiven for thinking that the code looks very similar. At the moment, we do not allow userspace to allocate objects in stolen, so there is neither the memory pressure to trigger stolen eviction nor any purgeable objects inside the stolen arena. However, this will change in the near future, and so better management and defragmentation of stolen memory will become a real issue. v2: Remember to remove the drm_mm_node. v3: Rebased to the latest drm-intel-nightly (Ankit) v4: corrected if-else braces format (Tvrtko/kerneldoc) v5: Rebased to the latest drm-intel-nightly (Ankit) Added a seperate list to maintain purgable objects from stolen memory region (Chris/Daniel) v6: Compiler optimization (merging 2 single loops into one for() loop), corrected code for object eviction, retire_requests before starting object eviction (Chris) v7: Added kernel doc for i915_gem_object_create_stolen() Testcase: igt/gem_stolen Signed-off-by: Chris Wilson Signed-off-by: Ankitprasad Sharma--- drivers/gpu/drm/i915/i915_debugfs.c| 4 +- drivers/gpu/drm/i915/i915_drv.h| 17 +++- drivers/gpu/drm/i915/i915_gem.c| 16 drivers/gpu/drm/i915/i915_gem_stolen.c | 169 + drivers/gpu/drm/i915/intel_pm.c| 4 +- 5 files changed, 186 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8797717..13762c1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -174,7 +174,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) seq_puts(m, ")"); } if (obj->stolen) - seq_printf(m, " (stolen: %08llx)", obj->stolen->start); + seq_printf(m, " (stolen: %08llx)", obj->stolen->base.start); if (obj->pin_display || obj->fault_mappable) { char s[3], *t = s; if (obj->pin_display) @@ -253,7 +253,7 @@ static int obj_rank_by_stolen(void *priv, struct drm_i915_gem_object *b = container_of(B, struct drm_i915_gem_object, obj_exec_link); - return a->stolen->start - b->stolen->start; + return a->stolen->base.start - b->stolen->base.start; } static int i915_gem_stolen_list_info(struct seq_file *m, void *data) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bca1572..5612df3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -850,6 +850,12 @@ struct i915_ctx_hang_stats { bool banned; }; +struct i915_stolen_node { + struct drm_mm_node base; + struct list_head mm_link; + struct drm_i915_gem_object *obj; +}; + /* This must match up with the value previously used for execbuf2.rsvd1. */ #define DEFAULT_CONTEXT_HANDLE 0 @@ -1279,6 +1285,13 @@ struct i915_gem_mm { */ struct list_head unbound_list; + /** +* List of stolen objects that have been marked as purgeable and +* thus available for reaping if we need more space for a new +* allocation. Ordered by time of marking purgeable. +*/ + struct list_head stolen_list; + /** Usable portion of the GTT for GEM */ unsigned long stolen_base; /* limited to low memory (32-bit) */ @@ -2047,7 +2060,7 @@ struct drm_i915_gem_object { struct list_head vma_list; /** Stolen memory for this object, instead of being backed by shmem. */ - struct drm_mm_node *stolen; + struct i915_stolen_node *stolen; struct list_head global_list; struct list_head ring_list[I915_NUM_RINGS]; @@ -2055,6 +2068,7 @@ struct drm_i915_gem_object { struct list_head obj_exec_link; struct list_head batch_pool_link; + struct list_head tmp_link; /** * This is set if the object is on the active lists (has pending @@ -2171,6 +2185,7 @@ struct drm_i915_gem_object { }; }; #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base) +#define I915_BO_IS_ACTIVE(__obj) (__obj->active) void i915_gem_track_fb(struct drm_i915_gem_object *old, struct drm_i915_gem_object *new, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 54f7df1..91a2e97 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4233,6 +4233,20 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, if (obj->madv == I915_MADV_DONTNEED && obj->pages == NULL) i915_gem_object_truncate(obj); +
[Intel-gfx] [PATCH 6/6] drm/i915: Migrate stolen objects before hibernation
From: Chris WilsonVille reminded us that stolen memory is not preserved across hibernation, and a result of this was that context objects now being allocated from stolen were being corrupted on S4 and promptly hanging the GPU on resume. We want to utilise stolen for as much as possible (nothing else will use that wasted memory otherwise), so we need a strategy for handling general objects allocated from stolen and hibernation. A simple solution is to do a CPU copy through the GTT of the stolen object into a fresh shmemfs backing store and thenceforth treat it as a normal objects. This can be refined in future to either use a GPU copy to avoid the slow uncached reads (though it's hibernation!) and recreate stolen objects upon resume/first-use. For now, a simple approach should suffice for testing the object migration. v2: Swap PTE for pinned bindings over to the shmemfs. This adds a complicated dance, but is required as many stolen objects are likely to be pinned for use by the hardware. Swapping the PTEs should not result in externally visible behaviour, as each PTE update should be atomic and the two pages identical. (danvet) safe-by-default, or the principle of least surprise. We need a new flag to mark objects that we can wilfully discard and recreate across hibernation. (danvet) Just use the global_list rather than invent a new stolen_list. This is the slowpath hibernate and so adding a new list and the associated complexity isn't worth it. v3: Rebased on drm-intel-nightly (Ankit) Signed-off-by: Chris Wilson Signed-off-by: Ankitprasad Sharma --- drivers/gpu/drm/i915/i915_drv.c | 17 ++- drivers/gpu/drm/i915/i915_drv.h | 7 + drivers/gpu/drm/i915/i915_gem.c | 230 ++-- drivers/gpu/drm/i915/intel_display.c| 3 + drivers/gpu/drm/i915/intel_fbdev.c | 6 + drivers/gpu/drm/i915/intel_pm.c | 2 + drivers/gpu/drm/i915/intel_ringbuffer.c | 6 + 7 files changed, 259 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e6d7a69..7663fb4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -968,6 +968,21 @@ static int i915_pm_suspend(struct device *dev) return i915_drm_suspend(drm_dev); } +static int i915_pm_freeze(struct device *dev) +{ + int ret; + + ret = i915_gem_freeze(pci_get_drvdata(to_pci_dev(dev))); + if (ret) + return ret; + + ret = i915_pm_suspend(dev); + if (ret) + return ret; + + return 0; +} + static int i915_pm_suspend_late(struct device *dev) { struct drm_device *drm_dev = dev_to_i915(dev)->dev; @@ -1621,7 +1636,7 @@ static const struct dev_pm_ops i915_pm_ops = { * @restore, @restore_early : called after rebooting and restoring the *hibernation image [PMSG_RESTORE] */ - .freeze = i915_pm_suspend, + .freeze = i915_pm_freeze, .freeze_late = i915_pm_suspend_late, .thaw_early = i915_pm_resume_early, .thaw = i915_pm_resume, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5612df3..1efa3b6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2094,6 +2094,12 @@ struct drm_i915_gem_object { * Advice: are the backing pages purgeable? */ unsigned int madv:2; + /** +* Whereas madv is for userspace, there are certain situations +* where we want I915_MADV_DONTNEED behaviour on internal objects +* without conflating the userspace setting. +*/ + unsigned int internal_volatile:1; /** * Current tiling mode for the object. @@ -2981,6 +2987,7 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice); void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); +int __must_check i915_gem_freeze(struct drm_device *dev); int __must_check i915_gem_suspend(struct drm_device *dev); void __i915_add_request(struct drm_i915_gem_request *req, struct drm_i915_gem_object *batch_obj, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2c94e22..843f3d1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4365,12 +4365,27 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = { .put_pages = i915_gem_object_put_pages_gtt, }; +static struct address_space * +i915_gem_set_inode_gfp(struct drm_device *dev, struct file *file) +{ + struct address_space *mapping = file_inode(file)->i_mapping; + gfp_t mask; + + mask = GFP_HIGHUSER | __GFP_RECLAIMABLE; + if (IS_CRESTLINE(dev) ||
[Intel-gfx] [PULL] topic/drm-misc
Hi Dave, Another round of drm-misc. Unfortunately the DRM_UNLOCKED removal for DRIVER_MODESET isn't complete yet for lack of review on 1-2 patches. Otherwise just various stuff all over. Cheers, Daniel The following changes since commit 2d4df13c0f9ef56452b1d9a9016cb3946e17bfe5: Merge tag 'topic/drm-misc-2015-09-25' of git://anongit.freedesktop.org/drm-intel into drm-next (2015-09-30 08:35:45 +1000) are available in the git repository at: git://anongit.freedesktop.org/drm-intel tags/topic/drm-misc-2015-10-08 for you to fetch changes up to b44f84081b8db1b5830cbd30280ba1109cc1a084: drm: Stop using drm_vblank_count() as the hw frame counter (2015-10-07 16:13:52 +0200) Daniel Vetter (8): drm/doc: Update docs about device instance setup drm: Remove __OS_HAS_AGP drm: Define a drm_invalid_op ioctl implementation drm/drm_ioctl.c: kerneldoc drm/vmwgfx: Stop checking for DRM_UNLOCKED drm: Remove dummy agp ioctl wrappers drm/i915: Remove setparam ioctl drm: Hack around CONFIG_AGP=m build failures Joonas Lahtinen (2): drm: Add DRM_ROTATE_MASK and DRM_REFLECT_MASK drm: Use DRM_ROTATE_MASK and DRM_REFLECT_MASK Lukas Wunner (1): vga_switcheroo: Add missing locking Rasmus Villemoes (1): vgaarb: use kzalloc in vga_arbiter_add_pci_device() Thierry Reding (1): drm/irq: Use unsigned int pipe in public API Ville Syrjälä (2): drm: Don't zero vblank timestamps from the irq handler drm: Stop using drm_vblank_count() as the hw frame counter Documentation/DocBook/drm.tmpl | 100 +--- drivers/gpu/drm/Makefile| 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 9 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 36 - drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h| 9 +-- drivers/gpu/drm/armada/armada_drv.c | 10 +-- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 8 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 2 +- drivers/gpu/drm/drm_agpsupport.c| 4 - drivers/gpu/drm/drm_bufs.c | 6 +- drivers/gpu/drm/drm_crtc.c | 3 +- drivers/gpu/drm/drm_drv.c | 55 - drivers/gpu/drm/drm_ioc32.c | 6 +- drivers/gpu/drm/drm_ioctl.c | 83 ++-- drivers/gpu/drm/drm_irq.c | 26 +- drivers/gpu/drm/drm_memory.c| 6 +- drivers/gpu/drm/drm_pci.c | 11 +++ drivers/gpu/drm/drm_platform.c | 3 + drivers/gpu/drm/drm_rect.c | 4 +- drivers/gpu/drm/drm_vm.c| 8 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c| 4 +- drivers/gpu/drm/exynos/exynos_drm_crtc.h| 4 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 7 +- drivers/gpu/drm/gma500/psb_drv.h| 6 +- drivers/gpu/drm/gma500/psb_irq.c| 8 +- drivers/gpu/drm/gma500/psb_irq.h| 6 +- drivers/gpu/drm/i915/i915_debugfs.c | 1 - drivers/gpu/drm/i915/i915_dma.c | 33 +--- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_gem_fence.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 34 drivers/gpu/drm/imx/imx-drm-core.c | 10 +-- drivers/gpu/drm/mga/mga_dma.c | 4 +- drivers/gpu/drm/mga/mga_drv.h | 6 +- drivers/gpu/drm/mga/mga_irq.c | 20 ++--- drivers/gpu/drm/msm/msm_drv.c | 14 ++-- drivers/gpu/drm/nouveau/nouveau_bo.c| 8 +- drivers/gpu/drm/nouveau/nouveau_display.c | 23 +++--- drivers/gpu/drm/nouveau/nouveau_display.h | 12 +-- drivers/gpu/drm/nouveau/nouveau_drm.c | 2 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/omapdrm/omap_drv.h | 4 +- drivers/gpu/drm/omapdrm/omap_fb.c | 4 +- drivers/gpu/drm/omapdrm/omap_irq.c | 16 ++-- drivers/gpu/drm/omapdrm/omap_plane.c| 2 +- drivers/gpu/drm/qxl/qxl_drv.c | 7 +- drivers/gpu/drm/r128/r128_cce.c | 12 +-- drivers/gpu/drm/r128/r128_drv.h | 6 +- drivers/gpu/drm/r128/r128_irq.c | 16 ++-- drivers/gpu/drm/radeon/r600_cp.c| 14 ++-- drivers/gpu/drm/radeon/radeon_agp.c | 8 +- drivers/gpu/drm/radeon/radeon_cp.c | 16 ++-- drivers/gpu/drm/radeon/radeon_display.c | 25 +++--- drivers/gpu/drm/radeon/radeon_drv.c | 13 ++-
[Intel-gfx] [PATCH 2/3] drm/edid: Round to closest when computing the CEA/HDMI alternate clock
From: Ville SyrjäläRounding to the closest kHz seems like the better option that round down or up when computing the alternate clock for CEA/HDMI modes. It'll give us a slightly more accurate clock in some cases. Not sure why I went for the down+up approach originally. Perhaps I was thinking we can go back and forth betwen the two frequencies without introducing errors, but round to closest still maintains that property. Cc: Adam Jackson Cc: Clint Taylor Cc: Libin Yang Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_edid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 977915c..d5d2c03 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2538,9 +2538,9 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode) * and the 60Hz variant otherwise. */ if (cea_mode->vdisplay == 240 || cea_mode->vdisplay == 480) - clock = clock * 1001 / 1000; + clock = DIV_ROUND_CLOSEST(clock * 1001, 1000); else - clock = DIV_ROUND_UP(clock * 1000, 1001); + clock = DIV_ROUND_CLOSEST(clock * 1000, 1001); return clock; } -- 2.4.9 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/3] drm/edid: Fix up clock for CEA/HDMI modes specified via detailed timings
From: Ville SyrjäläEDID detailed timings have a resolution of 10kHz for the pixel clock, so they can't represent certain CEA/HDMI modes accurately. If we see a mode coming in via detailed timings which otherwise matches one of the CEA/HDMI modes except the clock is just a bit off, let's assume that the intention was for that mode to be one of the CEA/HDMI modes and go ahead and fix up the clock to match the CEA/HDMI spec exactly (well, as close as we can get with the 1 kHz resolution we use). This should help code that's looking for an exact clock match (eg. i915 audio N/CTS setup). Cc: Adam Jackson Cc: Clint Taylor Cc: Libin Yang Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_edid.c | 48 ++ 1 file changed, 48 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index d895556..977915c 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2418,6 +2418,8 @@ add_cvt_modes(struct drm_connector *connector, struct edid *edid) return closure.modes; } +static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode); + static void do_detailed_mode(struct detailed_timing *timing, void *c) { @@ -2434,6 +2436,13 @@ do_detailed_mode(struct detailed_timing *timing, void *c) if (closure->preferred) newmode->type |= DRM_MODE_TYPE_PREFERRED; + /* +* Detailed modes are limited to 10kHz pixel clock resolution, +* so fix up anything that looks like CEA/HDMI mode, but the clock +* is just slightly off. +*/ + fixup_detailed_cea_mode_clock(newmode); + drm_mode_probed_add(closure->connector, newmode); closure->modes++; closure->preferred = 0; @@ -3103,6 +3112,45 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid) return modes; } +static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode) +{ + const struct drm_display_mode *cea_mode; + int clock1, clock2, clock; + u8 mode_idx; + const char *type; + + mode_idx = drm_match_cea_mode(mode) - 1; + if (mode_idx < ARRAY_SIZE(edid_cea_modes)) { + type = "CEA"; + cea_mode = _cea_modes[mode_idx]; + clock1 = cea_mode->clock; + clock2 = cea_mode_alternate_clock(cea_mode); + } else { + mode_idx = drm_match_hdmi_mode(mode) - 1; + if (mode_idx < ARRAY_SIZE(edid_4k_modes)) { + type = "HDMI"; + cea_mode = _4k_modes[mode_idx]; + clock1 = cea_mode->clock; + clock2 = hdmi_mode_alternate_clock(cea_mode); + } else { + return; + } + } + + /* pick whichever is closest */ + if (abs(mode->clock - clock1) < abs(mode->clock - clock2)) + clock = clock1; + else + clock = clock2; + + if (mode->clock == clock) + return; + + DRM_DEBUG("detailed mode matches %s VIC %d, adjusting clock %d -> %d\n", + type, mode_idx + 1, mode->clock, clock); + mode->clock = clock; +} + static void parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db) { -- 2.4.9 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/3] drm/i915: Use round to closest when computing the CEA 1.001 pixel clocks
From: Ville Syrjälädrm_edid.c now computes the alternate CEA clocks using DIV_ROUND_CLOSEST(), so follow suit in the N/CTS setup to make sure we pick the right setting for the mode. Unfortunately we can't actually use DIV_ROUND_CLOSEST() here due to the ({}) construct used, so just stick in raw numbers instead. Cc: Clint Taylor Cc: Libin Yang Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_audio.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 56c2f54..4dccd9b 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -61,21 +61,21 @@ static const struct { int clock; u32 config; } hdmi_audio_clock[] = { - { DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, + { 25175, AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, { 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ { 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, - { 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, + { 27027, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, { 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, - { 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, - { DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, + { 54054, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, + { 74176, AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, { 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, - { DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, + { 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, { 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, }; /* HDMI N/CTS table */ #define TMDS_297M 297000 -#define TMDS_296M DIV_ROUND_UP(297000 * 1000, 1001) +#define TMDS_296M 296703 static const struct { int sample_rate; int clock; -- 2.4.9 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: 4K audio N value incorrect at 29.97 and 23.98 refresh rate
On Wed, Oct 07, 2015 at 02:38:29PM -0700, clinton.a.tay...@intel.com wrote: > From: Clint Taylor> > The TMDS_296M define was computing as 296704 but the mode->clock is > 296700 as defined by EDID. Adjusted define to allow correct detection > of the need to program the correct N value for 29.97 and 23.98 refresh > rate. > > Signed-off-by: Clint Taylor > --- > drivers/gpu/drm/i915/intel_audio.c |2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/intel_audio.c > b/drivers/gpu/drm/i915/intel_audio.c > index 56c2f54..419c979 100644 > --- a/drivers/gpu/drm/i915/intel_audio.c > +++ b/drivers/gpu/drm/i915/intel_audio.c > @@ -75,7 +75,7 @@ static const struct { > > /* HDMI N/CTS table */ > #define TMDS_297M 297000 > -#define TMDS_296M DIV_ROUND_UP(297000 * 1000, 1001) > +#define TMDS_296M 296700 Hmm. I think we might want to fix up the mode instead. Let me post a few patches, and let's see what people think... > static const struct { > int sample_rate; > int clock; > -- > 1.7.9.5 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] igt/kms_addfb_basic: New subtest to check for fb modifier and tiling mode mismatch
On 07/10/15 22:07, Vivek Kasireddy wrote: Hi Tvrtko, On Wed, 7 Oct 2015 15:07:30 +0100 Tvrtko Ursulinwrote: Hi, On 07/10/15 03:35, Vivek Kasireddy wrote: This new subtest will validate a Y-tiled object's tiling mode against its associated fb modifier. Cc: Tvrtko Ursulin Signed-off-by: Vivek Kasireddy --- tests/kms_addfb_basic.c | 9 + 1 file changed, 9 insertions(+) diff --git a/tests/kms_addfb_basic.c b/tests/kms_addfb_basic.c index d466e4d..7ca1add 100644 --- a/tests/kms_addfb_basic.c +++ b/tests/kms_addfb_basic.c @@ -373,6 +373,15 @@ static void addfb25_ytile(int fd, int gen) f.handles[0] = gem_bo; } + igt_subtest("addfb25-Y-tiled-X-modifier-mismatch") { + igt_require(gen >= 9); + igt_require_fb_modifiers(fd); + gem_set_tiling(fd, gem_bo, I915_TILING_Y, 1024*4); + + f.modifier[0] = LOCAL_I915_FORMAT_MOD_X_TILED; + igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, ) < 0 && errno == EINVAL); + } + igt_subtest("addfb25-Y-tiled") { igt_require_fb_modifiers(fd); Wasn't the original WARN triggered by Y tiled object and Y fb modifier? Creating a new fb using a Y-tiled object and Y/X fb modifier will not trigger the original WARN. It'll be triggered only if the fb is going to be pinned -- and flipped. I am not sure how to get that WARN to be triggered with the existing suite of igt tests. Ah yes, you would need to attempt display it, not even necessarily flip it. I am sure there are tests which do that. :) I know from recent activity kms_rotation_crc for example creates a Y tiled FB and displays it. So maybe borrow some code to start with from there. Regards, Tvrtko ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v8 0/6] Support for creating/using Stolen memory backed objects
From: Ankitprasad SharmaThis patch series adds support for creating/using Stolen memory backed objects. Despite being a unified memory architecture (UMA) some bits of memory are more equal than others. In particular we have the thorny issue of stolen memory, memory stolen from the system by the BIOS and reserved for igfx use. Stolen memory is required for some functions of the GPU and display engine, but in general it goes wasted. Whilst we cannot return it back to the system, we need to find some other method for utilising it. As we do not support direct access to the physical address in the stolen region, it behaves like a different class of memory, closer in kin to local GPU memory. This strongly suggests that we need a placement model like TTM if we are to fully utilize these discrete chunks of differing memory. To add support for creating Stolen memory backed objects, we extend the drm_i915_gem_create structure, by adding a new flag through which user can specify the preference to allocate the object from stolen memory, which if set, an attempt will be made to allocate the object from stolen memory subject to the availability of free space in the stolen region. This patch series adds support for clearing buffer objects via CPU/GTT. This is particularly useful for clearing out the memory from stolen region, but can also be used for other shmem allocated objects. Currently being used for buffers allocated in the stolen region. Also adding support for stealing purgable stolen pages, if we run out of stolen memory when trying to allocate an object. v2: Added support for read/write from/to objects not backed by shmem using the pread/pwrite interface. Also extended the current get_aperture ioctl to retrieve the total and available size of the stolen region v3: Removed the extended get_aperture ioctl patch 5 (to be submitted as part of other patch series), addressed comments by Chris about pread/pwrite for non shmem backed objects v4: Rebased to the latest drm-intel-nightly v5: Addressed comments, replaced patch 1/4 "Clearing buffers via blitter engine" by "Clearing buffers via CPU/GTT" v6: Rebased to the latest drm-intel-nightly, Addressed comments, updated stolen memory purging logic by maintaining a list for purgable stolen memory objects, enabled pread/pwrite for all non-shmem backed objects without tiling restrictions v7: Addressed comments, compiler optimization, new patch added for correct error code propagation to the userspace v8: Added a new patch to the series to Migrate stolen objects before hibernation, as stolen memory is not preserved across hibernation. Added correct error propagation for shmem as well non-shmem backed object allocation This can be verified using IGT tests: igt/gem_stolen, igt/gem_create Ankitprasad Sharma (4): drm/i915: Clearing buffer objects via CPU/GTT drm/i915: Support for creating Stolen memory backed objects drm/i915: Propagating correct error codes to the userspace drm/i915: Support for pread/pwrite from/to non shmem backed objects Chris Wilson (2): drm/i915: Add support for stealing purgable stolen pages drm/i915: Migrate stolen objects before hibernation drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_dma.c | 3 + drivers/gpu/drm/i915/i915_drv.c | 17 +- drivers/gpu/drm/i915/i915_drv.h | 27 +- drivers/gpu/drm/i915/i915_gem.c | 451 --- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 4 +- drivers/gpu/drm/i915/i915_gem_context.c | 4 +- drivers/gpu/drm/i915/i915_gem_render_state.c | 4 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 210 ++--- drivers/gpu/drm/i915/i915_guc_submission.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 5 +- drivers/gpu/drm/i915/intel_fbdev.c | 12 +- drivers/gpu/drm/i915/intel_lrc.c | 8 +- drivers/gpu/drm/i915/intel_overlay.c | 4 +- drivers/gpu/drm/i915/intel_pm.c | 8 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 26 +- include/uapi/drm/i915_drm.h | 16 + 17 files changed, 694 insertions(+), 113 deletions(-) -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/2] drm/i915/skl: Allow universal planes to position
On 07/10/15 15:19, Daniel Vetter wrote: On Tue, Oct 06, 2015 at 07:28:10PM +0300, Ville Syrjälä wrote: On Tue, Oct 06, 2015 at 08:16:19AM -0700, Matt Roper wrote: On Tue, Oct 06, 2015 at 05:42:42PM +0300, Ville Syrjälä wrote: On Tue, Oct 06, 2015 at 07:29:54AM -0700, Matt Roper wrote: On Tue, Oct 06, 2015 at 02:32:47PM +0100, Tvrtko Ursulin wrote: On 10/04/15 10:07, Sonika Jindal wrote: Signed-off-by: Sonika JindalReviewed-by: Matt Roper --- drivers/gpu/drm/i915/intel_display.c |7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ceb2e61..f0bbc22 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12150,16 +12150,21 @@ intel_check_primary_plane(struct drm_plane *plane, struct drm_rect *dest = >dst; struct drm_rect *src = >src; const struct drm_rect *clip = >clip; + bool can_position = false; int ret; crtc = crtc ? crtc : plane->crtc; intel_crtc = to_intel_crtc(crtc); + if (INTEL_INFO(dev)->gen >= 9) + can_position = true; + ret = drm_plane_helper_check_update(plane, crtc, fb, src, dest, clip, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, - false, true, >visible); + can_position, true, + >visible); if (ret) return ret; I have discovered today that, while this allows SetCrtc and SetPlane ioctls to work with frame buffers which do not cover the plane, page flips are not that lucky and fail roughly with: [drm:drm_crtc_check_viewport] Invalid fb size 1080x1080 for CRTC viewport 1920x1080+0+0. Maybe I'm misunderstanding your explanation, but a framebuffer is always required to fill/cover the plane scanning out of it. What this patch is supposed to be allowing is for the primary plane to not cover the entire CRTC (since that's something that only became possible for Intel hardware on the gen9+ platforms). I.e., the primary plane is now allowed to positioned and resized to cover a subset of the CRTC area, just like "sprite" planes have always been able to. If you've got a 1080x1080 framebuffer, then it's legal to have a 1080x1080 primary plane while running in 1920x1080 mode on SKL/BXT. However it is not legal to size the primary plane as 1920x1080 and use this same 1080x1080 framebuffer with any of our interfaces (setplane, setcrtc, pageflip, or atomic). Are you using ioctls/libdrm directly or are you using igt_kms helpers? IIRC, the IGT helpers will try to be extra helpful and automatically size the plane to match the framebuffer (unless you override that behavior), so that might be what's causing the confusion here. The problem is clear as day in drm_mode_page_flip_ioctl(): ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, >mode, fb); if (ret) goto out; The fix should be easy; just extract the current src coordinates from the plane state and check those against the new fb size. And then hope that the plane state is really up to date. Yep, that's the conclusion we came to once Tvrtko explained what he was seeing on IRC. I'm not sure whether non-atomic drivers have enough state setup by the default helpers to work properly. Worst case we'll just assume that a non-atomic driver won't support primary plane windowing (since none have in the past) and fall back to looking at the mode for legacy non-atomic drivers. And I'm sure rotated cases will go boom in some other ways. Probably we should just switch over to using the full plane update for mmio flips to fix it. Yeah; the core looks at a drm_plane->invert_dimensions field that's only set by omap. That should probably be updated to look at the state's rotation on atomic-capable drivers. We can just look at the src coordinates. Those always match the fb orientation. Can we just not bother with legacy pageflips on rotated planes? setplane works and once you rotate it kinda gets nasty anyway. I don't know - thought it is simple enough to make it work so why not? Just " [PATCH] drm/i915: Consider plane rotation when calculating stride in skl_do_mmio_flip" I posted, plus Matt's "[PATCH] drm: Check fb against plane size rather than CRTC mode for pageflip" to allow smaller than mode planes. The problem I see is that with legacy pageflip we also need to hack up something that doesn't look at plane->state for legacy and all that for a grand total of about 2 drivers, both getting converted to atomic. I'll leave the legacy/atomic/etc considerations to the experts. :) Regards, Tvrtko ___
Re: [Intel-gfx] [PATCH] drm/i915: 4K audio N value incorrect at 29.97 and 23.98 refresh rate
On Thu, 08 Oct 2015, clinton.a.tay...@intel.com wrote: > From: Clint Taylor> > The TMDS_296M define was computing as 296704 but the mode->clock is > 296700 as defined by EDID. Adjusted define to allow correct detection > of the need to program the correct N value for 29.97 and 23.98 refresh > rate. > > Signed-off-by: Clint Taylor > --- > drivers/gpu/drm/i915/intel_audio.c |2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/intel_audio.c > b/drivers/gpu/drm/i915/intel_audio.c > index 56c2f54..419c979 100644 > --- a/drivers/gpu/drm/i915/intel_audio.c > +++ b/drivers/gpu/drm/i915/intel_audio.c > @@ -75,7 +75,7 @@ static const struct { > > /* HDMI N/CTS table */ > #define TMDS_297M 297000 > -#define TMDS_296M DIV_ROUND_UP(297000 * 1000, 1001) > +#define TMDS_296M 296700 > static const struct { > int sample_rate; > int clock; > -- > 1.7.9.5 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/4] drm/i915: Unify execlist and legacy request life-cycles
On Tue, Oct 06, 2015 at 03:52:01PM +0100, Nick Hoath wrote: > There is a desire to simplify the i915 driver by reducing the number of > different code paths introduced by the LRC / execlists support. As the > execlists request is now part of the gem request it is possible and > desirable to unify the request life-cycles for execlist and legacy > requests. > > Added a context complete flag to a request which gets set during the > context switch interrupt. Wrong approach. Legacy uses the request itself as the indicator for when the context is complete, if you were to take the same approach for LRC we would not need to add yet more execlist specific state. Lines of code is reduced by keeping the GEM semantics the same and just having execlists hold an indepedent ref on the request for its async submission approach. > Added a function i915_gem_request_retireable(). A request is considered > retireable if its seqno passed (i.e. the request has completed) and either > it was never submitted to the ELSP or its context completed. This ensures > that context save is carried out before the last request for a context is > considered retireable. retire_requests_ring() now uses > i915_gem_request_retireable() rather than request_complete() when deciding > which requests to retire. Requests that were not waiting for a context > switch interrupt (either as a result of being merged into a following > request or by being a legacy request) will be considered retireable as > soon as their seqno has passed. > > Removed the extra request reference held for the execlist request. > > Removed intel_execlists_retire_requests() and all references to > intel_engine_cs.execlist_retired_req_list. > > Moved context unpinning into retire_requests_ring() for now. Further work > is pending for the context pinning - this patch should allow us to use the > active list to track context and ring buffer objects later. > > Changed gen8_cs_irq_handler() so that notify_ring() is called when > contexts complete as well as when a user interrupt occurs so that > notification happens when a request is complete and context save has > finished. > > v2: Rebase over the read-read optimisation changes > > v3: Reworked IRQ handler after removing IRQ handler cleanup patch > > v4: Fixed various pin leaks > > Issue: VIZ-4277 > Signed-off-by: Thomas Daniel> Signed-off-by: Nick Hoath > --- > drivers/gpu/drm/i915/i915_drv.h | 6 +++ > drivers/gpu/drm/i915/i915_gem.c | 67 +-- > drivers/gpu/drm/i915/i915_irq.c | 81 > + > drivers/gpu/drm/i915/intel_lrc.c| 43 +++-- > drivers/gpu/drm/i915/intel_lrc.h| 2 +- > drivers/gpu/drm/i915/intel_ringbuffer.h | 1 - > 6 files changed, 118 insertions(+), 82 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index fbf0ae9..3d217f9 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -2262,6 +2262,12 @@ struct drm_i915_gem_request { > /** Execlists no. of times this request has been sent to the ELSP */ > int elsp_submitted; > > + /** > + * Execlists: whether this requests's context has completed after > + * submission to the ELSP > + */ > + bool ctx_complete; > + > }; > > int i915_gem_request_alloc(struct intel_engine_cs *ring, > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index 52642af..fc82171 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -1386,6 +1386,24 @@ __i915_gem_request_retire__upto(struct > drm_i915_gem_request *req) > typeof(*tmp), list); > > i915_gem_request_retire(tmp); > + > + if (i915.enable_execlists) { > + struct intel_context *ctx = tmp->ctx; > + struct drm_i915_private *dev_priv = > + engine->dev->dev_private; > + unsigned long flags; > + struct drm_i915_gem_object *ctx_obj = > + ctx->engine[engine->id].state; > + > + spin_lock_irqsave(>execlist_lock, flags); > + > + if (ctx_obj && (ctx != engine->default_context)) > + intel_lr_context_unpin(tmp); > + > + intel_runtime_pm_put(dev_priv); > + spin_unlock_irqrestore(>execlist_lock, flags); > + } Why here? Surely you intended this to be called by i915_gem_request_retire(). The runtime pm interaction is wrong, that is handled by GPU busyness tracking. But by doing this at this juncture you now increase the frequency at which we have to recreate the iomapping, most noticeable on bsw+ and take more spinlocks unnecessarily. Also since you no longer do
Re: [Intel-gfx] [PATCH 3/6] drm/i915: Propagating correct error codes to the userspace
Hi, On 08/10/15 07:24, ankitprasad.r.sha...@intel.com wrote: From: Ankitprasad SharmaPropagating correct error codes to userspace by using ERR_PTR and PTR_ERR macros for stolen memory based object allocation. We generally return -ENOMEM to the user whenever there is a failure in object allocation. This patch helps user to identify the correct reason for the failure and not just -ENOMEM each time. v2: Moved the patch up in the series, added error propagation for i915_gem_alloc_object too (Chris) Signed-off-by: Ankitprasad Sharma --- drivers/gpu/drm/i915/i915_gem.c | 15 +- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 4 +-- drivers/gpu/drm/i915/i915_gem_context.c | 4 +-- drivers/gpu/drm/i915/i915_gem_render_state.c | 4 +-- drivers/gpu/drm/i915/i915_gem_stolen.c | 43 drivers/gpu/drm/i915/i915_guc_submission.c | 4 +-- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_fbdev.c | 6 ++-- drivers/gpu/drm/i915/intel_lrc.c | 8 +++--- drivers/gpu/drm/i915/intel_overlay.c | 4 +-- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++--- 12 files changed, 61 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d3f4321..54f7df1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -393,9 +393,9 @@ i915_gem_create(struct drm_file *file, if (flags & I915_CREATE_PLACEMENT_STOLEN) { mutex_lock(>struct_mutex); obj = i915_gem_object_create_stolen(dev, size); - if (!obj) { + if (IS_ERR(obj)) { mutex_unlock(>struct_mutex); - return -ENOMEM; + return PTR_ERR(obj); } /* Always clear fresh buffers before handing to userspace */ @@ -411,8 +411,8 @@ i915_gem_create(struct drm_file *file, obj = i915_gem_alloc_object(dev, size); } - if (obj == NULL) - return -ENOMEM; + if (IS_ERR(obj)) + return PTR_ERR(obj); > ret = drm_gem_handle_create(file, >base, ); /* drop reference from allocate - handle holds it now */ @@ -4273,14 +4273,15 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, struct drm_i915_gem_object *obj; struct address_space *mapping; gfp_t mask; + int ret = 0; obj = i915_gem_object_alloc(dev); if (obj == NULL) - return NULL; + return ERR_PTR(-ENOMEM); - if (drm_gem_object_init(dev, >base, size) != 0) { + if ((ret = drm_gem_object_init(dev, >base, size)) != 0) { i915_gem_object_free(obj); - return NULL; + return ERR_PTR(ret); } mask = GFP_HIGHUSER | __GFP_RECLAIMABLE; diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index 7bf2f3f..d79caa2 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -135,8 +135,8 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, int ret; obj = i915_gem_alloc_object(pool->dev, size); - if (obj == NULL) - return ERR_PTR(-ENOMEM); + if (IS_ERR(obj)) + return obj; ret = i915_gem_object_get_pages(obj); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 74aa0c9..603600c 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -157,8 +157,8 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) int ret; obj = i915_gem_alloc_object(dev, size); - if (obj == NULL) - return ERR_PTR(-ENOMEM); + if (IS_ERR(obj)) + return obj; /* * Try to make the context utilize L3 as well as LLC. diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 5026a62..50d010e 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -58,8 +58,8 @@ static int render_state_init(struct render_state *so, struct drm_device *dev) return -EINVAL; so->obj = i915_gem_alloc_object(dev, 4096); - if (so->obj == NULL) - return -ENOMEM; + if (IS_ERR(so->obj)) + return PTR_ERR(so->obj); ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c
Re: [Intel-gfx] [PATCH 4/6] drm/i915: Add support for stealing purgable stolen pages
Hi, On 08/10/15 07:24, ankitprasad.r.sha...@intel.com wrote: From: Chris Wilson If we run out of stolen memory when trying to allocate an object, see if we can reap enough purgeable objects to free up enough contiguous free space for the allocation. This is in principle very much like evicting objects to free up enough contiguous space in the vma when binding a new object - and you will be forgiven for thinking that the code looks very similar. At the moment, we do not allow userspace to allocate objects in stolen, so there is neither the memory pressure to trigger stolen eviction nor any purgeable objects inside the stolen arena. However, this will change in the near future, and so better management and defragmentation of stolen memory will become a real issue. v2: Remember to remove the drm_mm_node. v3: Rebased to the latest drm-intel-nightly (Ankit) v4: corrected if-else braces format (Tvrtko/kerneldoc) v5: Rebased to the latest drm-intel-nightly (Ankit) Added a seperate list to maintain purgable objects from stolen memory region (Chris/Daniel) v6: Compiler optimization (merging 2 single loops into one for() loop), corrected code for object eviction, retire_requests before starting object eviction (Chris) v7: Added kernel doc for i915_gem_object_create_stolen() Testcase: igt/gem_stolen Signed-off-by: Chris Wilson Signed-off-by: Ankitprasad Sharma--- drivers/gpu/drm/i915/i915_debugfs.c| 4 +- drivers/gpu/drm/i915/i915_drv.h| 17 +++- drivers/gpu/drm/i915/i915_gem.c| 16 drivers/gpu/drm/i915/i915_gem_stolen.c | 169 + drivers/gpu/drm/i915/intel_pm.c| 4 +- 5 files changed, 186 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8797717..13762c1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -174,7 +174,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) seq_puts(m, ")"); } if (obj->stolen) - seq_printf(m, " (stolen: %08llx)", obj->stolen->start); + seq_printf(m, " (stolen: %08llx)", obj->stolen->base.start); if (obj->pin_display || obj->fault_mappable) { char s[3], *t = s; if (obj->pin_display) @@ -253,7 +253,7 @@ static int obj_rank_by_stolen(void *priv, struct drm_i915_gem_object *b = container_of(B, struct drm_i915_gem_object, obj_exec_link); - return a->stolen->start - b->stolen->start; + return a->stolen->base.start - b->stolen->base.start; } static int i915_gem_stolen_list_info(struct seq_file *m, void *data) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bca1572..5612df3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -850,6 +850,12 @@ struct i915_ctx_hang_stats { bool banned; }; +struct i915_stolen_node { + struct drm_mm_node base; + struct list_head mm_link; + struct drm_i915_gem_object *obj; +}; + /* This must match up with the value previously used for execbuf2.rsvd1. */ #define DEFAULT_CONTEXT_HANDLE 0 @@ -1279,6 +1285,13 @@ struct i915_gem_mm { */ struct list_head unbound_list; + /** +* List of stolen objects that have been marked as purgeable and +* thus available for reaping if we need more space for a new +* allocation. Ordered by time of marking purgeable. +*/ + struct list_head stolen_list; + /** Usable portion of the GTT for GEM */ unsigned long stolen_base; /* limited to low memory (32-bit) */ @@ -2047,7 +2060,7 @@ struct drm_i915_gem_object { struct list_head vma_list; /** Stolen memory for this object, instead of being backed by shmem. */ - struct drm_mm_node *stolen; + struct i915_stolen_node *stolen; struct list_head global_list; struct list_head ring_list[I915_NUM_RINGS]; @@ -2055,6 +2068,7 @@ struct drm_i915_gem_object { struct list_head obj_exec_link; struct list_head batch_pool_link; + struct list_head tmp_link; /** * This is set if the object is on the active lists (has pending @@ -2171,6 +2185,7 @@ struct drm_i915_gem_object { }; }; #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base) +#define I915_BO_IS_ACTIVE(__obj) (__obj->active) void i915_gem_track_fb(struct drm_i915_gem_object *old, struct drm_i915_gem_object *new, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 54f7df1..91a2e97 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4233,6 +4233,20 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, if (obj->madv == I915_MADV_DONTNEED &&
Re: [Intel-gfx] [v2] drm/i915/skl: Init cdclk in the driver rather than relying on pre-os
On 10/08/2015 04:59 PM, Imre Deak wrote: On to, 2015-10-08 at 09:58 +0530, Shobhit Kumar wrote: Reuse what is programmed by pre-os, but in case there is no pre-os initialization, init the cdclk with the max value by default untill dynamic cdclk support comes. v2: Check if BIOS programmed correctly rather than always calling init - Do validation of programmed cdctl and what it is expected - Only do slk_init_cdclk if validation failed else reuse BIOS programmed value Cc: Imre DeakCc: Ville Syrjälä Signed-off-by: Shobhit Kumar --- drivers/gpu/drm/i915/intel_ddi.c | 18 - drivers/gpu/drm/i915/intel_display.c | 39 +++- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 2d3cc82..3ec5618 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2946,11 +2946,19 @@ void intel_ddi_pll_init(struct drm_device *dev) int cdclk_freq; cdclk_freq = dev_priv->display.get_display_clock_speed(dev); - dev_priv->skl_boot_cdclk = cdclk_freq; - if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) - DRM_ERROR("LCPLL1 is disabled\n"); - else - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + + /* Invalid CDCLK from BIOS ? */ + if (cdclk_freq < 0) { + /* program to maximum cdclk till we have dynamic cdclk support */ + dev_priv->skl_boot_cdclk = 675000; + skl_init_cdclk(dev_priv); This would still try to reprogram CDCLK if BIOS enabled an output with an incorrect CDCLK decimal part. Isn't this the exact scenario you're seeing? As said before reprogramming CDCLK in that case would require disabling the outputs first. I went with the hypothesis that if VBIOS/GOP was loaded it would have to correct the cdclock, with wrong decimal value display cannot be enabled. For example AUX will fail on SKL. So for correct display output enabled cdclock has to be correctly programmed. If it is wrong display was not enabled at all. The scenario which I am seeing is VBIOS/GOP is not loaded at all, and the pre-os is not leaving cdclock in correct state. We would also need to call skl_init_cdclk if the BIOS hasn't enabled the PLL for some reason. But I guess that could be a separate change. + } else { + dev_priv->skl_boot_cdclk = cdclk_freq; + if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) + DRM_ERROR("LCPLL1 is disabled\n"); + else + intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + } } else if (IS_BROXTON(dev)) { broxton_init_cdclk(dev); broxton_ddi_phy_init(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bbeb6d3..f734410 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6634,12 +6634,15 @@ static int skylake_get_display_clock_speed(struct drm_device *dev) uint32_t lcpll1 = I915_READ(LCPLL1_CTL); uint32_t cdctl = I915_READ(CDCLK_CTL); uint32_t linkrate; + int freq; if (!(lcpll1 & LCPLL_PLL_ENABLE)) return 24000; /* 24MHz is the cd freq with NSSC ref */ - if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) - return 54; + if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) { + freq = 54; + goto verify; + } linkrate = (I915_READ(DPLL_CTRL1) & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; @@ -6649,30 +6652,46 @@ static int skylake_get_display_clock_speed(struct drm_device *dev) /* vco 8640 */ switch (cdctl & CDCLK_FREQ_SEL_MASK) { case CDCLK_FREQ_450_432: - return 432000; + freq = 432000; + break; case CDCLK_FREQ_337_308: - return 308570; + freq = 308570; + break; case CDCLK_FREQ_675_617: - return 617140; + freq = 617140; + break; default: WARN(1, "Unknown cd freq selection\n"); + return -EINVAL; } } else { /* vco 8100 */ switch (cdctl & CDCLK_FREQ_SEL_MASK) { case CDCLK_FREQ_450_432: - return 45; + freq = 45; + break;
Re: [Intel-gfx] [PATCH 2/5] drm/i915: Notify user about outdated dmc firmware
Animesh Mannawrites: > On 9/21/2015 2:00 PM, Mika Kuoppala wrote: >> Jani Nikula writes: >> >>> On Fri, 18 Sep 2015, Mika Kuoppala wrote: If csr/dmc firmware is known to be outdated, notify user. >>> What would break if we requested a firmware version that works? Or we've >>> made it so that we only request the major version because there's not >>> supposed to be changes like this between minor versions...? >>> >> I guess the question is more of a what should we do >> if there is only outdated (known bad) firmware available. >> >> Refuse to load and limb onwards, or return with error code >> on driver init. >> >> Latter would force firmware and version to be mandatory and the >> version to be tightly coupled to kernel driver version. > > A softlink is used to use recommended firmware for dmc and the same > information is published through 01.org for the firmware user. > Imo, we should not have this kind of hack in code which will change over time > and this is responsibility of repo-owner to link correct recommended firmware > for new kernel update. > On machines that had 1.19 symlinked, in filesystem, execlist submission sometimes broke due to interrupt delivery problem. To reach a conclusion that it was csr firmware, before 1.21 was out, took quite amount of work. I bet there are still machines with 1.19 only, and we get to wade through error states trying to connect the dots. The dmc/csr firmware is part of our driver functionality. Apparently it is very tightly coupled to our driver functionality as it can break things outside of its own domain. And currently it is loosely coupled black box with our driver, through symlink, accepting any version that happens to be in customers filesystem. So we recommend latest in website and end up in a situation that user gets what happens to be in filesystem. Even a known broken version? And we will keep debugging these problems caused by broken version? I don't want any more dimensions in our triaging space, the distributio/firmware version dimension. Symlink also means that bisectability is very close to worthless on these kind of bugs. Both in our machines and also on customers. We have loosely coupled, black box entity, affecting our driver depending on customers filesystem. Symlink threw that valuable tool out, and we gained what? So we are left with triaging. Which is true detective work as there are no traces of firmware versions nor loading success/fails on logs/error states. From where I look at, the version blacklist is not a hack. It is a cure. -Mika > -Animesh > >> -Mika >> >>> BR, >>> Jani. >>> >>> >>> Signed-off-by: Mika Kuoppala --- drivers/gpu/drm/i915/intel_csr.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 58edc3f..73807c3 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -45,6 +45,9 @@ MODULE_FIRMWARE(I915_CSR_SKL); +#define RECOMMENDED_FW_MAJOR 1 +#define RECOMMENDED_FW_MINOR 21 + /* * SKL CSR registers for DC5 and DC6 */ @@ -387,6 +390,12 @@ static void finish_csr_load(const struct firmware *fw, void *context) DRM_DEBUG_KMS("Finished loading %s v%u.%u\n", dev_priv->csr.fw_path, csr->dmc_ver_major, csr->dmc_ver_minor); + + if (csr->dmc_ver_major < RECOMMENDED_FW_MAJOR || + csr->dmc_ver_minor < RECOMMENDED_FW_MINOR) + DRM_INFO("Outdated dmc firmware found, please upgrade to %u.%u or newer\n", + RECOMMENDED_FW_MAJOR, RECOMMENDED_FW_MINOR); + out: if (fw_loaded) intel_runtime_pm_put(dev_priv); -- 2.1.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx >>> -- >>> Jani Nikula, Intel Open Source Technology Center >> ___ >> Intel-gfx mailing list >> Intel-gfx@lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Convert WARNs during userptr revoke to SIGBUS
On 28/09/15 15:14, Daniel Vetter wrote: On Mon, Sep 28, 2015 at 02:52:30PM +0100, Chris Wilson wrote: On Mon, Sep 28, 2015 at 03:42:22PM +0200, Daniel Vetter wrote: On Wed, Sep 23, 2015 at 09:07:24PM +0100, Chris Wilson wrote: If the client revokes the virtual address it asked to be mapped into GPU space via userptr (by using anything along the lines of mmap, mprotect, madvise, munmap, ftruncate etc) the mmu notifier sends a range invalidate command to userptr. Upon receiving the invalidation signal for the revoked range, we try to release the struct pages we pinned into the GTT. However, this can fail if any of the GPU's VMA are pinned for use by the hardware (i.e. despite the user's intention we cannot relinquish the client's address range and keep uptodate with whatever is placed in there). Currently we emit a few WARN so that we would notice if this every occurred in the wild; it has. Sadly this means we need to replace those WARNs with the proper SIGBUS to the offending clients instead. Signed-off-by: Chris WilsonCc: Tvrtko Ursulin Cc: Michał Winiarski --- drivers/gpu/drm/i915/i915_gem_userptr.c | 41 + 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index f75d9011..efb404b9fe69 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -81,11 +81,44 @@ static void __cancel_userptr__worker(struct work_struct *work) was_interruptible = dev_priv->mm.interruptible; dev_priv->mm.interruptible = false; - list_for_each_entry_safe(vma, tmp, >vma_list, obj_link) { - int ret = i915_vma_unbind(vma); - WARN_ON(ret && ret != -EIO); + list_for_each_entry_safe(vma, tmp, >vma_list, obj_link) + i915_vma_unbind(vma); + if (i915_gem_object_put_pages(obj)) { + struct task_struct *p; + + DRM_ERROR("Unable to revoke ownership by userptr of" + " invalidated address range, sending SIGBUS" + " to attached clients.\n"); + + rcu_read_lock(); + for_each_process(p) { + siginfo_t info; + + /* This doesn't capture everyone who has +* the pages pinned behind a VMA as we +* do not have that tracking information +* available, it does however kill the +* original process (and siblings) who +* created the userptr and presumably tried +* to reuse the address space despite having +* pinned it (possibly indirectly) to the hw. +* Arguably, we don't even want to kill the +* other processes as they are not at fault, +* likely to be a display server, and hopefully +* will release the pages in due course once +* the client is dead. +*/ + if (p->mm != obj->userptr.mm->mm) + continue; + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void __user *)obj->userptr.ptr; + force_sig_info(SIGBUS, , p); + } + rcu_read_unlock(); Why do we need to send a SIGBUS? It won't tear down the offending gem bo, any new users will hopefully get it, and abusing SIGBUS without the thread actually doing a memory access is a bit surprising. DRM_DEBUG seems to be the most we can do here I think - I think userspace being able to do this is just a fundamental property of userptr. It is not the bo that is at fault but the *client's* *address* *space* that is being changed. It is equivalent to mmap on a truncated file i.e. if the client tries to use its mmapping after it has truncated the file it is scolded via SIGBUS. But existing SIGBUS is thread-bound and comes with the fault address attached. This is just the gpu being a bit unhappy, so the SIGBUS comes out of complete nowhere to smack the userspace thread. Any kind of SIGBUS catcher userspace has for other reasons might be supremely surprised by this and do stupid things. Hence I don't think throwing SIGBUS here is correct behaviour. And there doesn't seem to be anything else suitable
Re: [Intel-gfx] [PATCH 2/2] drm/i915: Drop i915_gem_obj_is_pinned() from set-cache-level
On Thu, Oct 08, 2015 at 10:32:39AM +0100, Tvrtko Ursulin wrote: > > On 07/10/15 17:19, Chris Wilson wrote: > >On Wed, Oct 07, 2015 at 04:57:25PM +0100, Tvrtko Ursulin wrote: > >> > >>Hi, > >> > >>On 06/10/15 11:39, Chris Wilson wrote: > >>>Since the remove of the pin-ioctl, we only care about not changing the > >>>cache level on buffers pinned to the hardware as indicated by > >>>obj->pin_display. So we can safely replace i915_gem_object_is_pinned() > > [snip] > > >>>diff --git a/drivers/gpu/drm/i915/i915_gem.c > >>>b/drivers/gpu/drm/i915/i915_gem.c > >>>index d4a3bdf0c5b6..2b8ed7a2faab 100644 > >>>--- a/drivers/gpu/drm/i915/i915_gem.c > >>>+++ b/drivers/gpu/drm/i915/i915_gem.c > >>>@@ -3629,31 +3629,34 @@ int i915_gem_object_set_cache_level(struct > >>>drm_i915_gem_object *obj, > >>> { > >>> struct drm_device *dev = obj->base.dev; > >>> struct i915_vma *vma, *next; > >>>+ bool bound = false; > >>> int ret = 0; > >>> > >>> if (obj->cache_level == cache_level) > >>> goto out; > >>> > >>>- if (i915_gem_obj_is_pinned(obj)) { > >>>- DRM_DEBUG("can not change the cache level of pinned objects\n"); > >>>- return -EBUSY; > >>>- } > >>>- > >>> list_for_each_entry_safe(vma, next, >vma_list, vma_link) { > >>>+ if (!drm_mm_node_allocated(>node)) > >>>+ continue; > >>>+ > >>>+ if (vma->pin_count) { > >>>+ DRM_DEBUG("can not change the cache level of pinned > >>>objects\n"); > >>>+ return -EBUSY; > >>>+ } > >>>+ > >> > >>But this is the same as i915_gem_obj_is_pinned, where is the > >>obj->pin_display change commit message talks about? > > > >Right here. The difference is that we are only iterating the vma list > >once rather than 3x. > > Thats true, but the commit says it is going to use obj->pin_display > for something and then doesn't use it at all. Riddles in patches are > not that hot. :) I was trying to explain what the actual rules pertaining to the rebinding the vma was. We can rebind anything that isn't pinned and the only thing pinned here can be obj->pin_display. > >>> if (!i915_gem_valid_gtt_space(vma, cache_level)) { > >>> ret = i915_vma_unbind(vma); > >>> if (ret) > >>> return ret; > >>>- } > >>>+ } else > >>>+ bound = true; > >>> } > >>> > >>>- if (i915_gem_obj_bound_any(obj)) { > >>>+ if (bound) { > >>> ret = i915_gem_object_wait_rendering(obj, false); > >>> if (ret) > >>> return ret; > >>> > >>>- i915_gem_object_finish_gtt(obj); > >>>- > >>> /* Before SandyBridge, you could not use tiling or fence > >>>* registers with snooped memory, so relinquish any fences > >>>* currently pointing to our region in the aperture. > >>>@@ -3664,13 +3667,18 @@ int i915_gem_object_set_cache_level(struct > >>>drm_i915_gem_object *obj, > >>> return ret; > >>> } > >>> > >>>- list_for_each_entry(vma, >vma_list, vma_link) > >>>- if (drm_mm_node_allocated(>node)) { > >>>- ret = i915_vma_bind(vma, cache_level, > >>>- PIN_UPDATE); > >>>- if (ret) > >>>- return ret; > >>>- } > >>>+ /* Access to snoopable pages through the GTT is incoherent. */ > >>>+ if (cache_level != I915_CACHE_NONE && !HAS_LLC(dev)) > >>>+ i915_gem_release_mmap(obj); > >> > >>Don't fully understand this one - but my question is this. > >>Previously userspace would lose mappings on cache level changes any > >>time, after this only on !LLC when turning on caching mode. So this > >>means userspace needs to know about this change and modify it's > >>behavior? Or what exactly would happen in practice? > > > >No. Userspace has no knowledge of the kernel handling the PTEs, its > >mapping is persistent (i.e. the obj->mmap_offset inside the dev->mappping). > >Otoh, we are improving the situation so even if userspace tries to avoid > >set-cache-level nothing is lost. > > Hm so if a VMA is re-bound in this process and it could have gotten > a new GGTT address, why it is not necessary to always release mmaps > and so to update CPU PTEs? The VMA are not moved by this function, only the PTEs are rewritten. The GTT ignores the bits we are changing on llc architectures. On !llc using the GTT to access snoopable PTE is verboten and does cause machine hangs. > Also what about Sandy Bridge? Commit message mentions it and the > code doesn't? Age of patch and lack of !llc snb+ at the time, and the state of my mind when I think about llc. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org
Re: [Intel-gfx] [PATCH 5/5] drm/i915: Add dmc firmware debugfs status entry
On 9/18/2015 8:47 PM, Mika Kuoppala wrote: Add debugfs entry for csr/dmc fw to inspect firmware loading status and version. Signed-off-by: Mika Kuoppala--- drivers/gpu/drm/i915/i915_debugfs.c | 32 drivers/gpu/drm/i915/i915_reg.h | 5 + drivers/gpu/drm/i915/intel_csr.c| 3 --- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 72ae347..4a798a6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2509,6 +2509,37 @@ static int i915_guc_log_dump(struct seq_file *m, void *data) return 0; } +static int i915_dmc_load_status_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_i915_private *dev_priv = node->minor->dev->dev_private; + struct intel_csr *csr = _priv->csr; + uint32_t state; + const char * const state_str[] = { "uninitialized", + "loaded", + "failed", + "unknown" }; + + seq_puts(m, "DMC firmware status:\n"); + + mutex_lock(_priv->csr_lock); DMC-redesign series is floated for review where csr_lock is removed completely, not sure do we need mutex lock here. + + seq_printf(m, "\tpath: %s\n", csr->fw_path); + seq_printf(m, "\tfw_ver: %u.%u\n", csr->dmc_ver_major, + csr->dmc_ver_minor); + seq_printf(m, "\tsize: %u bytes\n", csr->dmc_fw_size * 4); + state = (uint32_t)csr->state <= 3 ? csr->state : 3; + seq_printf(m, "\tstate: %s\n", state_str[state]); + + seq_printf(m, "\tprogram base: 0x%08x\n", I915_READ(CSR_PROGRAM_BASE)); + seq_printf(m, "\tssp base: 0x%08x\n", I915_READ(CSR_SSP_BASE)); + seq_printf(m, "\thtp: 0x%08x\n", I915_READ(CSR_HTP_SKL)); Better print dmc firmware loading related info if firmware is loaded successfully. In failure case, only firmware not loaded msg with path I feel is sufficient. -Animesh + + mutex_unlock(_priv->csr_lock); + + return 0; +} + static int i915_edp_psr_status(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; @@ -5173,6 +5204,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_guc_info", i915_guc_info, 0}, {"i915_guc_load_status", i915_guc_load_status_info, 0}, {"i915_guc_log_dump", i915_guc_log_dump, 0}, + {"i915_dmc_load_status", i915_dmc_load_status_info, 0}, {"i915_frequency_info", i915_frequency_info, 0}, {"i915_hangcheck_info", i915_hangcheck_info, 0}, {"i915_drpc_info", i915_drpc_info, 0}, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 67bf205..cd040ff 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7977,4 +7977,9 @@ enum skl_disp_power_wells { #define GEN9_VEBOX_MOCS_0 0xcb00 /* Video MOCS base register*/ #define GEN9_BLT_MOCS_0 0xcc00 /* Blitter MOCS base register*/ +/* DMC/CSR firmware */ +#define CSR_PROGRAM_BASE 0x8 +#define CSR_SSP_BASE 0x8F074 +#define CSR_HTP_SKL0x8F004 + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 73807c3..876c839 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -51,11 +51,8 @@ MODULE_FIRMWARE(I915_CSR_SKL); /* * SKL CSR registers for DC5 and DC6 */ -#define CSR_PROGRAM_BASE 0x8 #define CSR_SSP_BASE_ADDR_GEN90x2FC0 #define CSR_HTP_ADDR_SKL 0x00500034 -#define CSR_SSP_BASE 0x8F074 -#define CSR_HTP_SKL0x8F004 #define CSR_LAST_WRITE0x8F034 #define CSR_LAST_WRITE_VALUE 0xc003b400 /* MMIO address range for CSR program (0x8 - 0x82FFF) */ ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/9] drm/i915: driver based PASID handling
On 07/10/2015 17:14, Daniel Vetter wrote: On Wed, Oct 07, 2015 at 08:16:42AM -0700, Jesse Barnes wrote: On 10/07/2015 06:00 AM, David Woodhouse wrote: On Fri, 2015-09-04 at 09:59 -0700, Jesse Barnes wrote: + + ret = handle_mm_fault(mm, vma, address, + desc.wr_req ? FAULT_FLAG_WRITE : 0); + if (ret & VM_FAULT_ERROR) { + gpu_mm_segv(tsk, address, SEGV_ACCERR); /* ? */ + goto out_unlock; + } + Hm, do you need to force the SEGV there, in what ought to be generic IOMMU code? Can you instead just let the fault handler return an appropriate failure code to the IOMMU request queue and then deal with the resulting error on the i915 device side? I'm not sure if we get enough info on the i915 side to handle it reasonably, we'll have to test that out. We do know precisely which context blew up, but without the TDR work we can't yet just kill the offender selective without affecting the other active gpu contexts. Could someone clarify what this means from the TDR point of view, please? When you say "context blew up" I'm guessing that you mean that come context caused the fault handler to get involved somehow? Does this imply that the offending context will hang and the driver will have to detect this hang? If so, then yes - if we have the per-engine hang recovery mode as part of the upcoming TDR work in place then we could handle it by stepping over the offending batch buffer and moving on with a minimum of side-effects on the rest of the driver/GPU. Or does this imply that we have some new integration path to deal with? (something that I should be aware of when upstreaming TDR?) Sorry if I missed something blatantly obvious in the patch ;). Thanks, Tomas But besides that I really don't see a reason why we need to kill the process if the gpu faults. After all if a thread sigfaults then signal goes to that thread and not some random one (or the one thread that forked the thread that blew up). And we do have interfaces to tell userspace that something bad happened with the gpu work it submitted. Chris made a similar patch for userptr and I didn't like that one either. Worst case userspace has a special SEGV handler and then things really go down badly when that handler gets triggered at an unexpected place. -Daniel That way, you should hopefully get to gracefully cope with reporting errors for a specific *context*, rather than killing the whole process. It would be best to get per-context error info, but killing the process may be unavoidable (just as if a single thread clobbers memory in your process). Jesse ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 9/9] drm/i915: add bufferless execbuf ioctl
On Fri, 2015-09-04 at 09:59 -0700, Jesse Barnes wrote: > We just need to pass in an address to execute and some flags, since we > don't have to worry about buffer relocation or any of the other usual > stuff. Returns a fence to be used for synchronization. > --- > drivers/gpu/drm/i915/i915_dma.c| 140 > - > drivers/gpu/drm/i915/i915_drv.h| 7 ++ > drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- > drivers/gpu/drm/i915/i915_svm.c| 10 --- > drivers/gpu/drm/i915/i915_sync.c | 4 +- > include/uapi/drm/i915_drm.h| 24 + > 6 files changed, 173 insertions(+), 14 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c > index b868084..19b463a 100644 > --- a/drivers/gpu/drm/i915/i915_dma.c > +++ b/drivers/gpu/drm/i915/i915_dma.c > @@ -50,7 +50,8 @@ > #include > #include > #include > - > +#include > +#include "../../../staging/android/sync.h" > > static int i915_getparam(struct drm_device *dev, void *data, > >> > > struct drm_file *file_priv) > @@ -1247,6 +1248,132 @@ i915_gem_reject_pin_ioctl(struct drm_device *dev, > void *data, > >> return -ENODEV; > } > > +int intel_exec_mm_ioctl(struct drm_device *dev, void *data, > +>> > > struct drm_file *file) > +{ > + > > struct drm_i915_private *dev_priv = dev->dev_private; > +>> struct drm_i915_exec_mm *exec_mm = data; > +>> struct intel_ringbuffer *ringbuf; > +>> struct intel_engine_cs *ring; > +>> struct intel_context *ctx; > +>> struct drm_i915_gem_request *request; > +>> struct fence *fence; > +>> struct sync_fence *sfence; > +>> u32 ctx_id = exec_mm->ctx_id; > +>> int fd = get_unused_fd_flags(O_CLOEXEC); > +>> int ret = 0; > + > +>> if (exec_mm->batch_ptr & 3) { > +>> > DRM_ERROR("misaligned batch ptr\n"); > +>> > ret = -ENOEXEC; > +>> > goto out; > +>> } > + > +>> if (!dev_priv->svm.svm_available) { > +>> > ret = -ENODEV; > +>> > goto out; > +>> } > + > +>> ret = i915_mutex_lock_interruptible(dev); > +>> if (ret) { > +>> > DRM_ERROR("mutex interrupted\n"); > +>> > goto out; > +>> } > + > +>> if (file == NULL) { > +>> > ret = -EINVAL; > +>> > goto out_unlock; > +>> } > + > +>> ctx = i915_gem_validate_context(dev, file, _priv->ring[RCS], > +>> > > > > ctx_id); > +>> if (ctx == NULL) { > +>> > ret = -ENOENT; > +>> > DRM_ERROR("couldn't get context\n"); > +>> > goto out_unlock; > +>> } > + > +>> if (!ctx->is_svm) { > +>> > ret = -EINVAL; > +>> > DRM_ERROR("context is not SVM enabled\n"); > +>> > goto out_unlock; > +>> } > + > +>> i915_gem_context_reference(ctx); > + > +>> ringbuf = ctx->engine[RCS].ringbuf; > +>> ring = ringbuf->ring; > +>> if (!ring) { > +>> > DRM_ERROR("context has no last ring\n"); > +>> > ret = -EIO; > +>> > goto out_unref; > +>> } > + > +>> if (!ctx->rcs_initialized) { > +>> > DRM_DEBUG("ring not ready\n"); > +>> > ret = -EIO; > +>> > goto out_unref; > +>> } > + > +>> ret = i915_gem_request_alloc(ring, ctx, ); > +>> if (ret) { > +>> > DRM_ERROR("request alloc failed\n"); > +>> > goto out_unref; > +>> } > + > +>> ret = i915_gem_request_add_to_client(request, file); > +>> if (ret) { > +>> > DRM_ERROR("failed to add request to client\n"); > +>> > goto out_free_req; > +>> } > + > +>> fence = i915_fence_create_ring(ring, ctx); > +>> if (!fence) { > +>> > ret = -ENOMEM; > +>> > DRM_ERROR("fence creation failed\n"); > +>> > goto out_free_req; > +>> } > + > +>> sfence = sync_fence_create_dma("svm-execbuf", fence); > +>> if (!sfence) { > +>> > ret = -ENOMEM; > +>> > DRM_ERROR("sfence creation failed\n"); > +>> > goto out_free_req; > +>> } > + > +>> exec_mm->fence = fd; > +>> sync_fence_install(sfence, fd); > + > +>> ret = ring->emit_flush(request, 0, I915_GEM_GPU_DOMAINS); > +>> if (ret) { > +>> > DRM_ERROR("ring flush failed: %d\n", ret); > +>> > goto out_free_req; > +>> } > + > +>> ret = ring->emit_bb_start(request, exec_mm->batch_ptr, 0); > +>> if (ret) { > +>> > DRM_ERROR("ring dispatch execbuf failed: %d\n", ret); > +>> > goto out_free_req; > +>> } FWIW naïvely adding a call to __i915_add_request(request, NULL, true); here in the hope that it would actually do something *useful* rather than just reserving space in the ring and never using it, causing the warning in intel_ring_reserved_space_reserve() that I observed next time we do anything... didn't work. With various and
Re: [Intel-gfx] [PATCH 3/6] drm/i915: Propagating correct error codes to the userspace
On Thu, Oct 08, 2015 at 11:54:26AM +0530, ankitprasad.r.sha...@intel.com wrote: > From: Ankitprasad Sharma> > Propagating correct error codes to userspace by using ERR_PTR and > PTR_ERR macros for stolen memory based object allocation. We generally > return -ENOMEM to the user whenever there is a failure in object > allocation. This patch helps user to identify the correct reason for the > failure and not just -ENOMEM each time. > > v2: Moved the patch up in the series, added error propagation for > i915_gem_alloc_object too (Chris) > > Signed-off-by: Ankitprasad Sharma > --- > drivers/gpu/drm/i915/i915_gem.c | 15 +- > drivers/gpu/drm/i915/i915_gem_batch_pool.c | 4 +-- > drivers/gpu/drm/i915/i915_gem_context.c | 4 +-- > drivers/gpu/drm/i915/i915_gem_render_state.c | 4 +-- > drivers/gpu/drm/i915/i915_gem_stolen.c | 43 > > drivers/gpu/drm/i915/i915_guc_submission.c | 4 +-- > drivers/gpu/drm/i915/intel_display.c | 2 +- > drivers/gpu/drm/i915/intel_fbdev.c | 6 ++-- > drivers/gpu/drm/i915/intel_lrc.c | 8 +++--- > drivers/gpu/drm/i915/intel_overlay.c | 4 +-- > drivers/gpu/drm/i915/intel_pm.c | 2 +- > drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++--- > 12 files changed, 61 insertions(+), 55 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index d3f4321..54f7df1 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -4273,14 +4273,15 @@ struct drm_i915_gem_object > *i915_gem_alloc_object(struct drm_device *dev, > struct drm_i915_gem_object *obj; > struct address_space *mapping; > gfp_t mask; > + int ret = 0; Pointless initialisation. > > obj = i915_gem_object_alloc(dev); > if (obj == NULL) > - return NULL; > + return ERR_PTR(-ENOMEM); > > - if (drm_gem_object_init(dev, >base, size) != 0) { > + if ((ret = drm_gem_object_init(dev, >base, size)) != 0) { > i915_gem_object_free(obj); > - return NULL; > + return ERR_PTR(ret); > } > > mask = GFP_HIGHUSER | __GFP_RECLAIMABLE; > diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c > b/drivers/gpu/drm/i915/i915_gem_batch_pool.c > index 7bf2f3f..d79caa2 100644 > --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c > +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c > @@ -135,8 +135,8 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, > int ret; > > obj = i915_gem_alloc_object(pool->dev, size); > - if (obj == NULL) > - return ERR_PTR(-ENOMEM); > + if (IS_ERR(obj)) > + return obj; > > ret = i915_gem_object_get_pages(obj); > if (ret) > diff --git a/drivers/gpu/drm/i915/i915_gem_context.c > b/drivers/gpu/drm/i915/i915_gem_context.c > index 74aa0c9..603600c 100644 > --- a/drivers/gpu/drm/i915/i915_gem_context.c > +++ b/drivers/gpu/drm/i915/i915_gem_context.c > @@ -157,8 +157,8 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t > size) > int ret; > > obj = i915_gem_alloc_object(dev, size); > - if (obj == NULL) > - return ERR_PTR(-ENOMEM); > + if (IS_ERR(obj)) > + return obj; > > /* >* Try to make the context utilize L3 as well as LLC. > diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c > b/drivers/gpu/drm/i915/i915_gem_render_state.c > index 5026a62..50d010e 100644 > --- a/drivers/gpu/drm/i915/i915_gem_render_state.c > +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c > @@ -58,8 +58,8 @@ static int render_state_init(struct render_state *so, > struct drm_device *dev) > return -EINVAL; > > so->obj = i915_gem_alloc_object(dev, 4096); > - if (so->obj == NULL) > - return -ENOMEM; > + if (IS_ERR(so->obj)) > + return PTR_ERR(so->obj); > > ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0); > if (ret) > diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c > b/drivers/gpu/drm/i915/i915_gem_stolen.c > index 5ec2190..d3e6813 100644 > --- a/drivers/gpu/drm/i915/i915_gem_stolen.c > +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c > @@ -406,6 +406,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, > struct drm_i915_private *dev_priv = dev->dev_private; > struct sg_table *st; > struct scatterlist *sg; > + int ret; > > DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size); > BUG_ON(offset > dev_priv->gtt.stolen_size - size); > @@ -417,11 +418,12 @@ i915_pages_create_for_stolen(struct drm_device *dev, > > st = kmalloc(sizeof(*st), GFP_KERNEL); > if (st == NULL) > - return NULL; > + return ERR_PTR(-ENOMEM); > > -
Re: [Intel-gfx] [PATCH 6/6] drm/i915: Migrate stolen objects before hibernation
On Thu, Oct 08, 2015 at 11:54:29AM +0530, ankitprasad.r.sha...@intel.com wrote: > + /* stolen objects are already pinned to prevent shrinkage */ > + memset(, 0, sizeof(node)); > + ret = drm_mm_insert_node_in_range_generic(>gtt.base.mm, > + , > + 4096, 0, I915_CACHE_NONE, > + 0, i915->gtt.mappable_end, > + DRM_MM_SEARCH_DEFAULT, > + DRM_MM_CREATE_DEFAULT); > + if (ret) > + return ret; > + > + i915->gtt.base.insert_entries(>gtt.base, obj->pages, > + node.start, I915_CACHE_NONE, 0); This was written using an insert_page() function you don't have. Either grab that as well, or you need to pin the entire object into the GGTT, i.e. i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE); note that to do so will also need to be very careful to handle the pinning of obj->pages and the introduction of a new GGTT vma. > + > + for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { > + struct page *page; > + void *__iomem src; > + void *dst; > + > + page = shmem_read_mapping_page(mapping, i); > + if (IS_ERR(page)) { > + ret = PTR_ERR(page); > + goto err_node; > + } > + > + src = io_mapping_map_atomic_wc(i915->gtt.mappable, node.start + > PAGE_SIZE * i); > + dst = kmap_atomic(page); > + memcpy_fromio(dst, src, PAGE_SIZE); > + kunmap_atomic(dst); > + io_mapping_unmap_atomic(src); > + > + page_cache_release(page); > + } > + > + wmb(); > + i915->gtt.base.clear_range(>gtt.base, > +node.start, node.size, > +true); > + drm_mm_remove_node(); > + > +swap_pages: > + stolen_pages = obj->pages; > + obj->pages = NULL; > + > + obj->base.filp = file; > + obj->base.read_domains = I915_GEM_DOMAIN_CPU; > + obj->base.write_domain = I915_GEM_DOMAIN_CPU; > + > + /* Recreate any pinned binding with pointers to the new storage */ > + if (!list_empty(>vma_list)) { > + ret = i915_gem_object_get_pages_gtt(obj); > + if (ret) { > + obj->pages = stolen_pages; > + goto err_file; > + } > + > + ret = i915_gem_gtt_prepare_object(obj); > + if (ret) { > + i915_gem_object_put_pages_gtt(obj); > + obj->pages = stolen_pages; > + goto err_file; > + } > + > + ret = i915_gem_object_set_to_gtt_domain(obj, true); > + if (ret) { > + i915_gem_gtt_finish_object(obj); > + i915_gem_object_put_pages_gtt(obj); > + obj->pages = stolen_pages; > + goto err_file; > + } > + > + obj->get_page.sg = obj->pages->sgl; > + obj->get_page.last = 0; > + > + list_for_each_entry(vma, >vma_list, vma_link) { > + if (!drm_mm_node_allocated(>node)) > + continue; > + > + WARN_ON(i915_vma_bind(vma, > + obj->cache_level, > + PIN_UPDATE)); > + } > + } else > + list_del(>global_list); > + > + /* drop the stolen pin and backing */ > + shmemfs_pages = obj->pages; > + obj->pages = stolen_pages; > + > + i915_gem_object_unpin_pages(obj); > + obj->ops->put_pages(obj); > + if (obj->ops->release) > + obj->ops->release(obj); > + > + obj->ops = _gem_object_ops; > + obj->pages = shmemfs_pages; > + > + return 0; > + > +err_node: > + wmb(); > + i915->gtt.base.clear_range(>gtt.base, > +node.start, node.size, > +true); > + drm_mm_remove_node(); > +err_file: > + fput(file); > + obj->base.filp = NULL; > + return ret; > +} > + > +int > +i915_gem_freeze(struct drm_device *dev) > +{ > + /* Called before i915_gem_suspend() when hibernating */ > + struct drm_i915_private *i915 = to_i915(dev); > + struct drm_i915_gem_object *obj, *tmp; > + struct list_head *phase[] = { > + >mm.unbound_list, >mm.bound_list, NULL > + }, **p; > + > + /* Across hibernation, the stolen area is not preserved. > + * Anything inside stolen must copied back to normal > + * memory if we wish to preserve it. > + */ > + for (p = phase; *p; p++) { Didn't we introduce a list of stolen objects in one of the other patches? > + struct list_head migrate; > + int ret; > + > +
Re: [Intel-gfx] [PATCH 4/6] drm/i915: Add support for stealing purgable stolen pages
On Thu, Oct 08, 2015 at 11:43:29AM +0100, Tvrtko Ursulin wrote: > >-struct drm_i915_gem_object * > >-i915_gem_object_create_stolen(struct drm_device *dev, u64 size) > >+static bool > >+mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind) > >+{ > >+BUG_ON(obj->stolen == NULL); > > I am fundamentally opposed to BUG_ONs which can be avoided. In this > I see no value in hanging the machine while we could WARN_ON and > return false. Don't bother with the WARN_ON. Either take the BUG_ON or accept that to get to this point the machine is dead anyway and a warning here doesn't help identify the root cause (better off with list debugging and memory debugging). I have personally been converting these asserts over to a dev-only compiletime option as I still find the BUGs more useful than WARNs in the GEM code. > >+if (obj->madv != I915_MADV_DONTNEED) > >+return false; > >+ > >+if (obj->pin_display) > >+return false; > >+ > >+list_add(>tmp_link, unwind); > >+return drm_mm_scan_add_block(>stolen->base); > >+} > >@@ -520,17 +609,59 @@ i915_gem_object_create_stolen(struct drm_device *dev, > >u64 size) > > if (!stolen) > > return ERR_PTR(-ENOMEM); > > > >-ret = i915_gem_stolen_insert_node(dev_priv, stolen, size, 4096); > >+ret = i915_gem_stolen_insert_node(dev_priv, >base, size, 4096); > >+if (ret == 0) > >+goto out; > >+ > >+/* No more stolen memory available, or too fragmented. > >+ * Try evicting purgeable objects and search again. > >+ */ > >+ret = stolen_evict(dev_priv, size); > > I have raised this question of struct_mutex in the previous round. > > Correct me if I am wrong, but I thought there was some effort made > to make stolen object allocation run without struct mutex? Correct. But note that we do GEM operations inside the eviction logic and the struct_mutex is the only one we have for them. > With this change it requires it again. At the moment callers seem to > hold it anyway. But I think lockdep_assert_held is needed now at > least to document the requirement, probably in top level > i915_gem_object_create_stolen. And a comment as to why, might as well also try and document the logic behind such decisions. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/5] drm/i915: Store and print dmc firmware version
On 9/18/2015 8:47 PM, Mika Kuoppala wrote: Parse csr/dmc firmware version and augment debug message by printing it. Cc: Animesh MannaSigned-off-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_csr.c | 7 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3bf8a9b..17e8b25 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -755,6 +755,8 @@ struct intel_csr { const char *fw_path; uint32_t *dmc_payload; uint32_t dmc_fw_size; + uint16_t dmc_ver_major; + uint16_t dmc_ver_minor; uint32_t mmio_count; uint32_t mmioaddr[8]; uint32_t mmiodata[8]; diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index b69264d..58edc3f 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -377,11 +377,16 @@ static void finish_csr_load(const struct firmware *fw, void *context) dmc_payload = csr->dmc_payload; memcpy(dmc_payload, >data[readcount], nbytes); + csr->dmc_ver_major = dmc_header->header_ver; + csr->dmc_ver_minor = ((dmc_header->fw_version & 0x) >> 16) * 10 + + (dmc_header->fw_version & 0x); + I am not able to locate the the way major and minor version is derived, is it present in bspec? -Animesh /* load csr program during system boot, as needed for DC states */ intel_csr_load_program(dev); fw_loaded = true; - DRM_DEBUG_KMS("Finished loading %s\n", dev_priv->csr.fw_path); + DRM_DEBUG_KMS("Finished loading %s v%u.%u\n", dev_priv->csr.fw_path, + csr->dmc_ver_major, csr->dmc_ver_minor); out: if (fw_loaded) intel_runtime_pm_put(dev_priv); ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/5] drm/i915: Store and print dmc firmware version
On Fri, Sep 18, 2015 at 06:17:05PM +0300, Mika Kuoppala wrote: > Parse csr/dmc firmware version and augment debug message > by printing it. > > Cc: Animesh Manna> Signed-off-by: Mika Kuoppala FWIW I did something similar in the past, but that contribution was denied. I also had the DC states entry counts, which sounds like something super useful to have: http://lists.freedesktop.org/archives/intel-gfx/2015-June/thread.html The DMC firmware version decoding was different in my patch and I'm sure it worked then. Maye the header has changed :( Feel free to use any part of that series with your authorship. -- Damien ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/9] drm/i915: driver based PASID handling
On 07/10/2015 17:14, Daniel Vetter wrote: On Wed, Oct 07, 2015 at 08:16:42AM -0700, Jesse Barnes wrote: On 10/07/2015 06:00 AM, David Woodhouse wrote: On Fri, 2015-09-04 at 09:59 -0700, Jesse Barnes wrote: + + ret = handle_mm_fault(mm, vma, address, + desc.wr_req ? FAULT_FLAG_WRITE : 0); + if (ret & VM_FAULT_ERROR) { + gpu_mm_segv(tsk, address, SEGV_ACCERR); /* ? */ + goto out_unlock; + } + Hm, do you need to force the SEGV there, in what ought to be generic IOMMU code? Can you instead just let the fault handler return an appropriate failure code to the IOMMU request queue and then deal with the resulting error on the i915 device side? I'm not sure if we get enough info on the i915 side to handle it reasonably, we'll have to test that out. We do know precisely which context blew up, but without the TDR work we can't yet just kill the offender selective without affecting the other active gpu contexts. Could someone clarify what this means from the TDR point of view, please? When you say "context blew up" I'm guessing that you mean that come context caused the fault handler to get involved somehow? Does this imply that the offending context will hang and the driver will have to detect this hang? If so, then yes - if we have the per-engine hang recovery mode as part of the upcoming TDR work in place then we could handle it by stepping over the offending batch buffer and moving on with a minimum of side-effects on the rest of the driver/GPU. Or does this imply that we have some new integration path to deal with? (something that I should be aware of when upstreaming TDR?) Sorry if I missed something blatantly obvious in the patch ;). Thanks, Tomas But besides that I really don't see a reason why we need to kill the process if the gpu faults. After all if a thread sigfaults then signal goes to that thread and not some random one (or the one thread that forked the thread that blew up). And we do have interfaces to tell userspace that something bad happened with the gpu work it submitted. Chris made a similar patch for userptr and I didn't like that one either. Worst case userspace has a special SEGV handler and then things really go down badly when that handler gets triggered at an unexpected place. -Daniel That way, you should hopefully get to gracefully cope with reporting errors for a specific *context*, rather than killing the whole process. It would be best to get per-context error info, but killing the process may be unavoidable (just as if a single thread clobbers memory in your process). Jesse ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [v2] drm/i915/skl: Init cdclk in the driver rather than relying on pre-os
On Thu, Oct 08, 2015 at 05:43:41PM +0530, Kumar, Shobhit wrote: > On 10/08/2015 04:59 PM, Imre Deak wrote: > > On to, 2015-10-08 at 09:58 +0530, Shobhit Kumar wrote: > >> Reuse what is programmed by pre-os, but in case there is no pre-os > >> initialization, init the cdclk with the max value by default untill > >> dynamic cdclk support comes. > >> > >> v2: Check if BIOS programmed correctly rather than always calling init > >> - Do validation of programmed cdctl and what it is expected > >> - Only do slk_init_cdclk if validation failed else reuse BIOS > >>programmed value > >> > >> Cc: Imre Deak> >> Cc: Ville Syrjälä > >> Signed-off-by: Shobhit Kumar > >> --- > >> drivers/gpu/drm/i915/intel_ddi.c | 18 - > >> drivers/gpu/drm/i915/intel_display.c | 39 > >> +++- > >> 2 files changed, 42 insertions(+), 15 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/i915/intel_ddi.c > >> b/drivers/gpu/drm/i915/intel_ddi.c > >> index 2d3cc82..3ec5618 100644 > >> --- a/drivers/gpu/drm/i915/intel_ddi.c > >> +++ b/drivers/gpu/drm/i915/intel_ddi.c > >> @@ -2946,11 +2946,19 @@ void intel_ddi_pll_init(struct drm_device *dev) > >>int cdclk_freq; > >> > >>cdclk_freq = dev_priv->display.get_display_clock_speed(dev); > >> - dev_priv->skl_boot_cdclk = cdclk_freq; > >> - if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) > >> - DRM_ERROR("LCPLL1 is disabled\n"); > >> - else > >> - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); > >> + > >> + /* Invalid CDCLK from BIOS ? */ > >> + if (cdclk_freq < 0) { > >> + /* program to maximum cdclk till we have dynamic cdclk > >> support */ > >> + dev_priv->skl_boot_cdclk = 675000; > >> + skl_init_cdclk(dev_priv); > > > > This would still try to reprogram CDCLK if BIOS enabled an output with > > an incorrect CDCLK decimal part. Isn't this the exact scenario you're > > seeing? As said before reprogramming CDCLK in that case would require > > disabling the outputs first. > > I went with the hypothesis that if VBIOS/GOP was loaded it would have to > correct the cdclock, with wrong decimal value display cannot be enabled. > For example AUX will fail on SKL. So for correct display output enabled > cdclock has to be correctly programmed. If it is wrong display was not > enabled at all. > > The scenario which I am seeing is VBIOS/GOP is not loaded at all, and > the pre-os is not leaving cdclock in correct state. But it still enabled DPLL0? Why does it do that if it doesn't set up cdclk? > > > > > We would also need to call skl_init_cdclk if the BIOS hasn't enabled the > > PLL for some reason. But I guess that could be a separate change. > > > >> + } else { > >> + dev_priv->skl_boot_cdclk = cdclk_freq; > >> + if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) > >> + DRM_ERROR("LCPLL1 is disabled\n"); > >> + else > >> + intel_display_power_get(dev_priv, > >> POWER_DOMAIN_PLLS); > >> + } > >>} else if (IS_BROXTON(dev)) { > >>broxton_init_cdclk(dev); > >>broxton_ddi_phy_init(dev); > >> diff --git a/drivers/gpu/drm/i915/intel_display.c > >> b/drivers/gpu/drm/i915/intel_display.c > >> index bbeb6d3..f734410 100644 > >> --- a/drivers/gpu/drm/i915/intel_display.c > >> +++ b/drivers/gpu/drm/i915/intel_display.c > >> @@ -6634,12 +6634,15 @@ static int skylake_get_display_clock_speed(struct > >> drm_device *dev) > >>uint32_t lcpll1 = I915_READ(LCPLL1_CTL); > >>uint32_t cdctl = I915_READ(CDCLK_CTL); > >>uint32_t linkrate; > >> + int freq; > >> > >>if (!(lcpll1 & LCPLL_PLL_ENABLE)) > >>return 24000; /* 24MHz is the cd freq with NSSC ref */ > >> > >> - if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) > >> - return 54; > >> + if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) { > >> + freq = 54; > >> + goto verify; > >> + } > >> > >>linkrate = (I915_READ(DPLL_CTRL1) & > >>DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; > >> @@ -6649,30 +6652,46 @@ static int skylake_get_display_clock_speed(struct > >> drm_device *dev) > >>/* vco 8640 */ > >>switch (cdctl & CDCLK_FREQ_SEL_MASK) { > >>case CDCLK_FREQ_450_432: > >> - return 432000; > >> + freq = 432000; > >> + break; > >>case CDCLK_FREQ_337_308: > >> - return 308570; > >> + freq = 308570; > >> + break; > >>case CDCLK_FREQ_675_617: > >> - return 617140; > >> + freq = 617140; > >> + break; > >>
Re: [Intel-gfx] [PATCH 2/5] drm/i915: Notify user about outdated dmc firmware
On 9/21/2015 2:00 PM, Mika Kuoppala wrote: Jani Nikulawrites: On Fri, 18 Sep 2015, Mika Kuoppala wrote: If csr/dmc firmware is known to be outdated, notify user. What would break if we requested a firmware version that works? Or we've made it so that we only request the major version because there's not supposed to be changes like this between minor versions...? I guess the question is more of a what should we do if there is only outdated (known bad) firmware available. Refuse to load and limb onwards, or return with error code on driver init. Latter would force firmware and version to be mandatory and the version to be tightly coupled to kernel driver version. A softlink is used to use recommended firmware for dmc and the same information is published through 01.org for the firmware user. Imo, we should not have this kind of hack in code which will change over time and this is responsibility of repo-owner to link correct recommended firmware for new kernel update. -Animesh -Mika BR, Jani. Signed-off-by: Mika Kuoppala --- drivers/gpu/drm/i915/intel_csr.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 58edc3f..73807c3 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -45,6 +45,9 @@ MODULE_FIRMWARE(I915_CSR_SKL); +#define RECOMMENDED_FW_MAJOR 1 +#define RECOMMENDED_FW_MINOR 21 + /* * SKL CSR registers for DC5 and DC6 */ @@ -387,6 +390,12 @@ static void finish_csr_load(const struct firmware *fw, void *context) DRM_DEBUG_KMS("Finished loading %s v%u.%u\n", dev_priv->csr.fw_path, csr->dmc_ver_major, csr->dmc_ver_minor); + + if (csr->dmc_ver_major < RECOMMENDED_FW_MAJOR || + csr->dmc_ver_minor < RECOMMENDED_FW_MINOR) + DRM_INFO("Outdated dmc firmware found, please upgrade to %u.%u or newer\n", +RECOMMENDED_FW_MAJOR, RECOMMENDED_FW_MINOR); + out: if (fw_loaded) intel_runtime_pm_put(dev_priv); -- 2.1.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [v2] drm/i915/skl: Init cdclk in the driver rather than relying on pre-os
On to, 2015-10-08 at 09:58 +0530, Shobhit Kumar wrote: > Reuse what is programmed by pre-os, but in case there is no pre-os > initialization, init the cdclk with the max value by default untill > dynamic cdclk support comes. > > v2: Check if BIOS programmed correctly rather than always calling init > - Do validation of programmed cdctl and what it is expected > - Only do slk_init_cdclk if validation failed else reuse BIOS > programmed value > > Cc: Imre Deak> Cc: Ville Syrjälä > Signed-off-by: Shobhit Kumar > --- > drivers/gpu/drm/i915/intel_ddi.c | 18 - > drivers/gpu/drm/i915/intel_display.c | 39 > +++- > 2 files changed, 42 insertions(+), 15 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c > b/drivers/gpu/drm/i915/intel_ddi.c > index 2d3cc82..3ec5618 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -2946,11 +2946,19 @@ void intel_ddi_pll_init(struct drm_device *dev) > int cdclk_freq; > > cdclk_freq = dev_priv->display.get_display_clock_speed(dev); > - dev_priv->skl_boot_cdclk = cdclk_freq; > - if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) > - DRM_ERROR("LCPLL1 is disabled\n"); > - else > - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); > + > + /* Invalid CDCLK from BIOS ? */ > + if (cdclk_freq < 0) { > + /* program to maximum cdclk till we have dynamic cdclk > support */ > + dev_priv->skl_boot_cdclk = 675000; > + skl_init_cdclk(dev_priv); This would still try to reprogram CDCLK if BIOS enabled an output with an incorrect CDCLK decimal part. Isn't this the exact scenario you're seeing? As said before reprogramming CDCLK in that case would require disabling the outputs first. We would also need to call skl_init_cdclk if the BIOS hasn't enabled the PLL for some reason. But I guess that could be a separate change. > + } else { > + dev_priv->skl_boot_cdclk = cdclk_freq; > + if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) > + DRM_ERROR("LCPLL1 is disabled\n"); > + else > + intel_display_power_get(dev_priv, > POWER_DOMAIN_PLLS); > + } > } else if (IS_BROXTON(dev)) { > broxton_init_cdclk(dev); > broxton_ddi_phy_init(dev); > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index bbeb6d3..f734410 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -6634,12 +6634,15 @@ static int skylake_get_display_clock_speed(struct > drm_device *dev) > uint32_t lcpll1 = I915_READ(LCPLL1_CTL); > uint32_t cdctl = I915_READ(CDCLK_CTL); > uint32_t linkrate; > + int freq; > > if (!(lcpll1 & LCPLL_PLL_ENABLE)) > return 24000; /* 24MHz is the cd freq with NSSC ref */ > > - if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) > - return 54; > + if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) { > + freq = 54; > + goto verify; > + } > > linkrate = (I915_READ(DPLL_CTRL1) & > DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; > @@ -6649,30 +6652,46 @@ static int skylake_get_display_clock_speed(struct > drm_device *dev) > /* vco 8640 */ > switch (cdctl & CDCLK_FREQ_SEL_MASK) { > case CDCLK_FREQ_450_432: > - return 432000; > + freq = 432000; > + break; > case CDCLK_FREQ_337_308: > - return 308570; > + freq = 308570; > + break; > case CDCLK_FREQ_675_617: > - return 617140; > + freq = 617140; > + break; > default: > WARN(1, "Unknown cd freq selection\n"); > + return -EINVAL; > } > } else { > /* vco 8100 */ > switch (cdctl & CDCLK_FREQ_SEL_MASK) { > case CDCLK_FREQ_450_432: > - return 45; > + freq = 45; > + break; > case CDCLK_FREQ_337_308: > - return 337500; > + freq = 337500; > + break; > case CDCLK_FREQ_675_617: > - return 675000; > + freq = 675000; > + break; > default: > WARN(1, "Unknown cd freq selection\n"); > +
Re: [Intel-gfx] [PATCH] drm/i915: 4K audio N value incorrect at 29.97 and 23.98 refresh rate
On Thu, 08 Oct 2015, Ville Syrjäläwrote: > On Wed, Oct 07, 2015 at 02:38:29PM -0700, clinton.a.tay...@intel.com wrote: >> From: Clint Taylor >> >> The TMDS_296M define was computing as 296704 but the mode->clock is >> 296700 as defined by EDID. Adjusted define to allow correct detection >> of the need to program the correct N value for 29.97 and 23.98 refresh >> rate. >> >> Signed-off-by: Clint Taylor >> --- >> drivers/gpu/drm/i915/intel_audio.c |2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/drivers/gpu/drm/i915/intel_audio.c >> b/drivers/gpu/drm/i915/intel_audio.c >> index 56c2f54..419c979 100644 >> --- a/drivers/gpu/drm/i915/intel_audio.c >> +++ b/drivers/gpu/drm/i915/intel_audio.c >> @@ -75,7 +75,7 @@ static const struct { >> >> /* HDMI N/CTS table */ >> #define TMDS_297M 297000 >> -#define TMDS_296M DIV_ROUND_UP(297000 * 1000, 1001) >> +#define TMDS_296M 296700 > > Hmm. I think we might want to fix up the mode instead. Let me post a few > patches, and let's see what people think... We might actually want to queue this up for v4.3 as the immediate fix, as I feel it's doubtful your other patches will make it to v4.3. If Someone(tm) provided their r-b that is. BR, Jani. > >> static const struct { >> int sample_rate; >> int clock; >> -- >> 1.7.9.5 >> >> ___ >> Intel-gfx mailing list >> Intel-gfx@lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx > > -- > Ville Syrjälä > Intel OTC > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/2] drm/i915: Call encoder hotplug for init and resume cases
On Mon, Oct 05, 2015 at 04:43:14PM +0530, Sonika Jindal wrote: > For all the encoders, call the hot_plug if it is registered. > This is required for connected boot and resume cases to generate > fake hpd resulting in reading of edid. > Removing the initial sdvo hot_plug call too so that it will be called > just once from this loop. > > Signed-off-by: Sonika Jindal> --- > drivers/gpu/drm/i915/intel_hotplug.c | 11 +++ > drivers/gpu/drm/i915/intel_sdvo.c|1 - > 2 files changed, 11 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/intel_hotplug.c > b/drivers/gpu/drm/i915/intel_hotplug.c > index 53c0173..eac4757 100644 > --- a/drivers/gpu/drm/i915/intel_hotplug.c > +++ b/drivers/gpu/drm/i915/intel_hotplug.c > @@ -458,6 +458,7 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) > { > struct drm_device *dev = dev_priv->dev; > struct drm_mode_config *mode_config = >mode_config; > + struct intel_encoder *encoder; > struct drm_connector *connector; > int i; > > @@ -482,6 +483,16 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) > if (dev_priv->display.hpd_irq_setup) > dev_priv->display.hpd_irq_setup(dev); > spin_unlock_irq(_priv->irq_lock); > + > + /* > + * Connected boot / resume scenarios can't generate new hot plug. > + * So, probe it manually. > + */ > + list_for_each_entry(encoder, >mode_config.encoder_list, > + base.head) { > + if (encoder->hot_plug) > + encoder->hot_plug(encoder); > + } This breaks the world on CHV [ 3187.575198] [drm:intel_hdmi_hot_plug] Live status not up! [ 3187.585154] = [ 3187.595010] [ INFO: possible recursive locking detected ] [ 3187.604685] 4.3.0-rc4-bsw+ #2488 Tainted: G U W [ 3187.614366] - [ 3187.623892] Xorg/32212 is trying to acquire lock: [ 3187.632635] (_domains->lock){+.+...}, at: [] intel_display_power_get+0x38/0xcb [i915] [ 3187.647492] [ 3187.647492] but task is already holding lock: [ 3187.661054] (_domains->lock){+.+...}, at: [] intel_display_power_get+0x38/0xcb [i915] [ 3187.675960] [ 3187.675960] other info that might help us debug this: [ 3187.690459] Possible unsafe locking scenario: [ 3187.690459] [ 3187.704224]CPU0 [ 3187.710485] [ 3187.716711] lock(_domains->lock); [ 3187.724718] lock(_domains->lock); [ 3187.732663] [ 3187.732663] *** DEADLOCK *** [ 3187.732663] [ 3187.749460] May be due to missing lock nesting notation [ 3187.749460] [ 3187.763833] 5 locks held by Xorg/32212: [ 3187.771523] #0: (drm_global_mutex){+.+.+.}, at: [] drm_release+0x3b/0x49b [drm] [ 3187.785216] #1: (>mode_config.mutex){+.+.+.}, at: [] drm_modeset_lock_all+0x54/0xcd [drm] [ 3187.800437] #2: (crtc_ww_class_acquire){+.+.+.}, at: [] drm_modeset_lock_all+0x5e/0xcd [drm] [ 3187.815488] #3: (crtc_ww_class_mutex){+.+.+.}, at: [] drm_modeset_lock+0x75/0xfc [drm] [ 3187.830094] #4: (_domains->lock){+.+...}, at: [] intel_display_power_get+0x38/0xcb [i915] [ 3187.845534] [ 3187.845534] stack backtrace: [ 3187.857685] CPU: 2 PID: 32212 Comm: Xorg Tainted: G U W 4.3.0-rc4-bsw+ #2488 [ 3187.870331] Hardware name: Intel Corporation CHERRYVIEW C0 PLATFORM/Braswell CRB, BIOS BRAS.X64.B085.R00.1509110553 09/11/2015 [ 3187.886827] 880175eff8e0 8128d59e 823f5ee0 [ 3187.898904] 880175eff958 810a7a08 880179d1c5d0 [ 3187.910954] 0004 0006 45422a91588a4c3e 0005 [ 3187.923011] Call Trace: [ 3187.929451] [] dump_stack+0x4e/0x79 [ 3187.938912] [] __lock_acquire+0x7ab/0x12af [ 3187.949027] [] lock_acquire+0x10e/0x1a9 [ 3187.958859] [] ? intel_display_power_get+0x38/0xcb [i915] [ 3187.970476] [] ? intel_display_power_get+0x38/0xcb [i915] [ 3187.982011] [] mutex_lock_nested+0x71/0x346 [ 3187.992167] [] ? intel_display_power_get+0x38/0xcb [i915] [ 3188.003655] [] ? _raw_spin_unlock_irqrestore+0x4b/0x60 [ 3188.014829] [] ? __pm_runtime_resume+0x71/0x7e [ 3188.025269] [] intel_display_power_get+0x38/0xcb [i915] [ 3188.036544] [] ? intel_display_power_get+0x38/0xcb [i915] [ 3188.047968] [] intel_hdmi_set_edid+0x3f/0xd6 [i915] [ 3188.058766] [] intel_hdmi_hot_plug+0xbf/0xfb [i915] [ 3188.069484] [] intel_hpd_init+0xfa/0x10b [i915] [ 3188.079753] [] vlv_display_power_well_init+0xdb/0xe8 [i915] [ 3188.091224] [] chv_pipe_power_well_enable+0x62/0x67 [i915] [ 3188.102594] [] intel_display_power_get+0xa0/0xcb [i915] [ 3188.113657] [] modeset_get_crtc_power_domains+0x11d/0x13c [i915] [ 3188.125589] [] intel_atomic_commit+0x228/0xf1b [i915] [ 3188.136522] [] ? drm_atomic_check_only+0x37b/0x4da [drm] [ 3188.147676] [] drm_atomic_commit+0x4d/0x52 [drm] [ 3188.158023] [] restore_fbdev_mode+0x11e/0x286
[Intel-gfx] [PATCH] drm,i915: Introduce drm_malloc_gfp()
I have instances where I want to use drm_malloc_ab() but with a custom gfp mask. And with those, where I want a temporary allocation, I want to try a high-order kmalloc() before using a vmalloc(). So refactor my usage into drm_malloc_gfp(). Signed-off-by: Chris WilsonCc: dri-de...@lists.freedesktop.org Cc: Ville Syrjälä --- drivers/gpu/drm/i915/i915_gem.c| 4 +--- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 +++- drivers/gpu/drm/i915/i915_gem_gtt.c| 5 +++-- drivers/gpu/drm/i915/i915_gem_userptr.c| 15 --- include/drm/drm_mem_util.h | 19 +++ 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fe672d4a4d73..c81127518083 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2346,9 +2346,7 @@ void *i915_gem_object_pin_vmap(struct drm_i915_gem_object *obj) int n; n = obj->base.size >> PAGE_SHIFT; - pages = kmalloc(n*sizeof(*pages), GFP_TEMPORARY | __GFP_NOWARN); - if (pages == NULL) - pages = drm_malloc_ab(n, sizeof(*pages)); + pages = drm_malloc_gfp(n, sizeof(*pages), GFP_TEMPORARY); if (pages != NULL) { n = 0; for_each_sg_page(obj->pages->sgl, _iter, obj->pages->nents, 0) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index c35c9dc526e7..91fb7417efc0 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1730,11 +1730,9 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, return -EINVAL; } - exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count, -GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); - if (exec2_list == NULL) - exec2_list = drm_malloc_ab(sizeof(*exec2_list), - args->buffer_count); + exec2_list = drm_malloc_gfp(sizeof(*exec2_list), + args->buffer_count, + GFP_TEMPORARY); if (exec2_list == NULL) { DRM_DEBUG("Failed to allocate exec list for %d buffers\n", args->buffer_count); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6e8c86d829d2..7820e8983136 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3221,8 +3221,9 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, int ret = -ENOMEM; /* Allocate a temporary list of source pages for random access. */ - page_addr_list = drm_malloc_ab(obj->base.size / PAGE_SIZE, - sizeof(dma_addr_t)); + page_addr_list = drm_malloc_gfp(obj->base.size / PAGE_SIZE, + sizeof(dma_addr_t), + GFP_TEMPORARY); if (!page_addr_list) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index afd4c2c4cc04..885605c38e7c 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -575,10 +575,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) ret = -ENOMEM; pinned = 0; - pvec = kmalloc(npages*sizeof(struct page *), - GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); - if (pvec == NULL) - pvec = drm_malloc_ab(npages, sizeof(struct page *)); + pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY); if (pvec != NULL) { struct mm_struct *mm = obj->userptr.mm->mm; @@ -715,14 +712,10 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) pvec = NULL; pinned = 0; if (obj->userptr.mm->mm == current->mm) { - pvec = kmalloc(num_pages*sizeof(struct page *), - GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); + pvec = drm_malloc_gfp(num_pages, sizeof(struct page *), GFP_TEMPORARY); if (pvec == NULL) { - pvec = drm_malloc_ab(num_pages, sizeof(struct page *)); - if (pvec == NULL) { - __i915_gem_userptr_set_active(obj, false); - return -ENOMEM; - } + __i915_gem_userptr_set_active(obj, false); + return -ENOMEM; } pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages, diff --git a/include/drm/drm_mem_util.h
Re: [Intel-gfx] [PATCH RESEND 1/3] drm/i915: use error path
On Thu, Oct 08, 2015 at 07:27:59PM +0530, Sudip Mukherjee wrote: > Use goto to handle the error path to avoid duplicating the same code. In > the error path intel_dig_port is the last one to be released as it was > the first one to be allocated and ideally the error path should be the > reverse of the execution path. > > Cc: Daniel Vetter> Cc: Jani Nikula > Signed-off-by: Sudip Mukherjee Queued for -next, thanks for the patch. -Daniel > --- > > Sent on 27/07/2015 > > drivers/gpu/drm/i915/intel_dp.c | 23 ++- > 1 file changed, 14 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index 8d34ca7..18bcfbe 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -6168,10 +6168,8 @@ intel_dp_init(struct drm_device *dev, int output_reg, > enum port port) > return; > > intel_connector = intel_connector_alloc(); > - if (!intel_connector) { > - kfree(intel_dig_port); > - return; > - } > + if (!intel_connector) > + goto err_connector_alloc; > > intel_encoder = _dig_port->base; > encoder = _encoder->base; > @@ -6219,11 +6217,18 @@ intel_dp_init(struct drm_device *dev, int output_reg, > enum port port) > intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; > dev_priv->hotplug.irq_port[port] = intel_dig_port; > > - if (!intel_dp_init_connector(intel_dig_port, intel_connector)) { > - drm_encoder_cleanup(encoder); > - kfree(intel_dig_port); > - kfree(intel_connector); > - } > + if (!intel_dp_init_connector(intel_dig_port, intel_connector)) > + goto err_init_connector; > + > + return; > + > +err_init_connector: > + drm_encoder_cleanup(encoder); > + kfree(intel_connector); > +err_connector_alloc: > + kfree(intel_dig_port); > + > + return; > } > > void intel_dp_mst_suspend(struct drm_device *dev) > -- > 1.9.1 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH RESEND 2/3] drm/i915: check for return value
On Thu, Oct 08, 2015 at 07:28:00PM +0530, Sudip Mukherjee wrote: > We were not checking the return value of drm_encoder_init() which can > fail. And if it fails then we will be working with an uninitialized > encoder. > > Cc: Daniel Vetter> Cc: Jani Nikula > Signed-off-by: Sudip Mukherjee Queued for -next, thanks for the patch. -Daniel > --- > > Sent on 27/07/2015 > > drivers/gpu/drm/i915/intel_dp.c | 6 -- > 1 file changed, 4 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index 18bcfbe..2a8b47e 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -6174,8 +6174,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, > enum port port) > intel_encoder = _dig_port->base; > encoder = _encoder->base; > > - drm_encoder_init(dev, _encoder->base, _dp_enc_funcs, > - DRM_MODE_ENCODER_TMDS); > + if (drm_encoder_init(dev, _encoder->base, _dp_enc_funcs, > + DRM_MODE_ENCODER_TMDS)) > + goto err_encoder_init; > > intel_encoder->compute_config = intel_dp_compute_config; > intel_encoder->disable = intel_disable_dp; > @@ -6224,6 +6225,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, > enum port port) > > err_init_connector: > drm_encoder_cleanup(encoder); > +err_encoder_init: > kfree(intel_connector); > err_connector_alloc: > kfree(intel_dig_port); > -- > 1.9.1 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm,i915: Introduce drm_malloc_gfp()
On Thu, Oct 08, 2015 at 02:39:24PM +0100, Chris Wilson wrote: > I have instances where I want to use drm_malloc_ab() but with a custom > gfp mask. And with those, where I want a temporary allocation, I want to > try a high-order kmalloc() before using a vmalloc(). > > So refactor my usage into drm_malloc_gfp(). > > Signed-off-by: Chris Wilson> Cc: dri-de...@lists.freedesktop.org > Cc: Ville Syrjälä lgtm Reviewed-by: Ville Syrjälä > --- > drivers/gpu/drm/i915/i915_gem.c| 4 +--- > drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 +++- > drivers/gpu/drm/i915/i915_gem_gtt.c| 5 +++-- > drivers/gpu/drm/i915/i915_gem_userptr.c| 15 --- > include/drm/drm_mem_util.h | 19 +++ > 5 files changed, 30 insertions(+), 21 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index fe672d4a4d73..c81127518083 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -2346,9 +2346,7 @@ void *i915_gem_object_pin_vmap(struct > drm_i915_gem_object *obj) > int n; > > n = obj->base.size >> PAGE_SHIFT; > - pages = kmalloc(n*sizeof(*pages), GFP_TEMPORARY | __GFP_NOWARN); > - if (pages == NULL) > - pages = drm_malloc_ab(n, sizeof(*pages)); > + pages = drm_malloc_gfp(n, sizeof(*pages), GFP_TEMPORARY); > if (pages != NULL) { > n = 0; > for_each_sg_page(obj->pages->sgl, _iter, > obj->pages->nents, 0) > diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c > b/drivers/gpu/drm/i915/i915_gem_execbuffer.c > index c35c9dc526e7..91fb7417efc0 100644 > --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c > +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c > @@ -1730,11 +1730,9 @@ i915_gem_execbuffer2(struct drm_device *dev, void > *data, > return -EINVAL; > } > > - exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count, > - GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); > - if (exec2_list == NULL) > - exec2_list = drm_malloc_ab(sizeof(*exec2_list), > -args->buffer_count); > + exec2_list = drm_malloc_gfp(sizeof(*exec2_list), > + args->buffer_count, > + GFP_TEMPORARY); > if (exec2_list == NULL) { > DRM_DEBUG("Failed to allocate exec list for %d buffers\n", > args->buffer_count); > diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c > b/drivers/gpu/drm/i915/i915_gem_gtt.c > index 6e8c86d829d2..7820e8983136 100644 > --- a/drivers/gpu/drm/i915/i915_gem_gtt.c > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c > @@ -3221,8 +3221,9 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view > *ggtt_view, > int ret = -ENOMEM; > > /* Allocate a temporary list of source pages for random access. */ > - page_addr_list = drm_malloc_ab(obj->base.size / PAGE_SIZE, > -sizeof(dma_addr_t)); > + page_addr_list = drm_malloc_gfp(obj->base.size / PAGE_SIZE, > + sizeof(dma_addr_t), > + GFP_TEMPORARY); > if (!page_addr_list) > return ERR_PTR(ret); > > diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c > b/drivers/gpu/drm/i915/i915_gem_userptr.c > index afd4c2c4cc04..885605c38e7c 100644 > --- a/drivers/gpu/drm/i915/i915_gem_userptr.c > +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c > @@ -575,10 +575,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct > *_work) > ret = -ENOMEM; > pinned = 0; > > - pvec = kmalloc(npages*sizeof(struct page *), > -GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); > - if (pvec == NULL) > - pvec = drm_malloc_ab(npages, sizeof(struct page *)); > + pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY); > if (pvec != NULL) { > struct mm_struct *mm = obj->userptr.mm->mm; > > @@ -715,14 +712,10 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object > *obj) > pvec = NULL; > pinned = 0; > if (obj->userptr.mm->mm == current->mm) { > - pvec = kmalloc(num_pages*sizeof(struct page *), > -GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); > + pvec = drm_malloc_gfp(num_pages, sizeof(struct page *), > GFP_TEMPORARY); > if (pvec == NULL) { > - pvec = drm_malloc_ab(num_pages, sizeof(struct page *)); > - if (pvec == NULL) { > - __i915_gem_userptr_set_active(obj, false); > - return -ENOMEM; > - } > +
Re: [Intel-gfx] [PATCH 4/6] drm/i915: Add support for stealing purgable stolen pages
On 08/10/15 12:09, Chris Wilson wrote: On Thu, Oct 08, 2015 at 11:43:29AM +0100, Tvrtko Ursulin wrote: -struct drm_i915_gem_object * -i915_gem_object_create_stolen(struct drm_device *dev, u64 size) +static bool +mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind) +{ + BUG_ON(obj->stolen == NULL); I am fundamentally opposed to BUG_ONs which can be avoided. In this I see no value in hanging the machine while we could WARN_ON and return false. Don't bother with the WARN_ON. Either take the BUG_ON or accept that to get to this point the machine is dead anyway and a warning here doesn't help identify the root cause (better off with list debugging and memory debugging). I have personally been converting these asserts over to a dev-only compiletime option as I still find the BUGs more useful than WARNs in the GEM code. This is one of the ones which are to be expected in development only. At that time I much prefer a WARN_ON since it potentially saves you one reboot cycle and there aren't really any downsides to it. Especially if, as you say, machine is dead already. + if (obj->madv != I915_MADV_DONTNEED) + return false; + + if (obj->pin_display) + return false; + + list_add(>tmp_link, unwind); + return drm_mm_scan_add_block(>stolen->base); +} @@ -520,17 +609,59 @@ i915_gem_object_create_stolen(struct drm_device *dev, u64 size) if (!stolen) return ERR_PTR(-ENOMEM); - ret = i915_gem_stolen_insert_node(dev_priv, stolen, size, 4096); + ret = i915_gem_stolen_insert_node(dev_priv, >base, size, 4096); + if (ret == 0) + goto out; + + /* No more stolen memory available, or too fragmented. +* Try evicting purgeable objects and search again. +*/ + ret = stolen_evict(dev_priv, size); I have raised this question of struct_mutex in the previous round. Correct me if I am wrong, but I thought there was some effort made to make stolen object allocation run without struct mutex? Correct. But note that we do GEM operations inside the eviction logic and the struct_mutex is the only one we have for them. With this change it requires it again. At the moment callers seem to hold it anyway. But I think lockdep_assert_held is needed now at least to document the requirement, probably in top level i915_gem_object_create_stolen. And a comment as to why, might as well also try and document the logic behind such decisions. Agreed. Regards, Tvrtko ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/3] drm/i915: Refactor duplicate object vmap functions
On Thu, Oct 08, 2015 at 03:58:13PM +0300, Ville Syrjälä wrote: > > + pages = kmalloc(n*sizeof(*pages), GFP_TEMPORARY); > > Random driveby: kmalloc_array() That would be scary, imagine having enough pages in the object to overflow unsigned long :) > Also __GFP_NOWARN? True. > I wonder if the drm_malloc stuff should do the kmalloc attempt > regardless fo the size, so we wouldn't have to do it here? It's a pattern I've reused in a few places, so probably worthy of being refactored. Something like -static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size) +static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size, gfp_t gfp) { if (size != 0 && nmemb > SIZE_MAX / size) return NULL; if (size * nmemb <= PAGE_SIZE) - return kmalloc(nmemb * size, GFP_KERNEL); + return kmalloc(nmemb * size, gfp); + + if (gfp & GFP_TEMPORARY) { + void *ptr = kmalloc(nmemb * size, gfp | __GFP_NOWARN); + if (ptr) + return ptr; + } return __vmalloc(size * nmemb, -GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); +gfp | __GFP_HIGHMEM, PAGE_KERNEL); } Would need to call it my_drm_malloc_ab() to avoid having to update everywhere. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: disable CPU PWM also on LPT/SPT backlight disable
Huang, please try this patch. BR, Jani. On Tue, 29 Sep 2015, Jani Nikulawrote: > Also adding Cc: intel-gfx, please include that in follow-ups. > > Thanks, > Jani. > > On Tue, 29 Sep 2015, Jani Nikula wrote: >> Although we don't support or enable CPU PWM with LPT/SPT based systems, >> it may have been enabled prior to loading the driver. Disable the CPU >> PWM on LPT/SPT backlight disable to avoid warnings on LCPLL disable. >> >> The issue has been present on BDW since BDW enabling, but was recently >> introduced on HSW with >> >> commit 437b15b8017e0d946453c10794b0c5d4591cf180 >> Author: Jani Nikula >> Date: Fri Sep 4 16:55:13 2015 +0300 >> >> drm/i915: use pch backlight override on hsw too >> >> Reference: http://mid.gmane.org/87y4frhwsn@yhuang-dev.intel.com >> Reported-by: kernel test robot >> Signed-off-by: Jani Nikula >> --- >> drivers/gpu/drm/i915/intel_panel.c | 14 ++ >> 1 file changed, 14 insertions(+) >> >> diff --git a/drivers/gpu/drm/i915/intel_panel.c >> b/drivers/gpu/drm/i915/intel_panel.c >> index dd71e7f139e3..c9c94d05f3dd 100644 >> --- a/drivers/gpu/drm/i915/intel_panel.c >> +++ b/drivers/gpu/drm/i915/intel_panel.c >> @@ -731,6 +731,20 @@ static void lpt_disable_backlight(struct >> intel_connector *connector) >> >> intel_panel_actually_set_backlight(connector, 0); >> >> +/* >> + * Although we don't support or enable CPU PWM with LPT/SPT based >> + * systems, it may have been enabled prior to loading the >> + * driver. Disable to avoid warnings on LCPLL disable. >> + * >> + * This needs rework if we need to add support for CPU PWM on PCH split >> + * platforms. >> + */ >> +tmp = I915_READ(BLC_PWM_CPU_CTL2); >> +if (tmp & BLM_PWM_ENABLE) { >> +DRM_DEBUG_KMS("cpu backlight was enabled, disabling\n"); >> +I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); >> +} >> + >> tmp = I915_READ(BLC_PWM_PCH_CTL1); >> I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); >> } >> -- >> 2.1.4 >> > > -- > Jani Nikula, Intel Open Source Technology Center -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/3] drm/i915: Refactor duplicate object vmap functions
We now have two implementations for vmapping a whole object, one for dma-buf and one for the ringbuffer. If we couple the vmapping into the obj->pages lifetime, then we can reuse an obj->vmapping for both and at the same time couple it into the shrinker. Signed-off-by: Chris Wilson--- drivers/gpu/drm/i915/i915_drv.h | 12 --- drivers/gpu/drm/i915/i915_gem.c | 41 drivers/gpu/drm/i915/i915_gem_dmabuf.c | 55 + drivers/gpu/drm/i915/intel_ringbuffer.c | 53 ++- 4 files changed, 72 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4093eedfd664..343a0a723d2c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2089,10 +2089,7 @@ struct drm_i915_gem_object { struct scatterlist *sg; int last; } get_page; - - /* prime dma-buf support */ - void *dma_buf_vmapping; - int vmapping_count; + void *vmapping; /** Breadcrumb of last rendering to the buffer. * There can only be one writer, but we allow for multiple readers. @@ -2840,12 +2837,19 @@ static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) BUG_ON(obj->pages == NULL); obj->pages_pin_count++; } + static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) { BUG_ON(obj->pages_pin_count == 0); obj->pages_pin_count--; } +void *__must_check i915_gem_object_pin_vmap(struct drm_i915_gem_object *obj); +static inline void i915_gem_object_unpin_vmap(struct drm_i915_gem_object *obj) +{ + i915_gem_object_unpin_pages(obj); +} + int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); int i915_gem_object_sync(struct drm_i915_gem_object *obj, struct intel_engine_cs *to, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 78640aecf86d..446cf0662a38 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2159,6 +2159,11 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) ops->put_pages(obj); obj->pages = NULL; + if (obj->vmapping) { + vunmap(obj->vmapping); + obj->vmapping = NULL; + } + i915_gem_object_invalidate(obj); return 0; @@ -2325,6 +2330,42 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj) return 0; } +void *i915_gem_object_pin_vmap(struct drm_i915_gem_object *obj) +{ + int ret; + + ret = i915_gem_object_get_pages(obj); + if (ret) + return ERR_PTR(ret); + + i915_gem_object_pin_pages(obj); + + if (obj->vmapping == NULL) { + struct sg_page_iter sg_iter; + struct page **pages; + int n; + + n = obj->base.size >> PAGE_SHIFT; + pages = kmalloc(n*sizeof(*pages), GFP_TEMPORARY); + if (pages == NULL) + pages = drm_malloc_ab(n, sizeof(*pages)); + if (pages != NULL) { + n = 0; + for_each_sg_page(obj->pages->sgl, _iter, obj->pages->nents, 0) + pages[n++] = sg_page_iter_page(_iter); + + obj->vmapping = vmap(pages, n, 0, PAGE_KERNEL); + drm_free_large(pages); + } + if (obj->vmapping == NULL) { + i915_gem_object_unpin_pages(obj); + return ERR_PTR(-ENOMEM); + } + } + + return obj->vmapping; +} + void i915_vma_move_to_active(struct i915_vma *vma, struct drm_i915_gem_request *req) { diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index e9c2bfd85b52..5c4163d3845a 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -95,14 +95,12 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, { struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf); - mutex_lock(>base.dev->struct_mutex); - dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir); sg_free_table(sg); kfree(sg); - i915_gem_object_unpin_pages(obj); - + mutex_lock(>base.dev->struct_mutex); + i915_gem_object_unpin_vmap(obj); mutex_unlock(>base.dev->struct_mutex); } @@ -110,51 +108,17 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) { struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); struct drm_device *dev = obj->base.dev; - struct sg_page_iter sg_iter; - struct page **pages; - int ret, i; + void *addr; + int ret; ret =
[Intel-gfx] [PATCH 1/3] drm/i915: Map the ringbuffer using WB on LLC machines
If we have llc coherency, we can write directly into the ringbuffer using ordinary cached writes rather than forcing WC access. v2: An important consequence is that we can forgo the mappable request for WB ringbuffers, allowing for many more simultaneous contexts. Signed-off-by: Chris Wilson--- drivers/gpu/drm/i915/intel_ringbuffer.c | 70 ++--- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index d608be46ea6e..f81ec7785fac 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1966,11 +1966,35 @@ static int init_phys_status_page(struct intel_engine_cs *ring) void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) { - iounmap(ringbuf->virtual_start); + if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen) + vunmap(ringbuf->virtual_start); + else + iounmap(ringbuf->virtual_start); ringbuf->virtual_start = NULL; i915_gem_object_ggtt_unpin(ringbuf->obj); } +static u32 *vmap_obj(struct drm_i915_gem_object *obj) +{ + struct sg_page_iter sg_iter; + struct page **pages; + void *addr; + int i; + + pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages)); + if (pages == NULL) + return NULL; + + i = 0; + for_each_sg_page(obj->pages->sgl, _iter, obj->pages->nents, 0) + pages[i++] = sg_page_iter_page(_iter); + + addr = vmap(pages, i, 0, PAGE_KERNEL); + drm_free_large(pages); + + return addr; +} + int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, struct intel_ringbuffer *ringbuf) { @@ -1978,21 +2002,39 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, struct drm_i915_gem_object *obj = ringbuf->obj; int ret; - ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); - if (ret) - return ret; + if (HAS_LLC(dev_priv) && !obj->stolen) { + ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 0); + if (ret) + return ret; - ret = i915_gem_object_set_to_gtt_domain(obj, true); - if (ret) { - i915_gem_object_ggtt_unpin(obj); - return ret; - } + ret = i915_gem_object_set_to_cpu_domain(obj, true); + if (ret) { + i915_gem_object_ggtt_unpin(obj); + return ret; + } + + ringbuf->virtual_start = vmap_obj(obj); + if (ringbuf->virtual_start == NULL) { + i915_gem_object_ggtt_unpin(obj); + return -ENOMEM; + } + } else { + ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); + if (ret) + return ret; - ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + - i915_gem_obj_ggtt_offset(obj), ringbuf->size); - if (ringbuf->virtual_start == NULL) { - i915_gem_object_ggtt_unpin(obj); - return -EINVAL; + ret = i915_gem_object_set_to_gtt_domain(obj, true); + if (ret) { + i915_gem_object_ggtt_unpin(obj); + return ret; + } + + ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + + i915_gem_obj_ggtt_offset(obj), ringbuf->size); + if (ringbuf->virtual_start == NULL) { + i915_gem_object_ggtt_unpin(obj); + return -EINVAL; + } } return 0; -- 2.6.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/3] drm/i915: Treat ringbuffer writes as write to normal memory
Ringbuffers are now being written to either through LLC or WC paths, so treating them as simply iomem is no longer adequate. However, for the older !llc hardware, the hardware is documentated as treating the TAIL register update as serialising, so we can relax the barriers when filling the rings (but even if it were not, it is still an uncached register write and so serialising anyway.). For simplicity, let's ignore the iomem annotation. Signed-off-by: Chris Wilson--- drivers/gpu/drm/i915/intel_lrc.c| 7 +-- drivers/gpu/drm/i915/intel_lrc.h| 6 +++--- drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +-- drivers/gpu/drm/i915/intel_ringbuffer.h | 17 - 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d38746c5370d..10020505be75 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -713,13 +713,8 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request) static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) { - uint32_t __iomem *virt; int rem = ringbuf->size - ringbuf->tail; - - virt = ringbuf->virtual_start + ringbuf->tail; - rem /= 4; - while (rem--) - iowrite32(MI_NOOP, virt++); + memset(ringbuf->virtual_start + ringbuf->tail, 0, rem); ringbuf->tail = 0; intel_ring_update_space(ringbuf); diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 64f89f9982a2..8b56fb934763 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -53,8 +53,9 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req); */ static inline void intel_logical_ring_advance(struct intel_ringbuffer *ringbuf) { - ringbuf->tail &= ringbuf->size - 1; + intel_ringbuffer_advance(ringbuf); } + /** * intel_logical_ring_emit() - write a DWORD to the ringbuffer. * @ringbuf: Ringbuffer to write to. @@ -63,8 +64,7 @@ static inline void intel_logical_ring_advance(struct intel_ringbuffer *ringbuf) static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf, u32 data) { - iowrite32(data, ringbuf->virtual_start + ringbuf->tail); - ringbuf->tail += 4; + intel_ringbuffer_emit(ringbuf, data); } /* Logical Ring Contexts */ diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 49aa52440db2..0eaaab92dea0 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2180,13 +2180,8 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n) static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) { - uint32_t __iomem *virt; int rem = ringbuf->size - ringbuf->tail; - - virt = ringbuf->virtual_start + ringbuf->tail; - rem /= 4; - while (rem--) - iowrite32(MI_NOOP, virt++); + memset(ringbuf->virtual_start + ringbuf->tail, 0, rem); ringbuf->tail = 0; intel_ring_update_space(ringbuf); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 2e85fda94963..ff290765e6c9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -427,17 +427,24 @@ int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request); int __must_check intel_ring_begin(struct drm_i915_gem_request *req, int n); int __must_check intel_ring_cacheline_align(struct drm_i915_gem_request *req); +static inline void intel_ringbuffer_emit(struct intel_ringbuffer *rb, +u32 data) +{ + *(uint32_t __force *)(rb->virtual_start + rb->tail) = data; + rb->tail += 4; +} +static inline void intel_ringbuffer_advance(struct intel_ringbuffer *rb) +{ + rb->tail &= rb->size - 1; +} static inline void intel_ring_emit(struct intel_engine_cs *ring, u32 data) { - struct intel_ringbuffer *ringbuf = ring->buffer; - iowrite32(data, ringbuf->virtual_start + ringbuf->tail); - ringbuf->tail += 4; + intel_ringbuffer_emit(ring->buffer, data); } static inline void intel_ring_advance(struct intel_engine_cs *ring) { - struct intel_ringbuffer *ringbuf = ring->buffer; - ringbuf->tail &= ringbuf->size - 1; + intel_ringbuffer_advance(ring->buffer); } int __intel_ring_space(int head, int tail, int size); void intel_ring_update_space(struct intel_ringbuffer *ringbuf); -- 2.6.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: 4K audio N value incorrect at 29.97 and 23.98 refresh rate
On Thu, Oct 08, 2015 at 03:39:26PM +0300, Jani Nikula wrote: > On Thu, 08 Oct 2015, Ville Syrjäläwrote: > > On Wed, Oct 07, 2015 at 02:38:29PM -0700, clinton.a.tay...@intel.com wrote: > >> From: Clint Taylor > >> > >> The TMDS_296M define was computing as 296704 but the mode->clock is > >> 296700 as defined by EDID. Adjusted define to allow correct detection > >> of the need to program the correct N value for 29.97 and 23.98 refresh > >> rate. > >> > >> Signed-off-by: Clint Taylor > >> --- > >> drivers/gpu/drm/i915/intel_audio.c |2 +- > >> 1 file changed, 1 insertion(+), 1 deletion(-) > >> > >> diff --git a/drivers/gpu/drm/i915/intel_audio.c > >> b/drivers/gpu/drm/i915/intel_audio.c > >> index 56c2f54..419c979 100644 > >> --- a/drivers/gpu/drm/i915/intel_audio.c > >> +++ b/drivers/gpu/drm/i915/intel_audio.c > >> @@ -75,7 +75,7 @@ static const struct { > >> > >> /* HDMI N/CTS table */ > >> #define TMDS_297M 297000 > >> -#define TMDS_296M DIV_ROUND_UP(297000 * 1000, 1001) > >> +#define TMDS_296M 296700 > > > > Hmm. I think we might want to fix up the mode instead. Let me post a few > > patches, and let's see what people think... > > We might actually want to queue this up for v4.3 as the immediate fix, > as I feel it's doubtful your other patches will make it to v4.3. > > If Someone(tm) provided their r-b that is. Except this is wrong if the mode came from the CEA/HDMI mode list as opposed from the EDID detailed timings. -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v4] drm/i915: Clean up associated VMAs on context destruction
Hi, On 08/10/15 14:45, Ville Syrjälä wrote: On Mon, Oct 05, 2015 at 01:26:36PM +0100, Tvrtko Ursulin wrote: From: Tvrtko UrsulinPrevent leaking VMAs and PPGTT VMs when objects are imported via flink. Scenario is that any VMAs created by the importer will be left dangling after the importer exits, or destroys the PPGTT context with which they are associated. This is caused by object destruction not running when the importer closes the buffer object handle due the reference held by the exporter. This also leaks the VM since the VMA has a reference on it. In practice these leaks can be observed by stopping and starting the X server on a kernel with fbcon compiled in. Every time X server exits another VMA will be leaked against the fbcon's frame buffer object. Also on systems where flink buffer sharing is used extensively, like Android, this leak has even more serious consequences. This version is takes a general approach from the earlier work by Rafael Barbalho (drm/i915: Clean-up PPGTT on context destruction) and tries to incorporate the subsequent discussion between Chris Wilson and Daniel Vetter. v2: Removed immediate cleanup on object retire - it was causing a recursive VMA unbind via i915_gem_object_wait_rendering. And it is in fact not even needed since by definition context cleanup worker runs only after the last context reference has been dropped, hence all VMAs against the VM belonging to the context are already on the inactive list. v3: Previous version could deadlock since VMA unbind waits on any rendering on an object to complete. Objects can be busy in a different VM which would mean that the cleanup loop would do the wait with the struct mutex held. This is an even simpler approach where we just unbind VMAs without waiting since we know all VMAs belonging to this VM are idle, and there is nothing in flight, at the point context destructor runs. v4: Double underscore prefix for __915_vma_unbind_no_wait and a commit message typo fix. (Michel Thierry) Signed-off-by: Tvrtko Ursulin Testcase: igt/gem_ppgtt.c/flink-and-exit-vma-leak Reviewed-by: Michel Thierry Cc: Daniel Vetter Cc: Chris Wilson Cc: Rafael Barbalho Cc: Michel Thierry --- drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_gem.c | 20 drivers/gpu/drm/i915/i915_gem_context.c | 24 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 824e7245044d..58afa1bb2957 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2840,6 +2840,11 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags); int __must_check i915_vma_unbind(struct i915_vma *vma); +/* + * BEWARE: Do not use the function below unless you can _absolutely_ + * _guarantee_ VMA in question is _not in use_ anywhere. + */ +int __must_check __i915_vma_unbind_no_wait(struct i915_vma *vma); int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); void i915_gem_release_mmap(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f0cfbb9ee12c..52642aff1dab 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3208,7 +3208,7 @@ static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj) old_write_domain); } -int i915_vma_unbind(struct i915_vma *vma) +static int __i915_vma_unbind(struct i915_vma *vma, bool wait) { struct drm_i915_gem_object *obj = vma->obj; struct drm_i915_private *dev_priv = obj->base.dev->dev_private; @@ -3227,9 +3227,11 @@ int i915_vma_unbind(struct i915_vma *vma) BUG_ON(obj->pages == NULL); - ret = i915_gem_object_wait_rendering(obj, false); - if (ret) - return ret; + if (wait) { + ret = i915_gem_object_wait_rendering(obj, false); + if (ret) + return ret; + } if (i915_is_ggtt(vma->vm) && vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) { @@ -3274,6 +3276,16 @@ int i915_vma_unbind(struct i915_vma *vma) return 0; } +int i915_vma_unbind(struct i915_vma *vma) +{ + return __i915_vma_unbind(vma, true); +} + +int __i915_vma_unbind_no_wait(struct i915_vma *vma) +{ + return __i915_vma_unbind(vma, false); +} + int i915_gpu_idle(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c
Re: [Intel-gfx] [PATCH 2/3] drm/i915: Refactor duplicate object vmap functions
On Thu, Oct 08, 2015 at 01:39:55PM +0100, Chris Wilson wrote: > We now have two implementations for vmapping a whole object, one for > dma-buf and one for the ringbuffer. If we couple the vmapping into the > obj->pages lifetime, then we can reuse an obj->vmapping for both and at > the same time couple it into the shrinker. > > Signed-off-by: Chris Wilson> --- > drivers/gpu/drm/i915/i915_drv.h | 12 --- > drivers/gpu/drm/i915/i915_gem.c | 41 > drivers/gpu/drm/i915/i915_gem_dmabuf.c | 55 > + > drivers/gpu/drm/i915/intel_ringbuffer.c | 53 ++- > 4 files changed, 72 insertions(+), 89 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 4093eedfd664..343a0a723d2c 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -2089,10 +2089,7 @@ struct drm_i915_gem_object { > struct scatterlist *sg; > int last; > } get_page; > - > - /* prime dma-buf support */ > - void *dma_buf_vmapping; > - int vmapping_count; > + void *vmapping; > > /** Breadcrumb of last rendering to the buffer. >* There can only be one writer, but we allow for multiple readers. > @@ -2840,12 +2837,19 @@ static inline void i915_gem_object_pin_pages(struct > drm_i915_gem_object *obj) > BUG_ON(obj->pages == NULL); > obj->pages_pin_count++; > } > + > static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object > *obj) > { > BUG_ON(obj->pages_pin_count == 0); > obj->pages_pin_count--; > } > > +void *__must_check i915_gem_object_pin_vmap(struct drm_i915_gem_object *obj); > +static inline void i915_gem_object_unpin_vmap(struct drm_i915_gem_object > *obj) > +{ > + i915_gem_object_unpin_pages(obj); > +} > + > int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); > int i915_gem_object_sync(struct drm_i915_gem_object *obj, >struct intel_engine_cs *to, > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index 78640aecf86d..446cf0662a38 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -2159,6 +2159,11 @@ i915_gem_object_put_pages(struct drm_i915_gem_object > *obj) > ops->put_pages(obj); > obj->pages = NULL; > > + if (obj->vmapping) { > + vunmap(obj->vmapping); > + obj->vmapping = NULL; > + } > + > i915_gem_object_invalidate(obj); > > return 0; > @@ -2325,6 +2330,42 @@ i915_gem_object_get_pages(struct drm_i915_gem_object > *obj) > return 0; > } > > +void *i915_gem_object_pin_vmap(struct drm_i915_gem_object *obj) > +{ > + int ret; > + > + ret = i915_gem_object_get_pages(obj); > + if (ret) > + return ERR_PTR(ret); > + > + i915_gem_object_pin_pages(obj); > + > + if (obj->vmapping == NULL) { > + struct sg_page_iter sg_iter; > + struct page **pages; > + int n; > + > + n = obj->base.size >> PAGE_SHIFT; > + pages = kmalloc(n*sizeof(*pages), GFP_TEMPORARY); Random driveby: kmalloc_array() Also __GFP_NOWARN? I wonder if the drm_malloc stuff should do the kmalloc attempt regardless fo the size, so we wouldn't have to do it here? > + if (pages == NULL) > + pages = drm_malloc_ab(n, sizeof(*pages)); > + if (pages != NULL) { > + n = 0; > + for_each_sg_page(obj->pages->sgl, _iter, > obj->pages->nents, 0) > + pages[n++] = sg_page_iter_page(_iter); > + > + obj->vmapping = vmap(pages, n, 0, PAGE_KERNEL); > + drm_free_large(pages); > + } > + if (obj->vmapping == NULL) { > + i915_gem_object_unpin_pages(obj); > + return ERR_PTR(-ENOMEM); > + } > + } > + > + return obj->vmapping; > +} > + > void i915_vma_move_to_active(struct i915_vma *vma, >struct drm_i915_gem_request *req) > { -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH RESEND 1/3] drm/i915: use error path
Use goto to handle the error path to avoid duplicating the same code. In the error path intel_dig_port is the last one to be released as it was the first one to be allocated and ideally the error path should be the reverse of the execution path. Cc: Daniel VetterCc: Jani Nikula Signed-off-by: Sudip Mukherjee --- Sent on 27/07/2015 drivers/gpu/drm/i915/intel_dp.c | 23 ++- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8d34ca7..18bcfbe 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -6168,10 +6168,8 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) return; intel_connector = intel_connector_alloc(); - if (!intel_connector) { - kfree(intel_dig_port); - return; - } + if (!intel_connector) + goto err_connector_alloc; intel_encoder = _dig_port->base; encoder = _encoder->base; @@ -6219,11 +6217,18 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; dev_priv->hotplug.irq_port[port] = intel_dig_port; - if (!intel_dp_init_connector(intel_dig_port, intel_connector)) { - drm_encoder_cleanup(encoder); - kfree(intel_dig_port); - kfree(intel_connector); - } + if (!intel_dp_init_connector(intel_dig_port, intel_connector)) + goto err_init_connector; + + return; + +err_init_connector: + drm_encoder_cleanup(encoder); + kfree(intel_connector); +err_connector_alloc: + kfree(intel_dig_port); + + return; } void intel_dp_mst_suspend(struct drm_device *dev) -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 5/6] drm/i915: Support for pread/pwrite from/to non shmem backed objects
Hi, On 08/10/15 07:24, ankitprasad.r.sha...@intel.com wrote: From: Ankitprasad SharmaThis patch adds support for extending the pread/pwrite functionality for objects not backed by shmem. The access will be made through gtt interface. This will cover prime objects as well as stolen memory backed objects but for userptr objects it is still forbidden. Where is the part which forbids it for userptr objects? v2: Drop locks around slow_user_access, prefault the pages before access (Chris) v3: Rebased to the latest drm-intel-nightly (Ankit) v4: Moved page base & offset calculations outside the copy loop, corrected data types for size and offset variables, corrected if-else braces format (Tvrtko/kerneldocs) v5: Enabled pread/pwrite for all non-shmem backed objects including without tiling restrictions (Ankit) v6: Using pwrite_fast for non-shmem backed objects as well (Chris) Testcase: igt/gem_stolen Signed-off-by: Ankitprasad Sharma --- drivers/gpu/drm/i915/i915_gem.c | 125 +--- 1 file changed, 104 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 91a2e97..2c94e22 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -614,6 +614,99 @@ shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length, return ret ? - EFAULT : 0; } +static inline uint64_t +slow_user_access(struct io_mapping *mapping, +uint64_t page_base, int page_offset, +char __user *user_data, +int length, bool pwrite) +{ + void __iomem *vaddr_inatomic; + void *vaddr; + uint64_t unwritten; + + vaddr_inatomic = io_mapping_map_wc(mapping, page_base); + /* We can use the cpu mem copy function because this is X86. */ + vaddr = (void __force *)vaddr_inatomic + page_offset; + if (pwrite) + unwritten = __copy_from_user(vaddr, user_data, length); + else + unwritten = __copy_to_user(user_data, vaddr, length); + + io_mapping_unmap(vaddr_inatomic); + return unwritten; +} + +static int +i915_gem_gtt_pread(struct drm_device *dev, + struct drm_i915_gem_object *obj, uint64_t size, + uint64_t data_offset, uint64_t data_ptr) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + char __user *user_data; + uint64_t remain; + uint64_t offset, page_base; + int page_offset, page_length, ret = 0; + + ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE); + if (ret) + goto out; + + ret = i915_gem_object_set_to_gtt_domain(obj, false); + if (ret) + goto out_unpin; + + ret = i915_gem_object_put_fence(obj); + if (ret) + goto out_unpin; + + user_data = to_user_ptr(data_ptr); + remain = size; + offset = i915_gem_obj_ggtt_offset(obj) + data_offset; + + mutex_unlock(>struct_mutex); + if (likely(!i915.prefault_disable)) + ret = fault_in_multipages_writeable(user_data, remain); + + /* +* page_offset = offset within page +* page_base = page offset within aperture +*/ + page_offset = offset_in_page(offset); + page_base = offset & PAGE_MASK; + + while (remain > 0) { + /* page_length = bytes to copy for this page */ + page_length = remain; + if ((page_offset + remain) > PAGE_SIZE) + page_length = PAGE_SIZE - page_offset; + + /* This is a slow read/write as it tries to read from +* and write to user memory which may result into page +* faults +*/ + ret = slow_user_access(dev_priv->gtt.mappable, page_base, + page_offset, user_data, + page_length, false); + + if (ret) { + ret = -EFAULT; + break; + } + + remain -= page_length; + user_data += page_length; + page_base += page_length; + page_offset = 0; + } + + mutex_lock(>struct_mutex); + +out_unpin: + i915_gem_object_ggtt_unpin(obj); +out: + return ret; +} + static int i915_gem_shmem_pread(struct drm_device *dev, struct drm_i915_gem_object *obj, @@ -737,17 +830,14 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, goto out; } - /* prime objects have no backing filp to GEM pread/pwrite -* pages from. -*/ - if (!obj->base.filp) { - ret = -EINVAL; - goto out; - } - trace_i915_gem_object_pread(obj, args->offset, args->size); - ret =
[Intel-gfx] [PATCH RESEND 2/3] drm/i915: check for return value
We were not checking the return value of drm_encoder_init() which can fail. And if it fails then we will be working with an uninitialized encoder. Cc: Daniel VetterCc: Jani Nikula Signed-off-by: Sudip Mukherjee --- Sent on 27/07/2015 drivers/gpu/drm/i915/intel_dp.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 18bcfbe..2a8b47e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -6174,8 +6174,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) intel_encoder = _dig_port->base; encoder = _encoder->base; - drm_encoder_init(dev, _encoder->base, _dp_enc_funcs, -DRM_MODE_ENCODER_TMDS); + if (drm_encoder_init(dev, _encoder->base, _dp_enc_funcs, +DRM_MODE_ENCODER_TMDS)) + goto err_encoder_init; intel_encoder->compute_config = intel_dp_compute_config; intel_encoder->disable = intel_disable_dp; @@ -6224,6 +6225,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) err_init_connector: drm_encoder_cleanup(encoder); +err_encoder_init: kfree(intel_connector); err_connector_alloc: kfree(intel_dig_port); -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/5] drm/i915: Notify user about outdated dmc firmware
On 10/8/2015 5:53 PM, Mika Kuoppala wrote: Animesh Mannawrites: On 9/21/2015 2:00 PM, Mika Kuoppala wrote: Jani Nikula writes: On Fri, 18 Sep 2015, Mika Kuoppala wrote: If csr/dmc firmware is known to be outdated, notify user. What would break if we requested a firmware version that works? Or we've made it so that we only request the major version because there's not supposed to be changes like this between minor versions...? I guess the question is more of a what should we do if there is only outdated (known bad) firmware available. Refuse to load and limb onwards, or return with error code on driver init. Latter would force firmware and version to be mandatory and the version to be tightly coupled to kernel driver version. A softlink is used to use recommended firmware for dmc and the same information is published through 01.org for the firmware user. Imo, we should not have this kind of hack in code which will change over time and this is responsibility of repo-owner to link correct recommended firmware for new kernel update. On machines that had 1.19 symlinked, in filesystem, execlist submission sometimes broke due to interrupt delivery problem. To reach a conclusion that it was csr firmware, before 1.21 was out, took quite amount of work. I bet there are still machines with 1.19 only, and we get to wade through error states trying to connect the dots. The dmc/csr firmware is part of our driver functionality. Apparently it is very tightly coupled to our driver functionality as it can break things outside of its own domain. And currently it is loosely coupled black box with our driver, through symlink, accepting any version that happens to be in customers filesystem. So we recommend latest in website and end up in a situation that user gets what happens to be in filesystem. Even a known broken version? And we will keep debugging these problems caused by broken version? I don't want any more dimensions in our triaging space, the distributio/firmware version dimension. Symlink also means that bisectability is very close to worthless on these kind of bugs. Both in our machines and also on customers. We have loosely coupled, black box entity, affecting our driver depending on customers filesystem. Symlink threw that valuable tool out, and we gained what? So we are left with triaging. Which is true detective work as there are no traces of firmware versions nor loading success/fails on logs/error states. From where I look at, the version blacklist is not a hack. It is a cure. I completely understand your concern and we discussed a lot on same during firmware naming convention and finally decided to have symlink. If we really want to tightly couple firmware and driver then imo putting exact firmware name will be better option. Next I saw your subsequent patch where you are not loading the firmware if it is older than 1.21. http://lists.freedesktop.org/archives/intel-gfx/2015-September/076422.html Curious to know the gpu-hang issue present for any version less than 1.21. -Animesh -Mika -Animesh -Mika BR, Jani. Signed-off-by: Mika Kuoppala --- drivers/gpu/drm/i915/intel_csr.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 58edc3f..73807c3 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -45,6 +45,9 @@ MODULE_FIRMWARE(I915_CSR_SKL); +#define RECOMMENDED_FW_MAJOR 1 +#define RECOMMENDED_FW_MINOR 21 + /* * SKL CSR registers for DC5 and DC6 */ @@ -387,6 +390,12 @@ static void finish_csr_load(const struct firmware *fw, void *context) DRM_DEBUG_KMS("Finished loading %s v%u.%u\n", dev_priv->csr.fw_path, csr->dmc_ver_major, csr->dmc_ver_minor); + + if (csr->dmc_ver_major < RECOMMENDED_FW_MAJOR || + csr->dmc_ver_minor < RECOMMENDED_FW_MINOR) + DRM_INFO("Outdated dmc firmware found, please upgrade to %u.%u or newer\n", +RECOMMENDED_FW_MAJOR, RECOMMENDED_FW_MINOR); + out: if (fw_loaded) intel_runtime_pm_put(dev_priv); -- 2.1.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Jani Nikula, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping
On 10/08/2015 02:07 AM, Chris Wilson wrote: > On Wed, Oct 07, 2015 at 11:34:17AM -0700, Wayne Boyer wrote: >> From: Chris Wilson>> >> A long time ago (before 3.14) we relied on a permanent pinning of the >> ifbdev to lock the fb in place inside the GGTT. However, the >> introduction of stealing the BIOS framebuffer and reusing its address in >> the GGTT for the fbdev has muddied waters and we use an inherited fb. >> However, the inherited fb is only pinned whilst it is active and we no >> longer have an explicit pin for the info->system_base mmapping used by >> the fbdev. The result is that after some aperture pressure the fbdev may >> be evicted, but we continue to write the fbcon into the same GGTT >> address - overwriting anything else that may be put into that offset. >> The effect is most pronounced across suspend/resume as >> intel_fbdev_set_suspend() does a full clear over the whole scanout. >> >> v2: rebased on latest nightly (Wayne) >> >> Signed-off-by: Chris Wilson >> Cc: "Goel, Akash" >> Cc: Daniel Vetter >> Cc: Jesse Barnes >> Cc: sta...@vger.kernel.org >> Reviewed-by: Deepak S >> Signed-off-by: Wayne Boyer >> --- >> drivers/gpu/drm/i915/intel_fbdev.c | 15 +++ >> 1 file changed, 15 insertions(+) >> >> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c >> b/drivers/gpu/drm/i915/intel_fbdev.c >> index 6532912..c6aa4f9 100644 >> --- a/drivers/gpu/drm/i915/intel_fbdev.c >> +++ b/drivers/gpu/drm/i915/intel_fbdev.c >> @@ -215,6 +215,16 @@ static int intelfb_create(struct drm_fb_helper *helper, >> obj = intel_fb->obj; >> size = obj->base.size; >> >> +/* The fb constructor will have already pinned us (or inherited a >> + * GGTT region from the BIOS) suitable for a scanout, so >> + * this should just be a no-op and increment the pin count for the >> + * fbdev mmapping. It does have a useful side-effect of validating >> + * the pin for fbdev's use via a GGTT mmapping. >> + */ >> +ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PIN_MAPPABLE); > > This should be i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE); > At which point I just rage quit. LOL GEM naming strikes again! Jesse ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Remove wrong warning from i915_gem_context_clean
On 10/8/2015 3:37 PM, Tvrtko Ursulin wrote: From: Tvrtko Ursulincommit e9f24d5fb7cf3628b195b18ff3ac4e37937ceeae Author: Tvrtko Ursulin Date: Mon Oct 5 13:26:36 2015 +0100 drm/i915: Clean up associated VMAs on context destruction Introduced a wrong assumption that all contexts have a ppgtt instance. This is not true when full PPGTT is not active so remove the WARN_ON_ONCE from the context cleanup code. Aliasing ppgtt? (for the record, I tried with enable_ppgtt=1 while reviewing the patch and didn't see the warning... maybe I didn't try hard enough). Signed-off-by: Tvrtko Ursulin Cc: Michel Thierry --- drivers/gpu/drm/i915/i915_gem_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 680b4c9f6b73..8c688a5f1589 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -138,7 +138,7 @@ static void i915_gem_context_clean(struct intel_context *ctx) struct i915_hw_ppgtt *ppgtt = ctx->ppgtt; struct i915_vma *vma, *next; - if (WARN_ON_ONCE(!ppgtt)) + if (!ppgtt) return; WARN_ON(!list_empty(>base.active_list)); Reviewed-by: Michel Thierry ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] periodic wakeup from DPMS suspend
On Thu, Oct 08, 2015 at 12:44:09PM +0200, Johannes Stezenbach wrote: > On Wed, Oct 07, 2015 at 01:26:32PM +0200, Johannes Stezenbach wrote: > > On Tue, Oct 06, 2015 at 11:04:53PM -0400, Alex Deucher wrote: > > > On Tue, Oct 6, 2015 at 11:10 AM, Johannes Stezenbach> > > wrote: > > > > > > > > I have a NEC EA244WMi monitor connected to an Asus P8H77-V > > > > mainboard with Ivy Bridge Core i5-3550 via DVI. > > > > If DPMS suspend is enabled (by xscreensaver, or for testing by > > > > "xset dpms force off/suspend/standby"), the monitor > > > > enters standby mode but wakes up every 10...30 seconds for > > > > 6 seconds to display a "DVI-D: no signal" message. > > > > > > Some monitors periodically scan all of their inputs if they are not > > > actively being driven by anything to try and automatically switch to > > > the connected input. When the monitor scans the DVI input, it sees > > > load on the pins and turns on, only to realize it's not getting a > > > signal and then turns off. If your monitor has an option to turn off > > > input probing, that might help. > > > > It's not like I didn't try to twiddle just about every > > available menu item, and also used the monitor's > > "Reset to Factory Defaults" to no avail. > > However, while trying again I found a hidden menu item > > which is only available during the short time the > > "No Signal" message is displayed, where the left/right > > touch buttons open a "Scan Time" setting with "Normal" > > and "Slow" options. After I changed it, the issue was > > solved. I changed it back and the issue doesn't reproduce. > > So it looks some internal configuration of the monitor > > was messed up and is now fixed by twiddling the hidden > > menu item. "Scan Time" is not documented in the manual > > nor is there an indication in the "No Signal" popup. > > > > Case closed. > > And I just came back to see the monitor doing the > wakeup cycling again. To try something differerent > I unplugged the charger of the laptop sitting nearby > in suspend. Bingo! So it looks like an EMI issue. > I tried a few times and could reproduce twice and > then no more :-( Now the monitor wakes up once > every 5min or so... > > Which brings me back to a previous question: > > > maybe it is some floating signal line causing the > > monitor to misdetect activity? > > Does the Intel hardware have the capability to switch > the DVI signal lines from high-z to ground during DPMS > suspend, and if so, does the driver do the right thing? > Obviously I have no clue about DVI and intel-gfx, but > I thought to ask anyway. We have already known fun with EMI from laptop chargers: i915 hase a hotpug storm detection logic to combat badly-shielded boards. Could just be another form of that problem. Afaik there's nothing we can do in the driver about this (except trying to filter out bad noise, which we do already). -Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/9] drm/i915: driver based PASID handling
On Fri, Sep 04, 2015 at 09:59:00AM -0700, Jesse Barnes wrote: > New file with VT-d SVM and PASID handling functions and page table > management. This belongs in the IOMMU code (along with some extra bits > for waiting for invalidations and page faults to complete, flushing the > device IOTLB, etc.) > > FIXME: > need work queue for re-submitting contexts > TE bit handling on SKL > --- > drivers/gpu/drm/i915/Makefile |5 +- > drivers/gpu/drm/i915/i915_drv.h | 43 ++ > drivers/gpu/drm/i915/i915_gem.c |3 + > drivers/gpu/drm/i915/i915_gem_context.c |3 + > drivers/gpu/drm/i915/i915_irq.c |7 + > drivers/gpu/drm/i915/i915_reg.h | 47 ++ > drivers/gpu/drm/i915/i915_svm.c | 1102 > +++ > drivers/gpu/drm/i915/intel_lrc.c| 120 +++- > drivers/gpu/drm/i915/intel_lrc.h|1 + > 9 files changed, 1299 insertions(+), 32 deletions(-) > create mode 100644 drivers/gpu/drm/i915/i915_svm.c > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index 44d290a..e4883a7 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -38,7 +38,8 @@ i915-y += i915_cmd_parser.o \ > intel_lrc.o \ > intel_mocs.o \ > intel_ringbuffer.o \ > - intel_uncore.o > + intel_uncore.o \ > + i915_svm.o Correct me if I am wrong, but it looks like i915_svm implements the lowlevel interface with the hardware, so by convention is intel_svm.c > # general-purpose microcontroller (GuC) support > i915-y += intel_guc_loader.o \ > @@ -93,6 +94,8 @@ i915-y += dvo_ch7017.o \ > # virtual gpu code > i915-y += i915_vgpu.o > > +i915-$(CONFIG_MMU_NOTIFIER) += i915_svm.o Added twice? > + > # legacy horrors > i915-y += i915_dma.o > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 20beb51..ca38a7a 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -47,6 +47,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -848,6 +849,13 @@ struct i915_ctx_hang_stats { > bool banned; > }; > > +struct intel_mm_struct { > + struct kref kref; > + struct mmu_notifier notifier; > + struct drm_i915_private *dev_priv; > + struct list_head context_list; > +}; Doesn't this look kind of familiar? struct i915_mm_struct perhaps? > + > /* This must match up with the value previously used for execbuf2.rsvd1. */ > #define DEFAULT_CONTEXT_HANDLE 0 > > @@ -874,6 +882,9 @@ struct i915_ctx_hang_stats { > struct intel_context { > struct kref ref; > int user_handle; > + bool is_svm; /* shares x86 page tables */ > + u32 pasid; /* 20 bits */ > + struct intel_mm_struct *ims; > uint8_t remap_slice; > struct drm_i915_private *i915; > int flags; > @@ -895,6 +906,9 @@ struct intel_context { > int pin_count; > } engine[I915_NUM_RINGS]; > > + struct list_head mm_list; This is a link, name it so. > + struct task_struct *tsk; One task? A context can be passed by the device fd to another process. Do we inherit the VM along with the context? I don't anything to prevent such. > +static void gpu_mm_segv(struct task_struct *tsk, unsigned long address, > + int si_code) > +{ > + siginfo_t info; > + > + /* Need specific signal info here */ > + info.si_signo = SIGSEGV; > + info.si_errno = EIO; > + info.si_code= si_code; > + info.si_addr= (void __user *)address; > + > + force_sig_info(SIGSEGV, , tsk); force_sig_info() is not exported, ah you builtin i915-svm.c > +} > + > +/* > + * Read the fault descriptor and handle the fault: > + * get PML4 from PASID > + * get mm struct > + * get the vma > + * verify the address is valid > + * call handle_mm_fault after taking the mm->mmap_sem > + */ > +void intel_gpu_fault_work(struct work_struct *work) > +{ > + struct i915_svm_state *svm = container_of(work, struct i915_svm_state, > + work); > + struct drm_i915_private *dev_priv = > + container_of(svm, struct drm_i915_private, svm); > + struct drm_device *dev = dev_priv->dev; > + struct intel_ringbuffer *ringbuf; > + struct page_request_dsc desc; > + struct page_group_response_dsc resp; > + struct intel_context *ctx; > + struct task_struct *tsk; > + struct mm_struct *mm; > + struct vm_area_struct *vma; > + u64 address; > + int ret; > + > + DRM_ERROR("PRQ updated, head 0x%08x, tail 0x%08x\n", > + I915_READ(SVM_PRQ_HEAD), I915_READ(SVM_PRQ_TAIL)); > + prq_read_descriptor(dev, ); > + DRM_ERROR("page fault on addr 0x%016llx, PASID %d, srr %d\n", > + (u64)(desc.addr << PAGE_SHIFT), desc.pasid, desc.srr); > + > + spin_lock(_priv->svm.lock); > + ctx =
Re: [Intel-gfx] [PATCH 1/5] drm/i915: Store and print dmc firmware version
On Thu, Oct 08, 2015 at 12:03:30PM +0100, Damien Lespiau wrote: > The DMC firmware version decoding was different in my patch and I'm sure > it worked then. Maye the header has changed :( By the way, if this is indeed the case, could you fix intel_firmware_decode as well? http://cgit.freedesktop.org/xorg/app/intel-gpu-tools/tree/tools/intel_firmware_decode.c Thanks, -- Damien ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915: Remove wrong warning from i915_gem_context_clean
From: Tvrtko Ursulincommit e9f24d5fb7cf3628b195b18ff3ac4e37937ceeae Author: Tvrtko Ursulin Date: Mon Oct 5 13:26:36 2015 +0100 drm/i915: Clean up associated VMAs on context destruction Introduced a wrong assumption that all contexts have a ppgtt instance. This is not true when full PPGTT is not active so remove the WARN_ON_ONCE from the context cleanup code. Signed-off-by: Tvrtko Ursulin Cc: Michel Thierry --- drivers/gpu/drm/i915/i915_gem_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 680b4c9f6b73..8c688a5f1589 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -138,7 +138,7 @@ static void i915_gem_context_clean(struct intel_context *ctx) struct i915_hw_ppgtt *ppgtt = ctx->ppgtt; struct i915_vma *vma, *next; - if (WARN_ON_ONCE(!ppgtt)) + if (!ppgtt) return; WARN_ON(!list_empty(>base.active_list)); -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 4/6] drm/i915: Add support for stealing purgable stolen pages
On Thu, Oct 08, 2015 at 03:31:08PM +0100, Tvrtko Ursulin wrote: > > On 08/10/15 12:09, Chris Wilson wrote: > >On Thu, Oct 08, 2015 at 11:43:29AM +0100, Tvrtko Ursulin wrote: > >>>-struct drm_i915_gem_object * > >>>-i915_gem_object_create_stolen(struct drm_device *dev, u64 size) > >>>+static bool > >>>+mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind) > >>>+{ > >>>+ BUG_ON(obj->stolen == NULL); > >> > >>I am fundamentally opposed to BUG_ONs which can be avoided. In this > >>I see no value in hanging the machine while we could WARN_ON and > >>return false. > > > >Don't bother with the WARN_ON. Either take the BUG_ON or accept that to > >get to this point the machine is dead anyway and a warning here doesn't > >help identify the root cause (better off with list debugging and memory > >debugging). I have personally been converting these asserts over to a > >dev-only compiletime option as I still find the BUGs more useful than > >WARNs in the GEM code. > > This is one of the ones which are to be expected in development > only. At that time I much prefer a WARN_ON since it potentially > saves you one reboot cycle and there aren't really any downsides to > it. Especially if, as you say, machine is dead already. panic-on-oops ftw :-p -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/2] drm/i915: Call encoder hotplug for init and resume cases
On Thu, 08 Oct 2015, Ville Syrjäläwrote: > On Mon, Oct 05, 2015 at 04:43:14PM +0530, Sonika Jindal wrote: >> For all the encoders, call the hot_plug if it is registered. >> This is required for connected boot and resume cases to generate >> fake hpd resulting in reading of edid. >> Removing the initial sdvo hot_plug call too so that it will be called >> just once from this loop. >> >> Signed-off-by: Sonika Jindal >> --- >> drivers/gpu/drm/i915/intel_hotplug.c | 11 +++ >> drivers/gpu/drm/i915/intel_sdvo.c|1 - >> 2 files changed, 11 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/gpu/drm/i915/intel_hotplug.c >> b/drivers/gpu/drm/i915/intel_hotplug.c >> index 53c0173..eac4757 100644 >> --- a/drivers/gpu/drm/i915/intel_hotplug.c >> +++ b/drivers/gpu/drm/i915/intel_hotplug.c >> @@ -458,6 +458,7 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) >> { >> struct drm_device *dev = dev_priv->dev; >> struct drm_mode_config *mode_config = >mode_config; >> +struct intel_encoder *encoder; >> struct drm_connector *connector; >> int i; >> >> @@ -482,6 +483,16 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) >> if (dev_priv->display.hpd_irq_setup) >> dev_priv->display.hpd_irq_setup(dev); >> spin_unlock_irq(_priv->irq_lock); >> + >> +/* >> + * Connected boot / resume scenarios can't generate new hot plug. >> + * So, probe it manually. >> + */ >> +list_for_each_entry(encoder, >mode_config.encoder_list, >> +base.head) { >> +if (encoder->hot_plug) >> +encoder->hot_plug(encoder); >> +} > > > This breaks the world on CHV Also patch 2/2 breaks: https://bugs.freedesktop.org/show_bug.cgi?id=88081 BR, Jani. > > [ 3187.575198] [drm:intel_hdmi_hot_plug] Live status not up! > [ 3187.585154] = > [ 3187.595010] [ INFO: possible recursive locking detected ] > [ 3187.604685] 4.3.0-rc4-bsw+ #2488 Tainted: G U W > [ 3187.614366] - > [ 3187.623892] Xorg/32212 is trying to acquire lock: > [ 3187.632635] (_domains->lock){+.+...}, at: [] > intel_display_power_get+0x38/0xcb [i915] > [ 3187.647492] > [ 3187.647492] but task is already holding lock: > [ 3187.661054] (_domains->lock){+.+...}, at: [] > intel_display_power_get+0x38/0xcb [i915] > [ 3187.675960] > [ 3187.675960] other info that might help us debug this: > [ 3187.690459] Possible unsafe locking scenario: > [ 3187.690459] > [ 3187.704224]CPU0 > [ 3187.710485] > [ 3187.716711] lock(_domains->lock); > [ 3187.724718] lock(_domains->lock); > [ 3187.732663] > [ 3187.732663] *** DEADLOCK *** > [ 3187.732663] > [ 3187.749460] May be due to missing lock nesting notation > [ 3187.749460] > [ 3187.763833] 5 locks held by Xorg/32212: > [ 3187.771523] #0: (drm_global_mutex){+.+.+.}, at: [] > drm_release+0x3b/0x49b [drm] > [ 3187.785216] #1: (>mode_config.mutex){+.+.+.}, at: > [] drm_modeset_lock_all+0x54/0xcd [drm] > [ 3187.800437] #2: (crtc_ww_class_acquire){+.+.+.}, at: > [] drm_modeset_lock_all+0x5e/0xcd [drm] > [ 3187.815488] #3: (crtc_ww_class_mutex){+.+.+.}, at: [] > drm_modeset_lock+0x75/0xfc [drm] > [ 3187.830094] #4: (_domains->lock){+.+...}, at: [] > intel_display_power_get+0x38/0xcb [i915] > [ 3187.845534] > [ 3187.845534] stack backtrace: > [ 3187.857685] CPU: 2 PID: 32212 Comm: Xorg Tainted: G U W > 4.3.0-rc4-bsw+ #2488 > [ 3187.870331] Hardware name: Intel Corporation CHERRYVIEW C0 > PLATFORM/Braswell CRB, BIOS BRAS.X64.B085.R00.1509110553 09/11/2015 > [ 3187.886827] 880175eff8e0 8128d59e > 823f5ee0 > [ 3187.898904] 880175eff958 810a7a08 > 880179d1c5d0 > [ 3187.910954] 0004 0006 45422a91588a4c3e > 0005 > [ 3187.923011] Call Trace: > [ 3187.929451] [] dump_stack+0x4e/0x79 > [ 3187.938912] [] __lock_acquire+0x7ab/0x12af > [ 3187.949027] [] lock_acquire+0x10e/0x1a9 > [ 3187.958859] [] ? intel_display_power_get+0x38/0xcb > [i915] > [ 3187.970476] [] ? intel_display_power_get+0x38/0xcb > [i915] > [ 3187.982011] [] mutex_lock_nested+0x71/0x346 > [ 3187.992167] [] ? intel_display_power_get+0x38/0xcb > [i915] > [ 3188.003655] [] ? _raw_spin_unlock_irqrestore+0x4b/0x60 > [ 3188.014829] [] ? __pm_runtime_resume+0x71/0x7e > [ 3188.025269] [] intel_display_power_get+0x38/0xcb [i915] > [ 3188.036544] [] ? intel_display_power_get+0x38/0xcb > [i915] > [ 3188.047968] [] intel_hdmi_set_edid+0x3f/0xd6 [i915] > [ 3188.058766] [] intel_hdmi_hot_plug+0xbf/0xfb [i915] > [ 3188.069484] [] intel_hpd_init+0xfa/0x10b [i915] > [ 3188.079753] [] vlv_display_power_well_init+0xdb/0xe8 > [i915] > [ 3188.091224] [] chv_pipe_power_well_enable+0x62/0x67 > [i915] > [ 3188.102594] []
Re: [Intel-gfx] [PATCH] drm/i915: Remove wrong warning from i915_gem_context_clean
On Thu, Oct 08, 2015 at 04:12:31PM +0100, Michel Thierry wrote: > On 10/8/2015 3:37 PM, Tvrtko Ursulin wrote: > >From: Tvrtko Ursulin> > > >commit e9f24d5fb7cf3628b195b18ff3ac4e37937ceeae > >Author: Tvrtko Ursulin > >Date: Mon Oct 5 13:26:36 2015 +0100 > > > > drm/i915: Clean up associated VMAs on context destruction > > > >Introduced a wrong assumption that all contexts have a ppgtt > >instance. This is not true when full PPGTT is not active so > >remove the WARN_ON_ONCE from the context cleanup code. > > Aliasing ppgtt? (for the record, I tried with enable_ppgtt=1 while > reviewing the patch and didn't see the warning... maybe I didn't try > hard enough). We create a context per-fd on all platforms, as in it we store user specific information (such as hangstats, process identifiers etc). Think of a context as a view of driver state not just GPU state. -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v4] drm/i915: Clean up associated VMAs on context destruction
On 08/10/15 17:03, Ville Syrjälä wrote: On Thu, Oct 08, 2015 at 03:03:11PM +0100, Tvrtko Ursulin wrote: Hi, On 08/10/15 14:45, Ville Syrjälä wrote: On Mon, Oct 05, 2015 at 01:26:36PM +0100, Tvrtko Ursulin wrote: From: Tvrtko UrsulinPrevent leaking VMAs and PPGTT VMs when objects are imported via flink. Scenario is that any VMAs created by the importer will be left dangling after the importer exits, or destroys the PPGTT context with which they are associated. This is caused by object destruction not running when the importer closes the buffer object handle due the reference held by the exporter. This also leaks the VM since the VMA has a reference on it. In practice these leaks can be observed by stopping and starting the X server on a kernel with fbcon compiled in. Every time X server exits another VMA will be leaked against the fbcon's frame buffer object. Also on systems where flink buffer sharing is used extensively, like Android, this leak has even more serious consequences. This version is takes a general approach from the earlier work by Rafael Barbalho (drm/i915: Clean-up PPGTT on context destruction) and tries to incorporate the subsequent discussion between Chris Wilson and Daniel Vetter. v2: Removed immediate cleanup on object retire - it was causing a recursive VMA unbind via i915_gem_object_wait_rendering. And it is in fact not even needed since by definition context cleanup worker runs only after the last context reference has been dropped, hence all VMAs against the VM belonging to the context are already on the inactive list. v3: Previous version could deadlock since VMA unbind waits on any rendering on an object to complete. Objects can be busy in a different VM which would mean that the cleanup loop would do the wait with the struct mutex held. This is an even simpler approach where we just unbind VMAs without waiting since we know all VMAs belonging to this VM are idle, and there is nothing in flight, at the point context destructor runs. v4: Double underscore prefix for __915_vma_unbind_no_wait and a commit message typo fix. (Michel Thierry) Signed-off-by: Tvrtko Ursulin Testcase: igt/gem_ppgtt.c/flink-and-exit-vma-leak Reviewed-by: Michel Thierry Cc: Daniel Vetter Cc: Chris Wilson Cc: Rafael Barbalho Cc: Michel Thierry --- drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_gem.c | 20 drivers/gpu/drm/i915/i915_gem_context.c | 24 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 824e7245044d..58afa1bb2957 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2840,6 +2840,11 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags); int __must_check i915_vma_unbind(struct i915_vma *vma); +/* + * BEWARE: Do not use the function below unless you can _absolutely_ + * _guarantee_ VMA in question is _not in use_ anywhere. + */ +int __must_check __i915_vma_unbind_no_wait(struct i915_vma *vma); int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); void i915_gem_release_mmap(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f0cfbb9ee12c..52642aff1dab 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3208,7 +3208,7 @@ static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj) old_write_domain); } -int i915_vma_unbind(struct i915_vma *vma) +static int __i915_vma_unbind(struct i915_vma *vma, bool wait) { struct drm_i915_gem_object *obj = vma->obj; struct drm_i915_private *dev_priv = obj->base.dev->dev_private; @@ -3227,9 +3227,11 @@ int i915_vma_unbind(struct i915_vma *vma) BUG_ON(obj->pages == NULL); - ret = i915_gem_object_wait_rendering(obj, false); - if (ret) - return ret; + if (wait) { + ret = i915_gem_object_wait_rendering(obj, false); + if (ret) + return ret; + } if (i915_is_ggtt(vma->vm) && vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) { @@ -3274,6 +3276,16 @@ int i915_vma_unbind(struct i915_vma *vma) return 0; } +int i915_vma_unbind(struct i915_vma *vma) +{ + return __i915_vma_unbind(vma, true); +} + +int __i915_vma_unbind_no_wait(struct i915_vma *vma) +{ + return __i915_vma_unbind(vma, false); +} + int i915_gpu_idle(struct drm_device *dev) {
Re: [Intel-gfx] [PATCH 1/3] drm/edid: Fix up clock for CEA/HDMI modes specified via detailed timings
On Thu, Oct 08, 2015 at 12:22:31PM -0400, Adam Jackson wrote: > On Thu, 2015-10-08 at 11:43 +0300, ville.syrj...@linux.intel.com wrote: > > From: Ville Syrjälä> > > > EDID detailed timings have a resolution of 10kHz for the pixel clock, so > > they can't represent certain CEA/HDMI modes accurately. If we see a mode > > coming in via detailed timings which otherwise matches one of the > > CEA/HDMI modes except the clock is just a bit off, let's assume that the > > intention was for that mode to be one of the CEA/HDMI modes and go ahead > > and fix up the clock to match the CEA/HDMI spec exactly (well, as close > > as we can get with the 1 kHz resolution we use). > > > > This should help code that's looking for an exact clock match (eg. i915 > > audio N/CTS setup). > > Looks like a sane set of changes. Series is: > > Reviewed-by: Adam Jackson Merged the first two patches to drm-misc (the later one has conflicts with the lack of drm-intel-next, so can pull it in only after a rebase). Thanks, Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v4] drm/i915: Clean up associated VMAs on context destruction
On Thu, Oct 08, 2015 at 03:03:11PM +0100, Tvrtko Ursulin wrote: > > Hi, > > On 08/10/15 14:45, Ville Syrjälä wrote: > > On Mon, Oct 05, 2015 at 01:26:36PM +0100, Tvrtko Ursulin wrote: > >> From: Tvrtko Ursulin> >> > >> Prevent leaking VMAs and PPGTT VMs when objects are imported > >> via flink. > >> > >> Scenario is that any VMAs created by the importer will be left > >> dangling after the importer exits, or destroys the PPGTT context > >> with which they are associated. > >> > >> This is caused by object destruction not running when the > >> importer closes the buffer object handle due the reference held > >> by the exporter. This also leaks the VM since the VMA has a > >> reference on it. > >> > >> In practice these leaks can be observed by stopping and starting > >> the X server on a kernel with fbcon compiled in. Every time > >> X server exits another VMA will be leaked against the fbcon's > >> frame buffer object. > >> > >> Also on systems where flink buffer sharing is used extensively, > >> like Android, this leak has even more serious consequences. > >> > >> This version is takes a general approach from the earlier work > >> by Rafael Barbalho (drm/i915: Clean-up PPGTT on context > >> destruction) and tries to incorporate the subsequent discussion > >> between Chris Wilson and Daniel Vetter. > >> > >> v2: > >> > >> Removed immediate cleanup on object retire - it was causing a > >> recursive VMA unbind via i915_gem_object_wait_rendering. And > >> it is in fact not even needed since by definition context > >> cleanup worker runs only after the last context reference has > >> been dropped, hence all VMAs against the VM belonging to the > >> context are already on the inactive list. > >> > >> v3: > >> > >> Previous version could deadlock since VMA unbind waits on any > >> rendering on an object to complete. Objects can be busy in a > >> different VM which would mean that the cleanup loop would do > >> the wait with the struct mutex held. > >> > >> This is an even simpler approach where we just unbind VMAs > >> without waiting since we know all VMAs belonging to this VM > >> are idle, and there is nothing in flight, at the point > >> context destructor runs. > >> > >> v4: > >> > >> Double underscore prefix for __915_vma_unbind_no_wait and a > >> commit message typo fix. (Michel Thierry) > >> > >> Signed-off-by: Tvrtko Ursulin > >> Testcase: igt/gem_ppgtt.c/flink-and-exit-vma-leak > >> Reviewed-by: Michel Thierry > >> Cc: Daniel Vetter > >> Cc: Chris Wilson > >> Cc: Rafael Barbalho > >> Cc: Michel Thierry > > > >> --- > >> drivers/gpu/drm/i915/i915_drv.h | 5 + > >> drivers/gpu/drm/i915/i915_gem.c | 20 > >> drivers/gpu/drm/i915/i915_gem_context.c | 24 > >> 3 files changed, 45 insertions(+), 4 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/i915/i915_drv.h > >> b/drivers/gpu/drm/i915/i915_drv.h > >> index 824e7245044d..58afa1bb2957 100644 > >> --- a/drivers/gpu/drm/i915/i915_drv.h > >> +++ b/drivers/gpu/drm/i915/i915_drv.h > >> @@ -2840,6 +2840,11 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object > >> *obj, > >> int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level > >> cache_level, > >> u32 flags); > >> int __must_check i915_vma_unbind(struct i915_vma *vma); > >> +/* > >> + * BEWARE: Do not use the function below unless you can _absolutely_ > >> + * _guarantee_ VMA in question is _not in use_ anywhere. > >> + */ > >> +int __must_check __i915_vma_unbind_no_wait(struct i915_vma *vma); > >> int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); > >> void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); > >> void i915_gem_release_mmap(struct drm_i915_gem_object *obj); > >> diff --git a/drivers/gpu/drm/i915/i915_gem.c > >> b/drivers/gpu/drm/i915/i915_gem.c > >> index f0cfbb9ee12c..52642aff1dab 100644 > >> --- a/drivers/gpu/drm/i915/i915_gem.c > >> +++ b/drivers/gpu/drm/i915/i915_gem.c > >> @@ -3208,7 +3208,7 @@ static void i915_gem_object_finish_gtt(struct > >> drm_i915_gem_object *obj) > >>old_write_domain); > >> } > >> > >> -int i915_vma_unbind(struct i915_vma *vma) > >> +static int __i915_vma_unbind(struct i915_vma *vma, bool wait) > >> { > >>struct drm_i915_gem_object *obj = vma->obj; > >>struct drm_i915_private *dev_priv = obj->base.dev->dev_private; > >> @@ -3227,9 +3227,11 @@ int i915_vma_unbind(struct i915_vma *vma) > >> > >>BUG_ON(obj->pages == NULL); > >> > >> - ret = i915_gem_object_wait_rendering(obj, false); > >> - if (ret) > >> - return ret; > >> + if (wait) { > >> + ret = i915_gem_object_wait_rendering(obj, false); > >> + if (ret) > >> + return ret; > >> + } > >> >
Re: [Intel-gfx] [PATCH 2/2] drm/i915: Simplify intel_dp_pre_emphasis_max()
Please ignore these two patches. They contain errors and are superseded by a new patch series I just sent. Ander On Mon, 2015-10-05 at 17:44 +0300, Ander Conselvan de Oliveira wrote: > Simplify intel_dp_pre_emphasis_max() by grouping the conditions for VLV, > HSW, BDW and gen 9 together, since they all use the same values. > > Signed-off-by: Ander Conselvan de Oliveira >> --- > drivers/gpu/drm/i915/intel_dp.c | 29 ++--- > 1 file changed, 2 insertions(+), 27 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index 3fa8a55..c7f93c5 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -3085,7 +3085,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, > uint8_t voltage_swing) > struct drm_device *dev = intel_dp_to_dev(intel_dp); > enum port port = dp_to_dig_port(intel_dp)->port; > > - if (INTEL_INFO(dev)->gen >= 9) { > + if (INTEL_INFO(dev)->gen >= 7 || !IS_IVYBRIDGE(dev)) { > switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { > case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: > return DP_TRAIN_PRE_EMPH_LEVEL_3; > @@ -3094,35 +3094,10 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, > uint8_t > voltage_swing) > case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: > return DP_TRAIN_PRE_EMPH_LEVEL_1; > case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: > - return DP_TRAIN_PRE_EMPH_LEVEL_0; > default: > return DP_TRAIN_PRE_EMPH_LEVEL_0; > } > - } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { > - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: > - return DP_TRAIN_PRE_EMPH_LEVEL_3; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: > - return DP_TRAIN_PRE_EMPH_LEVEL_2; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: > - return DP_TRAIN_PRE_EMPH_LEVEL_1; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: > - default: > - return DP_TRAIN_PRE_EMPH_LEVEL_0; > - } > - } else if (IS_VALLEYVIEW(dev)) { > - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: > - return DP_TRAIN_PRE_EMPH_LEVEL_3; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: > - return DP_TRAIN_PRE_EMPH_LEVEL_2; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: > - return DP_TRAIN_PRE_EMPH_LEVEL_1; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: > - default: > - return DP_TRAIN_PRE_EMPH_LEVEL_0; > - } > - } else if (IS_GEN7(dev) && port == PORT_A) { > + } else if (IS_IVYBRIDGE(dev) && port == PORT_A) { > switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { > case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: > return DP_TRAIN_PRE_EMPH_LEVEL_2; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v4] drm/i915: Clean up associated VMAs on context destruction
On Thu, Oct 08, 2015 at 05:26:44PM +0100, Tvrtko Ursulin wrote: > > On 08/10/15 17:03, Ville Syrjälä wrote: > > On Thu, Oct 08, 2015 at 03:03:11PM +0100, Tvrtko Ursulin wrote: > >> > >> Hi, > >> > >> On 08/10/15 14:45, Ville Syrjälä wrote: > >>> On Mon, Oct 05, 2015 at 01:26:36PM +0100, Tvrtko Ursulin wrote: > From: Tvrtko Ursulin> > Prevent leaking VMAs and PPGTT VMs when objects are imported > via flink. > > Scenario is that any VMAs created by the importer will be left > dangling after the importer exits, or destroys the PPGTT context > with which they are associated. > > This is caused by object destruction not running when the > importer closes the buffer object handle due the reference held > by the exporter. This also leaks the VM since the VMA has a > reference on it. > > In practice these leaks can be observed by stopping and starting > the X server on a kernel with fbcon compiled in. Every time > X server exits another VMA will be leaked against the fbcon's > frame buffer object. > > Also on systems where flink buffer sharing is used extensively, > like Android, this leak has even more serious consequences. > > This version is takes a general approach from the earlier work > by Rafael Barbalho (drm/i915: Clean-up PPGTT on context > destruction) and tries to incorporate the subsequent discussion > between Chris Wilson and Daniel Vetter. > > v2: > > Removed immediate cleanup on object retire - it was causing a > recursive VMA unbind via i915_gem_object_wait_rendering. And > it is in fact not even needed since by definition context > cleanup worker runs only after the last context reference has > been dropped, hence all VMAs against the VM belonging to the > context are already on the inactive list. > > v3: > > Previous version could deadlock since VMA unbind waits on any > rendering on an object to complete. Objects can be busy in a > different VM which would mean that the cleanup loop would do > the wait with the struct mutex held. > > This is an even simpler approach where we just unbind VMAs > without waiting since we know all VMAs belonging to this VM > are idle, and there is nothing in flight, at the point > context destructor runs. > > v4: > > Double underscore prefix for __915_vma_unbind_no_wait and a > commit message typo fix. (Michel Thierry) > > Signed-off-by: Tvrtko Ursulin > Testcase: igt/gem_ppgtt.c/flink-and-exit-vma-leak > Reviewed-by: Michel Thierry > Cc: Daniel Vetter > Cc: Chris Wilson > Cc: Rafael Barbalho > Cc: Michel Thierry > >>> > --- > drivers/gpu/drm/i915/i915_drv.h | 5 + > drivers/gpu/drm/i915/i915_gem.c | 20 > drivers/gpu/drm/i915/i915_gem_context.c | 24 > 3 files changed, 45 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h > b/drivers/gpu/drm/i915/i915_drv.h > index 824e7245044d..58afa1bb2957 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -2840,6 +2840,11 @@ i915_gem_object_ggtt_pin(struct > drm_i915_gem_object *obj, > int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level > cache_level, > u32 flags); > int __must_check i915_vma_unbind(struct i915_vma *vma); > +/* > + * BEWARE: Do not use the function below unless you can _absolutely_ > + * _guarantee_ VMA in question is _not in use_ anywhere. > + */ > +int __must_check __i915_vma_unbind_no_wait(struct i915_vma *vma); > int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); > void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); > void i915_gem_release_mmap(struct drm_i915_gem_object *obj); > diff --git a/drivers/gpu/drm/i915/i915_gem.c > b/drivers/gpu/drm/i915/i915_gem.c > index f0cfbb9ee12c..52642aff1dab 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -3208,7 +3208,7 @@ static void i915_gem_object_finish_gtt(struct > drm_i915_gem_object *obj) > old_write_domain); > } > > -int i915_vma_unbind(struct i915_vma *vma) > +static int __i915_vma_unbind(struct i915_vma *vma, bool wait) > { > struct drm_i915_gem_object *obj = vma->obj; > struct drm_i915_private *dev_priv = obj->base.dev->dev_private; > @@ -3227,9
Re: [Intel-gfx] [PATCH] drm/i915: 4K audio N value incorrect at 29.97 and 23.98 refresh rate
On 10/08/2015 05:44 AM, Ville Syrjälä wrote: On Thu, Oct 08, 2015 at 03:39:26PM +0300, Jani Nikula wrote: On Thu, 08 Oct 2015, Ville Syrjäläwrote: On Wed, Oct 07, 2015 at 02:38:29PM -0700, clinton.a.tay...@intel.com wrote: From: Clint Taylor The TMDS_296M define was computing as 296704 but the mode->clock is 296700 as defined by EDID. Adjusted define to allow correct detection of the need to program the correct N value for 29.97 and 23.98 refresh rate. Signed-off-by: Clint Taylor --- drivers/gpu/drm/i915/intel_audio.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 56c2f54..419c979 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -75,7 +75,7 @@ static const struct { /* HDMI N/CTS table */ #define TMDS_297M 297000 -#define TMDS_296M DIV_ROUND_UP(297000 * 1000, 1001) +#define TMDS_296M 296700 Hmm. I think we might want to fix up the mode instead. Let me post a few patches, and let's see what people think... We might actually want to queue this up for v4.3 as the immediate fix, as I feel it's doubtful your other patches will make it to v4.3. If Someone(tm) provided their r-b that is. Except this is wrong if the mode came from the CEA/HDMI mode list as opposed from the EDID detailed timings. The original patch was generated from a monitor with 296700 in the DTD. Ville's approach is more sane for the long term. We could also just add a third check in the 4K audio fixup for the DTD based pixel clock. ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/3] drm/edid: Fix up clock for CEA/HDMI modes specified via detailed timings
On Thu, 2015-10-08 at 11:43 +0300, ville.syrj...@linux.intel.com wrote: > From: Ville Syrjälä> > EDID detailed timings have a resolution of 10kHz for the pixel clock, so > they can't represent certain CEA/HDMI modes accurately. If we see a mode > coming in via detailed timings which otherwise matches one of the > CEA/HDMI modes except the clock is just a bit off, let's assume that the > intention was for that mode to be one of the CEA/HDMI modes and go ahead > and fix up the clock to match the CEA/HDMI spec exactly (well, as close > as we can get with the 1 kHz resolution we use). > > This should help code that's looking for an exact clock match (eg. i915 > audio N/CTS setup). Looks like a sane set of changes. Series is: Reviewed-by: Adam Jackson - ajax ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 00/11] Mixed bag of ioctl and agp cleanups
On Tue, Sep 08, 2015 at 02:58:52PM +0200, Christian König wrote: > Patches #1, #6, #7, #8 and #10 are Reviewed-by: Christian König >. > > That should be everything touching radeon/amdgpu if I missed something leave > me a note. Ok with an irc r-b from Chris and David I and yours here I pulled in the remaining patches from this series. Thanks, Daniel > > Regards, > Christian. > > On 08.09.2015 13:56, Daniel Vetter wrote: > >Hi all, > > > >Big thing for sure is deprecating DRM_UNLOCKED for DRIVER_MODESET (i.e. > >modern > >drivers) since all of them have their own locking. Besides that a few random > >things that kind where in the same area/files. > > > >Of course kerneldoc is updated too. > > > >Feedback highly welcome. > > > >Cheers, Daniel > > > >Daniel Vetter (11): > > drm: Remove __OS_HAS_AGP > > drm/i915: Kill cross-module option depencies > > drm/i915: Mark debug mod options as _unsafe > > drm/i915: Remove setparam ioctl > > drm/i915: Mark getparam ioctl as DRM_UNLOCKED > > drm: Define a drm_invalid_op ioctl implementation > > drm/drm_ioctl.c: kerneldoc > > drm: Enforce unlocked ioctl operation for kms driver ioctls > > drm/vmwgfx: Stop checking for DRM_UNLOCKED > > drm/: Drop DRM_UNLOCKED from modeset drivers > > drm: Remove dummy agp ioctl wrappers > > > > Documentation/DocBook/drm.tmpl | 5 +- > > drivers/gpu/drm/Makefile| 3 +- > > drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 24 +++ > > drivers/gpu/drm/armada/armada_drv.c | 9 +-- > > drivers/gpu/drm/drm_agpsupport.c| 4 +- > > drivers/gpu/drm/drm_bufs.c | 6 +- > > drivers/gpu/drm/drm_ioc32.c | 6 +- > > drivers/gpu/drm/drm_ioctl.c | 89 +-- > > drivers/gpu/drm/drm_memory.c| 6 +- > > drivers/gpu/drm/drm_vm.c| 8 +-- > > drivers/gpu/drm/exynos/exynos_drm_drv.c | 20 +++--- > > drivers/gpu/drm/i915/i915_dma.c | 101 ++ > > drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- > > drivers/gpu/drm/i915/i915_params.c | 30 > > drivers/gpu/drm/i915/intel_lrc.c| 3 +- > > drivers/gpu/drm/mga/mga_dma.c | 4 +- > > drivers/gpu/drm/msm/msm_drv.c | 14 ++-- > > drivers/gpu/drm/nouveau/nouveau_bo.c| 8 +-- > > drivers/gpu/drm/nouveau/nouveau_drm.c | 24 +++ > > drivers/gpu/drm/omapdrm/omap_drv.c | 12 ++-- > > drivers/gpu/drm/qxl/qxl_ioctl.c | 14 ++-- > > drivers/gpu/drm/r128/r128_cce.c | 12 ++-- > > drivers/gpu/drm/radeon/r600_cp.c| 14 ++-- > > drivers/gpu/drm/radeon/radeon_agp.c | 8 +-- > > drivers/gpu/drm/radeon/radeon_cp.c | 16 ++--- > > drivers/gpu/drm/radeon/radeon_kms.c | 124 > > +++- > > drivers/gpu/drm/radeon/radeon_ttm.c | 10 +-- > > drivers/gpu/drm/tegra/drm.c | 28 > > drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 62 +++- > > include/drm/drmP.h | 2 + > > include/drm/drm_agpsupport.h| 54 +- > > 31 files changed, 321 insertions(+), 401 deletions(-) > > > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915: Partial revert of atomic watermark series
It's been reported that the atomic watermark series triggers some regressions on SKL, which we haven't been able to track down yet. Let's temporarily revert these patches while we track down the root cause. This commit squashes the reverts of: 76305b1 drm/i915: Calculate watermark configuration during atomic check (v2) a4611e4 drm/i915: Don't set plane visible during HW readout if CRTC is off a28170f drm/i915: Calculate ILK-style watermarks during atomic check (v3) de4a9f8 drm/i915: Calculate pipe watermarks into CRTC state (v3) de165e0 drm/i915: Refactor ilk_update_wm (v3) Reference: http://lists.freedesktop.org/archives/intel-gfx/2015-October/077190.html Cc: "Zanoni, Paulo R"Cc: "Vetter, Daniel" Signed-off-by: Matt Roper --- I just got access to BXT hardware, so I'm hoping that the SKL problems reported by Paulo will also be reproducible on BXT. However I'm not going to be able to work on this for a couple days, so it's probably better to do some reverts now so that we don't leave di-nightly in a broken state in the meantime. Also note that this is a different regression than the one reported by Jani (for which we've already reverted a couple patches); his issue happens on the ILK-style watermark path which isn't relevant for Paulo's issues here. drivers/gpu/drm/i915/i915_drv.h | 12 -- drivers/gpu/drm/i915/intel_display.c | 60 + drivers/gpu/drm/i915/intel_drv.h | 49 +++- drivers/gpu/drm/i915/intel_pm.c | 232 +++ 4 files changed, 151 insertions(+), 202 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fbf0ae9..4b02be7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -627,8 +627,6 @@ struct drm_i915_display_funcs { int target, int refclk, struct dpll *match_clock, struct dpll *best_clock); - int (*compute_pipe_wm)(struct intel_crtc *crtc, - struct drm_atomic_state *state); void (*update_wm)(struct drm_crtc *crtc); int (*modeset_calc_cdclk)(struct drm_atomic_state *state); void (*modeset_commit_cdclk)(struct drm_atomic_state *state); @@ -1692,13 +1690,6 @@ struct i915_execbuffer_params { struct drm_i915_gem_request *request; }; -/* used in computing the new watermarks state */ -struct intel_wm_config { - unsigned int num_pipes_active; - bool sprites_enabled; - bool sprites_scaled; -}; - struct drm_i915_private { struct drm_device *dev; struct kmem_cache *objects; @@ -1923,9 +1914,6 @@ struct drm_i915_private { */ uint16_t skl_latency[8]; - /* Committed wm config */ - struct intel_wm_config config; - /* * The skl_wm_values structure is a bit too big for stack * allocation, so we keep the staging struct where we store diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 539c373..d84d5c0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11837,12 +11837,6 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, } ret = 0; - if (dev_priv->display.compute_pipe_wm) { - ret = dev_priv->display.compute_pipe_wm(intel_crtc, state); - if (ret) - return ret; - } - if (INTEL_INFO(dev)->gen >= 9) { if (mode_changed) ret = skl_update_scaler_crtc(pipe_config); @@ -13048,45 +13042,6 @@ static int intel_modeset_checks(struct drm_atomic_state *state) return 0; } -/* - * Handle calculation of various watermark data at the end of the atomic check - * phase. The code here should be run after the per-crtc and per-plane 'check' - * handlers to ensure that all derived state has been updated. - */ -static void calc_watermark_data(struct drm_atomic_state *state) -{ - struct drm_device *dev = state->dev; - struct intel_atomic_state *intel_state = to_intel_atomic_state(state); - struct drm_crtc *crtc; - struct drm_crtc_state *cstate; - struct drm_plane *plane; - struct drm_plane_state *pstate; - - /* -* Calculate watermark configuration details now that derived -* plane/crtc state is all properly updated. -*/ - drm_for_each_crtc(crtc, dev) { - cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?: - crtc->state; - - if (cstate->active) - intel_state->wm_config.num_pipes_active++; - } - drm_for_each_legacy_plane(plane, dev) { - pstate = drm_atomic_get_existing_plane_state(state, plane) ?: -
Re: [Intel-gfx] [PATCH 6/9] drm/i915: driver based PASID handling
On Thu, 2015-10-08 at 12:29 +0100, Tomas Elf wrote: > > Could someone clarify what this means from the TDR point of view, > please? When you say "context blew up" I'm guessing that you mean that > come context caused the fault handler to get involved somehow? > > Does this imply that the offending context will hang and the driver will > have to detect this hang? If so, then yes - if we have the per-engine > hang recovery mode as part of the upcoming TDR work in place then we > could handle it by stepping over the offending batch buffer and moving > on with a minimum of side-effects on the rest of the driver/GPU. I don't think the context does hang. I've made the page-request code artificially fail and report that it was an invalid page fault. The gem_svm_fault test seems to complete (albeit complaining that the test failed). Whereas if I just don't service the page-request at all, *then* the GPU hang is detected. I haven't actually looked at precisely what *is* happening. -- dwmw2 smime.p7s Description: S/MIME cryptographic signature ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/7] drm/i915: don't allocate fbcon from stolen memory if it's too big
On 09/23/2015 08:52 AM, Paulo Zanoni wrote: > Technology has evolved and now we have eDP panels with 3200x1800 > resolution. In the meantime, the BIOS guys didn't change the default > 32mb for stolen memory. On top of that, we can't assume our users will > be able to increase the default stolen memory size to more than 32mb - > I'm not even sure all BIOSes allow that. > > So just the fbcon buffer alone eats 22mb of my stolen memroy, and due > to the BDW/SKL restriction of not using the last 8mb of stolen memory, > all that's left for FBC is 2mb! Since fbcon is not the coolest feature > ever, I think it's better to save our precious stolen resource to FBC > and the other guys. > > On the other hand, we really want to use as much stolen memory as > possible, since on some older systems the stolen memory may be a > considerable percentage of the total available memory. > > This patch tries to achieve a little balance using a simple heuristic: > if the fbcon wants more than half of the available stolen memory, > don't use stolen memory in order to leave some for FBC and the other > features. > > The long term plan should be to implement a way to set priorities for > stolen memory allocation and then evict low priority users when the > high priority ones need the memory. While we still don't have that, > let's try to make FBC usable with the simple solution. > > Cc: Chris Wilson> Signed-off-by: Paulo Zanoni > --- > drivers/gpu/drm/i915/intel_display.c | 7 +++ > drivers/gpu/drm/i915/intel_fbdev.c | 10 -- > 2 files changed, 15 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index 2a1fab3..24b8a72 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -2486,6 +2486,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, > struct intel_initial_plane_config *plane_config) > { > struct drm_device *dev = crtc->base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > struct drm_i915_gem_object *obj = NULL; > struct drm_mode_fb_cmd2 mode_cmd = { 0 }; > struct drm_framebuffer *fb = _config->fb->base; > @@ -2498,6 +2499,12 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, > if (plane_config->size == 0) > return false; > > + /* If the FB is too big, just don't use it since fbdev is not very > + * important and we should probably use that space with FBC or other > + * features. */ > + if (size_aligned * 2 > dev_priv->gtt.stolen_usable_size) > + return false; > + > obj = i915_gem_object_create_stolen_for_preallocated(dev, >base_aligned, >base_aligned, > diff --git a/drivers/gpu/drm/i915/intel_fbdev.c > b/drivers/gpu/drm/i915/intel_fbdev.c > index 6532912..4fd5fdf 100644 > --- a/drivers/gpu/drm/i915/intel_fbdev.c > +++ b/drivers/gpu/drm/i915/intel_fbdev.c > @@ -121,8 +121,9 @@ static int intelfb_alloc(struct drm_fb_helper *helper, > container_of(helper, struct intel_fbdev, helper); > struct drm_framebuffer *fb; > struct drm_device *dev = helper->dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > struct drm_mode_fb_cmd2 mode_cmd = {}; > - struct drm_i915_gem_object *obj; > + struct drm_i915_gem_object *obj = NULL; > int size, ret; > > /* we don't do packed 24bpp */ > @@ -139,7 +140,12 @@ static int intelfb_alloc(struct drm_fb_helper *helper, > > size = mode_cmd.pitches[0] * mode_cmd.height; > size = PAGE_ALIGN(size); > - obj = i915_gem_object_create_stolen(dev, size); > + > + /* If the FB is too big, just don't use it since fbdev is not very > + * important and we should probably use that space with FBC or other > + * features. */ > + if (size * 2 < dev_priv->gtt.stolen_usable_size) > + obj = i915_gem_object_create_stolen(dev, size); > if (obj == NULL) > obj = i915_gem_alloc_object(dev, size); > if (!obj) { > I agree with Chris that we should make this smarter too, but I don't think this hurts in the meantime, so: Reviewed-by: Jesse Barnes Might be nice to macro-ize the size comparison too, both for readability and to change our threshold in one place if we ever need to. Thanks, Jesse ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/3] drm/i915: fix CFB size calculation
On Thu, Oct 01, 2015 at 07:55:57PM -0300, Paulo Zanoni wrote: > We were considering the whole framebuffer height, but the spec says we > should only consider the active display height size. There were still > some unclear questions based on the spec, but the hardware guys > clarified them for us. According to them: > > - CFB size = CFB stride * Number of lines FBC writes to CFB > - CFB stride = plane stride / compression limit > - Number of lines FBC writes to CFB = MIN(plane source height, maximum > number of lines FBC writes to CFB) > - Plane source height = > - pipe source height (PIPE_SRCSZ register) (before SKL) > - plane size register height (PLANE_SIZE register) (SKL+) > - Maximum number of lines FBC writes to CFB = > - plane source height (before HSW) > - 2048 (HSW+) > > For the plane source height, I could just have made our code do > I915_READ() in order to be more future proof, but since it's not cool > to do register reads I decided to just recalculate the values we use > when we actually write to those registers. > > With this patch, depending on your machine configuration, a lot of the > kms_frontbuffer_tracking subtests that used to result in a SKIP due to > not enough stolen memory still start resulting in a PASS. > > v2: Use the clipped src size instead of pipe_src_h (Ville). > v3: Use the appropriate information provided by the hardware guys. > v4: Bikesheds: s/sizes/size/, s/fb_cpp/cpp/ (Ville). > v5: - Don't use crtc->config->pipe_src_x for BDW- (Ville). > - Fix the register name written in the comment. > > Signed-off-by: Paulo Zanoni> --- > drivers/gpu/drm/i915/intel_fbc.c | 54 > > 1 file changed, 49 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_fbc.c > b/drivers/gpu/drm/i915/intel_fbc.c > index 1b2ebb2..18e228b 100644 > --- a/drivers/gpu/drm/i915/intel_fbc.c > +++ b/drivers/gpu/drm/i915/intel_fbc.c > @@ -698,16 +698,61 @@ void intel_fbc_cleanup_cfb(struct drm_i915_private > *dev_priv) > mutex_unlock(_priv->fbc.lock); > } > > -static int intel_fbc_setup_cfb(struct drm_i915_private *dev_priv, int size, > -int fb_cpp) > +/* > + * For SKL+, the plane source size used by the hardware is based on the > value we > + * write to the PLANE_SIZE register. For BDW-, the hardware looks at the > value > + * we wrote to PIPESRC. > + */ > +static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc, > + int *width, int *height) > { > + struct intel_plane_state *plane_state = > + to_intel_plane_state(crtc->base.primary->state); > + int w, h; > + > + if (intel_rotation_90_or_270(plane_state->base.rotation)) { > + w = drm_rect_height(_state->src) >> 16; > + h = drm_rect_width(_state->src) >> 16; > + } else { > + w = drm_rect_width(_state->src) >> 16; > + h = drm_rect_height(_state->src) >> 16; > + } > + > + if (width) > + *width = w; > + if (height) > + *height = h; > +} Yep, I like this much better. Reviewed-by: Ville Syrjälä > + > +static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc) > +{ > + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; > + struct drm_framebuffer *fb = crtc->base.primary->fb; > + int lines; > + > + intel_fbc_get_plane_source_size(crtc, NULL, ); > + if (INTEL_INFO(dev_priv)->gen >= 7) > + lines = min(lines, 2048); > + > + return lines * fb->pitches[0]; > +} > + > +static int intel_fbc_setup_cfb(struct intel_crtc *crtc) > +{ > + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; > + struct drm_framebuffer *fb = crtc->base.primary->fb; > + int size, cpp; > + > + size = intel_fbc_calculate_cfb_size(crtc); > + cpp = drm_format_plane_cpp(fb->pixel_format, 0); > + > if (size <= dev_priv->fbc.uncompressed_size) > return 0; > > /* Release any current block */ > __intel_fbc_cleanup_cfb(dev_priv); > > - return intel_fbc_alloc_cfb(dev_priv, size, fb_cpp); > + return intel_fbc_alloc_cfb(dev_priv, size, cpp); > } > > static bool stride_is_valid(struct drm_i915_private *dev_priv, > @@ -897,8 +942,7 @@ static void __intel_fbc_update(struct drm_i915_private > *dev_priv) > goto out_disable; > } > > - if (intel_fbc_setup_cfb(dev_priv, obj->base.size, > - drm_format_plane_cpp(fb->pixel_format, 0))) { > + if (intel_fbc_setup_cfb(intel_crtc)) { > set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL); > goto out_disable; > } > -- > 2.5.3 > > ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx --
Re: [Intel-gfx] [PATCH 04/16] drm/i915: set ILK_DPFC_FENCE_YOFF to 0 on SNB
On Thu, Oct 08, 2015 at 09:26:19PM +, Zanoni, Paulo R wrote: > Em Sex, 2015-08-28 às 17:46 +0300, Ville Syrjälä escreveu: > > On Fri, Aug 14, 2015 at 06:34:09PM -0300, Paulo Zanoni wrote: > > > The doc is pretty clear that this register should be set to 0 on > > > SNB. > > > We already write y_offset to DPFC_CPU_FENCE_OFFSET a few lines > > > below. > > > > Bspec says: > > "Restriction : The CPU fence is always programmed to match the > > Display > > Buffer base, so this offset must be programmed to 0 to match. > > DevSNB" > > > > We definitely don't program the fence to match DSPSURF, so it's not > > very > > clear that this is really the right thing to do. I suppose it depends > > on > > how the Y offset in the SA register interacts with this one. I never > > got > > around to fixing the Y offset stuff in my FBC efforts, so I've not > > tried > > it on real hardware and so I have no sure answer here. > > The BSpec page for DPFC Control on SNB says: > > 8<- > Project :DEVSNB > iMPH will only send the host modify message when modifications are in > the fence selected in the DPFC_CONTROL_SA register CPUFNCNUM field. The > fence field in the FBC Host Modification message will always be 0 and > this field must be programmed to 0 to match. > 8<- That's about the fence number, it doesn't say anything about the offset IIRC. I guess it could be tested by, say: - set the SA fence offset to some high number and leave this one low - do the opposite and in each case see if GTT tracking still works. And to make sure were testin the right thing, probably repeat with both offsets set high and make sure the tracking really does not work. > > (and DPFC_CONTROL_SA is register 0x100100) > > > > > > > > > Signed-off-by: Paulo Zanoni> > > --- > > > drivers/gpu/drm/i915/intel_fbc.c | 7 ++- > > > 1 file changed, 6 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/gpu/drm/i915/intel_fbc.c > > > b/drivers/gpu/drm/i915/intel_fbc.c > > > index 9ffa7dc..f7be9ab8 100644 > > > --- a/drivers/gpu/drm/i915/intel_fbc.c > > > +++ b/drivers/gpu/drm/i915/intel_fbc.c > > > @@ -216,7 +216,12 @@ static void ilk_fbc_enable(struct intel_crtc > > > *crtc) > > > dpfc_ctl |= obj->fence_reg; > > > > > > y_offset = get_crtc_fence_y_offset(crtc); > > > - I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset); > > > + > > > + if (IS_GEN5(dev_priv)) > > > + I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset); > > > + else > > > + I915_WRITE(ILK_DPFC_FENCE_YOFF, 0); > > > + > > > I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) > > > | ILK_FBC_RT_VALID); > > > /* enable it... */ > > > I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); > > > -- > > > 2.4.6 > > > > > > ___ > > > Intel-gfx mailing list > > > Intel-gfx@lists.freedesktop.org > > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx > > -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 04/16] drm/i915: set ILK_DPFC_FENCE_YOFF to 0 on SNB
Em Sex, 2015-08-28 às 17:46 +0300, Ville Syrjälä escreveu: > On Fri, Aug 14, 2015 at 06:34:09PM -0300, Paulo Zanoni wrote: > > The doc is pretty clear that this register should be set to 0 on > > SNB. > > We already write y_offset to DPFC_CPU_FENCE_OFFSET a few lines > > below. > > Bspec says: > "Restriction : The CPU fence is always programmed to match the > Display > Buffer base, so this offset must be programmed to 0 to match. > DevSNB" > > We definitely don't program the fence to match DSPSURF, so it's not > very > clear that this is really the right thing to do. I suppose it depends > on > how the Y offset in the SA register interacts with this one. I never > got > around to fixing the Y offset stuff in my FBC efforts, so I've not > tried > it on real hardware and so I have no sure answer here. The BSpec page for DPFC Control on SNB says: 8<- Project :DEVSNB iMPH will only send the host modify message when modifications are in the fence selected in the DPFC_CONTROL_SA register CPUFNCNUM field. The fence field in the FBC Host Modification message will always be 0 and this field must be programmed to 0 to match. 8<- (and DPFC_CONTROL_SA is register 0x100100) > > > > > Signed-off-by: Paulo Zanoni> > --- > > drivers/gpu/drm/i915/intel_fbc.c | 7 ++- > > 1 file changed, 6 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_fbc.c > > b/drivers/gpu/drm/i915/intel_fbc.c > > index 9ffa7dc..f7be9ab8 100644 > > --- a/drivers/gpu/drm/i915/intel_fbc.c > > +++ b/drivers/gpu/drm/i915/intel_fbc.c > > @@ -216,7 +216,12 @@ static void ilk_fbc_enable(struct intel_crtc > > *crtc) > > dpfc_ctl |= obj->fence_reg; > > > > y_offset = get_crtc_fence_y_offset(crtc); > > - I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset); > > + > > + if (IS_GEN5(dev_priv)) > > + I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset); > > + else > > + I915_WRITE(ILK_DPFC_FENCE_YOFF, 0); > > + > > I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) > > | ILK_FBC_RT_VALID); > > /* enable it... */ > > I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); > > -- > > 2.4.6 > > > > ___ > > Intel-gfx mailing list > > Intel-gfx@lists.freedesktop.org > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping
From: Chris WilsonA long time ago (before 3.14) we relied on a permanent pinning of the ifbdev to lock the fb in place inside the GGTT. However, the introduction of stealing the BIOS framebuffer and reusing its address in the GGTT for the fbdev has muddied waters and we use an inherited fb. However, the inherited fb is only pinned whilst it is active and we no longer have an explicit pin for the info->system_base mmapping used by the fbdev. The result is that after some aperture pressure the fbdev may be evicted, but we continue to write the fbcon into the same GGTT address - overwriting anything else that may be put into that offset. The effect is most pronounced across suspend/resume as intel_fbdev_set_suspend() does a full clear over the whole scanout. v2: rebased on latest nightly (Wayne) v3: changed i915_gem_object_ggtt_pin() to i915_gem_obj_ggtt_pin() based on Chris' review. (Wayne) Signed-off-by: Chris Wilson Cc: "Goel, Akash" Cc: Daniel Vetter Cc: Jesse Barnes Cc: sta...@vger.kernel.org Reviewed-by: Deepak S Signed-off-by: Wayne Boyer --- drivers/gpu/drm/i915/intel_fbdev.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 6532912..0ad46521 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -215,6 +215,16 @@ static int intelfb_create(struct drm_fb_helper *helper, obj = intel_fb->obj; size = obj->base.size; + /* The fb constructor will have already pinned us (or inherited a +* GGTT region from the BIOS) suitable for a scanout, so +* this should just be a no-op and increment the pin count for the +* fbdev mmapping. It does have a useful side-effect of validating +* the pin for fbdev's use via a GGTT mmapping. +*/ + ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE); + if (ret) + goto out_unlock; + info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); @@ -274,6 +284,9 @@ static int intelfb_create(struct drm_fb_helper *helper, out_destroy_fbi: drm_fb_helper_release_fbi(helper); out_unpin: + /* Once for info->screen_base mmaping... */ + i915_gem_object_ggtt_unpin(obj); + /* ...and once for the intel_fb */ i915_gem_object_ggtt_unpin(obj); drm_gem_object_unreference(>base); out_unlock: @@ -514,6 +527,8 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { static void intel_fbdev_destroy(struct drm_device *dev, struct intel_fbdev *ifbdev) { + /* Release the pinning for the info->screen_base mmaping. */ + i915_gem_object_ggtt_unpin(ifbdev->fb->obj); drm_fb_helper_unregister_fbi(>helper); drm_fb_helper_release_fbi(>helper); -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 7/7] iommu/vt-d: Implement page request handling
Signed-off-by: David Woodhouse--- drivers/iommu/intel-svm.c | 115 +++- include/linux/intel-iommu.h | 21 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 1260e87..ace1e32 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -356,10 +356,121 @@ int intel_svm_unbind_mm(struct device *dev, int pasid) } EXPORT_SYMBOL_GPL(intel_svm_unbind_mm); +/* Page request queue descriptor */ +struct page_req_dsc { + u64 srr:1; + u64 bof:1; + u64 pasid_present:1; + u64 lpig:1; + u64 pasid:20; + u64 bus:8; + u64 private:23; + u64 prg_index:9; + u64 rd_req:1; + u64 wr_req:1; + u64 exe_req:1; + u64 priv_req:1; + u64 devfn:8; + u64 addr:52; +}; +#define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10) static irqreturn_t prq_event_thread(int irq, void *d) { struct intel_iommu *iommu = d; - printk("PRQ event on %s\n", iommu->name); - return IRQ_HANDLED; + struct intel_svm *svm = NULL; + int head, tail, handled = 0; + + tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK; + head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK; + while (head != tail) { + struct vm_area_struct *vma; + struct page_req_dsc *req; + struct qi_desc resp; + int ret, result; + u64 address; + + handled = 1; + + req = >prq[head / sizeof(*req)]; + + result = QI_RESP_INVALID; + address = req->addr << PAGE_SHIFT; + if (!req->pasid_present) { + pr_err("%s: Page request without PASID: %08llx %08llx\n", + iommu->name, ((unsigned long long *)req)[0], + ((unsigned long long *)req)[1]); + goto inval_req; + } + + if (!svm || svm->pasid != req->pasid) { + mutex_lock(_mutex); + if (svm) + kref_put(>kref, _mm_free); + + svm = idr_find(>pasid_idr, req->pasid); + if (!svm) { + pr_err("%s: Page request for invalid PASID %d: %08llx %08llx\n", + iommu->name, req->pasid, ((unsigned long long *)req)[0], + ((unsigned long long *)req)[1]); + mutex_unlock(_mutex); + goto inval_req; + } + /* Strictly speaking, we shouldn't need this. It is forbidden + to unbind the PASID while there may still be requests in + flight. But let's do it anyway. */ + kref_get(>kref); + mutex_unlock(_mutex); + } + + result = QI_RESP_FAILURE; + down_read(>mm->mmap_sem); + vma = find_extend_vma(svm->mm, address); + if (!vma || address < vma->vm_start) + goto hard_fault; + + ret = handle_mm_fault(svm->mm, vma, address, + req->wr_req ? FAULT_FLAG_WRITE : 0); + if (ret & VM_FAULT_ERROR) + goto hard_fault; + + result = QI_RESP_SUCCESS; + hard_fault: + up_read(>mm->mmap_sem); + inval_req: + /* Accounting for major/minor faults? */ + + if (req->lpig) { + /* Page Group Response */ + resp.low = QI_PGRP_PASID(req->pasid) | + QI_PGRP_DID((req->bus << 8) | req->devfn) | + QI_PGRP_PASID_P(req->pasid_present) | + QI_PGRP_RESP_TYPE; + resp.high = QI_PGRP_IDX(req->prg_index) | + QI_PGRP_PRIV(req->private) | QI_PGRP_RESP_CODE(result); + + qi_submit_sync(, svm->iommu); + } else if (req->srr) { + /* Page Stream Response */ + resp.low = QI_PSTRM_IDX(req->prg_index) | + QI_PSTRM_PRIV(req->private) | QI_PSTRM_BUS(req->bus) | + QI_PSTRM_PASID(req->pasid) | QI_PSTRM_RESP_TYPE; + resp.high = QI_PSTRM_ADDR(address) | QI_PSTRM_DEVFN(req->devfn) | + QI_PSTRM_RESP_CODE(result); + + qi_submit_sync(, svm->iommu); + } + + head = (head + sizeof(*req)) & PRQ_RING_MASK; + } + + if (svm) { + mutex_lock(_mutex); +
[Intel-gfx] [PATCH 6/7] iommu/vt-d: Enable page request interrupt
Signed-off-by: David Woodhouse--- drivers/iommu/intel-iommu.c | 22 +- drivers/iommu/intel-svm.c | 71 + include/linux/intel-iommu.h | 5 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b5ab009..e27b9c6 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1687,8 +1687,11 @@ static void free_dmar_iommu(struct intel_iommu *iommu) free_context_table(iommu); #ifdef CONFIG_INTEL_IOMMU_SVM - if (pasid_enabled(iommu)) + if (pasid_enabled(iommu)) { + if (ecap_prs(iommu->ecap)) + intel_svm_finish_prq(iommu); intel_svm_free_pasid_tables(iommu); + } #endif } @@ -3204,6 +3207,13 @@ domains_done: iommu_flush_write_buffer(iommu); +#ifdef CONFIG_INTEL_IOMMU_SVM + if (pasid_enabled(iommu) && ecap_prs(iommu->ecap)) { + ret = intel_svm_enable_prq(iommu); + if (ret) + goto free_iommu; + } +#endif ret = dmar_set_interrupt(iommu); if (ret) goto free_iommu; @@ -4148,6 +4158,14 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru) intel_iommu_init_qi(iommu); iommu_flush_write_buffer(iommu); + +#ifdef CONFIG_INTEL_IOMMU_SVM + if (pasid_enabled(iommu) && ecap_prs(iommu->ecap)) { + ret = intel_svm_enable_prq(iommu); + if (ret) + goto disable_iommu; + } +#endif ret = dmar_set_interrupt(iommu); if (ret) goto disable_iommu; @@ -4952,6 +4970,8 @@ int intel_iommu_enable_pasid(struct intel_svm *svm) ctx_lo |= CONTEXT_TT_PT_PASID << 2; } ctx_lo |= CONTEXT_PASIDE; + if (svm->dev_iotlb && ecap_prs(svm->iommu->ecap)) + ctx_lo |= CONTEXT_PRS; context[0].lo = ctx_lo; wmb(); svm->iommu->flush.flush_context(svm->iommu, svm->did, diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 913c3a1..1260e87 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -18,6 +18,10 @@ #include #include #include +#include +#include + +static irqreturn_t prq_event_thread(int irq, void *d); struct pasid_entry { u64 val; @@ -75,6 +79,65 @@ int intel_svm_free_pasid_tables(struct intel_iommu *iommu) return 0; } +#define PRQ_ORDER 0 +int intel_svm_enable_prq(struct intel_iommu *iommu) +{ + struct page *pages; + int irq, ret; + + pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, PRQ_ORDER); + if (!pages) { + pr_warn("IOMMU: %s: Failed to allocate page request queue\n", + iommu->name); + return -ENOMEM; + } + iommu->prq = page_address(pages); + + irq = dmar_alloc_hwirq(DMAR_UNITS_SUPPORTED + iommu->seq_id, iommu->node, iommu); + if (irq <= 0) { + pr_err("IOMMU: %s: Failed to create IRQ vector for page request queue\n", + iommu->name); + ret = -EINVAL; + err: + free_pages((unsigned long)iommu->prq, PRQ_ORDER); + iommu->prq = 0; + return ret; + } + iommu->pr_irq = irq; + + snprintf(iommu->prq_name, sizeof(iommu->prq_name), "dmar%d-prq", iommu->seq_id); + + ret = request_threaded_irq(irq, NULL, prq_event_thread, IRQF_ONESHOT, + iommu->prq_name, iommu); + if (ret) { + pr_err("IOMMU: %s: Failed to request IRQ for page request queue\n", + iommu->name); + dmar_free_hwirq(irq); + goto err; + } + dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL); + dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL); + dmar_writeq(iommu->reg + DMAR_PQA_REG, virt_to_phys(iommu->prq) | PRQ_ORDER); + + return 0; +} + +int intel_svm_finish_prq(struct intel_iommu *iommu) +{ + dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL); + dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL); + dmar_writeq(iommu->reg + DMAR_PQA_REG, 0ULL); + + free_irq(iommu->pr_irq, iommu); + dmar_free_hwirq(iommu->pr_irq); + iommu->pr_irq = 0; + + free_pages((unsigned long)iommu->prq, PRQ_ORDER); + iommu->prq = 0; + + return 0; +} + static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address, int pages, int ih) { @@ -292,3 +355,11 @@ int intel_svm_unbind_mm(struct device *dev, int pasid) return ret; } EXPORT_SYMBOL_GPL(intel_svm_unbind_mm); + + +static irqreturn_t prq_event_thread(int irq, void *d) +{ +
[Intel-gfx] [PATCH 5/7] iommu/vt-d: Assume BIOS lies about ATSR for integrated gfx
If the device itself reports ATS in its PCIe capabilities, but the BIOS neglects to provide an ATSR structure to indicate that the root port can also cope, then assume the latter is lying. Signed-off-by: David Woodhouse--- drivers/iommu/intel-iommu.c | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a6fd639..b5ab009 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1447,9 +1447,14 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu, if (!pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS)) return NULL; - if (!dmar_find_matched_atsr_unit(pdev)) - return NULL; - + if (!dmar_find_matched_atsr_unit(pdev)) { + if (intel_iommu_pasid28 && IS_GFX_DEVICE(pdev) && + pdev->vendor == 0x8086) { + pr_warn("BIOS denies ATSR capability for %s; assuming it lies\n", + dev_name(info->dev)); + } else + return NULL; + } return info; } -- 2.4.3 -- David WoodhouseOpen Source Technology Centre david.woodho...@intel.com Intel Corporation smime.p7s Description: S/MIME cryptographic signature ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 0/7] Enable SVM for Intel VT-d
This patch set enables PASID support for the Intel IOMMU, along with page request support. Like its AMD counterpart, it exposes an IOMMU-specific API. I believe we'll have a session at the Kernel Summit later this month in which we can work out a generic API which will cover the two (now) existing implementations as well as upcoming ARM (and other?) versions. For the time being, however, exposing an Intel-specific API is good enough, especially as we don't have the required TLP prefix support on our PCIe root ports and we *can't* support discrete PCIe devices with PASID support. It's purely on-chip stuff right now, which is basically only Intel graphics. The AMD implementation allows a per-device PASID space, and managing the PASID space is left entirely to the device driver. In contrast, this implementation maintains a per-IOMMU PASID space, and drivers calling intel_svm_bind_mm() will be *given* the PASID that they are to use. In general we seem to be converging on using a single PASID space across *all* IOMMUs in the system, and this will support that mode of operation. -- David WoodhouseOpen Source Technology Centre david.woodho...@intel.com Intel Corporation smime.p7s Description: S/MIME cryptographic signature ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/7] iommu/vt-d: Add initial support for PASID tables
Add CONFIG_INTEL_IOMMU_SVM, and allocate PASID tables on supported hardware. Signed-off-by: David Woodhouse--- drivers/iommu/Kconfig | 8 ++ drivers/iommu/Makefile | 1 + drivers/iommu/intel-iommu.c | 14 ++ drivers/iommu/intel-svm.c | 65 + include/linux/intel-iommu.h | 15 +++ 5 files changed, 103 insertions(+) create mode 100644 drivers/iommu/intel-svm.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index d9da766..e3b2c2e 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -135,6 +135,14 @@ config INTEL_IOMMU and include PCI device scope covered by these DMA remapping devices. +config INTEL_IOMMU_SVM + bool "Support for Shared Virtual Memory with Intel IOMMU" + depends on INTEL_IOMMU && X86 + help + Shared Virtual Memory (SVM) provides a facility for devices + to access DMA resources through process address space by + means of a Process Address Space ID (PASID). + config INTEL_IOMMU_DEFAULT_ON def_bool y prompt "Enable Intel DMA Remapping Devices by default" diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index c6dcc51..dc6f511 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_ARM_SMMU) += arm-smmu.o obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o obj-$(CONFIG_DMAR_TABLE) += dmar.o obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o +obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a1514a5..1f89064 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1680,6 +1680,11 @@ static void free_dmar_iommu(struct intel_iommu *iommu) /* free context mapping */ free_context_table(iommu); + +#ifdef CONFIG_INTEL_IOMMU_SVM + if (pasid_enabled(iommu)) + intel_svm_free_pasid_tables(iommu); +#endif } static struct dmar_domain *alloc_domain(int flags) @@ -3103,6 +3108,10 @@ static int __init init_dmars(void) if (!ecap_pass_through(iommu->ecap)) hw_pass_through = 0; +#ifdef CONFIG_INTEL_IOMMU_SVM + if (pasid_enabled(iommu)) + intel_svm_alloc_pasid_tables(iommu); +#endif } if (iommu_pass_through) @@ -4118,6 +4127,11 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru) if (ret) goto out; +#ifdef CONFIG_INTEL_IOMMU_SVM + if (pasid_enabled(iommu)) + intel_svm_alloc_pasid_tables(iommu); +#endif + if (dmaru->ignored) { /* * we always have to disable PMRs or DMA may fail on this device diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c new file mode 100644 index 000..9b40ad6 --- /dev/null +++ b/drivers/iommu/intel-svm.c @@ -0,0 +1,65 @@ +/* + * Copyright © 2015 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * Authors: David Woodhouse + */ + +#include + +int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu) +{ + struct page *pages; + int order; + + order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT; + if (order < 0) + order = 0; + + pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); + if (!pages) { + pr_warn("IOMMU: %s: Failed to allocate PASID table\n", + iommu->name); + return -ENOMEM; + } + iommu->pasid_table = page_address(pages); + pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); + if (!pages) { + pr_warn("IOMMU: %s: Failed to allocate PASID state table\n", + iommu->name); + free_pages((unsigned long)iommu->pasid_table, order); + iommu->pasid_table = NULL; + return -ENOMEM; + } + iommu->pasid_state_table = page_address(pages); + pr_info("%s: Allocated order %d PASID table.\n", iommu->name, order); + + return 0; +} + +int intel_svm_free_pasid_tables(struct intel_iommu *iommu) +{ + int order; + + order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT; + if (order < 0) + order = 0; + + if (iommu->pasid_table) { + free_pages((unsigned
[Intel-gfx] [PATCH 1/7] iommu/vt-d: Introduce intel_iommu=pasid28, and pasid_enabled() macro
As long as we use an identity mapping to work around the worst of the hardware bugs which caused us to defeature it and change the definition of the capability bit, we *can* use PASID support on the devices which advertised it in bit 28 of the Extended Capability Register. Allow people to do so with 'intel_iommu=pasid28' on the command line. Signed-off-by: David Woodhouse--- drivers/iommu/intel-iommu.c | 20 ++-- include/linux/intel-iommu.h | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 041bc18..a1514a5 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -497,13 +497,21 @@ static int dmar_forcedac; static int intel_iommu_strict; static int intel_iommu_superpage = 1; static int intel_iommu_ecs = 1; +static int intel_iommu_pasid28; +static int iommu_identity_mapping; + +#define IDENTMAP_ALL 1 +#define IDENTMAP_GFX 2 +#define IDENTMAP_AZALIA4 /* We only actually use ECS when PASID support (on the new bit 40) * is also advertised. Some early implementations — the ones with * PASID support on bit 28 — have issues even when we *only* use * extended root/context tables. */ +#define pasid_enabled(iommu) (ecap_pasid(iommu->ecap) || \ + (intel_iommu_pasid28 && ecap_broken_pasid(iommu->ecap))) #define ecs_enabled(iommu) (intel_iommu_ecs && ecap_ecs(iommu->ecap) && \ - ecap_pasid(iommu->ecap)) + pasid_enabled(iommu)) int intel_iommu_gfx_mapped; EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); @@ -566,6 +574,11 @@ static int __init intel_iommu_setup(char *str) printk(KERN_INFO "Intel-IOMMU: disable extended context table support\n"); intel_iommu_ecs = 0; + } else if (!strncmp(str, "pasid28", 7)) { + printk(KERN_INFO + "Intel-IOMMU: enable pre-production PASID support\n"); + intel_iommu_pasid28 = 1; + iommu_identity_mapping |= IDENTMAP_GFX; } str += strcspn(str, ","); @@ -2399,11 +2412,6 @@ found_domain: return domain; } -static int iommu_identity_mapping; -#define IDENTMAP_ALL 1 -#define IDENTMAP_GFX 2 -#define IDENTMAP_AZALIA4 - static int iommu_domain_identity_map(struct dmar_domain *domain, unsigned long long start, unsigned long long end) diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 6240063..c03316d 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -123,7 +123,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define ecap_srs(e)((e >> 31) & 0x1) #define ecap_ers(e)((e >> 30) & 0x1) #define ecap_prs(e)((e >> 29) & 0x1) -/* PASID support used to be on bit 28 */ +#define ecap_broken_pasid(e) ((e >> 28) & 0x1) #define ecap_dis(e)((e >> 27) & 0x1) #define ecap_nest(e) ((e >> 26) & 0x1) #define ecap_mts(e)((e >> 25) & 0x1) -- 2.4.3 -- David WoodhouseOpen Source Technology Centre david.woodho...@intel.com Intel Corporation smime.p7s Description: S/MIME cryptographic signature ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 4/7] iommu/vt-d: Generalise DMAR MSI setup to allow for page request events
Signed-off-by: David Woodhouse--- drivers/iommu/dmar.c| 42 +++--- include/linux/intel-iommu.h | 10 +- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 8757f8d..80e3c17 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1086,6 +1086,11 @@ static void free_iommu(struct intel_iommu *iommu) iommu_device_destroy(iommu->iommu_dev); if (iommu->irq) { + if (iommu->pr_irq) { + free_irq(iommu->pr_irq, iommu); + dmar_free_hwirq(iommu->pr_irq); + iommu->pr_irq = 0; + } free_irq(iommu->irq, iommu); dmar_free_hwirq(iommu->irq); iommu->irq = 0; @@ -1493,53 +1498,68 @@ static const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type) } } + +static inline int dmar_msi_reg(struct intel_iommu *iommu, int irq) +{ + if (iommu->irq == irq) + return DMAR_FECTL_REG; + else if (iommu->pr_irq == irq) + return DMAR_PECTL_REG; + else + BUG(); +} + void dmar_msi_unmask(struct irq_data *data) { struct intel_iommu *iommu = irq_data_get_irq_handler_data(data); + int reg = dmar_msi_reg(iommu, data->irq); unsigned long flag; /* unmask it */ raw_spin_lock_irqsave(>register_lock, flag); - writel(0, iommu->reg + DMAR_FECTL_REG); + writel(0, iommu->reg + reg); /* Read a reg to force flush the post write */ - readl(iommu->reg + DMAR_FECTL_REG); + readl(iommu->reg + reg); raw_spin_unlock_irqrestore(>register_lock, flag); } void dmar_msi_mask(struct irq_data *data) { - unsigned long flag; struct intel_iommu *iommu = irq_data_get_irq_handler_data(data); + int reg = dmar_msi_reg(iommu, data->irq); + unsigned long flag; /* mask it */ raw_spin_lock_irqsave(>register_lock, flag); - writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG); + writel(DMA_FECTL_IM, iommu->reg + reg); /* Read a reg to force flush the post write */ - readl(iommu->reg + DMAR_FECTL_REG); + readl(iommu->reg + reg); raw_spin_unlock_irqrestore(>register_lock, flag); } void dmar_msi_write(int irq, struct msi_msg *msg) { struct intel_iommu *iommu = irq_get_handler_data(irq); + int reg = dmar_msi_reg(iommu, irq); unsigned long flag; raw_spin_lock_irqsave(>register_lock, flag); - writel(msg->data, iommu->reg + DMAR_FEDATA_REG); - writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG); - writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG); + writel(msg->data, iommu->reg + reg + 4); + writel(msg->address_lo, iommu->reg + reg + 8); + writel(msg->address_hi, iommu->reg + reg + 12); raw_spin_unlock_irqrestore(>register_lock, flag); } void dmar_msi_read(int irq, struct msi_msg *msg) { struct intel_iommu *iommu = irq_get_handler_data(irq); + int reg = dmar_msi_reg(iommu, irq); unsigned long flag; raw_spin_lock_irqsave(>register_lock, flag); - msg->data = readl(iommu->reg + DMAR_FEDATA_REG); - msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG); - msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG); + msg->data = readl(iommu->reg + reg + 4); + msg->address_lo = readl(iommu->reg + reg + 8); + msg->address_hi = readl(iommu->reg + reg + 12); raw_spin_unlock_irqrestore(>register_lock, flag); } diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index b0df572..564a61b 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -59,6 +59,14 @@ #define DMAR_IQA_REG 0x90/* Invalidation queue addr register */ #define DMAR_ICS_REG 0x9c/* Invalidation complete status register */ #define DMAR_IRTA_REG 0xb8/* Interrupt remapping table addr register */ +#define DMAR_PQH_REG 0xc0/* Page request queue head register */ +#define DMAR_PQT_REG 0xc8/* Page request queue tail register */ +#define DMAR_PQA_REG 0xd0/* Page request queue address register */ +#define DMAR_PRS_REG 0xdc/* Page request status register */ +#define DMAR_PECTL_REG 0xe0/* Page request event control register */ +#defineDMAR_PEDATA_REG 0xe4/* Page request event interrupt data register */ +#defineDMAR_PEADDR_REG 0xe8/* Page request event interrupt addr register */ +#defineDMAR_PEUADDR_REG 0xec /* Page request event Upper address register */ #define OFFSET_STRIDE (9) /* @@ -374,7 +382,7 @@ struct intel_iommu { int seq_id; /* sequence id of the iommu */ int agaw; /* agaw of this iommu */ int msagaw; /* max sagaw of this iommu
[Intel-gfx] [PATCH 3/7] iommu/vt-d: Add intel_svm_{un, }bind_mm() functions
This provides basic PASID support for endpoint devices, tested with a version of the i915 driver. A given process can bind to only one device per IOMMU for now. Making that more generic isn't particularly difficult but isn't needed yet, and can come later once the basic functionality is stable. Eventually we'll also want the PASID space to be system-wide, not just per-IOMMU. But when we have that requirement we'll also have a way to achieve it. Signed-off-by: David Woodhouse--- drivers/iommu/intel-iommu.c | 100 ++ drivers/iommu/intel-svm.c | 229 ++ include/linux/dma_remapping.h | 7 ++ include/linux/intel-iommu.h | 59 ++- include/linux/intel-svm.h | 68 + 5 files changed, 458 insertions(+), 5 deletions(-) create mode 100644 include/linux/intel-svm.h diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 1f89064..a6fd639 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4882,6 +4882,106 @@ static void intel_iommu_remove_device(struct device *dev) iommu_device_unlink(iommu->iommu_dev, dev); } +#ifdef CONFIG_INTEL_IOMMU_SVM +int intel_iommu_enable_pasid(struct intel_svm *svm) +{ + struct device_domain_info *info = NULL; + struct context_entry *context; + struct dmar_domain *domain; + unsigned long flags; + u8 bus, devfn; + u64 ctx_lo; + + if (iommu_dummy(svm->dev)) { + dev_warn(svm->dev, +"No IOMMU translation for device; cannot enable SVM\n"); + return -EINVAL; + } + + domain = get_valid_domain_for_dev(svm->dev); + if (!domain) { + dev_warn(svm->dev, "Cannot get IOMMU domain to enable SVM\n"); + return -EINVAL; + } + + svm->iommu = device_to_iommu(svm->dev, , ); + if (!ecs_enabled(svm->iommu)) { + dev_dbg(svm->dev, "No ECS support on IOMMU; cannot enable SVM\n"); + return -EINVAL; + } + svm->did = domain->iommu_did[svm->iommu->seq_id]; + + spin_lock_irqsave(_domain_lock, flags); + spin_lock(>iommu->lock); + context = iommu_context_addr(svm->iommu, bus, devfn, 0); + if (WARN_ON(!context)) { + spin_unlock(>iommu->lock); + spin_unlock_irqrestore(_domain_lock, flags); + return -EINVAL; + } + + ctx_lo = context[0].lo; + /* Modes in which the device IOTLB is enabled are 1 and 5. Modes +* 3 and 7 are invalid. so we only need to test the low bit of TT */ + svm->dev_iotlb = (ctx_lo >> 2) & 1; + + if (!(ctx_lo & CONTEXT_PASIDE)) { + context[1].hi = (u64)virt_to_phys(svm->iommu->pasid_state_table); + context[1].lo = (u64)virt_to_phys(svm->iommu->pasid_table) | ecap_pss(svm->iommu->ecap); + wmb(); + /* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both +* extended to permit requests-with-PASID if the PASIDE bit +* is set. which makes sense. For CONTEXT_TT_PASS_THROUGH, +* however, the PASIDE bit is ignored and requests-with-PASID +* are unconditionally blocked. Which makes less sense. +* So convert from CONTEXT_TT_PASS_THROUGH to one of the new +* "guest mode" translation types depending on whether ATS +* is available or not. */ + if ((ctx_lo & CONTEXT_TT_MASK) == (CONTEXT_TT_PASS_THROUGH << 2)) { + ctx_lo &= ~CONTEXT_TT_MASK; + info = iommu_support_dev_iotlb(domain, svm->iommu, bus, devfn); + if (info) { + ctx_lo |= CONTEXT_TT_PT_PASID_DEV_IOTLB << 2; + svm->dev_iotlb = 1; + } else + ctx_lo |= CONTEXT_TT_PT_PASID << 2; + } + ctx_lo |= CONTEXT_PASIDE; + context[0].lo = ctx_lo; + wmb(); + svm->iommu->flush.flush_context(svm->iommu, svm->did, + (((u16)bus) << 8) | devfn, + DMA_CCMD_MASK_NOBIT, + DMA_CCMD_DEVICE_INVL); + } + spin_unlock(>iommu->lock); + spin_unlock_irqrestore(_domain_lock, flags); + + /* This only happens if we just switched from CONTEXT_TT_PASS_THROUGH */ + if (info) + iommu_enable_dev_iotlb(info); + + /* This can also happen when we were already in a dev-iotlb mode */ + if (svm->dev_iotlb) { + svm->qdep = pci_ats_queue_depth(to_pci_dev(svm->dev)); + if (svm->qdep >= QI_DEV_EIOTLB_MAX_INVS) + svm->qdep = 0; + svm->sid = (((u16)bus)
Re: [Intel-gfx] [PATCH 1/2] drm/i915: Call encoder hotplug for init and resume cases
On 10/9/2015 1:24 AM, Daniel Vetter wrote: On Thu, Oct 08, 2015 at 05:38:58PM +0300, Jani Nikula wrote: On Thu, 08 Oct 2015, Ville Syrjäläwrote: On Mon, Oct 05, 2015 at 04:43:14PM +0530, Sonika Jindal wrote: For all the encoders, call the hot_plug if it is registered. This is required for connected boot and resume cases to generate fake hpd resulting in reading of edid. Removing the initial sdvo hot_plug call too so that it will be called just once from this loop. Signed-off-by: Sonika Jindal --- drivers/gpu/drm/i915/intel_hotplug.c | 11 +++ drivers/gpu/drm/i915/intel_sdvo.c|1 - 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index 53c0173..eac4757 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -458,6 +458,7 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; struct drm_mode_config *mode_config = >mode_config; + struct intel_encoder *encoder; struct drm_connector *connector; int i; @@ -482,6 +483,16 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) if (dev_priv->display.hpd_irq_setup) dev_priv->display.hpd_irq_setup(dev); spin_unlock_irq(_priv->irq_lock); + + /* +* Connected boot / resume scenarios can't generate new hot plug. +* So, probe it manually. +*/ + list_for_each_entry(encoder, >mode_config.encoder_list, + base.head) { + if (encoder->hot_plug) + encoder->hot_plug(encoder); + } This breaks the world on CHV Also patch 2/2 breaks: https://bugs.freedesktop.org/show_bug.cgi?id=88081 Hmm, will check why live status is not up for chv.. Regards, Sonika Both reverted, thanks for the reveport. -Daniel BR, Jani. [ 3187.575198] [drm:intel_hdmi_hot_plug] Live status not up! [ 3187.585154] = [ 3187.595010] [ INFO: possible recursive locking detected ] [ 3187.604685] 4.3.0-rc4-bsw+ #2488 Tainted: G U W [ 3187.614366] - [ 3187.623892] Xorg/32212 is trying to acquire lock: [ 3187.632635] (_domains->lock){+.+...}, at: [] intel_display_power_get+0x38/0xcb [i915] [ 3187.647492] [ 3187.647492] but task is already holding lock: [ 3187.661054] (_domains->lock){+.+...}, at: [] intel_display_power_get+0x38/0xcb [i915] [ 3187.675960] [ 3187.675960] other info that might help us debug this: [ 3187.690459] Possible unsafe locking scenario: [ 3187.690459] [ 3187.704224]CPU0 [ 3187.710485] [ 3187.716711] lock(_domains->lock); [ 3187.724718] lock(_domains->lock); [ 3187.732663] [ 3187.732663] *** DEADLOCK *** [ 3187.732663] [ 3187.749460] May be due to missing lock nesting notation [ 3187.749460] [ 3187.763833] 5 locks held by Xorg/32212: [ 3187.771523] #0: (drm_global_mutex){+.+.+.}, at: [] drm_release+0x3b/0x49b [drm] [ 3187.785216] #1: (>mode_config.mutex){+.+.+.}, at: [] drm_modeset_lock_all+0x54/0xcd [drm] [ 3187.800437] #2: (crtc_ww_class_acquire){+.+.+.}, at: [] drm_modeset_lock_all+0x5e/0xcd [drm] [ 3187.815488] #3: (crtc_ww_class_mutex){+.+.+.}, at: [] drm_modeset_lock+0x75/0xfc [drm] [ 3187.830094] #4: (_domains->lock){+.+...}, at: [] intel_display_power_get+0x38/0xcb [i915] [ 3187.845534] [ 3187.845534] stack backtrace: [ 3187.857685] CPU: 2 PID: 32212 Comm: Xorg Tainted: G U W 4.3.0-rc4-bsw+ #2488 [ 3187.870331] Hardware name: Intel Corporation CHERRYVIEW C0 PLATFORM/Braswell CRB, BIOS BRAS.X64.B085.R00.1509110553 09/11/2015 [ 3187.886827] 880175eff8e0 8128d59e 823f5ee0 [ 3187.898904] 880175eff958 810a7a08 880179d1c5d0 [ 3187.910954] 0004 0006 45422a91588a4c3e 0005 [ 3187.923011] Call Trace: [ 3187.929451] [] dump_stack+0x4e/0x79 [ 3187.938912] [] __lock_acquire+0x7ab/0x12af [ 3187.949027] [] lock_acquire+0x10e/0x1a9 [ 3187.958859] [] ? intel_display_power_get+0x38/0xcb [i915] [ 3187.970476] [] ? intel_display_power_get+0x38/0xcb [i915] [ 3187.982011] [] mutex_lock_nested+0x71/0x346 [ 3187.992167] [] ? intel_display_power_get+0x38/0xcb [i915] [ 3188.003655] [] ? _raw_spin_unlock_irqrestore+0x4b/0x60 [ 3188.014829] [] ? __pm_runtime_resume+0x71/0x7e [ 3188.025269] [] intel_display_power_get+0x38/0xcb [i915] [ 3188.036544] [] ? intel_display_power_get+0x38/0xcb [i915] [ 3188.047968] [] intel_hdmi_set_edid+0x3f/0xd6 [i915] [ 3188.058766] [] intel_hdmi_hot_plug+0xbf/0xfb [i915] [ 3188.069484] [] intel_hpd_init+0xfa/0x10b [i915] [ 3188.079753] [] vlv_display_power_well_init+0xdb/0xe8 [i915] [ 3188.091224] [] chv_pipe_power_well_enable+0x62/0x67 [i915] [ 3188.102594] []
[Intel-gfx] [PATCH 0/8] Stability improvements to error state capture
In preparation for the upcoming TDR per-engine hang recovery enablement the stability of the error state capture code needs to be addressed. The biggest reason for this is that in order to test TDR a long-duration test needs to be run for several hours during which a large number of hangs is handled together with the associated error state captures. In its current state the i915 driver experiences various forms of kernel panics and other kinds of fatal errors within the first hour(s) of the hang testing. The patches in this series have been tested with a long-duration hang testing clocking in at 12+ hours and should suffice as an initial improvement. The underlying issue of trying to capture the driver state without synchronization is still a problem that remains to be fixed. One way of at least further alleviating this problem that has been suggested by John Harrison is to do a mutex_trylock() of the struct_mutex for a while (give it a second or so) before going into the error state capture from i915_handle_error(). Then, if nobody is holding the struct_mutex, the error state capture is considerably more safe from sudden state changes. If some thread has hung while holding the struct_mutex one could at least hope that there would be no sudden state changes during error state capture due to the hung state (unless some thread has been caught in a livelock or is perhaps not stuck at all but is simply running for a very long time - still some improvements might be expected here). One fix that has been omitted from this patch series is in regards to the broken ring space calculation following a full GPU reset. Two independent patches to solve this are: "[PATCH] drm/i915: Update ring space correctly on lrc context reset" by Mika Kuoppala and "[51/70] drm/i915: Record the position of the start of the request" by Chris Wilson. Since the solution is currently in review I'll simply mention it here as a pre-requistite for long-duration operations stability testing. Without a fix for this problem the ring space is terminally depleted within the first iterations of the hang test, simply because the ring space is miscalculated following every GPU hang recovery and traversal of the GEM init hw path gradually leading to a terminally hung state. Tomas Elf (8): drm/i915: Early exit from semaphore_waits_for for execlist mode. drm/i915: Migrate to safe iterators in error state capture drm/i915: Cope with request list state change during error state capture drm/i915: NULL checking when capturing buffer objects during error state capture drm/i915: vma NULL pointer check drm/i915: Use safe list iterators drm/i915: Grab execlist spinlock to avoid post-reset concurrency issues. drm/i915: NULL check of unpin_work drivers/gpu/drm/i915/i915_gem.c | 18 --- drivers/gpu/drm/i915/i915_gpu_error.c | 61 +++ drivers/gpu/drm/i915/i915_irq.c | 20 drivers/gpu/drm/i915/intel_display.c | 5 +++ 4 files changed, 80 insertions(+), 24 deletions(-) -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/8] drm/i915: Migrate to safe iterators in error state capture
Using safe list iterators alleviates the problem of unsynchronized driver list manipulations while error state capture is in the process of traversing lists. Signed-off-by: Tomas Elf--- drivers/gpu/drm/i915/i915_gpu_error.c | 38 +-- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 2f04e4f..32c1799 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -718,10 +718,10 @@ static void capture_bo(struct drm_i915_error_buffer *err, static u32 capture_active_bo(struct drm_i915_error_buffer *err, int count, struct list_head *head) { - struct i915_vma *vma; + struct i915_vma *vma, *tmpvma; int i = 0; - list_for_each_entry(vma, head, mm_list) { + list_for_each_entry_safe(vma, tmpvma, head, mm_list) { capture_bo(err++, vma); if (++i == count) break; @@ -734,17 +734,17 @@ static u32 capture_pinned_bo(struct drm_i915_error_buffer *err, int count, struct list_head *head, struct i915_address_space *vm) { - struct drm_i915_gem_object *obj; + struct drm_i915_gem_object *obj, *tmpobj; struct drm_i915_error_buffer * const first = err; struct drm_i915_error_buffer * const last = err + count; - list_for_each_entry(obj, head, global_list) { - struct i915_vma *vma; + list_for_each_entry_safe(obj, tmpobj, head, global_list) { + struct i915_vma *vma, *tmpvma; if (err == last) break; - list_for_each_entry(vma, >vma_list, vma_link) + list_for_each_entry_safe(vma, tmpvma, >vma_list, vma_link) if (vma->vm == vm && vma->pin_count > 0) capture_bo(err++, vma); } @@ -958,13 +958,13 @@ static void i915_gem_record_active_context(struct intel_engine_cs *ring, struct drm_i915_error_ring *ering) { struct drm_i915_private *dev_priv = ring->dev->dev_private; - struct drm_i915_gem_object *obj; + struct drm_i915_gem_object *obj, *tmpobj; /* Currently render ring is the only HW context user */ if (ring->id != RCS || !error->ccid) return; - list_for_each_entry(obj, _priv->mm.bound_list, global_list) { + list_for_each_entry_safe(obj, tmpobj, _priv->mm.bound_list, global_list) { if (!i915_gem_obj_ggtt_bound(obj)) continue; @@ -979,7 +979,7 @@ static void i915_gem_record_rings(struct drm_device *dev, struct drm_i915_error_state *error) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_request *request; + struct drm_i915_gem_request *request, *tmpreq; int i, count; for (i = 0; i < I915_NUM_RINGS; i++) { @@ -1055,7 +1055,7 @@ static void i915_gem_record_rings(struct drm_device *dev, i915_gem_record_active_context(ring, error, >ring[i]); count = 0; - list_for_each_entry(request, >request_list, list) + list_for_each_entry_safe(request, tmpreq, >request_list, list) count++; error->ring[i].num_requests = count; @@ -1068,7 +1068,7 @@ static void i915_gem_record_rings(struct drm_device *dev, } count = 0; - list_for_each_entry(request, >request_list, list) { + list_for_each_entry_safe(request, tmpreq, >request_list, list) { struct drm_i915_error_request *erq; erq = >ring[i].requests[count++]; @@ -1088,17 +1088,17 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv, const int ndx) { struct drm_i915_error_buffer *active_bo = NULL, *pinned_bo = NULL; - struct drm_i915_gem_object *obj; - struct i915_vma *vma; + struct drm_i915_gem_object *obj, *tmpobj; + struct i915_vma *vma, *tmpvma; int i; i = 0; - list_for_each_entry(vma, >active_list, mm_list) + list_for_each_entry_safe(vma, tmpvma, >active_list, mm_list) i++; error->active_bo_count[ndx] = i; - list_for_each_entry(obj, _priv->mm.bound_list, global_list) { - list_for_each_entry(vma, >vma_list, vma_link) + list_for_each_entry_safe(obj, tmpobj, _priv->mm.bound_list, global_list) { + list_for_each_entry_safe(vma, tmpvma, >vma_list, vma_link) if (vma->vm == vm && vma->pin_count > 0) i++; } @@ -1128,10 +1128,10 @@ static void
[Intel-gfx] [PATCH 3/8] drm/i915: Cope with request list state change during error state capture
Since we're not synchronizing the ring request list during error state capture the request list state might change between the time the corresponding error request list was allocated and dimensioned to the time when the ring request list is actually captured into the error state. If this happens, throw a WARNING and do early exit and be aware that the captured error state might not be fully reliable. Signed-off-by: Tomas Elf--- drivers/gpu/drm/i915/i915_gpu_error.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 32c1799..cc75ca4 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1071,6 +1071,19 @@ static void i915_gem_record_rings(struct drm_device *dev, list_for_each_entry_safe(request, tmpreq, >request_list, list) { struct drm_i915_error_request *erq; + if (WARN_ON(!request || count >= error->ring[i].num_requests)) { + /* +* If the ring request list was changed in +* between the point where the error request +* list was created and dimensioned and this +* point then just update the num_requests +* field to reflect this. +*/ + error->ring[i].num_requests = + min(count, error->ring[i].num_requests); + break; + } + erq = >ring[i].requests[count++]; erq->seqno = request->seqno; erq->jiffies = request->emitted_jiffies; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx