diff options
author | Manish Rangankar <manish.rangankar@cavium.com> | 2018-02-12 01:48:41 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-02-13 21:35:41 -0500 |
commit | 1bc5ad3a6acdcf56f83272f2de1cd2389ea9e9e2 (patch) | |
tree | d5a3494e29017db8d41210e37282c0276c60d3d3 | |
parent | 00c20cdc79259c6c5bf978b21af96c2d3edb646d (diff) |
scsi: qla4xxx: skip error recovery in case of register disconnect.
A system crashes when continuously removing/re-adding the storage
controller.
Signed-off-by: Manish Rangankar <manish.rangankar@cavium.com>
Reviewed-by: Ewan D. Milne <emilne@redhat.com>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 46 |
2 files changed, 48 insertions, 0 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index fc233717355f..817f312023a9 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -168,6 +168,8 @@ | |||
168 | #define DEV_DB_NON_PERSISTENT 0 | 168 | #define DEV_DB_NON_PERSISTENT 0 |
169 | #define DEV_DB_PERSISTENT 1 | 169 | #define DEV_DB_PERSISTENT 1 |
170 | 170 | ||
171 | #define QL4_ISP_REG_DISCONNECT 0xffffffffU | ||
172 | |||
171 | #define COPY_ISID(dst_isid, src_isid) { \ | 173 | #define COPY_ISID(dst_isid, src_isid) { \ |
172 | int i, j; \ | 174 | int i, j; \ |
173 | for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \ | 175 | for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \ |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 82e889bbe0ed..fc2c97d9a0d6 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -262,6 +262,24 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
262 | 262 | ||
263 | static struct scsi_transport_template *qla4xxx_scsi_transport; | 263 | static struct scsi_transport_template *qla4xxx_scsi_transport; |
264 | 264 | ||
265 | static int qla4xxx_isp_check_reg(struct scsi_qla_host *ha) | ||
266 | { | ||
267 | u32 reg_val = 0; | ||
268 | int rval = QLA_SUCCESS; | ||
269 | |||
270 | if (is_qla8022(ha)) | ||
271 | reg_val = readl(&ha->qla4_82xx_reg->host_status); | ||
272 | else if (is_qla8032(ha) || is_qla8042(ha)) | ||
273 | reg_val = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER); | ||
274 | else | ||
275 | reg_val = readw(&ha->reg->ctrl_status); | ||
276 | |||
277 | if (reg_val == QL4_ISP_REG_DISCONNECT) | ||
278 | rval = QLA_ERROR; | ||
279 | |||
280 | return rval; | ||
281 | } | ||
282 | |||
265 | static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num, | 283 | static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num, |
266 | uint32_t iface_type, uint32_t payload_size, | 284 | uint32_t iface_type, uint32_t payload_size, |
267 | uint32_t pid, struct sockaddr *dst_addr) | 285 | uint32_t pid, struct sockaddr *dst_addr) |
@@ -9186,10 +9204,17 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) | |||
9186 | struct srb *srb = NULL; | 9204 | struct srb *srb = NULL; |
9187 | int ret = SUCCESS; | 9205 | int ret = SUCCESS; |
9188 | int wait = 0; | 9206 | int wait = 0; |
9207 | int rval; | ||
9189 | 9208 | ||
9190 | ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n", | 9209 | ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n", |
9191 | ha->host_no, id, lun, cmd, cmd->cmnd[0]); | 9210 | ha->host_no, id, lun, cmd, cmd->cmnd[0]); |
9192 | 9211 | ||
9212 | rval = qla4xxx_isp_check_reg(ha); | ||
9213 | if (rval != QLA_SUCCESS) { | ||
9214 | ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n"); | ||
9215 | return FAILED; | ||
9216 | } | ||
9217 | |||
9193 | spin_lock_irqsave(&ha->hardware_lock, flags); | 9218 | spin_lock_irqsave(&ha->hardware_lock, flags); |
9194 | srb = (struct srb *) CMD_SP(cmd); | 9219 | srb = (struct srb *) CMD_SP(cmd); |
9195 | if (!srb) { | 9220 | if (!srb) { |
@@ -9241,6 +9266,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
9241 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); | 9266 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); |
9242 | struct ddb_entry *ddb_entry = cmd->device->hostdata; | 9267 | struct ddb_entry *ddb_entry = cmd->device->hostdata; |
9243 | int ret = FAILED, stat; | 9268 | int ret = FAILED, stat; |
9269 | int rval; | ||
9244 | 9270 | ||
9245 | if (!ddb_entry) | 9271 | if (!ddb_entry) |
9246 | return ret; | 9272 | return ret; |
@@ -9260,6 +9286,12 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
9260 | cmd, jiffies, cmd->request->timeout / HZ, | 9286 | cmd, jiffies, cmd->request->timeout / HZ, |
9261 | ha->dpc_flags, cmd->result, cmd->allowed)); | 9287 | ha->dpc_flags, cmd->result, cmd->allowed)); |
9262 | 9288 | ||
9289 | rval = qla4xxx_isp_check_reg(ha); | ||
9290 | if (rval != QLA_SUCCESS) { | ||
9291 | ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n"); | ||
9292 | return FAILED; | ||
9293 | } | ||
9294 | |||
9263 | /* FIXME: wait for hba to go online */ | 9295 | /* FIXME: wait for hba to go online */ |
9264 | stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun); | 9296 | stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun); |
9265 | if (stat != QLA_SUCCESS) { | 9297 | if (stat != QLA_SUCCESS) { |
@@ -9303,6 +9335,7 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) | |||
9303 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); | 9335 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); |
9304 | struct ddb_entry *ddb_entry = cmd->device->hostdata; | 9336 | struct ddb_entry *ddb_entry = cmd->device->hostdata; |
9305 | int stat, ret; | 9337 | int stat, ret; |
9338 | int rval; | ||
9306 | 9339 | ||
9307 | if (!ddb_entry) | 9340 | if (!ddb_entry) |
9308 | return FAILED; | 9341 | return FAILED; |
@@ -9320,6 +9353,12 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) | |||
9320 | ha->host_no, cmd, jiffies, cmd->request->timeout / HZ, | 9353 | ha->host_no, cmd, jiffies, cmd->request->timeout / HZ, |
9321 | ha->dpc_flags, cmd->result, cmd->allowed)); | 9354 | ha->dpc_flags, cmd->result, cmd->allowed)); |
9322 | 9355 | ||
9356 | rval = qla4xxx_isp_check_reg(ha); | ||
9357 | if (rval != QLA_SUCCESS) { | ||
9358 | ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n"); | ||
9359 | return FAILED; | ||
9360 | } | ||
9361 | |||
9323 | stat = qla4xxx_reset_target(ha, ddb_entry); | 9362 | stat = qla4xxx_reset_target(ha, ddb_entry); |
9324 | if (stat != QLA_SUCCESS) { | 9363 | if (stat != QLA_SUCCESS) { |
9325 | starget_printk(KERN_INFO, scsi_target(cmd->device), | 9364 | starget_printk(KERN_INFO, scsi_target(cmd->device), |
@@ -9374,9 +9413,16 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
9374 | { | 9413 | { |
9375 | int return_status = FAILED; | 9414 | int return_status = FAILED; |
9376 | struct scsi_qla_host *ha; | 9415 | struct scsi_qla_host *ha; |
9416 | int rval; | ||
9377 | 9417 | ||
9378 | ha = to_qla_host(cmd->device->host); | 9418 | ha = to_qla_host(cmd->device->host); |
9379 | 9419 | ||
9420 | rval = qla4xxx_isp_check_reg(ha); | ||
9421 | if (rval != QLA_SUCCESS) { | ||
9422 | ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n"); | ||
9423 | return FAILED; | ||
9424 | } | ||
9425 | |||
9380 | if ((is_qla8032(ha) || is_qla8042(ha)) && ql4xdontresethba) | 9426 | if ((is_qla8032(ha) || is_qla8042(ha)) && ql4xdontresethba) |
9381 | qla4_83xx_set_idc_dontreset(ha); | 9427 | qla4_83xx_set_idc_dontreset(ha); |
9382 | 9428 | ||