summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/aachba.c
diff options
context:
space:
mode:
authorMark Haverkamp <markh@osdl.org>2005-05-16 18:28:42 -0700
committerJames Bottomley <jejb@mulgrave.(none)>2005-05-20 15:48:00 -0500
commit7c00ffa314bf0fb0e23858bbebad33b48b6abbb9 (patch)
tree4d6b65bb5a2c8fecf48a8c6402c2cc867aa2fe6c /drivers/scsi/aacraid/aachba.c
parent672b2d38da4fff4c4452685a25fb88b65243d1a6 (diff)
downloadblackbird-obmc-linux-7c00ffa314bf0fb0e23858bbebad33b48b6abbb9.tar.gz
blackbird-obmc-linux-7c00ffa314bf0fb0e23858bbebad33b48b6abbb9.zip
[SCSI] 2.6 aacraid: Variable FIB size (updated patch)
New code from the Adaptec driver. Performance enhancement for newer adapters. I hope that this isn't too big for a single patch. I believe that other than the few small cleanups mentioned, that the changes are all related. - Added Variable FIB size negotiation for new adapters. - Added support to maximize scatter gather tables and thus permit requests larger than 64KB/each. - Limit Scatter Gather to 34 elements for ROMB platforms. - aac_printf is only enabled with AAC_QUIRK_34SG - Large FIB ioctl support - some minor cleanup Passes sparse check. I have tested it on x86 and ppc64 machines. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r--drivers/scsi/aacraid/aachba.c132
1 files changed, 95 insertions, 37 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 9946e305055b..f02c99641467 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -53,10 +53,6 @@
#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */
#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */
-#define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER))
-
-#define MAX_DRIVER_SG_SEGMENT_COUNT 17
-
/*
* Sense codes
*/
@@ -158,6 +154,13 @@ MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0
module_param(commit, int, 0);
MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
+int numacb = -1;
+module_param(numacb, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid\nvalues are 512 and down. Default is to use suggestion from Firmware.");
+
+int acbsize = -1;
+module_param(acbsize, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512,\n2048, 4096 and 8192. Default is to use suggestion from Firmware.");
/**
* aac_get_config_status - check the adapter configuration
* @common: adapter to query
@@ -462,7 +465,7 @@ static int probe_container(struct aac_dev *dev, int cid)
1, 1,
NULL, NULL);
if (status < 0) {
- printk(KERN_WARNING "aacraid: probe_containers query failed.\n");
+ printk(KERN_WARNING "aacraid: probe_container query failed.\n");
goto error;
}
@@ -605,35 +608,63 @@ static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
int aac_get_adapter_info(struct aac_dev* dev)
{
struct fib* fibptr;
- struct aac_adapter_info* info;
int rcode;
u32 tmp;
+ struct aac_adapter_info * info;
+
if (!(fibptr = fib_alloc(dev)))
return -ENOMEM;
fib_init(fibptr);
- info = (struct aac_adapter_info*) fib_data(fibptr);
-
- memset(info,0,sizeof(struct aac_adapter_info));
+ info = (struct aac_adapter_info *) fib_data(fibptr);
+ memset(info,0,sizeof(*info));
rcode = fib_send(RequestAdapterInfo,
- fibptr,
- sizeof(struct aac_adapter_info),
- FsaNormal,
- 1, 1,
- NULL,
- NULL);
+ fibptr,
+ sizeof(*info),
+ FsaNormal,
+ 1, 1,
+ NULL,
+ NULL);
+
+ if (rcode < 0) {
+ fib_complete(fibptr);
+ fib_free(fibptr);
+ return rcode;
+ }
+ memcpy(&dev->adapter_info, info, sizeof(*info));
- memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
+ if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
+ struct aac_supplement_adapter_info * info;
+
+ fib_init(fibptr);
+
+ info = (struct aac_supplement_adapter_info *) fib_data(fibptr);
+
+ memset(info,0,sizeof(*info));
+
+ rcode = fib_send(RequestSupplementAdapterInfo,
+ fibptr,
+ sizeof(*info),
+ FsaNormal,
+ 1, 1,
+ NULL,
+ NULL);
+
+ if (rcode >= 0)
+ memcpy(&dev->supplement_adapter_info, info, sizeof(*info));
+ }
tmp = le32_to_cpu(dev->adapter_info.kernelrev);
- printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d]\n",
+ printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
dev->name,
dev->id,
tmp>>24,
(tmp>>16)&0xff,
tmp&0xff,
- le32_to_cpu(dev->adapter_info.kernelbuild));
+ le32_to_cpu(dev->adapter_info.kernelbuild),
+ (int)sizeof(dev->supplement_adapter_info.BuildDate),
+ dev->supplement_adapter_info.BuildDate);
tmp = le32_to_cpu(dev->adapter_info.monitorrev);
printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n",
dev->name, dev->id,
@@ -707,6 +738,38 @@ int aac_get_adapter_info(struct aac_dev* dev)
rcode = -ENOMEM;
}
}
+ /*
+ * 57 scatter gather elements
+ */
+ dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
+ sizeof(struct aac_fibhdr) -
+ sizeof(struct aac_write) + sizeof(struct sgmap)) /
+ sizeof(struct sgmap);
+ if (dev->dac_support) {
+ /*
+ * 38 scatter gather elements
+ */
+ dev->scsi_host_ptr->sg_tablesize =
+ (dev->max_fib_size -
+ sizeof(struct aac_fibhdr) -
+ sizeof(struct aac_write64) +
+ sizeof(struct sgmap64)) /
+ sizeof(struct sgmap64);
+ }
+ dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+ if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
+ /*
+ * Worst case size that could cause sg overflow when
+ * we break up SG elements that are larger than 64KB.
+ * Would be nice if we could tell the SCSI layer what
+ * the maximum SG element size can be. Worst case is
+ * (sg_tablesize-1) 4KB elements with one 64KB
+ * element.
+ * 32bit -> 468 or 238KB 64bit -> 424 or 212KB
+ */
+ dev->scsi_host_ptr->max_sectors =
+ (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+ }
fib_complete(fibptr);
fib_free(fibptr);
@@ -747,8 +810,10 @@ static void read_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(readreply->status) == ST_OK)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
else {
- printk(KERN_WARNING "read_callback: read failed, status = %d\n",
- le32_to_cpu(readreply->status));
+#ifdef AAC_DETAILED_STATUS_INFO
+ printk(KERN_WARNING "read_callback: io failed, status = %d\n",
+ le32_to_cpu(readreply->status));
+#endif
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR,
@@ -842,7 +907,8 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
}
- dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+ dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n",
+ smp_processor_id(), (unsigned long long)lba, jiffies));
/*
* Alocate and initialize a Fib
*/
@@ -852,7 +918,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fib_init(cmd_fibcontext);
- if(dev->dac_support == 1) {
+ if (dev->dac_support == 1) {
struct aac_read64 *readcmd;
readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -886,14 +952,11 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
readcmd->block = cpu_to_le32(lba);
readcmd->count = cpu_to_le32(count * 512);
- if (count * 512 > (64 * 1024))
- BUG();
-
aac_build_sg(scsicmd, &readcmd->sg);
fibsize = sizeof(struct aac_read) +
((le32_to_cpu(readcmd->sg.count) - 1) *
sizeof (struct sgentry));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -976,7 +1039,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
fibsize = sizeof(struct aac_write64) +
((le32_to_cpu(writecmd->sg.count) - 1) *
sizeof (struct sgentry64));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -998,15 +1061,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
writecmd->sg.count = cpu_to_le32(1);
/* ->stable is not used - it did mean which type of write */
- if (count * 512 > (64 * 1024)) {
- BUG();
- }
-
aac_build_sg(scsicmd, &writecmd->sg);
fibsize = sizeof(struct aac_write) +
((le32_to_cpu(writecmd->sg.count) - 1) *
sizeof (struct sgentry));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -1025,7 +1084,6 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
*/
if (status == -EINPROGRESS)
{
- dprintk("write queued.\n");
return 0;
}
@@ -1111,7 +1169,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
return SCSI_MLQUEUE_DEVICE_BUSY;
/*
- * Alocate and initialize a Fib
+ * Allocate and initialize a Fib
*/
if (!(cmd_fibcontext =
fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
@@ -1403,7 +1461,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
/*
* Unhandled commands
*/
- printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]);
+ dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
@@ -1818,7 +1876,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
((le32_to_cpu(srbcmd->sg.count) & 0xff) *
sizeof (struct sgentry64));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
@@ -1840,7 +1898,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
fibsize = sizeof (struct aac_srb) +
(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
sizeof (struct sgentry));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
OpenPOWER on IntegriCloud