[PATCH 7/7] um: simplify IRQ handling code
Johannes Berg
johannes at sipsolutions.net
Tue Nov 24 16:58:03 EST 2020
On Tue, 2020-11-24 at 21:50 +0000, Anton Ivanov wrote:
>
> > static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id)
> > {
> > - struct irq_reg *new_fd;
> > struct irq_entry *irq_entry;
> > - int i, err, events;
> > + int err, events = os_event_mask(type);
> > unsigned long flags;
> >
> > err = os_set_fd_async(fd);
> > @@ -151,73 +171,33 @@ static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id)
> > goto out;
> >
> > spin_lock_irqsave(&irq_lock, flags);
> > -
> > - /* Check if we have an entry for this fd */
> > -
> > - err = -EBUSY;
> > - for (irq_entry = active_fds;
> > - irq_entry != NULL; irq_entry = irq_entry->next) {
> > - if (irq_entry->fd == fd)
> > - break;
> > - }
> > -
> > - if (irq_entry == NULL) {
> > - /* This needs to be atomic as it may be called from an
> > - * IRQ context.
> > - */
> > - irq_entry = kmalloc(sizeof(struct irq_entry), GFP_ATOMIC);
> > - if (irq_entry == NULL) {
> > - printk(KERN_ERR
> > - "Failed to allocate new IRQ entry\n");
> > + irq_entry = get_irq_entry_by_fd(fd);
> > + if (irq_entry) {
>
> This is not right.
>
> You can re-register the same IRQ/fd, but with a different mask - f.e.
> turn on/off write or read on the same fd. F.E. - you have registered a
> read IRQ, you after that register same IRQ for write and you can alter
> the mask.
Hmm. You snipped some code, and it continued like this:
irq_entry = get_irq_entry_by_fd(fd);
if (irq_entry) {
/* cannot register the same FD twice with the same type */
if (WARN_ON(irq_entry->reg[type].events)) {
// basically return -EALREADY
I'm not sure I see this is different from what it was before? If the
irq_entry was found before (by fd, so that's equivalent to
get_irq_entry_by_fd(), was just open-coded), then previously it would
have gone into
- if (irq_entry->irq_array[type] != NULL) {
- printk(KERN_ERR
- "Trying to reregister IRQ %d FD %d TYPE %d ID %p\n",
- irq, fd, type, dev_id
- );
- goto out_unlock;
which was a failure?
But you meant a *different* type (IRQ_READ vs. IRQ_WRITE), and then in
my new code we also accept that:
irq_entry = get_irq_entry_by_fd(fd);
if (irq_entry) {
/* cannot register the same FD twice with the same type */
if (WARN_ON(irq_entry->reg[type].events)) {
err = -EALREADY;
goto out_unlock;
}
/* temporarily disable to avoid IRQ-side locking */
os_del_epoll_fd(fd);
} else {
[...]
}
irq_entry->reg[type].irq = irq;
irq_entry->reg[type].active = true;
irq_entry->reg[type].events = events;
So not sure I see the difference wrt. this?
You can't really *alter* the mask, even in the old code, you can just
register a new IRQ (or even the same) for the other type (read/write),
and then unregister the old type or such.
Ok ... what am I missing?
johannes
More information about the linux-um
mailing list