aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ipr.c59
-rw-r--r--drivers/scsi/ipr.h18
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 **/
815static void ipr_init_res_entry(struct ipr_resource_entry *res) 815static 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 **/
4104static 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 **/
1307static 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 *