|
@@ -10,6 +10,98 @@
|
|
|
#include "ql4_dbg.h"
|
|
|
#include "ql4_inline.h"
|
|
|
|
|
|
+/**
|
|
|
+ * qla4xxx_copy_sense - copy sense data into cmd sense buffer
|
|
|
+ * @ha: Pointer to host adapter structure.
|
|
|
+ * @sts_entry: Pointer to status entry structure.
|
|
|
+ * @srb: Pointer to srb structure.
|
|
|
+ **/
|
|
|
+static void qla4xxx_copy_sense(struct scsi_qla_host *ha,
|
|
|
+ struct status_entry *sts_entry,
|
|
|
+ struct srb *srb)
|
|
|
+{
|
|
|
+ struct scsi_cmnd *cmd = srb->cmd;
|
|
|
+ uint16_t sense_len;
|
|
|
+
|
|
|
+ memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
|
|
|
+ sense_len = le16_to_cpu(sts_entry->senseDataByteCnt);
|
|
|
+ if (sense_len == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* Save total available sense length,
|
|
|
+ * not to exceed cmd's sense buffer size */
|
|
|
+ sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE);
|
|
|
+ srb->req_sense_ptr = cmd->sense_buffer;
|
|
|
+ srb->req_sense_len = sense_len;
|
|
|
+
|
|
|
+ /* Copy sense from sts_entry pkt */
|
|
|
+ sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN);
|
|
|
+ memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len);
|
|
|
+
|
|
|
+ DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: %s: sense key = %x, "
|
|
|
+ "ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no,
|
|
|
+ cmd->device->channel, cmd->device->id,
|
|
|
+ cmd->device->lun, __func__,
|
|
|
+ sts_entry->senseData[2] & 0x0f,
|
|
|
+ sts_entry->senseData[7],
|
|
|
+ sts_entry->senseData[12],
|
|
|
+ sts_entry->senseData[13]));
|
|
|
+
|
|
|
+ DEBUG5(qla4xxx_dump_buffer(cmd->sense_buffer, sense_len));
|
|
|
+ srb->flags |= SRB_GOT_SENSE;
|
|
|
+
|
|
|
+ /* Update srb, in case a sts_cont pkt follows */
|
|
|
+ srb->req_sense_ptr += sense_len;
|
|
|
+ srb->req_sense_len -= sense_len;
|
|
|
+ if (srb->req_sense_len != 0)
|
|
|
+ ha->status_srb = srb;
|
|
|
+ else
|
|
|
+ ha->status_srb = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * qla4xxx_status_cont_entry - Process a Status Continuations entry.
|
|
|
+ * @ha: SCSI driver HA context
|
|
|
+ * @sts_cont: Entry pointer
|
|
|
+ *
|
|
|
+ * Extended sense data.
|
|
|
+ */
|
|
|
+static void
|
|
|
+qla4xxx_status_cont_entry(struct scsi_qla_host *ha,
|
|
|
+ struct status_cont_entry *sts_cont)
|
|
|
+{
|
|
|
+ struct srb *srb = ha->status_srb;
|
|
|
+ struct scsi_cmnd *cmd;
|
|
|
+ uint8_t sense_len;
|
|
|
+
|
|
|
+ if (srb == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ cmd = srb->cmd;
|
|
|
+ if (cmd == NULL) {
|
|
|
+ DEBUG2(printk(KERN_INFO "scsi%ld: %s: Cmd already returned "
|
|
|
+ "back to OS srb=%p srb->state:%d\n", ha->host_no,
|
|
|
+ __func__, srb, srb->state));
|
|
|
+ ha->status_srb = NULL;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Copy sense data. */
|
|
|
+ sense_len = min_t(uint16_t, srb->req_sense_len,
|
|
|
+ IOCB_MAX_EXT_SENSEDATA_LEN);
|
|
|
+ memcpy(srb->req_sense_ptr, sts_cont->ext_sense_data, sense_len);
|
|
|
+ DEBUG5(qla4xxx_dump_buffer(srb->req_sense_ptr, sense_len));
|
|
|
+
|
|
|
+ srb->req_sense_ptr += sense_len;
|
|
|
+ srb->req_sense_len -= sense_len;
|
|
|
+
|
|
|
+ /* Place command on done queue. */
|
|
|
+ if (srb->req_sense_len == 0) {
|
|
|
+ qla4xxx_srb_compl(ha, srb);
|
|
|
+ ha->status_srb = NULL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* qla4xxx_status_entry - processes status IOCBs
|
|
|
* @ha: Pointer to host adapter structure.
|
|
@@ -23,7 +115,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
|
|
|
struct srb *srb;
|
|
|
struct ddb_entry *ddb_entry;
|
|
|
uint32_t residual;
|
|
|
- uint16_t sensebytecnt;
|
|
|
|
|
|
srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
|
|
|
if (!srb) {
|
|
@@ -92,24 +183,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
|
|
|
break;
|
|
|
|
|
|
/* Copy Sense Data into sense buffer. */
|
|
|
- memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
|
|
|
-
|
|
|
- sensebytecnt = le16_to_cpu(sts_entry->senseDataByteCnt);
|
|
|
- if (sensebytecnt == 0)
|
|
|
- break;
|
|
|
-
|
|
|
- memcpy(cmd->sense_buffer, sts_entry->senseData,
|
|
|
- min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE));
|
|
|
-
|
|
|
- DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, "
|
|
|
- "ASC/ASCQ = %02x/%02x\n", ha->host_no,
|
|
|
- cmd->device->channel, cmd->device->id,
|
|
|
- cmd->device->lun, __func__,
|
|
|
- sts_entry->senseData[2] & 0x0f,
|
|
|
- sts_entry->senseData[12],
|
|
|
- sts_entry->senseData[13]));
|
|
|
-
|
|
|
- srb->flags |= SRB_GOT_SENSE;
|
|
|
+ qla4xxx_copy_sense(ha, sts_entry, srb);
|
|
|
break;
|
|
|
|
|
|
case SCS_INCOMPLETE:
|
|
@@ -176,23 +250,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
|
|
|
break;
|
|
|
|
|
|
/* Copy Sense Data into sense buffer. */
|
|
|
- memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
|
|
|
-
|
|
|
- sensebytecnt =
|
|
|
- le16_to_cpu(sts_entry->senseDataByteCnt);
|
|
|
- if (sensebytecnt == 0)
|
|
|
- break;
|
|
|
-
|
|
|
- memcpy(cmd->sense_buffer, sts_entry->senseData,
|
|
|
- min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE));
|
|
|
-
|
|
|
- DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, "
|
|
|
- "ASC/ASCQ = %02x/%02x\n", ha->host_no,
|
|
|
- cmd->device->channel, cmd->device->id,
|
|
|
- cmd->device->lun, __func__,
|
|
|
- sts_entry->senseData[2] & 0x0f,
|
|
|
- sts_entry->senseData[12],
|
|
|
- sts_entry->senseData[13]));
|
|
|
+ qla4xxx_copy_sense(ha, sts_entry, srb);
|
|
|
} else {
|
|
|
/*
|
|
|
* If RISC reports underrun and target does not
|
|
@@ -268,9 +326,10 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
|
|
|
|
|
|
status_entry_exit:
|
|
|
|
|
|
- /* complete the request */
|
|
|
+ /* complete the request, if not waiting for status_continuation pkt */
|
|
|
srb->cc_stat = sts_entry->completionStatus;
|
|
|
- qla4xxx_srb_compl(ha, srb);
|
|
|
+ if (ha->status_srb == NULL)
|
|
|
+ qla4xxx_srb_compl(ha, srb);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -305,10 +364,7 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
|
|
|
/* process entry */
|
|
|
switch (sts_entry->hdr.entryType) {
|
|
|
case ET_STATUS:
|
|
|
- /*
|
|
|
- * Common status - Single completion posted in single
|
|
|
- * IOSB.
|
|
|
- */
|
|
|
+ /* Common status */
|
|
|
qla4xxx_status_entry(ha, sts_entry);
|
|
|
break;
|
|
|
|
|
@@ -316,9 +372,8 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
|
|
|
break;
|
|
|
|
|
|
case ET_STATUS_CONTINUATION:
|
|
|
- /* Just throw away the status continuation entries */
|
|
|
- DEBUG2(printk("scsi%ld: %s: Status Continuation entry "
|
|
|
- "- ignoring\n", ha->host_no, __func__));
|
|
|
+ qla4xxx_status_cont_entry(ha,
|
|
|
+ (struct status_cont_entry *) sts_entry);
|
|
|
break;
|
|
|
|
|
|
case ET_COMMAND:
|