From bed30de47b034b5f28fb7db2fae4860b9d9c0622 Mon Sep 17 00:00:00 2001
From: Mark Haverkamp <markh@osdl.org>
Date: Wed, 3 Aug 2005 15:38:51 -0700
Subject: [SCSI] aacraid: interupt mitigation

Received from Mark Salyzyn from Adaptec:

If more than two commands are outstanding to the controller, there is no
need to notify the adapter via a PCI bus transaction of additional
commands added into the queue; it will get to them when it works through
the produce/consumer indexes.

This reduced the PCI traffic in the driver to submit a command to the
queue to near zero allowing a significant number of commands to be
turned around with no need to block for the PCI bridge to flush the
notify request to the adapter.

Interrupt mitigation has always been present in the driver; it was
turned off because of a bug that prevented one from realizing the
usefulness of the feature. This bug is fixed in this patch.

Signed-off-by: Mark Haverkamp <markh@osdl.org>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/scsi/aacraid/comminit.c |  4 +++-
 drivers/scsi/aacraid/commsup.c  | 20 +++++++++++++++++---
 2 files changed, 20 insertions(+), 4 deletions(-)

(limited to 'drivers/scsi')

diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 43557bf661f..75abd045328 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -44,7 +44,9 @@
 
 #include "aacraid.h"
 
-struct aac_common aac_config;
+struct aac_common aac_config = {
+	.irq_mod = 1
+};
 
 static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
 {
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 5322865942e..a1d303f0348 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -254,6 +254,7 @@ static void fib_dealloc(struct fib * fibptr)
 static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify)
 {
 	struct aac_queue * q;
+	unsigned long idx;
 
 	/*
 	 *	All of the queues wrap when they reach the end, so we check
@@ -263,10 +264,23 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
 	 */
 
 	q = &dev->queues->queue[qid];
-	
-	*index = le32_to_cpu(*(q->headers.producer));
-	if ((*index - 2) == le32_to_cpu(*(q->headers.consumer)))
+
+	idx = *index = le32_to_cpu(*(q->headers.producer));
+	/* Interrupt Moderation, only interrupt for first two entries */
+	if (idx != le32_to_cpu(*(q->headers.consumer))) {
+		if (--idx == 0) {
+			if (qid == AdapHighCmdQueue)
+				idx = ADAP_HIGH_CMD_ENTRIES;
+			else if (qid == AdapNormCmdQueue)
+				idx = ADAP_NORM_CMD_ENTRIES;
+			else if (qid == AdapHighRespQueue) 
+	        		idx = ADAP_HIGH_RESP_ENTRIES;
+			else if (qid == AdapNormRespQueue) 
+				idx = ADAP_NORM_RESP_ENTRIES;
+		}
+		if (idx != le32_to_cpu(*(q->headers.consumer)))
 			*nonotify = 1; 
+	}
 
 	if (qid == AdapHighCmdQueue) {
 	        if (*index >= ADAP_HIGH_CMD_ENTRIES)
-- 
cgit v1.2.3-70-g09d2