[SCSI] qla2xxx: Correct extended sense-data handling.
authorAndrew Vasquez <andrew.vasquez@qlogic.com>
Fri, 23 Jul 2010 10:28:27 +0000 (15:28 +0500)
committerJames Bottomley <James.Bottomley@suse.de>
Wed, 28 Jul 2010 14:06:10 +0000 (09:06 -0500)
Earlier implementation did not take into account the varying
sizes of data buffers returned from structures sts_entry_t and
sts_entry_24xx.  Sense-data after the 20th byte could be
incorrect.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/qla2xxx/qla_isr.c

index ba971ac..88b5774 100644 (file)
@@ -1320,8 +1320,9 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
 }
 
 static inline void
-qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len,
-       struct rsp_que *rsp)
+
+qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
+    uint32_t sense_len, struct rsp_que *rsp)
 {
        struct scsi_cmnd *cp = sp->cmd;
 
@@ -1330,8 +1331,8 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len,
 
        sp->request_sense_length = sense_len;
        sp->request_sense_ptr = cp->sense_buffer;
-       if (sp->request_sense_length > 32)
-               sense_len = 32;
+       if (sp->request_sense_length > par_sense_len)
+               sense_len = par_sense_len;
 
        memcpy(cp->sense_buffer, sense_data, sense_len);
 
@@ -1438,7 +1439,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
        uint16_t        ox_id;
        uint8_t         lscsi_status;
        int32_t         resid;
-       uint32_t        sense_len, rsp_info_len, resid_len, fw_resid_len;
+       uint32_t sense_len, par_sense_len, rsp_info_len, resid_len,
+           fw_resid_len;
        uint8_t         *rsp_info, *sense_data;
        struct qla_hw_data *ha = vha->hw;
        uint32_t handle;
@@ -1496,7 +1498,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
        fcport = sp->fcport;
 
        ox_id = 0;
-       sense_len = rsp_info_len = resid_len = fw_resid_len = 0;
+       sense_len = par_sense_len = rsp_info_len = resid_len =
+           fw_resid_len = 0;
        if (IS_FWI2_CAPABLE(ha)) {
                if (scsi_status & SS_SENSE_LEN_VALID)
                        sense_len = le32_to_cpu(sts24->sense_len);
@@ -1510,6 +1513,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                sense_data = sts24->data;
                host_to_fcp_swap(sts24->data, sizeof(sts24->data));
                ox_id = le16_to_cpu(sts24->ox_id);
+               par_sense_len = sizeof(sts24->data);
        } else {
                if (scsi_status & SS_SENSE_LEN_VALID)
                        sense_len = le16_to_cpu(sts->req_sense_length);
@@ -1518,13 +1522,16 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                resid_len = le32_to_cpu(sts->residual_length);
                rsp_info = sts->rsp_info;
                sense_data = sts->req_sense_data;
+               par_sense_len = sizeof(sts->req_sense_data);
        }
 
        /* Check for any FCP transport errors. */
        if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
                /* Sense data lies beyond any FCP RESPONSE data. */
-               if (IS_FWI2_CAPABLE(ha))
+               if (IS_FWI2_CAPABLE(ha)) {
                        sense_data += rsp_info_len;
+                       par_sense_len -= rsp_info_len;
+               }
                if (rsp_info_len > 3 && rsp_info[3]) {
                        DEBUG2(qla_printk(KERN_INFO, ha,
                            "scsi(%ld:%d:%d): FCP I/O protocol failure "
@@ -1584,7 +1591,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                if (!(scsi_status & SS_SENSE_LEN_VALID))
                        break;
 
-               qla2x00_handle_sense(sp, sense_data, sense_len, rsp);
+               qla2x00_handle_sense(sp, sense_data, par_sense_len, sense_len,
+                   rsp);
                break;
 
        case CS_DATA_UNDERRUN:
@@ -1648,7 +1656,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                        if (!(scsi_status & SS_SENSE_LEN_VALID))
                                break;
 
-                       qla2x00_handle_sense(sp, sense_data, sense_len, rsp);
+                       qla2x00_handle_sense(sp, sense_data, par_sense_len,
+                           sense_len, rsp);
                }
                break;