summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2007-07-28 23:11:05 -0600
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:38:40 -0400
commit074c8fe4c0c0c7918d99bca34ea8e02a86997530 (patch)
tree3749b38af53c46df54a036cb8d9cfd740031eef3
parent2a437959e963d98e04dbbcd26b69bfb1985567ce (diff)
[SCSI] advansys: Improve interrupt handler
Pass the Scsi_Host to the interrupt handler, rather than polling all hosts for each interrupt. Return IRQ_NONE if we didn't handle this interrupt Don't set the IRQF_DISABLED flag; this is not a fast-executing interrupt handler. Signed-off-by: Matthew Wilcox <matthew@wil.cx> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/advansys.c172
1 files changed, 72 insertions, 100 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 6d11076bbd0..a407ff34199 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -3951,7 +3951,6 @@ static PortAddr _asc_def_iop_base[];
* advansys.h contains function prototypes for functions global to Linux.
*/
-static irqreturn_t advansys_interrupt(int, void *);
static int advansys_slave_configure(struct scsi_device *);
static void asc_scsi_done_list(struct scsi_cmnd *);
static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
@@ -4684,89 +4683,76 @@ static struct scsi_host_template driver_template = {
*/
static irqreturn_t advansys_interrupt(int irq, void *dev_id)
{
- ulong flags;
- int i;
- asc_board_t *boardp;
+ unsigned long flags;
struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
struct scsi_cmnd *new_last_scp;
- struct Scsi_Host *shost;
+ struct Scsi_Host *shost = dev_id;
+ asc_board_t *boardp = ASC_BOARDP(shost);
+ irqreturn_t result = IRQ_NONE;
- ASC_DBG(1, "advansys_interrupt: begin\n");
+ ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
+ spin_lock_irqsave(&boardp->lock, flags);
+ if (ASC_NARROW_BOARD(boardp)) {
+ /*
+ * Narrow Board
+ */
+ if (AscIsIntPending(shost->io_port)) {
+ result = IRQ_HANDLED;
+ ASC_STATS(shost, interrupt);
+ ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
+ AscISR(&boardp->dvc_var.asc_dvc_var);
+ }
+ } else {
+ /*
+ * Wide Board
+ */
+ ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
+ if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
+ result = IRQ_HANDLED;
+ ASC_STATS(shost, interrupt);
+ }
+ }
/*
- * Check for interrupts on all boards.
- * AscISR() will call asc_isr_callback().
- */
- for (i = 0; i < asc_board_count; i++) {
- shost = asc_host[i];
- boardp = ASC_BOARDP(shost);
- ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n",
- i, (ulong)boardp);
- spin_lock_irqsave(&boardp->lock, flags);
- if (ASC_NARROW_BOARD(boardp)) {
- /*
- * Narrow Board
- */
- if (AscIsIntPending(shost->io_port)) {
- ASC_STATS(shost, interrupt);
- ASC_DBG(1,
- "advansys_interrupt: before AscISR()\n");
- AscISR(&boardp->dvc_var.asc_dvc_var);
- }
- } else {
- /*
- * Wide Board
- */
- ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
- if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
- ASC_STATS(shost, interrupt);
- }
+ * Start waiting requests and create a list of completed requests.
+ *
+ * If a reset request is being performed for the board, the reset
+ * handler will complete pending requests after it has completed.
+ */
+ if ((boardp->flags & ASC_HOST_IN_RESET) == 0) {
+ ASC_DBG2(1, "advansys_interrupt: done_scp 0x%p, "
+ "last_scp 0x%p\n", done_scp, last_scp);
+
+ /* Start any waiting commands for the board. */
+ if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
+ ASC_DBG(1, "advansys_interrupt: before "
+ "asc_execute_queue()\n");
+ asc_execute_queue(&boardp->waiting);
}
/*
- * Start waiting requests and create a list of completed requests.
+ * Add to the list of requests that must be completed.
*
- * If a reset request is being performed for the board, the reset
- * handler will complete pending requests after it has completed.
+ * 'done_scp' will always be NULL on the first iteration of
+ * this loop. 'last_scp' is set at the same time as 'done_scp'.
*/
- if ((boardp->flags & ASC_HOST_IN_RESET) == 0) {
- ASC_DBG2(1,
- "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n",
- (ulong)done_scp, (ulong)last_scp);
-
- /* Start any waiting commands for the board. */
- if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
- ASC_DBG(1,
- "advansys_interrupt: before asc_execute_queue()\n");
- asc_execute_queue(&boardp->waiting);
- }
-
- /*
- * Add to the list of requests that must be completed.
- *
- * 'done_scp' will always be NULL on the first iteration
- * of this loop. 'last_scp' is set at the same time as
- * 'done_scp'.
- */
- if (done_scp == NULL) {
- done_scp =
- asc_dequeue_list(&boardp->done, &last_scp,
- ASC_TID_ALL);
- } else {
- ASC_ASSERT(last_scp != NULL);
- last_scp->host_scribble =
- (unsigned char *)asc_dequeue_list(&boardp->
- done,
- &new_last_scp,
- ASC_TID_ALL);
- if (new_last_scp != NULL) {
- ASC_ASSERT(REQPNEXT(last_scp) != NULL);
- last_scp = new_last_scp;
- }
+ if (done_scp == NULL) {
+ done_scp = asc_dequeue_list(&boardp->done,
+ &last_scp, ASC_TID_ALL);
+ } else {
+ ASC_ASSERT(last_scp != NULL);
+ last_scp->host_scribble =
+ (unsigned char *)asc_dequeue_list(&boardp->
+ done,
+ &new_last_scp,
+ ASC_TID_ALL);
+ if (new_last_scp != NULL) {
+ ASC_ASSERT(REQPNEXT(last_scp) != NULL);
+ last_scp = new_last_scp;
}
}
- spin_unlock_irqrestore(&boardp->lock, flags);
}
+ spin_unlock_irqrestore(&boardp->lock, flags);
/*
* If interrupts were enabled on entry, then they
@@ -4778,7 +4764,7 @@ static irqreturn_t advansys_interrupt(int irq, void *dev_id)
asc_scsi_done_list(done_scp);
ASC_DBG(1, "advansys_interrupt: end\n");
- return IRQ_HANDLED;
+ return result;
}
/*
@@ -17764,7 +17750,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
ASC_DVC_VAR *asc_dvc_varp = NULL;
ADV_DVC_VAR *adv_dvc_varp = NULL;
adv_sgblk_t *sgp = NULL;
- int share_irq = FALSE;
+ int share_irq;
int iolen = 0;
ADV_PADDR pci_memory_address;
int warn_code, err_code;
@@ -17918,15 +17904,15 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
#ifdef CONFIG_ISA
case ASC_IS_ISA:
shost->unchecked_isa_dma = TRUE;
- share_irq = FALSE;
+ share_irq = 0;
break;
case ASC_IS_VL:
shost->unchecked_isa_dma = FALSE;
- share_irq = FALSE;
+ share_irq = 0;
break;
case ASC_IS_EISA:
shost->unchecked_isa_dma = FALSE;
- share_irq = TRUE;
+ share_irq = IRQF_SHARED;
break;
#endif /* CONFIG_ISA */
#ifdef CONFIG_PCI
@@ -17937,7 +17923,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn));
shost->unchecked_isa_dma = FALSE;
- share_irq = TRUE;
+ share_irq = IRQF_SHARED;
break;
#endif /* CONFIG_PCI */
default:
@@ -17945,7 +17931,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
("advansys_board_found: board %d: unknown adapter type: %d\n",
boardp->id, asc_dvc_varp->bus_type);
shost->unchecked_isa_dma = TRUE;
- share_irq = FALSE;
+ share_irq = 0;
break;
}
} else {
@@ -17961,7 +17947,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn));
shost->unchecked_isa_dma = FALSE;
- share_irq = TRUE;
+ share_irq = IRQF_SHARED;
#endif /* CONFIG_PCI */
}
@@ -18425,25 +18411,11 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
/* Register IRQ Number. */
ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
- /*
- * If request_irq() fails with the IRQF_DISABLED flag set,
- * then try again without the IRQF_DISABLED flag set. This
- * allows IRQ sharing to work even with other drivers that
- * do not set the IRQF_DISABLED flag.
- *
- * If IRQF_DISABLED is not set, then interrupts are enabled
- * before the driver interrupt function is called.
- */
- if (((ret = request_irq(shost->irq, advansys_interrupt,
- IRQF_DISABLED | (share_irq ==
- TRUE ?
- IRQF_SHARED :
- 0), "advansys", boardp)) != 0)
- &&
- ((ret =
- request_irq(shost->irq, advansys_interrupt,
- (share_irq == TRUE ? IRQF_SHARED : 0),
- "advansys", boardp)) != 0)) {
+
+ ret = request_irq(shost->irq, advansys_interrupt, share_irq,
+ "advansys", shost);
+
+ if (ret) {
if (ret == -EBUSY) {
ASC_PRINT2
("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
@@ -18644,7 +18616,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
#ifdef CONFIG_PROC_FS
kfree(boardp->prtbuf);
#endif /* CONFIG_PROC_FS */
- free_irq(shost->irq, boardp);
+ free_irq(shost->irq, shost);
scsi_unregister(shost);
asc_board_count--;
return NULL;
@@ -18960,7 +18932,7 @@ static int advansys_release(struct Scsi_Host *shost)
ASC_DBG(1, "advansys_release: begin\n");
boardp = ASC_BOARDP(shost);
- free_irq(shost->irq, boardp);
+ free_irq(shost->irq, shost);
if (shost->dma_channel != NO_ISA_DMA) {
ASC_DBG(1, "advansys_release: free_dma()\n");
free_dma(shost->dma_channel);