> > +
> > +static int sch_gpio_irq_type(struct irq_data *d, unsigned type)
> > +{
> > +       struct sch_gpio *sch = container_of(d, struct sch_gpio, data);
> > +       unsigned long flags;
> > +       u32 gpio_num;
> > +
> > +       if (d == NULL)
> > +               return -EINVAL;
> > +
> > +       gpio_num = d->irq - sch->irq_base;
> > +
> > +       spin_lock_irqsave(&sch->lock, flags);
> > +
> > +       switch (type) {
> > +       case IRQ_TYPE_EDGE_RISING:
> > +               sch_gpio_register_set(sch, gpio_num, GTPE);
> > +               sch_gpio_register_clear(sch, gpio_num, GTNE);
> 
> You will have the same problem as I pointed out in patch 1/3 that
> sch_gpio_register_set/clear() will try to acquire the already-locked
> sch->lock. No way this can ever work, or I am under a serious
> misapprehension.
> 
> > +               break;
> > +
> > +       case IRQ_TYPE_EDGE_FALLING:
> > +               sch_gpio_register_set(sch, gpio_num, GTNE);
> > +               sch_gpio_register_clear(sch, gpio_num, GTPE);
> > +               break;
> > +
> > +       case IRQ_TYPE_EDGE_BOTH:
> > +               sch_gpio_register_set(sch, gpio_num, GTPE);
> > +               sch_gpio_register_set(sch, gpio_num, GTNE);
> > +               break;
> > +
> > +       case IRQ_TYPE_NONE:
> > +               sch_gpio_register_clear(sch, gpio_num, GTPE);
> > +               sch_gpio_register_clear(sch, gpio_num, GTNE);
> > +               break;
> > +
> > +       default:
> > +               spin_unlock_irqrestore(&sch->lock, flags);
> > +               return -EINVAL;
> > +       }
> > +
> > +       spin_unlock_irqrestore(&sch->lock, flags);
> > +
> > +       return 0;
> > +}
> > +
> > +static struct irq_chip sch_irq_chip = {
> > +       .irq_enable     = sch_gpio_irq_enable,
> > +       .irq_disable    = sch_gpio_irq_disable,
> > +       .irq_ack        = sch_gpio_irq_ack,
> > +       .irq_set_type   = sch_gpio_irq_type,
> > +};
> > +
> > +static void sch_gpio_irqs_init(struct sch_gpio *sch, unsigned int num)
> > +{
> > +       unsigned int i;
> > +
> > +       for (i = 0; i < num; i++) {
> > +               irq_set_chip_data(i + sch->irq_base, sch);
> > +               irq_set_chip_and_handler_name(i + sch->irq_base,
> > +                                             &sch_irq_chip,
> > +                                             handle_simple_irq,
> > +                                             "sch_gpio_irq_chip");
> > +       }
> > +}
> > +
> > +static void sch_gpio_irqs_deinit(struct sch_gpio *sch, unsigned int num)
> > +{
> > +       unsigned int i;
> > +
> > +       for (i = 0; i < num; i++) {
> > +               irq_set_chip_data(i + sch->irq_base, 0);
> > +               irq_set_chip_and_handler_name(i + sch->irq_base, 0, 0, 0);
> > +       }
> > +}
> > +
> > +static void sch_gpio_irq_disable_all(struct sch_gpio *sch, unsigned int 
> > num)
> > +{
> > +       unsigned long flags;
> > +       unsigned int gpio_num;
> > +
> > +       spin_lock_irqsave(&sch->lock, flags);
> > +
> > +       for (gpio_num = 0; gpio_num < num; gpio_num++) {
> > +               sch_gpio_register_clear(sch, gpio_num, GTPE);
> > +               sch_gpio_register_clear(sch, gpio_num, GTNE);
> > +               sch_gpio_register_clear(sch, gpio_num, GGPE);
> > +               sch_gpio_register_clear(sch, gpio_num, GSMI);
> 
> Same here.


Alright. I should have noticed this double locking issue earlier. Thanks. I 
think the next version will be much cleaner. Thanks for spending time and 
effort to review.

Rebecca

Reply via email to