[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: David C Somayajulu <david.somayajulu@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
af7a5647c0
commit
9d56291366
5 changed files with 26 additions and 53 deletions
|
@ -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);
|
||||||
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,
|
||||||
*
|
*
|
||||||
* 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,
|
||||||
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)
|
||||||
/* 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 @@
|
||||||
#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,
|
||||||
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,
|
||||||
"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,
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue