Commit 9d562913 authored by David C Somayajulu's avatar David C Somayajulu Committed by James Bottomley

[SCSI] qla4xxx: fix scsi command completion, lun reset and target reset code

This patch contains the following:

1. when hba completion status is good, check for iscsi transport
   errors (underflow/overflow) prior to checking the scsi status

2. New firmware requires that one marker iocb be issued for each task
   management command. The patch issues marker iocb immediately
   following a LUN or Target reset.
Signed-off-by: default avatarDavid C Somayajulu <david.somayajulu@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent af7a5647
...@@ -678,7 +678,8 @@ struct qla4_marker_entry { ...@@ -678,7 +678,8 @@ struct qla4_marker_entry {
uint32_t system_defined; /* 04-07 */ uint32_t system_defined; /* 04-07 */
uint16_t target; /* 08-09 */ uint16_t target; /* 08-09 */
uint16_t modifier; /* 0A-0B */ uint16_t modifier; /* 0A-0B */
#define MM_LUN_RESET 0 #define MM_LUN_RESET 0
#define MM_TGT_WARM_RESET 1
uint16_t flags; /* 0C-0D */ uint16_t flags; /* 0C-0D */
uint16_t reserved1; /* 0E-0F */ uint16_t reserved1; /* 0E-0F */
......
...@@ -70,6 +70,8 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); ...@@ -70,6 +70,8 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
uint32_t fw_ddb_index, uint32_t state); uint32_t fw_ddb_index, uint32_t state);
void qla4xxx_dump_buffer(void *b, uint32_t size); void qla4xxx_dump_buffer(void *b, uint32_t size);
int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
extern int ql4xextended_error_logging; extern int ql4xextended_error_logging;
extern int ql4xdiscoverywait; extern int ql4xdiscoverywait;
......
...@@ -66,8 +66,8 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, ...@@ -66,8 +66,8 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
* *
* This routine issues a marker IOCB. * This routine issues a marker IOCB.
**/ **/
static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry, int lun) struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod)
{ {
struct qla4_marker_entry *marker_entry; struct qla4_marker_entry *marker_entry;
unsigned long flags = 0; unsigned long flags = 0;
...@@ -87,7 +87,7 @@ static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, ...@@ -87,7 +87,7 @@ static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
marker_entry->hdr.entryType = ET_MARKER; marker_entry->hdr.entryType = ET_MARKER;
marker_entry->hdr.entryCount = 1; marker_entry->hdr.entryCount = 1;
marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index); marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
marker_entry->modifier = cpu_to_le16(MM_LUN_RESET); marker_entry->modifier = cpu_to_le16(mrkr_mod);
int_to_scsilun(lun, &marker_entry->lun); int_to_scsilun(lun, &marker_entry->lun);
wmb(); wmb();
...@@ -210,14 +210,6 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) ...@@ -210,14 +210,6 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
/* Get real lun and adapter */ /* Get real lun and adapter */
ddb_entry = srb->ddb; ddb_entry = srb->ddb;
/* Send marker(s) if needed. */
if (ha->marker_needed == 1) {
if (qla4xxx_send_marker_iocb(ha, ddb_entry,
cmd->device->lun) != QLA_SUCCESS)
return QLA_ERROR;
ha->marker_needed = 0;
}
tot_dsds = 0; tot_dsds = 0;
/* Acquire hardware specific lock */ /* Acquire hardware specific lock */
......
...@@ -10,28 +10,6 @@ ...@@ -10,28 +10,6 @@
#include "ql4_dbg.h" #include "ql4_dbg.h"
#include "ql4_inline.h" #include "ql4_inline.h"
/**
* qla2x00_process_completed_request() - Process a Fast Post response.
* @ha: SCSI driver HA context
* @index: SRB index
**/
static void qla4xxx_process_completed_request(struct scsi_qla_host *ha,
uint32_t index)
{
struct srb *srb;
srb = qla4xxx_del_from_active_array(ha, index);
if (srb) {
/* Save ISP completion status */
srb->cmd->result = DID_OK << 16;
qla4xxx_srb_compl(ha, srb);
} else {
DEBUG2(printk("scsi%ld: Invalid ISP SCSI completion handle = "
"%d\n", ha->host_no, index));
set_bit(DPC_RESET_HA, &ha->dpc_flags);
}
}
/** /**
* qla4xxx_status_entry - processes status IOCBs * qla4xxx_status_entry - processes status IOCBs
* @ha: Pointer to host adapter structure. * @ha: Pointer to host adapter structure.
...@@ -47,14 +25,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, ...@@ -47,14 +25,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
uint32_t residual; uint32_t residual;
uint16_t sensebytecnt; uint16_t sensebytecnt;
if (sts_entry->completionStatus == SCS_COMPLETE &&
sts_entry->scsiStatus == 0) {
qla4xxx_process_completed_request(ha,
le32_to_cpu(sts_entry->
handle));
return;
}
srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
if (!srb) { if (!srb) {
/* FIXMEdg: Don't we need to reset ISP in this case??? */ /* FIXMEdg: Don't we need to reset ISP in this case??? */
...@@ -62,6 +32,9 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, ...@@ -62,6 +32,9 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
"handle 0x%x, sp=%p. This cmd may have already " "handle 0x%x, sp=%p. This cmd may have already "
"been completed.\n", ha->host_no, __func__, "been completed.\n", ha->host_no, __func__,
le32_to_cpu(sts_entry->handle), srb)); le32_to_cpu(sts_entry->handle), srb));
dev_warn(&ha->pdev->dev, "%s invalid status entry:"
" handle=0x%0x\n", __func__, sts_entry->handle);
set_bit(DPC_RESET_HA, &ha->dpc_flags);
return; return;
} }
...@@ -88,10 +61,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, ...@@ -88,10 +61,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
scsi_status = sts_entry->scsiStatus; scsi_status = sts_entry->scsiStatus;
switch (sts_entry->completionStatus) { switch (sts_entry->completionStatus) {
case SCS_COMPLETE: case SCS_COMPLETE:
if (scsi_status == 0) {
cmd->result = DID_OK << 16;
break;
}
if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) { if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
cmd->result = DID_ERROR << 16; cmd->result = DID_ERROR << 16;
...@@ -100,7 +69,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, ...@@ -100,7 +69,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) { if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
scsi_set_resid(cmd, residual); scsi_set_resid(cmd, residual);
if ((scsi_bufflen(cmd) - residual) < cmd->underflow) { if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
cmd->underflow)) {
cmd->result = DID_ERROR << 16; cmd->result = DID_ERROR << 16;
......
...@@ -1552,9 +1552,6 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) ...@@ -1552,9 +1552,6 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
goto eh_dev_reset_done; goto eh_dev_reset_done;
} }
/* Send marker. */
ha->marker_needed = 1;
if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
cmd->device)) { cmd->device)) {
dev_info(&ha->pdev->dev, dev_info(&ha->pdev->dev,
...@@ -1563,6 +1560,11 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) ...@@ -1563,6 +1560,11 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
goto eh_dev_reset_done; goto eh_dev_reset_done;
} }
/* Send marker. */
if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
MM_LUN_RESET) != QLA_SUCCESS)
goto eh_dev_reset_done;
dev_info(&ha->pdev->dev, dev_info(&ha->pdev->dev,
"scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
ha->host_no, cmd->device->channel, cmd->device->id, ha->host_no, cmd->device->channel, cmd->device->id,
...@@ -1606,9 +1608,6 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) ...@@ -1606,9 +1608,6 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
return FAILED; return FAILED;
} }
/* Send marker. */
ha->marker_needed = 1;
if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
NULL)) { NULL)) {
starget_printk(KERN_INFO, scsi_target(cmd->device), starget_printk(KERN_INFO, scsi_target(cmd->device),
...@@ -1617,6 +1616,15 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) ...@@ -1617,6 +1616,15 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
return FAILED; return FAILED;
} }
/* Send marker. */
if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
MM_TGT_WARM_RESET) != QLA_SUCCESS) {
starget_printk(KERN_INFO, scsi_target(cmd->device),
"WARM TARGET DEVICE RESET FAILED - "
"marker iocb failed.\n");
return FAILED;
}
starget_printk(KERN_INFO, scsi_target(cmd->device), starget_printk(KERN_INFO, scsi_target(cmd->device),
"WARM TARGET RESET SUCCEEDED.\n"); "WARM TARGET RESET SUCCEEDED.\n");
return SUCCESS; return SUCCESS;
......
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