scsi: arcmsr: Avoid over-read of sense buffer
[linux-2.6-microblaze.git] / drivers / scsi / arcmsr / arcmsr_hba.c
index 4b79661..ec1a834 100644 (file)
@@ -1323,19 +1323,21 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb)
 
 static void arcmsr_report_sense_info(struct CommandControlBlock *ccb)
 {
-
        struct scsi_cmnd *pcmd = ccb->pcmd;
-       struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer;
-       pcmd->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-       if (sensebuffer) {
-               int sense_data_length =
-                       sizeof(struct SENSE_DATA) < SCSI_SENSE_BUFFERSIZE
-                       ? sizeof(struct SENSE_DATA) : SCSI_SENSE_BUFFERSIZE;
-               memset(sensebuffer, 0, SCSI_SENSE_BUFFERSIZE);
-               memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length);
+
+       pcmd->result = (DID_OK << 16) | SAM_STAT_CHECK_CONDITION;
+       if (pcmd->sense_buffer) {
+               struct SENSE_DATA *sensebuffer;
+
+               memcpy_and_pad(pcmd->sense_buffer,
+                              SCSI_SENSE_BUFFERSIZE,
+                              ccb->arcmsr_cdb.SenseData,
+                              sizeof(ccb->arcmsr_cdb.SenseData),
+                              0);
+
+               sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer;
                sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS;
                sensebuffer->Valid = 1;
-               pcmd->result |= (DRIVER_SENSE << 24);
        }
 }
 
@@ -1923,8 +1925,12 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
 
                if (ccb->arc_cdb_size <= 0x300)
                        arc_cdb_size = (ccb->arc_cdb_size - 1) >> 6 | 1;
-               else
-                       arc_cdb_size = (((ccb->arc_cdb_size + 0xff) >> 8) + 2) << 1 | 1;
+               else {
+                       arc_cdb_size = ((ccb->arc_cdb_size + 0xff) >> 8) + 2;
+                       if (arc_cdb_size > 0xF)
+                               arc_cdb_size = 0xF;
+                       arc_cdb_size = (arc_cdb_size << 1) | 1;
+               }
                ccb_post_stamp = (ccb->smid | arc_cdb_size);
                writel(0, &pmu->inbound_queueport_high);
                writel(ccb_post_stamp, &pmu->inbound_queueport_low);
@@ -2415,10 +2421,17 @@ static void arcmsr_hbaD_doorbell_isr(struct AdapterControlBlock *pACB)
 
 static void arcmsr_hbaE_doorbell_isr(struct AdapterControlBlock *pACB)
 {
-       uint32_t outbound_doorbell, in_doorbell, tmp;
+       uint32_t outbound_doorbell, in_doorbell, tmp, i;
        struct MessageUnit_E __iomem *reg = pACB->pmuE;
 
-       in_doorbell = readl(&reg->iobound_doorbell);
+       if (pACB->adapter_type == ACB_ADAPTER_TYPE_F) {
+               for (i = 0; i < 5; i++) {
+                       in_doorbell = readl(&reg->iobound_doorbell);
+                       if (in_doorbell != 0)
+                               break;
+               }
+       } else
+               in_doorbell = readl(&reg->iobound_doorbell);
        outbound_doorbell = in_doorbell ^ pACB->in_doorbell;
        do {
                writel(0, &reg->host_int_status); /* clear interrupt */
@@ -3243,7 +3256,7 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd,
        if (!ccb)
                return SCSI_MLQUEUE_HOST_BUSY;
        if (arcmsr_build_ccb( acb, ccb, cmd ) == FAILED) {
-               cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1);
+               cmd->result = (DID_ERROR << 16) | SAM_STAT_RESERVATION_CONFLICT;
                cmd->scsi_done(cmd);
                return 0;
        }