diff options
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 326 |
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 | ||
309 | struct sdebug_dev_info; | 309 | struct sdebug_dev_info; |
310 | static int scsi_debug_queuecommand(struct scsi_cmnd *scp); | ||
311 | static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *); | 310 | static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *); |
312 | static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *); | 311 | static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *); |
313 | static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *); | 312 | static 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 *); | |||
322 | static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *); | 321 | static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *); |
323 | static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *); | 322 | static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *); |
324 | static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *); | 323 | static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *); |
324 | static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
325 | static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
325 | static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *); | 326 | static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *); |
326 | static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *); | 327 | static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *); |
327 | static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *); | 328 | static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *); |
329 | static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
328 | 330 | ||
329 | struct opcode_info_t { | 331 | struct 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 | ||
385 | static const struct opcode_info_t maint_in_iarr[2] = { | 387 | static 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 | ||
1608 | static int | ||
1609 | resp_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 | |||
1759 | static int | ||
1760 | resp_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 | ||
1608 | static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) | 1788 | static 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. */ | ||
2351 | static bool | ||
2352 | comp_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 | |||
2168 | static __be16 dif_compute_csum(const void *buf, int len) | 2380 | static __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 | ||
3036 | static int | ||
3037 | resp_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 | |||
2824 | struct unmap_block_desc { | 3112 | struct 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 | ||
4671 | static int | 4959 | static int |
4672 | sdebug_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 | |||
4686 | static int | ||
4687 | sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) | 4960 | sdebug_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 | ||
5188 | static int | ||
5189 | sdebug_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 | |||
4915 | static struct scsi_host_template sdebug_driver_template = { | 5203 | static 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, |