From dfed823eabf545795f04c8b5164d46a73c5b58ea Mon Sep 17 00:00:00 2001 From: "brking@us.ibm.com" Date: Tue, 1 Nov 2005 17:02:55 -0600 Subject: [SCSI] ipr: Better handle failure of adapter bringup commands Some new ipr adapters do not support some of the initialization commands currently sent to it from the driver. Handle these commands failing and continue on with the adapter initialization. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 59 +++++++++++++++++++++++++++++++++++++++++++++--------- drivers/scsi/ipr.h | 2 ++ 2 files changed, 52 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 8d364f232877..fa2cb3582cfa 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4883,6 +4883,51 @@ static void ipr_build_mode_sense(struct ipr_cmnd *ipr_cmd, ioarcb->read_data_transfer_length = cpu_to_be32(xfer_len); } +/** + * ipr_reset_cmd_failed - Handle failure of IOA reset command + * @ipr_cmd: ipr command struct + * + * This function handles the failure of an IOA bringup command. + * + * Return value: + * IPR_RC_JOB_RETURN + **/ +static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd) +{ + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + + dev_err(&ioa_cfg->pdev->dev, + "0x%02X failed with IOASC: 0x%08X\n", + ipr_cmd->ioarcb.cmd_pkt.cdb[0], ioasc); + + ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); + list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); + return IPR_RC_JOB_RETURN; +} + +/** + * ipr_reset_mode_sense_failed - Handle failure of IOAFP mode sense + * @ipr_cmd: ipr command struct + * + * This function handles the failure of a Mode Sense to the IOAFP. + * Some adapters do not handle all mode pages. + * + * Return value: + * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN + **/ +static int ipr_reset_mode_sense_failed(struct ipr_cmnd *ipr_cmd) +{ + u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + + if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { + ipr_cmd->job_step = ipr_setup_write_cache; + return IPR_RC_JOB_CONTINUE; + } + + return ipr_reset_cmd_failed(ipr_cmd); +} + /** * ipr_ioafp_mode_sense_page28 - Issue Mode Sense Page 28 to IOA * @ipr_cmd: ipr command struct @@ -4904,6 +4949,7 @@ static int ipr_ioafp_mode_sense_page28(struct ipr_cmnd *ipr_cmd) sizeof(struct ipr_mode_pages)); ipr_cmd->job_step = ipr_ioafp_mode_select_page28; + ipr_cmd->job_step_failed = ipr_reset_mode_sense_failed; ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT); @@ -5716,7 +5762,6 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd) static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd) { u32 rc, ioasc; - unsigned long scratch = ipr_cmd->u.scratch; struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; do { @@ -5732,17 +5777,13 @@ static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd) } if (IPR_IOASC_SENSE_KEY(ioasc)) { - dev_err(&ioa_cfg->pdev->dev, - "0x%02X failed with IOASC: 0x%08X\n", - ipr_cmd->ioarcb.cmd_pkt.cdb[0], ioasc); - - ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); - list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); - return; + rc = ipr_cmd->job_step_failed(ipr_cmd); + if (rc == IPR_RC_JOB_RETURN) + return; } ipr_reinit_ipr_cmnd(ipr_cmd); - ipr_cmd->u.scratch = scratch; + ipr_cmd->job_step_failed = ipr_reset_cmd_failed; rc = ipr_cmd->job_step(ipr_cmd); } while(rc == IPR_RC_JOB_CONTINUE); } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 2f18284b6004..637b891eb50f 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -84,6 +84,7 @@ #define IPR_IOASC_HW_DEV_BUS_STATUS 0x04448500 #define IPR_IOASC_IOASC_MASK 0xFFFFFF00 #define IPR_IOASC_SCSI_STATUS_MASK 0x000000FF +#define IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT 0x05240000 #define IPR_IOASC_IR_RESOURCE_HANDLE 0x05250000 #define IPR_IOASC_IR_NO_CMDS_TO_2ND_IOA 0x05258100 #define IPR_IOASA_IR_DUAL_IOA_DISABLED 0x052C8000 @@ -1031,6 +1032,7 @@ struct ipr_cmnd { struct timer_list timer; void (*done) (struct ipr_cmnd *); int (*job_step) (struct ipr_cmnd *); + int (*job_step_failed) (struct ipr_cmnd *); u16 cmd_index; u8 sense_buffer[SCSI_SENSE_BUFFERSIZE]; dma_addr_t sense_buffer_dma; -- cgit v1.2.3