[SCSI] mvsas: Add support for interrupt tasklet
authorXiangliang Yu <yuxiangl@marvell.com>
Thu, 30 Jun 2011 14:27:36 +0000 (22:27 +0800)
committerJames Bottomley <JBottomley@Parallels.com>
Tue, 26 Jul 2011 08:59:55 +0000 (12:59 +0400)
Add support for interrupt tasklet, which will improve performance.
Correct spelling of "20011"

[jejb: simplified ifdefs and fixed unused variable problem]
Signed-off-by: Xiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/mvsas/Kconfig
drivers/scsi/mvsas/mv_64xx.c
drivers/scsi/mvsas/mv_94xx.c
drivers/scsi/mvsas/mv_init.c
drivers/scsi/mvsas/mv_sas.h

index c82b012..78f7e20 100644 (file)
@@ -3,7 +3,7 @@
 #
 # Copyright 2007 Red Hat, Inc.
 # Copyright 2008 Marvell. <kewei@marvell.com>
-# Copyright 2009-20011 Marvell. <yuxiangl@marvell.com>
+# Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
 #
 # This file is licensed under GPLv2.
 #
@@ -41,3 +41,10 @@ config SCSI_MVSAS_DEBUG
        help
                Compiles the 88SE64XX/88SE94XX driver in debug mode.  In debug mode,
                the driver prints some messages to the console.
+config SCSI_MVSAS_TASKLET
+       bool "Support for interrupt tasklet"
+       default n
+       depends on SCSI_MVSAS
+       help
+               Compiles the 88SE64xx/88SE94xx driver in interrupt tasklet mode.In this mode,
+               the interrupt will schedule a tasklet.
index dec5f96..8ba4722 100644 (file)
@@ -471,13 +471,11 @@ static irqreturn_t mvs_64xx_isr(struct mvs_info *mvi, int irq, u32 stat)
 
        /* clear CMD_CMPLT ASAP */
        mw32_f(MVS_INT_STAT, CINT_DONE);
-#ifndef MVS_USE_TASKLET
+
        spin_lock(&mvi->lock);
-#endif
        mvs_int_full(mvi);
-#ifndef MVS_USE_TASKLET
        spin_unlock(&mvi->lock);
-#endif
+
        return IRQ_HANDLED;
 }
 
index f4a995c..3501291 100644 (file)
@@ -579,13 +579,10 @@ static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat)
        if (((stat & IRQ_SAS_A) && mvi->id == 0) ||
                        ((stat & IRQ_SAS_B) && mvi->id == 1)) {
                mw32_f(MVS_INT_STAT, CINT_DONE);
-       #ifndef MVS_USE_TASKLET
+
                spin_lock(&mvi->lock);
-       #endif
                mvs_int_full(mvi);
-       #ifndef MVS_USE_TASKLET
                spin_unlock(&mvi->lock);
-       #endif
        }
        return IRQ_HANDLED;
 }
index cf4aaa9..4e9af66 100644 (file)
@@ -170,11 +170,9 @@ static void mvs_free(struct mvs_info *mvi)
        kfree(mvi);
 }
 
-#ifdef MVS_USE_TASKLET
-struct tasklet_struct  mv_tasklet;
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
 static void mvs_tasklet(unsigned long opaque)
 {
-       unsigned long flags;
        u32 stat;
        u16 core_nr, i = 0;
 
@@ -187,35 +185,49 @@ static void mvs_tasklet(unsigned long opaque)
        if (unlikely(!mvi))
                BUG_ON(1);
 
+       stat = MVS_CHIP_DISP->isr_status(mvi, mvi->pdev->irq);
+       if (!stat)
+               goto out;
+
        for (i = 0; i < core_nr; i++) {
                mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
-               stat = MVS_CHIP_DISP->isr_status(mvi, mvi->irq);
-               if (stat)
-                       MVS_CHIP_DISP->isr(mvi, mvi->irq, stat);
+               MVS_CHIP_DISP->isr(mvi, mvi->pdev->irq, stat);
        }
+out:
+       MVS_CHIP_DISP->interrupt_enable(mvi);
 
 }
 #endif
 
 static irqreturn_t mvs_interrupt(int irq, void *opaque)
 {
-       u32 core_nr, i = 0;
+       u32 core_nr;
        u32 stat;
        struct mvs_info *mvi;
        struct sas_ha_struct *sha = opaque;
+#ifndef CONFIG_SCSI_MVSAS_TASKLET
+       u32 i;
+#endif
 
        core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
        mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
 
        if (unlikely(!mvi))
                return IRQ_NONE;
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+       MVS_CHIP_DISP->interrupt_disable(mvi);
+#endif
 
        stat = MVS_CHIP_DISP->isr_status(mvi, irq);
-       if (!stat)
+       if (!stat) {
+       #ifdef CONFIG_SCSI_MVSAS_TASKLET
+               MVS_CHIP_DISP->interrupt_enable(mvi);
+       #endif
                return IRQ_NONE;
+       }
 
-#ifdef MVS_USE_TASKLET
-       tasklet_schedule(&mv_tasklet);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+       tasklet_schedule(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
 #else
        for (i = 0; i < core_nr; i++) {
                mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
@@ -388,9 +400,6 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
        mvi->id = id;
        mvi->sas = sha;
        mvi->shost = shost;
-#ifdef MVS_USE_TASKLET
-       tasklet_init(&mv_tasklet, mvs_tasklet, (unsigned long)sha);
-#endif
 
        mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL);
        if (!mvi->tags)
@@ -535,6 +544,7 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
 {
        unsigned int rc, nhost = 0;
        struct mvs_info *mvi;
+       struct mvs_prv_info *mpi;
        irq_handler_t irq_handler = mvs_interrupt;
        struct Scsi_Host *shost = NULL;
        const struct mvs_chip_info *chip;
@@ -599,8 +609,9 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
                }
                nhost++;
        } while (nhost < chip->n_host);
-#ifdef MVS_USE_TASKLET
-       tasklet_init(&mv_tasklet, mvs_tasklet,
+       mpi = (struct mvs_prv_info *)(SHOST_TO_SAS_HA(shost)->lldd_ha);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+       tasklet_init(&(mpi->mv_tasklet), mvs_tasklet,
                     (unsigned long)SHOST_TO_SAS_HA(shost));
 #endif
 
@@ -645,8 +656,8 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
        core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
        mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
 
-#ifdef MVS_USE_TASKLET
-       tasklet_kill(&mv_tasklet);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+       tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
 #endif
 
        pci_set_drvdata(pdev, NULL);
index 25fae4f..44d7885 100644 (file)
@@ -420,6 +420,7 @@ struct mvs_prv_info{
        u8 scan_finished;
        u8 reserve;
        struct mvs_info *mvi[2];
+       struct tasklet_struct mv_tasklet;
 };
 
 struct mvs_wq {