diff options
Diffstat (limited to 'drivers/scsi/aacraid')
| -rw-r--r-- | drivers/scsi/aacraid/aachba.c | 312 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/aacraid.h | 114 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/commctrl.c | 8 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/comminit.c | 76 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/commsup.c | 60 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/dpcsup.c | 6 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/linit.c | 62 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/nark.c | 4 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/rkt.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/rx.c | 14 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/sa.c | 8 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/src.c | 414 |
12 files changed, 849 insertions, 231 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 409f5805bdd..681434e2dfe 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -132,9 +132,13 @@ struct inquiry_data { * M O D U L E G L O B A L S */ -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 long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *sgmap); +static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg); +static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg); +static 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); @@ -151,7 +155,15 @@ int aac_msi; 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"); @@ -959,25 +971,50 @@ 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; + long ret; + 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); + ret = aac_build_sgraw2(cmd, readcmd2, + dev->scsi_host_ptr->sg_tablesize); + if (ret < 0) + return ret; + 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; + ret = aac_build_sgraw(cmd, &readcmd->sg); + if (ret < 0) + return ret; + 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, @@ -990,6 +1027,8 @@ static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u { u16 fibsize; struct aac_read64 *readcmd; + long ret; + aac_fib_init(fib); readcmd = (struct aac_read64 *) fib_data(fib); readcmd->command = cpu_to_le32(VM_CtHostRead64); @@ -999,7 +1038,9 @@ static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u readcmd->pad = 0; readcmd->flags = 0; - aac_build_sg64(cmd, &readcmd->sg); + ret = aac_build_sg64(cmd, &readcmd->sg); + if (ret < 0) + return ret; fibsize = sizeof(struct aac_read64) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentry64)); @@ -1021,6 +1062,8 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 { u16 fibsize; struct aac_read *readcmd; + long ret; + aac_fib_init(fib); readcmd = (struct aac_read *) fib_data(fib); readcmd->command = cpu_to_le32(VM_CtBlockRead); @@ -1028,7 +1071,9 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); readcmd->count = cpu_to_le32(count * 512); - aac_build_sg(cmd, &readcmd->sg); + ret = aac_build_sg(cmd, &readcmd->sg); + if (ret < 0) + return ret; fibsize = sizeof(struct aac_read) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentry)); @@ -1048,28 +1093,56 @@ 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; + long ret; + 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); + ret = aac_build_sgraw2(cmd, writecmd2, + dev->scsi_host_ptr->sg_tablesize); + if (ret < 0) + return ret; + 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; + ret = aac_build_sgraw(cmd, &writecmd->sg); + if (ret < 0) + return ret; + 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, @@ -1082,6 +1155,8 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, { u16 fibsize; struct aac_write64 *writecmd; + long ret; + aac_fib_init(fib); writecmd = (struct aac_write64 *) fib_data(fib); writecmd->command = cpu_to_le32(VM_CtHostWrite64); @@ -1091,7 +1166,9 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, writecmd->pad = 0; writecmd->flags = 0; - aac_build_sg64(cmd, &writecmd->sg); + ret = aac_build_sg64(cmd, &writecmd->sg); + if (ret < 0) + return ret; fibsize = sizeof(struct aac_write64) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentry64)); @@ -1113,6 +1190,8 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 { u16 fibsize; struct aac_write *writecmd; + long ret; + aac_fib_init(fib); writecmd = (struct aac_write *) fib_data(fib); writecmd->command = cpu_to_le32(VM_CtBlockWrite); @@ -1122,7 +1201,9 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 writecmd->sg.count = cpu_to_le32(1); /* ->stable is not used - it did mean which type of write */ - aac_build_sg(cmd, &writecmd->sg); + ret = aac_build_sg(cmd, &writecmd->sg); + if (ret < 0) + return ret; fibsize = sizeof(struct aac_write) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentry)); @@ -1184,8 +1265,11 @@ static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd) { u16 fibsize; struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); + long ret; - aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg); + ret = aac_build_sg64(cmd, (struct sgmap64 *) &srbcmd->sg); + if (ret < 0) + return ret; srbcmd->count = cpu_to_le32(scsi_bufflen(cmd)); memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); @@ -1212,8 +1296,11 @@ static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd) { u16 fibsize; struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); + long ret; - aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg); + ret = aac_build_sg(cmd, (struct sgmap *)&srbcmd->sg); + if (ret < 0) + return ret; srbcmd->count = cpu_to_le32(scsi_bufflen(cmd)); memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); @@ -1488,8 +1575,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 @@ -2612,12 +2697,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); @@ -2815,7 +2906,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) return -1; } -static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg) +static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *psg) { struct aac_dev *dev; unsigned long byte_count = 0; @@ -2828,7 +2919,8 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg) psg->sg[0].count = 0; nseg = scsi_dma_map(scsicmd); - BUG_ON(nseg < 0); + if (nseg < 0) + return nseg; if (nseg) { struct scatterlist *sg; int i; @@ -2857,7 +2949,7 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg) } -static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg) +static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg) { struct aac_dev *dev; unsigned long byte_count = 0; @@ -2872,7 +2964,8 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p psg->sg[0].count = 0; nseg = scsi_dma_map(scsicmd); - BUG_ON(nseg < 0); + if (nseg < 0) + return nseg; if (nseg) { struct scatterlist *sg; int i; @@ -2902,7 +2995,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p return byte_count; } -static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg) +static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg) { unsigned long byte_count = 0; int nseg; @@ -2917,7 +3010,8 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg->sg[0].flags = 0; nseg = scsi_dma_map(scsicmd); - BUG_ON(nseg < 0); + if (nseg < 0) + return nseg; if (nseg) { struct scatterlist *sg; int i; @@ -2950,6 +3044,120 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* return byte_count; } +static 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); + if (nseg < 0) + return nseg; + 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 { diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index ffb587817ef..eaaf8705a5f 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,13 +12,13 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 28000 +# define AAC_DRIVER_BUILD 30300 # define AAC_DRIVER_BRANCH "-ms" #endif #define MAXIMUM_NUM_CONTAINERS 32 #define AAC_NUM_MGT_FIB 8 -#define AAC_NUM_IO_FIB (512 - AAC_NUM_MGT_FIB) +#define AAC_NUM_IO_FIB (1024 - AAC_NUM_MGT_FIB) #define AAC_NUM_FIB (AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB) #define AAC_MAX_LUN (8) @@ -36,6 +36,10 @@ #define CONTAINER_TO_ID(cont) (cont) #define CONTAINER_TO_LUN(cont) (0) +#define PMC_DEVICE_S7 0x28c +#define PMC_DEVICE_S8 0x28d +#define PMC_DEVICE_S9 0x28f + #define aac_phys_to_logical(x) ((x)+1) #define aac_logical_to_phys(x) ((x)?(x)-1:0) @@ -100,6 +104,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 +281,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 +309,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 +372,7 @@ struct hw_fib { #define ContainerCommand 500 #define ContainerCommand64 501 #define ContainerRawIo 502 +#define ContainerRawIo2 503 /* * Scsi Port commands (scsi passthrough) */ @@ -417,6 +429,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 +454,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 */ @@ -756,8 +771,16 @@ struct src_mu_registers { struct src_registers { struct src_mu_registers MUnit; /* 00h - c7h */ - __le32 reserved1[130790]; /* c8h - 7fc5fh */ - struct src_inbound IndexRegs; /* 7fc60h */ + union { + struct { + __le32 reserved1[130790]; /* c8h - 7fc5fh */ + struct src_inbound IndexRegs; /* 7fc60h */ + } tupelo; + struct { + __le32 reserved1[974]; /* c8h - fffh */ + struct src_inbound IndexRegs; /* 1000h */ + } denali; + } u; }; #define src_readb(AEP, CSR) readb(&((AEP)->regs.src.bar0->CSR)) @@ -999,6 +1022,10 @@ struct aac_bus_info_response { #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) #define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28) +#define AAC_OPT_NEW_COMM_TYPE2 cpu_to_le32(1<<29) +#define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) +#define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31) + struct aac_dev { @@ -1040,10 +1067,11 @@ struct aac_dev struct adapter_ops a_ops; unsigned long fsrev; /* Main driver's revision number */ - unsigned long dbg_base; /* address of UART + resource_size_t base_start; /* main IO base */ + resource_size_t dbg_base; /* address of UART * debug buffer */ - unsigned base_size, dbg_size; /* Size of + resource_size_t base_size, dbg_size; /* Size of * mapped in region */ struct aac_init *init; /* Holds initialization info to communicate with adapter */ @@ -1076,6 +1104,8 @@ struct aac_dev # define AAC_MIN_FOOTPRINT_SIZE 8192 # define AAC_MIN_SRC_BAR0_SIZE 0x400000 # define AAC_MIN_SRC_BAR1_SIZE 0x800 +# define AAC_MIN_SRCV_BAR0_SIZE 0x100000 +# define AAC_MIN_SRCV_BAR1_SIZE 0x400 #endif union { @@ -1109,6 +1139,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; @@ -1116,7 +1147,10 @@ struct aac_dev u8 msi; int management_fib_count; spinlock_t manage_lock; - + spinlock_t sync_lock; + int sync_mode; + struct fib *sync_fib; + struct list_head sync_fib_list; }; #define aac_adapter_interrupt(dev) \ @@ -1163,6 +1197,8 @@ 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 @@ -1269,6 +1305,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; @@ -1313,9 +1365,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 @@ -1336,6 +1385,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 */ @@ -1853,6 +1918,10 @@ extern struct aac_common aac_config; #define MONITOR_PANIC 0x00000020 #define KERNEL_UP_AND_RUNNING 0x00000080 #define KERNEL_PANIC 0x00000100 +#define FLASH_UPD_PENDING 0x00002000 +#define FLASH_UPD_SUCCESS 0x00004000 +#define FLASH_UPD_FAILED 0x00008000 +#define FWUPD_TIMEOUT (5 * 60) /* * Doorbell bit defines @@ -1970,6 +2039,7 @@ int aac_rkt_init(struct aac_dev *dev); int aac_nark_init(struct aac_dev *dev); int aac_sa_init(struct aac_dev *dev); int aac_src_init(struct aac_dev *dev); +int aac_srcv_init(struct aac_dev *dev); int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify); unsigned int aac_response_normal(struct aac_queue * q); unsigned int aac_command_normal(struct aac_queue * q); diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 0bd38da4ada..fbcd48d0bfc 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -318,7 +318,8 @@ return_fib: kthread_stop(dev->thread); ssleep(1); dev->aif_thread = 0; - dev->thread = kthread_run(aac_command_thread, dev, dev->name); + dev->thread = kthread_run(aac_command_thread, dev, + "%s", dev->name); ssleep(1); } if (f.wait) { @@ -498,6 +499,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); @@ -508,7 +511,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) goto cleanup; } - if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) { + if ((fibsize < (sizeof(struct user_aac_srb) - sizeof(struct user_sgentry))) || + (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))) { rcode = -EINVAL; goto cleanup; } diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 7ac8fdb5577..177b094c779 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -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 = (u32)((u64)dev->host_rrq_pa >> 32); - init->HostRRQ_AddrLow = (u32)(dev->host_rrq_pa & 0xffffffff); - /* * Increment the base address by the amount already used @@ -206,7 +214,7 @@ int aac_send_shutdown(struct aac_dev * dev) cmd = (struct aac_close *) fib_data(fibctx); cmd->command = cpu_to_le32(VM_CloseAll); - cmd->cid = cpu_to_le32(0xffffffff); + cmd->cid = cpu_to_le32(0xfffffffe); status = aac_fib_send(ContainerCommand, fibctx, @@ -325,12 +333,14 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) { u32 status[5]; struct Scsi_Host * host = dev->scsi_host_ptr; + extern int aac_sync_mode; /* * Check the preferred comm settings, defaults from template. */ dev->management_fib_count = 0; spin_lock_init(&dev->manage_lock); + spin_lock_init(&dev->sync_lock); dev->max_fib_size = sizeof(struct hw_fib); dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size - sizeof(struct aac_fibhdr) @@ -344,13 +354,23 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) (status[0] == 0x00000001)) { if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) dev->raw_io_64 = 1; - if (dev->a_ops.adapter_comm) { - if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1)) { - dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; - dev->raw_io_interface = 1; - } else if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM)) { + dev->sync_mode = aac_sync_mode; + if (dev->a_ops.adapter_comm && + (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM))) { dev->comm_interface = AAC_COMM_MESSAGE; dev->raw_io_interface = 1; + 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))) { + /* 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) && @@ -384,7 +404,13 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) dev->max_fib_size = status[1] & 0xFFE0; host->sg_tablesize = status[2] >> 16; dev->sg_tablesize = status[2] & 0xFFFF; - host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB; + if (dev->pdev->device == PMC_DEVICE_S7 || + dev->pdev->device == PMC_DEVICE_S8 || + dev->pdev->device == PMC_DEVICE_S9) + host->can_queue = ((status[3] >> 16) ? (status[3] >> 16) : + (status[3] & 0xFFFF)) - AAC_NUM_MGT_FIB; + else + host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB; dev->max_num_aif = status[4] & 0xFFFF; /* * NOTE: @@ -432,6 +458,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) } } + if (host->can_queue > AAC_NUM_IO_FIB) + host->can_queue = AAC_NUM_IO_FIB; + /* * Ok now init the communication subsystem */ @@ -455,6 +484,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) } INIT_LIST_HEAD(&dev->fib_list); + INIT_LIST_HEAD(&dev->sync_fib_list); return dev; } diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index e5f2d7d9002..cab190af634 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -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; } /* @@ -416,6 +416,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, unsigned long flags = 0; unsigned long qflags; unsigned long mflags = 0; + unsigned long sflags = 0; if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned))) @@ -449,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 @@ -459,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 */ @@ -512,6 +512,31 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, spin_lock_irqsave(&fibptr->event_lock, flags); } + if (dev->sync_mode) { + if (wait) + spin_unlock_irqrestore(&fibptr->event_lock, flags); + spin_lock_irqsave(&dev->sync_lock, sflags); + if (dev->sync_fib) { + list_add_tail(&fibptr->fiblink, &dev->sync_fib_list); + spin_unlock_irqrestore(&dev->sync_lock, sflags); + } else { + dev->sync_fib = fibptr; + spin_unlock_irqrestore(&dev->sync_lock, sflags); + aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, + (u32)fibptr->hw_fib_pa, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL); + } + if (wait) { + fibptr->flags |= FIB_CONTEXT_FLAG_WAIT; + if (down_interruptible(&fibptr->event_wait)) { + fibptr->flags &= ~FIB_CONTEXT_FLAG_WAIT; + return -EFAULT; + } + return 0; + } + return -EINPROGRESS; + } + if (aac_adapter_deliver(fibptr) != 0) { printk(KERN_ERR "aac_fib_send: returned -EBUSY\n"); if (wait) { @@ -538,10 +563,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, * functioning because an interrupt routing or other * hardware failure has occurred. */ - unsigned long count = 36000000L; /* 3 minutes */ + unsigned long timeout = jiffies + (180 * HZ); /* 3 minutes */ while (down_trylock(&fibptr->event_wait)) { int blink; - if (--count == 0) { + if (time_is_before_eq_jiffies(timeout)) { struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; spin_lock_irqsave(q->lock, qflags); q->numpending--; @@ -562,7 +587,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, } return -EFAULT; } - udelay(5); + /* We used to udelay() here but that absorbed + * a CPU when a timeout occured. Not very + * useful. */ + cpu_relax(); } } else if (down_interruptible(&fibptr->event_wait)) { /* Do nothing ... satisfy @@ -682,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; } @@ -695,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; @@ -757,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 @@ -1303,7 +1336,8 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) if ((retval = pci_set_dma_mask(aac->pdev, DMA_BIT_MASK(32)))) goto out; if (jafo) { - aac->thread = kthread_run(aac_command_thread, aac, aac->name); + aac->thread = kthread_run(aac_command_thread, aac, "%s", + aac->name); if (IS_ERR(aac->thread)) { retval = PTR_ERR(aac->thread); goto out; diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index f0c66a80ad1..d81b2810f0f 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -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; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 705e13e470a..4921ed19a02 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -56,7 +56,7 @@ #include "aacraid.h" -#define AAC_DRIVER_VERSION "1.1-7" +#define AAC_DRIVER_VERSION "1.2-0" #ifndef AAC_DRIVER_BRANCH #define AAC_DRIVER_BRANCH "" #endif @@ -88,13 +88,7 @@ char aac_driver_version[] = AAC_DRIVER_FULL_VERSION; * * Note: The last field is used to index into aac_drivers below. */ -#ifdef DECLARE_PCI_DEVICE_TABLE -static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = { -#elif defined(__devinitconst) -static const struct pci_device_id aac_pci_tbl[] __devinitconst = { -#else -static const struct pci_device_id aac_pci_tbl[] __devinitdata = { -#endif +static const struct pci_device_id aac_pci_tbl[] = { { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */ { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */ { 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */ @@ -162,7 +156,10 @@ static const struct pci_device_id aac_pci_tbl[] __devinitdata = { { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */ { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */ { 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */ - { 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Catch All */ + { 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Series 6 (Tupelo) */ + { 0x9005, 0x028c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 63 }, /* Adaptec PMC Series 7 (Denali) */ + { 0x9005, 0x028d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 64 }, /* Adaptec PMC Series 8 */ + { 0x9005, 0x028f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 65 }, /* Adaptec PMC Series 9 */ { 0,} }; MODULE_DEVICE_TABLE(pci, aac_pci_tbl); @@ -238,7 +235,10 @@ static struct aac_driver_ident aac_drivers[] = { { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */ { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec NEMER/ARK Catch All */ - { aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Catch All */ + { aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 6 (Tupelo) */ + { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 7 (Denali) */ + { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 8 */ + { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Series 9 */ }; /** @@ -771,6 +771,8 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) { struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg); } @@ -1079,12 +1081,22 @@ static struct scsi_host_template aac_driver_template = { #endif .use_clustering = ENABLE_CLUSTERING, .emulated = 1, + .no_write_same = 1, }; static void __aac_shutdown(struct aac_dev * aac) { - if (aac->aif_thread) + if (aac->aif_thread) { + int i; + /* Clear out events first */ + for (i = 0; i < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++) { + struct fib *fib = &aac->fibs[i]; + if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && + (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) + up(&fib->event_wait); + } kthread_stop(aac->thread); + } aac_send_shutdown(aac); aac_adapter_disable_int(aac); free_irq(aac->pdev->irq, aac); @@ -1092,8 +1104,7 @@ static void __aac_shutdown(struct aac_dev * aac) pci_disable_msi(aac->pdev); } -static int __devinit aac_probe_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { unsigned index = id->driver_data; struct Scsi_Host *shost; @@ -1102,6 +1113,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, int error = -ENODEV; int unique_id = 0; u64 dmamask; + extern int aac_sync_mode; list_for_each_entry(aac, &aac_devices, entry) { if (aac->id > unique_id) @@ -1138,11 +1150,11 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, goto out_disable_pdev; shost->irq = pdev->irq; - shost->base = pci_resource_start(pdev, 0); shost->unique_id = unique_id; shost->max_cmd_len = 16; aac = (struct aac_dev *)shost->hostdata; + aac->base_start = pci_resource_start(pdev, 0); aac->scsi_host_ptr = shost; aac->pdev = pdev; aac->name = aac_driver_template.name; @@ -1150,7 +1162,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); @@ -1162,6 +1174,21 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, if ((*aac_drivers[index].init)(aac)) goto out_unmap; + if (aac->sync_mode) { + if (aac_sync_mode) + printk(KERN_INFO "%s%d: Sync. mode enforced " + "by driver parameter. This will cause " + "a significant performance decrease!\n", + aac->name, + aac->id); + else + printk(KERN_INFO "%s%d: Async. mode not supported " + "by current driver, sync. mode enforced." + "\nPlease update driver to get full performance.\n", + aac->name, + aac->id); + } + /* * Start any kernel threads needed */ @@ -1169,6 +1196,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, if (IS_ERR(aac->thread)) { printk(KERN_ERR "aacraid: Unable to create command thread.\n"); error = PTR_ERR(aac->thread); + aac->thread = NULL; goto out_deinit; } @@ -1278,7 +1306,7 @@ static void aac_shutdown(struct pci_dev *dev) __aac_shutdown((struct aac_dev *)shost->hostdata); } -static void __devexit aac_remove_one(struct pci_dev *pdev) +static void aac_remove_one(struct pci_dev *pdev) { struct Scsi_Host *shost = pci_get_drvdata(pdev); struct aac_dev *aac = (struct aac_dev *)shost->hostdata; @@ -1309,7 +1337,7 @@ static struct pci_driver aac_pci_driver = { .name = AAC_DRIVERNAME, .id_table = aac_pci_tbl, .probe = aac_probe_one, - .remove = __devexit_p(aac_remove_one), + .remove = aac_remove_one, .shutdown = aac_shutdown, }; diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c index f397d21a0c0..6c53b1d8b2b 100644 --- a/drivers/scsi/aacraid/nark.c +++ b/drivers/scsi/aacraid/nark.c @@ -49,14 +49,14 @@ static int aac_nark_ioremap(struct aac_dev * dev, u32 size) dev->base = NULL; return 0; } - dev->scsi_host_ptr->base = pci_resource_start(dev->pdev, 2); + dev->base_start = pci_resource_start(dev->pdev, 2); dev->regs.rx = ioremap((u64)pci_resource_start(dev->pdev, 0) | ((u64)pci_resource_start(dev->pdev, 1) << 32), sizeof(struct rx_registers) - sizeof(struct rx_inbound)); dev->base = NULL; if (dev->regs.rx == NULL) return -1; - dev->base = ioremap(dev->scsi_host_ptr->base, size); + dev->base = ioremap(dev->base_start, size); if (dev->base == NULL) { iounmap(dev->regs.rx); dev->regs.rx = NULL; diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index be44de92429..7d8013feedd 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -79,7 +79,7 @@ static int aac_rkt_ioremap(struct aac_dev * dev, u32 size) iounmap(dev->regs.rkt); return 0; } - dev->base = dev->regs.rkt = ioremap(dev->scsi_host_ptr->base, size); + dev->base = dev->regs.rkt = ioremap(dev->base_start, size); if (dev->base == NULL) return -1; dev->IndexRegs = &dev->regs.rkt->IndexRegs; diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index ce530f113fd..5c6a8703f53 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -471,7 +471,7 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size) iounmap(dev->regs.rx); return 0; } - dev->base = dev->regs.rx = ioremap(dev->scsi_host_ptr->base, size); + dev->base = dev->regs.rx = ioremap(dev->base_start, size); if (dev->base == NULL) return -1; dev->IndexRegs = &dev->regs.rx->IndexRegs; @@ -480,7 +480,7 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size) static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) { - u32 var; + u32 var = 0; if (!(dev->supplement_adapter_info.SupportedOptions2 & AAC_OPTION_MU_RESET) || (bled >= 0) || (bled == -2)) { @@ -500,13 +500,14 @@ static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) if (bled && (bled != -ETIMEDOUT)) return -EINVAL; } - if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */ + if (bled && (var == 0x3803000F)) { /* USE_OTHER_METHOD */ rx_writel(dev, MUnit.reserved2, 3); msleep(5000); /* Delay 5 seconds */ var = 0x00000001; } - if (var != 0x00000001) + if (bled && (var != 0x00000001)) return -EINVAL; + ssleep(5); if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) return -ENODEV; if (startup_timeout < 300) @@ -643,16 +644,17 @@ int _aac_rx_init(struct aac_dev *dev) if (aac_init_adapter(dev) == NULL) goto error_iounmap; aac_adapter_comm(dev, dev->comm_interface); + dev->sync_mode = 0; /* sync. mode not supported */ dev->msi = aac_msi && !pci_enable_msi(dev->pdev); if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, - IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { + IRQF_SHARED, "aacraid", dev) < 0) { if (dev->msi) pci_disable_msi(dev->pdev); printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance); goto error_iounmap; } - dev->dbg_base = dev->scsi_host_ptr->base; + dev->dbg_base = dev->base_start; dev->dbg_base_mapped = dev->base; dev->dbg_size = dev->base_size; diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index e5d4457121e..e66477c9824 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -305,7 +305,7 @@ static int aac_sa_ioremap(struct aac_dev * dev, u32 size) iounmap(dev->regs.sa); return 0; } - dev->base = dev->regs.sa = ioremap(dev->scsi_host_ptr->base, size); + dev->base = dev->regs.sa = ioremap(dev->base_start, size); return (dev->base == NULL) ? -1 : 0; } @@ -385,14 +385,14 @@ int aac_sa_init(struct aac_dev *dev) if(aac_init_adapter(dev) == NULL) goto error_irq; + dev->sync_mode = 0; /* sync. mode not supported */ if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, - IRQF_SHARED|IRQF_DISABLED, - "aacraid", (void *)dev ) < 0) { + IRQF_SHARED, "aacraid", (void *)dev) < 0) { printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance); goto error_iounmap; } - dev->dbg_base = dev->scsi_host_ptr->base; + dev->dbg_base = dev->base_start; dev->dbg_base_mapped = dev->base; dev->dbg_size = dev->base_size; diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 957595a7a45..9c65aed2621 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -56,25 +56,14 @@ 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) */ - handle = (dev->host_rrq[index] & 0x7fffffff); + handle = le32_to_cpu(dev->host_rrq[index]) & 0x7fffffff; /* check fast response bit (30) */ if (handle & 0x40000000) isFastResponse = 1; @@ -93,14 +82,57 @@ 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); + } else if (bellbits_shifted & OUTBOUNDDOORBELL_0) { + unsigned long sflags; + struct list_head *entry; + int send_it = 0; + extern int aac_sync_mode; + + src_writel(dev, MUnit.ODR_C, bellbits); + src_readl(dev, MUnit.ODR_C); + + 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; + if (dev->sync_fib->callback) + dev->sync_fib->callback(dev->sync_fib->callback_data, + dev->sync_fib); + spin_lock_irqsave(&dev->sync_fib->event_lock, sflags); + if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) { + dev->management_fib_count--; + up(&dev->sync_fib->event_wait); + } + spin_unlock_irqrestore(&dev->sync_fib->event_lock, sflags); + spin_lock_irqsave(&dev->sync_lock, sflags); + if (!list_empty(&dev->sync_fib_list)) { + entry = dev->sync_fib_list.next; + dev->sync_fib = list_entry(entry, struct fib, fiblink); + list_del(entry); + send_it = 1; + } else { + dev->sync_fib = NULL; + } + spin_unlock_irqrestore(&dev->sync_lock, sflags); + if (send_it) { + aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, + (u32)dev->sync_fib->hw_fib_pa, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL); + } + } } } if (our_interrupt) { - src_writel(dev, MUnit.ODR_C, bellbits); return IRQ_HANDLED; } return IRQ_NONE; @@ -177,56 +209,63 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, */ src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT); - ok = 0; - start = jiffies; + if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) { + ok = 0; + start = jiffies; - /* - * Wait up to 30 seconds - */ - while (time_before(jiffies, start+30*HZ)) { - /* Delay 5 microseconds to let Mon960 get info. */ - udelay(5); - - /* Mon960 will set doorbell0 bit - * when it has completed the command + /* + * Wait up to 5 minutes */ - if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { - /* Clear the doorbell */ - src_writel(dev, - MUnit.ODR_C, - OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); - ok = 1; - break; + while (time_before(jiffies, start+300*HZ)) { + udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ + /* + * Mon960 will set doorbell0 bit when it has completed the command. + */ + if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { + /* + * Clear the doorbell. + */ + src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); + ok = 1; + break; + } + /* + * Yield the processor in case we are slow + */ + msleep(1); } - - /* Yield the processor in case we are slow */ - msleep(1); - } - if (unlikely(ok != 1)) { - /* Restore interrupt mask even though we timed out */ - aac_adapter_enable_int(dev); - return -ETIMEDOUT; + if (unlikely(ok != 1)) { + /* + * Restore interrupt mask even though we timed out + */ + aac_adapter_enable_int(dev); + return -ETIMEDOUT; + } + /* + * Pull the synch status from Mailbox 0. + */ + if (status) + *status = readl(&dev->IndexRegs->Mailbox[0]); + if (r1) + *r1 = readl(&dev->IndexRegs->Mailbox[1]); + if (r2) + *r2 = readl(&dev->IndexRegs->Mailbox[2]); + if (r3) + *r3 = readl(&dev->IndexRegs->Mailbox[3]); + if (r4) + *r4 = readl(&dev->IndexRegs->Mailbox[4]); + + /* + * Clear the synch command doorbell. + */ + src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); } - /* Pull the synch status from Mailbox 0 */ - if (status) - *status = readl(&dev->IndexRegs->Mailbox[0]); - if (r1) - *r1 = readl(&dev->IndexRegs->Mailbox[1]); - if (r2) - *r2 = readl(&dev->IndexRegs->Mailbox[2]); - if (r3) - *r3 = readl(&dev->IndexRegs->Mailbox[3]); - if (r4) - *r4 = readl(&dev->IndexRegs->Mailbox[4]); - - /* Clear the synch command doorbell */ - src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); - - /* Restore interrupt mask */ + /* + * Restore interrupt mask + */ aac_adapter_enable_int(dev); return 0; - } /** @@ -297,6 +336,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()); @@ -350,30 +392,51 @@ static int aac_src_deliver_message(struct fib *fib) struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; unsigned long qflags; u32 fibsize; - u64 address; + dma_addr_t address; struct aac_fib_xporthdr *pFibX; + u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size); spin_lock_irqsave(q->lock, qflags); q->numpending++; spin_unlock_irqrestore(q->lock, qflags); - /* Calculate the amount to the fibsize bits */ - fibsize = (sizeof(struct aac_fib_xporthdr) + - fib->hw_fib_va->header.Size + 127) / 128 - 1; - if (fibsize > (ALIGN32 - 1)) - fibsize = ALIGN32 - 1; - - /* Fill XPORT header */ - pFibX = (struct aac_fib_xporthdr *) - ((unsigned char *)fib->hw_fib_va - - sizeof(struct aac_fib_xporthdr)); - pFibX->Handle = fib->hw_fib_va->header.SenderData + 1; - pFibX->HostAddress = fib->hw_fib_pa; - pFibX->Size = fib->hw_fib_va->header.Size; - address = fib->hw_fib_pa - (u64)sizeof(struct aac_fib_xporthdr); - - src_writel(dev, MUnit.IQ_H, (u32)(address >> 32)); - src_writel(dev, MUnit.IQ_L, (u32)(address & 0xffffffff) + fibsize); + 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(upper_32_bits(address) != 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); + + /* + * 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, upper_32_bits(address) & 0xffffffff); + src_writel(dev, MUnit.IQ_L, address & 0xffffffff); + return 0; } @@ -385,10 +448,10 @@ static int aac_src_deliver_message(struct fib *fib) static int aac_src_ioremap(struct aac_dev *dev, u32 size) { if (!size) { + iounmap(dev->regs.src.bar1); + dev->regs.src.bar1 = NULL; iounmap(dev->regs.src.bar0); - dev->regs.src.bar0 = NULL; - iounmap(dev->base); - dev->base = NULL; + dev->base = dev->regs.src.bar0 = NULL; return 0; } dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2), @@ -396,15 +459,34 @@ static int aac_src_ioremap(struct aac_dev *dev, u32 size) dev->base = NULL; if (dev->regs.src.bar1 == NULL) return -1; - dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base, - size); + dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size); if (dev->base == NULL) { iounmap(dev->regs.src.bar1); dev->regs.src.bar1 = NULL; return -1; } dev->IndexRegs = &((struct src_registers __iomem *) - dev->base)->IndexRegs; + dev->base)->u.tupelo.IndexRegs; + return 0; +} + +/** + * aac_srcv_ioremap + * @size: mapping resize request + * + */ +static int aac_srcv_ioremap(struct aac_dev *dev, u32 size) +{ + if (!size) { + iounmap(dev->regs.src.bar0); + dev->base = dev->regs.src.bar0 = NULL; + return 0; + } + dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size); + if (dev->base == NULL) + return -1; + dev->IndexRegs = &((struct src_registers __iomem *) + dev->base)->u.denali.IndexRegs; return 0; } @@ -419,7 +501,7 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); if (bled || (var != 0x00000001)) - bled = -EINVAL; + return -EINVAL; if (dev->supplement_adapter_info.SupportedOptions2 & AAC_OPTION_DOORBELL_RESET) { src_writel(dev, MUnit.IDR, reset_mask); @@ -565,7 +647,7 @@ int aac_src_init(struct aac_dev *dev) dev->msi = aac_msi && !pci_enable_msi(dev->pdev); if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, - IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { + IRQF_SHARED, "aacraid", dev) < 0) { if (dev->msi) pci_disable_msi(dev->pdev); @@ -579,15 +661,173 @@ int aac_src_init(struct aac_dev *dev) dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; aac_adapter_enable_int(dev); + + if (!dev->sync_mode) { + /* + * Tell the adapter that all is configured, and it can + * start accepting requests + */ + aac_src_start_adapter(dev); + } + return 0; + +error_iounmap: + + return -1; +} + +/** + * aac_srcv_init - initialize an SRCv card + * @dev: device to configure + * + */ + +int aac_srcv_init(struct aac_dev *dev) +{ + unsigned long start; + unsigned long status; + int restart = 0; + int instance = dev->id; + const char *name = dev->name; + + dev->a_ops.adapter_ioremap = aac_srcv_ioremap; + dev->a_ops.adapter_comm = aac_src_select_comm; + + dev->base_size = AAC_MIN_SRCV_BAR0_SIZE; + if (aac_adapter_ioremap(dev, dev->base_size)) { + printk(KERN_WARNING "%s: unable to map adapter.\n", name); + goto error_iounmap; + } + + /* Failure to reset here is an option ... */ + dev->a_ops.adapter_sync_cmd = src_sync_cmd; + dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; + if ((aac_reset_devices || reset_devices) && + !aac_src_restart_adapter(dev, 0)) + ++restart; + /* + * Check to see if flash update is running. + * Wait for the adapter to be up and running. Wait up to 5 minutes + */ + status = src_readl(dev, MUnit.OMR); + if (status & FLASH_UPD_PENDING) { + start = jiffies; + do { + status = src_readl(dev, MUnit.OMR); + if (time_after(jiffies, start+HZ*FWUPD_TIMEOUT)) { + printk(KERN_ERR "%s%d: adapter flash update failed.\n", + dev->name, instance); + goto error_iounmap; + } + } while (!(status & FLASH_UPD_SUCCESS) && + !(status & FLASH_UPD_FAILED)); + /* Delay 10 seconds. + * Because right now FW is doing a soft reset, + * do not read scratch pad register at this time + */ + ssleep(10); + } /* - * Tell the adapter that all is configured, and it can - * start accepting requests + * Check to see if the board panic'd while booting. + */ + status = src_readl(dev, MUnit.OMR); + if (status & KERNEL_PANIC) { + if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) + goto error_iounmap; + ++restart; + } + /* + * Check to see if the board failed any self tests. */ - aac_src_start_adapter(dev); + status = src_readl(dev, MUnit.OMR); + if (status & SELF_TEST_FAILED) { + printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); + goto error_iounmap; + } + /* + * Check to see if the monitor panic'd while booting. + */ + if (status & MONITOR_PANIC) { + printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); + goto error_iounmap; + } + start = jiffies; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + while (!((status = src_readl(dev, MUnit.OMR)) & + KERNEL_UP_AND_RUNNING) || + status == 0xffffffff) { + if ((restart && + (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || + time_after(jiffies, start+HZ*startup_timeout)) { + printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", + dev->name, instance, status); + goto error_iounmap; + } + if (!restart && + ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || + time_after(jiffies, start + HZ * + ((startup_timeout > 60) + ? (startup_timeout - 60) + : (startup_timeout / 2))))) { + if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev)))) + start = jiffies; + ++restart; + } + msleep(1); + } + if (restart && aac_commit) + aac_commit = 1; + /* + * Fill in the common function dispatch table. + */ + dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; + dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; + dev->a_ops.adapter_notify = aac_src_notify_adapter; + dev->a_ops.adapter_sync_cmd = src_sync_cmd; + dev->a_ops.adapter_check_health = aac_src_check_health; + dev->a_ops.adapter_restart = aac_src_restart_adapter; + + /* + * First clear out all interrupts. Then enable the one's that we + * can handle. + */ + aac_adapter_comm(dev, AAC_COMM_MESSAGE); + aac_adapter_disable_int(dev); + src_writel(dev, MUnit.ODR_C, 0xffffffff); + aac_adapter_enable_int(dev); + + if (aac_init_adapter(dev) == NULL) + goto error_iounmap; + 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, + IRQF_SHARED, "aacraid", dev) < 0) { + if (dev->msi) + pci_disable_msi(dev->pdev); + printk(KERN_ERR "%s%d: Interrupt unavailable.\n", + name, instance); + goto error_iounmap; + } + dev->dbg_base = dev->base_start; + dev->dbg_base_mapped = dev->base; + dev->dbg_size = dev->base_size; + aac_adapter_enable_int(dev); + + if (!dev->sync_mode) { + /* + * Tell the adapter that all is configured, and it can + * start accepting requests + */ + aac_src_start_adapter(dev); + } return 0; error_iounmap: return -1; } + |
