linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Interrupt threads vs. tasklets (rt2x00 related)
@ 2010-11-05  9:21 Helmut Schaa
  0 siblings, 0 replies; only message in thread
From: Helmut Schaa @ 2010-11-05  9:21 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ivo van Doorn

Hi,

we've just discussed a rt2x00 related problem that resulted in a few questions
around interrupt threads vs. tasklets.

At the moment, we do the following:

interrupt_handler()
	ack_irq
	save_irq_value
	mask_all_irqs_in_hw
	wake_irq_thread

interrupt_thread()
	read_irq_value
	if (irq & RX_INT)
		process_rx
	if (irq & TBTT)
		process_tbtt
	...
	enable_all_irqs_in_hw

The same approach is also taken by b43 for example.

The problem I've seen (on a slow MIPS machine under high load) was that a new
RX int could happen in the time window between process_rx finished and the 
enabling of the device irqs.

Basically this wouldn't be such a big problem since we will process the
received frame together with the next rx irq invocation. But in some unlikely
situations (which are reproducible under high traffic + CPU load after "some"
time) that didn't happen due to the rx queue filling up completely and the
last free buffer is the one not getting processed. Hence, the hw won't emit
a new interrupt since it still thinks the queue is full (even though the other
entries are already marked as free). This results in the RX queue getting
stuck ...

Second, disabling all other interrupts while processing just one interrupt
might results in other interrupts getting dropped. For example while processing
rx interrupts the tbtt interrupt might get lost. However, I haven't managed to
really make that happen while experimenting.

Now, with tasklets for example, we could do the following:

interrupt_handler()
	ack_irq
	if (irq & RX_INT)
		mask_rx_int
		schedule_rx_tasklet
	if (irq & TBTT)
		mask_tbtt_int
		schedule_tbtt_tasklet

rx_tasklet()
	process_rx
	enable_rx_int

tbtt_tasklet()
	process_tbtt
	enable_tbtt_int

That should mitigate the race since the interrupts are enabled directly before
the tasklet finishes.

Another possibility to achieve the same (?) would be something like this (using
interrupt threads):

interrupt_handler()
	ack_irq
	update_irqvalue
	wake_irq_thread

interrupt_thread()
	while(read_irq_value)
		if (irq & RX_INT)
			disable_rx_int
			process_rx
			enable_rx_int
		if (irq & TBTT)
			disable_tbtt_int
			process_tbtt
			enable_tbtt_int

This would disable single interrupts just while they get processed which should
have the same effect as the tasklet approach.

So, what would be a reasonable way to solve that issue?
What about b43, does that suffer from the same?

Thanks a lot,
Helmut

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2010-11-05  9:22 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-05  9:21 Interrupt threads vs. tasklets (rt2x00 related) Helmut Schaa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).