aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorbrking@us.ibm.com <brking@us.ibm.com>2005-11-01 18:02:22 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-11-06 14:09:47 -0500
commitee0a90fa3efffcaccffea5a9c1599f4c59ca55d4 (patch)
tree3d0ac366068cfa5c2925645634bde1a6b87538b3 /drivers
parentee0f05b863df0a623792eaa46703019c100be2de (diff)
[SCSI] ipr: Support new device queueing model
New ipr adapters support a new device queueing model in the adapter firmware. The queueing model is the NACA queueing model, but it does not mean use of NACA is required. The new model removes some of the adapter firmware queue state that made handling QERR=0 almost impossible. The queueing model on older adapters included the concept of a queue frozen state, which would freeze the response queue in the adapter when a check condition occurred, requiring a a primitive to resume the queue. The new queueing model removes this complexity. Signed-off-by: Brian King <brking@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
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 *