diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/ipr.c | 59 | ||||
-rw-r--r-- | drivers/scsi/ipr.h | 18 |
2 files changed, 66 insertions, 11 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index cca4972735be..2f84f26624bf 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -814,7 +814,7 @@ static void ipr_send_hcam(struct ipr_ioa_cfg *ioa_cfg, u8 type, | |||
814 | **/ | 814 | **/ |
815 | static void ipr_init_res_entry(struct ipr_resource_entry *res) | 815 | static void ipr_init_res_entry(struct ipr_resource_entry *res) |
816 | { | 816 | { |
817 | res->needs_sync_complete = 1; | 817 | res->needs_sync_complete = 0; |
818 | res->in_erp = 0; | 818 | res->in_erp = 0; |
819 | res->add_to_ml = 0; | 819 | res->add_to_ml = 0; |
820 | res->del_from_ml = 0; | 820 | res->del_from_ml = 0; |
@@ -3251,7 +3251,8 @@ static int ipr_slave_alloc(struct scsi_device *sdev) | |||
3251 | res->add_to_ml = 0; | 3251 | res->add_to_ml = 0; |
3252 | res->in_erp = 0; | 3252 | res->in_erp = 0; |
3253 | sdev->hostdata = res; | 3253 | sdev->hostdata = res; |
3254 | res->needs_sync_complete = 1; | 3254 | if (!ipr_is_naca_model(res)) |
3255 | res->needs_sync_complete = 1; | ||
3255 | rc = 0; | 3256 | rc = 0; |
3256 | break; | 3257 | break; |
3257 | } | 3258 | } |
@@ -3515,7 +3516,8 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) | |||
3515 | } | 3516 | } |
3516 | 3517 | ||
3517 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); | 3518 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); |
3518 | res->needs_sync_complete = 1; | 3519 | if (!ipr_is_naca_model(res)) |
3520 | res->needs_sync_complete = 1; | ||
3519 | 3521 | ||
3520 | LEAVE; | 3522 | LEAVE; |
3521 | return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS); | 3523 | return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS); |
@@ -3819,7 +3821,8 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) | |||
3819 | } | 3821 | } |
3820 | 3822 | ||
3821 | if (res) { | 3823 | if (res) { |
3822 | res->needs_sync_complete = 1; | 3824 | if (!ipr_is_naca_model(res)) |
3825 | res->needs_sync_complete = 1; | ||
3823 | res->in_erp = 0; | 3826 | res->in_erp = 0; |
3824 | } | 3827 | } |
3825 | ipr_unmap_sglist(ioa_cfg, ipr_cmd); | 3828 | ipr_unmap_sglist(ioa_cfg, ipr_cmd); |
@@ -4089,6 +4092,30 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) | |||
4089 | } | 4092 | } |
4090 | 4093 | ||
4091 | /** | 4094 | /** |
4095 | * ipr_get_autosense - Copy autosense data to sense buffer | ||
4096 | * @ipr_cmd: ipr command struct | ||
4097 | * | ||
4098 | * This function copies the autosense buffer to the buffer | ||
4099 | * in the scsi_cmd, if there is autosense available. | ||
4100 | * | ||
4101 | * Return value: | ||
4102 | * 1 if autosense was available / 0 if not | ||
4103 | **/ | ||
4104 | static int ipr_get_autosense(struct ipr_cmnd *ipr_cmd) | ||
4105 | { | ||
4106 | struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; | ||
4107 | |||
4108 | if ((be32_to_cpu(ioasa->ioasc_specific) & | ||
4109 | (IPR_ADDITIONAL_STATUS_FMT | IPR_AUTOSENSE_VALID)) == 0) | ||
4110 | return 0; | ||
4111 | |||
4112 | memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data, | ||
4113 | min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len), | ||
4114 | SCSI_SENSE_BUFFERSIZE)); | ||
4115 | return 1; | ||
4116 | } | ||
4117 | |||
4118 | /** | ||
4092 | * ipr_erp_start - Process an error response for a SCSI op | 4119 | * ipr_erp_start - Process an error response for a SCSI op |
4093 | * @ioa_cfg: ioa config struct | 4120 | * @ioa_cfg: ioa config struct |
4094 | * @ipr_cmd: ipr command struct | 4121 | * @ipr_cmd: ipr command struct |
@@ -4118,7 +4145,10 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, | |||
4118 | 4145 | ||
4119 | switch (ioasc & IPR_IOASC_IOASC_MASK) { | 4146 | switch (ioasc & IPR_IOASC_IOASC_MASK) { |
4120 | case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST: | 4147 | case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST: |
4121 | scsi_cmd->result |= (DID_IMM_RETRY << 16); | 4148 | if (ipr_is_naca_model(res)) |
4149 | scsi_cmd->result |= (DID_ABORT << 16); | ||
4150 | else | ||
4151 | scsi_cmd->result |= (DID_IMM_RETRY << 16); | ||
4122 | break; | 4152 | break; |
4123 | case IPR_IOASC_IR_RESOURCE_HANDLE: | 4153 | case IPR_IOASC_IR_RESOURCE_HANDLE: |
4124 | case IPR_IOASC_IR_NO_CMDS_TO_2ND_IOA: | 4154 | case IPR_IOASC_IR_NO_CMDS_TO_2ND_IOA: |
@@ -4126,7 +4156,8 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, | |||
4126 | break; | 4156 | break; |
4127 | case IPR_IOASC_HW_SEL_TIMEOUT: | 4157 | case IPR_IOASC_HW_SEL_TIMEOUT: |
4128 | scsi_cmd->result |= (DID_NO_CONNECT << 16); | 4158 | scsi_cmd->result |= (DID_NO_CONNECT << 16); |
4129 | res->needs_sync_complete = 1; | 4159 | if (!ipr_is_naca_model(res)) |
4160 | res->needs_sync_complete = 1; | ||
4130 | break; | 4161 | break; |
4131 | case IPR_IOASC_SYNC_REQUIRED: | 4162 | case IPR_IOASC_SYNC_REQUIRED: |
4132 | if (!res->in_erp) | 4163 | if (!res->in_erp) |
@@ -4146,21 +4177,27 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, | |||
4146 | if (!res->resetting_device) | 4177 | if (!res->resetting_device) |
4147 | scsi_report_bus_reset(ioa_cfg->host, scsi_cmd->device->channel); | 4178 | scsi_report_bus_reset(ioa_cfg->host, scsi_cmd->device->channel); |
4148 | scsi_cmd->result |= (DID_ERROR << 16); | 4179 | scsi_cmd->result |= (DID_ERROR << 16); |
4149 | res->needs_sync_complete = 1; | 4180 | if (!ipr_is_naca_model(res)) |
4181 | res->needs_sync_complete = 1; | ||
4150 | break; | 4182 | break; |
4151 | case IPR_IOASC_HW_DEV_BUS_STATUS: | 4183 | case IPR_IOASC_HW_DEV_BUS_STATUS: |
4152 | scsi_cmd->result |= IPR_IOASC_SENSE_STATUS(ioasc); | 4184 | scsi_cmd->result |= IPR_IOASC_SENSE_STATUS(ioasc); |
4153 | if (IPR_IOASC_SENSE_STATUS(ioasc) == SAM_STAT_CHECK_CONDITION) { | 4185 | if (IPR_IOASC_SENSE_STATUS(ioasc) == SAM_STAT_CHECK_CONDITION) { |
4154 | ipr_erp_cancel_all(ipr_cmd); | 4186 | if (!ipr_get_autosense(ipr_cmd)) { |
4155 | return; | 4187 | if (!ipr_is_naca_model(res)) { |
4188 | ipr_erp_cancel_all(ipr_cmd); | ||
4189 | return; | ||
4190 | } | ||
4191 | } | ||
4156 | } | 4192 | } |
4157 | res->needs_sync_complete = 1; | 4193 | if (!ipr_is_naca_model(res)) |
4194 | res->needs_sync_complete = 1; | ||
4158 | break; | 4195 | break; |
4159 | case IPR_IOASC_NR_INIT_CMD_REQUIRED: | 4196 | case IPR_IOASC_NR_INIT_CMD_REQUIRED: |
4160 | break; | 4197 | break; |
4161 | default: | 4198 | default: |
4162 | scsi_cmd->result |= (DID_ERROR << 16); | 4199 | scsi_cmd->result |= (DID_ERROR << 16); |
4163 | if (!ipr_is_vset_device(res)) | 4200 | if (!ipr_is_vset_device(res) && !ipr_is_naca_model(res)) |
4164 | res->needs_sync_complete = 1; | 4201 | res->needs_sync_complete = 1; |
4165 | break; | 4202 | break; |
4166 | } | 4203 | } |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index f7fa8cd2ecad..c9cc40e5db24 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -302,6 +302,10 @@ struct ipr_config_table_entry { | |||
302 | #define IPR_SUBTYPE_GENERIC_SCSI 1 | 302 | #define IPR_SUBTYPE_GENERIC_SCSI 1 |
303 | #define IPR_SUBTYPE_VOLUME_SET 2 | 303 | #define IPR_SUBTYPE_VOLUME_SET 2 |
304 | 304 | ||
305 | #define IPR_QUEUEING_MODEL(res) ((((res)->cfgte.flags) & 0x70) >> 4) | ||
306 | #define IPR_QUEUE_FROZEN_MODEL 0 | ||
307 | #define IPR_QUEUE_NACA_MODEL 1 | ||
308 | |||
305 | struct ipr_res_addr res_addr; | 309 | struct ipr_res_addr res_addr; |
306 | __be32 res_handle; | 310 | __be32 res_handle; |
307 | __be32 reserved4[2]; | 311 | __be32 reserved4[2]; |
@@ -1294,6 +1298,20 @@ static inline int ipr_is_gscsi(struct ipr_resource_entry *res) | |||
1294 | } | 1298 | } |
1295 | 1299 | ||
1296 | /** | 1300 | /** |
1301 | * ipr_is_naca_model - Determine if a resource is using NACA queueing model | ||
1302 | * @res: resource entry struct | ||
1303 | * | ||
1304 | * Return value: | ||
1305 | * 1 if NACA queueing model / 0 if not NACA queueing model | ||
1306 | **/ | ||
1307 | static inline int ipr_is_naca_model(struct ipr_resource_entry *res) | ||
1308 | { | ||
1309 | if (ipr_is_gscsi(res) && IPR_QUEUEING_MODEL(res) == IPR_QUEUE_NACA_MODEL) | ||
1310 | return 1; | ||
1311 | return 0; | ||
1312 | } | ||
1313 | |||
1314 | /** | ||
1297 | * ipr_is_device - Determine if resource address is that of a device | 1315 | * ipr_is_device - Determine if resource address is that of a device |
1298 | * @res_addr: resource address struct | 1316 | * @res_addr: resource address struct |
1299 | * | 1317 | * |