diff options
| -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 | * |
