aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSreekanth Reddy <sreekanth.reddy@avagotech.com>2014-09-12 06:05:21 -0400
committerChristoph Hellwig <hch@lst.de>2014-09-16 12:14:15 -0400
commitdaeaa9df92bd742f4e6d4d6039d689277a8e31bd (patch)
tree712a7a2df69c28e69b9e0308e54c3836deb8fbe3
parent49563e1e4b202436a36409f365b0a96796db5aad (diff)
mpt2sas: Avoid type casting for direct I/O commands
A type casting error caused the max volume LBA to be truncated from 64 to 32 bits. The virtual LBA would also get truncated to 32 bits in the case of a 16-byte READ/WRITE command. Rewrite entire function to get rid of code duplication and type casts. Use get/put_unaligned wrappers to extract and replace the LBA field in the MPI request CDB. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Tested-by: Sreekanth Reddy <Sreekanth.Reddy@avagotech.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c117
1 files changed, 40 insertions, 77 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index e7303edc3d8e..231ec34d8ea9 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -55,6 +55,8 @@
55#include <linux/raid_class.h> 55#include <linux/raid_class.h>
56#include <linux/slab.h> 56#include <linux/slab.h>
57 57
58#include <asm/unaligned.h>
59
58#include "mpt2sas_base.h" 60#include "mpt2sas_base.h"
59 61
60MODULE_AUTHOR(MPT2SAS_AUTHOR); 62MODULE_AUTHOR(MPT2SAS_AUTHOR);
@@ -3858,85 +3860,46 @@ _scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3858 struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request, 3860 struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
3859 u16 smid) 3861 u16 smid)
3860{ 3862{
3861 u32 v_lba, p_lba, stripe_off, stripe_unit, column, io_size; 3863 sector_t v_lba, p_lba, stripe_off, stripe_unit, column, io_size;
3862 u32 stripe_sz, stripe_exp; 3864 u32 stripe_sz, stripe_exp;
3863 u8 num_pds, *cdb_ptr, i; 3865 u8 num_pds, cmd = scmd->cmnd[0];
3864 u8 cdb0 = scmd->cmnd[0];
3865 u64 v_llba;
3866 3866
3867 /* 3867 if (cmd != READ_10 && cmd != WRITE_10 &&
3868 * Try Direct I/O to RAID memeber disks 3868 cmd != READ_16 && cmd != WRITE_16)
3869 */ 3869 return;
3870 if (cdb0 == READ_16 || cdb0 == READ_10 || 3870
3871 cdb0 == WRITE_16 || cdb0 == WRITE_10) { 3871 if (cmd == READ_10 || cmd == WRITE_10)
3872 cdb_ptr = mpi_request->CDB.CDB32; 3872 v_lba = get_unaligned_be32(&mpi_request->CDB.CDB32[2]);
3873 3873 else
3874 if ((cdb0 < READ_16) || !(cdb_ptr[2] | cdb_ptr[3] | cdb_ptr[4] 3874 v_lba = get_unaligned_be64(&mpi_request->CDB.CDB32[2]);
3875 | cdb_ptr[5])) { 3875
3876 io_size = scsi_bufflen(scmd) >> 3876 io_size = scsi_bufflen(scmd) >> raid_device->block_exponent;
3877 raid_device->block_exponent; 3877
3878 i = (cdb0 < READ_16) ? 2 : 6; 3878 if (v_lba + io_size - 1 > raid_device->max_lba)
3879 /* get virtual lba */ 3879 return;
3880 v_lba = be32_to_cpu(*(__be32 *)(&cdb_ptr[i])); 3880
3881 3881 stripe_sz = raid_device->stripe_sz;
3882 if (((u64)v_lba + (u64)io_size - 1) <= 3882 stripe_exp = raid_device->stripe_exponent;
3883 (u32)raid_device->max_lba) { 3883 stripe_off = v_lba & (stripe_sz - 1);
3884 stripe_sz = raid_device->stripe_sz; 3884
3885 stripe_exp = raid_device->stripe_exponent; 3885 /* Return unless IO falls within a stripe */
3886 stripe_off = v_lba & (stripe_sz - 1); 3886 if (stripe_off + io_size > stripe_sz)
3887 3887 return;
3888 /* Check whether IO falls within a stripe */ 3888
3889 if ((stripe_off + io_size) <= stripe_sz) { 3889 num_pds = raid_device->num_pds;
3890 num_pds = raid_device->num_pds; 3890 p_lba = v_lba >> stripe_exp;
3891 p_lba = v_lba >> stripe_exp; 3891 stripe_unit = p_lba / num_pds;
3892 stripe_unit = p_lba / num_pds; 3892 column = p_lba % num_pds;
3893 column = p_lba % num_pds; 3893 p_lba = (stripe_unit << stripe_exp) + stripe_off;
3894 p_lba = (stripe_unit << stripe_exp) + 3894 mpi_request->DevHandle = cpu_to_le16(raid_device->pd_handle[column]);
3895 stripe_off; 3895
3896 mpi_request->DevHandle = 3896 if (cmd == READ_10 || cmd == WRITE_10)
3897 cpu_to_le16(raid_device-> 3897 put_unaligned_be32(lower_32_bits(p_lba),
3898 pd_handle[column]); 3898 &mpi_request->CDB.CDB32[2]);
3899 (*(__be32 *)(&cdb_ptr[i])) = 3899 else
3900 cpu_to_be32(p_lba); 3900 put_unaligned_be64(p_lba, &mpi_request->CDB.CDB32[2]);
3901 /* 3901
3902 * WD: To indicate this I/O is directI/O 3902 _scsih_scsi_direct_io_set(ioc, smid, 1);
3903 */
3904 _scsih_scsi_direct_io_set(ioc, smid, 1);
3905 }
3906 }
3907 } else {
3908 io_size = scsi_bufflen(scmd) >>
3909 raid_device->block_exponent;
3910 /* get virtual lba */
3911 v_llba = be64_to_cpu(*(__be64 *)(&cdb_ptr[2]));
3912
3913 if ((v_llba + (u64)io_size - 1) <=
3914 raid_device->max_lba) {
3915 stripe_sz = raid_device->stripe_sz;
3916 stripe_exp = raid_device->stripe_exponent;
3917 stripe_off = (u32) (v_llba & (stripe_sz - 1));
3918
3919 /* Check whether IO falls within a stripe */
3920 if ((stripe_off + io_size) <= stripe_sz) {
3921 num_pds = raid_device->num_pds;
3922 p_lba = (u32)(v_llba >> stripe_exp);
3923 stripe_unit = p_lba / num_pds;
3924 column = p_lba % num_pds;
3925 p_lba = (stripe_unit << stripe_exp) +
3926 stripe_off;
3927 mpi_request->DevHandle =
3928 cpu_to_le16(raid_device->
3929 pd_handle[column]);
3930 (*(__be64 *)(&cdb_ptr[2])) =
3931 cpu_to_be64((u64)p_lba);
3932 /*
3933 * WD: To indicate this I/O is directI/O
3934 */
3935 _scsih_scsi_direct_io_set(ioc, smid, 1);
3936 }
3937 }
3938 }
3939 }
3940} 3903}
3941 3904
3942/** 3905/**