In-depth analysis of the dev_id Parameter Function of request_irq

Source: Internet
Author: User
Request_irq applies to use IRQ and registers the interrupt handler. The prototype of the request_irq () function is as follows:/* kernel/IRQ/manage. C */INT request_irq (unsigned int IRQ, irqreturn_t (* Handler) (INT, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void * dev_id ); we know that when kernel sharing is interrupted, request_irq must provide the dev_id parameter and the value of dev_id must be unique. So what exactly is the use of the unique dev_id value provided here? At first, I thought that the value of dev_id was provided to the kernel to determine which device on the shared interrupt line was interrupted (that is, which irqaction was interrupted ), then execute the corresponding interrupt processing function (irqaction-> handler ). Actually, it is not. Let's take a look at the shared Handlers section in Chapter 6 of Linux kernel development-Second edition. The summary text is as follows, it invokes sequentially each registered handler on the line. therefore, it is important that the handler be capable of distinguishing whether it generated a given interrupt. the handler must quickly exit if its associated device did not generate the interrupt. this requi Res the hardware device to have a status register (or similar mechanic) that the handler can check. most hardware does indeed have such a feature. in this section, the kernel does not determine which device on the shared interrupt line is interrupted when an interruption occurs, it cyclically executes all the interrupt processing functions (irqaction-> handler functions) for online registration of the interrupt ). Therefore, the irqaction-> handler function is responsible for identifying whether your hardware device has encountered an interruption and then executing the interrupt processing function. It is usually determined by reading the interrupt flag Flag provided by the hardware device. Now that the kernel cyclically executes all irqaction-> handler functions for online registration of the interrupt, it submits the process of identifying which hardware device has an interrupt to the interrupt handler itself, what is the use of the dev_id parameter of request_irq? I have summarized that dev_id has two main functions: 1. when the interrupt handler is released, use dev_id: when your driver unloads, You need to unregister your interrupt handler and potentially disable the interrupt line. to do this, callvoid free_irq (unsigned int IRQ, void * dev_id )...... The specified th parameter, dev_id, is used primarily for shared interrupt lines. when an interrupt handler is freed (discussed later), dev_id provides a unique cookie to allow the removal of only the desired interrupt handler from the interrupt line. without this parameter, it wocould be impossible for the kernel to know which handler to remove on a given interrupt line. here, lkd2 makes it clear that when calling free_irq to deregister the interrupt processing function (When the driver is often uninstalled, the function will be canceled.) Because dev_id is unique, therefore, it can be used to determine how to delete a specified interrupt handler from multiple interrupt handlers on the shared interrupt line. Without this parameter, it is impossible for the kernel to know which handler is to be deleted for the given interrupt line. Next let's take a look at the free_irq code: void free_irq (unsigned int IRQ, void * dev_id) {struct irq_desc * DESC; struct irqaction ** P; unsigned long flags; warn_on (in_interrupt (); If (IRQ> = nr_irqs) return; DESC = irq_desc + IRQ; /* obtain the irq_desc */spin_lock_irqsave (& desc-> lock, flags) corresponding to the interrupt number; P = & desc-> action; /* Find the irqaction linked list */For (;) {struct irqaction * Action = * P; If (Action) {struct irqaction ** pp = P; P = & Action-> next; If (action-> dev_id! = Dev_id) continue;/* the two sentences are cyclically judged, until you find the irqaction * // * found it-now remove it from the list of entries */* PP = action-> next; /* points to the next irqaction * // * currently used only by UML, might disappear one day. */# ifdef config_irq_release_method if (desc-> chip-> release) desc-> chip-> release (IRQ, dev_id); # endif if (! Desc-> action) {desc-> Status | = irq_disabled; If (desc-> chip-> shutdown) desc-> chip-> Shutdown (IRQ ); else desc-> chip-> disable (IRQ);} recalculate_desc_flags (DESC); spin_unlock_irqrestore (& desc-> lock, flags); unregister_handler_proc (IRQ, action ); /* Make sure it's not being used on another CPU */synchronize_irq (IRQ); kfree (action);/* Delete the irqaction of the device (dev_id) */return ;} printk (kern_err "trying to Fr EE already-free IRQ % d \ n ", IRQ); spin_unlock_irqrestore (& desc-> lock, flags); Return ;}} II. pass the device struct that uses the interrupt handler to the interrupt handler. First, consider the following two prerequisites: 1) Each device struct in the kernel must be unique, therefore, the only requirement of dev_id is met. 2) The dev_id parameter will be passed to the service program that interrupts the operation. A typical interrupt service program is defined as follows: static irqreturn_t intr_handler (int irq, void * dev_id, struct pt_regs * regs); that is, the dev_id parameter of request_irq is passed to the dev_id of the interrupt service program. Therefore, the device structure of the driver can be passed to the interrupt service program through dev_id. In this way, there are two main functions: 1) the interrupt service program may use the information in the device structure, such as the IIS audio driver of S3c2410, it is to pass the DMA channel struct to the interrupt service program/* ARCH/ARM/mach-s3c2410/DMA through dev_id. C */INT s3c2410_dma_request (unsigned int channel, struct s3c2410_dma_client * client, void * Dev) {err = request_irq (Chan-> IRQ, scheme, ir1__disabled, client-> name, (void *) Chan );......} The purpose is to use the DUF and load_state members of the Chan struct In the interrupt processing function s3c2410_dma_irq. The usage is as follows:/* ARCH/ARM/mach-s3c2410/DMA. C */static irqreturn_ts3c2410_dma_irq (int irq, void * devpw, struct pt_regs * regs) {struct s3c2410_dma_chan * Chan = (struct s3c2410_dma_chan *) devpw; /* The device type that is forcibly converted to request_irq when it is passed to dev_id. In this example, It is s3c2410_dma_chan. You can use it */struct s3c2410_dma_buf * Buf; Buf = Chan-> curr ;......} Therefore, we can pass the device structure to the dev_id parameter of request_irq by using the device struct In the interrupt processing function, which is a common approach for most drivers. 2) As mentioned above, if shared interrupt is used, the interrupt handler itself needs to be able to identify whether its own device has encountered an interrupt. This is usually determined by reading the interrupt flag signs provided by the hardware device. The device struct defined in the driver usually contains the IO address of the device. With the offset, you can calculate the IO address information of the interrupt Status Register and the interrupt flag Flag flag. Therefore, another function of passing the device struct to the device interrupt handler through dev_id is to use the shared interrupt function to read the device structure (dev_id) the flag address information provided in the interrupt flag is used to determine whether the device is interrupted, and then determine whether to continue or skip to the next irqaction-> handler function and then determine whether to execute. Of course, if you already know the IO address of the device interrupt Status Register, you can also select readl to determine the address information directly.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.