diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-05-25 10:38:26 +0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-05-25 10:38:26 +0400 |
commit | b1e50ebcf24668e57f058deb48b0704b5391ed0f (patch) | |
tree | 17e1b69b249d0738317b732186340c9dd053f1a1 /drivers/scsi/aacraid | |
parent | 0c2a2ae32793e3500a15a449612485f5d17dd431 (diff) | |
parent | 7e125f7b9cbfce4101191b8076d606c517a73066 (diff) | |
download | linux-b1e50ebcf24668e57f058deb48b0704b5391ed0f.tar.xz |
Merge remote branch 'origin' into secretlab/next-spi
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 67 | ||||
-rw-r--r-- | drivers/scsi/aacraid/aacraid.h | 4 | ||||
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 18 | ||||
-rw-r--r-- | drivers/scsi/aacraid/linit.c | 11 |
4 files changed, 94 insertions, 6 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 7e26ebc26661..7df2dd1d2c6f 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -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; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 619c02d9c862..4dbcc055ac78 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,7 +12,7 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 24702 +# define AAC_DRIVER_BUILD 26400 # define AAC_DRIVER_BRANCH "-ms" #endif #define MAXIMUM_NUM_CONTAINERS 32 @@ -26,6 +26,8 @@ #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) #define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)256) +#define AAC_DEBUG_INSTRUMENT_AIF_DELETE + /* * These macros convert from physical channels to virtual channels */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 94d2954d79ae..70079146e203 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -966,6 +966,16 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) device_config_needed = (((__le32 *)aifcmd->data)[0] == cpu_to_le32(AifEnAddJBOD)) ? ADD : DELETE; + if (device_config_needed == ADD) { + device = scsi_device_lookup(dev->scsi_host_ptr, + channel, + id, + lun); + if (device) { + scsi_remove_device(device); + scsi_device_put(device); + } + } break; case AifEnEnclosureManagement: @@ -1123,6 +1133,9 @@ retry_next: if (device) { switch (device_config_needed) { case DELETE: +#if (defined(AAC_DEBUG_INSTRUMENT_AIF_DELETE)) + scsi_remove_device(device); +#else if (scsi_device_online(device)) { scsi_device_set_state(device, SDEV_OFFLINE); sdev_printk(KERN_INFO, device, @@ -1131,6 +1144,7 @@ retry_next: "array deleted" : "enclosure services event"); } +#endif break; case ADD: if (!scsi_device_online(device)) { @@ -1145,12 +1159,16 @@ retry_next: case CHANGE: if ((channel == CONTAINER_CHANNEL) && (!dev->fsa_dev[container].valid)) { +#if (defined(AAC_DEBUG_INSTRUMENT_AIF_DELETE)) + scsi_remove_device(device); +#else if (!scsi_device_online(device)) break; scsi_device_set_state(device, SDEV_OFFLINE); sdev_printk(KERN_INFO, device, "Device offlined - %s\n", "array failed"); +#endif break; } scsi_rescan_device(&device->sdev_gendev); diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index e9373a2d14fa..33898b61fdb5 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -705,12 +705,17 @@ static int aac_cfg_open(struct inode *inode, struct file *file) * Bugs: Needs to handle hot plugging */ -static int aac_cfg_ioctl(struct inode *inode, struct file *file, +static long aac_cfg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + int ret; if (!capable(CAP_SYS_RAWIO)) return -EPERM; - return aac_do_ioctl(file->private_data, cmd, (void __user *)arg); + lock_kernel(); + ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg); + unlock_kernel(); + + return ret; } #ifdef CONFIG_COMPAT @@ -1029,7 +1034,7 @@ ssize_t aac_get_serial_number(struct device *device, char *buf) static const struct file_operations aac_cfg_fops = { .owner = THIS_MODULE, - .ioctl = aac_cfg_ioctl, + .unlocked_ioctl = aac_cfg_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = aac_compat_cfg_ioctl, #endif |