Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 360234
b: refs/heads/master
c: 67b2a31
h: refs/heads/master
v: v3
  • Loading branch information
Chad Dupuis authored and James Bottomley committed Feb 22, 2013
1 parent ca92cec commit df947b9
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 57 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b00ee7d770abbe1e63df74eada0376c75ceb2daf
refs/heads/master: 67b2a31f517a43631af218d146e39f4e502b3e83
127 changes: 75 additions & 52 deletions trunk/drivers/scsi/qla2xxx/qla_bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,58 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
done:
return rval;
}

/* Disable loopback mode */
static inline int
qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
int wait)
{
int ret = 0;
int rval = 0;
uint16_t new_config[4];
struct qla_hw_data *ha = vha->hw;

if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
goto done_reset_internal;

memset(new_config, 0 , sizeof(new_config));
if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
ENABLE_INTERNAL_LOOPBACK ||
(config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
ENABLE_EXTERNAL_LOOPBACK) {
new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
ql_dbg(ql_dbg_user, vha, 0x70bf, "new_config[0]=%02x\n",
(new_config[0] & INTERNAL_LOOPBACK_MASK));
memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;

ha->notify_dcbx_comp = wait;
ret = qla81xx_set_port_config(vha, new_config);
if (ret != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x7025,
"Set port config failed.\n");
ha->notify_dcbx_comp = 0;
rval = -EINVAL;
goto done_reset_internal;
}

/* Wait for DCBX complete event */
if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
(20 * HZ))) {
ql_dbg(ql_dbg_user, vha, 0x7026,
"State change notification not received.\n");
ha->notify_dcbx_comp = 0;
rval = -EINVAL;
goto done_reset_internal;
} else
ql_dbg(ql_dbg_user, vha, 0x7027,
"State change received.\n");

ha->notify_dcbx_comp = 0;
}
done_reset_internal:
return rval;
}

/*
* Set the port configuration to enable the internal or external loopback
* depending on the loopback mode.
Expand Down Expand Up @@ -569,6 +621,15 @@ 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");
ret = qla81xx_reset_loopback_mode(vha, new_config, 0);
/*
* If the reset of the loopback mode doesn't work take a FCoE
* dump and reset the chip.
*/
if (ret) {
ha->isp_ops->fw_dump(vha, 0);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
}
rval = -EINVAL;
} else {
if (ha->flags.idc_compl_status) {
Expand All @@ -587,57 +648,6 @@ qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
return rval;
}

/* Disable loopback mode */
static inline int
qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
int wait)
{
int ret = 0;
int rval = 0;
uint16_t new_config[4];
struct qla_hw_data *ha = vha->hw;

if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
goto done_reset_internal;

memset(new_config, 0 , sizeof(new_config));
if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
ENABLE_INTERNAL_LOOPBACK ||
(config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
ENABLE_EXTERNAL_LOOPBACK) {
new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
ql_dbg(ql_dbg_user, vha, 0x70bf, "new_config[0]=%02x\n",
(new_config[0] & INTERNAL_LOOPBACK_MASK));
memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;

ha->notify_dcbx_comp = wait;
ret = qla81xx_set_port_config(vha, new_config);
if (ret != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x7025,
"Set port config failed.\n");
ha->notify_dcbx_comp = 0;
rval = -EINVAL;
goto done_reset_internal;
}

/* Wait for DCBX complete event */
if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
(20 * HZ))) {
ql_dbg(ql_dbg_user, vha, 0x7026,
"State change notification not received.\n");
ha->notify_dcbx_comp = 0;
rval = -EINVAL;
goto done_reset_internal;
} else
ql_dbg(ql_dbg_user, vha, 0x7027,
"State change received.\n");

ha->notify_dcbx_comp = 0;
}
done_reset_internal:
return rval;
}

static int
qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
{
Expand Down Expand Up @@ -781,11 +791,24 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
rval = qla2x00_loopback_test(vha, &elreq, response);

if (new_config[0]) {
int ret;

/* Revert back to original port config
* Also clear internal loopback
*/
qla81xx_reset_loopback_mode(vha,
ret = qla81xx_reset_loopback_mode(vha,
new_config, 0);
if (ret) {
/*
* If the reset of the loopback mode
* doesn't work take FCoE dump and then
* reset the chip.
*/
ha->isp_ops->fw_dump(vha, 0);
set_bit(ISP_ABORT_NEEDED,
&vha->dpc_flags);
}

}

if (response[0] == MBS_COMMAND_ERROR &&
Expand Down
16 changes: 12 additions & 4 deletions trunk/drivers/scsi/qla2xxx/qla_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -985,13 +985,21 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
mb[1], mb[2], mb[3]);
break;
case MBA_IDC_NOTIFY:
/* See if we need to quiesce any I/O */
if (IS_QLA8031(vha->hw))
if ((mb[2] & 0x7fff) == MBC_PORT_RESET ||
(mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) {
if (IS_QLA8031(vha->hw)) {
mb[4] = RD_REG_WORD(&reg24->mailbox4);
if (((mb[2] & 0x7fff) == MBC_PORT_RESET ||
(mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) &&
(mb[4] & INTERNAL_LOOPBACK_MASK) != 0) {
set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
/*
* Extend loop down timer since port is active.
*/
if (atomic_read(&vha->loop_state) == LOOP_DOWN)
atomic_set(&vha->loop_down_timer,
LOOP_DOWN_TIME);
qla2xxx_wake_dpc(vha);
}
}
case MBA_IDC_COMPLETE:
case MBA_IDC_TIME_EXT:
if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw))
Expand Down

0 comments on commit df947b9

Please sign in to comment.