Re: [patch] voluntary-preempt-2.6.8.1-P2

Thomas Charbonnel
2004-08-18T15:28:05Z

Takashi Iwai wrote :
> At Wed, 18 Aug 2004 14:22:07 +0200,
> Thomas Charbonnel wrote:
> >
> > As a side note, and this has already been reported here several times,
> > the SA_INTERRUPT flag set notably by the sound card drivers handlers is
> > not honored on current kernels if the device is not the first one to be
> > registered. A simple fix would be to add SA_INTERRUPT handlers at the
> > beginning instead of the end of the irq queue in setup_irq.
> >
> > Similarly, when using SA_SAMPLE_RANDOM, all devices on the given irq
> > contribute to the entropy, even those that have a predictable interrupt
> > rate (e.g. sound cards), and/or for which the number of interrupts could
> > outweight the number of interrupts of the original SA_SAMPLE_RANDOM
> > driver.
>
> Hmm, something like this?
>
>
> Takashi
>
> --- linux/arch/i386/kernel/irq.c 2004-08-18 15:15:18.272067276 +0200
> +++ linux/arch/i386/kernel/irq.c 2004-08-18 15:26:13.513979698 +0200
> @@ -219,15 +219,22 @@ inline void synchronize_irq(unsigned int
> asmlinkage int handle_IRQ_event(unsigned int irq,
> struct pt_regs *regs, struct irqaction *action)
> {
> - int status = 1; /* Force the "do bottom halves" bit */
> - int retval = 0;
> -
> - if (!(action->flags & SA_INTERRUPT))
> + int status;
> + int ret, retval = 0;
> + struct irqaction *ac;
> +
> + status = 0;
> + for (ac = action; ac; ac = ac->next)
> + status |= ac->flags;
> + if (!(status & SA_INTERRUPT))
> local_irq_enable();
>
> + status = 0;
> do {
> - status |= action->flags;
> - retval |= action->handler(irq, action->dev_id, regs);
> + ret = action->handler(irq, action->dev_id, regs);
> + if (ret)
> + status |= action->flags;
> + retval |= ret;
> action = action->next;
> } while (action);
> if (status & SA_SAMPLE_RANDOM)

I was thinking more of something like this :

--- irq.c.orig 2004-08-16 14:26:34.000000000 +0200
+++ irq.c 2004-08-18 17:23:18.011059064 +0200
@@ -955,11 +955,16 @@
return -EBUSY;
}

- /* add new interrupt at end of irq queue */
- do {
- p = &old->next;
- old = *p;
- } while (old);
+ if (new->flags & SA_INTERRUPT)
+ /* add interrupt at the start of the queue */
+ new->next = old;
+ else
+ /* add new interrupt at end of irq queue */
+ do {
+ p = &old->next;
+ old = *p;
+ } while (old);
+
shared = 1;
}

Thomas