Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: arizona: Correctly clean up after IRQs

Currently we leak a lot of things when tearing down the IRQs this patch
fixes this cleaning up both the IRQ mappings and the IRQ domain itself.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Charles Keepax and committed by
Lee Jones
3dfaff27 1a86dcb3

+41 -18
+41 -18
drivers/mfd/arizona-irq.c
··· 210 210 int ret; 211 211 const struct regmap_irq_chip *aod, *irq; 212 212 struct irq_data *irq_data; 213 + unsigned int virq; 213 214 214 215 arizona->ctrlif_error = true; 215 216 ··· 322 321 } 323 322 324 323 if (aod) { 325 - ret = regmap_add_irq_chip(arizona->regmap, 326 - irq_create_mapping(arizona->virq, 327 - ARIZONA_AOD_IRQ_INDEX), 328 - IRQF_ONESHOT, 0, aod, 329 - &arizona->aod_irq_chip); 324 + virq = irq_create_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX); 325 + if (!virq) { 326 + dev_err(arizona->dev, "Failed to map AOD IRQs\n"); 327 + ret = -EINVAL; 328 + goto err_domain; 329 + } 330 + 331 + ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT, 332 + 0, aod, &arizona->aod_irq_chip); 330 333 if (ret != 0) { 331 334 dev_err(arizona->dev, 332 335 "Failed to add AOD IRQs: %d\n", ret); 333 - goto err; 336 + goto err_map_aod; 334 337 } 335 338 } 336 339 337 - ret = regmap_add_irq_chip(arizona->regmap, 338 - irq_create_mapping(arizona->virq, 339 - ARIZONA_MAIN_IRQ_INDEX), 340 - IRQF_ONESHOT, 0, irq, 341 - &arizona->irq_chip); 340 + virq = irq_create_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX); 341 + if (!virq) { 342 + dev_err(arizona->dev, "Failed to map main IRQs\n"); 343 + ret = -EINVAL; 344 + goto err_aod; 345 + } 346 + 347 + ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT, 348 + 0, irq, &arizona->irq_chip); 342 349 if (ret != 0) { 343 350 dev_err(arizona->dev, "Failed to add main IRQs: %d\n", ret); 344 - goto err_aod; 351 + goto err_map_main_irq; 345 352 } 346 353 347 354 /* Used to emulate edge trigger and to work around broken pinmux */ ··· 413 404 regmap_del_irq_chip(irq_find_mapping(arizona->virq, 414 405 ARIZONA_MAIN_IRQ_INDEX), 415 406 arizona->irq_chip); 407 + err_map_main_irq: 408 + irq_dispose_mapping(irq_find_mapping(arizona->virq, 409 + ARIZONA_MAIN_IRQ_INDEX)); 416 410 err_aod: 417 411 regmap_del_irq_chip(irq_find_mapping(arizona->virq, 418 412 ARIZONA_AOD_IRQ_INDEX), 419 413 arizona->aod_irq_chip); 414 + err_map_aod: 415 + irq_dispose_mapping(irq_find_mapping(arizona->virq, 416 + ARIZONA_AOD_IRQ_INDEX)); 417 + err_domain: 418 + irq_domain_remove(arizona->virq); 420 419 err: 421 420 return ret; 422 421 } 423 422 424 423 int arizona_irq_exit(struct arizona *arizona) 425 424 { 425 + unsigned int virq; 426 + 426 427 if (arizona->ctrlif_error) 427 428 arizona_free_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR, arizona); 428 429 arizona_free_irq(arizona, ARIZONA_IRQ_BOOT_DONE, arizona); 429 430 430 - regmap_del_irq_chip(irq_find_mapping(arizona->virq, 431 - ARIZONA_MAIN_IRQ_INDEX), 432 - arizona->irq_chip); 433 - regmap_del_irq_chip(irq_find_mapping(arizona->virq, 434 - ARIZONA_AOD_IRQ_INDEX), 435 - arizona->aod_irq_chip); 431 + virq = irq_find_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX); 432 + regmap_del_irq_chip(virq, arizona->irq_chip); 433 + irq_dispose_mapping(virq); 434 + 435 + virq = irq_find_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX); 436 + regmap_del_irq_chip(virq, arizona->aod_irq_chip); 437 + irq_dispose_mapping(virq); 438 + 439 + irq_domain_remove(arizona->virq); 440 + 436 441 free_irq(arizona->irq, arizona); 437 442 438 443 return 0;