diff options
Diffstat (limited to 'driver/int.c')
-rw-r--r-- | driver/int.c | 226 |
1 files changed, 113 insertions, 113 deletions
diff --git a/driver/int.c b/driver/int.c index 5dbcb7f..f78c6ec 100644 --- a/driver/int.c +++ b/driver/int.c @@ -9,7 +9,7 @@ /* * Change History: - * + * * $Log: not supported by cvs2svn $ * Revision 1.7 2008-01-11 10:18:28 marcus * Modified interrupt mechanism. Added atomic functions and queues, to address race conditions. Removed unused interrupt code. @@ -60,7 +60,7 @@ /* * The ID between IRQ_SOURCE in irq_outstanding and the actual source is arbitrary. - * Therefore, be careful when communicating with multiple implementations. + * Therefore, be careful when communicating with multiple implementations. */ /* IRQ_SOURCES */ @@ -92,90 +92,90 @@ */ int pcidriver_probe_irq(pcidriver_privdata_t *privdata) { - unsigned char int_pin, int_line; - unsigned long bar_addr, bar_len, bar_flags; - int i; - int err; - - for (i = 0; i < 6; i++) - privdata->bars_kmapped[i] = NULL; - - for (i = 0; i < 6; i++) { - bar_addr = pci_resource_start(privdata->pdev, i); - bar_len = pci_resource_len(privdata->pdev, i); - bar_flags = pci_resource_flags(privdata->pdev, i); - - /* check if it is a valid BAR, skip if not */ - if ((bar_addr == 0) || (bar_len == 0)) - continue; - - /* Skip IO regions (map only mem regions) */ - if (bar_flags & IORESOURCE_IO) - continue; - - /* Check if the region is available */ - if ((err = pci_request_region(privdata->pdev, i, NULL)) != 0) { - mod_info( "Failed to request BAR memory region.\n" ); - return err; - } - - /* Map it into kernel space. */ - /* For x86 this is just a dereference of the pointer, but that is - * not portable. So we need to do the portable way. Thanks Joern! - */ - - /* respect the cacheable-bility of the region */ - if (bar_flags & IORESOURCE_PREFETCH) - privdata->bars_kmapped[i] = ioremap(bar_addr, bar_len); - else - privdata->bars_kmapped[i] = ioremap_nocache(bar_addr, bar_len); - - /* check for error */ - if (privdata->bars_kmapped[i] == NULL) { - mod_info( "Failed to remap BAR%d into kernel space.\n", i ); - return -EIO; - } - } - - /* Initialize the interrupt handler for this device */ - /* Initialize the wait queues */ - for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) { - init_waitqueue_head(&(privdata->irq_queues[i])); - atomic_set(&(privdata->irq_outstanding[i]), 0); - } - - /* Initialize the irq config */ - if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &int_pin)) != 0) { - /* continue without interrupts */ - int_pin = 0; - mod_info("Error getting the interrupt pin. Disabling interrupts for this device\n"); - } - - /* Disable interrupts and activate them if everything can be set up properly */ - privdata->irq_enabled = 0; - - if (int_pin == 0) - return 0; - - if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &int_line)) != 0) { - mod_info("Error getting the interrupt line. Disabling interrupts for this device\n"); - return 0; - } - - /* Enable interrupts using MSI mode */ - if (!pci_enable_msi(privdata->pdev)) - privdata->msi_mode = 1; - - /* register interrupt handler */ - if ((err = request_irq(privdata->pdev->irq, pcidriver_irq_handler, MODNAME, privdata)) != 0) { - mod_info("Error registering the interrupt handler. Disabling interrupts for this device\n"); - return 0; - } - - privdata->irq_enabled = 1; - mod_info("Registered Interrupt Handler at pin %i, line %i, IRQ %i\n", int_pin, int_line, privdata->pdev->irq ); - - return 0; + unsigned char int_pin, int_line; + unsigned long bar_addr, bar_len, bar_flags; + int i; + int err; + + for (i = 0; i < 6; i++) + privdata->bars_kmapped[i] = NULL; + + for (i = 0; i < 6; i++) { + bar_addr = pci_resource_start(privdata->pdev, i); + bar_len = pci_resource_len(privdata->pdev, i); + bar_flags = pci_resource_flags(privdata->pdev, i); + + /* check if it is a valid BAR, skip if not */ + if ((bar_addr == 0) || (bar_len == 0)) + continue; + + /* Skip IO regions (map only mem regions) */ + if (bar_flags & IORESOURCE_IO) + continue; + + /* Check if the region is available */ + if ((err = pci_request_region(privdata->pdev, i, NULL)) != 0) { + mod_info( "Failed to request BAR memory region.\n" ); + return err; + } + + /* Map it into kernel space. */ + /* For x86 this is just a dereference of the pointer, but that is + * not portable. So we need to do the portable way. Thanks Joern! + */ + + /* respect the cacheable-bility of the region */ + if (bar_flags & IORESOURCE_PREFETCH) + privdata->bars_kmapped[i] = ioremap(bar_addr, bar_len); + else + privdata->bars_kmapped[i] = ioremap_nocache(bar_addr, bar_len); + + /* check for error */ + if (privdata->bars_kmapped[i] == NULL) { + mod_info( "Failed to remap BAR%d into kernel space.\n", i ); + return -EIO; + } + } + + /* Initialize the interrupt handler for this device */ + /* Initialize the wait queues */ + for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) { + init_waitqueue_head(&(privdata->irq_queues[i])); + atomic_set(&(privdata->irq_outstanding[i]), 0); + } + + /* Initialize the irq config */ + if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &int_pin)) != 0) { + /* continue without interrupts */ + int_pin = 0; + mod_info("Error getting the interrupt pin. Disabling interrupts for this device\n"); + } + + /* Disable interrupts and activate them if everything can be set up properly */ + privdata->irq_enabled = 0; + + if (int_pin == 0) + return 0; + + if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &int_line)) != 0) { + mod_info("Error getting the interrupt line. Disabling interrupts for this device\n"); + return 0; + } + + /* Enable interrupts using MSI mode */ + if (!pci_enable_msi(privdata->pdev)) + privdata->msi_mode = 1; + + /* register interrupt handler */ + if ((err = request_irq(privdata->pdev->irq, pcidriver_irq_handler, MODNAME, privdata)) != 0) { + mod_info("Error registering the interrupt handler. Disabling interrupts for this device\n"); + return 0; + } + + privdata->irq_enabled = 1; + mod_info("Registered Interrupt Handler at pin %i, line %i, IRQ %i\n", int_pin, int_line, privdata->pdev->irq ); + + return 0; } /** @@ -185,16 +185,16 @@ int pcidriver_probe_irq(pcidriver_privdata_t *privdata) */ void pcidriver_remove_irq(pcidriver_privdata_t *privdata) { - /* Release the IRQ handler */ - if (privdata->irq_enabled != 0) - free_irq(privdata->pdev->irq, privdata); - - if (privdata->msi_mode) { - pci_disable_msi(privdata->pdev); - privdata->msi_mode = 0; - } - - pcidriver_irq_unmap_bars(privdata); + /* Release the IRQ handler */ + if (privdata->irq_enabled != 0) + free_irq(privdata->pdev->irq, privdata); + + if (privdata->msi_mode) { + pci_disable_msi(privdata->pdev); + privdata->msi_mode = 0; + } + + pcidriver_irq_unmap_bars(privdata); } /** @@ -204,15 +204,15 @@ void pcidriver_remove_irq(pcidriver_privdata_t *privdata) */ void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata) { - int i; + int i; - for (i = 0; i < 6; i++) { - if (privdata->bars_kmapped[i] == NULL) - continue; + for (i = 0; i < 6; i++) { + if (privdata->bars_kmapped[i] == NULL) + continue; - iounmap((void*)privdata->bars_kmapped[i]); - pci_release_region(privdata->pdev, i); - } + iounmap((void*)privdata->bars_kmapped[i]); + pci_release_region(privdata->pdev, i); + } } /** @@ -227,15 +227,15 @@ void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata) */ static bool pcidriver_irq_acknowledge(pcidriver_privdata_t *privdata) { - int channel = 0; + int channel = 0; // volatile unsigned int *bar; // bar = privdata->bars_kmapped[0]; // mod_info_dbg("interrupt registers. ISR: %x, IER: %x\n", bar[ABB_INT_STAT], bar[ABB_INT_ENABLE]); - atomic_inc(&(privdata->irq_outstanding[channel])); - wake_up_interruptible(&(privdata->irq_queues[channel])); - - return true; + atomic_inc(&(privdata->irq_outstanding[channel])); + wake_up_interruptible(&(privdata->irq_queues[channel])); + + return true; } /** @@ -248,11 +248,11 @@ static bool pcidriver_irq_acknowledge(pcidriver_privdata_t *privdata) */ IRQ_HANDLER_FUNC(pcidriver_irq_handler) { - pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)dev_id; + pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)dev_id; - if (!pcidriver_irq_acknowledge(privdata)) - return IRQ_NONE; + if (!pcidriver_irq_acknowledge(privdata)) + return IRQ_NONE; - privdata->irq_count++; - return IRQ_HANDLED; + privdata->irq_count++; + return IRQ_HANDLED; } |