Search Linux Wireless

Interrupt threads vs. tasklets (rt2x00 related)

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

 



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
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux