diff --git a/kernel/spec-fmc.c b/kernel/spec-fmc.c index 6322e3ff5e6e9572f61a80d9966ed71ee12e2a90..3f76aee6e344c79872b4ec457cbbb444a22ccb5d 100644 --- a/kernel/spec-fmc.c +++ b/kernel/spec-fmc.c @@ -127,6 +127,10 @@ static irqreturn_t spec_vic_irq_handler(int id, void *data) struct spec_dev *spec = (struct spec_dev *)fmc->carrier_data; irqreturn_t rv; + /* + * Lock to avoid to remove the VIC or the handler itself while + * it's running + */ spin_lock(&spec->irq_lock); rv = spec_vic_irq_dispatch(spec); spin_unlock(&spec->irq_lock); @@ -157,29 +161,29 @@ static int spec_irq_request(struct fmc_device *fmc, irq_handler_t handler, /* VIC mode interrupt */ if (!(flags & IRQF_SHARED)) { + /* + * Lock to serialize request/free and have a consistent status + * during these operations + */ spin_lock(&spec->irq_lock); first_time = !spec->vic; /* configure the VIC */ rv = spec_vic_irq_request(spec, fmc, fmc->irq, handler); - if (rv) { - spin_unlock(&spec->irq_lock); + spin_unlock(&spec->irq_lock); + if (rv) return rv; - } /* on first IRQ, configure VIC "master" handler and GPIO too */ if (first_time) { rv = spec_shared_irq_request(fmc, spec_vic_irq_handler, "spec-vic", IRQF_SHARED); - if (rv) { - spin_unlock(&spec->irq_lock); + if (rv) return rv; - } fmc->op->gpio_config(fmc, spec_vic_gpio_cfg, ARRAY_SIZE(spec_vic_gpio_cfg)); } - spin_unlock(&spec->irq_lock); } else { rv = spec_shared_irq_request(fmc, handler, name, flags); pr_debug("Requesting irq '%s' in shared mode (rv %d)\n", name, @@ -226,6 +230,11 @@ static int spec_irq_free(struct fmc_device *fmc) { struct spec_dev *spec = fmc->carrier_data; + /* + * Lock to serialize request/free and have a consistent status + * during these operations. And, to avoid to run VIC handler while + * it is going to desappear + */ spin_lock(&spec->irq_lock); if (spec->vic) spec_vic_irq_free(spec, fmc->irq);