Re: [PATCH v2] drivers/uio/uio_pdrv_genirq.c: Fix memory freeing issues

From: Vitalii Demianets
Date: Fri Dec 07 2012 - 08:50:57 EST


On Friday 07 December 2012 11:41:45 Vitalii Demianets wrote:
> On Friday 07 December 2012 00:15:59 Hans J. Koch wrote:
> > On Thu, Dec 06, 2012 at 11:11:38AM +0200, Vitalii Demianets wrote:
> > > On Thursday 06 December 2012 04:41:01 Hans J. Koch wrote:
> > > > > @@ -63,7 +68,7 @@ static irqreturn_t uio_pdrv_genirq_handler(int
> > > > > irq,
> > >
> > > struct uio_info *dev_info)
> > >
> > > > > * remember the state so we can allow user space to enable it
> > > > > later. */
> > > > >
> > > > > - if (!test_and_set_bit(0, &priv->flags))
> > > > > + if (!test_and_set_bit(UIO_IRQ_DISABLED, &priv->flags))
> > > > > disable_irq_nosync(irq);
> > > >
> > > > That is not safe. That flag can only be changed by userspace, and if
> > > > the userspace part is not running, the CPU on which the irq is
> > > > pending will hang.
> > > > The handler has to disable the interrupt in any case.
> > > > (The original version had the same problem, I know...)
> > >
> > > Perhaps I'm missing something here, but I don't see your point. If
> > > userspace is not (implicitly) calling uio_pdrv_genirq_irqcontrol() by
> > > writing to the device file, then on the first invocation of interrupt
> > > handler that IRQ is disabled by disable_irq_nosync() and that's the end
> > > of story - no more irqs, no problems. Until userspace writes non-zero
> > > to the device file, of course.
> >
> > If you run into the irq handler, the interrupt was obviously enabled.
> > Since irq sharing is not supported by this driver, you ALWAYS have to
> > disable it because it IS your interrupt. Storing the enabled/disabled
> > status in a variable is not needed at all here. Or am I missing
> > something?
>
> Good point. I agree that having UIO_IRQ_DISABLED flag is redundant. Inside
> the irq handler we know for sure that irq is enabled. In
> uio_pdrv_genirq_irqcontrol() this knowledge is not mandatory, we could
> enable/disable irq unconditionally.
>

On second thought, we can't call enable_irq()/disable_irq() unconditionally
because of the potential disable counter (irq_desc->depth) disbalance. That's
why we need UIO_IRQ_DISABLED flag, and that's why we should check it in
uio_pdrv_genirq_irqcontrol().
On the other hand, you are right in that we don't need to check it inside irq
handler. Inside irq handler we can disable irq and set the flag
unconditionally, because:
a) We know for sure that irqs are enabled, because we are inside (not-shared)
irq handler;
and
b) We are guarded from potential race conditions by spin_lock_irqsave() call
in uio_pdrv_genirq_irqcontrol().

So,yes, we can get rid of costly atomic call to
test_and_set_bit(UIO_IRQ_DISABLED,..) inside irq handler. But I still don't
like the idea of mixing this optimization with bug fixes in a single patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/