diff options
| -rw-r--r-- | drivers/scsi/scsi_debug.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 0a537a0515ca..d055450c2a4a 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
| @@ -439,10 +439,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, | |||
| 439 | 439 | ||
| 440 | act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents, | 440 | act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents, |
| 441 | arr, arr_len); | 441 | arr, arr_len); |
| 442 | if (sdb->resid) | 442 | sdb->resid = scsi_bufflen(scp) - act_len; |
| 443 | sdb->resid -= act_len; | ||
| 444 | else | ||
| 445 | sdb->resid = scsi_bufflen(scp) - act_len; | ||
| 446 | 443 | ||
| 447 | return 0; | 444 | return 0; |
| 448 | } | 445 | } |
| @@ -1693,24 +1690,48 @@ static int check_device_access_params(struct sdebug_dev_info *devi, | |||
| 1693 | return 0; | 1690 | return 0; |
| 1694 | } | 1691 | } |
| 1695 | 1692 | ||
| 1693 | /* Returns number of bytes copied or -1 if error. */ | ||
| 1696 | static int do_device_access(struct scsi_cmnd *scmd, | 1694 | static int do_device_access(struct scsi_cmnd *scmd, |
| 1697 | struct sdebug_dev_info *devi, | 1695 | struct sdebug_dev_info *devi, |
| 1698 | unsigned long long lba, unsigned int num, int write) | 1696 | unsigned long long lba, unsigned int num, int write) |
| 1699 | { | 1697 | { |
| 1700 | int ret; | 1698 | int ret; |
| 1701 | unsigned long long block, rest = 0; | 1699 | unsigned long long block, rest = 0; |
| 1702 | int (*func)(struct scsi_cmnd *, unsigned char *, int); | 1700 | struct scsi_data_buffer *sdb; |
| 1701 | enum dma_data_direction dir; | ||
| 1702 | size_t (*func)(struct scatterlist *, unsigned int, void *, size_t, | ||
| 1703 | off_t); | ||
| 1704 | |||
| 1705 | if (write) { | ||
| 1706 | sdb = scsi_out(scmd); | ||
| 1707 | dir = DMA_TO_DEVICE; | ||
| 1708 | func = sg_pcopy_to_buffer; | ||
| 1709 | } else { | ||
| 1710 | sdb = scsi_in(scmd); | ||
| 1711 | dir = DMA_FROM_DEVICE; | ||
| 1712 | func = sg_pcopy_from_buffer; | ||
| 1713 | } | ||
| 1703 | 1714 | ||
| 1704 | func = write ? fetch_to_dev_buffer : fill_from_dev_buffer; | 1715 | if (!sdb->length) |
| 1716 | return 0; | ||
| 1717 | if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir)) | ||
| 1718 | return -1; | ||
| 1705 | 1719 | ||
| 1706 | block = do_div(lba, sdebug_store_sectors); | 1720 | block = do_div(lba, sdebug_store_sectors); |
| 1707 | if (block + num > sdebug_store_sectors) | 1721 | if (block + num > sdebug_store_sectors) |
| 1708 | rest = block + num - sdebug_store_sectors; | 1722 | rest = block + num - sdebug_store_sectors; |
| 1709 | 1723 | ||
| 1710 | ret = func(scmd, fake_storep + (block * scsi_debug_sector_size), | 1724 | ret = func(sdb->table.sgl, sdb->table.nents, |
| 1711 | (num - rest) * scsi_debug_sector_size); | 1725 | fake_storep + (block * scsi_debug_sector_size), |
| 1712 | if (!ret && rest) | 1726 | (num - rest) * scsi_debug_sector_size, 0); |
| 1713 | ret = func(scmd, fake_storep, rest * scsi_debug_sector_size); | 1727 | if (ret != (num - rest) * scsi_debug_sector_size) |
| 1728 | return ret; | ||
| 1729 | |||
| 1730 | if (rest) { | ||
| 1731 | ret += func(sdb->table.sgl, sdb->table.nents, | ||
| 1732 | fake_storep, rest * scsi_debug_sector_size, | ||
| 1733 | (num - rest) * scsi_debug_sector_size); | ||
| 1734 | } | ||
| 1714 | 1735 | ||
| 1715 | return ret; | 1736 | return ret; |
| 1716 | } | 1737 | } |
| @@ -1849,7 +1870,12 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, | |||
| 1849 | read_lock_irqsave(&atomic_rw, iflags); | 1870 | read_lock_irqsave(&atomic_rw, iflags); |
| 1850 | ret = do_device_access(SCpnt, devip, lba, num, 0); | 1871 | ret = do_device_access(SCpnt, devip, lba, num, 0); |
| 1851 | read_unlock_irqrestore(&atomic_rw, iflags); | 1872 | read_unlock_irqrestore(&atomic_rw, iflags); |
| 1852 | return ret; | 1873 | if (ret == -1) |
| 1874 | return DID_ERROR << 16; | ||
| 1875 | |||
| 1876 | scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret; | ||
| 1877 | |||
| 1878 | return 0; | ||
| 1853 | } | 1879 | } |
| 1854 | 1880 | ||
| 1855 | void dump_sector(unsigned char *buf, int len) | 1881 | void dump_sector(unsigned char *buf, int len) |
