Commit 85d22bbf authored by Mahesh Rajashekhara's avatar Mahesh Rajashekhara Committed by James Bottomley

[SCSI] aacraid: Series 7 Async. (performance) mode support

- Series 7 Async. (performance) mode support added
- New scatter/gather list format for Series 7
- Driver converts s/g list to a firmware suitable list for best performance on
  Series 7, this can be disabled with driver parameter "aac_convert_sgl" for
  testing purposes
- New container read/write command structure for Series 7
- Fast response support for the SCSI pass-through path added
- Async. status response buffer changes
Signed-off-by: default avatarMahesh Rajashekhara <Mahesh_Rajashekhara@pmc-sierra.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent fa7250d6
This diff is collapsed.
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#ifndef AAC_DRIVER_BUILD #ifndef AAC_DRIVER_BUILD
# define AAC_DRIVER_BUILD 28900 # define AAC_DRIVER_BUILD 29800
# define AAC_DRIVER_BRANCH "-ms" # define AAC_DRIVER_BRANCH "-ms"
#endif #endif
#define MAXIMUM_NUM_CONTAINERS 32 #define MAXIMUM_NUM_CONTAINERS 32
...@@ -100,6 +100,13 @@ struct user_sgentryraw { ...@@ -100,6 +100,13 @@ struct user_sgentryraw {
u32 flags; /* reserved for F/W use */ u32 flags; /* reserved for F/W use */
}; };
struct sge_ieee1212 {
u32 addrLow;
u32 addrHigh;
u32 length;
u32 flags;
};
/* /*
* SGMAP * SGMAP
* *
...@@ -270,6 +277,8 @@ enum aac_queue_types { ...@@ -270,6 +277,8 @@ enum aac_queue_types {
*/ */
#define FIB_MAGIC 0x0001 #define FIB_MAGIC 0x0001
#define FIB_MAGIC2 0x0004
#define FIB_MAGIC2_64 0x0005
/* /*
* Define the priority levels the FSA communication routines support. * Define the priority levels the FSA communication routines support.
...@@ -296,22 +305,20 @@ struct aac_fibhdr { ...@@ -296,22 +305,20 @@ struct aac_fibhdr {
__le32 XferState; /* Current transfer state for this CCB */ __le32 XferState; /* Current transfer state for this CCB */
__le16 Command; /* Routing information for the destination */ __le16 Command; /* Routing information for the destination */
u8 StructType; /* Type FIB */ u8 StructType; /* Type FIB */
u8 Flags; /* Flags for FIB */ u8 Unused; /* Unused */
__le16 Size; /* Size of this FIB in bytes */ __le16 Size; /* Size of this FIB in bytes */
__le16 SenderSize; /* Size of the FIB in the sender __le16 SenderSize; /* Size of the FIB in the sender
(for response sizing) */ (for response sizing) */
__le32 SenderFibAddress; /* Host defined data in the FIB */ __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 { union {
struct { __le32 ReceiverFibAddress;/* Logical address of this FIB for
__le32 _ReceiverTimeStart; /* Timestamp for the adapter (old) */
receipt of fib */ __le32 SenderFibAddressHigh;/* upper 32bit of phys. FIB address */
__le32 _ReceiverTimeDone; /* Timestamp for __le32 TimeStamp; /* otherwise timestamp for FW internal use */
completion of fib */ } u;
} _s; u32 Handle; /* FIB handle used for MSGU commnunication */
} _u; u32 Previous; /* FW internal use */
u32 Next; /* FW internal use */
}; };
struct hw_fib { struct hw_fib {
...@@ -361,6 +368,7 @@ struct hw_fib { ...@@ -361,6 +368,7 @@ struct hw_fib {
#define ContainerCommand 500 #define ContainerCommand 500
#define ContainerCommand64 501 #define ContainerCommand64 501
#define ContainerRawIo 502 #define ContainerRawIo 502
#define ContainerRawIo2 503
/* /*
* Scsi Port commands (scsi passthrough) * Scsi Port commands (scsi passthrough)
*/ */
...@@ -417,6 +425,7 @@ enum fib_xfer_state { ...@@ -417,6 +425,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 #define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science
#define ADAPTER_INIT_STRUCT_REVISION_6 6 /* PMC src */ #define ADAPTER_INIT_STRUCT_REVISION_6 6 /* PMC src */
#define ADAPTER_INIT_STRUCT_REVISION_7 7 /* Denali */
struct aac_init struct aac_init
{ {
...@@ -441,7 +450,9 @@ struct aac_init ...@@ -441,7 +450,9 @@ struct aac_init
#define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001 #define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001
#define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010 #define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010
#define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020 #define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020
#define INITFLAGS_NEW_COMM_TYPE1_SUPPORTED 0x00000041 #define INITFLAGS_NEW_COMM_TYPE1_SUPPORTED 0x00000040
#define INITFLAGS_FAST_JBOD_SUPPORTED 0x00000080
#define INITFLAGS_NEW_COMM_TYPE2_SUPPORTED 0x00000100
__le32 MaxIoCommands; /* max outstanding commands */ __le32 MaxIoCommands; /* max outstanding commands */
__le32 MaxIoSize; /* largest I/O command */ __le32 MaxIoSize; /* largest I/O command */
__le32 MaxFibSize; /* largest FIB to adapter */ __le32 MaxFibSize; /* largest FIB to adapter */
...@@ -1124,6 +1135,7 @@ struct aac_dev ...@@ -1124,6 +1135,7 @@ struct aac_dev
# define AAC_COMM_PRODUCER 0 # define AAC_COMM_PRODUCER 0
# define AAC_COMM_MESSAGE 1 # define AAC_COMM_MESSAGE 1
# define AAC_COMM_MESSAGE_TYPE1 3 # define AAC_COMM_MESSAGE_TYPE1 3
# define AAC_COMM_MESSAGE_TYPE2 4
u8 raw_io_interface; u8 raw_io_interface;
u8 raw_io_64; u8 raw_io_64;
u8 printf_enabled; u8 printf_enabled;
...@@ -1182,6 +1194,7 @@ struct aac_dev ...@@ -1182,6 +1194,7 @@ struct aac_dev
#define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001)
#define FIB_CONTEXT_FLAG (0x00000002) #define FIB_CONTEXT_FLAG (0x00000002)
#define FIB_CONTEXT_FLAG_WAIT (0x00000004) #define FIB_CONTEXT_FLAG_WAIT (0x00000004)
#define FIB_CONTEXT_FLAG_FASTRESP (0x00000008)
/* /*
* Define the command values * Define the command values
...@@ -1288,6 +1301,22 @@ struct aac_dev ...@@ -1288,6 +1301,22 @@ struct aac_dev
#define CMDATA_SYNCH 4 #define CMDATA_SYNCH 4
#define CMUNSTABLE 5 #define CMUNSTABLE 5
#define RIO_TYPE_WRITE 0x0000
#define RIO_TYPE_READ 0x0001
#define RIO_SUREWRITE 0x0008
#define RIO2_IO_TYPE 0x0003
#define RIO2_IO_TYPE_WRITE 0x0000
#define RIO2_IO_TYPE_READ 0x0001
#define RIO2_IO_TYPE_VERIFY 0x0002
#define RIO2_IO_ERROR 0x0004
#define RIO2_IO_SUREWRITE 0x0008
#define RIO2_SGL_CONFORMANT 0x0010
#define RIO2_SG_FORMAT 0xF000
#define RIO2_SG_FORMAT_ARC 0x0000
#define RIO2_SG_FORMAT_SRL 0x1000
#define RIO2_SG_FORMAT_IEEE1212 0x2000
struct aac_read struct aac_read
{ {
__le32 command; __le32 command;
...@@ -1332,9 +1361,6 @@ struct aac_write64 ...@@ -1332,9 +1361,6 @@ struct aac_write64
__le32 block; __le32 block;
__le16 pad; __le16 pad;
__le16 flags; __le16 flags;
#define IO_TYPE_WRITE 0x00000000
#define IO_TYPE_READ 0x00000001
#define IO_SUREWRITE 0x00000008
struct sgmap64 sg; // Must be last in struct because it is variable struct sgmap64 sg; // Must be last in struct because it is variable
}; };
struct aac_write_reply struct aac_write_reply
...@@ -1355,6 +1381,22 @@ struct aac_raw_io ...@@ -1355,6 +1381,22 @@ struct aac_raw_io
struct sgmapraw sg; struct sgmapraw sg;
}; };
struct aac_raw_io2 {
__le32 blockLow;
__le32 blockHigh;
__le32 byteCount;
__le16 cid;
__le16 flags; /* RIO2 flags */
__le32 sgeFirstSize; /* size of first sge el. */
__le32 sgeNominalSize; /* size of 2nd sge el. (if conformant) */
u8 sgeCnt; /* only 8 bits required */
u8 bpTotal; /* reserved for F/W use */
u8 bpComplete; /* reserved for F/W use */
u8 sgeFirstIndex; /* reserved for F/W use */
u8 unused[4];
struct sge_ieee1212 sge[1];
};
#define CT_FLUSH_CACHE 129 #define CT_FLUSH_CACHE 129
struct aac_synchronize { struct aac_synchronize {
__le32 command; /* VM_ContainerConfig */ __le32 command; /* VM_ContainerConfig */
......
...@@ -498,6 +498,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -498,6 +498,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
return -ENOMEM; return -ENOMEM;
} }
aac_fib_init(srbfib); aac_fib_init(srbfib);
/* raw_srb FIB is not FastResponseCapable */
srbfib->hw_fib_va->header.XferState &= ~cpu_to_le32(FastResponseCapable);
srbcmd = (struct aac_srb*) fib_data(srbfib); srbcmd = (struct aac_srb*) fib_data(srbfib);
......
...@@ -58,7 +58,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -58,7 +58,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
dma_addr_t phys; dma_addr_t phys;
unsigned long aac_max_hostphysmempages; unsigned long aac_max_hostphysmempages;
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE2)
host_rrq_size = (dev->scsi_host_ptr->can_queue host_rrq_size = (dev->scsi_host_ptr->can_queue
+ AAC_NUM_MGT_FIB) * sizeof(u32); + AAC_NUM_MGT_FIB) * sizeof(u32);
size = fibsize + sizeof(struct aac_init) + commsize + size = fibsize + sizeof(struct aac_init) + commsize +
...@@ -75,7 +76,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -75,7 +76,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
dev->comm_phys = phys; dev->comm_phys = phys;
dev->comm_size = size; dev->comm_size = size;
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
dev->host_rrq = (u32 *)(base + fibsize); dev->host_rrq = (u32 *)(base + fibsize);
dev->host_rrq_pa = phys + fibsize; dev->host_rrq_pa = phys + fibsize;
memset(dev->host_rrq, 0, host_rrq_size); memset(dev->host_rrq, 0, host_rrq_size);
...@@ -115,26 +117,32 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -115,26 +117,32 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
else else
init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
init->InitFlags = 0; init->InitFlags = cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME |
INITFLAGS_DRIVER_SUPPORTS_PM);
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);
init->MaxNumAif = cpu_to_le32(dev->max_num_aif);
if (dev->comm_interface == AAC_COMM_MESSAGE) { if (dev->comm_interface == AAC_COMM_MESSAGE) {
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n")); dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { } else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6); init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6);
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_TYPE1_SUPPORTED); init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
dprintk((KERN_WARNING INITFLAGS_NEW_COMM_TYPE1_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED);
"aacraid: New Comm Interface type1 enabled\n")); init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32));
init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff));
dprintk((KERN_WARNING"aacraid: New Comm Interface type1 enabled\n"));
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_7);
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED);
init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32));
init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff));
init->MiniPortRevision = cpu_to_le32(0L); /* number of MSI-X */
dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n"));
} }
init->InitFlags |= cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME |
INITFLAGS_DRIVER_SUPPORTS_PM);
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);
init->MaxNumAif = cpu_to_le32(dev->max_num_aif);
init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32));
init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff));
/* /*
* Increment the base address by the amount already used * Increment the base address by the amount already used
...@@ -354,13 +362,15 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) ...@@ -354,13 +362,15 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1))) { if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1))) {
/* driver supports TYPE1 (Tupelo) */ /* driver supports TYPE1 (Tupelo) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
} else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE2))) {
/* driver supports TYPE2 (Denali) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE2;
} else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE4)) || } else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE4)) ||
(status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3)) || (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3))) {
(status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE2))) { /* driver doesn't TYPE3 and TYPE4 */
/* driver doesn't support TYPE2 (Series7), TYPE3 and TYPE4 */ /* switch to sync. mode */
/* switch to sync. mode */ dev->comm_interface = AAC_COMM_MESSAGE_TYPE2;
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; dev->sync_mode = 1;
dev->sync_mode = 1;
} }
} }
if ((dev->comm_interface == AAC_COMM_MESSAGE) && if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
......
...@@ -136,6 +136,7 @@ int aac_fib_setup(struct aac_dev * dev) ...@@ -136,6 +136,7 @@ int aac_fib_setup(struct aac_dev * dev)
i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
i++, fibptr++) i++, fibptr++)
{ {
fibptr->flags = 0;
fibptr->dev = dev; fibptr->dev = dev;
fibptr->hw_fib_va = hw_fib; fibptr->hw_fib_va = hw_fib;
fibptr->data = (void *) fibptr->hw_fib_va->data; fibptr->data = (void *) fibptr->hw_fib_va->data;
...@@ -240,11 +241,11 @@ void aac_fib_init(struct fib *fibptr) ...@@ -240,11 +241,11 @@ void aac_fib_init(struct fib *fibptr)
{ {
struct hw_fib *hw_fib = fibptr->hw_fib_va; struct hw_fib *hw_fib = fibptr->hw_fib_va;
memset(&hw_fib->header, 0, sizeof(struct aac_fibhdr));
hw_fib->header.StructType = FIB_MAGIC; hw_fib->header.StructType = FIB_MAGIC;
hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); 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 = 0; /* Filled in later if needed */ hw_fib->header.u.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(fibptr->dev->max_fib_size); hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size);
} }
...@@ -259,7 +260,6 @@ void aac_fib_init(struct fib *fibptr) ...@@ -259,7 +260,6 @@ void aac_fib_init(struct fib *fibptr)
static void fib_dealloc(struct fib * fibptr) static void fib_dealloc(struct fib * fibptr)
{ {
struct hw_fib *hw_fib = fibptr->hw_fib_va; struct hw_fib *hw_fib = fibptr->hw_fib_va;
BUG_ON(hw_fib->header.StructType != FIB_MAGIC);
hw_fib->header.XferState = 0; hw_fib->header.XferState = 0;
} }
...@@ -370,7 +370,7 @@ int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw ...@@ -370,7 +370,7 @@ int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw
entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size));
entry->addr = hw_fib->header.SenderFibAddress; entry->addr = hw_fib->header.SenderFibAddress;
/* Restore adapters pointer to the FIB */ /* Restore adapters pointer to the FIB */
hw_fib->header.ReceiverFibAddress = hw_fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ hw_fib->header.u.ReceiverFibAddress = hw_fib->header.SenderFibAddress; /* Let the adapter now where to find its data */
map = 0; map = 0;
} }
/* /*
...@@ -450,7 +450,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, ...@@ -450,7 +450,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
*/ */
hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2); hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2);
hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); hw_fib->header.Handle = (u32)(fibptr - dev->fibs) + 1;
/* /*
* Set FIB state to indicate where it came from and if we want a * Set FIB state to indicate where it came from and if we want a
* response from the adapter. Also load the command from the * response from the adapter. Also load the command from the
...@@ -460,7 +460,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, ...@@ -460,7 +460,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
*/ */
hw_fib->header.Command = cpu_to_le16(command); hw_fib->header.Command = cpu_to_le16(command);
hw_fib->header.XferState |= cpu_to_le32(SentFromHost); hw_fib->header.XferState |= cpu_to_le32(SentFromHost);
fibptr->hw_fib_va->header.Flags = 0; /* 0 the flags field - internal only*/
/* /*
* Set the size of the Fib we want to send to the adapter * Set the size of the Fib we want to send to the adapter
*/ */
...@@ -711,7 +710,8 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) ...@@ -711,7 +710,8 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
unsigned long nointr = 0; unsigned long nointr = 0;
unsigned long qflags; unsigned long qflags;
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
kfree(hw_fib); kfree(hw_fib);
return 0; return 0;
} }
...@@ -724,7 +724,9 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) ...@@ -724,7 +724,9 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
/* /*
* If we plan to do anything check the structure type first. * If we plan to do anything check the structure type first.
*/ */
if (hw_fib->header.StructType != FIB_MAGIC) { if (hw_fib->header.StructType != FIB_MAGIC &&
hw_fib->header.StructType != FIB_MAGIC2 &&
hw_fib->header.StructType != FIB_MAGIC2_64) {
if (dev->comm_interface == AAC_COMM_MESSAGE) if (dev->comm_interface == AAC_COMM_MESSAGE)
kfree(hw_fib); kfree(hw_fib);
return -EINVAL; return -EINVAL;
...@@ -786,7 +788,9 @@ int aac_fib_complete(struct fib *fibptr) ...@@ -786,7 +788,9 @@ int aac_fib_complete(struct fib *fibptr)
* If we plan to do anything check the structure type first. * If we plan to do anything check the structure type first.
*/ */
if (hw_fib->header.StructType != FIB_MAGIC) if (hw_fib->header.StructType != FIB_MAGIC &&
hw_fib->header.StructType != FIB_MAGIC2 &&
hw_fib->header.StructType != FIB_MAGIC2_64)
return -EINVAL; return -EINVAL;
/* /*
* This block completes a cdb which orginated on the host and we * This block completes a cdb which orginated on the host and we
......
...@@ -101,6 +101,7 @@ unsigned int aac_response_normal(struct aac_queue * q) ...@@ -101,6 +101,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
*/ */
*(__le32 *)hwfib->data = cpu_to_le32(ST_OK); *(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
hwfib->header.XferState |= cpu_to_le32(AdapterProcessed); hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
} }
FIB_COUNTER_INCREMENT(aac_config.FibRecved); FIB_COUNTER_INCREMENT(aac_config.FibRecved);
...@@ -121,7 +122,7 @@ unsigned int aac_response_normal(struct aac_queue * q) ...@@ -121,7 +122,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
* NOTE: we cannot touch the fib after this * NOTE: we cannot touch the fib after this
* call, because it may have been deallocated. * call, because it may have been deallocated.
*/ */
fib->flags = 0; fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
fib->callback(fib->callback_data, fib); fib->callback(fib->callback_data, fib);
} else { } else {
unsigned long flagv; unsigned long flagv;
...@@ -367,6 +368,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, ...@@ -367,6 +368,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
*/ */
*(__le32 *)hwfib->data = cpu_to_le32(ST_OK); *(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
hwfib->header.XferState |= cpu_to_le32(AdapterProcessed); hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
} }
FIB_COUNTER_INCREMENT(aac_config.FibRecved); FIB_COUNTER_INCREMENT(aac_config.FibRecved);
...@@ -387,7 +389,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, ...@@ -387,7 +389,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
* NOTE: we cannot touch the fib after this * NOTE: we cannot touch the fib after this
* call, because it may have been deallocated. * call, because it may have been deallocated.
*/ */
fib->flags = 0; fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
fib->callback(fib->callback_data, fib); fib->callback(fib->callback_data, fib);
} else { } else {
unsigned long flagv; unsigned long flagv;
......
...@@ -1166,7 +1166,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, ...@@ -1166,7 +1166,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) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL); aac->fibs = kzalloc(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);
......
...@@ -56,21 +56,10 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) ...@@ -56,21 +56,10 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
if (bellbits & PmDoorBellResponseSent) { if (bellbits & PmDoorBellResponseSent) {
bellbits = PmDoorBellResponseSent; bellbits = PmDoorBellResponseSent;
/* handle async. status */ /* handle async. status */
src_writel(dev, MUnit.ODR_C, bellbits);
src_readl(dev, MUnit.ODR_C);
our_interrupt = 1; our_interrupt = 1;
index = dev->host_rrq_idx; index = dev->host_rrq_idx;
if (dev->host_rrq[index] == 0) {
u32 old_index = index;
/* adjust index */
do {
index++;
if (index == dev->scsi_host_ptr->can_queue +
AAC_NUM_MGT_FIB)
index = 0;
if (dev->host_rrq[index] != 0)
break;
} while (index != old_index);
dev->host_rrq_idx = index;
}
for (;;) { for (;;) {
isFastResponse = 0; isFastResponse = 0;
/* remove toggle bit (31) */ /* remove toggle bit (31) */
...@@ -93,6 +82,8 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) ...@@ -93,6 +82,8 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
} else { } else {
bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
if (bellbits_shifted & DoorBellAifPending) { if (bellbits_shifted & DoorBellAifPending) {
src_writel(dev, MUnit.ODR_C, bellbits);
src_readl(dev, MUnit.ODR_C);
our_interrupt = 1; our_interrupt = 1;
/* handle AIF */ /* handle AIF */
aac_intr_normal(dev, 0, 2, 0, NULL); aac_intr_normal(dev, 0, 2, 0, NULL);
...@@ -100,6 +91,13 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) ...@@ -100,6 +91,13 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
unsigned long sflags; unsigned long sflags;
struct list_head *entry; struct list_head *entry;
int send_it = 0; int send_it = 0;
extern int aac_sync_mode;
if (!aac_sync_mode) {
src_writel(dev, MUnit.ODR_C, bellbits);
src_readl(dev, MUnit.ODR_C);
our_interrupt = 1;
}
if (dev->sync_fib) { if (dev->sync_fib) {
our_interrupt = 1; our_interrupt = 1;
...@@ -132,7 +130,6 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) ...@@ -132,7 +130,6 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
} }
if (our_interrupt) { if (our_interrupt) {
src_writel(dev, MUnit.ODR_C, bellbits);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
return IRQ_NONE; return IRQ_NONE;
...@@ -336,6 +333,9 @@ static void aac_src_start_adapter(struct aac_dev *dev) ...@@ -336,6 +333,9 @@ static void aac_src_start_adapter(struct aac_dev *dev)
{ {
struct aac_init *init; struct aac_init *init;
/* reset host_rrq_idx first */
dev->host_rrq_idx = 0;
init = dev->init; init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds()); init->HostElapsedSeconds = cpu_to_le32(get_seconds());
...@@ -397,31 +397,40 @@ static int aac_src_deliver_message(struct fib *fib) ...@@ -397,31 +397,40 @@ static int aac_src_deliver_message(struct fib *fib)
q->numpending++; q->numpending++;
spin_unlock_irqrestore(q->lock, qflags); spin_unlock_irqrestore(q->lock, qflags);
/* Calculate the amount to the fibsize bits */ if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1; /* Calculate the amount to the fibsize bits */
if (fibsize > (ALIGN32 - 1)) fibsize = (hdr_size + 127) / 128 - 1;
return -EMSGSIZE; if (fibsize > (ALIGN32 - 1))
return -EMSGSIZE;
/* New FIB header, 32-bit */
address = fib->hw_fib_pa;
fib->hw_fib_va->header.StructType = FIB_MAGIC2;
fib->hw_fib_va->header.SenderFibAddress = (u32)address;
fib->hw_fib_va->header.u.TimeStamp = 0;
BUG_ON((u32)(address >> 32) != 0L);
address |= fibsize;
} else {
/* Calculate the amount to the fibsize bits */
fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1;
if (fibsize > (ALIGN32 - 1))
return -EMSGSIZE;
/* Fill XPORT header */
pFibX = (void *)fib->hw_fib_va - sizeof(struct aac_fib_xporthdr);
pFibX->Handle = cpu_to_le32(fib->hw_fib_va->header.Handle);
pFibX->HostAddress = cpu_to_le64(fib->hw_fib_pa);
pFibX->Size = cpu_to_le32(hdr_size);
/* Fill XPORT header */ /*
pFibX = (void *)fib->hw_fib_va - sizeof(struct aac_fib_xporthdr); * The xport header has been 32-byte aligned for us so that fibsize
/* * can be masked out of this address by hardware. -- BenC
* This was stored by aac_fib_send() and it is the index into */
* dev->fibs. Not sure why we add 1 to it, but I suspect that it's address = fib->hw_fib_pa - sizeof(struct aac_fib_xporthdr);
* because it can't be zero when we pass it to the hardware. Note that if (address & (ALIGN32 - 1))
* it was stored in native endian, hence the lack of swapping. -- BenC return -EINVAL;
*/ address |= fibsize;
pFibX->Handle = cpu_to_le32(fib->hw_fib_va->header.SenderData + 1); }
pFibX->HostAddress = cpu_to_le64(fib->hw_fib_pa);
pFibX->Size = cpu_to_le32(hdr_size);
/*
* The xport header has been 32-byte aligned for us so that fibsize
* can be masked out of this address by hardware. -- BenC
*/
address = fib->hw_fib_pa - sizeof(struct aac_fib_xporthdr);
if (address & (ALIGN32 - 1))
return -EINVAL;
address |= fibsize;
src_writel(dev, MUnit.IQ_H, (address >> 32) & 0xffffffff); src_writel(dev, MUnit.IQ_H, (address >> 32) & 0xffffffff);
src_writel(dev, MUnit.IQ_L, address & 0xffffffff); src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
...@@ -764,7 +773,7 @@ int aac_srcv_init(struct aac_dev *dev) ...@@ -764,7 +773,7 @@ int aac_srcv_init(struct aac_dev *dev)
if (aac_init_adapter(dev) == NULL) if (aac_init_adapter(dev) == NULL)
goto error_iounmap; goto error_iounmap;
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1) if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2)
goto error_iounmap; goto error_iounmap;
dev->msi = aac_msi && !pci_enable_msi(dev->pdev); dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
......
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