aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>2005-06-21 20:16:19 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-21 22:07:32 -0400
commitdbce706e2550253c5ab6043f4f5dfde0cd02470f (patch)
tree5d96bab350d86e43e32faa80b64e05e7dc514ae8
parent5757b284a300e0e5d2173750906625b6470bd9f0 (diff)
[PATCH] uml: add and use generic hw_controller_type->release
With Chris Wedgwood <cw@f00f.org> Currently UML must explicitly call the UML-specific free_irq_by_irq_and_dev() for each free_irq call it's done. This is needed because ->shutdown and/or ->disable are only called when the last "action" for that irq is removed. Instead, for UML shared IRQs (UML IRQs are very often, if not always, shared), for each dev_id some setup is done, which must be cleared on the release of that fd. For instance, for each open console a new instance (i.e. new dev_id) of the same IRQ is requested(). Exactly, a fd is stored in an array (pollfds), which is after read by a host thread and passed to poll(). Each event registered by poll() triggers an interrupt. So, for each free_irq() we must remove the corresponding host fd from the table, which we do via this -release() method. In this patch we add an appropriate hook for this, and remove all uses of it by pointing the hook to the said procedure; this is safe to do since the said procedure. Also some cosmetic improvements are included. This is heavily based on some work by Chris Wedgwood, which however didn't get the patch merged for something I'd call a "misunderstanding" (the need for this patch wasn't cleanly explained, thus adding the generic hook was felt as undesirable). Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> CC: Ingo Molnar <mingo@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/um/drivers/line.c2
-rw-r--r--arch/um/drivers/net_kern.c1
-rw-r--r--arch/um/drivers/port_kern.c1
-rw-r--r--arch/um/drivers/xterm_kern.c1
-rw-r--r--arch/um/kernel/irq.c11
-rw-r--r--arch/um/kernel/irq_user.c2
-rw-r--r--include/linux/irq.h1
-rw-r--r--kernel/irq/manage.c4
8 files changed, 12 insertions, 11 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 025d3be8aca4..562f864254ba 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -406,14 +406,12 @@ void line_disable(struct tty_struct *tty, int current_irq)
406 if(line->driver->read_irq == current_irq) 406 if(line->driver->read_irq == current_irq)
407 free_irq_later(line->driver->read_irq, tty); 407 free_irq_later(line->driver->read_irq, tty);
408 else { 408 else {
409 free_irq_by_irq_and_dev(line->driver->read_irq, tty);
410 free_irq(line->driver->read_irq, tty); 409 free_irq(line->driver->read_irq, tty);
411 } 410 }
412 411
413 if(line->driver->write_irq == current_irq) 412 if(line->driver->write_irq == current_irq)
414 free_irq_later(line->driver->write_irq, tty); 413 free_irq_later(line->driver->write_irq, tty);
415 else { 414 else {
416 free_irq_by_irq_and_dev(line->driver->write_irq, tty);
417 free_irq(line->driver->write_irq, tty); 415 free_irq(line->driver->write_irq, tty);
418 } 416 }
419 417
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 4eeaf88c1e97..5388a7428691 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -146,7 +146,6 @@ static int uml_net_close(struct net_device *dev)
146 netif_stop_queue(dev); 146 netif_stop_queue(dev);
147 spin_lock(&lp->lock); 147 spin_lock(&lp->lock);
148 148
149 free_irq_by_irq_and_dev(dev->irq, dev);
150 free_irq(dev->irq, dev); 149 free_irq(dev->irq, dev);
151 if(lp->close != NULL) 150 if(lp->close != NULL)
152 (*lp->close)(lp->fd, &lp->user); 151 (*lp->close)(lp->fd, &lp->user);
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index b5ee07472f79..c41efd207fcc 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -257,7 +257,6 @@ int port_wait(void *data)
257 * connection. Then we loop here throwing out failed 257 * connection. Then we loop here throwing out failed
258 * connections until a good one is found. 258 * connections until a good one is found.
259 */ 259 */
260 free_irq_by_irq_and_dev(TELNETD_IRQ, conn);
261 free_irq(TELNETD_IRQ, conn); 260 free_irq(TELNETD_IRQ, conn);
262 261
263 if(conn->fd >= 0) break; 262 if(conn->fd >= 0) break;
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index a4fdf3584ad2..d269a80f4b0c 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -69,7 +69,6 @@ int xterm_fd(int socket, int *pid_out)
69 * isn't set) this will hang... */ 69 * isn't set) this will hang... */
70 wait_for_completion(&data->ready); 70 wait_for_completion(&data->ready);
71 71
72 free_irq_by_irq_and_dev(XTERM_IRQ, data);
73 free_irq(XTERM_IRQ, data); 72 free_irq(XTERM_IRQ, data);
74 73
75 ret = data->new_fd; 74 ret = data->new_fd;
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index d44fb5282547..9f18061ef4c9 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -124,14 +124,16 @@ void irq_unlock(unsigned long flags)
124 spin_unlock_irqrestore(&irq_spinlock, flags); 124 spin_unlock_irqrestore(&irq_spinlock, flags);
125} 125}
126 126
127/* presently hw_interrupt_type must define (startup || enable) && 127/* hw_interrupt_type must define (startup || enable) &&
128 * disable && end */ 128 * (shutdown || disable) && end */
129static void dummy(unsigned int irq) 129static void dummy(unsigned int irq)
130{ 130{
131} 131}
132 132
133static struct hw_interrupt_type SIGIO_irq_type = { 133/* This is used for everything else than the timer. */
134static struct hw_interrupt_type normal_irq_type = {
134 .typename = "SIGIO", 135 .typename = "SIGIO",
136 .release = free_irq_by_irq_and_dev,
135 .disable = dummy, 137 .disable = dummy,
136 .enable = dummy, 138 .enable = dummy,
137 .ack = dummy, 139 .ack = dummy,
@@ -140,6 +142,7 @@ static struct hw_interrupt_type SIGIO_irq_type = {
140 142
141static struct hw_interrupt_type SIGVTALRM_irq_type = { 143static struct hw_interrupt_type SIGVTALRM_irq_type = {
142 .typename = "SIGVTALRM", 144 .typename = "SIGVTALRM",
145 .release = free_irq_by_irq_and_dev,
143 .shutdown = dummy, /* never called */ 146 .shutdown = dummy, /* never called */
144 .disable = dummy, 147 .disable = dummy,
145 .enable = dummy, 148 .enable = dummy,
@@ -160,7 +163,7 @@ void __init init_IRQ(void)
160 irq_desc[i].status = IRQ_DISABLED; 163 irq_desc[i].status = IRQ_DISABLED;
161 irq_desc[i].action = NULL; 164 irq_desc[i].action = NULL;
162 irq_desc[i].depth = 1; 165 irq_desc[i].depth = 1;
163 irq_desc[i].handler = &SIGIO_irq_type; 166 irq_desc[i].handler = &normal_irq_type;
164 enable_irq(i); 167 enable_irq(i);
165 } 168 }
166} 169}
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index b3074cbaa479..c3ccaf24f3e0 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -85,8 +85,6 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
85 next = irq_fd->next; 85 next = irq_fd->next;
86 if(irq_fd->freed){ 86 if(irq_fd->freed){
87 free_irq(irq_fd->irq, irq_fd->id); 87 free_irq(irq_fd->irq, irq_fd->id);
88 free_irq_by_irq_and_dev(irq_fd->irq,
89 irq_fd->id);
90 } 88 }
91 } 89 }
92 } 90 }
diff --git a/include/linux/irq.h b/include/linux/irq.h
index c3ff4d101667..b68ad80e2464 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -47,6 +47,7 @@ struct hw_interrupt_type {
47 void (*ack)(unsigned int irq); 47 void (*ack)(unsigned int irq);
48 void (*end)(unsigned int irq); 48 void (*end)(unsigned int irq);
49 void (*set_affinity)(unsigned int irq, cpumask_t dest); 49 void (*set_affinity)(unsigned int irq, cpumask_t dest);
50 void (*release)(unsigned int irq, void *dev_id);
50}; 51};
51 52
52typedef struct hw_interrupt_type hw_irq_controller; 53typedef struct hw_interrupt_type hw_irq_controller;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 5202e4c4a5b6..5fde8177eedf 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -255,6 +255,10 @@ void free_irq(unsigned int irq, void *dev_id)
255 255
256 /* Found it - now remove it from the list of entries */ 256 /* Found it - now remove it from the list of entries */
257 *pp = action->next; 257 *pp = action->next;
258
259 if (desc->handler->release)
260 desc->handler->release(irq, dev_id);
261
258 if (!desc->action) { 262 if (!desc->action) {
259 desc->status |= IRQ_DISABLED; 263 desc->status |= IRQ_DISABLED;
260 if (desc->handler->shutdown) 264 if (desc->handler->shutdown)