diff mbox series

[04/11] aacraid: Do not wait for outstanding write commands on synchronize_cache

Message ID 20191120103114.24723-5-hare@suse.de (mailing list archive)
State Superseded
Headers show
Series scsi: remove legacy cmd_list implementation | expand

Commit Message

Hannes Reinecke Nov. 20, 2019, 10:31 a.m. UTC
There is no need to wait for outstanding write commands on synchronize
cache; the block layer is responsible for I/O scheduling, no need
to out-guess it on the driver layer.

Cc: Balsundar P <balsundar.p@microsemi.com>
Cc: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/aacraid/aachba.c | 76 ++-----------------------------------------
 1 file changed, 2 insertions(+), 74 deletions(-)

Comments

Christoph Hellwig Nov. 26, 2019, 5:02 p.m. UTC | #1
On Wed, Nov 20, 2019 at 11:31:07AM +0100, Hannes Reinecke wrote:
> There is no need to wait for outstanding write commands on synchronize
> cache; the block layer is responsible for I/O scheduling, no need
> to out-guess it on the driver layer.

So I think this doesn't make any sense as it doesn't fit the SCSI
SYNCRONIZE CACHE or Linux flush semantics, but i'd really like to hear
from the Microsemi folks.

FYI, below is the rather inconclusive commit from the history tree that
added this code originally:

---
From 45b95e26fd0e7dd6c38e424ee650becc15fe5975 Mon Sep 17 00:00:00 2001
From: Mark Haverkamp <markh@osdl.org>
Date: Sat, 22 Jan 2005 21:12:43 -0600
Subject: [PATCH] aacraid 2.6: add scsi synchronize cache support.

This is an update from the Adaptec driver that adds support for the scsi
synchronize cache command.  It essentially blocks further commands until
data has been flushed to the disks.

Signed-off-by: Mark Haverkamp <markh@osdl.org>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/scsi/aacraid/aachba.c  | 113 +++++++++++++++++++++++++++++++++
 drivers/scsi/aacraid/aacraid.h |  24 +++++++
 2 files changed, 137 insertions(+)

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 514caa9adc2c..782776243b96 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -1029,6 +1029,114 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
 	return 0;
 }
 
+static void synchronize_callback(void *context, struct fib *fibptr)
+{
+	struct aac_synchronize_reply *synchronizereply;
+	struct scsi_cmnd *cmd;
+
+	cmd = context;
+
+	dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", 
+				smp_processor_id(), jiffies));
+	BUG_ON(fibptr == NULL);
+
+
+	synchronizereply = fib_data(fibptr);
+	if (le32_to_cpu(synchronizereply->status) == CT_OK)
+		cmd->result = DID_OK << 16 | 
+			COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+	else {
+		struct scsi_device *sdev = cmd->device;
+		struct aac_dev *dev = (struct aav_dev *)sdev->host->hostdata;
+		u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun);
+		printk(KERN_WARNING 
+		     "synchronize_callback: synchronize failed, status = %d\n",
+		     synchronizereply->status);
+		cmd->result = DID_OK << 16 | 
+			COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
+		set_sense((u8 *)&dev->fsa_dev[cid].sense_data,
+				    HARDWARE_ERROR,
+				    SENCODE_INTERNAL_TARGET_FAILURE,
+				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+				    0, 0);
+		memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+		  min(sizeof(dev->fsa_dev[cid].sense_data), 
+			  sizeof(cmd->sense_buffer)));
+	}
+
+	fib_complete(fibptr);
+	fib_free(fibptr);
+	aac_io_done(cmd);
+}
+
+static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
+{
+	int status;
+	struct fib *cmd_fibcontext;
+	struct aac_synchronize *synchronizecmd;
+	struct scsi_cmnd *cmd;
+	struct scsi_device *sdev = scsicmd->device;
+	int active = 0;
+	unsigned long flags;
+
+	/*
+	 * Wait for all commands to complete to this specific
+	 * target (block).
+	 */
+	spin_lock_irqsave(&sdev->list_lock, flags);
+	list_for_each_entry(cmd, &sdev->cmd_list, list)
+		if (cmd != scsicmd && cmd->serial_number != 0) {
+			++active;
+			break;
+		}
+
+	spin_unlock_irqrestore(&sdev->list_lock, flags);
+
+	/*
+	 *	Yield the processor (requeue for later)
+	 */
+	if (active)
+		return SCSI_MLQUEUE_DEVICE_BUSY;
+
+	/*
+	 *	Alocate and initialize a Fib
+	 */
+	if (!(cmd_fibcontext = 
+	    fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) 
+		return SCSI_MLQUEUE_HOST_BUSY;
+
+	fib_init(cmd_fibcontext);
+
+	synchronizecmd = fib_data(cmd_fibcontext);
+	synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
+	synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE);
+	synchronizecmd->cid = cpu_to_le32(cid);
+	synchronizecmd->count = 
+	     cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
+
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	status = fib_send(ContainerCommand,
+		  cmd_fibcontext,
+		  sizeof(struct aac_synchronize),
+		  FsaNormal,
+		  0, 1,
+		  (fib_callback)synchronize_callback,
+		  (void *)scsicmd);
+
+	/*
+	 *	Check that the command queued to the controller
+	 */
+	if (status == -EINPROGRESS)
+		return 0;
+
+	printk(KERN_WARNING 
+		"aac_synchronize: fib_send failed with status: %d.\n", status);
+	fib_complete(cmd_fibcontext);
+	fib_free(cmd_fibcontext);
+	return SCSI_MLQUEUE_HOST_BUSY;
+}
 
 /**
  *	aac_scsi_cmd()		-	Process SCSI command
@@ -1274,6 +1382,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
 			ret = aac_write(scsicmd, cid);
 			spin_lock_irq(host->host_lock);
 			return ret;
+
+		case SYNCHRONIZE_CACHE:
+			/* Issue FIB to tell Firmware to flush it's cache */
+			return aac_synchronize(scsicmd, cid);
+			
 		default:
 			/*
 			 *	Unhandled commands
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 987222ef30e1..7309129568b6 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1069,6 +1069,30 @@ struct aac_write_reply
 	u32		committed;
 };
 
+#define CT_FLUSH_CACHE 129
+struct aac_synchronize {
+	u32		command;	/* VM_ContainerConfig */
+	u32		type;		/* CT_FLUSH_CACHE */
+	u32		cid;
+	u32		parm1;
+	u32		parm2;
+	u32		parm3;
+	u32		parm4;
+	u32		count;	/* sizeof(((struct aac_synchronize_reply *)NULL)->data) */
+};
+
+struct aac_synchronize_reply {
+	u32		dummy0;
+	u32		dummy1;
+	u32		status;	/* CT_OK */
+	u32		parm1;
+	u32		parm2;
+	u32		parm3;
+	u32		parm4;
+	u32		parm5;
+	u8		data[16];
+};
+
 struct aac_srb
 {
 	u32		function;
Balsundar.P@microchip.com Nov. 28, 2019, 11:40 a.m. UTC | #2
Acked-by: Balsundar P < Balsundar.P@microchip.com>

Before flushing the cache, raid firmware will ensure no commands are active.
This patch can be applied.

-----Original Message-----
From: Hannes Reinecke <hare@suse.de> 
Sent: Wednesday, November 20, 2019 16:01
To: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>; James Bottomley <james.bottomley@hansenpartnership.com>; linux-scsi@vger.kernel.org; Hannes Reinecke <hare@suse.de>; Balsundar P <balsundar.p@microsemi.com>; Adaptec OEM Raid Solutions <aacraid@microsemi.com>
Subject: [PATCH 04/11] aacraid: Do not wait for outstanding write commands on synchronize_cache

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

There is no need to wait for outstanding write commands on synchronize cache; the block layer is responsible for I/O scheduling, no need to out-guess it on the driver layer.

Cc: Balsundar P <balsundar.p@microsemi.com>
Cc: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/aacraid/aachba.c | 76 ++-----------------------------------------
 1 file changed, 2 insertions(+), 74 deletions(-)

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index e36608ce937a..cfa14e15d5f0 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -2601,9 +2601,7 @@ static int aac_write(struct scsi_cmnd * scsicmd)  static void synchronize_callback(void *context, struct fib *fibptr)  {
        struct aac_synchronize_reply *synchronizereply;
-       struct scsi_cmnd *cmd;
-
-       cmd = context;
+       struct scsi_cmnd *cmd = context;

        if (!aac_valid_context(cmd, fibptr))
                return;
@@ -2644,77 +2642,8 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
        int status;
        struct fib *cmd_fibcontext;
        struct aac_synchronize *synchronizecmd;
-       struct scsi_cmnd *cmd;
        struct scsi_device *sdev = scsicmd->device;
-       int active = 0;
        struct aac_dev *aac;
-       u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) |
-               (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
-       u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
-       unsigned long flags;
-
-       /*
-        * Wait for all outstanding queued commands to complete to this
-        * specific target (block).
-        */
-       spin_lock_irqsave(&sdev->list_lock, flags);
-       list_for_each_entry(cmd, &sdev->cmd_list, list)
-               if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
-                       u64 cmnd_lba;
-                       u32 cmnd_count;
-
-                       if (cmd->cmnd[0] == WRITE_6) {
-                               cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) |
-                                       (cmd->cmnd[2] << 8) |
-                                       cmd->cmnd[3];
-                               cmnd_count = cmd->cmnd[4];
-                               if (cmnd_count == 0)
-                                       cmnd_count = 256;
-                       } else if (cmd->cmnd[0] == WRITE_16) {
-                               cmnd_lba = ((u64)cmd->cmnd[2] << 56) |
-                                       ((u64)cmd->cmnd[3] << 48) |
-                                       ((u64)cmd->cmnd[4] << 40) |
-                                       ((u64)cmd->cmnd[5] << 32) |
-                                       ((u64)cmd->cmnd[6] << 24) |
-                                       (cmd->cmnd[7] << 16) |
-                                       (cmd->cmnd[8] << 8) |
-                                       cmd->cmnd[9];
-                               cmnd_count = (cmd->cmnd[10] << 24) |
-                                       (cmd->cmnd[11] << 16) |
-                                       (cmd->cmnd[12] << 8) |
-                                       cmd->cmnd[13];
-                       } else if (cmd->cmnd[0] == WRITE_12) {
-                               cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
-                                       (cmd->cmnd[3] << 16) |
-                                       (cmd->cmnd[4] << 8) |
-                                       cmd->cmnd[5];
-                               cmnd_count = (cmd->cmnd[6] << 24) |
-                                       (cmd->cmnd[7] << 16) |
-                                       (cmd->cmnd[8] << 8) |
-                                       cmd->cmnd[9];
-                       } else if (cmd->cmnd[0] == WRITE_10) {
-                               cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
-                                       (cmd->cmnd[3] << 16) |
-                                       (cmd->cmnd[4] << 8) |
-                                       cmd->cmnd[5];
-                               cmnd_count = (cmd->cmnd[7] << 8) |
-                                       cmd->cmnd[8];
-                       } else
-                               continue;
-                       if (((cmnd_lba + cmnd_count) < lba) ||
-                         (count && ((lba + count) < cmnd_lba)))
-                               continue;
-                       ++active;
-                       break;
-               }
-
-       spin_unlock_irqrestore(&sdev->list_lock, flags);
-
-       /*
-        *      Yield the processor (requeue for later)
-        */
-       if (active)
-               return SCSI_MLQUEUE_DEVICE_BUSY;

        aac = (struct aac_dev *)sdev->host->hostdata;
        if (aac->in_reset)
@@ -2723,8 +2652,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
        /*
         *      Allocate and initialize a Fib
         */
-       if (!(cmd_fibcontext = aac_fib_alloc(aac)))
-               return SCSI_MLQUEUE_HOST_BUSY;
+       cmd_fibcontext = aac_fib_alloc_tag(aac, scsicmd);

        aac_fib_init(cmd_fibcontext);

--
2.16.4
diff mbox series

Patch

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index e36608ce937a..cfa14e15d5f0 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -2601,9 +2601,7 @@  static int aac_write(struct scsi_cmnd * scsicmd)
 static void synchronize_callback(void *context, struct fib *fibptr)
 {
 	struct aac_synchronize_reply *synchronizereply;
-	struct scsi_cmnd *cmd;
-
-	cmd = context;
+	struct scsi_cmnd *cmd = context;
 
 	if (!aac_valid_context(cmd, fibptr))
 		return;
@@ -2644,77 +2642,8 @@  static int aac_synchronize(struct scsi_cmnd *scsicmd)
 	int status;
 	struct fib *cmd_fibcontext;
 	struct aac_synchronize *synchronizecmd;
-	struct scsi_cmnd *cmd;
 	struct scsi_device *sdev = scsicmd->device;
-	int active = 0;
 	struct aac_dev *aac;
-	u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) |
-		(scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
-	u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
-	unsigned long flags;
-
-	/*
-	 * Wait for all outstanding queued commands to complete to this
-	 * specific target (block).
-	 */
-	spin_lock_irqsave(&sdev->list_lock, flags);
-	list_for_each_entry(cmd, &sdev->cmd_list, list)
-		if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
-			u64 cmnd_lba;
-			u32 cmnd_count;
-
-			if (cmd->cmnd[0] == WRITE_6) {
-				cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) |
-					(cmd->cmnd[2] << 8) |
-					cmd->cmnd[3];
-				cmnd_count = cmd->cmnd[4];
-				if (cmnd_count == 0)
-					cmnd_count = 256;
-			} else if (cmd->cmnd[0] == WRITE_16) {
-				cmnd_lba = ((u64)cmd->cmnd[2] << 56) |
-					((u64)cmd->cmnd[3] << 48) |
-					((u64)cmd->cmnd[4] << 40) |
-					((u64)cmd->cmnd[5] << 32) |
-					((u64)cmd->cmnd[6] << 24) |
-					(cmd->cmnd[7] << 16) |
-					(cmd->cmnd[8] << 8) |
-					cmd->cmnd[9];
-				cmnd_count = (cmd->cmnd[10] << 24) |
-					(cmd->cmnd[11] << 16) |
-					(cmd->cmnd[12] << 8) |
-					cmd->cmnd[13];
-			} else if (cmd->cmnd[0] == WRITE_12) {
-				cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
-					(cmd->cmnd[3] << 16) |
-					(cmd->cmnd[4] << 8) |
-					cmd->cmnd[5];
-				cmnd_count = (cmd->cmnd[6] << 24) |
-					(cmd->cmnd[7] << 16) |
-					(cmd->cmnd[8] << 8) |
-					cmd->cmnd[9];
-			} else if (cmd->cmnd[0] == WRITE_10) {
-				cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
-					(cmd->cmnd[3] << 16) |
-					(cmd->cmnd[4] << 8) |
-					cmd->cmnd[5];
-				cmnd_count = (cmd->cmnd[7] << 8) |
-					cmd->cmnd[8];
-			} else
-				continue;
-			if (((cmnd_lba + cmnd_count) < lba) ||
-			  (count && ((lba + count) < cmnd_lba)))
-				continue;
-			++active;
-			break;
-		}
-
-	spin_unlock_irqrestore(&sdev->list_lock, flags);
-
-	/*
-	 *	Yield the processor (requeue for later)
-	 */
-	if (active)
-		return SCSI_MLQUEUE_DEVICE_BUSY;
 
 	aac = (struct aac_dev *)sdev->host->hostdata;
 	if (aac->in_reset)
@@ -2723,8 +2652,7 @@  static int aac_synchronize(struct scsi_cmnd *scsicmd)
 	/*
 	 *	Allocate and initialize a Fib
 	 */
-	if (!(cmd_fibcontext = aac_fib_alloc(aac)))
-		return SCSI_MLQUEUE_HOST_BUSY;
+	cmd_fibcontext = aac_fib_alloc_tag(aac, scsicmd);
 
 	aac_fib_init(cmd_fibcontext);