Документ взят из кэша поисковой машины. Адрес оригинального документа : http://mavr.sao.ru/hq/sts/linux/doc/porting_to_26/23625.html
Дата изменения: Unknown
Дата индексирования: Fri Dec 28 19:25:51 2007
Кодировка:

Поисковые слова: star formation
LWN: Driver porting: dealing with interrupts
LWN.net Logo

 
Sponsored Link
Mandrake 10 and Training

Mandrake 10 Community release $3.89 with 4 hours of audio/video movies only $17.95 OpenOffice book included $26.95


 
Summary page
Return to the Kernel page
 
Recent Features

LWN.net Weekly Edition for March 18, 2004

LWN.net Weekly Edition for March 11, 2004

The annotated SCO stock price chart

A grumpy editor's calendar search

LWN.net Weekly Edition for March 4, 2004

Printable page
 

 

Driver porting: dealing with interrupts

This article is part of the LWN Porting Drivers to 2.6 series.
The kernel's handling of device interrupts has been massively reworked in the 2.6 series. Fortunately, very few of those changes are visible to the rest of the kernel; most well-written code should "just work" (almost) under 2.6. There are, however, two important exceptions: the return type of interrupt handlers has changed, and drivers which depend on being able to globally disable interrupts will require some changes for 2.6.

Interrupt handler return values

Prior to 2.5.69, interrupt handlers returned void. There is, however, one useful thing that interrupt handlers can tell the kernel: whether the interrupt was something they could handle or not. If a device starts generating spurious interrupts, the kernel would like to respond by blocking interrupts from that device. If no interrupt handler for a given IRQ has been registered, the kernel knows that any interrupt on that number is spurious. When interrupt handlers exist, however, they must tell the kernel about spurious interrupts.

So, interrupt handlers now return an irqreturn_t value; void handlers will no longer compile. If your interrupt handler recognizes and handles a given interrupt, it should return IRQ_HANDLED. If it knows that the interrupt was not on a device it manages, it can return IRQ_NONE instead. The macro:

    IRQ_RETVAL(handled)

can also be used; handled should be nonzero if the handler could deal with the interrupt. The "safe" value to return, if, for some reason you are not sure, is IRQ_HANDLED.

Disabling interrupts

In the 2.6 kernel, it is no longer possible to globally disable interrupts. In particular, the cli(), sti(), save_flags(), and restore_flags() functions are no longer available. Disabling interrupts across all processors in the system is simply no longer done. This behavior has been strongly discouraged for some time, so most code should have been converted by now.

The proper way to do this fixing, of course, is to figure out exactly which resources were being protected by disabling interrupts. Those resources can then be explicitly protected with spinlocks instead. The change is usually fairly straightforward, but it does require an understanding of what is really going on.

It is still possible to disable all interrupts locally with local_save_flags() or local_irq_disable(). A single interrupt can be disabled globally with disable_irq(). Some of the spinlock operations also disable interrupts on the local processor, of course. None of these functions are changed (at least, with regard to their external interface) since 2.4.

Various small changes

One function that has changed is synchronize_irq(). In 2.6, this function takes an integer IRQ number as a parameter. It spins until no interrupt handler is running for the given IRQ. If the IRQ is disabled prior to calling synchronize_irq(), the caller will know that no interrupt handler can be running after that call. The 2.6 version of synchronize_irq() only waits for handlers for the given IRQ number; it is no longer possible to wait until no interrupt handlers at all are running.

If your code has post-interrupt logic which runs as a bottom half, or out of a task queue, it will need to be changed for 2.6. Bottom halves are deprecated, and the task queue mechanism has been removed altogether. Post-interrupt processing should now be done using tasklets or work queues.

A new function was added in 2.6.1:

    int can_request_irq(unsigned int irq, unsigned long flags);

This function returns a true value if the given interrupt allocation request would succeed, but does not actually allocate anything. Potential users should always be aware that the situation could change after calling can_request_irq().

Finally, the declarations of request_irq() and free_irq() have moved from <linux/sched.h> to <linux/interrupt.h>.


No comments have been posted. Post one now

Copyright (©) 2003, Eklektix, Inc.
Linux (®) is a registered trademark of Linus Torvalds
Powered by Rackspace Managed Hosting.