Commit 801f4063 authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley

[PATCH] PATCH [13/15] qla2xxx: Device reset fix

During a back-door device reset call, hold off execution of
commands until the reset is complete.
parent 65be55a7
...@@ -664,6 +664,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)) ...@@ -664,6 +664,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
host = cmd->device->host; host = cmd->device->host;
ha = (scsi_qla_host_t *) host->hostdata; ha = (scsi_qla_host_t *) host->hostdata;
was_empty = 1;
cmd->scsi_done = fn; cmd->scsi_done = fn;
...@@ -812,13 +813,17 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)) ...@@ -812,13 +813,17 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
sp->err_id = SRB_ERR_PORT; sp->err_id = SRB_ERR_PORT;
add_to_done_queue(ha, sp); add_to_done_queue(ha, sp);
if (!list_empty(&ha->done_queue)) qla2x00_done(ha);
qla2x00_done(ha);
spin_lock_irq(ha->host->host_lock); spin_lock_irq(ha->host->host_lock);
return (0); return (0);
} }
was_empty = add_to_pending_queue(ha, sp); if (tq && test_bit(TQF_SUSPENDED, &tq->flags)) {
/* If target suspended put incoming I/O in retry_q. */
qla2x00_extend_timeout(sp->cmd, 10);
add_to_scsi_retry_queue(ha, sp);
} else
was_empty = add_to_pending_queue(ha, sp);
if ((IS_QLA2100(ha) || IS_QLA2200(ha)) && ha->flags.online) { if ((IS_QLA2100(ha) || IS_QLA2200(ha)) && ha->flags.online) {
unsigned long flags; unsigned long flags;
...@@ -1344,6 +1349,9 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) ...@@ -1344,6 +1349,9 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
os_tgt_t *tq; os_tgt_t *tq;
os_lun_t *lq; os_lun_t *lq;
fc_port_t *fcport_to_reset; fc_port_t *fcport_to_reset;
unsigned long flags;
srb_t *rp;
struct list_head *list, *temp;
return_status = FAILED; return_status = FAILED;
if (cmd == NULL) { if (cmd == NULL) {
...@@ -1375,6 +1383,10 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) ...@@ -1375,6 +1383,10 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
} }
fcport_to_reset = lq->fclun->fcport; fcport_to_reset = lq->fclun->fcport;
/* If we are coming in from the back-door, stall I/O until complete. */
if (!cmd->device->host->eh_active)
set_bit(TQF_SUSPENDED, &tq->flags);
qla_printk(KERN_INFO, ha, qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, b, t, l); "scsi(%ld:%d:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, b, t, l);
...@@ -1384,6 +1396,23 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) ...@@ -1384,6 +1396,23 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ, ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ,
ha->dpc_flags, cmd->result, cmd->allowed, cmd->state)); ha->dpc_flags, cmd->result, cmd->allowed, cmd->state));
/* Clear commands from the retry queue. */
spin_lock_irqsave(&ha->list_lock, flags);
list_for_each_safe(list, temp, &ha->retry_queue) {
rp = list_entry(list, srb_t, list);
if (t != rp->cmd->device->id)
continue;
DEBUG2(printk(KERN_INFO
"qla2xxx_eh_reset: found in retry queue. SP=%p\n", rp));
__del_from_retry_queue(ha, rp);
rp->cmd->result = DID_RESET << 16;
__add_to_done_queue(ha, rp);
}
spin_unlock_irqrestore(&ha->list_lock, flags);
spin_unlock_irq(ha->host->host_lock); spin_unlock_irq(ha->host->host_lock);
/* Blocking call-Does context switching if abort isp is active etc */ /* Blocking call-Does context switching if abort isp is active etc */
...@@ -1451,6 +1480,9 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) ...@@ -1451,6 +1480,9 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
eh_dev_reset_done: eh_dev_reset_done:
if (!cmd->device->host->eh_active)
clear_bit(TQF_SUSPENDED, &tq->flags);
return (return_status); return (return_status);
} }
...@@ -3155,7 +3187,10 @@ qla2x00_do_dpc(void *data) ...@@ -3155,7 +3187,10 @@ qla2x00_do_dpc(void *data)
unsigned long flags = 0; unsigned long flags = 0;
struct list_head *list, *templist; struct list_head *list, *templist;
int dead_cnt, online_cnt; int dead_cnt, online_cnt;
int retry_cmds = 0;
uint16_t next_loopid; uint16_t next_loopid;
int t;
os_tgt_t *tq;
ha = (scsi_qla_host_t *)data; ha = (scsi_qla_host_t *)data;
...@@ -3267,6 +3302,7 @@ qla2x00_do_dpc(void *data) ...@@ -3267,6 +3302,7 @@ qla2x00_do_dpc(void *data)
sp = list_entry(list, srb_t, list); sp = list_entry(list, srb_t, list);
q = sp->lun_queue; q = sp->lun_queue;
tq = sp->tgt_queue;
DEBUG3(printk("scsi(%ld): scsi_retry_q: " DEBUG3(printk("scsi(%ld): scsi_retry_q: "
"pid=%ld sp=%p, spflags=0x%x, " "pid=%ld sp=%p, spflags=0x%x, "
...@@ -3278,7 +3314,15 @@ qla2x00_do_dpc(void *data) ...@@ -3278,7 +3314,15 @@ qla2x00_do_dpc(void *data)
if (q->q_state != LUN_STATE_WAIT) { if (q->q_state != LUN_STATE_WAIT) {
online_cnt++; online_cnt++;
__del_from_scsi_retry_queue(ha, sp); __del_from_scsi_retry_queue(ha, sp);
__add_to_retry_queue(ha,sp);
if (test_bit(TQF_RETRY_CMDS,
&tq->flags)) {
qla2x00_extend_timeout(sp->cmd,
(sp->cmd->timeout_per_command / HZ) - QLA_CMD_TIMER_DELTA);
__add_to_pending_queue(ha, sp);
retry_cmds++;
} else
__add_to_retry_queue(ha, sp);
} }
/* Was this command suspended for N secs */ /* Was this command suspended for N secs */
...@@ -3294,6 +3338,17 @@ qla2x00_do_dpc(void *data) ...@@ -3294,6 +3338,17 @@ qla2x00_do_dpc(void *data)
} }
spin_unlock_irqrestore(&ha->list_lock, flags); spin_unlock_irqrestore(&ha->list_lock, flags);
/* Clear all Target Unsuspended bits */
for (t = 0; t < ha->max_targets; t++) {
if ((tq = ha->otgt[t]) == NULL)
continue;
if (test_bit(TQF_RETRY_CMDS, &tq->flags))
clear_bit(TQF_RETRY_CMDS, &tq->flags);
}
if (retry_cmds)
qla2x00_next(ha);
DEBUG(if (online_cnt > 0)) DEBUG(if (online_cnt > 0))
DEBUG(printk("scsi(%ld): dpc() found scsi reqs to " DEBUG(printk("scsi(%ld): dpc() found scsi reqs to "
"restart= %d\n", "restart= %d\n",
......
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