Commit 45b95e26 authored by Mark Haverkamp's avatar Mark Haverkamp Committed by James Bottomley

[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: default avatarMark Haverkamp <markh@osdl.org>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 02984f02
...@@ -1029,6 +1029,114 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) ...@@ -1029,6 +1029,114 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
return 0; 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 * aac_scsi_cmd() - Process SCSI command
...@@ -1274,6 +1382,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) ...@@ -1274,6 +1382,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
ret = aac_write(scsicmd, cid); ret = aac_write(scsicmd, cid);
spin_lock_irq(host->host_lock); spin_lock_irq(host->host_lock);
return ret; return ret;
case SYNCHRONIZE_CACHE:
/* Issue FIB to tell Firmware to flush it's cache */
return aac_synchronize(scsicmd, cid);
default: default:
/* /*
* Unhandled commands * Unhandled commands
......
...@@ -1069,6 +1069,30 @@ struct aac_write_reply ...@@ -1069,6 +1069,30 @@ struct aac_write_reply
u32 committed; 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 struct aac_srb
{ {
u32 function; u32 function;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment