Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier...
[sfrench/cifs-2.6.git] / drivers / scsi / aacraid / aachba.c
index 7e26ebc266614ad18030622a4db2c7cc16c9f450..7df2dd1d2c6f8c014b10ad560d49c731e6477347 100644 (file)
@@ -328,6 +328,16 @@ int aac_get_config_status(struct aac_dev *dev, int commit_flag)
        return status;
 }
 
+static void aac_expose_phy_device(struct scsi_cmnd *scsicmd)
+{
+       char inq_data;
+       scsi_sg_copy_to_buffer(scsicmd,  &inq_data, sizeof(inq_data));
+       if ((inq_data & 0x20) && (inq_data & 0x1f) == TYPE_DISK) {
+               inq_data &= 0xdf;
+               scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
+       }
+}
+
 /**
  *     aac_get_containers      -       list containers
  *     @common: adapter to probe
@@ -1598,6 +1608,7 @@ static int aac_read(struct scsi_cmnd * scsicmd)
        int status;
        struct aac_dev *dev;
        struct fib * cmd_fibcontext;
+       int cid;
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        /*
@@ -1647,6 +1658,22 @@ static int aac_read(struct scsi_cmnd * scsicmd)
                count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
                break;
        }
+
+       if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
+               cid = scmd_id(scsicmd);
+               dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
+                       SAM_STAT_CHECK_CONDITION;
+               set_sense(&dev->fsa_dev[cid].sense_data,
+                         HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+                         ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
+               memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+                      min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
+                            SCSI_SENSE_BUFFERSIZE));
+               scsicmd->scsi_done(scsicmd);
+               return 1;
+       }
+
        dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
          smp_processor_id(), (unsigned long long)lba, jiffies));
        if (aac_adapter_bounds(dev,scsicmd,lba))
@@ -1688,6 +1715,7 @@ static int aac_write(struct scsi_cmnd * scsicmd)
        int status;
        struct aac_dev *dev;
        struct fib * cmd_fibcontext;
+       int cid;
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        /*
@@ -1727,6 +1755,22 @@ static int aac_write(struct scsi_cmnd * scsicmd)
                count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
                fua = scsicmd->cmnd[1] & 0x8;
        }
+
+       if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
+               cid = scmd_id(scsicmd);
+               dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
+                       SAM_STAT_CHECK_CONDITION;
+               set_sense(&dev->fsa_dev[cid].sense_data,
+                         HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+                         ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
+               memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+                      min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
+                            SCSI_SENSE_BUFFERSIZE));
+               scsicmd->scsi_done(scsicmd);
+               return 1;
+       }
+
        dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
          smp_processor_id(), (unsigned long long)lba, jiffies));
        if (aac_adapter_bounds(dev,scsicmd,lba))
@@ -2573,6 +2617,11 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
 
        scsi_dma_unmap(scsicmd);
 
+       /* expose physical device if expose_physicald flag is on */
+       if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
+         && expose_physicals > 0)
+               aac_expose_phy_device(scsicmd);
+
        /*
         * First check the fib status
         */
@@ -2678,8 +2727,22 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                        scsicmd->cmnd[0],
                        le32_to_cpu(srbreply->scsi_status));
 #endif
-               scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
-               break;
+               if ((scsicmd->cmnd[0] == ATA_12)
+                 || (scsicmd->cmnd[0] == ATA_16)) {
+                       if (scsicmd->cmnd[2] & (0x01 << 5)) {
+                               scsicmd->result = DID_OK << 16
+                                               | COMMAND_COMPLETE << 8;
+                               break;
+                       } else {
+                               scsicmd->result = DID_ERROR << 16
+                                               | COMMAND_COMPLETE << 8;
+                               break;
+                       }
+               } else {
+                       scsicmd->result = DID_ERROR << 16
+                                       | COMMAND_COMPLETE << 8;
+                       break;
+               }
        }
        if (le32_to_cpu(srbreply->scsi_status) == SAM_STAT_CHECK_CONDITION) {
                int len;