Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 074c8fe4 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by James Bottomley
Browse files

[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: default avatarMatthew Wilcox <matthew@wil.cx>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 2a437959
Loading
Loading
Loading
Loading
+72 −100
Original line number Diff line number Diff line
@@ -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,33 +4683,23 @@ 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;
	ASC_DBG(1, "advansys_interrupt: begin\n");
	struct Scsi_Host *shost = dev_id;
	asc_board_t *boardp = ASC_BOARDP(shost);
	irqreturn_t result = IRQ_NONE;
	/*
	 * 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);
	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");
			ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
			AscISR(&boardp->dvc_var.asc_dvc_var);
		}
	} else {
@@ -4719,6 +4708,7 @@ static irqreturn_t advansys_interrupt(int irq, void *dev_id)
		 */
		ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
		if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
			result = IRQ_HANDLED;
			ASC_STATS(shost, interrupt);
		}
	}
@@ -4730,28 +4720,25 @@ static irqreturn_t advansys_interrupt(int irq, void *dev_id)
	 * 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%lx, last_scp 0x%lx\n",
				 (ulong)done_scp, (ulong)last_scp);
		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_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'.
		 * '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);
			done_scp = asc_dequeue_list(&boardp->done,
						&last_scp, ASC_TID_ALL);
		} else {
			ASC_ASSERT(last_scp != NULL);
			last_scp->host_scribble =
@@ -4766,7 +4753,6 @@ static irqreturn_t advansys_interrupt(int irq, void *dev_id)
		}
	}
	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);