aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/aacraid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r--drivers/scsi/aacraid/aachba.c165
-rw-r--r--drivers/scsi/aacraid/aacraid.h468
-rw-r--r--drivers/scsi/aacraid/commctrl.c228
-rw-r--r--drivers/scsi/aacraid/comminit.c92
-rw-r--r--drivers/scsi/aacraid/commsup.c100
-rw-r--r--drivers/scsi/aacraid/dpcsup.c6
-rw-r--r--drivers/scsi/aacraid/linit.c179
-rw-r--r--drivers/scsi/aacraid/rkt.c43
-rw-r--r--drivers/scsi/aacraid/rx.c46
-rw-r--r--drivers/scsi/aacraid/sa.c35
10 files changed, 924 insertions, 438 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index f3fc3538606..f02c9964146 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;
}
@@ -562,10 +565,10 @@ static void setinqstr(int devtype, void *data, int tindex)
inqstrcpy ("V1.0", str->prl);
}
-void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
- u8 a_sense_code, u8 incorrect_length,
- u8 bit_pointer, u16 field_pointer,
- u32 residue)
+static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
+ u8 a_sense_code, u8 incorrect_length,
+ u8 bit_pointer, u16 field_pointer,
+ u32 residue)
{
sense_buf[0] = 0xF0; /* Sense data valid, err code 70h (current error) */
sense_buf[1] = 0; /* Segment number, always zero */
@@ -605,35 +608,63 @@ 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));
+
+ if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
+ struct aac_supplement_adapter_info * info;
- memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_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,
@@ -813,7 +878,7 @@ static void write_callback(void *context, struct fib * fibptr)
aac_io_done(scsicmd);
}
-int aac_read(struct scsi_cmnd * scsicmd, int cid)
+static int aac_read(struct scsi_cmnd * scsicmd, int cid)
{
u32 lba;
u32 count;
@@ -842,7 +907,8 @@ 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 @@ 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 @@ 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)));
/*
@@ -1893,7 +1951,9 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
}
/* hba wants the size to be exact */
if(byte_count > scsicmd->request_bufflen){
- psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
+ u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+ (byte_count - scsicmd->request_bufflen);
+ psg->sg[i-1].count = cpu_to_le32(temp);
byte_count = scsicmd->request_bufflen;
}
/* Check for command underflow */
@@ -1922,7 +1982,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
{
struct aac_dev *dev;
unsigned long byte_count = 0;
- u64 le_addr;
+ u64 addr;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
// Get rid of old data
@@ -1943,16 +2003,18 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
byte_count = 0;
for (i = 0; i < sg_count; i++) {
- le_addr = cpu_to_le64(sg_dma_address(sg));
- psg->sg[i].addr[1] = (u32)(le_addr>>32);
- psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
+ addr = sg_dma_address(sg);
+ psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
byte_count += sg_dma_len(sg);
sg++;
}
/* hba wants the size to be exact */
if(byte_count > scsicmd->request_bufflen){
- psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
+ u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+ (byte_count - scsicmd->request_bufflen);
+ psg->sg[i-1].count = cpu_to_le32(temp);
byte_count = scsicmd->request_bufflen;
}
/* Check for command underflow */
@@ -1962,15 +2024,14 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
}
}
else if(scsicmd->request_bufflen) {
- dma_addr_t addr;
+ u64 addr;
addr = pci_map_single(dev->pdev,
scsicmd->request_buffer,
scsicmd->request_bufflen,
scsicmd->sc_data_direction);
psg->count = cpu_to_le32(1);
- le_addr = cpu_to_le64(addr);
- psg->sg[0].addr[1] = (u32)(le_addr>>32);
- psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);
+ psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);
scsicmd->SCp.dma_handle = addr;
byte_count = scsicmd->request_bufflen;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 700d90331c1..42484417cef 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -8,12 +8,18 @@
#define MAXIMUM_NUM_CONTAINERS 32
-#define AAC_NUM_FIB (256 + 64)
-#define AAC_NUM_IO_FIB 100
+#define AAC_NUM_MGT_FIB 8
+#define AAC_NUM_IO_FIB (512 - AAC_NUM_MGT_FIB)
+#define AAC_NUM_FIB (AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB)
#define AAC_MAX_LUN (8)
#define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
+/*
+ * max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512
+ * Linux has starvation problems if we permit larger than 4MB I/O ...
+ */
+#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)8192)
/*
* These macros convert from physical channels to virtual channels
@@ -89,11 +95,21 @@ struct diskparm
* on 64 bit systems not all cards support the 64 bit version
*/
struct sgentry {
+ __le32 addr; /* 32-bit address. */
+ __le32 count; /* Length. */
+};
+
+struct user_sgentry {
u32 addr; /* 32-bit address. */
u32 count; /* Length. */
};
struct sgentry64 {
+ __le32 addr[2]; /* 64-bit addr. 2 pieces for data alignment */
+ __le32 count; /* Length. */
+};
+
+struct user_sgentry64 {
u32 addr[2]; /* 64-bit addr. 2 pieces for data alignment */
u32 count; /* Length. */
};
@@ -106,15 +122,25 @@ struct sgentry64 {
*/
struct sgmap {
- u32 count;
+ __le32 count;
struct sgentry sg[1];
};
-struct sgmap64 {
+struct user_sgmap {
u32 count;
+ struct user_sgentry sg[1];
+};
+
+struct sgmap64 {
+ __le32 count;
struct sgentry64 sg[1];
};
+struct user_sgmap64 {
+ u32 count;
+ struct user_sgentry64 sg[1];
+};
+
struct creation_info
{
u8 buildnum; /* e.g., 588 */
@@ -123,14 +149,14 @@ struct creation_info
* 2 = API
*/
u8 year; /* e.g., 1997 = 97 */
- u32 date; /*
+ __le32 date; /*
* unsigned Month :4; // 1 - 12
* unsigned Day :6; // 1 - 32
* unsigned Hour :6; // 0 - 23
* unsigned Minute :6; // 0 - 60
* unsigned Second :6; // 0 - 60
*/
- u32 serial[2]; /* e.g., 0x1DEADB0BFAFAF001 */
+ __le32 serial[2]; /* e.g., 0x1DEADB0BFAFAF001 */
};
@@ -175,8 +201,8 @@ struct creation_info
*/
struct aac_entry {
- u32 size; /* Size in bytes of Fib which this QE points to */
- u32 addr; /* Receiver address of the FIB */
+ __le32 size; /* Size in bytes of Fib which this QE points to */
+ __le32 addr; /* Receiver address of the FIB */
};
/*
@@ -185,9 +211,10 @@ struct aac_entry {
*/
struct aac_qhdr {
- u64 header_addr; /* Address to hand the adapter to access to this queue head */
- u32 *producer; /* The producer index for this queue (host address) */
- u32 *consumer; /* The consumer index for this queue (host address) */
+ __le64 header_addr;/* Address to hand the adapter to access
+ to this queue head */
+ __le32 *producer; /* The producer index for this queue (host address) */
+ __le32 *consumer; /* The consumer index for this queue (host address) */
};
/*
@@ -261,29 +288,30 @@ enum aac_queue_types {
*/
struct aac_fibhdr {
- u32 XferState; // Current transfer state for this CCB
- u16 Command; // Routing information for the destination
- u8 StructType; // Type FIB
- u8 Flags; // Flags for FIB
- u16 Size; // Size of this FIB in bytes
- u16 SenderSize; // Size of the FIB in the sender (for response sizing)
- u32 SenderFibAddress; // Host defined data in the FIB
- u32 ReceiverFibAddress; // Logical address of this FIB for the adapter
- u32 SenderData; // Place holder for the sender to store data
+ __le32 XferState; /* Current transfer state for this CCB */
+ __le16 Command; /* Routing information for the destination */
+ u8 StructType; /* Type FIB */
+ u8 Flags; /* Flags for FIB */
+ __le16 Size; /* Size of this FIB in bytes */
+ __le16 SenderSize; /* Size of the FIB in the sender
+ (for response sizing) */
+ __le32 SenderFibAddress; /* Host defined data in the FIB */
+ __le32 ReceiverFibAddress;/* Logical address of this FIB for
+ the adapter */
+ u32 SenderData; /* Place holder for the sender to store data */
union {
struct {
- u32 _ReceiverTimeStart; // Timestamp for receipt of fib
- u32 _ReceiverTimeDone; // Timestamp for completion of fib
+ __le32 _ReceiverTimeStart; /* Timestamp for
+ receipt of fib */
+ __le32 _ReceiverTimeDone; /* Timestamp for
+ completion of fib */
} _s;
} _u;
};
-#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr))
-
-
struct hw_fib {
struct aac_fibhdr header;
- u8 data[FIB_DATA_SIZE_IN_BYTES]; // Command specific data
+ u8 data[512-sizeof(struct aac_fibhdr)]; // Command specific data
};
/*
@@ -345,11 +373,12 @@ struct hw_fib {
#define RequestAdapterInfo 703
#define IsAdapterPaused 704
#define SendHostTime 705
-#define LastMiscCommand 706
+#define RequestSupplementAdapterInfo 706
+#define LastMiscCommand 707
-//
-// Commands that will target the failover level on the FSA adapter
-//
+/*
+ * Commands that will target the failover level on the FSA adapter
+ */
enum fib_xfer_state {
HostOwned = (1<<0),
@@ -382,22 +411,32 @@ enum fib_xfer_state {
*/
#define ADAPTER_INIT_STRUCT_REVISION 3
+#define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science
struct aac_init
{
- u32 InitStructRevision;
- u32 MiniPortRevision;
- u32 fsrev;
- u32 CommHeaderAddress;
- u32 FastIoCommAreaAddress;
- u32 AdapterFibsPhysicalAddress;
- u32 AdapterFibsVirtualAddress;
- u32 AdapterFibsSize;
- u32 AdapterFibAlign;
- u32 printfbuf;
- u32 printfbufsiz;
- u32 HostPhysMemPages; // number of 4k pages of host physical memory
- u32 HostElapsedSeconds; // number of seconds since 1970.
+ __le32 InitStructRevision;
+ __le32 MiniPortRevision;
+ __le32 fsrev;
+ __le32 CommHeaderAddress;
+ __le32 FastIoCommAreaAddress;
+ __le32 AdapterFibsPhysicalAddress;
+ __le32 AdapterFibsVirtualAddress;
+ __le32 AdapterFibsSize;
+ __le32 AdapterFibAlign;
+ __le32 printfbuf;
+ __le32 printfbufsiz;
+ __le32 HostPhysMemPages; /* number of 4k pages of host
+ physical memory */
+ __le32 HostElapsedSeconds; /* number of seconds since 1970. */
+ /*
+ * ADAPTER_INIT_STRUCT_REVISION_4 begins here
+ */
+ __le32 InitFlags; /* flags for supported features */
+#define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001
+ __le32 MaxIoCommands; /* max outstanding commands */
+ __le32 MaxIoSize; /* largest I/O command */
+ __le32 MaxFibSize; /* largest FIB to adapter */
};
enum aac_log_level {
@@ -421,7 +460,7 @@ struct adapter_ops
{
void (*adapter_interrupt)(struct aac_dev *dev);
void (*adapter_notify)(struct aac_dev *dev, u32 event);
- int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status);
+ int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev);
};
@@ -541,6 +580,7 @@ struct sa_drawbridge_CSR {
#define Mailbox3 SaDbCSR.MAILBOX3
#define Mailbox4 SaDbCSR.MAILBOX4
#define Mailbox5 SaDbCSR.MAILBOX5
+#define Mailbox6 SaDbCSR.MAILBOX6
#define Mailbox7 SaDbCSR.MAILBOX7
#define DoorbellReg_p SaDbCSR.PRISETIRQ
@@ -763,29 +803,48 @@ struct fib {
struct aac_adapter_info
{
- u32 platform;
- u32 cpu;
- u32 subcpu;
- u32 clock;
- u32 execmem;
- u32 buffermem;
- u32 totalmem;
- u32 kernelrev;
- u32 kernelbuild;
- u32 monitorrev;
- u32 monitorbuild;
- u32 hwrev;
- u32 hwbuild;
- u32 biosrev;
- u32 biosbuild;
- u32 cluster;
- u32 clusterchannelmask;
- u32 serial[2];
- u32 battery;
- u32 options;
- u32 OEM;
+ __le32 platform;
+ __le32 cpu;
+ __le32 subcpu;
+ __le32 clock;
+ __le32 execmem;
+ __le32 buffermem;
+ __le32 totalmem;
+ __le32 kernelrev;
+ __le32 kernelbuild;
+ __le32 monitorrev;
+ __le32 monitorbuild;
+ __le32 hwrev;
+ __le32 hwbuild;
+ __le32 biosrev;
+ __le32 biosbuild;
+ __le32 cluster;
+ __le32 clusterchannelmask;
+ __le32 serial[2];
+ __le32 battery;
+ __le32 options;
+ __le32 OEM;
};
+struct aac_supplement_adapter_info
+{
+ u8 AdapterTypeText[17+1];
+ u8 Pad[2];
+ __le32 FlashMemoryByteSize;
+ __le32 FlashImageId;
+ __le32 MaxNumberPorts;
+ __le32 Version;
+ __le32 FeatureBits;
+ u8 SlotNumber;
+ u8 ReservedPad0[0];
+ u8 BuildDate[12];
+ __le32 CurrentNumberPorts;
+ __le32 ReservedGrowth[24];
+};
+#define AAC_FEATURE_FALCON 0x00000010
+#define AAC_SIS_VERSION_V3 3
+#define AAC_SIS_SLOT_UNKNOWN 0xFF
+
/*
* Battery platforms
*/
@@ -831,6 +890,12 @@ struct aac_dev
u16 irq_mask;
/*
+ * negotiated FIB settings
+ */
+ unsigned max_fib_size;
+ unsigned sg_tablesize;
+
+ /*
* Map for 128 fib objects (64k)
*/
dma_addr_t hw_fib_pa;
@@ -889,12 +954,14 @@ struct aac_dev
u32 aif_thread;
struct completion aif_completion;
struct aac_adapter_info adapter_info;
+ struct aac_supplement_adapter_info supplement_adapter_info;
/* These are in adapter info but they are in the io flow so
* lets break them out so we don't have to do an AND to check them
*/
u8 nondasd_support;
u8 dac_support;
u8 raid_scsi_mode;
+ u8 printf_enabled;
};
#define aac_adapter_interrupt(dev) \
@@ -903,6 +970,8 @@ struct aac_dev
#define aac_adapter_notify(dev, event) \
(dev)->a_ops.adapter_notify(dev, event)
+#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
+ (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
#define aac_adapter_check_health(dev) \
(dev)->a_ops.adapter_check_health(dev)
@@ -1016,83 +1085,102 @@ struct aac_dev
struct aac_read
{
- u32 command;
- u32 cid;
- u32 block;
- u32 count;
+ __le32 command;
+ __le32 cid;
+ __le32 block;
+ __le32 count;
struct sgmap sg; // Must be last in struct because it is variable
};
struct aac_read64
{
- u32 command;
- u16 cid;
- u16 sector_count;
- u32 block;
- u16 pad;
- u16 flags;
+ __le32 command;
+ __le16 cid;
+ __le16 sector_count;
+ __le32 block;
+ __le16 pad;
+ __le16 flags;
struct sgmap64 sg; // Must be last in struct because it is variable
};
struct aac_read_reply
{
- u32 status;
- u32 count;
+ __le32 status;
+ __le32 count;
};
struct aac_write
{
- u32 command;
- u32 cid;
- u32 block;
- u32 count;
- u32 stable; // Not used
+ __le32 command;
+ __le32 cid;
+ __le32 block;
+ __le32 count;
+ __le32 stable; // Not used
struct sgmap sg; // Must be last in struct because it is variable
};
struct aac_write64
{
- u32 command;
- u16 cid;
- u16 sector_count;
- u32 block;
- u16 pad;
- u16 flags;
+ __le32 command;
+ __le16 cid;
+ __le16 sector_count;
+ __le32 block;
+ __le16 pad;
+ __le16 flags;
struct sgmap64 sg; // Must be last in struct because it is variable
};
struct aac_write_reply
{
- u32 status;
- u32 count;
- u32 committed;
+ __le32 status;
+ __le32 count;
+ __le32 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) */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_FLUSH_CACHE */
+ __le32 cid;
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 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;
+ __le32 dummy0;
+ __le32 dummy1;
+ __le32 status; /* CT_OK */
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 parm5;
u8 data[16];
};
struct aac_srb
{
+ __le32 function;
+ __le32 channel;
+ __le32 id;
+ __le32 lun;
+ __le32 timeout;
+ __le32 flags;
+ __le32 count; // Data xfer size
+ __le32 retry_limit;
+ __le32 cdb_size;
+ u8 cdb[16];
+ struct sgmap sg;
+};
+
+/*
+ * This and assocated data structs are used by the
+ * ioctl caller and are in cpu order.
+ */
+struct user_aac_srb
+{
u32 function;
u32 channel;
u32 id;
@@ -1103,20 +1191,18 @@ struct aac_srb
u32 retry_limit;
u32 cdb_size;
u8 cdb[16];
- struct sgmap sg;
+ struct user_sgmap sg;
};
-
-
#define AAC_SENSE_BUFFERSIZE 30
struct aac_srb_reply
{
- u32 status;
- u32 srb_status;
- u32 scsi_status;
- u32 data_xfer_length;
- u32 sense_data_size;
+ __le32 status;
+ __le32 srb_status;
+ __le32 scsi_status;
+ __le32 data_xfer_length;
+ __le32 sense_data_size;
u8 sense_data[AAC_SENSE_BUFFERSIZE]; // Can this be SCSI_SENSE_BUFFERSIZE
};
/*
@@ -1223,14 +1309,14 @@ struct aac_srb_reply
*/
struct aac_fsinfo {
- u32 fsTotalSize; /* Consumed by fs, incl. metadata */
- u32 fsBlockSize;
- u32 fsFragSize;
- u32 fsMaxExtendSize;
- u32 fsSpaceUnits;
- u32 fsMaxNumFiles;
- u32 fsNumFreeFiles;
- u32 fsInodeDensity;
+ __le32 fsTotalSize; /* Consumed by fs, incl. metadata */
+ __le32 fsBlockSize;
+ __le32 fsFragSize;
+ __le32 fsMaxExtendSize;
+ __le32 fsSpaceUnits;
+ __le32 fsMaxNumFiles;
+ __le32 fsNumFreeFiles;
+ __le32 fsInodeDensity;
}; /* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */
union aac_contentinfo {
@@ -1243,32 +1329,32 @@ union aac_contentinfo {
#define CT_GET_CONFIG_STATUS 147
struct aac_get_config_status {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_GET_CONFIG_STATUS */
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 parm5;
- u32 count; /* sizeof(((struct aac_get_config_status_resp *)NULL)->data) */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_GET_CONFIG_STATUS */
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 parm5;
+ __le32 count; /* sizeof(((struct aac_get_config_status_resp *)NULL)->data) */
};
#define CFACT_CONTINUE 0
#define CFACT_PAUSE 1
#define CFACT_ABORT 2
struct aac_get_config_status_resp {
- u32 response; /* ST_OK */
- u32 dummy0;
- u32 status; /* CT_OK */
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 parm5;
+ __le32 response; /* ST_OK */
+ __le32 dummy0;
+ __le32 status; /* CT_OK */
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 parm5;
struct {
- u32 action; /* CFACT_CONTINUE, CFACT_PAUSE or CFACT_ABORT */
- u16 flags;
- s16 count;
+ __le32 action; /* CFACT_CONTINUE, CFACT_PAUSE or CFACT_ABORT */
+ __le16 flags;
+ __le16 count;
} data;
};
@@ -1279,26 +1365,26 @@ struct aac_get_config_status_resp {
#define CT_COMMIT_CONFIG 152
struct aac_commit_config {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_COMMIT_CONFIG */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_COMMIT_CONFIG */
};
/*
- * Query for Container Configuration Count
+ * Query for Container Configuration Status
*/
#define CT_GET_CONTAINER_COUNT 4
struct aac_get_container_count {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_GET_CONTAINER_COUNT */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_GET_CONTAINER_COUNT */
};
struct aac_get_container_count_resp {
- u32 response; /* ST_OK */
- u32 dummy0;
- u32 MaxContainers;
- u32 ContainerSwitchEntries;
- u32 MaxPartitions;
+ __le32 response; /* ST_OK */
+ __le32 dummy0;
+ __le32 MaxContainers;
+ __le32 ContainerSwitchEntries;
+ __le32 MaxPartitions;
};
@@ -1308,15 +1394,19 @@ struct aac_get_container_count_resp {
*/
struct aac_mntent {
- u32 oid;
- u8 name[16]; // if applicable
- struct creation_info create_info; // if applicable
- u32 capacity;
- u32 vol; // substrate structure
- u32 obj; // FT_FILESYS, FT_DATABASE, etc.
- u32 state; // unready for mounting, readonly, etc.
- union aac_contentinfo fileinfo; // Info specific to content manager (eg, filesystem)
- u32 altoid; // != oid <==> snapshot or broken mirror exists
+ __le32 oid;
+ u8 name[16]; /* if applicable */
+ struct creation_info create_info; /* if applicable */
+ __le32 capacity;
+ __le32 vol; /* substrate structure */
+ __le32 obj; /* FT_FILESYS,
+ FT_DATABASE, etc. */
+ __le32 state; /* unready for mounting,
+ readonly, etc. */
+ union aac_contentinfo fileinfo; /* Info specific to content
+ manager (eg, filesystem) */
+ __le32 altoid; /* != oid <==> snapshot or
+ broken mirror exists */
};
#define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */
@@ -1324,40 +1414,40 @@ struct aac_mntent {
#define FSCS_HIDDEN 0x0004 /* should be ignored - set during a clear */
struct aac_query_mount {
- u32 command;
- u32 type;
- u32 count;
+ __le32 command;
+ __le32 type;
+ __le32 count;
};
struct aac_mount {
- u32 status;
- u32 type; /* should be same as that requested */
- u32 count;
+ __le32 status;
+ __le32 type; /* should be same as that requested */
+ __le32 count;
struct aac_mntent mnt[1];
};
#define CT_READ_NAME 130
struct aac_get_name {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_READ_NAME */
- u32 cid;
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 count; /* sizeof(((struct aac_get_name_resp *)NULL)->data) */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_READ_NAME */
+ __le32 cid;
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 count; /* sizeof(((struct aac_get_name_resp *)NULL)->data) */
};
#define CT_OK 218
struct aac_get_name_resp {
- u32 dummy0;
- u32 dummy1;
- u32 status; /* CT_OK */
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 parm5;
+ __le32 dummy0;
+ __le32 dummy1;
+ __le32 status; /* CT_OK */
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 parm5;
u8 data[16];
};
@@ -1366,8 +1456,8 @@ struct aac_get_name_resp {
*/
struct aac_close {
- u32 command;
- u32 cid;
+ __le32 command;
+ __le32 cid;
};
struct aac_query_disk
@@ -1434,6 +1524,7 @@ struct revision
#define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED)
#define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER)
#define FSACTL_GET_CONTAINERS 2131
+#define FSACTL_SEND_LARGE_FIB CTL_CODE(2138, METHOD_BUFFERED)
struct aac_common
@@ -1573,8 +1664,8 @@ extern struct aac_common aac_config;
*/
struct aac_aifcmd {
- u32 command; /* Tell host what type of notify this is */
- u32 seqnum; /* To allow ordering of reports (if necessary) */
+ __le32 command; /* Tell host what type of notify this is */
+ __le32 seqnum; /* To allow ordering of reports (if necessary) */
u8 data[1]; /* Undefined length (from kernel viewpoint) */
};
@@ -1597,7 +1688,6 @@ int fib_setup(struct aac_dev *dev);
void fib_map_free(struct aac_dev *dev);
void fib_free(struct fib * context);
void fib_init(struct fib * context);
-void fib_dealloc(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val);
int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
@@ -1621,3 +1711,5 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
+extern int numacb;
+extern int acbsize;
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 30dd1f7120f..1fef92d55de 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -51,15 +51,22 @@
* This routine sends a fib to the adapter on behalf of a user level
* program.
*/
+# define AAC_DEBUG_PREAMBLE KERN_INFO
+# define AAC_DEBUG_POSTAMBLE
static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
{
struct hw_fib * kfib;
struct fib *fibptr;
+ struct hw_fib * hw_fib = (struct hw_fib *)0;
+ dma_addr_t hw_fib_pa = (dma_addr_t)0LL;
+ unsigned size;
+ int retval;
fibptr = fib_alloc(dev);
- if(fibptr == NULL)
+ if(fibptr == NULL) {
return -ENOMEM;
+ }
kfib = fibptr->hw_fib;
/*
@@ -74,19 +81,24 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* will not overrun the buffer when we copy the memory. Return
* an error if we would.
*/
- if (le16_to_cpu(kfib->header.Size) >
- sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
- fib_free(fibptr);
- return -EINVAL;
+ size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr);
+ if (size < le16_to_cpu(kfib->header.SenderSize))
+ size = le16_to_cpu(kfib->header.SenderSize);
+ if (size > dev->max_fib_size) {
+ /* Highjack the hw_fib */
+ hw_fib = fibptr->hw_fib;
+ hw_fib_pa = fibptr->hw_fib_pa;
+ fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
+ memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);
+ memcpy(kfib, hw_fib, dev->max_fib_size);
}
- if (copy_from_user(kfib, arg, le16_to_cpu(kfib->header.Size) +
- sizeof(struct aac_fibhdr))) {
- fib_free(fibptr);
- return -EFAULT;
+ if (copy_from_user(kfib, arg, size)) {
+ retval = -EFAULT;
+ goto cleanup;
}
- if (kfib->header.Command == cpu_to_le32(TakeABreakPt)) {
+ if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {
aac_adapter_interrupt(dev);
/*
* Since we didn't really send a fib, zero out the state to allow
@@ -94,16 +106,15 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
*/
kfib->header.XferState = 0;
} else {
- int retval = fib_send(kfib->header.Command, fibptr,
+ retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
le16_to_cpu(kfib->header.Size) , FsaNormal,
1, 1, NULL, NULL);
if (retval) {
- fib_free(fibptr);
- return retval;
+ goto cleanup;
}
if (fib_complete(fibptr) != 0) {
- fib_free(fibptr);
- return -EINVAL;
+ retval = -EINVAL;
+ goto cleanup;
}
}
/*
@@ -114,12 +125,17 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* was already included by the adapter.)
*/
- if (copy_to_user(arg, (void *)kfib, kfib->header.Size)) {
- fib_free(fibptr);
- return -EFAULT;
+ retval = 0;
+ if (copy_to_user(arg, (void *)kfib, size))
+ retval = -EFAULT;
+cleanup:
+ if (hw_fib) {
+ pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa);
+ fibptr->hw_fib_pa = hw_fib_pa;
+ fibptr->hw_fib = hw_fib;
}
fib_free(fibptr);
- return 0;
+ return retval;
}
/**
@@ -391,26 +407,28 @@ static int check_revision(struct aac_dev *dev, void __user *arg)
struct revision response;
response.compat = 1;
- response.version = dev->adapter_info.kernelrev;
- response.build = dev->adapter_info.kernelbuild;
+ response.version = le32_to_cpu(dev->adapter_info.kernelrev);
+ response.build = le32_to_cpu(dev->adapter_info.kernelbuild);
if (copy_to_user(arg, &response, sizeof(response)))
return -EFAULT;
return 0;
}
+
/**
*
* aac_send_raw_scb
*
*/
-int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
+static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
{
struct fib* srbfib;
int status;
- struct aac_srb *srbcmd;
- struct aac_srb __user *user_srb = arg;
+ struct aac_srb *srbcmd = NULL;
+ struct user_aac_srb *user_srbcmd = NULL;
+ struct user_aac_srb __user *user_srb = arg;
struct aac_srb_reply __user *user_reply;
struct aac_srb_reply* reply;
u32 fibsize = 0;
@@ -426,50 +444,59 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if (!capable(CAP_SYS_ADMIN)){
- printk(KERN_DEBUG"aacraid: No permission to send raw srb\n");
+ dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n"));
return -EPERM;
}
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
if (!(srbfib = fib_alloc(dev))) {
- return -1;
+ return -ENOMEM;
}
fib_init(srbfib);
srbcmd = (struct aac_srb*) fib_data(srbfib);
+ memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
- printk(KERN_DEBUG"aacraid: Could not copy data size from user\n");
+ dprintk((KERN_DEBUG"aacraid: Could not copy data size from user\n"));
rcode = -EFAULT;
goto cleanup;
}
- if (fibsize > FIB_DATA_SIZE_IN_BYTES) {
+ if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) {
rcode = -EINVAL;
goto cleanup;
}
- if(copy_from_user(srbcmd, user_srb,fibsize)){
- printk(KERN_DEBUG"aacraid: Could not copy srb from user\n");
+ user_srbcmd = kmalloc(GFP_KERNEL, fibsize);
+ if (!user_srbcmd) {
+ dprintk((KERN_DEBUG"aacraid: Could not make a copy of the srb\n"));
+ rcode = -ENOMEM;
+ goto cleanup;
+ }
+ if(copy_from_user(user_srbcmd, user_srb,fibsize)){
+ dprintk((KERN_DEBUG"aacraid: Could not copy srb from user\n"));
rcode = -EFAULT;
goto cleanup;
}
user_reply = arg+fibsize;
- flags = srbcmd->flags;
+ flags = user_srbcmd->flags; /* from user in cpu order */
// Fix up srb for endian and force some values
+
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this
- srbcmd->channel = cpu_to_le32(srbcmd->channel);
- srbcmd->id = cpu_to_le32(srbcmd->id);
- srbcmd->lun = cpu_to_le32(srbcmd->lun);
- srbcmd->flags = cpu_to_le32(srbcmd->flags);
- srbcmd->timeout = cpu_to_le32(srbcmd->timeout);
- srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
- srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size);
+ srbcmd->channel = cpu_to_le32(user_srbcmd->channel);
+ srbcmd->id = cpu_to_le32(user_srbcmd->id);
+ srbcmd->lun = cpu_to_le32(user_srbcmd->lun);
+ srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout);
+ srbcmd->flags = cpu_to_le32(flags);
+ srbcmd->retry_limit = 0; // Obsolete parameter
+ srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
+ memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
- switch (srbcmd->flags & (SRB_DataIn | SRB_DataOut)) {
+ switch (flags & (SRB_DataIn | SRB_DataOut)) {
case SRB_DataOut:
data_dir = DMA_TO_DEVICE;
break;
@@ -482,118 +509,148 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
default:
data_dir = DMA_NONE;
}
+ if (user_srbcmd->sg.count > (sizeof(sg_list)/sizeof(sg_list[0]))) {
+ dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
+ le32_to_cpu(srbcmd->sg.count)));
+ rcode = -EINVAL;
+ goto cleanup;
+ }
if (dev->dac_support == 1) {
- struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
+ struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
+ struct sgmap64* psg = (struct sgmap64*)&user_srbcmd->sg;
+ struct user_sgmap* usg;
byte_count = 0;
/*
* This should also catch if user used the 32 bit sgmap
*/
actual_fibsize = sizeof(struct aac_srb) -
- sizeof(struct sgentry) + ((srbcmd->sg.count & 0xff) *
- sizeof(struct sgentry64));
+ sizeof(struct sgentry) +
+ ((upsg->count & 0xff) *
+ sizeof(struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
- printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
+ dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
}
- if ((data_dir == DMA_NONE) && psg->count) {
- printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
+ usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
+ + sizeof(struct sgmap), GFP_KERNEL);
+ if (!usg) {
+ dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
+ rcode = -ENOMEM;
+ goto cleanup;
+ }
+ memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
+ + sizeof(struct sgmap));
+ actual_fibsize = sizeof(struct aac_srb) -
+ sizeof(struct sgentry) + ((usg->count & 0xff) *
+ sizeof(struct sgentry64));
+ if ((data_dir == DMA_NONE) && upsg->count) {
+ kfree (usg);
+ dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
}
- for (i = 0; i < psg->count; i++) {
- dma_addr_t addr;
- u64 le_addr;
+ for (i = 0; i < usg->count; i++) {
+ u64 addr;
void* p;
- p = kmalloc(psg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+ /* Does this really need to be GFP_DMA? */
+ p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
if(p == 0) {
- printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
- psg->sg[i].count,i,psg->count);
+ kfree (usg);
+ dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+ usg->sg[i].count,i,usg->count));
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)psg->sg[i].addr;
+ sg_user[i] = (void __user *)usg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
if( flags & SRB_DataOut ){
- if(copy_from_user(p,sg_user[i],psg->sg[i].count)){
- printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n");
+ if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+ kfree (usg);
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT;
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p, psg->sg[i].count, data_dir);
+ addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
- le_addr = cpu_to_le64(addr);
- psg->sg[i].addr[1] = (u32)(le_addr>>32);
- psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
- psg->sg[i].count = cpu_to_le32(psg->sg[i].count);
- byte_count += psg->sg[i].count;
+ psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+ psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
+ byte_count += usg->sg[i].count;
}
+ kfree (usg);
srbcmd->count = cpu_to_le32(byte_count);
+ psg->count = cpu_to_le32(sg_indx+1);
status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
} else {
+ struct user_sgmap* upsg = &user_srbcmd->sg;
struct sgmap* psg = &srbcmd->sg;
byte_count = 0;
- actual_fibsize = sizeof (struct aac_srb) +
- (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
- sizeof (struct sgentry));
+ actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
- printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
+ dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
}
- if ((data_dir == DMA_NONE) && psg->count) {
- printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
+ if ((data_dir == DMA_NONE) && upsg->count) {
+ dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
}
- for (i = 0; i < psg->count; i++) {
+ for (i = 0; i < upsg->count; i++) {
dma_addr_t addr;
void* p;
- p = kmalloc(psg->sg[i].count,GFP_KERNEL);
+ p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
if(p == 0) {
- printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
- psg->sg[i].count,i,psg->count);
+ dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+ upsg->sg[i].count, i, upsg->count));
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)(psg->sg[i].addr);
+ sg_user[i] = (void __user *)upsg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
if( flags & SRB_DataOut ){
- if(copy_from_user(p,sg_user[i],psg->sg[i].count)){
- printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n");
+ if(copy_from_user(p, sg_user[i],
+ upsg->sg[i].count)) {
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT;
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p, psg->sg[i].count, data_dir);
+ addr = pci_map_single(dev->pdev, p,
+ upsg->sg[i].count, data_dir);
psg->sg[i].addr = cpu_to_le32(addr);
- psg->sg[i].count = cpu_to_le32(psg->sg[i].count);
- byte_count += psg->sg[i].count;
+ psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
+ byte_count += upsg->sg[i].count;
}
srbcmd->count = cpu_to_le32(byte_count);
+ psg->count = cpu_to_le32(sg_indx+1);
status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
}
if (status != 0){
- printk(KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n");
- rcode = -1;
+ dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"));
+ rcode = -ENXIO;
goto cleanup;
}
if( flags & SRB_DataIn ) {
for(i = 0 ; i <= sg_indx; i++){
- if(copy_to_user(sg_user[i],sg_list[i],le32_to_cpu(srbcmd->sg.sg[i].count))){
- printk(KERN_DEBUG"aacraid: Could not copy sg data to user\n");
+ byte_count = le32_to_cpu((dev->dac_support == 1)
+ ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
+ : srbcmd->sg.sg[i].count);
+ if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n"));
rcode = -EFAULT;
goto cleanup;
@@ -603,12 +660,13 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
reply = (struct aac_srb_reply *) fib_data(srbfib);
if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){
- printk(KERN_DEBUG"aacraid: Could not copy reply to user\n");
+ dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n"));
rcode = -EFAULT;
goto cleanup;
}
cleanup:
+ kfree(user_srbcmd);
for(i=0; i <= sg_indx; i++){
kfree(sg_list[i]);
}
@@ -618,14 +676,13 @@ cleanup:
return rcode;
}
-
struct aac_pci_info {
u32 bus;
u32 slot;
};
-int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
+static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
{
struct aac_pci_info pci_info;
@@ -633,11 +690,11 @@ int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
pci_info.slot = PCI_SLOT(dev->pdev->devfn);
if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
- printk(KERN_DEBUG "aacraid: Could not copy pci info\n");
+ dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
return -EFAULT;
}
return 0;
- }
+}
int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
@@ -656,6 +713,7 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
case FSACTL_MINIPORT_REV_CHECK:
status = check_revision(dev, arg);
break;
+ case FSACTL_SEND_LARGE_FIB:
case FSACTL_SENDFIB:
status = ioctl_send_fib(dev, arg);
break;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 6832a55ca90..43557bf661f 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -39,6 +39,7 @@
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/mm.h>
+#include <scsi/scsi_host.h>
#include <asm/semaphore.h>
#include "aacraid.h"
@@ -49,8 +50,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
{
unsigned char *base;
unsigned long size, align;
- unsigned long fibsize = 4096;
- unsigned long printfbufsiz = 256;
+ const unsigned long fibsize = 4096;
+ const unsigned long printfbufsiz = 256;
struct aac_init *init;
dma_addr_t phys;
@@ -74,6 +75,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
init = dev->init;
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
+ if (dev->max_fib_size != sizeof(struct hw_fib))
+ init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION);
init->fsrev = cpu_to_le32(dev->fsrev);
@@ -110,6 +113,10 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
}
+ init->InitFlags = 0;
+ init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
+ init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
+ init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
/*
* Increment the base address by the amount already used
@@ -152,8 +159,8 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem,
init_waitqueue_head(&q->qfull);
spin_lock_init(&q->lockdata);
q->lock = &q->lockdata;
- q->headers.producer = mem;
- q->headers.consumer = mem+1;
+ q->headers.producer = (__le32 *)mem;
+ q->headers.consumer = (__le32 *)(mem+1);
*(q->headers.producer) = cpu_to_le32(qsize);
*(q->headers.consumer) = cpu_to_le32(qsize);
q->entries = qsize;
@@ -173,6 +180,8 @@ int aac_send_shutdown(struct aac_dev * dev)
int status;
fibctx = fib_alloc(dev);
+ if (!fibctx)
+ return -ENOMEM;
fib_init(fibctx);
cmd = (struct aac_close *) fib_data(fibctx);
@@ -204,7 +213,7 @@ int aac_send_shutdown(struct aac_dev * dev)
* 0 - If there were errors initing. This is a fatal error.
*/
-int aac_comm_init(struct aac_dev * dev)
+static int aac_comm_init(struct aac_dev * dev)
{
unsigned long hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2;
unsigned long queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES;
@@ -293,6 +302,79 @@ int aac_comm_init(struct aac_dev * dev)
struct aac_dev *aac_init_adapter(struct aac_dev *dev)
{
+ u32 status[5];
+ struct Scsi_Host * host = dev->scsi_host_ptr;
+
+ /*
+ * Check the preferred comm settings, defaults from template.
+ */
+ dev->max_fib_size = sizeof(struct hw_fib);
+ dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
+ - sizeof(struct aac_fibhdr)
+ - sizeof(struct aac_write) + sizeof(struct sgmap))
+ / sizeof(struct sgmap);
+ if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
+ 0, 0, 0, 0, 0, 0,
+ status+0, status+1, status+2, status+3, status+4))
+ && (status[0] == 0x00000001)) {
+ /*
+ * status[1] >> 16 maximum command size in KB
+ * status[1] & 0xFFFF maximum FIB size
+ * status[2] >> 16 maximum SG elements to driver
+ * status[2] & 0xFFFF maximum SG elements from driver
+ * status[3] & 0xFFFF maximum number FIBs outstanding
+ */
+ host->max_sectors = (status[1] >> 16) << 1;
+ dev->max_fib_size = status[1] & 0xFFFF;
+ host->sg_tablesize = status[2] >> 16;
+ dev->sg_tablesize = status[2] & 0xFFFF;
+ host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
+ /*
+ * NOTE:
+ * All these overrides are based on a fixed internal
+ * knowledge and understanding of existing adapters,
+ * acbsize should be set with caution.
+ */
+ if (acbsize == 512) {
+ host->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+ dev->max_fib_size = 512;
+ dev->sg_tablesize = host->sg_tablesize
+ = (512 - sizeof(struct aac_fibhdr)
+ - sizeof(struct aac_write) + sizeof(struct sgmap))
+ / sizeof(struct sgmap);
+ host->can_queue = AAC_NUM_IO_FIB;
+ } else if (acbsize == 2048) {
+ host->max_sectors = 512;
+ dev->max_fib_size = 2048;
+ host->sg_tablesize = 65;
+ dev->sg_tablesize = 81;
+ host->can_queue = 512 - AAC_NUM_MGT_FIB;
+ } else if (acbsize == 4096) {
+ host->max_sectors = 1024;
+ dev->max_fib_size = 4096;
+ host->sg_tablesize = 129;
+ dev->sg_tablesize = 166;
+ host->can_queue = 256 - AAC_NUM_MGT_FIB;
+ } else if (acbsize == 8192) {
+ host->max_sectors = 2048;
+ dev->max_fib_size = 8192;
+ host->sg_tablesize = 257;
+ dev->sg_tablesize = 337;
+ host->can_queue = 128 - AAC_NUM_MGT_FIB;
+ } else if (acbsize > 0) {
+ printk("Illegal acbsize=%d ignored\n", acbsize);
+ }
+ }
+ {
+
+ if (numacb > 0) {
+ if (numacb < host->can_queue)
+ host->can_queue = numacb;
+ else
+ printk("numacb=%d ignored\n", numacb);
+ }
+ }
+
/*
* Ok now init the communication subsystem
*/
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 3f36dbaa2bb..5322865942e 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -25,7 +25,7 @@
* commsup.c
*
* Abstract: Contain all routines that are required for FSA host/adapter
- * commuication.
+ * communication.
*
*/
@@ -38,6 +38,7 @@
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
#include <asm/semaphore.h>
#include "aacraid.h"
@@ -52,7 +53,13 @@
static int fib_map_alloc(struct aac_dev *dev)
{
- if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, &dev->hw_fib_pa))==NULL)
+ dprintk((KERN_INFO
+ "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
+ dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue,
+ AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
+ if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, dev->max_fib_size
+ * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
+ &dev->hw_fib_pa))==NULL)
return -ENOMEM;
return 0;
}
@@ -67,7 +74,7 @@ static int fib_map_alloc(struct aac_dev *dev)
void fib_map_free(struct aac_dev *dev)
{
- pci_free_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, dev->hw_fib_va, dev->hw_fib_pa);
+ pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa);
}
/**
@@ -84,17 +91,22 @@ int fib_setup(struct aac_dev * dev)
struct hw_fib *hw_fib_va;
dma_addr_t hw_fib_pa;
int i;
-
- if(fib_map_alloc(dev)<0)
+
+ while (((i = fib_map_alloc(dev)) == -ENOMEM)
+ && (dev->scsi_host_ptr->can_queue > (64 - AAC_NUM_MGT_FIB))) {
+ dev->init->MaxIoCommands = cpu_to_le32((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) >> 1);
+ dev->scsi_host_ptr->can_queue = le32_to_cpu(dev->init->MaxIoCommands) - AAC_NUM_MGT_FIB;
+ }
+ if (i<0)
return -ENOMEM;
hw_fib_va = dev->hw_fib_va;
hw_fib_pa = dev->hw_fib_pa;
- memset(hw_fib_va, 0, sizeof(struct hw_fib) * AAC_NUM_FIB);
+ memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
/*
* Initialise the fibs
*/
- for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++)
+ for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++)
{
fibptr->dev = dev;
fibptr->hw_fib = hw_fib_va;
@@ -102,16 +114,16 @@ int fib_setup(struct aac_dev * dev)
fibptr->next = fibptr+1; /* Forward chain the fibs */
init_MUTEX_LOCKED(&fibptr->event_wait);
spin_lock_init(&fibptr->event_lock);
- hw_fib_va->header.XferState = 0xffffffff;
- hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
+ hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
+ hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size);
fibptr->hw_fib_pa = hw_fib_pa;
- hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib));
- hw_fib_pa = hw_fib_pa + sizeof(struct hw_fib);
+ hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size);
+ hw_fib_pa = hw_fib_pa + dev->max_fib_size;
}
/*
* Add the fib chain to the free list
*/
- dev->fibs[AAC_NUM_FIB-1].next = NULL;
+ dev->fibs[dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1].next = NULL;
/*
* Enable this to debug out of queue space
*/
@@ -124,7 +136,7 @@ int fib_setup(struct aac_dev * dev)
* @dev: Adapter to allocate the fib for
*
* Allocate a fib from the adapter fib pool. If the pool is empty we
- * wait for fibs to become free.
+ * return NULL.
*/
struct fib * fib_alloc(struct aac_dev *dev)
@@ -133,10 +145,10 @@ struct fib * fib_alloc(struct aac_dev *dev)
unsigned long flags;
spin_lock_irqsave(&dev->fib_lock, flags);
fibptr = dev->free_fib;
- /* Cannot sleep here or you get hangs. Instead we did the
- maths at compile time. */
- if(!fibptr)
- BUG();
+ if(!fibptr){
+ spin_unlock_irqrestore(&dev->fib_lock, flags);
+ return fibptr;
+ }
dev->free_fib = fibptr->next;
spin_unlock_irqrestore(&dev->fib_lock, flags);
/*
@@ -196,11 +208,11 @@ void fib_init(struct fib *fibptr)
struct hw_fib *hw_fib = fibptr->hw_fib;
hw_fib->header.StructType = FIB_MAGIC;
- hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib));
- hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
+ hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
+ hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
- hw_fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
+ hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size);
}
/**
@@ -211,7 +223,7 @@ void fib_init(struct fib *fibptr)
* caller.
*/
-void fib_dealloc(struct fib * fibptr)
+static void fib_dealloc(struct fib * fibptr)
{
struct hw_fib *hw_fib = fibptr->hw_fib;
if(hw_fib->header.StructType != FIB_MAGIC)
@@ -279,7 +291,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
}
if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */
- printk(KERN_WARNING "Queue %d full, %d outstanding.\n",
+ printk(KERN_WARNING "Queue %d full, %u outstanding.\n",
qid, q->numpending);
return 0;
} else {
@@ -658,9 +670,8 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
}
if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) {
}
- }
- else if (hw_fib->header.XferState & NormalPriority)
- {
+ } else if (hw_fib->header.XferState &
+ cpu_to_le32(NormalPriority)) {
u32 index;
if (size) {
@@ -744,22 +755,25 @@ int fib_complete(struct fib * fibptr)
void aac_printf(struct aac_dev *dev, u32 val)
{
- int length = val & 0xffff;
- int level = (val >> 16) & 0xffff;
char *cp = dev->printfbuf;
-
- /*
- * The size of the printfbuf is set in port.c
- * There is no variable or define for it
- */
- if (length > 255)
- length = 255;
- if (cp[length] != 0)
- cp[length] = 0;
- if (level == LOG_AAC_HIGH_ERROR)
- printk(KERN_WARNING "aacraid:%s", cp);
- else
- printk(KERN_INFO "aacraid:%s", cp);
+ if (dev->printf_enabled)
+ {
+ int length = val & 0xffff;
+ int level = (val >> 16) & 0xffff;
+
+ /*
+ * The size of the printfbuf is set in port.c
+ * There is no variable or define for it
+ */
+ if (length > 255)
+ length = 255;
+ if (cp[length] != 0)
+ cp[length] = 0;
+ if (level == LOG_AAC_HIGH_ERROR)
+ printk(KERN_WARNING "aacraid:%s", cp);
+ else
+ printk(KERN_INFO "aacraid:%s", cp);
+ }
memset(cp, 0, 256);
}
@@ -832,8 +846,8 @@ int aac_command_thread(struct aac_dev * dev)
aifcmd = (struct aac_aifcmd *) hw_fib->data;
if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
/* Handle Driver Notify Events */
- *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fib, sizeof(u32));
+ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
+ fib_adapter_complete(fib, (u16)sizeof(u32));
} else {
struct list_head *entry;
/* The u32 here is important and intended. We are using
@@ -916,7 +930,7 @@ int aac_command_thread(struct aac_dev * dev)
/*
* Set the status of this FIB
*/
- *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
+ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, sizeof(u32));
spin_unlock_irqrestore(&dev->fib_lock, flagv);
}
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index 8480b427a6d..be2e98de9fa 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -99,7 +99,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
/*
* Doctor the fib
*/
- *(u32 *)hwfib->data = cpu_to_le32(ST_OK);
+ *(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
}
@@ -107,7 +107,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
if (hwfib->header.Command == cpu_to_le16(NuFileSystem))
{
- u32 *pstatus = (u32 *)hwfib->data;
+ __le32 *pstatus = (__le32 *)hwfib->data;
if (*pstatus & cpu_to_le32(0xffff0000))
*pstatus = cpu_to_le32(ST_OK);
}
@@ -205,7 +205,7 @@ unsigned int aac_command_normal(struct aac_queue *q)
/*
* Set the status of this FIB
*/
- *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
+ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, sizeof(u32));
spin_lock_irqsave(q->lock, flags);
}
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 242fa77513f..f7e9c89c491 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -215,7 +215,7 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
* Returns a static string describing the device in question
*/
-const char *aac_info(struct Scsi_Host *shost)
+static const char *aac_info(struct Scsi_Host *shost)
{
struct aac_dev *dev = (struct aac_dev *)shost->hostdata;
return aac_drivers[dev->cardtype].name;
@@ -288,7 +288,7 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
* translations ( 64/32, 128/32, 255/63 ).
*/
buf = scsi_bios_ptable(bdev);
- if(*(unsigned short *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
+ if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
struct partition *first = (struct partition * )buf;
struct partition *entry = first;
int saved_cylinders = param->cylinders;
@@ -347,10 +347,16 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
static int aac_slave_configure(struct scsi_device *sdev)
{
+ struct Scsi_Host *host = sdev->host;
+
if (sdev->tagged_supported)
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128);
else
scsi_adjust_queue_depth(sdev, 0, 1);
+
+ if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT)
+ blk_queue_max_segment_size(sdev->request_queue, 65536);
+
return 0;
}
@@ -361,14 +367,6 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
}
/*
- * XXX: does aac really need no error handling??
- */
-static int aac_eh_abort(struct scsi_cmnd *cmd)
-{
- return FAILED;
-}
-
-/*
* aac_eh_reset - Reset command handling
* @scsi_cmd: SCSI command block causing the reset
*
@@ -386,10 +384,13 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
AAC_DRIVERNAME);
+ spin_lock_irq(host->host_lock);
+
aac = (struct aac_dev *)host->hostdata;
if (aac_adapter_check_health(aac)) {
printk(KERN_ERR "%s: Host adapter appears dead\n",
AAC_DRIVERNAME);
+ spin_unlock_irq(host->host_lock);
return -ENODEV;
}
/*
@@ -420,6 +421,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
ssleep(1);
spin_lock_irq(host->host_lock);
}
+ spin_unlock_irq(host->host_lock);
printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
return -ETIMEDOUT;
}
@@ -439,11 +441,11 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
static int aac_cfg_open(struct inode *inode, struct file *file)
{
struct aac_dev *aac;
- unsigned minor = iminor(inode);
+ unsigned minor_number = iminor(inode);
int err = -ENODEV;
list_for_each_entry(aac, &aac_devices, entry) {
- if (aac->id == minor) {
+ if (aac->id == minor_number) {
file->private_data = aac;
err = 0;
break;
@@ -489,6 +491,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
case FSACTL_DELETE_DISK:
case FSACTL_FORCE_DELETE_DISK:
case FSACTL_GET_CONTAINERS:
+ case FSACTL_SEND_LARGE_FIB:
ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
break;
@@ -526,6 +529,134 @@ static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long
}
#endif
+static ssize_t aac_show_model(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len;
+
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
+ aac_drivers[dev->cardtype].model);
+ return len;
+}
+
+static ssize_t aac_show_vendor(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len;
+
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
+ aac_drivers[dev->cardtype].vname);
+ return len;
+}
+
+static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+ len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n",
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ le32_to_cpu(dev->adapter_info.kernelbuild));
+ return len;
+}
+
+static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+ len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n",
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ le32_to_cpu(dev->adapter_info.monitorbuild));
+ return len;
+}
+
+static ssize_t aac_show_bios_version(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.biosrev);
+ len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n",
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ le32_to_cpu(dev->adapter_info.biosbuild));
+ return len;
+}
+
+static ssize_t aac_show_serial_number(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len = 0;
+
+ if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+ len = snprintf(buf, PAGE_SIZE, "%x\n",
+ le32_to_cpu(dev->adapter_info.serial[0]));
+ return len;
+}
+
+
+static struct class_device_attribute aac_model = {
+ .attr = {
+ .name = "model",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_model,
+};
+static struct class_device_attribute aac_vendor = {
+ .attr = {
+ .name = "vendor",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_vendor,
+};
+static struct class_device_attribute aac_kernel_version = {
+ .attr = {
+ .name = "hba_kernel_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_kernel_version,
+};
+static struct class_device_attribute aac_monitor_version = {
+ .attr = {
+ .name = "hba_monitor_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_monitor_version,
+};
+static struct class_device_attribute aac_bios_version = {
+ .attr = {
+ .name = "hba_bios_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_bios_version,
+};
+static struct class_device_attribute aac_serial_number = {
+ .attr = {
+ .name = "serial_number",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_serial_number,
+};
+
+static struct class_device_attribute *aac_attrs[] = {
+ &aac_model,
+ &aac_vendor,
+ &aac_kernel_version,
+ &aac_monitor_version,
+ &aac_bios_version,
+ &aac_serial_number,
+ NULL
+};
+
+
static struct file_operations aac_cfg_fops = {
.owner = THIS_MODULE,
.ioctl = aac_cfg_ioctl,
@@ -538,7 +669,7 @@ static struct file_operations aac_cfg_fops = {
static struct scsi_host_template aac_driver_template = {
.module = THIS_MODULE,
.name = "AAC",
- .proc_name = "aacraid",
+ .proc_name = AAC_DRIVERNAME,
.info = aac_info,
.ioctl = aac_ioctl,
#ifdef CONFIG_COMPAT
@@ -546,8 +677,8 @@ static struct scsi_host_template aac_driver_template = {
#endif
.queuecommand = aac_queuecommand,
.bios_param = aac_biosparm,
+ .shost_attrs = aac_attrs,
.slave_configure = aac_slave_configure,
- .eh_abort_handler = aac_eh_abort,
.eh_host_reset_handler = aac_eh_reset,
.can_queue = AAC_NUM_IO_FIB,
.this_id = 16,
@@ -612,7 +743,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac->cardtype = index;
INIT_LIST_HEAD(&aac->entry);
- aac->fibs = kmalloc(sizeof(struct fib) * AAC_NUM_FIB, GFP_KERNEL);
+ aac->fibs = kmalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL);
if (!aac->fibs)
goto out_free_host;
spin_lock_init(&aac->fib_lock);
@@ -632,6 +763,24 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac_get_adapter_info(aac);
/*
+ * Lets override negotiations and drop the maximum SG limit to 34
+ */
+ if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) &&
+ (aac->scsi_host_ptr->sg_tablesize > 34)) {
+ aac->scsi_host_ptr->sg_tablesize = 34;
+ aac->scsi_host_ptr->max_sectors
+ = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+ }
+
+ /*
+ * Firware printf works only with older firmware.
+ */
+ if (aac_drivers[index].quirks & AAC_QUIRK_34SG)
+ aac->printf_enabled = 1;
+ else
+ aac->printf_enabled = 0;
+
+ /*
* max channel will be the physical channels plus 1 virtual channel
* all containers are on the virtual channel 0
* physical channels are address by their actual physical number+1
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 1b8ed47cfe3..7d68b782513 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -98,7 +98,9 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
* for its completion.
*/
-static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
+static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
+ u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+ u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
{
unsigned long start;
int ok;
@@ -107,12 +109,12 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/
rkt_writel(dev, InboundMailbox0, command);
/*
- * Write the parameters into Mailboxes 1 - 4
+ * Write the parameters into Mailboxes 1 - 6
*/
rkt_writel(dev, InboundMailbox1, p1);
- rkt_writel(dev, InboundMailbox2, 0);
- rkt_writel(dev, InboundMailbox3, 0);
- rkt_writel(dev, InboundMailbox4, 0);
+ rkt_writel(dev, InboundMailbox2, p2);
+ rkt_writel(dev, InboundMailbox3, p3);
+ rkt_writel(dev, InboundMailbox4, p4);
/*
* Clear the synch command doorbell to start on a clean slate.
*/
@@ -169,6 +171,14 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/
if (status)
*status = rkt_readl(dev, IndexRegs.Mailbox[0]);
+ if (r1)
+ *r1 = rkt_readl(dev, IndexRegs.Mailbox[1]);
+ if (r2)
+ *r2 = rkt_readl(dev, IndexRegs.Mailbox[2]);
+ if (r3)
+ *r3 = rkt_readl(dev, IndexRegs.Mailbox[3]);
+ if (r4)
+ *r4 = rkt_readl(dev, IndexRegs.Mailbox[4]);
/*
* Clear the synch command doorbell.
*/
@@ -190,8 +200,8 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
static void aac_rkt_interrupt_adapter(struct aac_dev *dev)
{
- u32 ret;
- rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+ rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -220,7 +230,8 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
break;
case HostShutdown:
-// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
+// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+// NULL, NULL, NULL, NULL, NULL);
break;
case FastIo:
rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
@@ -243,17 +254,11 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
static void aac_rkt_start_adapter(struct aac_dev *dev)
{
- u32 status;
struct aac_init *init;
init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
/*
- * Tell the adapter we are back and up and running so it will scan
- * its command queues and enable our interrupts
- */
- dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4);
- /*
* First clear out all interrupts. Then enable the one's that we
* can handle.
*/
@@ -263,7 +268,8 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
// We can only use a 32 bit address here
- rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status);
+ rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
+ 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -288,8 +294,8 @@ static int aac_rkt_check_health(struct aac_dev *dev)
if (status & KERNEL_PANIC) {
char * buffer;
struct POSTSTATUS {
- u32 Post_Command;
- u32 Post_Address;
+ __le32 Post_Command;
+ __le32 Post_Address;
} * post;
dma_addr_t paddr, baddr;
int ret;
@@ -310,7 +316,8 @@ static int aac_rkt_check_health(struct aac_dev *dev)
post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr);
rkt_writel(dev, MUnit.IMRx[0], paddr);
- rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
+ rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
if ((buffer[0] == '0') && (buffer[1] == 'x')) {
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 630b99e1fe8..1ff25f49fad 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -63,7 +63,7 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
{
bellbits = rx_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
- aac_printf(dev, le32_to_cpu(rx_readl (dev, IndexRegs.Mailbox[5])));
+ aac_printf(dev, rx_readl(dev, IndexRegs.Mailbox[5]));
rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
}
@@ -98,7 +98,9 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
* for its completion.
*/
-static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
+static int rx_sync_cmd(struct aac_dev *dev, u32 command,
+ u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+ u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
{
unsigned long start;
int ok;
@@ -107,12 +109,12 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/
rx_writel(dev, InboundMailbox0, command);
/*
- * Write the parameters into Mailboxes 1 - 4
+ * Write the parameters into Mailboxes 1 - 6
*/
rx_writel(dev, InboundMailbox1, p1);
- rx_writel(dev, InboundMailbox2, 0);
- rx_writel(dev, InboundMailbox3, 0);
- rx_writel(dev, InboundMailbox4, 0);
+ rx_writel(dev, InboundMailbox2, p2);
+ rx_writel(dev, InboundMailbox3, p3);
+ rx_writel(dev, InboundMailbox4, p4);
/*
* Clear the synch command doorbell to start on a clean slate.
*/
@@ -120,7 +122,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/*
* Disable doorbell interrupts
*/
- rx_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04);
+ rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
/*
* Force the completion of the mask register write before issuing
* the interrupt.
@@ -169,6 +171,14 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/
if (status)
*status = rx_readl(dev, IndexRegs.Mailbox[0]);
+ if (r1)
+ *r1 = rx_readl(dev, IndexRegs.Mailbox[1]);
+ if (r2)
+ *r2 = rx_readl(dev, IndexRegs.Mailbox[2]);
+ if (r3)
+ *r3 = rx_readl(dev, IndexRegs.Mailbox[3]);
+ if (r4)
+ *r4 = rx_readl(dev, IndexRegs.Mailbox[4]);
/*
* Clear the synch command doorbell.
*/
@@ -190,8 +200,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
static void aac_rx_interrupt_adapter(struct aac_dev *dev)
{
- u32 ret;
- rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+ rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -220,7 +229,8 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
break;
case HostShutdown:
-// rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
+// rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+// NULL, NULL, NULL, NULL, NULL);
break;
case FastIo:
rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
@@ -243,17 +253,11 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
static void aac_rx_start_adapter(struct aac_dev *dev)
{
- u32 status;
struct aac_init *init;
init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
/*
- * Tell the adapter we are back and up and running so it will scan
- * its command queues and enable our interrupts
- */
- dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4);
- /*
* First clear out all interrupts. Then enable the one's that we
* can handle.
*/
@@ -263,7 +267,8 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
// We can only use a 32 bit address here
- rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status);
+ rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
+ 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -288,8 +293,8 @@ static int aac_rx_check_health(struct aac_dev *dev)
if (status & KERNEL_PANIC) {
char * buffer;
struct POSTSTATUS {
- u32 Post_Command;
- u32 Post_Address;
+ __le32 Post_Command;
+ __le32 Post_Address;
} * post;
dma_addr_t paddr, baddr;
int ret;
@@ -310,7 +315,8 @@ static int aac_rx_check_health(struct aac_dev *dev)
post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr);
rx_writel(dev, MUnit.IMRx[0], paddr);
- rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
+ rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
if ((buffer[0] == '0') && (buffer[1] == 'x')) {
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index bd6c30723fb..0680249ab86 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -89,7 +89,7 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
* Notify the adapter of an event
*/
-void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
+static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
{
switch (event) {
@@ -106,7 +106,10 @@ void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
sa_writew(dev, DoorbellReg_s,DOORBELL_3);
break;
case HostShutdown:
- //sa_sync_cmd(dev, HOST_CRASHING, 0, &ret);
+ /*
+ sa_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
+ */
break;
case FastIo:
sa_writew(dev, DoorbellReg_s,DOORBELL_6);
@@ -132,7 +135,9 @@ void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
* for its completion.
*/
-static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
+static int sa_sync_cmd(struct aac_dev *dev, u32 command,
+ u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+ u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
{
unsigned long start;
int ok;
@@ -144,9 +149,10 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
* Write the parameters into Mailboxes 1 - 4
*/
sa_writel(dev, Mailbox1, p1);
- sa_writel(dev, Mailbox2, 0);
- sa_writel(dev, Mailbox3, 0);
- sa_writel(dev, Mailbox4, 0);
+ sa_writel(dev, Mailbox2, p2);
+ sa_writel(dev, Mailbox3, p3);
+ sa_writel(dev, Mailbox4, p4);
+
/*
* Clear the synch command doorbell to start on a clean slate.
*/
@@ -188,6 +194,14 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
*/
if (ret)
*ret = sa_readl(dev, Mailbox0);
+ if (r1)
+ *r1 = sa_readl(dev, Mailbox1);
+ if (r2)
+ *r2 = sa_readl(dev, Mailbox2);
+ if (r3)
+ *r3 = sa_readl(dev, Mailbox3);
+ if (r4)
+ *r4 = sa_readl(dev, Mailbox4);
return 0;
}
@@ -201,7 +215,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
static void aac_sa_interrupt_adapter (struct aac_dev *dev)
{
u32 ret;
- sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+ sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
+ &ret, NULL, NULL, NULL, NULL);
}
/**
@@ -230,10 +245,12 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
* First clear out all interrupts. Then enable the one's that
* we can handle.
*/
- sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff));
+ sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
/* We can only use a 32 bit address here */
- sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &ret);
+ sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
+ (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
+ &ret, NULL, NULL, NULL, NULL);
}
/**