Commit b6a029e1 authored by Arun Easi's avatar Arun Easi Committed by Christoph Hellwig

qla2xxx: Handle chip reset in target mode.

A chip reset can occur after driver submits command to the stack. Abort
command processing if a chip reset has occurred or in progress when you
get a follow up for a command.
Signed-off-by: default avatarArun Easi <arun.easi@qlogic.com>
Signed-off-by: default avatarSaurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent c0cb4496
...@@ -3446,6 +3446,7 @@ struct qla_hw_data { ...@@ -3446,6 +3446,7 @@ struct qla_hw_data {
struct work_struct board_disable; struct work_struct board_disable;
struct mr_data_fx00 mr; struct mr_data_fx00 mr;
uint32_t chip_reset;
struct qlt_hw_data tgt; struct qlt_hw_data tgt;
int allow_cna_fw_dump; int allow_cna_fw_dump;
......
...@@ -72,6 +72,7 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, ...@@ -72,6 +72,7 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *, extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *); uint16_t *);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *); extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
extern void *qla2x00_alloc_iocbs_ready(struct scsi_qla_host *, srb_t *);
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *); extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
extern fc_port_t * extern fc_port_t *
......
...@@ -4575,6 +4575,10 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) ...@@ -4575,6 +4575,10 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
/* Requeue all commands in outstanding command list. */ /* Requeue all commands in outstanding command list. */
qla2x00_abort_all_cmds(vha, DID_RESET << 16); qla2x00_abort_all_cmds(vha, DID_RESET << 16);
} }
ha->chip_reset++;
/* memory barrier */
wmb();
} }
/* /*
......
...@@ -1858,6 +1858,17 @@ static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) ...@@ -1858,6 +1858,17 @@ static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp)
} }
/* Generic Control-SRB manipulation functions. */ /* Generic Control-SRB manipulation functions. */
/* hardware_lock assumed to be held. */
void *
qla2x00_alloc_iocbs_ready(scsi_qla_host_t *vha, srb_t *sp)
{
if (qla2x00_reset_active(vha))
return NULL;
return qla2x00_alloc_iocbs(vha, sp);
}
void * void *
qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp) qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
{ {
......
...@@ -106,6 +106,8 @@ static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd ...@@ -106,6 +106,8 @@ static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd
*cmd, struct atio_from_isp *atio, int ha_locked); *cmd, struct atio_from_isp *atio, int ha_locked);
static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha, static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha,
struct qla_tgt_srr_imm *imm, int ha_lock); struct qla_tgt_srr_imm *imm, int ha_lock);
static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
struct qla_tgt_cmd *cmd);
/* /*
* Global Variables * Global Variables
*/ */
...@@ -1036,7 +1038,7 @@ static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha, ...@@ -1036,7 +1038,7 @@ static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha,
if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) if (qlt_issue_marker(vha, 1) != QLA_SUCCESS)
return; return;
resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs(vha, NULL); resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs_ready(vha, NULL);
if (!resp) { if (!resp) {
ql_dbg(ql_dbg_tgt, vha, 0xe04a, ql_dbg(ql_dbg_tgt, vha, 0xe04a,
"qla_target(%d): %s failed: unable to allocate " "qla_target(%d): %s failed: unable to allocate "
...@@ -1107,7 +1109,7 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, ...@@ -1107,7 +1109,7 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) if (qlt_issue_marker(vha, 1) != QLA_SUCCESS)
return; return;
ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(vha, NULL); ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs_ready(vha, NULL);
if (ctio == NULL) { if (ctio == NULL) {
ql_dbg(ql_dbg_tgt, vha, 0xe04b, ql_dbg(ql_dbg_tgt, vha, 0xe04b,
"qla_target(%d): %s failed: unable to allocate " "qla_target(%d): %s failed: unable to allocate "
...@@ -1326,6 +1328,21 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) ...@@ -1326,6 +1328,21 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
mcmd, mcmd->fc_tm_rsp, mcmd->flags); mcmd, mcmd->fc_tm_rsp, mcmd->flags);
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
if (qla2x00_reset_active(vha) || mcmd->reset_count != ha->chip_reset) {
/*
* Either a chip reset is active or this request was from
* previous life, just abort the processing.
*/
ql_dbg(ql_dbg_async, vha, 0xe100,
"RESET-TMR active/old-count/new-count = %d/%d/%d.\n",
qla2x00_reset_active(vha), mcmd->reset_count,
ha->chip_reset);
ha->tgt.tgt_ops->free_mcmd(mcmd);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return;
}
if (mcmd->flags == QLA24XX_MGMT_SEND_NACK) if (mcmd->flags == QLA24XX_MGMT_SEND_NACK)
qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy, qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy,
0, 0, 0, 0, 0, 0); 0, 0, 0, 0, 0, 0);
...@@ -2269,6 +2286,21 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, ...@@ -2269,6 +2286,21 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
if (qla2x00_reset_active(vha) || cmd->reset_count != ha->chip_reset) {
/*
* Either a chip reset is active or this request was from
* previous life, just abort the processing.
*/
cmd->state = QLA_TGT_STATE_PROCESSED;
qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
ql_dbg(ql_dbg_async, vha, 0xe101,
"RESET-RSP active/old-count/new-count = %d/%d/%d.\n",
qla2x00_reset_active(vha), cmd->reset_count,
ha->chip_reset);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return 0;
}
/* Does F/W have an IOCBs for this request */ /* Does F/W have an IOCBs for this request */
res = qlt_check_reserve_free_req(vha, full_req_cnt); res = qlt_check_reserve_free_req(vha, full_req_cnt);
if (unlikely(res)) if (unlikely(res))
...@@ -2392,6 +2424,21 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) ...@@ -2392,6 +2424,21 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
if (qla2x00_reset_active(vha) || cmd->reset_count != ha->chip_reset) {
/*
* Either a chip reset is active or this request was from
* previous life, just abort the processing.
*/
cmd->state = QLA_TGT_STATE_NEED_DATA;
qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
ql_dbg(ql_dbg_async, vha, 0xe102,
"RESET-XFR active/old-count/new-count = %d/%d/%d.\n",
qla2x00_reset_active(vha), cmd->reset_count,
ha->chip_reset);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return 0;
}
/* Does F/W have an IOCBs for this request */ /* Does F/W have an IOCBs for this request */
res = qlt_check_reserve_free_req(vha, prm.req_cnt); res = qlt_check_reserve_free_req(vha, prm.req_cnt);
if (res != 0) if (res != 0)
...@@ -2577,7 +2624,7 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, ...@@ -2577,7 +2624,7 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt, vha, 0xe01c, "Sending TERM EXCH CTIO (ha=%p)\n", ha); ql_dbg(ql_dbg_tgt, vha, 0xe01c, "Sending TERM EXCH CTIO (ha=%p)\n", ha);
pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL);
if (pkt == NULL) { if (pkt == NULL) {
ql_dbg(ql_dbg_tgt, vha, 0xe050, ql_dbg(ql_dbg_tgt, vha, 0xe050,
"qla_target(%d): %s failed: unable to allocate " "qla_target(%d): %s failed: unable to allocate "
...@@ -3305,6 +3352,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, ...@@ -3305,6 +3352,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
return -ENOMEM; return -ENOMEM;
} }
cmd->reset_count = vha->hw->chip_reset;
INIT_WORK(&cmd->work, qlt_do_work); INIT_WORK(&cmd->work, qlt_do_work);
queue_work(qla_tgt_wq, &cmd->work); queue_work(qla_tgt_wq, &cmd->work);
return 0; return 0;
...@@ -3338,6 +3387,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, ...@@ -3338,6 +3387,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
} }
mcmd->tmr_func = fn; mcmd->tmr_func = fn;
mcmd->flags = flags; mcmd->flags = flags;
mcmd->reset_count = vha->hw->chip_reset;
switch (fn) { switch (fn) {
case QLA_TGT_CLEAR_ACA: case QLA_TGT_CLEAR_ACA:
......
...@@ -923,6 +923,7 @@ struct qla_tgt_cmd { ...@@ -923,6 +923,7 @@ struct qla_tgt_cmd {
uint32_t tag; uint32_t tag;
uint32_t unpacked_lun; uint32_t unpacked_lun;
enum dma_data_direction dma_data_direction; enum dma_data_direction dma_data_direction;
uint32_t reset_count;
uint16_t loop_id; /* to save extra sess dereferences */ uint16_t loop_id; /* to save extra sess dereferences */
struct qla_tgt *tgt; /* to save extra sess dereferences */ struct qla_tgt *tgt; /* to save extra sess dereferences */
...@@ -958,6 +959,7 @@ struct qla_tgt_mgmt_cmd { ...@@ -958,6 +959,7 @@ struct qla_tgt_mgmt_cmd {
struct se_cmd se_cmd; struct se_cmd se_cmd;
struct work_struct free_work; struct work_struct free_work;
unsigned int flags; unsigned int flags;
uint32_t reset_count;
#define QLA24XX_MGMT_SEND_NACK 1 #define QLA24XX_MGMT_SEND_NACK 1
union { union {
struct atio_from_isp atio; struct atio_from_isp atio;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment