aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r--drivers/scsi/scsi_debug.c326
1 files changed, 307 insertions, 19 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 2181427a1ea5..aa4b6b80aade 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -307,7 +307,6 @@ static const unsigned char opcode_ind_arr[256] = {
307#define FF_SA (F_SA_HIGH | F_SA_LOW) 307#define FF_SA (F_SA_HIGH | F_SA_LOW)
308 308
309struct sdebug_dev_info; 309struct sdebug_dev_info;
310static int scsi_debug_queuecommand(struct scsi_cmnd *scp);
311static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *); 310static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
312static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *); 311static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
313static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *); 312static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
@@ -322,9 +321,12 @@ static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
322static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *); 321static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
323static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *); 322static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
324static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *); 323static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
324static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
325static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *);
325static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *); 326static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
326static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *); 327static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
327static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *); 328static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
329static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
328 330
329struct opcode_info_t { 331struct opcode_info_t {
330 u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff 332 u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff
@@ -383,10 +385,10 @@ static const struct opcode_info_t vl_iarr[1] = { /* VARIABLE LENGTH */
383}; 385};
384 386
385static const struct opcode_info_t maint_in_iarr[2] = { 387static const struct opcode_info_t maint_in_iarr[2] = {
386 {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, NULL, NULL, 388 {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL,
387 {12, 0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 389 {12, 0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
388 0xc7, 0, 0, 0, 0} }, 390 0xc7, 0, 0, 0, 0} },
389 {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, NULL, NULL, 391 {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL,
390 {12, 0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, 392 {12, 0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
391 0, 0} }, 393 0, 0} },
392}; 394};
@@ -487,7 +489,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
487 {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */ 489 {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */
488 {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0, 490 {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
489 0, 0, 0, 0} }, 491 0, 0, 0, 0} },
490 {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, NULL, NULL, 492 {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, resp_comp_write, NULL,
491 {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 493 {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
492 0, 0xff, 0x1f, 0xc7} }, /* COMPARE AND WRITE */ 494 0, 0xff, 0x1f, 0xc7} }, /* COMPARE AND WRITE */
493 495
@@ -1603,6 +1605,184 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp,
1603 return ret; 1605 return ret;
1604} 1606}
1605 1607
1608static int
1609resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1610{
1611 bool rctd;
1612 u8 reporting_opts, req_opcode, sdeb_i, supp;
1613 u16 req_sa, u;
1614 u32 alloc_len, a_len;
1615 int k, offset, len, errsts, count, bump, na;
1616 const struct opcode_info_t *oip;
1617 const struct opcode_info_t *r_oip;
1618 u8 *arr;
1619 u8 *cmd = scp->cmnd;
1620
1621 rctd = !!(cmd[2] & 0x80);
1622 reporting_opts = cmd[2] & 0x7;
1623 req_opcode = cmd[3];
1624 req_sa = get_unaligned_be16(cmd + 4);
1625 alloc_len = get_unaligned_be32(cmd + 6);
1626 if (alloc_len < 4 && alloc_len > 0xffff) {
1627 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1628 return check_condition_result;
1629 }
1630 if (alloc_len > 8192)
1631 a_len = 8192;
1632 else
1633 a_len = alloc_len;
1634 arr = kzalloc((a_len < 256) ? 320 : a_len + 64, GFP_KERNEL);
1635 if (NULL == arr) {
1636 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
1637 INSUFF_RES_ASCQ);
1638 return check_condition_result;
1639 }
1640 switch (reporting_opts) {
1641 case 0: /* all commands */
1642 /* count number of commands */
1643 for (count = 0, oip = opcode_info_arr;
1644 oip->num_attached != 0xff; ++oip) {
1645 if (F_INV_OP & oip->flags)
1646 continue;
1647 count += (oip->num_attached + 1);
1648 }
1649 bump = rctd ? 20 : 8;
1650 put_unaligned_be32(count * bump, arr);
1651 for (offset = 4, oip = opcode_info_arr;
1652 oip->num_attached != 0xff && offset < a_len; ++oip) {
1653 if (F_INV_OP & oip->flags)
1654 continue;
1655 na = oip->num_attached;
1656 arr[offset] = oip->opcode;
1657 put_unaligned_be16(oip->sa, arr + offset + 2);
1658 if (rctd)
1659 arr[offset + 5] |= 0x2;
1660 if (FF_SA & oip->flags)
1661 arr[offset + 5] |= 0x1;
1662 put_unaligned_be16(oip->len_mask[0], arr + offset + 6);
1663 if (rctd)
1664 put_unaligned_be16(0xa, arr + offset + 8);
1665 r_oip = oip;
1666 for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) {
1667 if (F_INV_OP & oip->flags)
1668 continue;
1669 offset += bump;
1670 arr[offset] = oip->opcode;
1671 put_unaligned_be16(oip->sa, arr + offset + 2);
1672 if (rctd)
1673 arr[offset + 5] |= 0x2;
1674 if (FF_SA & oip->flags)
1675 arr[offset + 5] |= 0x1;
1676 put_unaligned_be16(oip->len_mask[0],
1677 arr + offset + 6);
1678 if (rctd)
1679 put_unaligned_be16(0xa,
1680 arr + offset + 8);
1681 }
1682 oip = r_oip;
1683 offset += bump;
1684 }
1685 break;
1686 case 1: /* one command: opcode only */
1687 case 2: /* one command: opcode plus service action */
1688 case 3: /* one command: if sa==0 then opcode only else opcode+sa */
1689 sdeb_i = opcode_ind_arr[req_opcode];
1690 oip = &opcode_info_arr[sdeb_i];
1691 if (F_INV_OP & oip->flags) {
1692 supp = 1;
1693 offset = 4;
1694 } else {
1695 if (1 == reporting_opts) {
1696 if (FF_SA & oip->flags) {
1697 mk_sense_invalid_fld(scp, SDEB_IN_CDB,
1698 2, 2);
1699 kfree(arr);
1700 return check_condition_result;
1701 }
1702 req_sa = 0;
1703 } else if (2 == reporting_opts &&
1704 0 == (FF_SA & oip->flags)) {
1705 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
1706 kfree(arr); /* point at requested sa */
1707 return check_condition_result;
1708 }
1709 if (0 == (FF_SA & oip->flags) &&
1710 req_opcode == oip->opcode)
1711 supp = 3;
1712 else if (0 == (FF_SA & oip->flags)) {
1713 na = oip->num_attached;
1714 for (k = 0, oip = oip->arrp; k < na;
1715 ++k, ++oip) {
1716 if (req_opcode == oip->opcode)
1717 break;
1718 }
1719 supp = (k >= na) ? 1 : 3;
1720 } else if (req_sa != oip->sa) {
1721 na = oip->num_attached;
1722 for (k = 0, oip = oip->arrp; k < na;
1723 ++k, ++oip) {
1724 if (req_sa == oip->sa)
1725 break;
1726 }
1727 supp = (k >= na) ? 1 : 3;
1728 } else
1729 supp = 3;
1730 if (3 == supp) {
1731 u = oip->len_mask[0];
1732 put_unaligned_be16(u, arr + 2);
1733 arr[4] = oip->opcode;
1734 for (k = 1; k < u; ++k)
1735 arr[4 + k] = (k < 16) ?
1736 oip->len_mask[k] : 0xff;
1737 offset = 4 + u;
1738 } else
1739 offset = 4;
1740 }
1741 arr[1] = (rctd ? 0x80 : 0) | supp;
1742 if (rctd) {
1743 put_unaligned_be16(0xa, arr + offset);
1744 offset += 12;
1745 }
1746 break;
1747 default:
1748 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2);
1749 kfree(arr);
1750 return check_condition_result;
1751 }
1752 offset = (offset < a_len) ? offset : a_len;
1753 len = (offset < alloc_len) ? offset : alloc_len;
1754 errsts = fill_from_dev_buffer(scp, arr, len);
1755 kfree(arr);
1756 return errsts;
1757}
1758
1759static int
1760resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1761{
1762 bool repd;
1763 u32 alloc_len, len;
1764 u8 arr[16];
1765 u8 *cmd = scp->cmnd;
1766
1767 memset(arr, 0, sizeof(arr));
1768 repd = !!(cmd[2] & 0x80);
1769 alloc_len = get_unaligned_be32(cmd + 6);
1770 if (alloc_len < 4) {
1771 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1772 return check_condition_result;
1773 }
1774 arr[0] = 0xc8; /* ATS | ATSS | LURS */
1775 arr[1] = 0x1; /* ITNRS */
1776 if (repd) {
1777 arr[3] = 0xc;
1778 len = 16;
1779 } else
1780 len = 4;
1781
1782 len = (len < alloc_len) ? len : alloc_len;
1783 return fill_from_dev_buffer(scp, arr, len);
1784}
1785
1606/* <<Following mode page info copied from ST318451LW>> */ 1786/* <<Following mode page info copied from ST318451LW>> */
1607 1787
1608static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) 1788static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
@@ -2165,6 +2345,38 @@ do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
2165 return ret; 2345 return ret;
2166} 2346}
2167 2347
2348/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
2349 * arr into fake_store(lba,num) and return true. If comparison fails then
2350 * return false. */
2351static bool
2352comp_write_worker(u64 lba, u32 num, const u8 *arr)
2353{
2354 bool res;
2355 u64 block, rest = 0;
2356 u32 store_blks = sdebug_store_sectors;
2357 u32 lb_size = scsi_debug_sector_size;
2358
2359 block = do_div(lba, store_blks);
2360 if (block + num > store_blks)
2361 rest = block + num - store_blks;
2362
2363 res = !memcmp(fake_storep + (block * lb_size), arr,
2364 (num - rest) * lb_size);
2365 if (!res)
2366 return res;
2367 if (rest)
2368 res = memcmp(fake_storep, arr + ((num - rest) * lb_size),
2369 rest * lb_size);
2370 if (!res)
2371 return res;
2372 arr += num * lb_size;
2373 memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size);
2374 if (rest)
2375 memcpy(fake_storep, arr + ((num - rest) * lb_size),
2376 rest * lb_size);
2377 return res;
2378}
2379
2168static __be16 dif_compute_csum(const void *buf, int len) 2380static __be16 dif_compute_csum(const void *buf, int len)
2169{ 2381{
2170 __be16 csum; 2382 __be16 csum;
@@ -2821,6 +3033,82 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
2821 return resp_write_same(scp, lba, num, ei_lba, unmap, ndob); 3033 return resp_write_same(scp, lba, num, ei_lba, unmap, ndob);
2822} 3034}
2823 3035
3036static int
3037resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3038{
3039 u8 *cmd = scp->cmnd;
3040 u8 *arr;
3041 u8 *fake_storep_hold;
3042 u64 lba;
3043 u32 dnum;
3044 u32 lb_size = scsi_debug_sector_size;
3045 u8 num;
3046 unsigned long iflags;
3047 int ret;
3048
3049 lba = get_unaligned_be32(cmd + 2);
3050 num = cmd[13]; /* 1 to a maximum of 255 logical blocks */
3051 if (0 == num)
3052 return 0; /* degenerate case, not an error */
3053 dnum = 2 * num;
3054 arr = kzalloc(dnum * lb_size, GFP_ATOMIC);
3055 if (NULL == arr) {
3056 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3057 INSUFF_RES_ASCQ);
3058 return check_condition_result;
3059 }
3060 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3061 (cmd[1] & 0xe0)) {
3062 mk_sense_invalid_opcode(scp);
3063 return check_condition_result;
3064 }
3065 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3066 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3067 (cmd[1] & 0xe0) == 0)
3068 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
3069 "to DIF device\n");
3070
3071 /* inline check_device_access_params() */
3072 if (lba + num > sdebug_capacity) {
3073 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
3074 return check_condition_result;
3075 }
3076 /* transfer length excessive (tie in to block limits VPD page) */
3077 if (num > sdebug_store_sectors) {
3078 /* needs work to find which cdb byte 'num' comes from */
3079 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
3080 return check_condition_result;
3081 }
3082
3083 write_lock_irqsave(&atomic_rw, iflags);
3084
3085 /* trick do_device_access() to fetch both compare and write buffers
3086 * from data-in into arr. Safe (atomic) since write_lock held. */
3087 fake_storep_hold = fake_storep;
3088 fake_storep = arr;
3089 ret = do_device_access(scp, 0, dnum, true);
3090 fake_storep = fake_storep_hold;
3091 if (ret == -1) {
3092 write_unlock_irqrestore(&atomic_rw, iflags);
3093 kfree(arr);
3094 return DID_ERROR << 16;
3095 } else if ((ret < (dnum * lb_size)) &&
3096 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3097 sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
3098 "indicated=%u, IO sent=%d bytes\n", my_name,
3099 dnum * lb_size, ret);
3100 if (!comp_write_worker(lba, num, arr)) {
3101 write_unlock_irqrestore(&atomic_rw, iflags);
3102 kfree(arr);
3103 mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
3104 return check_condition_result;
3105 }
3106 if (scsi_debug_lbp())
3107 map_region(lba, num);
3108 write_unlock_irqrestore(&atomic_rw, iflags);
3109 return 0;
3110}
3111
2824struct unmap_block_desc { 3112struct unmap_block_desc {
2825 __be64 lba; 3113 __be64 lba;
2826 __be32 blocks; 3114 __be32 blocks;
@@ -4669,21 +4957,6 @@ static void sdebug_remove_adapter(void)
4669} 4957}
4670 4958
4671static int 4959static int
4672sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
4673{
4674 if (scsi_debug_host_lock) {
4675 unsigned long iflags;
4676 int rc;
4677
4678 spin_lock_irqsave(shost->host_lock, iflags);
4679 rc = scsi_debug_queuecommand(cmd);
4680 spin_unlock_irqrestore(shost->host_lock, iflags);
4681 return rc;
4682 } else
4683 return scsi_debug_queuecommand(cmd);
4684}
4685
4686static int
4687sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) 4960sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
4688{ 4961{
4689 int num_in_q = 0; 4962 int num_in_q = 0;
@@ -4912,6 +5185,21 @@ check_cond:
4912 return schedule_resp(scp, devip, check_condition_result, 0); 5185 return schedule_resp(scp, devip, check_condition_result, 0);
4913} 5186}
4914 5187
5188static int
5189sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
5190{
5191 if (scsi_debug_host_lock) {
5192 unsigned long iflags;
5193 int rc;
5194
5195 spin_lock_irqsave(shost->host_lock, iflags);
5196 rc = scsi_debug_queuecommand(cmd);
5197 spin_unlock_irqrestore(shost->host_lock, iflags);
5198 return rc;
5199 } else
5200 return scsi_debug_queuecommand(cmd);
5201}
5202
4915static struct scsi_host_template sdebug_driver_template = { 5203static struct scsi_host_template sdebug_driver_template = {
4916 .show_info = scsi_debug_show_info, 5204 .show_info = scsi_debug_show_info,
4917 .write_info = scsi_debug_write_info, 5205 .write_info = scsi_debug_write_info,