Remove the racy try_irq/check_irq/undo_irq interface, and try to register the correct handler directly in pcmcia_request_irq(). Also, remove the unneeded database in rsrc_mgr, as the kernel IRQ subsystem does that for us. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cs.c | 107 +++++++++++++++++++++----------------- drivers/pcmcia/cs_internal.h | 2 drivers/pcmcia/rsrc_mgr.c | 118 ------------------------------------------- 3 files changed, 59 insertions(+), 168 deletions(-) Index: 2.6.10/drivers/pcmcia/cs.c =================================================================== --- 2.6.10.orig/drivers/pcmcia/cs.c 2004-12-26 14:52:31.737604481 +0100 +++ 2.6.10/drivers/pcmcia/cs.c 2004-12-26 14:56:02.155775943 +0100 @@ -1296,11 +1296,6 @@ free_irq(req->AssignedIRQ, req->Instance); } -#ifdef CONFIG_PCMCIA_PROBE - if (req->AssignedIRQ != s->pci_irq) - undo_irq(req->Attributes, req->AssignedIRQ); -#endif - return CS_SUCCESS; } /* cs_release_irq */ @@ -1532,65 +1527,79 @@ ======================================================================*/ +#ifdef CONFIG_PCMCIA_PROBE +static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + return IRQ_NONE; +} +#endif + int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) { - struct pcmcia_socket *s; - config_t *c; - int ret = CS_IN_USE, irq = 0; - struct pcmcia_device *p_dev = handle_to_pdev(handle); - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - c = CONFIG(handle); - if (c->state & CONFIG_LOCKED) - return CS_CONFIGURATION_LOCKED; - if (c->state & CONFIG_IRQ_REQ) - return CS_IN_USE; + struct pcmcia_socket *s; + config_t *c; + int ret = CS_IN_USE, irq = 0; + struct pcmcia_device *p_dev = handle_to_pdev(handle); + + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + s = SOCKET(handle); + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + c = CONFIG(handle); + if (c->state & CONFIG_LOCKED) + return CS_CONFIGURATION_LOCKED; + if (c->state & CONFIG_IRQ_REQ) + return CS_IN_USE; #ifdef CONFIG_PCMCIA_PROBE if (s->irq.AssignedIRQ != 0) { /* If the interrupt is already assigned, it must be the same */ irq = s->irq.AssignedIRQ; } else { - u_int try, mask = s->irq_mask; - for (try = 0; try < 2; try++) { - for (irq = 0; irq < 32; irq++) { - if ((mask >> irq) & 1) { - ret = try_irq(req->Attributes, irq, try); - if (!ret) - break; + u32 mask = s->irq_mask; + void *data = NULL; + + for (irq = 0; irq < 32; irq++) { + if ((mask >> irq) & 1) { + ret = request_irq(irq, + (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, + ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || + (s->functions > 1) || + (irq == s->pci_irq)) ? SA_SHIRQ : 0, + p_dev->dev.bus_id, + (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); + if (!ret) { + if (!(req->Attributes & IRQ_HANDLE_PRESENT)) + free_irq(irq, data); + break; } } - if (!ret) - break; } } #endif - if (ret != 0) { - if (!s->pci_irq) - return ret; - irq = s->pci_irq; - } + if (ret) { + if (!s->pci_irq) + return ret; + irq = s->pci_irq; + } - if (req->Attributes & IRQ_HANDLE_PRESENT) { - if (request_irq(irq, req->Handler, - ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || - (s->functions > 1) || - (irq == s->pci_irq)) ? SA_SHIRQ : 0, - p_dev->dev.bus_id, req->Instance)) - return CS_IN_USE; - } + if (ret && req->Attributes & IRQ_HANDLE_PRESENT) { + if (request_irq(irq, req->Handler, + ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || + (s->functions > 1) || + (irq == s->pci_irq)) ? SA_SHIRQ : 0, + p_dev->dev.bus_id, req->Instance)) + return CS_IN_USE; + } - c->irq.Attributes = req->Attributes; - s->irq.AssignedIRQ = req->AssignedIRQ = irq; - s->irq.Config++; - - c->state |= CONFIG_IRQ_REQ; - handle->state |= CLIENT_IRQ_REQ; - return CS_SUCCESS; + c->irq.Attributes = req->Attributes; + s->irq.AssignedIRQ = req->AssignedIRQ = irq; + s->irq.Config++; + + c->state |= CONFIG_IRQ_REQ; + handle->state |= CLIENT_IRQ_REQ; + return CS_SUCCESS; } /* pcmcia_request_irq */ /*====================================================================== Index: 2.6.10/drivers/pcmcia/cs_internal.h =================================================================== --- 2.6.10.orig/drivers/pcmcia/cs_internal.h 2004-12-26 14:50:41.816186762 +0100 +++ 2.6.10/drivers/pcmcia/cs_internal.h 2004-12-26 14:56:00.469015056 +0100 @@ -140,8 +140,6 @@ unsigned long r_end, struct pcmcia_socket *s); struct resource *find_mem_region(u_long base, u_long num, u_long align, int low, struct pcmcia_socket *s); -int try_irq(u_int Attributes, int irq, int specific); -void undo_irq(u_int Attributes, int irq); int adjust_resource_info(client_handle_t handle, adjust_t *adj); void release_resource_db(struct pcmcia_socket *s); Index: 2.6.10/drivers/pcmcia/rsrc_mgr.c =================================================================== --- 2.6.10.orig/drivers/pcmcia/rsrc_mgr.c 2004-12-26 14:52:32.589483720 +0100 +++ 2.6.10/drivers/pcmcia/rsrc_mgr.c 2004-12-26 14:56:29.505898834 +0100 @@ -34,122 +34,6 @@ #include #include "cs_internal.h" -static DECLARE_MUTEX(rsrc_sem); - -#ifdef CONFIG_PCMCIA_PROBE - -typedef struct irq_info_t { - u_int Attributes; - int time_share, dyn_share; - struct pcmcia_socket *Socket; -} irq_info_t; - -/* Table of IRQ assignments */ -static irq_info_t irq_table[NR_IRQS]; - -#endif - - -/*====================================================================== - - This checks to see if an interrupt is available, with support - for interrupt sharing. We don't support reserving interrupts - yet. If the interrupt is available, we allocate it. - -======================================================================*/ - -#ifdef CONFIG_PCMCIA_PROBE - -static irqreturn_t fake_irq(int i, void *d, struct pt_regs *r) { return IRQ_NONE; } -static inline int check_irq(int irq) -{ - if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0) - return -1; - free_irq(irq, NULL); - return 0; -} - -int try_irq(u_int Attributes, int irq, int specific) -{ - irq_info_t *info = &irq_table[irq]; - int ret = 0; - - down(&rsrc_sem); - if (info->Attributes & RES_ALLOCATED) { - switch (Attributes & IRQ_TYPE) { - case IRQ_TYPE_EXCLUSIVE: - ret = CS_IN_USE; - break; - case IRQ_TYPE_DYNAMIC_SHARING: - if ((info->Attributes & RES_IRQ_TYPE) - != RES_IRQ_TYPE_DYNAMIC) { - ret = CS_IN_USE; - break; - } - if (Attributes & IRQ_FIRST_SHARED) { - ret = CS_BAD_ATTRIBUTE; - break; - } - info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED; - info->dyn_share++; - break; - } - } else { - if ((info->Attributes & RES_RESERVED) && !specific) { - ret = CS_IN_USE; - goto out; - } - if (check_irq(irq) != 0) { - ret = CS_IN_USE; - goto out; - } - switch (Attributes & IRQ_TYPE) { - case IRQ_TYPE_EXCLUSIVE: - info->Attributes |= RES_ALLOCATED; - break; - case IRQ_TYPE_DYNAMIC_SHARING: - if (!(Attributes & IRQ_FIRST_SHARED)) { - ret = CS_BAD_ATTRIBUTE; - break; - } - info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED; - info->dyn_share = 1; - break; - } - } - out: - up(&rsrc_sem); - return ret; -} - -#endif - -/*====================================================================*/ - -#ifdef CONFIG_PCMCIA_PROBE - -void undo_irq(u_int Attributes, int irq) -{ - irq_info_t *info; - - info = &irq_table[irq]; - down(&rsrc_sem); - switch (Attributes & IRQ_TYPE) { - case IRQ_TYPE_EXCLUSIVE: - info->Attributes &= RES_RESERVED; - break; - case IRQ_TYPE_DYNAMIC_SHARING: - info->dyn_share--; - if (info->dyn_share == 0) - info->Attributes &= RES_RESERVED; - break; - } - up(&rsrc_sem); -} - -#endif - -/*====================================================================*/ #ifdef CONFIG_PCMCIA_PROBE @@ -167,7 +51,7 @@ mask = 1 << irq; - if !(s->irq_mask & mask) + if (!(s->irq_mask & mask)) return 0; s->irq_mask &= ~mask;