[SCSI] aacraid: Series 7 Async. (performance) mode support
authorMahesh Rajashekhara <Mahesh_Rajashekhara@pmc-sierra.com>
Sat, 14 Jul 2012 12:48:51 +0000 (18:18 +0530)
committerJames Bottomley <JBottomley@Parallels.com>
Fri, 20 Jul 2012 07:59:04 +0000 (08:59 +0100)
- 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: Mahesh Rajashekhara <Mahesh_Rajashekhara@pmc-sierra.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commctrl.c
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/aacraid/dpcsup.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/src.c

index 52551662d1077d7188236a1ecf0ff482213ffc3c..d79457ac8beff1628787ce8b9b4c632ed0b5e77d 100644 (file)
@@ -135,6 +135,8 @@ struct inquiry_data {
 static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
 static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
 static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
+static unsigned long aac_build_sgraw2(struct scsi_cmnd *scsicmd, struct aac_raw_io2 *rio2, int sg_max);
+static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int nseg_new);
 static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
 #ifdef AAC_DETAILED_STATUS_INFO
 static char *aac_get_status_string(u32 status);
@@ -152,10 +154,14 @@ int aac_commit = -1;
 int startup_timeout = 180;
 int aif_timeout = 120;
 int aac_sync_mode;  /* Only Sync. transfer - disabled */
+int aac_convert_sgl = 1;       /* convert non-conformable s/g list - enabled */
 
 module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(aac_sync_mode, "Force sync. transfer mode"
        " 0=off, 1=on");
+module_param(aac_convert_sgl, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(aac_convert_sgl, "Convert non-conformable s/g list"
+       " 0=off, 1=on");
 module_param(nondasd, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices."
        " 0=off, 1=on");
@@ -963,25 +969,44 @@ static void io_callback(void *context, struct fib * fibptr);
 
 static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
 {
-       u16 fibsize;
-       struct aac_raw_io *readcmd;
+       struct aac_dev *dev = fib->dev;
+       u16 fibsize, command;
+
        aac_fib_init(fib);
-       readcmd = (struct aac_raw_io *) fib_data(fib);
-       readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
-       readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
-       readcmd->count = cpu_to_le32(count<<9);
-       readcmd->cid = cpu_to_le16(scmd_id(cmd));
-       readcmd->flags = cpu_to_le16(IO_TYPE_READ);
-       readcmd->bpTotal = 0;
-       readcmd->bpComplete = 0;
+       if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) {
+               struct aac_raw_io2 *readcmd2;
+               readcmd2 = (struct aac_raw_io2 *) fib_data(fib);
+               memset(readcmd2, 0, sizeof(struct aac_raw_io2));
+               readcmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff));
+               readcmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+               readcmd2->byteCount = cpu_to_le32(count<<9);
+               readcmd2->cid = cpu_to_le16(scmd_id(cmd));
+               readcmd2->flags = cpu_to_le16(RIO2_IO_TYPE_READ);
+               aac_build_sgraw2(cmd, readcmd2, dev->scsi_host_ptr->sg_tablesize);
+               command = ContainerRawIo2;
+               fibsize = sizeof(struct aac_raw_io2) +
+                       ((le32_to_cpu(readcmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
+       } else {
+               struct aac_raw_io *readcmd;
+               readcmd = (struct aac_raw_io *) fib_data(fib);
+               readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+               readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+               readcmd->count = cpu_to_le32(count<<9);
+               readcmd->cid = cpu_to_le16(scmd_id(cmd));
+               readcmd->flags = cpu_to_le16(RIO_TYPE_READ);
+               readcmd->bpTotal = 0;
+               readcmd->bpComplete = 0;
+               aac_build_sgraw(cmd, &readcmd->sg);
+               command = ContainerRawIo;
+               fibsize = sizeof(struct aac_raw_io) +
+                       ((le32_to_cpu(readcmd->sg.count)-1) * sizeof(struct sgentryraw));
+       }
 
-       aac_build_sgraw(cmd, &readcmd->sg);
-       fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
        BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
        /*
         *      Now send the Fib to the adapter
         */
-       return aac_fib_send(ContainerRawIo,
+       return aac_fib_send(command,
                          fib,
                          fibsize,
                          FsaNormal,
@@ -1052,28 +1077,50 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32
 
 static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
 {
-       u16 fibsize;
-       struct aac_raw_io *writecmd;
+       struct aac_dev *dev = fib->dev;
+       u16 fibsize, command;
+
        aac_fib_init(fib);
-       writecmd = (struct aac_raw_io *) fib_data(fib);
-       writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
-       writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
-       writecmd->count = cpu_to_le32(count<<9);
-       writecmd->cid = cpu_to_le16(scmd_id(cmd));
-       writecmd->flags = (fua && ((aac_cache & 5) != 1) &&
-         (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
-               cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) :
-               cpu_to_le16(IO_TYPE_WRITE);
-       writecmd->bpTotal = 0;
-       writecmd->bpComplete = 0;
-
-       aac_build_sgraw(cmd, &writecmd->sg);
-       fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
+       if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) {
+               struct aac_raw_io2 *writecmd2;
+               writecmd2 = (struct aac_raw_io2 *) fib_data(fib);
+               memset(writecmd2, 0, sizeof(struct aac_raw_io2));
+               writecmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff));
+               writecmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+               writecmd2->byteCount = cpu_to_le32(count<<9);
+               writecmd2->cid = cpu_to_le16(scmd_id(cmd));
+               writecmd2->flags = (fua && ((aac_cache & 5) != 1) &&
+                                                  (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
+                       cpu_to_le16(RIO2_IO_TYPE_WRITE|RIO2_IO_SUREWRITE) :
+                       cpu_to_le16(RIO2_IO_TYPE_WRITE);
+               aac_build_sgraw2(cmd, writecmd2, dev->scsi_host_ptr->sg_tablesize);
+               command = ContainerRawIo2;
+               fibsize = sizeof(struct aac_raw_io2) +
+                       ((le32_to_cpu(writecmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
+       } else {
+               struct aac_raw_io *writecmd;
+               writecmd = (struct aac_raw_io *) fib_data(fib);
+               writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+               writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+               writecmd->count = cpu_to_le32(count<<9);
+               writecmd->cid = cpu_to_le16(scmd_id(cmd));
+               writecmd->flags = (fua && ((aac_cache & 5) != 1) &&
+                                                  (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
+                       cpu_to_le16(RIO_TYPE_WRITE|RIO_SUREWRITE) :
+                       cpu_to_le16(RIO_TYPE_WRITE);
+               writecmd->bpTotal = 0;
+               writecmd->bpComplete = 0;
+               aac_build_sgraw(cmd, &writecmd->sg);
+               command = ContainerRawIo;
+               fibsize = sizeof(struct aac_raw_io) +
+                       ((le32_to_cpu(writecmd->sg.count)-1) * sizeof (struct sgentryraw));
+       }
+
        BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
        /*
         *      Now send the Fib to the adapter
         */
-       return aac_fib_send(ContainerRawIo,
+       return aac_fib_send(command,
                          fib,
                          fibsize,
                          FsaNormal,
@@ -1492,8 +1539,6 @@ int aac_get_adapter_info(struct aac_dev* dev)
                        dev->a_ops.adapter_write = aac_write_block;
                }
                dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
-               if (dev->adapter_info.options & AAC_OPT_NEW_COMM_TYPE1)
-                       dev->adapter_info.options |= AAC_OPT_NEW_COMM;
                if (!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
                        /*
                         * Worst case size that could cause sg overflow when
@@ -2616,12 +2661,18 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
        srbreply = (struct aac_srb_reply *) fib_data(fibptr);
 
        scsicmd->sense_buffer[0] = '\0';  /* Initialize sense valid flag to false */
-       /*
-        *      Calculate resid for sg
-        */
 
-       scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
-                      - le32_to_cpu(srbreply->data_xfer_length));
+       if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) {
+               /* fast response */
+               srbreply->srb_status = cpu_to_le32(SRB_STATUS_SUCCESS);
+               srbreply->scsi_status = cpu_to_le32(SAM_STAT_GOOD);
+       } else {
+               /*
+                *      Calculate resid for sg
+                */
+               scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
+                                  - le32_to_cpu(srbreply->data_xfer_length));
+       }
 
        scsi_dma_unmap(scsicmd);
 
@@ -2954,6 +3005,118 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw*
        return byte_count;
 }
 
+static unsigned long aac_build_sgraw2(struct scsi_cmnd *scsicmd, struct aac_raw_io2 *rio2, int sg_max)
+{
+       unsigned long byte_count = 0;
+       int nseg;
+
+       nseg = scsi_dma_map(scsicmd);
+       BUG_ON(nseg < 0);
+       if (nseg) {
+               struct scatterlist *sg;
+               int i, conformable = 0;
+               u32 min_size = PAGE_SIZE, cur_size;
+
+               scsi_for_each_sg(scsicmd, sg, nseg, i) {
+                       int count = sg_dma_len(sg);
+                       u64 addr = sg_dma_address(sg);
+
+                       BUG_ON(i >= sg_max);
+                       rio2->sge[i].addrHigh = cpu_to_le32((u32)(addr>>32));
+                       rio2->sge[i].addrLow = cpu_to_le32((u32)(addr & 0xffffffff));
+                       cur_size = cpu_to_le32(count);
+                       rio2->sge[i].length = cur_size;
+                       rio2->sge[i].flags = 0;
+                       if (i == 0) {
+                               conformable = 1;
+                               rio2->sgeFirstSize = cur_size;
+                       } else if (i == 1) {
+                               rio2->sgeNominalSize = cur_size;
+                               min_size = cur_size;
+                       } else if ((i+1) < nseg && cur_size != rio2->sgeNominalSize) {
+                               conformable = 0;
+                               if (cur_size < min_size)
+                                       min_size = cur_size;
+                       }
+                       byte_count += count;
+               }
+
+               /* hba wants the size to be exact */
+               if (byte_count > scsi_bufflen(scsicmd)) {
+                       u32 temp = le32_to_cpu(rio2->sge[i-1].length) -
+                               (byte_count - scsi_bufflen(scsicmd));
+                       rio2->sge[i-1].length = cpu_to_le32(temp);
+                       byte_count = scsi_bufflen(scsicmd);
+               }
+
+               rio2->sgeCnt = cpu_to_le32(nseg);
+               rio2->flags |= cpu_to_le16(RIO2_SG_FORMAT_IEEE1212);
+               /* not conformable: evaluate required sg elements */
+               if (!conformable) {
+                       int j, nseg_new = nseg, err_found;
+                       for (i = min_size / PAGE_SIZE; i >= 1; --i) {
+                               err_found = 0;
+                               nseg_new = 2;
+                               for (j = 1; j < nseg - 1; ++j) {
+                                       if (rio2->sge[j].length % (i*PAGE_SIZE)) {
+                                               err_found = 1;
+                                               break;
+                                       }
+                                       nseg_new += (rio2->sge[j].length / (i*PAGE_SIZE));
+                               }
+                               if (!err_found)
+                                       break;
+                       }
+                       if (i > 0 && nseg_new <= sg_max)
+                               aac_convert_sgraw2(rio2, i, nseg, nseg_new);
+               } else
+                       rio2->flags |= cpu_to_le16(RIO2_SGL_CONFORMANT);
+
+               /* Check for command underflow */
+               if (scsicmd->underflow && (byte_count < scsicmd->underflow)) {
+                       printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+                                       byte_count, scsicmd->underflow);
+               }
+       }
+
+       return byte_count;
+}
+
+static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int nseg_new)
+{
+       struct sge_ieee1212 *sge;
+       int i, j, pos;
+       u32 addr_low;
+
+       if (aac_convert_sgl == 0)
+               return 0;
+
+       sge = kmalloc(nseg_new * sizeof(struct sge_ieee1212), GFP_ATOMIC);
+       if (sge == NULL)
+               return -1;
+
+       for (i = 1, pos = 1; i < nseg-1; ++i) {
+               for (j = 0; j < rio2->sge[i].length / (pages * PAGE_SIZE); ++j) {
+                       addr_low = rio2->sge[i].addrLow + j * pages * PAGE_SIZE;
+                       sge[pos].addrLow = addr_low;
+                       sge[pos].addrHigh = rio2->sge[i].addrHigh;
+                       if (addr_low < rio2->sge[i].addrLow)
+                               sge[pos].addrHigh++;
+                       sge[pos].length = pages * PAGE_SIZE;
+                       sge[pos].flags = 0;
+                       pos++;
+               }
+       }
+       sge[pos] = rio2->sge[nseg-1];
+       memcpy(&rio2->sge[1], &sge[1], (nseg_new-1)*sizeof(struct sge_ieee1212));
+
+       kfree(sge);
+       rio2->sgeCnt = cpu_to_le32(nseg_new);
+       rio2->flags |= cpu_to_le16(RIO2_SGL_CONFORMANT);
+       rio2->sgeNominalSize = pages * PAGE_SIZE;
+       return 0;
+}
+
 #ifdef AAC_DETAILED_STATUS_INFO
 
 struct aac_srb_status_info {
index 6ab32db73bb6fc140ff88b43745cfe393ce1a91f..9e933a88a8bc5aaa95b8fc929ec51395a53495e1 100644 (file)
@@ -12,7 +12,7 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 28900
+# define AAC_DRIVER_BUILD 29800
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS 32
@@ -100,6 +100,13 @@ struct user_sgentryraw {
        u32             flags;  /* reserved for F/W use */
 };
 
+struct sge_ieee1212 {
+       u32     addrLow;
+       u32     addrHigh;
+       u32     length;
+       u32     flags;
+};
+
 /*
  *     SGMAP
  *
@@ -270,6 +277,8 @@ enum aac_queue_types {
  */
 
 #define                FIB_MAGIC       0x0001
+#define                FIB_MAGIC2      0x0004
+#define                FIB_MAGIC2_64   0x0005
 
 /*
  *     Define the priority levels the FSA communication routines support.
@@ -296,22 +305,20 @@ struct aac_fibhdr {
        __le32 XferState;       /* Current transfer state for this CCB */
        __le16 Command;         /* Routing information for the destination */
        u8 StructType;          /* Type FIB */
-       u8 Flags;               /* Flags for FIB */
+       u8 Unused;              /* Unused */
        __le16 Size;            /* Size of this FIB in bytes */
        __le16 SenderSize;      /* Size of the FIB in the sender
                                   (for response sizing) */
        __le32 SenderFibAddress;  /* Host defined data in the FIB */
-       __le32 ReceiverFibAddress;/* Logical address of this FIB for
-                                    the adapter */
-       u32 SenderData;         /* Place holder for the sender to store data */
        union {
-               struct {
-                   __le32 _ReceiverTimeStart;  /* Timestamp for
-                                                  receipt of fib */
-                   __le32 _ReceiverTimeDone;   /* Timestamp for
-                                                  completion of fib */
-               } _s;
-       } _u;
+               __le32 ReceiverFibAddress;/* Logical address of this FIB for
+                                    the adapter (old) */
+               __le32 SenderFibAddressHigh;/* upper 32bit of phys. FIB address */
+               __le32 TimeStamp;       /* otherwise timestamp for FW internal use */
+       } u;
+       u32 Handle;             /* FIB handle used for MSGU commnunication */
+       u32 Previous;           /* FW internal use */
+       u32 Next;               /* FW internal use */
 };
 
 struct hw_fib {
@@ -361,6 +368,7 @@ struct hw_fib {
 #define                ContainerCommand                500
 #define                ContainerCommand64              501
 #define                ContainerRawIo                  502
+#define                ContainerRawIo2                 503
 /*
  *     Scsi Port commands (scsi passthrough)
  */
@@ -417,6 +425,7 @@ enum fib_xfer_state {
 #define ADAPTER_INIT_STRUCT_REVISION           3
 #define ADAPTER_INIT_STRUCT_REVISION_4         4 // rocket science
 #define ADAPTER_INIT_STRUCT_REVISION_6         6 /* PMC src */
+#define ADAPTER_INIT_STRUCT_REVISION_7         7 /* Denali */
 
 struct aac_init
 {
@@ -441,7 +450,9 @@ struct aac_init
 #define INITFLAGS_NEW_COMM_SUPPORTED   0x00000001
 #define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010
 #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  MaxIoSize;      /* largest I/O command */
        __le32  MaxFibSize;     /* largest FIB to adapter */
@@ -1124,6 +1135,7 @@ struct aac_dev
 #      define AAC_COMM_PRODUCER 0
 #      define AAC_COMM_MESSAGE  1
 #      define AAC_COMM_MESSAGE_TYPE1   3
+#      define AAC_COMM_MESSAGE_TYPE2   4
        u8                      raw_io_interface;
        u8                      raw_io_64;
        u8                      printf_enabled;
@@ -1182,6 +1194,7 @@ struct aac_dev
 #define FIB_CONTEXT_FLAG_TIMED_OUT             (0x00000001)
 #define FIB_CONTEXT_FLAG                       (0x00000002)
 #define FIB_CONTEXT_FLAG_WAIT                  (0x00000004)
+#define FIB_CONTEXT_FLAG_FASTRESP              (0x00000008)
 
 /*
  *     Define the command values
@@ -1288,6 +1301,22 @@ struct aac_dev
 #define CMDATA_SYNCH           4
 #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
 {
        __le32          command;
@@ -1332,9 +1361,6 @@ struct aac_write64
        __le32          block;
        __le16          pad;
        __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 aac_write_reply
@@ -1355,6 +1381,22 @@ struct aac_raw_io
        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
 struct aac_synchronize {
        __le32          command;        /* VM_ContainerConfig */
index 0bd38da4ada0e7cfc9e112cefdd693b039efc54c..1ef041bc60c89c17b9f130124e9e1273995adb11 100644 (file)
@@ -498,6 +498,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
                return -ENOMEM;
        }
        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);
 
index 8e4b525b1b790b0f7bc88fab1612b1cffbd5b7cb..8e5d3be1612712566b084453ad747c8d5582525d 100644 (file)
@@ -58,7 +58,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
        dma_addr_t phys;
        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
                        + AAC_NUM_MGT_FIB) * sizeof(u32);
        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
        dev->comm_phys = phys;
        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_pa = phys + fibsize;
                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
        else
                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) {
                init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
                dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
        } else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
                init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6);
-               init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_TYPE1_SUPPORTED);
-               dprintk((KERN_WARNING
-                       "aacraid: New Comm Interface type1 enabled\n"));
+               init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
+                       INITFLAGS_NEW_COMM_TYPE1_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));
+               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
@@ -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))) {
                                /* driver supports TYPE1 (Tupelo) */
                                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)) ||
-                                 (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3)) ||
-                                 (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE2))) {
-                                       /* driver doesn't support TYPE2 (Series7), TYPE3 and TYPE4 */
-                                       /* switch to sync. mode */
-                                       dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
-                                       dev->sync_mode = 1;
+                                 (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3))) {
+                               /* driver doesn't TYPE3 and TYPE4 */
+                               /* switch to sync. mode */
+                               dev->comm_interface = AAC_COMM_MESSAGE_TYPE2;
+                               dev->sync_mode = 1;
                        }
                }
                if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
index 906a5013edae4a87d97e0e57d719235fc9830520..1be0776a80c4b00e73b8a914378d1d8c8c79ba58 100644 (file)
@@ -136,6 +136,7 @@ int aac_fib_setup(struct aac_dev * dev)
                i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
                i++, fibptr++)
        {
+               fibptr->flags = 0;
                fibptr->dev = dev;
                fibptr->hw_fib_va = hw_fib;
                fibptr->data = (void *) fibptr->hw_fib_va->data;
@@ -240,11 +241,11 @@ void aac_fib_init(struct fib *fibptr)
 {
        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.Size = cpu_to_le16(fibptr->dev->max_fib_size);
        hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
-       hw_fib->header.SenderFibAddress = 0; /* Filled in later if needed */
-       hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
+       hw_fib->header.u.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
        hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size);
 }
 
@@ -259,7 +260,6 @@ void aac_fib_init(struct fib *fibptr)
 static void fib_dealloc(struct fib * fibptr)
 {
        struct hw_fib *hw_fib = fibptr->hw_fib_va;
-       BUG_ON(hw_fib->header.StructType != FIB_MAGIC);
        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
                entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size));
                entry->addr = hw_fib->header.SenderFibAddress;
                        /* 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;
        }
        /*
@@ -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.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
         *      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,
         */
        hw_fib->header.Command = cpu_to_le16(command);
        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
         */
@@ -711,7 +710,8 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
        unsigned long nointr = 0;
        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);
                return 0;
        }
@@ -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 (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)
                        kfree(hw_fib);
                return -EINVAL;
@@ -786,7 +788,9 @@ int aac_fib_complete(struct fib *fibptr)
         *      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;
        /*
         *      This block completes a cdb which orginated on the host and we
index f0c66a80ad13ef12cd183d46c28b5c3bd8cb7b8b..d81b2810f0f7d507fc86fa536d24309a83147316 100644 (file)
@@ -101,6 +101,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
                         */
                        *(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
                        hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
+                       fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
                }
 
                FIB_COUNTER_INCREMENT(aac_config.FibRecved);
@@ -121,7 +122,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
                         *      NOTE:  we cannot touch the fib after this
                         *          call, because it may have been deallocated.
                         */
-                       fib->flags = 0;
+                       fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
                        fib->callback(fib->callback_data, fib);
                } else {
                        unsigned long flagv;
@@ -367,6 +368,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
                         */
                        *(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
                        hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
+                       fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
                }
 
                FIB_COUNTER_INCREMENT(aac_config.FibRecved);
@@ -387,7 +389,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
                         *      NOTE:  we cannot touch the fib after this
                         *          call, because it may have been deallocated.
                         */
-                       fib->flags = 0;
+                       fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
                        fib->callback(fib->callback_data, fib);
                } else {
                        unsigned long flagv;
index 2be612b0caa5dc7cfabb3d15bb0a01c2ca0e54d2..7199534cd07dba461f80d1dcde707ec4bda7fe4d 100644 (file)
@@ -1166,7 +1166,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
        aac->cardtype = index;
        INIT_LIST_HEAD(&aac->entry);
 
-       aac->fibs = kmalloc(sizeof(struct fib) * (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)
                goto out_free_host;
        spin_lock_init(&aac->fib_lock);
index 0fb1f5507cd86c3f34ab605f6a72f05d7c6695f6..3b021ec63255469aaac381f99cfcb54fb296887d 100644 (file)
@@ -56,21 +56,10 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
        if (bellbits & PmDoorBellResponseSent) {
                bellbits = PmDoorBellResponseSent;
                /* handle async. status */
+               src_writel(dev, MUnit.ODR_C, bellbits);
+               src_readl(dev, MUnit.ODR_C);
                our_interrupt = 1;
                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 (;;) {
                        isFastResponse = 0;
                        /* remove toggle bit (31) */
@@ -93,6 +82,8 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
        } else {
                bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
                if (bellbits_shifted & DoorBellAifPending) {
+                       src_writel(dev, MUnit.ODR_C, bellbits);
+                       src_readl(dev, MUnit.ODR_C);
                        our_interrupt = 1;
                        /* handle AIF */
                        aac_intr_normal(dev, 0, 2, 0, NULL);
@@ -100,6 +91,13 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
                        unsigned long sflags;
                        struct list_head *entry;
                        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) {
                                our_interrupt = 1;
@@ -132,7 +130,6 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
        }
 
        if (our_interrupt) {
-               src_writel(dev, MUnit.ODR_C, bellbits);
                return IRQ_HANDLED;
        }
        return IRQ_NONE;
@@ -336,6 +333,9 @@ static void aac_src_start_adapter(struct aac_dev *dev)
 {
        struct aac_init *init;
 
+        /* reset host_rrq_idx first */
+       dev->host_rrq_idx = 0;
+
        init = dev->init;
        init->HostElapsedSeconds = cpu_to_le32(get_seconds());
 
@@ -397,31 +397,40 @@ static int aac_src_deliver_message(struct fib *fib)
        q->numpending++;
        spin_unlock_irqrestore(q->lock, qflags);
 
-       /* Calculate the amount to the fibsize bits */
-       fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1;
-       if (fibsize > (ALIGN32 - 1))
-               return -EMSGSIZE;
+       if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
+               /* Calculate the amount to the fibsize bits */
+               fibsize = (hdr_size + 127) / 128 - 1;
+               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);
-       /*
-        * 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
-        * because it can't be zero when we pass it to the hardware. Note that
-        * it was stored in native endian, hence the lack of swapping. -- BenC
-        */
-       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;
+       }
 
-       /*
-        * 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_L, address & 0xffffffff);
 
@@ -764,7 +773,7 @@ int aac_srcv_init(struct aac_dev *dev)
 
        if (aac_init_adapter(dev) == NULL)
                goto error_iounmap;
-       if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
+       if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2)
                goto error_iounmap;
        dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
        if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
This page took 0.040955 seconds and 5 git commands to generate.