Commit 7c00ffa3 authored by Mark Haverkamp 's avatar Mark Haverkamp Committed by James Bottomley

[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: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 672b2d38
...@@ -53,10 +53,6 @@ ...@@ -53,10 +53,6 @@
#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */ #define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */
#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer 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 * Sense codes
*/ */
...@@ -158,6 +154,13 @@ MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0 ...@@ -158,6 +154,13 @@ MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0
module_param(commit, int, 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"); 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 * aac_get_config_status - check the adapter configuration
* @common: adapter to query * @common: adapter to query
...@@ -462,7 +465,7 @@ static int probe_container(struct aac_dev *dev, int cid) ...@@ -462,7 +465,7 @@ static int probe_container(struct aac_dev *dev, int cid)
1, 1, 1, 1,
NULL, NULL); NULL, NULL);
if (status < 0) { if (status < 0) {
printk(KERN_WARNING "aacraid: probe_containers query failed.\n"); printk(KERN_WARNING "aacraid: probe_container query failed.\n");
goto error; goto error;
} }
...@@ -605,35 +608,63 @@ static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, ...@@ -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) int aac_get_adapter_info(struct aac_dev* dev)
{ {
struct fib* fibptr; struct fib* fibptr;
struct aac_adapter_info* info;
int rcode; int rcode;
u32 tmp; u32 tmp;
struct aac_adapter_info * info;
if (!(fibptr = fib_alloc(dev))) if (!(fibptr = fib_alloc(dev)))
return -ENOMEM; return -ENOMEM;
fib_init(fibptr); fib_init(fibptr);
info = (struct aac_adapter_info*) fib_data(fibptr); info = (struct aac_adapter_info *) fib_data(fibptr);
memset(info,0,sizeof(*info));
memset(info,0,sizeof(struct aac_adapter_info));
rcode = fib_send(RequestAdapterInfo, rcode = fib_send(RequestAdapterInfo,
fibptr, fibptr,
sizeof(struct aac_adapter_info), 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;
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, FsaNormal,
1, 1, 1, 1,
NULL, NULL,
NULL); NULL);
memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info)); if (rcode >= 0)
memcpy(&dev->supplement_adapter_info, info, sizeof(*info));
}
tmp = le32_to_cpu(dev->adapter_info.kernelrev); 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->name,
dev->id, dev->id,
tmp>>24, tmp>>24,
(tmp>>16)&0xff, (tmp>>16)&0xff,
tmp&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); tmp = le32_to_cpu(dev->adapter_info.monitorrev);
printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n", printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n",
dev->name, dev->id, dev->name, dev->id,
...@@ -707,6 +738,38 @@ int aac_get_adapter_info(struct aac_dev* dev) ...@@ -707,6 +738,38 @@ int aac_get_adapter_info(struct aac_dev* dev)
rcode = -ENOMEM; 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_complete(fibptr);
fib_free(fibptr); fib_free(fibptr);
...@@ -747,8 +810,10 @@ static void read_callback(void *context, struct fib * fibptr) ...@@ -747,8 +810,10 @@ static void read_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(readreply->status) == ST_OK) if (le32_to_cpu(readreply->status) == ST_OK)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
else { else {
printk(KERN_WARNING "read_callback: read failed, status = %d\n", #ifdef AAC_DETAILED_STATUS_INFO
printk(KERN_WARNING "read_callback: io failed, status = %d\n",
le32_to_cpu(readreply->status)); le32_to_cpu(readreply->status));
#endif
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data, set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR, HARDWARE_ERROR,
...@@ -842,7 +907,8 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) ...@@ -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]; lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; 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 * Alocate and initialize a Fib
*/ */
...@@ -852,7 +918,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) ...@@ -852,7 +918,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fib_init(cmd_fibcontext); fib_init(cmd_fibcontext);
if(dev->dac_support == 1) { if (dev->dac_support == 1) {
struct aac_read64 *readcmd; struct aac_read64 *readcmd;
readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
readcmd->command = cpu_to_le32(VM_CtHostRead64); readcmd->command = cpu_to_le32(VM_CtHostRead64);
...@@ -886,14 +952,11 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) ...@@ -886,14 +952,11 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
readcmd->block = cpu_to_le32(lba); readcmd->block = cpu_to_le32(lba);
readcmd->count = cpu_to_le32(count * 512); readcmd->count = cpu_to_le32(count * 512);
if (count * 512 > (64 * 1024))
BUG();
aac_build_sg(scsicmd, &readcmd->sg); aac_build_sg(scsicmd, &readcmd->sg);
fibsize = sizeof(struct aac_read) + fibsize = sizeof(struct aac_read) +
((le32_to_cpu(readcmd->sg.count) - 1) * ((le32_to_cpu(readcmd->sg.count) - 1) *
sizeof (struct sgentry)); sizeof (struct sgentry));
BUG_ON (fibsize > (sizeof(struct hw_fib) - BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr))); sizeof(struct aac_fibhdr)));
/* /*
* Now send the Fib to the adapter * Now send the Fib to the adapter
...@@ -976,7 +1039,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) ...@@ -976,7 +1039,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
fibsize = sizeof(struct aac_write64) + fibsize = sizeof(struct aac_write64) +
((le32_to_cpu(writecmd->sg.count) - 1) * ((le32_to_cpu(writecmd->sg.count) - 1) *
sizeof (struct sgentry64)); sizeof (struct sgentry64));
BUG_ON (fibsize > (sizeof(struct hw_fib) - BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr))); sizeof(struct aac_fibhdr)));
/* /*
* Now send the Fib to the adapter * Now send the Fib to the adapter
...@@ -998,15 +1061,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) ...@@ -998,15 +1061,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
writecmd->sg.count = cpu_to_le32(1); writecmd->sg.count = cpu_to_le32(1);
/* ->stable is not used - it did mean which type of write */ /* ->stable is not used - it did mean which type of write */
if (count * 512 > (64 * 1024)) {
BUG();
}
aac_build_sg(scsicmd, &writecmd->sg); aac_build_sg(scsicmd, &writecmd->sg);
fibsize = sizeof(struct aac_write) + fibsize = sizeof(struct aac_write) +
((le32_to_cpu(writecmd->sg.count) - 1) * ((le32_to_cpu(writecmd->sg.count) - 1) *
sizeof (struct sgentry)); sizeof (struct sgentry));
BUG_ON (fibsize > (sizeof(struct hw_fib) - BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr))); sizeof(struct aac_fibhdr)));
/* /*
* Now send the Fib to the adapter * Now send the Fib to the adapter
...@@ -1025,7 +1084,6 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) ...@@ -1025,7 +1084,6 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
*/ */
if (status == -EINPROGRESS) if (status == -EINPROGRESS)
{ {
dprintk("write queued.\n");
return 0; return 0;
} }
...@@ -1111,7 +1169,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) ...@@ -1111,7 +1169,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
return SCSI_MLQUEUE_DEVICE_BUSY; return SCSI_MLQUEUE_DEVICE_BUSY;
/* /*
* Alocate and initialize a Fib * Allocate and initialize a Fib
*/ */
if (!(cmd_fibcontext = if (!(cmd_fibcontext =
fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
...@@ -1403,7 +1461,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) ...@@ -1403,7 +1461,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
/* /*
* Unhandled commands * 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; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data, set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND, ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
...@@ -1818,7 +1876,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) ...@@ -1818,7 +1876,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) + fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
((le32_to_cpu(srbcmd->sg.count) & 0xff) * ((le32_to_cpu(srbcmd->sg.count) & 0xff) *
sizeof (struct sgentry64)); sizeof (struct sgentry64));
BUG_ON (fibsize > (sizeof(struct hw_fib) - BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr))); sizeof(struct aac_fibhdr)));
/* /*
...@@ -1840,7 +1898,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) ...@@ -1840,7 +1898,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
fibsize = sizeof (struct aac_srb) + fibsize = sizeof (struct aac_srb) +
(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
sizeof (struct sgentry)); sizeof (struct sgentry));
BUG_ON (fibsize > (sizeof(struct hw_fib) - BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr))); sizeof(struct aac_fibhdr)));
/* /*
......
...@@ -8,12 +8,18 @@ ...@@ -8,12 +8,18 @@
#define MAXIMUM_NUM_CONTAINERS 32 #define MAXIMUM_NUM_CONTAINERS 32
#define AAC_NUM_FIB (256 + 64) #define AAC_NUM_MGT_FIB 8
#define AAC_NUM_IO_FIB 100 #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_LUN (8)
#define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) #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 * These macros convert from physical channels to virtual channels
...@@ -303,12 +309,9 @@ struct aac_fibhdr { ...@@ -303,12 +309,9 @@ struct aac_fibhdr {
} _u; } _u;
}; };
#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr))
struct hw_fib { struct hw_fib {
struct aac_fibhdr header; struct aac_fibhdr header;
u8 data[FIB_DATA_SIZE_IN_BYTES]; // Command specific data u8 data[512-sizeof(struct aac_fibhdr)]; // Command specific data
}; };
/* /*
...@@ -370,11 +373,12 @@ struct hw_fib { ...@@ -370,11 +373,12 @@ struct hw_fib {
#define RequestAdapterInfo 703 #define RequestAdapterInfo 703
#define IsAdapterPaused 704 #define IsAdapterPaused 704
#define SendHostTime 705 #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 { enum fib_xfer_state {
HostOwned = (1<<0), HostOwned = (1<<0),
...@@ -407,6 +411,7 @@ enum fib_xfer_state { ...@@ -407,6 +411,7 @@ enum fib_xfer_state {
*/ */
#define ADAPTER_INIT_STRUCT_REVISION 3 #define ADAPTER_INIT_STRUCT_REVISION 3
#define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science
struct aac_init struct aac_init
{ {
...@@ -424,6 +429,14 @@ struct aac_init ...@@ -424,6 +429,14 @@ struct aac_init
__le32 HostPhysMemPages; /* number of 4k pages of host __le32 HostPhysMemPages; /* number of 4k pages of host
physical memory */ physical memory */
__le32 HostElapsedSeconds; /* number of seconds since 1970. */ __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 { enum aac_log_level {
...@@ -447,7 +460,7 @@ struct adapter_ops ...@@ -447,7 +460,7 @@ struct adapter_ops
{ {
void (*adapter_interrupt)(struct aac_dev *dev); void (*adapter_interrupt)(struct aac_dev *dev);
void (*adapter_notify)(struct aac_dev *dev, u32 event); 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); int (*adapter_check_health)(struct aac_dev *dev);
}; };
...@@ -567,6 +580,7 @@ struct sa_drawbridge_CSR { ...@@ -567,6 +580,7 @@ struct sa_drawbridge_CSR {
#define Mailbox3 SaDbCSR.MAILBOX3 #define Mailbox3 SaDbCSR.MAILBOX3
#define Mailbox4 SaDbCSR.MAILBOX4 #define Mailbox4 SaDbCSR.MAILBOX4
#define Mailbox5 SaDbCSR.MAILBOX5 #define Mailbox5 SaDbCSR.MAILBOX5
#define Mailbox6 SaDbCSR.MAILBOX6
#define Mailbox7 SaDbCSR.MAILBOX7 #define Mailbox7 SaDbCSR.MAILBOX7
#define DoorbellReg_p SaDbCSR.PRISETIRQ #define DoorbellReg_p SaDbCSR.PRISETIRQ
...@@ -812,6 +826,25 @@ struct aac_adapter_info ...@@ -812,6 +826,25 @@ struct aac_adapter_info
__le32 OEM; __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 * Battery platforms
*/ */
...@@ -856,6 +889,12 @@ struct aac_dev ...@@ -856,6 +889,12 @@ struct aac_dev
int id; int id;
u16 irq_mask; u16 irq_mask;
/*
* negotiated FIB settings
*/
unsigned max_fib_size;
unsigned sg_tablesize;
/* /*
* Map for 128 fib objects (64k) * Map for 128 fib objects (64k)
*/ */
...@@ -915,12 +954,14 @@ struct aac_dev ...@@ -915,12 +954,14 @@ struct aac_dev
u32 aif_thread; u32 aif_thread;
struct completion aif_completion; struct completion aif_completion;
struct aac_adapter_info adapter_info; 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 /* 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 * lets break them out so we don't have to do an AND to check them
*/ */
u8 nondasd_support; u8 nondasd_support;
u8 dac_support; u8 dac_support;
u8 raid_scsi_mode; u8 raid_scsi_mode;
u8 printf_enabled;
}; };
#define aac_adapter_interrupt(dev) \ #define aac_adapter_interrupt(dev) \
...@@ -929,6 +970,8 @@ struct aac_dev ...@@ -929,6 +970,8 @@ struct aac_dev
#define aac_adapter_notify(dev, event) \ #define aac_adapter_notify(dev, event) \
(dev)->a_ops.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) \ #define aac_adapter_check_health(dev) \
(dev)->a_ops.adapter_check_health(dev) (dev)->a_ops.adapter_check_health(dev)
...@@ -1327,7 +1370,7 @@ struct aac_commit_config { ...@@ -1327,7 +1370,7 @@ struct aac_commit_config {
}; };
/* /*
* Query for Container Configuration Count * Query for Container Configuration Status
*/ */
#define CT_GET_CONTAINER_COUNT 4 #define CT_GET_CONTAINER_COUNT 4
...@@ -1481,6 +1524,7 @@ struct revision ...@@ -1481,6 +1524,7 @@ struct revision
#define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED) #define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED)
#define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER) #define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER)
#define FSACTL_GET_CONTAINERS 2131 #define FSACTL_GET_CONTAINERS 2131
#define FSACTL_SEND_LARGE_FIB CTL_CODE(2138, METHOD_BUFFERED)
struct aac_common struct aac_common
...@@ -1667,3 +1711,5 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size); ...@@ -1667,3 +1711,5 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype); struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev); int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev); int aac_send_shutdown(struct aac_dev *dev);
extern int numacb;
extern int acbsize;
...@@ -51,15 +51,22 @@ ...@@ -51,15 +51,22 @@
* This routine sends a fib to the adapter on behalf of a user level * This routine sends a fib to the adapter on behalf of a user level
* program. * program.
*/ */
# define AAC_DEBUG_PREAMBLE KERN_INFO
# define AAC_DEBUG_POSTAMBLE
static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
{ {
struct hw_fib * kfib; struct hw_fib * kfib;
struct fib *fibptr; 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); fibptr = fib_alloc(dev);
if(fibptr == NULL) if(fibptr == NULL) {
return -ENOMEM; return -ENOMEM;
}
kfib = fibptr->hw_fib; kfib = fibptr->hw_fib;
/* /*
...@@ -74,16 +81,21 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) ...@@ -74,16 +81,21 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* will not overrun the buffer when we copy the memory. Return * will not overrun the buffer when we copy the memory. Return
* an error if we would. * an error if we would.
*/ */
if (le16_to_cpu(kfib->header.Size) > size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr);
sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) { if (size < le16_to_cpu(kfib->header.SenderSize))
fib_free(fibptr); size = le16_to_cpu(kfib->header.SenderSize);
return -EINVAL; if (size > dev->max_fib_size) {
} /* Highjack the hw_fib */
hw_fib = fibptr->hw_fib;
if (copy_from_user(kfib, arg, le16_to_cpu(kfib->header.Size) + hw_fib_pa = fibptr->hw_fib_pa;
sizeof(struct aac_fibhdr))) { fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
fib_free(fibptr); memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);
return -EFAULT; memcpy(kfib, hw_fib, dev->max_fib_size);
}
if (copy_from_user(kfib, arg, size)) {
retval = -EFAULT;
goto cleanup;
} }
if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) { if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {
...@@ -94,16 +106,15 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) ...@@ -94,16 +106,15 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
*/ */
kfib->header.XferState = 0; kfib->header.XferState = 0;
} else { } else {
int retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr, retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
le16_to_cpu(kfib->header.Size) , FsaNormal, le16_to_cpu(kfib->header.Size) , FsaNormal,
1, 1, NULL, NULL); 1, 1, NULL, NULL);
if (retval) { if (retval) {
fib_free(fibptr); goto cleanup;
return retval;
} }
if (fib_complete(fibptr) != 0) { if (fib_complete(fibptr) != 0) {
fib_free(fibptr); retval = -EINVAL;
return -EINVAL; goto cleanup;
} }
} }
/* /*
...@@ -114,12 +125,17 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) ...@@ -114,12 +125,17 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* was already included by the adapter.) * was already included by the adapter.)
*/ */
if (copy_to_user(arg, (void *)kfib, le16_to_cpu(kfib->header.Size))) { retval = 0;
fib_free(fibptr); if (copy_to_user(arg, (void *)kfib, size))
return -EFAULT; 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); fib_free(fibptr);
return 0; return retval;
} }
/** /**
...@@ -399,6 +415,7 @@ static int check_revision(struct aac_dev *dev, void __user *arg) ...@@ -399,6 +415,7 @@ static int check_revision(struct aac_dev *dev, void __user *arg)
return 0; return 0;
} }
/** /**
* *
* aac_send_raw_scb * aac_send_raw_scb
...@@ -427,7 +444,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -427,7 +444,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if (!capable(CAP_SYS_ADMIN)){ 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; return -EPERM;
} }
/* /*
...@@ -440,20 +457,26 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -440,20 +457,26 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
srbcmd = (struct aac_srb*) fib_data(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))){ 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; rcode = -EFAULT;
goto cleanup; goto cleanup;
} }
if (fibsize > FIB_DATA_SIZE_IN_BYTES) { if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) {
rcode = -EINVAL; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
user_srbcmd = kmalloc(GFP_KERNEL, fibsize); 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)){ if(copy_from_user(user_srbcmd, user_srb,fibsize)){
printk(KERN_DEBUG"aacraid: Could not copy srb from user\n"); dprintk((KERN_DEBUG"aacraid: Could not copy srb from user\n"));
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto cleanup;
} }
...@@ -467,9 +490,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -467,9 +490,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
srbcmd->channel = cpu_to_le32(user_srbcmd->channel); srbcmd->channel = cpu_to_le32(user_srbcmd->channel);
srbcmd->id = cpu_to_le32(user_srbcmd->id); srbcmd->id = cpu_to_le32(user_srbcmd->id);
srbcmd->lun = cpu_to_le32(user_srbcmd->lun); srbcmd->lun = cpu_to_le32(user_srbcmd->lun);
srbcmd->flags = cpu_to_le32(user_srbcmd->flags); srbcmd->flags = cpu_to_le32(flags);
srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout); srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout);
srbcmd->retry_limit = 0; srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size); srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
switch (flags & (SRB_DataIn | SRB_DataOut)) { switch (flags & (SRB_DataIn | SRB_DataOut)) {
...@@ -485,9 +508,16 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -485,9 +508,16 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
default: default:
data_dir = DMA_NONE; data_dir = DMA_NONE;
} }
if (le32_to_cpu(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) { if (dev->dac_support == 1) {
struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg; struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
struct sgmap64* psg = (struct sgmap64*)&user_srbcmd->sg; struct sgmap64* psg = (struct sgmap64*)&user_srbcmd->sg;
struct user_sgmap* usg;
byte_count = 0; byte_count = 0;
/* /*
...@@ -495,65 +525,81 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -495,65 +525,81 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
*/ */
actual_fibsize = sizeof(struct aac_srb) - actual_fibsize = sizeof(struct aac_srb) -
sizeof(struct sgentry) + sizeof(struct sgentry) +
((user_srbcmd->sg.count & 0xff) * ((upsg->count & 0xff) *
sizeof(struct sgentry64)); sizeof(struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue 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; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
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) { if ((data_dir == DMA_NONE) && upsg->count) {
printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"); kfree (usg);
dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
rcode = -EINVAL; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
for (i = 0; i < upsg->count; i++) { for (i = 0; i < usg->count; i++) {
u64 addr; u64 addr;
void* p; void* p;
p = kmalloc(upsg->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) { if(p == 0) {
printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", kfree (usg);
upsg->sg[i].count,i,upsg->count); 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; rcode = -ENOMEM;
goto cleanup; goto cleanup;
} }
sg_user[i] = (void __user *)upsg->sg[i].addr; sg_user[i] = (void __user *)usg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later sg_list[i] = p; // save so we can clean up later
sg_indx = i; sg_indx = i;
if( flags & SRB_DataOut ){ if( flags & SRB_DataOut ){
if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){ if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); kfree (usg);
dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto cleanup;
} }
} }
addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir); addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr >> 32); psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
byte_count += upsg->sg[i].count; byte_count += usg->sg[i].count;
} }
kfree (usg);
srbcmd->count = cpu_to_le32(byte_count); 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); status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
} else { } else {
struct user_sgmap* upsg = &user_srbcmd->sg; struct user_sgmap* upsg = &user_srbcmd->sg;
struct sgmap* psg = &srbcmd->sg; struct sgmap* psg = &srbcmd->sg;
byte_count = 0; byte_count = 0;
actual_fibsize = sizeof (struct aac_srb) + actual_fibsize = sizeof (struct aac_srb) + (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * sizeof (struct sgentry));
(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
sizeof (struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue 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; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
if ((data_dir == DMA_NONE) && upsg->count) { if ((data_dir == DMA_NONE) && upsg->count) {
printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"); dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
rcode = -EINVAL; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
...@@ -562,8 +608,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -562,8 +608,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
void* p; void* p;
p = kmalloc(upsg->sg[i].count, GFP_KERNEL); p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
if(p == 0) { if(p == 0) {
printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
upsg->sg[i].count, i, upsg->count); upsg->sg[i].count, i, upsg->count));
rcode = -ENOMEM; rcode = -ENOMEM;
goto cleanup; goto cleanup;
} }
...@@ -574,7 +620,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -574,7 +620,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if( flags & SRB_DataOut ){ if( flags & SRB_DataOut ){
if(copy_from_user(p, sg_user[i], if(copy_from_user(p, sg_user[i],
upsg->sg[i].count)) { upsg->sg[i].count)) {
printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto cleanup;
} }
...@@ -587,19 +633,23 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -587,19 +633,23 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
byte_count += upsg->sg[i].count; byte_count += upsg->sg[i].count;
} }
srbcmd->count = cpu_to_le32(byte_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); status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
} }
if (status != 0){ if (status != 0){
printk(KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"); dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"));
rcode = -1; rcode = -1;
goto cleanup; goto cleanup;
} }
if( flags & SRB_DataIn ) { if( flags & SRB_DataIn ) {
for(i = 0 ; i <= sg_indx; i++){ 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))){ byte_count = le32_to_cpu((dev->dac_support == 1)
printk(KERN_DEBUG"aacraid: Could not copy sg data to user\n"); ? ((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; rcode = -EFAULT;
goto cleanup; goto cleanup;
...@@ -609,7 +659,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -609,7 +659,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
reply = (struct aac_srb_reply *) fib_data(srbfib); reply = (struct aac_srb_reply *) fib_data(srbfib);
if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){ 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; rcode = -EFAULT;
goto cleanup; goto cleanup;
} }
...@@ -625,7 +675,6 @@ cleanup: ...@@ -625,7 +675,6 @@ cleanup:
return rcode; return rcode;
} }
struct aac_pci_info { struct aac_pci_info {
u32 bus; u32 bus;
u32 slot; u32 slot;
...@@ -640,11 +689,11 @@ static int aac_get_pci_info(struct aac_dev* dev, void __user *arg) ...@@ -640,11 +689,11 @@ static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
pci_info.slot = PCI_SLOT(dev->pdev->devfn); pci_info.slot = PCI_SLOT(dev->pdev->devfn);
if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) { 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 -EFAULT;
} }
return 0; return 0;
} }
int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg) int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
...@@ -663,6 +712,7 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg) ...@@ -663,6 +712,7 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
case FSACTL_MINIPORT_REV_CHECK: case FSACTL_MINIPORT_REV_CHECK:
status = check_revision(dev, arg); status = check_revision(dev, arg);
break; break;
case FSACTL_SEND_LARGE_FIB:
case FSACTL_SENDFIB: case FSACTL_SENDFIB:
status = ioctl_send_fib(dev, arg); status = ioctl_send_fib(dev, arg);
break; break;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <scsi/scsi_host.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include "aacraid.h" #include "aacraid.h"
...@@ -49,8 +50,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -49,8 +50,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
{ {
unsigned char *base; unsigned char *base;
unsigned long size, align; unsigned long size, align;
unsigned long fibsize = 4096; const unsigned long fibsize = 4096;
unsigned long printfbufsiz = 256; const unsigned long printfbufsiz = 256;
struct aac_init *init; struct aac_init *init;
dma_addr_t phys; dma_addr_t phys;
...@@ -74,6 +75,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -74,6 +75,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
init = dev->init; init = dev->init;
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); 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->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION);
init->fsrev = cpu_to_le32(dev->fsrev); 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 ...@@ -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->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 * Increment the base address by the amount already used
...@@ -173,6 +180,8 @@ int aac_send_shutdown(struct aac_dev * dev) ...@@ -173,6 +180,8 @@ int aac_send_shutdown(struct aac_dev * dev)
int status; int status;
fibctx = fib_alloc(dev); fibctx = fib_alloc(dev);
if (!fibctx)
return -ENOMEM;
fib_init(fibctx); fib_init(fibctx);
cmd = (struct aac_close *) fib_data(fibctx); cmd = (struct aac_close *) fib_data(fibctx);
...@@ -293,6 +302,79 @@ static int aac_comm_init(struct aac_dev * dev) ...@@ -293,6 +302,79 @@ static int aac_comm_init(struct aac_dev * dev)
struct aac_dev *aac_init_adapter(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 * Ok now init the communication subsystem
*/ */
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
* commsup.c * commsup.c
* *
* Abstract: Contain all routines that are required for FSA host/adapter * Abstract: Contain all routines that are required for FSA host/adapter
* commuication. * communication.
* *
*/ */
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <scsi/scsi_host.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include "aacraid.h" #include "aacraid.h"
...@@ -52,7 +53,13 @@ ...@@ -52,7 +53,13 @@
static int fib_map_alloc(struct aac_dev *dev) 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 -ENOMEM;
return 0; return 0;
} }
...@@ -67,7 +74,7 @@ static int fib_map_alloc(struct aac_dev *dev) ...@@ -67,7 +74,7 @@ static int fib_map_alloc(struct aac_dev *dev)
void fib_map_free(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);
} }
/** /**
...@@ -85,16 +92,21 @@ int fib_setup(struct aac_dev * dev) ...@@ -85,16 +92,21 @@ int fib_setup(struct aac_dev * dev)
dma_addr_t hw_fib_pa; dma_addr_t hw_fib_pa;
int i; 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; return -ENOMEM;
hw_fib_va = dev->hw_fib_va; hw_fib_va = dev->hw_fib_va;
hw_fib_pa = dev->hw_fib_pa; 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 * 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->dev = dev;
fibptr->hw_fib = hw_fib_va; fibptr->hw_fib = hw_fib_va;
...@@ -103,15 +115,15 @@ int fib_setup(struct aac_dev * dev) ...@@ -103,15 +115,15 @@ int fib_setup(struct aac_dev * dev)
init_MUTEX_LOCKED(&fibptr->event_wait); init_MUTEX_LOCKED(&fibptr->event_wait);
spin_lock_init(&fibptr->event_lock); spin_lock_init(&fibptr->event_lock);
hw_fib_va->header.XferState = cpu_to_le32(0xffffffff); hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size);
fibptr->hw_fib_pa = hw_fib_pa; fibptr->hw_fib_pa = hw_fib_pa;
hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + 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 + sizeof(struct hw_fib); hw_fib_pa = hw_fib_pa + dev->max_fib_size;
} }
/* /*
* Add the fib chain to the free list * 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 * Enable this to debug out of queue space
*/ */
...@@ -124,7 +136,7 @@ int fib_setup(struct aac_dev * dev) ...@@ -124,7 +136,7 @@ int fib_setup(struct aac_dev * dev)
* @dev: Adapter to allocate the fib for * @dev: Adapter to allocate the fib for
* *
* Allocate a fib from the adapter fib pool. If the pool is empty we * 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) struct fib * fib_alloc(struct aac_dev *dev)
...@@ -133,10 +145,10 @@ struct fib * fib_alloc(struct aac_dev *dev) ...@@ -133,10 +145,10 @@ struct fib * fib_alloc(struct aac_dev *dev)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev->fib_lock, flags); spin_lock_irqsave(&dev->fib_lock, flags);
fibptr = dev->free_fib; fibptr = dev->free_fib;
/* Cannot sleep here or you get hangs. Instead we did the if(!fibptr){
maths at compile time. */ spin_unlock_irqrestore(&dev->fib_lock, flags);
if(!fibptr) return fibptr;
BUG(); }
dev->free_fib = fibptr->next; dev->free_fib = fibptr->next;
spin_unlock_irqrestore(&dev->fib_lock, flags); spin_unlock_irqrestore(&dev->fib_lock, flags);
/* /*
...@@ -196,11 +208,11 @@ void fib_init(struct fib *fibptr) ...@@ -196,11 +208,11 @@ void fib_init(struct fib *fibptr)
struct hw_fib *hw_fib = fibptr->hw_fib; struct hw_fib *hw_fib = fibptr->hw_fib;
hw_fib->header.StructType = FIB_MAGIC; hw_fib->header.StructType = FIB_MAGIC;
hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib)); 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.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa); 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.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);
} }
/** /**
...@@ -279,7 +291,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr ...@@ -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 */ 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); qid, q->numpending);
return 0; return 0;
} else { } else {
...@@ -743,9 +755,11 @@ int fib_complete(struct fib * fibptr) ...@@ -743,9 +755,11 @@ int fib_complete(struct fib * fibptr)
void aac_printf(struct aac_dev *dev, u32 val) void aac_printf(struct aac_dev *dev, u32 val)
{ {
char *cp = dev->printfbuf;
if (dev->printf_enabled)
{
int length = val & 0xffff; int length = val & 0xffff;
int level = (val >> 16) & 0xffff; int level = (val >> 16) & 0xffff;
char *cp = dev->printfbuf;
/* /*
* The size of the printfbuf is set in port.c * The size of the printfbuf is set in port.c
...@@ -759,6 +773,7 @@ void aac_printf(struct aac_dev *dev, u32 val) ...@@ -759,6 +773,7 @@ void aac_printf(struct aac_dev *dev, u32 val)
printk(KERN_WARNING "aacraid:%s", cp); printk(KERN_WARNING "aacraid:%s", cp);
else else
printk(KERN_INFO "aacraid:%s", cp); printk(KERN_INFO "aacraid:%s", cp);
}
memset(cp, 0, 256); memset(cp, 0, 256);
} }
......
...@@ -347,10 +347,16 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, ...@@ -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) static int aac_slave_configure(struct scsi_device *sdev)
{ {
struct Scsi_Host *host = sdev->host;
if (sdev->tagged_supported) if (sdev->tagged_supported)
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128); scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128);
else else
scsi_adjust_queue_depth(sdev, 0, 1); 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; return 0;
} }
...@@ -439,11 +445,11 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) ...@@ -439,11 +445,11 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
static int aac_cfg_open(struct inode *inode, struct file *file) static int aac_cfg_open(struct inode *inode, struct file *file)
{ {
struct aac_dev *aac; struct aac_dev *aac;
unsigned minor = iminor(inode); unsigned minor_number = iminor(inode);
int err = -ENODEV; int err = -ENODEV;
list_for_each_entry(aac, &aac_devices, entry) { list_for_each_entry(aac, &aac_devices, entry) {
if (aac->id == minor) { if (aac->id == minor_number) {
file->private_data = aac; file->private_data = aac;
err = 0; err = 0;
break; break;
...@@ -489,6 +495,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long ...@@ -489,6 +495,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
case FSACTL_DELETE_DISK: case FSACTL_DELETE_DISK:
case FSACTL_FORCE_DELETE_DISK: case FSACTL_FORCE_DELETE_DISK:
case FSACTL_GET_CONTAINERS: case FSACTL_GET_CONTAINERS:
case FSACTL_SEND_LARGE_FIB:
ret = aac_do_ioctl(dev, cmd, (void __user *)arg); ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
break; break;
...@@ -538,7 +545,7 @@ static struct file_operations aac_cfg_fops = { ...@@ -538,7 +545,7 @@ static struct file_operations aac_cfg_fops = {
static struct scsi_host_template aac_driver_template = { static struct scsi_host_template aac_driver_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "AAC", .name = "AAC",
.proc_name = "aacraid", .proc_name = AAC_DRIVERNAME,
.info = aac_info, .info = aac_info,
.ioctl = aac_ioctl, .ioctl = aac_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -612,7 +619,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, ...@@ -612,7 +619,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac->cardtype = index; aac->cardtype = index;
INIT_LIST_HEAD(&aac->entry); 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) if (!aac->fibs)
goto out_free_host; goto out_free_host;
spin_lock_init(&aac->fib_lock); spin_lock_init(&aac->fib_lock);
...@@ -631,6 +638,24 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, ...@@ -631,6 +638,24 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac_get_adapter_info(aac); 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 * max channel will be the physical channels plus 1 virtual channel
* all containers are on the virtual channel 0 * all containers are on the virtual channel 0
......
...@@ -98,7 +98,9 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -98,7 +98,9 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
* for its completion. * 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; unsigned long start;
int ok; int ok;
...@@ -107,12 +109,12 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) ...@@ -107,12 +109,12 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/ */
rkt_writel(dev, InboundMailbox0, command); 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, InboundMailbox1, p1);
rkt_writel(dev, InboundMailbox2, 0); rkt_writel(dev, InboundMailbox2, p2);
rkt_writel(dev, InboundMailbox3, 0); rkt_writel(dev, InboundMailbox3, p3);
rkt_writel(dev, InboundMailbox4, 0); rkt_writel(dev, InboundMailbox4, p4);
/* /*
* Clear the synch command doorbell to start on a clean slate. * 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) ...@@ -169,6 +171,14 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/ */
if (status) if (status)
*status = rkt_readl(dev, IndexRegs.Mailbox[0]); *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. * Clear the synch command doorbell.
*/ */
...@@ -190,8 +200,8 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) ...@@ -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) static void aac_rkt_interrupt_adapter(struct aac_dev *dev)
{ {
u32 ret; rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); NULL, NULL, NULL, NULL, NULL);
} }
/** /**
...@@ -220,7 +230,8 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event) ...@@ -220,7 +230,8 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
break; break;
case HostShutdown: 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; break;
case FastIo: case FastIo:
rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
...@@ -243,16 +254,10 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event) ...@@ -243,16 +254,10 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
static void aac_rkt_start_adapter(struct aac_dev *dev) static void aac_rkt_start_adapter(struct aac_dev *dev)
{ {
u32 status;
struct aac_init *init; struct aac_init *init;
init = dev->init; init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds()); 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 * First clear out all interrupts. Then enable the one's that we
* can handle. * can handle.
...@@ -263,7 +268,8 @@ static void aac_rkt_start_adapter(struct aac_dev *dev) ...@@ -263,7 +268,8 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
// We can only use a 32 bit address here // 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);
} }
/** /**
...@@ -310,7 +316,8 @@ static int aac_rkt_check_health(struct aac_dev *dev) ...@@ -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_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr); post->Post_Address = cpu_to_le32(baddr);
rkt_writel(dev, MUnit.IMRx[0], paddr); 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), pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr); post, paddr);
if ((buffer[0] == '0') && (buffer[1] == 'x')) { if ((buffer[0] == '0') && (buffer[1] == 'x')) {
......
...@@ -98,7 +98,9 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -98,7 +98,9 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
* for its completion. * 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; unsigned long start;
int ok; int ok;
...@@ -107,12 +109,12 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) ...@@ -107,12 +109,12 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/ */
rx_writel(dev, InboundMailbox0, command); 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, InboundMailbox1, p1);
rx_writel(dev, InboundMailbox2, 0); rx_writel(dev, InboundMailbox2, p2);
rx_writel(dev, InboundMailbox3, 0); rx_writel(dev, InboundMailbox3, p3);
rx_writel(dev, InboundMailbox4, 0); rx_writel(dev, InboundMailbox4, p4);
/* /*
* Clear the synch command doorbell to start on a clean slate. * 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) ...@@ -120,7 +122,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/* /*
* Disable doorbell interrupts * 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 * Force the completion of the mask register write before issuing
* the interrupt. * the interrupt.
...@@ -169,6 +171,14 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) ...@@ -169,6 +171,14 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/ */
if (status) if (status)
*status = rx_readl(dev, IndexRegs.Mailbox[0]); *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. * Clear the synch command doorbell.
*/ */
...@@ -190,8 +200,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) ...@@ -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) static void aac_rx_interrupt_adapter(struct aac_dev *dev)
{ {
u32 ret; rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
} }
/** /**
...@@ -220,7 +229,8 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) ...@@ -220,7 +229,8 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
break; break;
case HostShutdown: 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; break;
case FastIo: case FastIo:
rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
...@@ -243,16 +253,10 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) ...@@ -243,16 +253,10 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
static void aac_rx_start_adapter(struct aac_dev *dev) static void aac_rx_start_adapter(struct aac_dev *dev)
{ {
u32 status;
struct aac_init *init; struct aac_init *init;
init = dev->init; init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds()); 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 * First clear out all interrupts. Then enable the one's that we
* can handle. * can handle.
...@@ -263,7 +267,8 @@ static void aac_rx_start_adapter(struct aac_dev *dev) ...@@ -263,7 +267,8 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
// We can only use a 32 bit address here // 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);
} }
/** /**
...@@ -310,7 +315,8 @@ static int aac_rx_check_health(struct aac_dev *dev) ...@@ -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_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr); post->Post_Address = cpu_to_le32(baddr);
rx_writel(dev, MUnit.IMRx[0], paddr); 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), pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr); post, paddr);
if ((buffer[0] == '0') && (buffer[1] == 'x')) { if ((buffer[0] == '0') && (buffer[1] == 'x')) {
......
...@@ -106,7 +106,10 @@ static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event) ...@@ -106,7 +106,10 @@ static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
sa_writew(dev, DoorbellReg_s,DOORBELL_3); sa_writew(dev, DoorbellReg_s,DOORBELL_3);
break; break;
case HostShutdown: 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; break;
case FastIo: case FastIo:
sa_writew(dev, DoorbellReg_s,DOORBELL_6); sa_writew(dev, DoorbellReg_s,DOORBELL_6);
...@@ -132,7 +135,9 @@ static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event) ...@@ -132,7 +135,9 @@ static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
* for its completion. * 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; unsigned long start;
int ok; int ok;
...@@ -144,9 +149,10 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret) ...@@ -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 * Write the parameters into Mailboxes 1 - 4
*/ */
sa_writel(dev, Mailbox1, p1); sa_writel(dev, Mailbox1, p1);
sa_writel(dev, Mailbox2, 0); sa_writel(dev, Mailbox2, p2);
sa_writel(dev, Mailbox3, 0); sa_writel(dev, Mailbox3, p3);
sa_writel(dev, Mailbox4, 0); sa_writel(dev, Mailbox4, p4);
/* /*
* Clear the synch command doorbell to start on a clean slate. * 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) ...@@ -188,6 +194,14 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
*/ */
if (ret) if (ret)
*ret = sa_readl(dev, Mailbox0); *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; return 0;
} }
...@@ -201,7 +215,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret) ...@@ -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) static void aac_sa_interrupt_adapter (struct aac_dev *dev)
{ {
u32 ret; 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);
} }
/** /**
...@@ -233,7 +248,9 @@ static void aac_sa_start_adapter(struct aac_dev *dev) ...@@ -233,7 +248,9 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
/* We can only use a 32 bit address here */ /* 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);
} }
/** /**
......
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