[patches 6/8] pcmcia: remove racy try_irq()
Dominik Brodowski
linux at dominikbrodowski.de
Tue Jan 11 11:59:00 EST 2005
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 <linux at brodo.de>
---
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 <pcmcia/cistpl.h>
#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;
More information about the linux-pcmcia
mailing list