aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2009-01-04 03:08:19 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-12 13:57:55 -0400
commitc6a44287417de1625a59f1d4ae52d033c03b9dab (patch)
tree380e7fdb6f689196a648c7c8bc3cf41c5cd58fcc /drivers/scsi
parent59d3270326fcba29226c28df27cb43fefd8c58d0 (diff)
[SCSI] scsi_debug: DIF/DIX support
This patch adds support for DIX and DIF in scsi_debug. A separate buffer is allocated for the protection information. - The dix parameter indicates whether the controller supports DIX (protection information DMA) - The dif parameter indicates whether the simulated storage device supports DIF - The guard parameter switches between T10 CRC(0) and IP checksum(1) - The ato parameter indicates whether the application tag is owned by the disk(0) or the OS(1) - DIF and DIX errors can be triggered using the scsi_debug_opts mask Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Acked-by: Douglas Gilbert <dgilbert@interlog.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_debug.c443
1 files changed, 436 insertions, 7 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 6eebd0bbe8a8..213123b0486b 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -40,6 +40,9 @@
40#include <linux/moduleparam.h> 40#include <linux/moduleparam.h>
41#include <linux/scatterlist.h> 41#include <linux/scatterlist.h>
42#include <linux/blkdev.h> 42#include <linux/blkdev.h>
43#include <linux/crc-t10dif.h>
44
45#include <net/checksum.h>
43 46
44#include <scsi/scsi.h> 47#include <scsi/scsi.h>
45#include <scsi/scsi_cmnd.h> 48#include <scsi/scsi_cmnd.h>
@@ -48,8 +51,7 @@
48#include <scsi/scsicam.h> 51#include <scsi/scsicam.h>
49#include <scsi/scsi_eh.h> 52#include <scsi/scsi_eh.h>
50 53
51#include <linux/stat.h> 54#include "sd.h"
52
53#include "scsi_logging.h" 55#include "scsi_logging.h"
54 56
55#define SCSI_DEBUG_VERSION "1.81" 57#define SCSI_DEBUG_VERSION "1.81"
@@ -95,6 +97,10 @@ static const char * scsi_debug_version_date = "20070104";
95#define DEF_FAKE_RW 0 97#define DEF_FAKE_RW 0
96#define DEF_VPD_USE_HOSTNO 1 98#define DEF_VPD_USE_HOSTNO 1
97#define DEF_SECTOR_SIZE 512 99#define DEF_SECTOR_SIZE 512
100#define DEF_DIX 0
101#define DEF_DIF 0
102#define DEF_GUARD 0
103#define DEF_ATO 1
98 104
99/* bit mask values for scsi_debug_opts */ 105/* bit mask values for scsi_debug_opts */
100#define SCSI_DEBUG_OPT_NOISE 1 106#define SCSI_DEBUG_OPT_NOISE 1
@@ -102,6 +108,8 @@ static const char * scsi_debug_version_date = "20070104";
102#define SCSI_DEBUG_OPT_TIMEOUT 4 108#define SCSI_DEBUG_OPT_TIMEOUT 4
103#define SCSI_DEBUG_OPT_RECOVERED_ERR 8 109#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
104#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 110#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16
111#define SCSI_DEBUG_OPT_DIF_ERR 32
112#define SCSI_DEBUG_OPT_DIX_ERR 64
105/* When "every_nth" > 0 then modulo "every_nth" commands: 113/* When "every_nth" > 0 then modulo "every_nth" commands:
106 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set 114 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
107 * - a RECOVERED_ERROR is simulated on successful read and write 115 * - a RECOVERED_ERROR is simulated on successful read and write
@@ -144,6 +152,10 @@ static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
144static int scsi_debug_fake_rw = DEF_FAKE_RW; 152static int scsi_debug_fake_rw = DEF_FAKE_RW;
145static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; 153static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
146static int scsi_debug_sector_size = DEF_SECTOR_SIZE; 154static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
155static int scsi_debug_dix = DEF_DIX;
156static int scsi_debug_dif = DEF_DIF;
157static int scsi_debug_guard = DEF_GUARD;
158static int scsi_debug_ato = DEF_ATO;
147 159
148static int scsi_debug_cmnd_count = 0; 160static int scsi_debug_cmnd_count = 0;
149 161
@@ -204,11 +216,15 @@ struct sdebug_queued_cmd {
204static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; 216static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
205 217
206static unsigned char * fake_storep; /* ramdisk storage */ 218static unsigned char * fake_storep; /* ramdisk storage */
219static unsigned char *dif_storep; /* protection info */
207 220
208static int num_aborts = 0; 221static int num_aborts = 0;
209static int num_dev_resets = 0; 222static int num_dev_resets = 0;
210static int num_bus_resets = 0; 223static int num_bus_resets = 0;
211static int num_host_resets = 0; 224static int num_host_resets = 0;
225static int dix_writes;
226static int dix_reads;
227static int dif_errors;
212 228
213static DEFINE_SPINLOCK(queued_arr_lock); 229static DEFINE_SPINLOCK(queued_arr_lock);
214static DEFINE_RWLOCK(atomic_rw); 230static DEFINE_RWLOCK(atomic_rw);
@@ -217,6 +233,11 @@ static char sdebug_proc_name[] = "scsi_debug";
217 233
218static struct bus_type pseudo_lld_bus; 234static struct bus_type pseudo_lld_bus;
219 235
236static inline sector_t dif_offset(sector_t sector)
237{
238 return sector << 3;
239}
240
220static struct device_driver sdebug_driverfs_driver = { 241static struct device_driver sdebug_driverfs_driver = {
221 .name = sdebug_proc_name, 242 .name = sdebug_proc_name,
222 .bus = &pseudo_lld_bus, 243 .bus = &pseudo_lld_bus,
@@ -225,6 +246,9 @@ static struct device_driver sdebug_driverfs_driver = {
225static const int check_condition_result = 246static const int check_condition_result =
226 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; 247 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
227 248
249static const int illegal_condition_result =
250 (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
251
228static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 252static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
229 0, 0, 0x2, 0x4b}; 253 0, 0, 0x2, 0x4b};
230static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, 254static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
@@ -726,7 +750,12 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
726 } else if (0x86 == cmd[2]) { /* extended inquiry */ 750 } else if (0x86 == cmd[2]) { /* extended inquiry */
727 arr[1] = cmd[2]; /*sanity */ 751 arr[1] = cmd[2]; /*sanity */
728 arr[3] = 0x3c; /* number of following entries */ 752 arr[3] = 0x3c; /* number of following entries */
729 arr[4] = 0x0; /* no protection stuff */ 753 if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
754 arr[4] = 0x4; /* SPT: GRD_CHK:1 */
755 else if (scsi_debug_dif)
756 arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
757 else
758 arr[4] = 0x0; /* no protection stuff */
730 arr[5] = 0x7; /* head of q, ordered + simple q's */ 759 arr[5] = 0x7; /* head of q, ordered + simple q's */
731 } else if (0x87 == cmd[2]) { /* mode page policy */ 760 } else if (0x87 == cmd[2]) { /* mode page policy */
732 arr[1] = cmd[2]; /*sanity */ 761 arr[1] = cmd[2]; /*sanity */
@@ -767,6 +796,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
767 arr[2] = scsi_debug_scsi_level; 796 arr[2] = scsi_debug_scsi_level;
768 arr[3] = 2; /* response_data_format==2 */ 797 arr[3] = 2; /* response_data_format==2 */
769 arr[4] = SDEBUG_LONG_INQ_SZ - 5; 798 arr[4] = SDEBUG_LONG_INQ_SZ - 5;
799 arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
770 if (0 == scsi_debug_vpd_use_hostno) 800 if (0 == scsi_debug_vpd_use_hostno)
771 arr[5] = 0x10; /* claim: implicit TGPS */ 801 arr[5] = 0x10; /* claim: implicit TGPS */
772 arr[6] = 0x10; /* claim: MultiP */ 802 arr[6] = 0x10; /* claim: MultiP */
@@ -915,6 +945,12 @@ static int resp_readcap16(struct scsi_cmnd * scp,
915 arr[9] = (scsi_debug_sector_size >> 16) & 0xff; 945 arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
916 arr[10] = (scsi_debug_sector_size >> 8) & 0xff; 946 arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
917 arr[11] = scsi_debug_sector_size & 0xff; 947 arr[11] = scsi_debug_sector_size & 0xff;
948
949 if (scsi_debug_dif) {
950 arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
951 arr[12] |= 1; /* PROT_EN */
952 }
953
918 return fill_from_dev_buffer(scp, arr, 954 return fill_from_dev_buffer(scp, arr,
919 min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); 955 min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
920} 956}
@@ -1066,6 +1102,10 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
1066 ctrl_m_pg[2] |= 0x4; 1102 ctrl_m_pg[2] |= 0x4;
1067 else 1103 else
1068 ctrl_m_pg[2] &= ~0x4; 1104 ctrl_m_pg[2] &= ~0x4;
1105
1106 if (scsi_debug_ato)
1107 ctrl_m_pg[5] |= 0x80; /* ATO=1 */
1108
1069 memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg)); 1109 memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1070 if (1 == pcontrol) 1110 if (1 == pcontrol)
1071 memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg)); 1111 memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
@@ -1536,6 +1576,87 @@ static int do_device_access(struct scsi_cmnd *scmd,
1536 return ret; 1576 return ret;
1537} 1577}
1538 1578
1579static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
1580 unsigned int sectors)
1581{
1582 unsigned int i, resid;
1583 struct scatterlist *psgl;
1584 struct sd_dif_tuple *sdt;
1585 sector_t sector;
1586 sector_t tmp_sec = start_sec;
1587 void *paddr;
1588
1589 start_sec = do_div(tmp_sec, sdebug_store_sectors);
1590
1591 sdt = (struct sd_dif_tuple *)(dif_storep + dif_offset(start_sec));
1592
1593 for (i = 0 ; i < sectors ; i++) {
1594 u16 csum;
1595
1596 if (sdt[i].app_tag == 0xffff)
1597 continue;
1598
1599 sector = start_sec + i;
1600
1601 switch (scsi_debug_guard) {
1602 case 1:
1603 csum = ip_compute_csum(fake_storep +
1604 sector * scsi_debug_sector_size,
1605 scsi_debug_sector_size);
1606 break;
1607 case 0:
1608 csum = crc_t10dif(fake_storep +
1609 sector * scsi_debug_sector_size,
1610 scsi_debug_sector_size);
1611 csum = cpu_to_be16(csum);
1612 break;
1613 default:
1614 BUG();
1615 }
1616
1617 if (sdt[i].guard_tag != csum) {
1618 printk(KERN_ERR "%s: GUARD check failed on sector %lu" \
1619 " rcvd 0x%04x, data 0x%04x\n", __func__,
1620 (unsigned long)sector,
1621 be16_to_cpu(sdt[i].guard_tag),
1622 be16_to_cpu(csum));
1623 dif_errors++;
1624 return 0x01;
1625 }
1626
1627 if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION &&
1628 be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) {
1629 printk(KERN_ERR "%s: REF check failed on sector %lu\n",
1630 __func__, (unsigned long)sector);
1631 dif_errors++;
1632 return 0x03;
1633 }
1634 }
1635
1636 resid = sectors * 8; /* Bytes of protection data to copy into sgl */
1637 sector = start_sec;
1638
1639 scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) {
1640 int len = min(psgl->length, resid);
1641
1642 paddr = kmap_atomic(sg_page(psgl), KM_IRQ0) + psgl->offset;
1643 memcpy(paddr, dif_storep + dif_offset(sector), len);
1644
1645 sector += len >> 3;
1646 if (sector >= sdebug_store_sectors) {
1647 /* Force wrap */
1648 tmp_sec = sector;
1649 sector = do_div(tmp_sec, sdebug_store_sectors);
1650 }
1651 resid -= len;
1652 kunmap_atomic(paddr, KM_IRQ0);
1653 }
1654
1655 dix_reads++;
1656
1657 return 0;
1658}
1659
1539static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, 1660static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
1540 unsigned int num, struct sdebug_dev_info *devip) 1661 unsigned int num, struct sdebug_dev_info *devip)
1541{ 1662{
@@ -1563,12 +1684,162 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
1563 } 1684 }
1564 return check_condition_result; 1685 return check_condition_result;
1565 } 1686 }
1687
1688 /* DIX + T10 DIF */
1689 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
1690 int prot_ret = prot_verify_read(SCpnt, lba, num);
1691
1692 if (prot_ret) {
1693 mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret);
1694 return illegal_condition_result;
1695 }
1696 }
1697
1566 read_lock_irqsave(&atomic_rw, iflags); 1698 read_lock_irqsave(&atomic_rw, iflags);
1567 ret = do_device_access(SCpnt, devip, lba, num, 0); 1699 ret = do_device_access(SCpnt, devip, lba, num, 0);
1568 read_unlock_irqrestore(&atomic_rw, iflags); 1700 read_unlock_irqrestore(&atomic_rw, iflags);
1569 return ret; 1701 return ret;
1570} 1702}
1571 1703
1704void dump_sector(unsigned char *buf, int len)
1705{
1706 int i, j;
1707
1708 printk(KERN_ERR ">>> Sector Dump <<<\n");
1709
1710 for (i = 0 ; i < len ; i += 16) {
1711 printk(KERN_ERR "%04d: ", i);
1712
1713 for (j = 0 ; j < 16 ; j++) {
1714 unsigned char c = buf[i+j];
1715 if (c >= 0x20 && c < 0x7e)
1716 printk(" %c ", buf[i+j]);
1717 else
1718 printk("%02x ", buf[i+j]);
1719 }
1720
1721 printk("\n");
1722 }
1723}
1724
1725static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1726 unsigned int sectors)
1727{
1728 int i, j, ret;
1729 struct sd_dif_tuple *sdt;
1730 struct scatterlist *dsgl = scsi_sglist(SCpnt);
1731 struct scatterlist *psgl = scsi_prot_sglist(SCpnt);
1732 void *daddr, *paddr;
1733 sector_t tmp_sec = start_sec;
1734 sector_t sector;
1735 int ppage_offset;
1736 unsigned short csum;
1737
1738 sector = do_div(tmp_sec, sdebug_store_sectors);
1739
1740 if (((SCpnt->cmnd[1] >> 5) & 7) != 1) {
1741 printk(KERN_WARNING "scsi_debug: WRPROTECT != 1\n");
1742 return 0;
1743 }
1744
1745 BUG_ON(scsi_sg_count(SCpnt) == 0);
1746 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
1747
1748 paddr = kmap_atomic(sg_page(psgl), KM_IRQ1) + psgl->offset;
1749 ppage_offset = 0;
1750
1751 /* For each data page */
1752 scsi_for_each_sg(SCpnt, dsgl, scsi_sg_count(SCpnt), i) {
1753 daddr = kmap_atomic(sg_page(dsgl), KM_IRQ0) + dsgl->offset;
1754
1755 /* For each sector-sized chunk in data page */
1756 for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) {
1757
1758 /* If we're at the end of the current
1759 * protection page advance to the next one
1760 */
1761 if (ppage_offset >= psgl->length) {
1762 kunmap_atomic(paddr, KM_IRQ1);
1763 psgl = sg_next(psgl);
1764 BUG_ON(psgl == NULL);
1765 paddr = kmap_atomic(sg_page(psgl), KM_IRQ1)
1766 + psgl->offset;
1767 ppage_offset = 0;
1768 }
1769
1770 sdt = paddr + ppage_offset;
1771
1772 switch (scsi_debug_guard) {
1773 case 1:
1774 csum = ip_compute_csum(daddr,
1775 scsi_debug_sector_size);
1776 break;
1777 case 0:
1778 csum = cpu_to_be16(crc_t10dif(daddr,
1779 scsi_debug_sector_size));
1780 break;
1781 default:
1782 BUG();
1783 ret = 0;
1784 goto out;
1785 }
1786
1787 if (sdt->guard_tag != csum) {
1788 printk(KERN_ERR
1789 "%s: GUARD check failed on sector %lu " \
1790 "rcvd 0x%04x, calculated 0x%04x\n",
1791 __func__, (unsigned long)sector,
1792 be16_to_cpu(sdt->guard_tag),
1793 be16_to_cpu(csum));
1794 ret = 0x01;
1795 dump_sector(daddr, scsi_debug_sector_size);
1796 goto out;
1797 }
1798
1799 if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION &&
1800 be32_to_cpu(sdt->ref_tag)
1801 != (start_sec & 0xffffffff)) {
1802 printk(KERN_ERR
1803 "%s: REF check failed on sector %lu\n",
1804 __func__, (unsigned long)sector);
1805 ret = 0x03;
1806 dump_sector(daddr, scsi_debug_sector_size);
1807 goto out;
1808 }
1809
1810 /* Would be great to copy this in bigger
1811 * chunks. However, for the sake of
1812 * correctness we need to verify each sector
1813 * before writing it to "stable" storage
1814 */
1815 memcpy(dif_storep + dif_offset(sector), sdt, 8);
1816
1817 sector++;
1818
1819 if (sector == sdebug_store_sectors)
1820 sector = 0; /* Force wrap */
1821
1822 start_sec++;
1823 daddr += scsi_debug_sector_size;
1824 ppage_offset += sizeof(struct sd_dif_tuple);
1825 }
1826
1827 kunmap_atomic(daddr, KM_IRQ0);
1828 }
1829
1830 kunmap_atomic(paddr, KM_IRQ1);
1831
1832 dix_writes++;
1833
1834 return 0;
1835
1836out:
1837 dif_errors++;
1838 kunmap_atomic(daddr, KM_IRQ0);
1839 kunmap_atomic(paddr, KM_IRQ1);
1840 return ret;
1841}
1842
1572static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, 1843static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
1573 unsigned int num, struct sdebug_dev_info *devip) 1844 unsigned int num, struct sdebug_dev_info *devip)
1574{ 1845{
@@ -1579,6 +1850,16 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
1579 if (ret) 1850 if (ret)
1580 return ret; 1851 return ret;
1581 1852
1853 /* DIX + T10 DIF */
1854 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
1855 int prot_ret = prot_verify_write(SCpnt, lba, num);
1856
1857 if (prot_ret) {
1858 mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret);
1859 return illegal_condition_result;
1860 }
1861 }
1862
1582 write_lock_irqsave(&atomic_rw, iflags); 1863 write_lock_irqsave(&atomic_rw, iflags);
1583 ret = do_device_access(SCpnt, devip, lba, num, 1); 1864 ret = do_device_access(SCpnt, devip, lba, num, 1);
1584 write_unlock_irqrestore(&atomic_rw, iflags); 1865 write_unlock_irqrestore(&atomic_rw, iflags);
@@ -2095,6 +2376,10 @@ module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
2095module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, 2376module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
2096 S_IRUGO | S_IWUSR); 2377 S_IRUGO | S_IWUSR);
2097module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); 2378module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
2379module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
2380module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
2381module_param_named(guard, scsi_debug_guard, int, S_IRUGO);
2382module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
2098 2383
2099MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); 2384MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
2100MODULE_DESCRIPTION("SCSI debug adapter driver"); 2385MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2117,7 +2402,10 @@ MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
2117MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); 2402MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
2118MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); 2403MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
2119MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)"); 2404MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)");
2120 2405MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
2406MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
2407MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
2408MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
2121 2409
2122static char sdebug_info[256]; 2410static char sdebug_info[256];
2123 2411
@@ -2164,14 +2452,14 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta
2164 "delay=%d, max_luns=%d, scsi_level=%d\n" 2452 "delay=%d, max_luns=%d, scsi_level=%d\n"
2165 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" 2453 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
2166 "number of aborts=%d, device_reset=%d, bus_resets=%d, " 2454 "number of aborts=%d, device_reset=%d, bus_resets=%d, "
2167 "host_resets=%d\n", 2455 "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n",
2168 SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts, 2456 SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts,
2169 scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, 2457 scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
2170 scsi_debug_cmnd_count, scsi_debug_delay, 2458 scsi_debug_cmnd_count, scsi_debug_delay,
2171 scsi_debug_max_luns, scsi_debug_scsi_level, 2459 scsi_debug_max_luns, scsi_debug_scsi_level,
2172 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, 2460 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
2173 sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets, 2461 sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
2174 num_host_resets); 2462 num_host_resets, dix_reads, dix_writes, dif_errors);
2175 if (pos < offset) { 2463 if (pos < offset) {
2176 len = 0; 2464 len = 0;
2177 begin = pos; 2465 begin = pos;
@@ -2452,6 +2740,31 @@ static ssize_t sdebug_sector_size_show(struct device_driver * ddp, char * buf)
2452} 2740}
2453DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL); 2741DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL);
2454 2742
2743static ssize_t sdebug_dix_show(struct device_driver *ddp, char *buf)
2744{
2745 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
2746}
2747DRIVER_ATTR(dix, S_IRUGO, sdebug_dix_show, NULL);
2748
2749static ssize_t sdebug_dif_show(struct device_driver *ddp, char *buf)
2750{
2751 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
2752}
2753DRIVER_ATTR(dif, S_IRUGO, sdebug_dif_show, NULL);
2754
2755static ssize_t sdebug_guard_show(struct device_driver *ddp, char *buf)
2756{
2757 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_guard);
2758}
2759DRIVER_ATTR(guard, S_IRUGO, sdebug_guard_show, NULL);
2760
2761static ssize_t sdebug_ato_show(struct device_driver *ddp, char *buf)
2762{
2763 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
2764}
2765DRIVER_ATTR(ato, S_IRUGO, sdebug_ato_show, NULL);
2766
2767
2455/* Note: The following function creates attribute files in the 2768/* Note: The following function creates attribute files in the
2456 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these 2769 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
2457 files (over those found in the /sys/module/scsi_debug/parameters 2770 files (over those found in the /sys/module/scsi_debug/parameters
@@ -2478,11 +2791,19 @@ static int do_create_driverfs_files(void)
2478 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); 2791 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb);
2479 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); 2792 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno);
2480 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size); 2793 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size);
2794 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dix);
2795 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dif);
2796 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_guard);
2797 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ato);
2481 return ret; 2798 return ret;
2482} 2799}
2483 2800
2484static void do_remove_driverfs_files(void) 2801static void do_remove_driverfs_files(void)
2485{ 2802{
2803 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ato);
2804 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_guard);
2805 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dif);
2806 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dix);
2486 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size); 2807 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size);
2487 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); 2808 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno);
2488 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); 2809 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb);
@@ -2526,11 +2847,33 @@ static int __init scsi_debug_init(void)
2526 case 4096: 2847 case 4096:
2527 break; 2848 break;
2528 default: 2849 default:
2529 printk(KERN_ERR "scsi_debug_init: invalid sector_size %u\n", 2850 printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n",
2530 scsi_debug_sector_size); 2851 scsi_debug_sector_size);
2531 return -EINVAL; 2852 return -EINVAL;
2532 } 2853 }
2533 2854
2855 switch (scsi_debug_dif) {
2856
2857 case SD_DIF_TYPE0_PROTECTION:
2858 case SD_DIF_TYPE1_PROTECTION:
2859 case SD_DIF_TYPE3_PROTECTION:
2860 break;
2861
2862 default:
2863 printk(KERN_ERR "scsi_debug_init: dif must be 0, 1 or 3\n");
2864 return -EINVAL;
2865 }
2866
2867 if (scsi_debug_guard > 1) {
2868 printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n");
2869 return -EINVAL;
2870 }
2871
2872 if (scsi_debug_ato > 1) {
2873 printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n");
2874 return -EINVAL;
2875 }
2876
2534 if (scsi_debug_dev_size_mb < 1) 2877 if (scsi_debug_dev_size_mb < 1)
2535 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ 2878 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
2536 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; 2879 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
@@ -2563,6 +2906,24 @@ static int __init scsi_debug_init(void)
2563 if (scsi_debug_num_parts > 0) 2906 if (scsi_debug_num_parts > 0)
2564 sdebug_build_parts(fake_storep, sz); 2907 sdebug_build_parts(fake_storep, sz);
2565 2908
2909 if (scsi_debug_dif) {
2910 int dif_size;
2911
2912 dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
2913 dif_storep = vmalloc(dif_size);
2914
2915 printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n",
2916 dif_size, dif_storep);
2917
2918 if (dif_storep == NULL) {
2919 printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n");
2920 ret = -ENOMEM;
2921 goto free_vm;
2922 }
2923
2924 memset(dif_storep, 0xff, dif_size);
2925 }
2926
2566 ret = device_register(&pseudo_primary); 2927 ret = device_register(&pseudo_primary);
2567 if (ret < 0) { 2928 if (ret < 0) {
2568 printk(KERN_WARNING "scsi_debug: device_register error: %d\n", 2929 printk(KERN_WARNING "scsi_debug: device_register error: %d\n",
@@ -2615,6 +2976,8 @@ bus_unreg:
2615dev_unreg: 2976dev_unreg:
2616 device_unregister(&pseudo_primary); 2977 device_unregister(&pseudo_primary);
2617free_vm: 2978free_vm:
2979 if (dif_storep)
2980 vfree(dif_storep);
2618 vfree(fake_storep); 2981 vfree(fake_storep);
2619 2982
2620 return ret; 2983 return ret;
@@ -2632,6 +2995,9 @@ static void __exit scsi_debug_exit(void)
2632 bus_unregister(&pseudo_lld_bus); 2995 bus_unregister(&pseudo_lld_bus);
2633 device_unregister(&pseudo_primary); 2996 device_unregister(&pseudo_primary);
2634 2997
2998 if (dif_storep)
2999 vfree(dif_storep);
3000
2635 vfree(fake_storep); 3001 vfree(fake_storep);
2636} 3002}
2637 3003
@@ -2732,6 +3098,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
2732 struct sdebug_dev_info *devip = NULL; 3098 struct sdebug_dev_info *devip = NULL;
2733 int inj_recovered = 0; 3099 int inj_recovered = 0;
2734 int inj_transport = 0; 3100 int inj_transport = 0;
3101 int inj_dif = 0;
3102 int inj_dix = 0;
2735 int delay_override = 0; 3103 int delay_override = 0;
2736 3104
2737 scsi_set_resid(SCpnt, 0); 3105 scsi_set_resid(SCpnt, 0);
@@ -2769,6 +3137,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
2769 inj_recovered = 1; /* to reads and writes below */ 3137 inj_recovered = 1; /* to reads and writes below */
2770 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) 3138 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
2771 inj_transport = 1; /* to reads and writes below */ 3139 inj_transport = 1; /* to reads and writes below */
3140 else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts)
3141 inj_dif = 1; /* to reads and writes below */
3142 else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts)
3143 inj_dix = 1; /* to reads and writes below */
2772 } 3144 }
2773 3145
2774 if (devip->wlun) { 3146 if (devip->wlun) {
@@ -2870,6 +3242,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
2870 mk_sense_buffer(devip, ABORTED_COMMAND, 3242 mk_sense_buffer(devip, ABORTED_COMMAND,
2871 TRANSPORT_PROBLEM, ACK_NAK_TO); 3243 TRANSPORT_PROBLEM, ACK_NAK_TO);
2872 errsts = check_condition_result; 3244 errsts = check_condition_result;
3245 } else if (inj_dif && (0 == errsts)) {
3246 mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
3247 errsts = illegal_condition_result;
3248 } else if (inj_dix && (0 == errsts)) {
3249 mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
3250 errsts = illegal_condition_result;
2873 } 3251 }
2874 break; 3252 break;
2875 case REPORT_LUNS: /* mandatory, ignore unit attention */ 3253 case REPORT_LUNS: /* mandatory, ignore unit attention */
@@ -2894,6 +3272,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
2894 mk_sense_buffer(devip, RECOVERED_ERROR, 3272 mk_sense_buffer(devip, RECOVERED_ERROR,
2895 THRESHOLD_EXCEEDED, 0); 3273 THRESHOLD_EXCEEDED, 0);
2896 errsts = check_condition_result; 3274 errsts = check_condition_result;
3275 } else if (inj_dif && (0 == errsts)) {
3276 mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
3277 errsts = illegal_condition_result;
3278 } else if (inj_dix && (0 == errsts)) {
3279 mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
3280 errsts = illegal_condition_result;
2897 } 3281 }
2898 break; 3282 break;
2899 case MODE_SENSE: 3283 case MODE_SENSE:
@@ -2982,6 +3366,7 @@ static int sdebug_driver_probe(struct device * dev)
2982 int error = 0; 3366 int error = 0;
2983 struct sdebug_host_info *sdbg_host; 3367 struct sdebug_host_info *sdbg_host;
2984 struct Scsi_Host *hpnt; 3368 struct Scsi_Host *hpnt;
3369 int host_prot;
2985 3370
2986 sdbg_host = to_sdebug_host(dev); 3371 sdbg_host = to_sdebug_host(dev);
2987 3372
@@ -3000,6 +3385,50 @@ static int sdebug_driver_probe(struct device * dev)
3000 hpnt->max_id = scsi_debug_num_tgts; 3385 hpnt->max_id = scsi_debug_num_tgts;
3001 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */ 3386 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
3002 3387
3388 host_prot = 0;
3389
3390 switch (scsi_debug_dif) {
3391
3392 case SD_DIF_TYPE1_PROTECTION:
3393 host_prot = SHOST_DIF_TYPE1_PROTECTION;
3394 if (scsi_debug_dix)
3395 host_prot |= SHOST_DIX_TYPE1_PROTECTION;
3396 break;
3397
3398 case SD_DIF_TYPE2_PROTECTION:
3399 host_prot = SHOST_DIF_TYPE2_PROTECTION;
3400 if (scsi_debug_dix)
3401 host_prot |= SHOST_DIX_TYPE2_PROTECTION;
3402 break;
3403
3404 case SD_DIF_TYPE3_PROTECTION:
3405 host_prot = SHOST_DIF_TYPE3_PROTECTION;
3406 if (scsi_debug_dix)
3407 host_prot |= SHOST_DIX_TYPE3_PROTECTION;
3408 break;
3409
3410 default:
3411 if (scsi_debug_dix)
3412 host_prot |= SHOST_DIX_TYPE0_PROTECTION;
3413 break;
3414 }
3415
3416 scsi_host_set_prot(hpnt, host_prot);
3417
3418 printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n",
3419 (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
3420 (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
3421 (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
3422 (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
3423 (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
3424 (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
3425 (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
3426
3427 if (scsi_debug_guard == 1)
3428 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
3429 else
3430 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
3431
3003 error = scsi_add_host(hpnt, &sdbg_host->dev); 3432 error = scsi_add_host(hpnt, &sdbg_host->dev);
3004 if (error) { 3433 if (error) {
3005 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); 3434 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);