From: Chad Dupuis Date: Mon, 27 Aug 2012 07:24:57 +0000 (+0530) Subject: qla2xxx: Fix for handling some error conditions in loopback. X-Git-Tag: v2.6.39-400.9.0~408 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=a9eced0b5ca8c075406549648a700fc9a4a83fe0;p=users%2Fjedix%2Flinux-maple.git qla2xxx: Fix for handling some error conditions in loopback. Fixes the bug where in case we do not receive DCBX completion aen after a set-port mbx Or when we get a bad status for IDC completion (mbx 8100) AEN (i.e. bit 15 of mb2 is set) then we need to return error status and fail the loopback operation. JIRA Key: V2632FC-245 Acked-by: Giridhar Malavali Acked-by: Saurav Kashyap --- diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 76669d96f0f00..3a8c34528cb35 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -568,9 +568,17 @@ qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config, if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) { ql_dbg(ql_dbg_user, vha, 0x7022, "State change notification not received.\n"); - } else - ql_dbg(ql_dbg_user, vha, 0x7023, - "State change received.\n"); + rval = -EINVAL; + } else { + if (ha->flags.idc_compl_status) { + ql_dbg(ql_dbg_user, vha, 0x70c3, + "Bad status in IDC Completion AEN\n"); + rval = -EINVAL; + ha->flags.idc_compl_status = 0; + } else + ql_dbg(ql_dbg_user, vha, 0x7023, + "State change received.\n"); + } ha->notify_dcbx_comp = 0; diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index fcf55642d33c1..e5a3eda2d683e 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -20,7 +20,7 @@ * | Async Events | 0x5071 | 0x502b-0x502f | * | | | 0x5047,0x5052 | * | Timer Routines | 0x6011 | | - * | User Space Interactions | 0x70c2 | 0x7018,0x702e | + * | User Space Interactions | 0x70c3 | 0x7018,0x702e | * | | | 0x7039,0x7045 | * | | | 0x7073-0x7075 | * | | | 0x708c, | diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 15b36703b95f1..c0624a25d23bd 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2567,7 +2567,8 @@ struct qla_hw_data { uint32_t nic_core_reset_hdlr_active:1; uint32_t nic_core_reset_owner:1; uint32_t isp82xx_no_md_cap:1; - /* 28 bits */ + uint32_t idc_compl_status:1; + /* 31 bits */ } flags; /* This spinlock is used to protect "io transactions", you must diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index b2e81eb129827..e0df54f8ecbf5 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -293,17 +293,20 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) "%04x %04x %04x %04x %04x %04x %04x.\n", event[aen & 0xff], mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]); + if ((aen == MBA_IDC_COMPLETE && mb[1] >> 15)) { + vha->hw->flags.idc_compl_status = 1; + if (vha->hw->notify_dcbx_comp) + complete(&vha->hw->dcbx_comp); + } - if (IS_QLA81XX(vha->hw)) { - /* Acknowledgement needed? [Notify && non-zero timeout]. */ - timeout = (descr >> 8) & 0xf; - if (aen != MBA_IDC_NOTIFY || !timeout) - return; + /* Acknowledgement needed? [Notify && non-zero timeout]. */ + timeout = (descr >> 8) & 0xf; + if (aen != MBA_IDC_NOTIFY || !timeout) + return; - ql_dbg(ql_dbg_async, vha, 0x5022, - "%lu Inter-Driver Communication %s -- ACK timeout=%d.\n", - vha->host_no, event[aen & 0xff], timeout); - } + ql_dbg(ql_dbg_async, vha, 0x5022, + "%lu Inter-Driver Communication %s -- ACK timeout=%d.\n", + vha->host_no, event[aen & 0xff], timeout); rval = qla2x00_post_idc_ack_work(vha, mb); if (rval != QLA_SUCCESS) @@ -982,13 +985,11 @@ skip_rio: if ((mb[2] & 0x7fff) == MBC_PORT_RESET || (mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) { set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags); - /* Ack that we have quiesced I/O */ - qla81xx_idc_event(vha, mb[0], mb[1]); qla2xxx_wake_dpc(vha); } case MBA_IDC_COMPLETE: case MBA_IDC_TIME_EXT: - if (IS_QLA81XX(vha->hw)) + if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw)) qla81xx_idc_event(vha, mb[0], mb[1]); break;