proposals/questions about the IRQ registers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jul 08, 2013 at 05:20:21PM -0300, Paulo Zanoni wrote:
> Hi
> 
> Due to the current features that I'm implementing I started looking at
> our interrupt code so I can reuse it. I noticed quite a few details
> and potential problems, and I can write patches for them, but first I
> think I should ask some questions to make sure I won't spend a big
> time writing patches that get NACKed because of a small detail I
> missed.
> 
> Here's a list of questions/problems:
> 
> 1 - IRQ preinstall/uninstall
> 
> One of Daniel's comments implied that runing irq_uninstall should
> leave the hardware in the same state as runing irq_preinstall. I also
> read Documentation/DocBook/drm.tmpl and the text suggests the same
> thing. On our driver, we have the following differences between
> irq_uninstall and irq_preinstall:
> 
> - irq_uninstall clears the IIR registers
> - irq_preinstall calls posting_read on the IER registers
> - HSWSTAM is set differently
> - some registers are only present in one of the functions (e.g,
> GEN6_PMI* is reset at preinstall, but it's completely forgotten at
> uninstall)
> 
> Why do we have these differences? We could save a lot of source code
> lines by merging chunks of the irq_uninstall and irq_preinstall
> functions. We could make both functions clear the IIR register, and
> also do the posting_read if needed. If I propose such patches, is
> anybody going to reject them?

I think the right sequence in preinstall for the usul interrupts register
with 4 regs (IIR, ISR, IER and IMR) is:

1) mask everything in IMR, disable all interrupts in IER.
2) posting read on IER
3) clear IIR interrupts, posting read
4) repeat step 3)

With some C tricker that could be made to look rather tidy:

#define I915_DISABLE_AND_CLEAR_INTERRUPTS(prefix) \
	do { \
		I915_WRITE(prefix # IMR, 0xffffffff); \
		I915_WRITE(prefix # IER, 0); \
		POSTING_READ(prefix # IER); \
		I915_WRITE(prefix # IIR, 0xffffffff); \
		POSTING_READ(prefix # IIR); \
		I915_WRITE(prefix # IIR, 0xffffffff); \
		POSTING_READ(prefix # IIR); \
	} while (0)

and then in the code

	I915_DISABLE_AND_CLEAR_INTERRUPTS(GT);
	I915_DISABLE_AND_CLEAR_INTERRUPTS(DE);
	I915_DISABLE_AND_CLEAR_INTERRUPTS(GEN6_PM);

(totally untested, but I think you get the idea).

Sharing the code more between preinstall and uninstall on top of that
sounds nice.

> 2 - IIR register initialization
> 
> 2.1- Writing twice vs writing once
> 
> As documented on our specification, the IIR registers are capable of
> storing 2 interrupts, so if we get two interrupts and then write
> 0xFFFFFFFF to IIR, its value won't become 0, the bits that received 2
> interrupts will go back to 1. In most of our code, when we want to
> clear IIR we only do something like "I915_WRITE(XXX_IIR,
> I915_READ(XXX_IIR))", but this does not guarantee us that the XXX_IIR
> register will become 0. Shouldn't we write twice? Notice that GTIIR on
> valleyview_irq_preinstall is an exception.
> 
> If I write a patch adding a macro/inline-function
> intel_init_iir(uint32_t register) that writes twice to make sure the
> value is 0, is this okay? This may even solve bugs since when we
> initialize the HW there's no guarantee that all the IIR registers are
> zero.

See above my suggestion for solving the IER, IMR, IIR initial setup
sequence in preinstall and clearing them in the uninstall hook. Note that
we need the C trickery to have flexibilty in case the relative register
offsets of IIR, IMR IER ever changes.

> 2.2 - How we clear them
> 
> In most of the cases we do "I915_WRITE(XXX_IIR, I915_READ(XXX_IIR))".
> I understand this is what we should do after interrupts are processed,
> but when they are disabled, why not do I915_WRITE(XXX_IIR, 0xFFFFFFF)?
> That seems faster. We do this with the VLV_IIR register.
> 
> Anybody against changing the code to use 0xFFFFFFFF when interrupts
> are disabled?

I think it's a good idea, so I've used it in my example code above
already.

> 2.3 - The interrupt handler
> 
> On some interrupt handlers (e.g., ironlake_irq_handler) we only read
> the IIR register once and then clear it by rewriting the value we
> read. If we have 2 of the same interrupt stored in the queue, we will
> leave the IRQ handler with the IIR register with a non-zero value.
> Shouldn't we process the IIR registers on the IRQ handlers until they
> become zero? I patched my HSW machine to do this and it's working
> fine. I also expect this could make things a little bit faster or
> solve random bugs. Again, the valleyview_irq_handler function makes
> sure all IIR registers are zero.
> 
> Anybody against this?

I'm against looping in the interrupt handler since it's a really good way
to paper over bugs. E.g. I expect that the south interrupt race you've
fixed could be paper over this way. But it'll obviously not fix the
underlying issue correctly.

So I prefer our interrupt handling code to not have such loops if
possible.

> All these patches could be quite big, so an upfront ACK/NACK on each
> of the 4 proposals would be good. Anyway, if we get a NACK for
> something we should probably write patches changing VLV code that uses
> it

I think if you split up the patches into interrupt register
blocks/platforms we should be able to get things in pretty quickly. At
least we'll have minimal blockage if something suspicious pops up.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux