aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_debug.c48
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. */
1696static int do_device_access(struct scsi_cmnd *scmd, 1694static 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
1855void dump_sector(unsigned char *buf, int len) 1881void dump_sector(unsigned char *buf, int len)