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

[ARM] ecard: add helper function for setting ecard irq ops

Rather than having every driver fiddle about setting its private
IRQ operations and data, provide a helper function to contain
this functionality in one place.

Arrange to remove the driver-private IRQ operations and data when
the device is removed from the driver, and remove the driver
private code to do this.

This fixes potential problems caused by drivers forgetting to
remove these hooks.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Russell King and committed by
Russell King
c7b87f3d 129a84de

+33 -25
+16
arch/arm/kernel/ecard.c
··· 958 958 } 959 959 EXPORT_SYMBOL(ecard_release_resources); 960 960 961 + void ecard_setirq(struct expansion_card *ec, const struct expansion_card_ops *ops, void *irq_data) 962 + { 963 + ec->irq_data = irq_data; 964 + barrier(); 965 + ec->ops = ops; 966 + } 967 + EXPORT_SYMBOL(ecard_setirq); 968 + 961 969 /* 962 970 * Probe for an expansion card. 963 971 * ··· 1140 1132 1141 1133 drv->remove(ec); 1142 1134 ecard_release(ec); 1135 + 1136 + /* 1137 + * Restore the default operations. We ensure that the 1138 + * ops are set before we change the data. 1139 + */ 1140 + ec->ops = &ecard_default_ops; 1141 + barrier(); 1142 + ec->irq_data = NULL; 1143 1143 1144 1144 return 0; 1145 1145 }
+4 -9
drivers/ata/pata_icside.c
··· 434 434 435 435 ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT; 436 436 ec->irqmask = 1; 437 - ec->irq_data = state; 438 - ec->ops = &pata_icside_ops_arcin_v5; 437 + 438 + ecard_setirq(ec, &pata_icside_ops_arcin_v5, state); 439 439 440 440 /* 441 441 * Be on the safe side - disable interrupts ··· 480 480 481 481 writeb(sel, ioc_base); 482 482 483 - ec->irq_data = state; 484 - ec->ops = &pata_icside_ops_arcin_v6; 483 + ecard_setirq(ec, &pata_icside_ops_arcin_v6, state); 485 484 486 485 state->irq_port = easi_base; 487 486 state->ioc_base = ioc_base; ··· 608 609 * this register via that region. 609 610 */ 610 611 local_irq_save(flags); 611 - if (ec->ops) 612 - ec->ops->irqdisable(ec, ec->irq); 612 + ec->ops->irqdisable(ec, ec->irq); 613 613 local_irq_restore(flags); 614 614 615 615 /* ··· 636 638 * don't NULL out the drvdata - devres/libata wants it 637 639 * to free the ata_host structure. 638 640 */ 639 - ec->ops = NULL; 640 - ec->irq_data = NULL; 641 - 642 641 if (state->dma != NO_DMA) 643 642 free_dma(state->dma); 644 643 if (state->ioc_base)
+3 -6
drivers/ide/arm/icside.c
··· 574 574 575 575 ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT; 576 576 ec->irqmask = 1; 577 - ec->irq_data = state; 578 - ec->ops = &icside_ops_arcin_v5; 577 + 578 + ecard_setirq(ec, &icside_ops_arcin_v5, state); 579 579 580 580 /* 581 581 * Be on the safe side - disable interrupts ··· 630 630 631 631 writeb(sel, ioc_base); 632 632 633 - ec->irq_data = state; 634 - ec->ops = &icside_ops_arcin_v6; 633 + ecard_setirq(ec, &icside_ops_arcin_v6, state); 635 634 636 635 state->irq_port = easi_base; 637 636 state->ioc_base = ioc_base; ··· 792 793 } 793 794 794 795 ecard_set_drvdata(ec, NULL); 795 - ec->ops = NULL; 796 - ec->irq_data = NULL; 797 796 798 797 if (state->ioc_base) 799 798 iounmap(state->ioc_base);
+1 -3
drivers/net/arm/etherh.c
··· 710 710 * IRQ and control port handling - only for non-NIC slot cards. 711 711 */ 712 712 if (ec->slot_no != 8) { 713 - ec->ops = &etherh_ops; 714 - ec->irq_data = eh; 713 + ecard_setirq(ec, &etherh_ops, eh); 715 714 } else { 716 715 /* 717 716 * If we're in the NIC slot, make sure the IRQ is enabled ··· 777 778 ecard_set_drvdata(ec, NULL); 778 779 779 780 unregister_netdev(dev); 780 - ec->ops = NULL; 781 781 782 782 if (eh->ioc_fast) 783 783 iounmap(eh->ioc_fast);
+2 -2
drivers/scsi/arm/cumana_2.c
··· 450 450 451 451 ec->irqaddr = info->base + CUMANASCSI2_STATUS; 452 452 ec->irqmask = STATUS_INT; 453 - ec->irq_data = info; 454 - ec->ops = &cumanascsi_2_ops; 453 + 454 + ecard_setirq(ec, &cumanascsi_2_ops, info); 455 455 456 456 ret = fas216_init(host); 457 457 if (ret)
+2 -2
drivers/scsi/arm/eesox.c
··· 569 569 570 570 ec->irqaddr = base + EESOX_DMASTAT; 571 571 ec->irqmask = EESOX_STAT_INTR; 572 - ec->irq_data = info; 573 - ec->ops = &eesoxscsi_ops; 572 + 573 + ecard_setirq(ec, &eesoxscsi_ops, info); 574 574 575 575 device_create_file(&ec->dev, &dev_attr_bus_term); 576 576
+2 -2
drivers/scsi/arm/powertec.c
··· 361 361 362 362 ec->irqaddr = base + POWERTEC_INTR_STATUS; 363 363 ec->irqmask = POWERTEC_INTR_BIT; 364 - ec->irq_data = info; 365 - ec->ops = &powertecscsi_ops; 364 + 365 + ecard_setirq(ec, &powertecscsi_ops, info); 366 366 367 367 device_create_file(&ec->dev, &dev_attr_bus_term); 368 368
+3 -1
include/asm-arm/ecard.h
··· 121 121 typedef struct expansion_card ecard_t; 122 122 typedef unsigned long *loader_t; 123 123 124 - typedef struct { /* Card handler routines */ 124 + typedef struct expansion_card_ops { /* Card handler routines */ 125 125 void (*irqenable)(ecard_t *ec, int irqnr); 126 126 void (*irqdisable)(ecard_t *ec, int irqnr); 127 127 int (*irqpending)(ecard_t *ec); ··· 178 178 CONST loader_t loader; /* loader program */ 179 179 u64 dma_mask; 180 180 }; 181 + 182 + void ecard_setirq(struct expansion_card *ec, const struct expansion_card_ops *ops, void *irq_data); 181 183 182 184 struct in_chunk_dir { 183 185 unsigned int start_offset;