diff options
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 237 |
1 files changed, 200 insertions, 37 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 52551662d107..d79457ac8bef 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -135,6 +135,8 @@ struct inquiry_data { | |||
135 | static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap); | 135 | static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap); |
136 | static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg); | 136 | static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg); |
137 | static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg); | 137 | static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg); |
138 | static unsigned long aac_build_sgraw2(struct scsi_cmnd *scsicmd, struct aac_raw_io2 *rio2, int sg_max); | ||
139 | static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int nseg_new); | ||
138 | static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); | 140 | static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); |
139 | #ifdef AAC_DETAILED_STATUS_INFO | 141 | #ifdef AAC_DETAILED_STATUS_INFO |
140 | static char *aac_get_status_string(u32 status); | 142 | static char *aac_get_status_string(u32 status); |
@@ -152,10 +154,14 @@ int aac_commit = -1; | |||
152 | int startup_timeout = 180; | 154 | int startup_timeout = 180; |
153 | int aif_timeout = 120; | 155 | int aif_timeout = 120; |
154 | int aac_sync_mode; /* Only Sync. transfer - disabled */ | 156 | int aac_sync_mode; /* Only Sync. transfer - disabled */ |
157 | int aac_convert_sgl = 1; /* convert non-conformable s/g list - enabled */ | ||
155 | 158 | ||
156 | module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR); | 159 | module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR); |
157 | MODULE_PARM_DESC(aac_sync_mode, "Force sync. transfer mode" | 160 | MODULE_PARM_DESC(aac_sync_mode, "Force sync. transfer mode" |
158 | " 0=off, 1=on"); | 161 | " 0=off, 1=on"); |
162 | module_param(aac_convert_sgl, int, S_IRUGO|S_IWUSR); | ||
163 | MODULE_PARM_DESC(aac_convert_sgl, "Convert non-conformable s/g list" | ||
164 | " 0=off, 1=on"); | ||
159 | module_param(nondasd, int, S_IRUGO|S_IWUSR); | 165 | module_param(nondasd, int, S_IRUGO|S_IWUSR); |
160 | MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices." | 166 | MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices." |
161 | " 0=off, 1=on"); | 167 | " 0=off, 1=on"); |
@@ -963,25 +969,44 @@ static void io_callback(void *context, struct fib * fibptr); | |||
963 | 969 | ||
964 | static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) | 970 | static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) |
965 | { | 971 | { |
966 | u16 fibsize; | 972 | struct aac_dev *dev = fib->dev; |
967 | struct aac_raw_io *readcmd; | 973 | u16 fibsize, command; |
974 | |||
968 | aac_fib_init(fib); | 975 | aac_fib_init(fib); |
969 | readcmd = (struct aac_raw_io *) fib_data(fib); | 976 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) { |
970 | readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); | 977 | struct aac_raw_io2 *readcmd2; |
971 | readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | 978 | readcmd2 = (struct aac_raw_io2 *) fib_data(fib); |
972 | readcmd->count = cpu_to_le32(count<<9); | 979 | memset(readcmd2, 0, sizeof(struct aac_raw_io2)); |
973 | readcmd->cid = cpu_to_le16(scmd_id(cmd)); | 980 | readcmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff)); |
974 | readcmd->flags = cpu_to_le16(IO_TYPE_READ); | 981 | readcmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); |
975 | readcmd->bpTotal = 0; | 982 | readcmd2->byteCount = cpu_to_le32(count<<9); |
976 | readcmd->bpComplete = 0; | 983 | readcmd2->cid = cpu_to_le16(scmd_id(cmd)); |
984 | readcmd2->flags = cpu_to_le16(RIO2_IO_TYPE_READ); | ||
985 | aac_build_sgraw2(cmd, readcmd2, dev->scsi_host_ptr->sg_tablesize); | ||
986 | command = ContainerRawIo2; | ||
987 | fibsize = sizeof(struct aac_raw_io2) + | ||
988 | ((le32_to_cpu(readcmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212)); | ||
989 | } else { | ||
990 | struct aac_raw_io *readcmd; | ||
991 | readcmd = (struct aac_raw_io *) fib_data(fib); | ||
992 | readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); | ||
993 | readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | ||
994 | readcmd->count = cpu_to_le32(count<<9); | ||
995 | readcmd->cid = cpu_to_le16(scmd_id(cmd)); | ||
996 | readcmd->flags = cpu_to_le16(RIO_TYPE_READ); | ||
997 | readcmd->bpTotal = 0; | ||
998 | readcmd->bpComplete = 0; | ||
999 | aac_build_sgraw(cmd, &readcmd->sg); | ||
1000 | command = ContainerRawIo; | ||
1001 | fibsize = sizeof(struct aac_raw_io) + | ||
1002 | ((le32_to_cpu(readcmd->sg.count)-1) * sizeof(struct sgentryraw)); | ||
1003 | } | ||
977 | 1004 | ||
978 | aac_build_sgraw(cmd, &readcmd->sg); | ||
979 | fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); | ||
980 | BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); | 1005 | BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); |
981 | /* | 1006 | /* |
982 | * Now send the Fib to the adapter | 1007 | * Now send the Fib to the adapter |
983 | */ | 1008 | */ |
984 | return aac_fib_send(ContainerRawIo, | 1009 | return aac_fib_send(command, |
985 | fib, | 1010 | fib, |
986 | fibsize, | 1011 | fibsize, |
987 | FsaNormal, | 1012 | FsaNormal, |
@@ -1052,28 +1077,50 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 | |||
1052 | 1077 | ||
1053 | static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua) | 1078 | static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua) |
1054 | { | 1079 | { |
1055 | u16 fibsize; | 1080 | struct aac_dev *dev = fib->dev; |
1056 | struct aac_raw_io *writecmd; | 1081 | u16 fibsize, command; |
1082 | |||
1057 | aac_fib_init(fib); | 1083 | aac_fib_init(fib); |
1058 | writecmd = (struct aac_raw_io *) fib_data(fib); | 1084 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) { |
1059 | writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); | 1085 | struct aac_raw_io2 *writecmd2; |
1060 | writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | 1086 | writecmd2 = (struct aac_raw_io2 *) fib_data(fib); |
1061 | writecmd->count = cpu_to_le32(count<<9); | 1087 | memset(writecmd2, 0, sizeof(struct aac_raw_io2)); |
1062 | writecmd->cid = cpu_to_le16(scmd_id(cmd)); | 1088 | writecmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff)); |
1063 | writecmd->flags = (fua && ((aac_cache & 5) != 1) && | 1089 | writecmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); |
1064 | (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ? | 1090 | writecmd2->byteCount = cpu_to_le32(count<<9); |
1065 | cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) : | 1091 | writecmd2->cid = cpu_to_le16(scmd_id(cmd)); |
1066 | cpu_to_le16(IO_TYPE_WRITE); | 1092 | writecmd2->flags = (fua && ((aac_cache & 5) != 1) && |
1067 | writecmd->bpTotal = 0; | 1093 | (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ? |
1068 | writecmd->bpComplete = 0; | 1094 | cpu_to_le16(RIO2_IO_TYPE_WRITE|RIO2_IO_SUREWRITE) : |
1069 | 1095 | cpu_to_le16(RIO2_IO_TYPE_WRITE); | |
1070 | aac_build_sgraw(cmd, &writecmd->sg); | 1096 | aac_build_sgraw2(cmd, writecmd2, dev->scsi_host_ptr->sg_tablesize); |
1071 | fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); | 1097 | command = ContainerRawIo2; |
1098 | fibsize = sizeof(struct aac_raw_io2) + | ||
1099 | ((le32_to_cpu(writecmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212)); | ||
1100 | } else { | ||
1101 | struct aac_raw_io *writecmd; | ||
1102 | writecmd = (struct aac_raw_io *) fib_data(fib); | ||
1103 | writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); | ||
1104 | writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | ||
1105 | writecmd->count = cpu_to_le32(count<<9); | ||
1106 | writecmd->cid = cpu_to_le16(scmd_id(cmd)); | ||
1107 | writecmd->flags = (fua && ((aac_cache & 5) != 1) && | ||
1108 | (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ? | ||
1109 | cpu_to_le16(RIO_TYPE_WRITE|RIO_SUREWRITE) : | ||
1110 | cpu_to_le16(RIO_TYPE_WRITE); | ||
1111 | writecmd->bpTotal = 0; | ||
1112 | writecmd->bpComplete = 0; | ||
1113 | aac_build_sgraw(cmd, &writecmd->sg); | ||
1114 | command = ContainerRawIo; | ||
1115 | fibsize = sizeof(struct aac_raw_io) + | ||
1116 | ((le32_to_cpu(writecmd->sg.count)-1) * sizeof (struct sgentryraw)); | ||
1117 | } | ||
1118 | |||
1072 | BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); | 1119 | BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); |
1073 | /* | 1120 | /* |
1074 | * Now send the Fib to the adapter | 1121 | * Now send the Fib to the adapter |
1075 | */ | 1122 | */ |
1076 | return aac_fib_send(ContainerRawIo, | 1123 | return aac_fib_send(command, |
1077 | fib, | 1124 | fib, |
1078 | fibsize, | 1125 | fibsize, |
1079 | FsaNormal, | 1126 | FsaNormal, |
@@ -1492,8 +1539,6 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
1492 | dev->a_ops.adapter_write = aac_write_block; | 1539 | dev->a_ops.adapter_write = aac_write_block; |
1493 | } | 1540 | } |
1494 | dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; | 1541 | dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; |
1495 | if (dev->adapter_info.options & AAC_OPT_NEW_COMM_TYPE1) | ||
1496 | dev->adapter_info.options |= AAC_OPT_NEW_COMM; | ||
1497 | if (!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { | 1542 | if (!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { |
1498 | /* | 1543 | /* |
1499 | * Worst case size that could cause sg overflow when | 1544 | * Worst case size that could cause sg overflow when |
@@ -2616,12 +2661,18 @@ static void aac_srb_callback(void *context, struct fib * fibptr) | |||
2616 | srbreply = (struct aac_srb_reply *) fib_data(fibptr); | 2661 | srbreply = (struct aac_srb_reply *) fib_data(fibptr); |
2617 | 2662 | ||
2618 | scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */ | 2663 | scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */ |
2619 | /* | ||
2620 | * Calculate resid for sg | ||
2621 | */ | ||
2622 | 2664 | ||
2623 | scsi_set_resid(scsicmd, scsi_bufflen(scsicmd) | 2665 | if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) { |
2624 | - le32_to_cpu(srbreply->data_xfer_length)); | 2666 | /* fast response */ |
2667 | srbreply->srb_status = cpu_to_le32(SRB_STATUS_SUCCESS); | ||
2668 | srbreply->scsi_status = cpu_to_le32(SAM_STAT_GOOD); | ||
2669 | } else { | ||
2670 | /* | ||
2671 | * Calculate resid for sg | ||
2672 | */ | ||
2673 | scsi_set_resid(scsicmd, scsi_bufflen(scsicmd) | ||
2674 | - le32_to_cpu(srbreply->data_xfer_length)); | ||
2675 | } | ||
2625 | 2676 | ||
2626 | scsi_dma_unmap(scsicmd); | 2677 | scsi_dma_unmap(scsicmd); |
2627 | 2678 | ||
@@ -2954,6 +3005,118 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* | |||
2954 | return byte_count; | 3005 | return byte_count; |
2955 | } | 3006 | } |
2956 | 3007 | ||
3008 | static unsigned long aac_build_sgraw2(struct scsi_cmnd *scsicmd, struct aac_raw_io2 *rio2, int sg_max) | ||
3009 | { | ||
3010 | unsigned long byte_count = 0; | ||
3011 | int nseg; | ||
3012 | |||
3013 | nseg = scsi_dma_map(scsicmd); | ||
3014 | BUG_ON(nseg < 0); | ||
3015 | if (nseg) { | ||
3016 | struct scatterlist *sg; | ||
3017 | int i, conformable = 0; | ||
3018 | u32 min_size = PAGE_SIZE, cur_size; | ||
3019 | |||
3020 | scsi_for_each_sg(scsicmd, sg, nseg, i) { | ||
3021 | int count = sg_dma_len(sg); | ||
3022 | u64 addr = sg_dma_address(sg); | ||
3023 | |||
3024 | BUG_ON(i >= sg_max); | ||
3025 | rio2->sge[i].addrHigh = cpu_to_le32((u32)(addr>>32)); | ||
3026 | rio2->sge[i].addrLow = cpu_to_le32((u32)(addr & 0xffffffff)); | ||
3027 | cur_size = cpu_to_le32(count); | ||
3028 | rio2->sge[i].length = cur_size; | ||
3029 | rio2->sge[i].flags = 0; | ||
3030 | if (i == 0) { | ||
3031 | conformable = 1; | ||
3032 | rio2->sgeFirstSize = cur_size; | ||
3033 | } else if (i == 1) { | ||
3034 | rio2->sgeNominalSize = cur_size; | ||
3035 | min_size = cur_size; | ||
3036 | } else if ((i+1) < nseg && cur_size != rio2->sgeNominalSize) { | ||
3037 | conformable = 0; | ||
3038 | if (cur_size < min_size) | ||
3039 | min_size = cur_size; | ||
3040 | } | ||
3041 | byte_count += count; | ||
3042 | } | ||
3043 | |||
3044 | /* hba wants the size to be exact */ | ||
3045 | if (byte_count > scsi_bufflen(scsicmd)) { | ||
3046 | u32 temp = le32_to_cpu(rio2->sge[i-1].length) - | ||
3047 | (byte_count - scsi_bufflen(scsicmd)); | ||
3048 | rio2->sge[i-1].length = cpu_to_le32(temp); | ||
3049 | byte_count = scsi_bufflen(scsicmd); | ||
3050 | } | ||
3051 | |||
3052 | rio2->sgeCnt = cpu_to_le32(nseg); | ||
3053 | rio2->flags |= cpu_to_le16(RIO2_SG_FORMAT_IEEE1212); | ||
3054 | /* not conformable: evaluate required sg elements */ | ||
3055 | if (!conformable) { | ||
3056 | int j, nseg_new = nseg, err_found; | ||
3057 | for (i = min_size / PAGE_SIZE; i >= 1; --i) { | ||
3058 | err_found = 0; | ||
3059 | nseg_new = 2; | ||
3060 | for (j = 1; j < nseg - 1; ++j) { | ||
3061 | if (rio2->sge[j].length % (i*PAGE_SIZE)) { | ||
3062 | err_found = 1; | ||
3063 | break; | ||
3064 | } | ||
3065 | nseg_new += (rio2->sge[j].length / (i*PAGE_SIZE)); | ||
3066 | } | ||
3067 | if (!err_found) | ||
3068 | break; | ||
3069 | } | ||
3070 | if (i > 0 && nseg_new <= sg_max) | ||
3071 | aac_convert_sgraw2(rio2, i, nseg, nseg_new); | ||
3072 | } else | ||
3073 | rio2->flags |= cpu_to_le16(RIO2_SGL_CONFORMANT); | ||
3074 | |||
3075 | /* Check for command underflow */ | ||
3076 | if (scsicmd->underflow && (byte_count < scsicmd->underflow)) { | ||
3077 | printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", | ||
3078 | byte_count, scsicmd->underflow); | ||
3079 | } | ||
3080 | } | ||
3081 | |||
3082 | return byte_count; | ||
3083 | } | ||
3084 | |||
3085 | static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int nseg_new) | ||
3086 | { | ||
3087 | struct sge_ieee1212 *sge; | ||
3088 | int i, j, pos; | ||
3089 | u32 addr_low; | ||
3090 | |||
3091 | if (aac_convert_sgl == 0) | ||
3092 | return 0; | ||
3093 | |||
3094 | sge = kmalloc(nseg_new * sizeof(struct sge_ieee1212), GFP_ATOMIC); | ||
3095 | if (sge == NULL) | ||
3096 | return -1; | ||
3097 | |||
3098 | for (i = 1, pos = 1; i < nseg-1; ++i) { | ||
3099 | for (j = 0; j < rio2->sge[i].length / (pages * PAGE_SIZE); ++j) { | ||
3100 | addr_low = rio2->sge[i].addrLow + j * pages * PAGE_SIZE; | ||
3101 | sge[pos].addrLow = addr_low; | ||
3102 | sge[pos].addrHigh = rio2->sge[i].addrHigh; | ||
3103 | if (addr_low < rio2->sge[i].addrLow) | ||
3104 | sge[pos].addrHigh++; | ||
3105 | sge[pos].length = pages * PAGE_SIZE; | ||
3106 | sge[pos].flags = 0; | ||
3107 | pos++; | ||
3108 | } | ||
3109 | } | ||
3110 | sge[pos] = rio2->sge[nseg-1]; | ||
3111 | memcpy(&rio2->sge[1], &sge[1], (nseg_new-1)*sizeof(struct sge_ieee1212)); | ||
3112 | |||
3113 | kfree(sge); | ||
3114 | rio2->sgeCnt = cpu_to_le32(nseg_new); | ||
3115 | rio2->flags |= cpu_to_le16(RIO2_SGL_CONFORMANT); | ||
3116 | rio2->sgeNominalSize = pages * PAGE_SIZE; | ||
3117 | return 0; | ||
3118 | } | ||
3119 | |||
2957 | #ifdef AAC_DETAILED_STATUS_INFO | 3120 | #ifdef AAC_DETAILED_STATUS_INFO |
2958 | 3121 | ||
2959 | struct aac_srb_status_info { | 3122 | struct aac_srb_status_info { |