1
0
Fork 0

qla2xxx: Add Host reset handling in target mode.

Signed-off-by: Arun Easi <arun.easi@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
hifive-unleashed-5.1
Arun Easi 2014-09-25 06:14:51 -04:00 committed by Christoph Hellwig
parent dd9c4eff77
commit c0cb44967b
4 changed files with 78 additions and 1 deletions

View File

@ -68,7 +68,7 @@
* | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe |
* | Target Mode | 0xe078 | |
* | Target Mode Management | 0xf072 | 0xf002-0xf003 |
* | Target Mode Management | 0xf072 | 0xf002 |
* | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000b | |
* ----------------------------------------------------------------------

View File

@ -766,4 +766,5 @@ extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t);
extern int qla8044_abort_isp(scsi_qla_host_t *);
extern int qla8044_check_fw_alive(struct scsi_qla_host *);
extern void qlt_host_reset_handler(struct qla_hw_data *ha);
#endif /* _QLA_GBL_H */

View File

@ -1363,6 +1363,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
struct qla_hw_data *ha = vha->hw;
struct req_que *req;
qlt_host_reset_handler(ha);
spin_lock_irqsave(&ha->hardware_lock, flags);
for (que = 0; que < ha->max_req_queues; que++) {
req = ha->req_q_map[que];

View File

@ -2843,6 +2843,80 @@ static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
return cmd;
}
/* hardware_lock should be held by caller. */
static void
qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
{
struct qla_hw_data *ha = vha->hw;
uint32_t handle;
if (cmd->sg_mapped)
qlt_unmap_sg(vha, cmd);
handle = qlt_make_handle(vha);
/* TODO: fix debug message type and ids. */
if (cmd->state == QLA_TGT_STATE_PROCESSED) {
ql_dbg(ql_dbg_io, vha, 0xff00,
"HOST-ABORT: handle=%d, state=PROCESSED.\n", handle);
} else if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
cmd->write_data_transferred = 0;
cmd->state = QLA_TGT_STATE_DATA_IN;
ql_dbg(ql_dbg_io, vha, 0xff01,
"HOST-ABORT: handle=%d, state=DATA_IN.\n", handle);
ha->tgt.tgt_ops->handle_data(cmd);
return;
} else if (cmd->state == QLA_TGT_STATE_ABORTED) {
ql_dbg(ql_dbg_io, vha, 0xff02,
"HOST-ABORT: handle=%d, state=ABORTED.\n", handle);
} else {
ql_dbg(ql_dbg_io, vha, 0xff03,
"HOST-ABORT: handle=%d, state=BAD(%d).\n", handle,
cmd->state);
dump_stack();
}
ha->tgt.tgt_ops->free_cmd(cmd);
}
void
qlt_host_reset_handler(struct qla_hw_data *ha)
{
struct qla_tgt_cmd *cmd;
unsigned long flags;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
scsi_qla_host_t *vha = NULL;
struct qla_tgt *tgt = base_vha->vha_tgt.qla_tgt;
uint32_t i;
if (!base_vha->hw->tgt.tgt_ops)
return;
if (!tgt || qla_ini_mode_enabled(base_vha)) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003,
"Target mode disabled\n");
return;
}
ql_dbg(ql_dbg_tgt_mgt, vha, 0xff10,
"HOST-ABORT-HNDLR: base_vha->dpc_flags=%lx.\n",
base_vha->dpc_flags);
spin_lock_irqsave(&ha->hardware_lock, flags);
for (i = 1; i < DEFAULT_OUTSTANDING_COMMANDS + 1; i++) {
cmd = qlt_get_cmd(base_vha, i);
if (!cmd)
continue;
/* ha->tgt.cmds entry is cleared by qlt_get_cmd. */
vha = cmd->vha;
qlt_abort_cmd_on_host_reset(vha, cmd);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/