diff options
author | nagalakshmi.nandigama@lsi.com <nagalakshmi.nandigama@lsi.com> | 2011-11-30 21:21:55 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-12-15 01:57:33 -0500 |
commit | ba96bd0b1d4a4e11f23671e1f375a5c8f46b0fe7 (patch) | |
tree | 7db0fcd7efbc8b3fcf9bdb88e1ffef1fda9fc78e /drivers/scsi | |
parent | 7509d6bb955d08c4125bcf44650b2df839470bf8 (diff) |
[SCSI] mpt2sas: Support for greater than 2TB capacity WarpDrive
The driver is modified to allow access to the greater than 2TB WarpDrive
and properly handle direct-io mapping for WarpDrive volumes greater than 2TB.
Signed-off-by: Nagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.h | 2 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 115 |
2 files changed, 74 insertions, 43 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index b3b03bb8ab50..88ead5ed2afc 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
@@ -374,6 +374,7 @@ struct _sas_device { | |||
374 | * @percent_complete: resync percent complete | 374 | * @percent_complete: resync percent complete |
375 | * @direct_io_enabled: Whether direct io to PDs are allowed or not | 375 | * @direct_io_enabled: Whether direct io to PDs are allowed or not |
376 | * @stripe_exponent: X where 2powX is the stripe sz in blocks | 376 | * @stripe_exponent: X where 2powX is the stripe sz in blocks |
377 | * @block_exponent: X where 2powX is the block sz in bytes | ||
377 | * @max_lba: Maximum number of LBA in the volume | 378 | * @max_lba: Maximum number of LBA in the volume |
378 | * @stripe_sz: Stripe Size of the volume | 379 | * @stripe_sz: Stripe Size of the volume |
379 | * @device_info: Device info of the volume member disk | 380 | * @device_info: Device info of the volume member disk |
@@ -395,6 +396,7 @@ struct _raid_device { | |||
395 | u8 percent_complete; | 396 | u8 percent_complete; |
396 | u8 direct_io_enabled; | 397 | u8 direct_io_enabled; |
397 | u8 stripe_exponent; | 398 | u8 stripe_exponent; |
399 | u8 block_exponent; | ||
398 | u64 max_lba; | 400 | u64 max_lba; |
399 | u32 stripe_sz; | 401 | u32 stripe_sz; |
400 | u32 device_info; | 402 | u32 device_info; |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index a9efc4551086..ba8171fe17ef 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -1780,11 +1780,9 @@ _scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc, | |||
1780 | Mpi2ConfigReply_t mpi_reply; | 1780 | Mpi2ConfigReply_t mpi_reply; |
1781 | u16 sz; | 1781 | u16 sz; |
1782 | u8 num_pds, count; | 1782 | u8 num_pds, count; |
1783 | u64 mb = 1024 * 1024; | 1783 | unsigned long stripe_sz, block_sz; |
1784 | u64 tb_2 = 2 * mb * mb; | 1784 | u8 stripe_exp, block_exp; |
1785 | u64 capacity; | 1785 | u64 dev_max_lba; |
1786 | u32 stripe_sz; | ||
1787 | u8 i, stripe_exp; | ||
1788 | 1786 | ||
1789 | if (!ioc->is_warpdrive) | 1787 | if (!ioc->is_warpdrive) |
1790 | return; | 1788 | return; |
@@ -1848,51 +1846,57 @@ _scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc, | |||
1848 | vol_pg0->PhysDisk[count].PhysDiskNum); | 1846 | vol_pg0->PhysDisk[count].PhysDiskNum); |
1849 | goto out_error; | 1847 | goto out_error; |
1850 | } | 1848 | } |
1849 | /* Disable direct I/O if member drive lba exceeds 4 bytes */ | ||
1850 | dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA); | ||
1851 | if (dev_max_lba >> 32) { | ||
1852 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is " | ||
1853 | "disabled for the drive with handle(0x%04x) member" | ||
1854 | "handle (0x%04x) unsupported max lba 0x%016llx\n", | ||
1855 | ioc->name, raid_device->handle, | ||
1856 | le16_to_cpu(pd_pg0.DevHandle), | ||
1857 | (unsigned long long)dev_max_lba); | ||
1858 | goto out_error; | ||
1859 | } | ||
1860 | |||
1851 | raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle); | 1861 | raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle); |
1852 | } | 1862 | } |
1853 | 1863 | ||
1854 | /* | 1864 | /* |
1855 | * Assumption for WD: Direct I/O is not supported if the volume is | 1865 | * Assumption for WD: Direct I/O is not supported if the volume is |
1856 | * not RAID0, if the stripe size is not 64KB, if the block size is | 1866 | * not RAID0 |
1857 | * not 512 and if the volume size is >2TB | ||
1858 | */ | 1867 | */ |
1859 | if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0 || | 1868 | if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) { |
1860 | le16_to_cpu(vol_pg0->BlockSize) != 512) { | ||
1861 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | 1869 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " |
1862 | "for the drive with handle(0x%04x): type=%d, " | 1870 | "for the drive with handle(0x%04x): type=%d, " |
1863 | "s_sz=%uK, blk_size=%u\n", ioc->name, | 1871 | "s_sz=%uK, blk_size=%u\n", ioc->name, |
1864 | raid_device->handle, raid_device->volume_type, | 1872 | raid_device->handle, raid_device->volume_type, |
1865 | le32_to_cpu(vol_pg0->StripeSize)/2, | 1873 | (le32_to_cpu(vol_pg0->StripeSize) * |
1874 | le16_to_cpu(vol_pg0->BlockSize)) / 1024, | ||
1866 | le16_to_cpu(vol_pg0->BlockSize)); | 1875 | le16_to_cpu(vol_pg0->BlockSize)); |
1867 | goto out_error; | 1876 | goto out_error; |
1868 | } | 1877 | } |
1869 | 1878 | ||
1870 | capacity = (u64) le16_to_cpu(vol_pg0->BlockSize) * | 1879 | stripe_sz = le32_to_cpu(vol_pg0->StripeSize); |
1871 | (le64_to_cpu(vol_pg0->MaxLBA) + 1); | 1880 | stripe_exp = find_first_bit(&stripe_sz, 32); |
1872 | 1881 | if (stripe_exp == 32) { | |
1873 | if (capacity > tb_2) { | ||
1874 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | 1882 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " |
1875 | "for the drive with handle(0x%04x) since drive sz > 2TB\n", | 1883 | "for the drive with handle(0x%04x) invalid stripe sz %uK\n", |
1876 | ioc->name, raid_device->handle); | 1884 | ioc->name, raid_device->handle, |
1885 | (le32_to_cpu(vol_pg0->StripeSize) * | ||
1886 | le16_to_cpu(vol_pg0->BlockSize)) / 1024); | ||
1877 | goto out_error; | 1887 | goto out_error; |
1878 | } | 1888 | } |
1879 | 1889 | raid_device->stripe_exponent = stripe_exp; | |
1880 | stripe_sz = le32_to_cpu(vol_pg0->StripeSize); | 1890 | block_sz = le16_to_cpu(vol_pg0->BlockSize); |
1881 | stripe_exp = 0; | 1891 | block_exp = find_first_bit(&block_sz, 16); |
1882 | for (i = 0; i < 32; i++) { | 1892 | if (block_exp == 16) { |
1883 | if (stripe_sz & 1) | ||
1884 | break; | ||
1885 | stripe_exp++; | ||
1886 | stripe_sz >>= 1; | ||
1887 | } | ||
1888 | if (i == 32) { | ||
1889 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | 1893 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " |
1890 | "for the drive with handle(0x%04x) invalid stripe sz %uK\n", | 1894 | "for the drive with handle(0x%04x) invalid block sz %u\n", |
1891 | ioc->name, raid_device->handle, | 1895 | ioc->name, raid_device->handle, |
1892 | le32_to_cpu(vol_pg0->StripeSize)/2); | 1896 | le16_to_cpu(vol_pg0->BlockSize)); |
1893 | goto out_error; | 1897 | goto out_error; |
1894 | } | 1898 | } |
1895 | raid_device->stripe_exponent = stripe_exp; | 1899 | raid_device->block_exponent = block_exp; |
1896 | raid_device->direct_io_enabled = 1; | 1900 | raid_device->direct_io_enabled = 1; |
1897 | 1901 | ||
1898 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive" | 1902 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive" |
@@ -3808,8 +3812,9 @@ _scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
3808 | { | 3812 | { |
3809 | u32 v_lba, p_lba, stripe_off, stripe_unit, column, io_size; | 3813 | u32 v_lba, p_lba, stripe_off, stripe_unit, column, io_size; |
3810 | u32 stripe_sz, stripe_exp; | 3814 | u32 stripe_sz, stripe_exp; |
3811 | u8 num_pds, *cdb_ptr, *tmp_ptr, *lba_ptr1, *lba_ptr2; | 3815 | u8 num_pds, *cdb_ptr, i; |
3812 | u8 cdb0 = scmd->cmnd[0]; | 3816 | u8 cdb0 = scmd->cmnd[0]; |
3817 | u64 v_llba; | ||
3813 | 3818 | ||
3814 | /* | 3819 | /* |
3815 | * Try Direct I/O to RAID memeber disks | 3820 | * Try Direct I/O to RAID memeber disks |
@@ -3820,15 +3825,11 @@ _scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
3820 | 3825 | ||
3821 | if ((cdb0 < READ_16) || !(cdb_ptr[2] | cdb_ptr[3] | cdb_ptr[4] | 3826 | if ((cdb0 < READ_16) || !(cdb_ptr[2] | cdb_ptr[3] | cdb_ptr[4] |
3822 | | cdb_ptr[5])) { | 3827 | | cdb_ptr[5])) { |
3823 | io_size = scsi_bufflen(scmd) >> 9; | 3828 | io_size = scsi_bufflen(scmd) >> |
3829 | raid_device->block_exponent; | ||
3830 | i = (cdb0 < READ_16) ? 2 : 6; | ||
3824 | /* get virtual lba */ | 3831 | /* get virtual lba */ |
3825 | lba_ptr1 = lba_ptr2 = (cdb0 < READ_16) ? &cdb_ptr[2] : | 3832 | v_lba = be32_to_cpu(*(__be32 *)(&cdb_ptr[i])); |
3826 | &cdb_ptr[6]; | ||
3827 | tmp_ptr = (u8 *)&v_lba + 3; | ||
3828 | *tmp_ptr-- = *lba_ptr1++; | ||
3829 | *tmp_ptr-- = *lba_ptr1++; | ||
3830 | *tmp_ptr-- = *lba_ptr1++; | ||
3831 | *tmp_ptr = *lba_ptr1; | ||
3832 | 3833 | ||
3833 | if (((u64)v_lba + (u64)io_size - 1) <= | 3834 | if (((u64)v_lba + (u64)io_size - 1) <= |
3834 | (u32)raid_device->max_lba) { | 3835 | (u32)raid_device->max_lba) { |
@@ -3847,11 +3848,39 @@ _scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
3847 | mpi_request->DevHandle = | 3848 | mpi_request->DevHandle = |
3848 | cpu_to_le16(raid_device-> | 3849 | cpu_to_le16(raid_device-> |
3849 | pd_handle[column]); | 3850 | pd_handle[column]); |
3850 | tmp_ptr = (u8 *)&p_lba + 3; | 3851 | (*(__be32 *)(&cdb_ptr[i])) = |
3851 | *lba_ptr2++ = *tmp_ptr--; | 3852 | cpu_to_be32(p_lba); |
3852 | *lba_ptr2++ = *tmp_ptr--; | 3853 | /* |
3853 | *lba_ptr2++ = *tmp_ptr--; | 3854 | * WD: To indicate this I/O is directI/O |
3854 | *lba_ptr2 = *tmp_ptr; | 3855 | */ |
3856 | _scsih_scsi_direct_io_set(ioc, smid, 1); | ||
3857 | } | ||
3858 | } | ||
3859 | } else { | ||
3860 | io_size = scsi_bufflen(scmd) >> | ||
3861 | raid_device->block_exponent; | ||
3862 | /* get virtual lba */ | ||
3863 | v_llba = be64_to_cpu(*(__be64 *)(&cdb_ptr[2])); | ||
3864 | |||
3865 | if ((v_llba + (u64)io_size - 1) <= | ||
3866 | raid_device->max_lba) { | ||
3867 | stripe_sz = raid_device->stripe_sz; | ||
3868 | stripe_exp = raid_device->stripe_exponent; | ||
3869 | stripe_off = (u32) (v_llba & (stripe_sz - 1)); | ||
3870 | |||
3871 | /* Check whether IO falls within a stripe */ | ||
3872 | if ((stripe_off + io_size) <= stripe_sz) { | ||
3873 | num_pds = raid_device->num_pds; | ||
3874 | p_lba = (u32)(v_llba >> stripe_exp); | ||
3875 | stripe_unit = p_lba / num_pds; | ||
3876 | column = p_lba % num_pds; | ||
3877 | p_lba = (stripe_unit << stripe_exp) + | ||
3878 | stripe_off; | ||
3879 | mpi_request->DevHandle = | ||
3880 | cpu_to_le16(raid_device-> | ||
3881 | pd_handle[column]); | ||
3882 | (*(__be64 *)(&cdb_ptr[2])) = | ||
3883 | cpu_to_be64((u64)p_lba); | ||
3855 | /* | 3884 | /* |
3856 | * WD: To indicate this I/O is directI/O | 3885 | * WD: To indicate this I/O is directI/O |
3857 | */ | 3886 | */ |