Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c7b87f3d5037a35b5c7bb916ffc826be3fcb208d
Commit:     c7b87f3d5037a35b5c7bb916ffc826be3fcb208d
Parent:     129a84de2347002f09721cda3155ccfd19fade40
Author:     Russell King <[EMAIL PROTECTED]>
AuthorDate: Thu May 10 16:46:13 2007 +0100
Committer:  Russell King <[EMAIL PROTECTED]>
CommitDate: Fri May 11 17:18:55 2007 +0100

    [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 <[EMAIL PROTECTED]>
---
 arch/arm/kernel/ecard.c     |   16 ++++++++++++++++
 drivers/ata/pata_icside.c   |   13 ++++---------
 drivers/ide/arm/icside.c    |    9 +++------
 drivers/net/arm/etherh.c    |    4 +---
 drivers/scsi/arm/cumana_2.c |    4 ++--
 drivers/scsi/arm/eesox.c    |    4 ++--
 drivers/scsi/arm/powertec.c |    4 ++--
 include/asm-arm/ecard.h     |    4 +++-
 8 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index bdbd7da..65f1398 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -958,6 +958,14 @@ void ecard_release_resources(struct expansion_card *ec)
 }
 EXPORT_SYMBOL(ecard_release_resources);
 
+void ecard_setirq(struct expansion_card *ec, const struct expansion_card_ops 
*ops, void *irq_data)
+{
+       ec->irq_data = irq_data;
+       barrier();
+       ec->ops = ops;
+}
+EXPORT_SYMBOL(ecard_setirq);
+
 /*
  * Probe for an expansion card.
  *
@@ -1133,6 +1141,14 @@ static int ecard_drv_remove(struct device *dev)
        drv->remove(ec);
        ecard_release(ec);
 
+       /*
+        * Restore the default operations.  We ensure that the
+        * ops are set before we change the data.
+        */
+       ec->ops = &ecard_default_ops;
+       barrier();
+       ec->irq_data = NULL;
+
        return 0;
 }
 
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index dbc8ee2..d7621a3 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -434,8 +434,8 @@ pata_icside_register_v5(struct ata_probe_ent *ae, struct 
expansion_card *ec)
 
        ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
        ec->irqmask = 1;
-       ec->irq_data = state;
-       ec->ops = &pata_icside_ops_arcin_v5;
+
+       ecard_setirq(ec, &pata_icside_ops_arcin_v5, state);
 
        /*
         * Be on the safe side - disable interrupts
@@ -480,8 +480,7 @@ pata_icside_register_v6(struct ata_probe_ent *ae, struct 
expansion_card *ec)
 
        writeb(sel, ioc_base);
 
-       ec->irq_data = state;
-       ec->ops = &pata_icside_ops_arcin_v6;
+       ecard_setirq(ec, &pata_icside_ops_arcin_v6, state);
 
        state->irq_port = easi_base;
        state->ioc_base = ioc_base;
@@ -609,8 +608,7 @@ static void pata_icside_shutdown(struct expansion_card *ec)
         * this register via that region.
         */
        local_irq_save(flags);
-       if (ec->ops)
-               ec->ops->irqdisable(ec, ec->irq);
+       ec->ops->irqdisable(ec, ec->irq);
        local_irq_restore(flags);
 
        /*
@@ -638,9 +636,6 @@ static void __devexit pata_icside_remove(struct 
expansion_card *ec)
         * don't NULL out the drvdata - devres/libata wants it
         * to free the ata_host structure.
         */
-       ec->ops = NULL;
-       ec->irq_data = NULL;
-
        if (state->dma != NO_DMA)
                free_dma(state->dma);
        if (state->ioc_base)
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 1fe0457..69c949e 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -574,8 +574,8 @@ icside_register_v5(struct icside_state *state, struct 
expansion_card *ec)
 
        ec->irqaddr  = base + ICS_ARCIN_V5_INTRSTAT;
        ec->irqmask  = 1;
-       ec->irq_data = state;
-       ec->ops      = &icside_ops_arcin_v5;
+
+       ecard_setirq(ec, &icside_ops_arcin_v5, state);
 
        /*
         * Be on the safe side - disable interrupts
@@ -630,8 +630,7 @@ icside_register_v6(struct icside_state *state, struct 
expansion_card *ec)
 
        writeb(sel, ioc_base);
 
-       ec->irq_data      = state;
-       ec->ops           = &icside_ops_arcin_v6;
+       ecard_setirq(ec, &icside_ops_arcin_v6, state);
 
        state->irq_port   = easi_base;
        state->ioc_base   = ioc_base;
@@ -793,8 +792,6 @@ static void __devexit icside_remove(struct expansion_card 
*ec)
        }
 
        ecard_set_drvdata(ec, NULL);
-       ec->ops = NULL;
-       ec->irq_data = NULL;
 
        if (state->ioc_base)
                iounmap(state->ioc_base);
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 61f574a..387f1e3 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -710,8 +710,7 @@ etherh_probe(struct expansion_card *ec, const struct 
ecard_id *id)
         * IRQ and control port handling - only for non-NIC slot cards.
         */
        if (ec->slot_no != 8) {
-               ec->ops         = &etherh_ops;
-               ec->irq_data    = eh;
+               ecard_setirq(ec, &etherh_ops, eh);
        } else {
                /*
                 * If we're in the NIC slot, make sure the IRQ is enabled
@@ -778,7 +777,6 @@ static void __devexit etherh_remove(struct expansion_card 
*ec)
        ecard_set_drvdata(ec, NULL);
 
        unregister_netdev(dev);
-       ec->ops = NULL;
 
        if (eh->ioc_fast)
                iounmap(eh->ioc_fast);
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 82add77..f51aa34 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -450,8 +450,8 @@ cumanascsi2_probe(struct expansion_card *ec, const struct 
ecard_id *id)
 
        ec->irqaddr     = info->base + CUMANASCSI2_STATUS;
        ec->irqmask     = STATUS_INT;
-       ec->irq_data    = info;
-       ec->ops         = &cumanascsi_2_ops;
+
+       ecard_setirq(ec, &cumanascsi_2_ops, info);
 
        ret = fas216_init(host);
        if (ret)
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index ed06a8c..cc5d513 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -569,8 +569,8 @@ eesoxscsi_probe(struct expansion_card *ec, const struct 
ecard_id *id)
 
        ec->irqaddr     = base + EESOX_DMASTAT;
        ec->irqmask     = EESOX_STAT_INTR;
-       ec->irq_data    = info;
-       ec->ops         = &eesoxscsi_ops;
+
+       ecard_setirq(ec, &eesoxscsi_ops, info);
 
        device_create_file(&ec->dev, &dev_attr_bus_term);
 
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 159047a..3cbd525 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -361,8 +361,8 @@ powertecscsi_probe(struct expansion_card *ec, const struct 
ecard_id *id)
 
        ec->irqaddr     = base + POWERTEC_INTR_STATUS;
        ec->irqmask     = POWERTEC_INTR_BIT;
-       ec->irq_data    = info;
-       ec->ops         = &powertecscsi_ops;
+
+       ecard_setirq(ec, &powertecscsi_ops, info);
 
        device_create_file(&ec->dev, &dev_attr_bus_term);
 
diff --git a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h
index 3a6d3eb..8f1000e 100644
--- a/include/asm-arm/ecard.h
+++ b/include/asm-arm/ecard.h
@@ -121,7 +121,7 @@ struct in_ecid {                    /* Packed card ID 
information   */
 typedef struct expansion_card ecard_t;
 typedef unsigned long *loader_t;
 
-typedef struct {                       /* Card handler routines        */
+typedef struct expansion_card_ops {    /* Card handler routines        */
        void (*irqenable)(ecard_t *ec, int irqnr);
        void (*irqdisable)(ecard_t *ec, int irqnr);
        int  (*irqpending)(ecard_t *ec);
@@ -179,6 +179,8 @@ struct expansion_card {
        u64                     dma_mask;
 };
 
+void ecard_setirq(struct expansion_card *ec, const struct expansion_card_ops 
*ops, void *irq_data);
+
 struct in_chunk_dir {
        unsigned int start_offset;
        union {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to