aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/advansys.c
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2007-07-29 01:11:05 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:38:40 -0400
commit074c8fe4c0c0c7918d99bca34ea8e02a86997530 (patch)
tree3749b38af53c46df54a036cb8d9cfd740031eef3 /drivers/scsi/advansys.c
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>
Diffstat (limited to 'drivers/scsi/advansys.c')
-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 6d11076bbd02..a407ff34199d 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -3951,7 +3951,6 @@ static PortAddr _asc_def_iop_base[];
3951 * advansys.h contains function prototypes for functions global to Linux. 3951 * advansys.h contains function prototypes for functions global to Linux.
3952 */ 3952 */
3953 3953
3954static irqreturn_t advansys_interrupt(int, void *);
3955static int advansys_slave_configure(struct scsi_device *); 3954static int advansys_slave_configure(struct scsi_device *);
3956static void asc_scsi_done_list(struct scsi_cmnd *); 3955static void asc_scsi_done_list(struct scsi_cmnd *);
3957static int asc_execute_scsi_cmnd(struct scsi_cmnd *); 3956static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
@@ -4684,89 +4683,76 @@ static struct scsi_host_template driver_template = {
4684 */ 4683 */
4685static irqreturn_t advansys_interrupt(int irq, void *dev_id) 4684static irqreturn_t advansys_interrupt(int irq, void *dev_id)
4686{ 4685{
4687 ulong flags; 4686 unsigned long flags;
4688 int i;
4689 asc_board_t *boardp;
4690 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; 4687 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
4691 struct scsi_cmnd *new_last_scp; 4688 struct scsi_cmnd *new_last_scp;
4692 struct Scsi_Host *shost; 4689 struct Scsi_Host *shost = dev_id;
4690 asc_board_t *boardp = ASC_BOARDP(shost);
4691 irqreturn_t result = IRQ_NONE;
4693 4692
4694 ASC_DBG(1, "advansys_interrupt: begin\n"); 4693 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
4694 spin_lock_irqsave(&boardp->lock, flags);
4695 if (ASC_NARROW_BOARD(boardp)) {
4696 /*
4697 * Narrow Board
4698 */
4699 if (AscIsIntPending(shost->io_port)) {
4700 result = IRQ_HANDLED;
4701 ASC_STATS(shost, interrupt);
4702 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
4703 AscISR(&boardp->dvc_var.asc_dvc_var);
4704 }
4705 } else {
4706 /*
4707 * Wide Board
4708 */
4709 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
4710 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
4711 result = IRQ_HANDLED;
4712 ASC_STATS(shost, interrupt);
4713 }
4714 }
4695 4715
4696 /* 4716 /*
4697 * Check for interrupts on all boards. 4717 * Start waiting requests and create a list of completed requests.
4698 * AscISR() will call asc_isr_callback(). 4718 *
4699 */ 4719 * If a reset request is being performed for the board, the reset
4700 for (i = 0; i < asc_board_count; i++) { 4720 * handler will complete pending requests after it has completed.
4701 shost = asc_host[i]; 4721 */
4702 boardp = ASC_BOARDP(shost); 4722 if ((boardp->flags & ASC_HOST_IN_RESET) == 0) {
4703 ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n", 4723 ASC_DBG2(1, "advansys_interrupt: done_scp 0x%p, "
4704 i, (ulong)boardp); 4724 "last_scp 0x%p\n", done_scp, last_scp);
4705 spin_lock_irqsave(&boardp->lock, flags); 4725
4706 if (ASC_NARROW_BOARD(boardp)) { 4726 /* Start any waiting commands for the board. */
4707 /* 4727 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
4708 * Narrow Board 4728 ASC_DBG(1, "advansys_interrupt: before "
4709 */ 4729 "asc_execute_queue()\n");
4710 if (AscIsIntPending(shost->io_port)) { 4730 asc_execute_queue(&boardp->waiting);
4711 ASC_STATS(shost, interrupt);
4712 ASC_DBG(1,
4713 "advansys_interrupt: before AscISR()\n");
4714 AscISR(&boardp->dvc_var.asc_dvc_var);
4715 }
4716 } else {
4717 /*
4718 * Wide Board
4719 */
4720 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
4721 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
4722 ASC_STATS(shost, interrupt);
4723 }
4724 } 4731 }
4725 4732
4726 /* 4733 /*
4727 * Start waiting requests and create a list of completed requests. 4734 * Add to the list of requests that must be completed.
4728 * 4735 *
4729 * If a reset request is being performed for the board, the reset 4736 * 'done_scp' will always be NULL on the first iteration of
4730 * handler will complete pending requests after it has completed. 4737 * this loop. 'last_scp' is set at the same time as 'done_scp'.
4731 */ 4738 */
4732 if ((boardp->flags & ASC_HOST_IN_RESET) == 0) { 4739 if (done_scp == NULL) {
4733 ASC_DBG2(1, 4740 done_scp = asc_dequeue_list(&boardp->done,
4734 "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n", 4741 &last_scp, ASC_TID_ALL);
4735 (ulong)done_scp, (ulong)last_scp); 4742 } else {
4736 4743 ASC_ASSERT(last_scp != NULL);
4737 /* Start any waiting commands for the board. */ 4744 last_scp->host_scribble =
4738 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { 4745 (unsigned char *)asc_dequeue_list(&boardp->
4739 ASC_DBG(1, 4746 done,
4740 "advansys_interrupt: before asc_execute_queue()\n"); 4747 &new_last_scp,
4741 asc_execute_queue(&boardp->waiting); 4748 ASC_TID_ALL);
4742 } 4749 if (new_last_scp != NULL) {
4743 4750 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4744 /* 4751 last_scp = new_last_scp;
4745 * Add to the list of requests that must be completed.
4746 *
4747 * 'done_scp' will always be NULL on the first iteration
4748 * of this loop. 'last_scp' is set at the same time as
4749 * 'done_scp'.
4750 */
4751 if (done_scp == NULL) {
4752 done_scp =
4753 asc_dequeue_list(&boardp->done, &last_scp,
4754 ASC_TID_ALL);
4755 } else {
4756 ASC_ASSERT(last_scp != NULL);
4757 last_scp->host_scribble =
4758 (unsigned char *)asc_dequeue_list(&boardp->
4759 done,
4760 &new_last_scp,
4761 ASC_TID_ALL);
4762 if (new_last_scp != NULL) {
4763 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
4764 last_scp = new_last_scp;
4765 }
4766 } 4752 }
4767 } 4753 }
4768 spin_unlock_irqrestore(&boardp->lock, flags);
4769 } 4754 }
4755 spin_unlock_irqrestore(&boardp->lock, flags);
4770 4756
4771 /* 4757 /*
4772 * If interrupts were enabled on entry, then they 4758 * If interrupts were enabled on entry, then they
@@ -4778,7 +4764,7 @@ static irqreturn_t advansys_interrupt(int irq, void *dev_id)
4778 asc_scsi_done_list(done_scp); 4764 asc_scsi_done_list(done_scp);
4779 4765
4780 ASC_DBG(1, "advansys_interrupt: end\n"); 4766 ASC_DBG(1, "advansys_interrupt: end\n");
4781 return IRQ_HANDLED; 4767 return result;
4782} 4768}
4783 4769
4784/* 4770/*
@@ -17764,7 +17750,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
17764 ASC_DVC_VAR *asc_dvc_varp = NULL; 17750 ASC_DVC_VAR *asc_dvc_varp = NULL;
17765 ADV_DVC_VAR *adv_dvc_varp = NULL; 17751 ADV_DVC_VAR *adv_dvc_varp = NULL;
17766 adv_sgblk_t *sgp = NULL; 17752 adv_sgblk_t *sgp = NULL;
17767 int share_irq = FALSE; 17753 int share_irq;
17768 int iolen = 0; 17754 int iolen = 0;
17769 ADV_PADDR pci_memory_address; 17755 ADV_PADDR pci_memory_address;
17770 int warn_code, err_code; 17756 int warn_code, err_code;
@@ -17918,15 +17904,15 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
17918#ifdef CONFIG_ISA 17904#ifdef CONFIG_ISA
17919 case ASC_IS_ISA: 17905 case ASC_IS_ISA:
17920 shost->unchecked_isa_dma = TRUE; 17906 shost->unchecked_isa_dma = TRUE;
17921 share_irq = FALSE; 17907 share_irq = 0;
17922 break; 17908 break;
17923 case ASC_IS_VL: 17909 case ASC_IS_VL:
17924 shost->unchecked_isa_dma = FALSE; 17910 shost->unchecked_isa_dma = FALSE;
17925 share_irq = FALSE; 17911 share_irq = 0;
17926 break; 17912 break;
17927 case ASC_IS_EISA: 17913 case ASC_IS_EISA:
17928 shost->unchecked_isa_dma = FALSE; 17914 shost->unchecked_isa_dma = FALSE;
17929 share_irq = TRUE; 17915 share_irq = IRQF_SHARED;
17930 break; 17916 break;
17931#endif /* CONFIG_ISA */ 17917#endif /* CONFIG_ISA */
17932#ifdef CONFIG_PCI 17918#ifdef CONFIG_PCI
@@ -17937,7 +17923,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
17937 PCI_SLOT(pdev->devfn), 17923 PCI_SLOT(pdev->devfn),
17938 PCI_FUNC(pdev->devfn)); 17924 PCI_FUNC(pdev->devfn));
17939 shost->unchecked_isa_dma = FALSE; 17925 shost->unchecked_isa_dma = FALSE;
17940 share_irq = TRUE; 17926 share_irq = IRQF_SHARED;
17941 break; 17927 break;
17942#endif /* CONFIG_PCI */ 17928#endif /* CONFIG_PCI */
17943 default: 17929 default:
@@ -17945,7 +17931,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
17945 ("advansys_board_found: board %d: unknown adapter type: %d\n", 17931 ("advansys_board_found: board %d: unknown adapter type: %d\n",
17946 boardp->id, asc_dvc_varp->bus_type); 17932 boardp->id, asc_dvc_varp->bus_type);
17947 shost->unchecked_isa_dma = TRUE; 17933 shost->unchecked_isa_dma = TRUE;
17948 share_irq = FALSE; 17934 share_irq = 0;
17949 break; 17935 break;
17950 } 17936 }
17951 } else { 17937 } else {
@@ -17961,7 +17947,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
17961 PCI_SLOT(pdev->devfn), 17947 PCI_SLOT(pdev->devfn),
17962 PCI_FUNC(pdev->devfn)); 17948 PCI_FUNC(pdev->devfn));
17963 shost->unchecked_isa_dma = FALSE; 17949 shost->unchecked_isa_dma = FALSE;
17964 share_irq = TRUE; 17950 share_irq = IRQF_SHARED;
17965#endif /* CONFIG_PCI */ 17951#endif /* CONFIG_PCI */
17966 } 17952 }
17967 17953
@@ -18425,25 +18411,11 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
18425 18411
18426 /* Register IRQ Number. */ 18412 /* Register IRQ Number. */
18427 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq); 18413 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
18428 /* 18414
18429 * If request_irq() fails with the IRQF_DISABLED flag set, 18415 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
18430 * then try again without the IRQF_DISABLED flag set. This 18416 "advansys", shost);
18431 * allows IRQ sharing to work even with other drivers that 18417
18432 * do not set the IRQF_DISABLED flag. 18418 if (ret) {
18433 *
18434 * If IRQF_DISABLED is not set, then interrupts are enabled
18435 * before the driver interrupt function is called.
18436 */
18437 if (((ret = request_irq(shost->irq, advansys_interrupt,
18438 IRQF_DISABLED | (share_irq ==
18439 TRUE ?
18440 IRQF_SHARED :
18441 0), "advansys", boardp)) != 0)
18442 &&
18443 ((ret =
18444 request_irq(shost->irq, advansys_interrupt,
18445 (share_irq == TRUE ? IRQF_SHARED : 0),
18446 "advansys", boardp)) != 0)) {
18447 if (ret == -EBUSY) { 18419 if (ret == -EBUSY) {
18448 ASC_PRINT2 18420 ASC_PRINT2
18449 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n", 18421 ("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)
18644#ifdef CONFIG_PROC_FS 18616#ifdef CONFIG_PROC_FS
18645 kfree(boardp->prtbuf); 18617 kfree(boardp->prtbuf);
18646#endif /* CONFIG_PROC_FS */ 18618#endif /* CONFIG_PROC_FS */
18647 free_irq(shost->irq, boardp); 18619 free_irq(shost->irq, shost);
18648 scsi_unregister(shost); 18620 scsi_unregister(shost);
18649 asc_board_count--; 18621 asc_board_count--;
18650 return NULL; 18622 return NULL;
@@ -18960,7 +18932,7 @@ static int advansys_release(struct Scsi_Host *shost)
18960 18932
18961 ASC_DBG(1, "advansys_release: begin\n"); 18933 ASC_DBG(1, "advansys_release: begin\n");
18962 boardp = ASC_BOARDP(shost); 18934 boardp = ASC_BOARDP(shost);
18963 free_irq(shost->irq, boardp); 18935 free_irq(shost->irq, shost);
18964 if (shost->dma_channel != NO_ISA_DMA) { 18936 if (shost->dma_channel != NO_ISA_DMA) {
18965 ASC_DBG(1, "advansys_release: free_dma()\n"); 18937 ASC_DBG(1, "advansys_release: free_dma()\n");
18966 free_dma(shost->dma_channel); 18938 free_dma(shost->dma_channel);