diff options
author | Xiangliang Yu <yuxiangl@marvell.com> | 2011-06-30 10:27:36 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-26 04:59:55 -0400 |
commit | 6f8ac161b8b3332a9d96d6650ed3bae81baab30b (patch) | |
tree | 2cd89c7bbe9678ad5ec38cd9a15df726e01731a4 | |
parent | e144f7ef49ec85e9dfdf130f3a9a2372fe5fe39b (diff) |
[SCSI] mvsas: Add support for interrupt tasklet
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>
-rw-r--r-- | drivers/scsi/mvsas/Kconfig | 9 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_64xx.c | 6 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_94xx.c | 5 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_init.c | 45 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.h | 1 |
5 files changed, 40 insertions, 26 deletions
diff --git a/drivers/scsi/mvsas/Kconfig b/drivers/scsi/mvsas/Kconfig index c82b012aba37..78f7e20a0c1c 100644 --- a/drivers/scsi/mvsas/Kconfig +++ b/drivers/scsi/mvsas/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | # Copyright 2007 Red Hat, Inc. | 4 | # Copyright 2007 Red Hat, Inc. |
5 | # Copyright 2008 Marvell. <kewei@marvell.com> | 5 | # Copyright 2008 Marvell. <kewei@marvell.com> |
6 | # Copyright 2009-20011 Marvell. <yuxiangl@marvell.com> | 6 | # Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> |
7 | # | 7 | # |
8 | # This file is licensed under GPLv2. | 8 | # This file is licensed under GPLv2. |
9 | # | 9 | # |
@@ -41,3 +41,10 @@ config SCSI_MVSAS_DEBUG | |||
41 | help | 41 | help |
42 | Compiles the 88SE64XX/88SE94XX driver in debug mode. In debug mode, | 42 | Compiles the 88SE64XX/88SE94XX driver in debug mode. In debug mode, |
43 | the driver prints some messages to the console. | 43 | the driver prints some messages to the console. |
44 | config SCSI_MVSAS_TASKLET | ||
45 | bool "Support for interrupt tasklet" | ||
46 | default n | ||
47 | depends on SCSI_MVSAS | ||
48 | help | ||
49 | Compiles the 88SE64xx/88SE94xx driver in interrupt tasklet mode.In this mode, | ||
50 | the interrupt will schedule a tasklet. | ||
diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c index dec5f96f47a0..8ba47229049f 100644 --- a/drivers/scsi/mvsas/mv_64xx.c +++ b/drivers/scsi/mvsas/mv_64xx.c | |||
@@ -471,13 +471,11 @@ static irqreturn_t mvs_64xx_isr(struct mvs_info *mvi, int irq, u32 stat) | |||
471 | 471 | ||
472 | /* clear CMD_CMPLT ASAP */ | 472 | /* clear CMD_CMPLT ASAP */ |
473 | mw32_f(MVS_INT_STAT, CINT_DONE); | 473 | mw32_f(MVS_INT_STAT, CINT_DONE); |
474 | #ifndef MVS_USE_TASKLET | 474 | |
475 | spin_lock(&mvi->lock); | 475 | spin_lock(&mvi->lock); |
476 | #endif | ||
477 | mvs_int_full(mvi); | 476 | mvs_int_full(mvi); |
478 | #ifndef MVS_USE_TASKLET | ||
479 | spin_unlock(&mvi->lock); | 477 | spin_unlock(&mvi->lock); |
480 | #endif | 478 | |
481 | return IRQ_HANDLED; | 479 | return IRQ_HANDLED; |
482 | } | 480 | } |
483 | 481 | ||
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index f4a995c29eb1..3501291618fd 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c | |||
@@ -579,13 +579,10 @@ static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat) | |||
579 | if (((stat & IRQ_SAS_A) && mvi->id == 0) || | 579 | if (((stat & IRQ_SAS_A) && mvi->id == 0) || |
580 | ((stat & IRQ_SAS_B) && mvi->id == 1)) { | 580 | ((stat & IRQ_SAS_B) && mvi->id == 1)) { |
581 | mw32_f(MVS_INT_STAT, CINT_DONE); | 581 | mw32_f(MVS_INT_STAT, CINT_DONE); |
582 | #ifndef MVS_USE_TASKLET | 582 | |
583 | spin_lock(&mvi->lock); | 583 | spin_lock(&mvi->lock); |
584 | #endif | ||
585 | mvs_int_full(mvi); | 584 | mvs_int_full(mvi); |
586 | #ifndef MVS_USE_TASKLET | ||
587 | spin_unlock(&mvi->lock); | 585 | spin_unlock(&mvi->lock); |
588 | #endif | ||
589 | } | 586 | } |
590 | return IRQ_HANDLED; | 587 | return IRQ_HANDLED; |
591 | } | 588 | } |
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index cf4aaa9db5fe..4e9af66fd1d3 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c | |||
@@ -170,11 +170,9 @@ static void mvs_free(struct mvs_info *mvi) | |||
170 | kfree(mvi); | 170 | kfree(mvi); |
171 | } | 171 | } |
172 | 172 | ||
173 | #ifdef MVS_USE_TASKLET | 173 | #ifdef CONFIG_SCSI_MVSAS_TASKLET |
174 | struct tasklet_struct mv_tasklet; | ||
175 | static void mvs_tasklet(unsigned long opaque) | 174 | static void mvs_tasklet(unsigned long opaque) |
176 | { | 175 | { |
177 | unsigned long flags; | ||
178 | u32 stat; | 176 | u32 stat; |
179 | u16 core_nr, i = 0; | 177 | u16 core_nr, i = 0; |
180 | 178 | ||
@@ -187,35 +185,49 @@ static void mvs_tasklet(unsigned long opaque) | |||
187 | if (unlikely(!mvi)) | 185 | if (unlikely(!mvi)) |
188 | BUG_ON(1); | 186 | BUG_ON(1); |
189 | 187 | ||
188 | stat = MVS_CHIP_DISP->isr_status(mvi, mvi->pdev->irq); | ||
189 | if (!stat) | ||
190 | goto out; | ||
191 | |||
190 | for (i = 0; i < core_nr; i++) { | 192 | for (i = 0; i < core_nr; i++) { |
191 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; | 193 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; |
192 | stat = MVS_CHIP_DISP->isr_status(mvi, mvi->irq); | 194 | MVS_CHIP_DISP->isr(mvi, mvi->pdev->irq, stat); |
193 | if (stat) | ||
194 | MVS_CHIP_DISP->isr(mvi, mvi->irq, stat); | ||
195 | } | 195 | } |
196 | out: | ||
197 | MVS_CHIP_DISP->interrupt_enable(mvi); | ||
196 | 198 | ||
197 | } | 199 | } |
198 | #endif | 200 | #endif |
199 | 201 | ||
200 | static irqreturn_t mvs_interrupt(int irq, void *opaque) | 202 | static irqreturn_t mvs_interrupt(int irq, void *opaque) |
201 | { | 203 | { |
202 | u32 core_nr, i = 0; | 204 | u32 core_nr; |
203 | u32 stat; | 205 | u32 stat; |
204 | struct mvs_info *mvi; | 206 | struct mvs_info *mvi; |
205 | struct sas_ha_struct *sha = opaque; | 207 | struct sas_ha_struct *sha = opaque; |
208 | #ifndef CONFIG_SCSI_MVSAS_TASKLET | ||
209 | u32 i; | ||
210 | #endif | ||
206 | 211 | ||
207 | core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; | 212 | core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; |
208 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; | 213 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; |
209 | 214 | ||
210 | if (unlikely(!mvi)) | 215 | if (unlikely(!mvi)) |
211 | return IRQ_NONE; | 216 | return IRQ_NONE; |
217 | #ifdef CONFIG_SCSI_MVSAS_TASKLET | ||
218 | MVS_CHIP_DISP->interrupt_disable(mvi); | ||
219 | #endif | ||
212 | 220 | ||
213 | stat = MVS_CHIP_DISP->isr_status(mvi, irq); | 221 | stat = MVS_CHIP_DISP->isr_status(mvi, irq); |
214 | if (!stat) | 222 | if (!stat) { |
223 | #ifdef CONFIG_SCSI_MVSAS_TASKLET | ||
224 | MVS_CHIP_DISP->interrupt_enable(mvi); | ||
225 | #endif | ||
215 | return IRQ_NONE; | 226 | return IRQ_NONE; |
227 | } | ||
216 | 228 | ||
217 | #ifdef MVS_USE_TASKLET | 229 | #ifdef CONFIG_SCSI_MVSAS_TASKLET |
218 | tasklet_schedule(&mv_tasklet); | 230 | tasklet_schedule(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet); |
219 | #else | 231 | #else |
220 | for (i = 0; i < core_nr; i++) { | 232 | for (i = 0; i < core_nr; i++) { |
221 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; | 233 | 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, | |||
388 | mvi->id = id; | 400 | mvi->id = id; |
389 | mvi->sas = sha; | 401 | mvi->sas = sha; |
390 | mvi->shost = shost; | 402 | mvi->shost = shost; |
391 | #ifdef MVS_USE_TASKLET | ||
392 | tasklet_init(&mv_tasklet, mvs_tasklet, (unsigned long)sha); | ||
393 | #endif | ||
394 | 403 | ||
395 | mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL); | 404 | mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL); |
396 | if (!mvi->tags) | 405 | if (!mvi->tags) |
@@ -535,6 +544,7 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev, | |||
535 | { | 544 | { |
536 | unsigned int rc, nhost = 0; | 545 | unsigned int rc, nhost = 0; |
537 | struct mvs_info *mvi; | 546 | struct mvs_info *mvi; |
547 | struct mvs_prv_info *mpi; | ||
538 | irq_handler_t irq_handler = mvs_interrupt; | 548 | irq_handler_t irq_handler = mvs_interrupt; |
539 | struct Scsi_Host *shost = NULL; | 549 | struct Scsi_Host *shost = NULL; |
540 | const struct mvs_chip_info *chip; | 550 | const struct mvs_chip_info *chip; |
@@ -599,8 +609,9 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev, | |||
599 | } | 609 | } |
600 | nhost++; | 610 | nhost++; |
601 | } while (nhost < chip->n_host); | 611 | } while (nhost < chip->n_host); |
602 | #ifdef MVS_USE_TASKLET | 612 | mpi = (struct mvs_prv_info *)(SHOST_TO_SAS_HA(shost)->lldd_ha); |
603 | tasklet_init(&mv_tasklet, mvs_tasklet, | 613 | #ifdef CONFIG_SCSI_MVSAS_TASKLET |
614 | tasklet_init(&(mpi->mv_tasklet), mvs_tasklet, | ||
604 | (unsigned long)SHOST_TO_SAS_HA(shost)); | 615 | (unsigned long)SHOST_TO_SAS_HA(shost)); |
605 | #endif | 616 | #endif |
606 | 617 | ||
@@ -645,8 +656,8 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev) | |||
645 | core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; | 656 | core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; |
646 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; | 657 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; |
647 | 658 | ||
648 | #ifdef MVS_USE_TASKLET | 659 | #ifdef CONFIG_SCSI_MVSAS_TASKLET |
649 | tasklet_kill(&mv_tasklet); | 660 | tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet); |
650 | #endif | 661 | #endif |
651 | 662 | ||
652 | pci_set_drvdata(pdev, NULL); | 663 | pci_set_drvdata(pdev, NULL); |
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 25fae4f6aff2..44d7885a4a1d 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h | |||
@@ -420,6 +420,7 @@ struct mvs_prv_info{ | |||
420 | u8 scan_finished; | 420 | u8 scan_finished; |
421 | u8 reserve; | 421 | u8 reserve; |
422 | struct mvs_info *mvi[2]; | 422 | struct mvs_info *mvi[2]; |
423 | struct tasklet_struct mv_tasklet; | ||
423 | }; | 424 | }; |
424 | 425 | ||
425 | struct mvs_wq { | 426 | struct mvs_wq { |