diff options
author | Magnus Damm <damm@opensource.se> | 2010-08-02 09:16:37 +0200 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-08-04 09:10:34 +0200 |
commit | 82b20d8bae03406e954d8b7d0f6f734967088b17 (patch) | |
tree | 6d7d83c59d52930a59a2315cc423a94e997327ca /drivers/i2c | |
parent | sh: dma: check return value of create_proc_read_entry() (diff) | |
download | linux-82b20d8bae03406e954d8b7d0f6f734967088b17.tar.xz linux-82b20d8bae03406e954d8b7d0f6f734967088b17.zip |
i2c: i2c-sh_mobile irq rollback fix
Update the i2c-sh_mobile driver to properly free
interrupts. The function sh_mobile_i2c_hook_irqs()
is fixed so module both unload and load are working
as expected.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index ffb405d7c6f2..97b84b80d0ff 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -497,15 +497,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) { struct resource *res; int ret = -ENXIO; - int q, m; - int k = 0; - int n = 0; + int n, k = 0; while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { for (n = res->start; hook && n <= res->end; n++) { if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED, - dev_name(&dev->dev), dev)) + dev_name(&dev->dev), dev)) { + for (n--; n >= res->start; n--) + free_irq(n, dev); + goto rollback; + } } k++; } @@ -513,16 +515,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) if (hook) return k > 0 ? 0 : -ENOENT; - k--; ret = 0; rollback: - for (q = k; k >= 0; k--) { - for (m = n; m >= res->start; m--) - free_irq(m, dev); + k--; + + while (k >= 0) { + res = platform_get_resource(dev, IORESOURCE_IRQ, k); + for (n = res->start; n <= res->end; n++) + free_irq(n, dev); - res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1); - m = res->end; + k--; } return ret; |