aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_debug.c70
-rw-r--r--include/scsi/scsi.h1
2 files changed, 71 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index d810aa7aee40..1541c174937a 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -280,6 +280,8 @@ static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
280 unsigned int num, struct sdebug_dev_info * devip); 280 unsigned int num, struct sdebug_dev_info * devip);
281static int resp_report_luns(struct scsi_cmnd * SCpnt, 281static int resp_report_luns(struct scsi_cmnd * SCpnt,
282 struct sdebug_dev_info * devip); 282 struct sdebug_dev_info * devip);
283static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
284 unsigned int num, struct sdebug_dev_info *devip);
283static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, 285static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
284 int arr_len); 286 int arr_len);
285static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, 287static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
@@ -334,6 +336,7 @@ static void get_data_transfer_info(unsigned char *cmd,
334 break; 336 break;
335 case WRITE_10: 337 case WRITE_10:
336 case READ_10: 338 case READ_10:
339 case XDWRITEREAD_10:
337 *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); 340 *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
338 *num = cmd[8] + (cmd[7] << 8); 341 *num = cmd[8] + (cmd[7] << 8);
339 break; 342 break;
@@ -542,6 +545,28 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
542 case WRITE_BUFFER: 545 case WRITE_BUFFER:
543 errsts = check_readiness(SCpnt, 1, devip); 546 errsts = check_readiness(SCpnt, 1, devip);
544 break; 547 break;
548 case XDWRITEREAD_10:
549 if (!scsi_bidi_cmnd(SCpnt)) {
550 mk_sense_buffer(devip, ILLEGAL_REQUEST,
551 INVALID_FIELD_IN_CDB, 0);
552 errsts = check_condition_result;
553 break;
554 }
555
556 errsts = check_readiness(SCpnt, 0, devip);
557 if (errsts)
558 break;
559 if (scsi_debug_fake_rw)
560 break;
561 get_data_transfer_info(cmd, &lba, &num);
562 errsts = resp_read(SCpnt, lba, num, devip);
563 if (errsts)
564 break;
565 errsts = resp_write(SCpnt, lba, num, devip);
566 if (errsts)
567 break;
568 errsts = resp_xdwriteread(SCpnt, lba, num, devip);
569 break;
545 default: 570 default:
546 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 571 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
547 printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " 572 printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
@@ -1948,6 +1973,50 @@ static int resp_report_luns(struct scsi_cmnd * scp,
1948 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ)); 1973 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
1949} 1974}
1950 1975
1976static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
1977 unsigned int num, struct sdebug_dev_info *devip)
1978{
1979 int i, j, ret = -1;
1980 unsigned char *kaddr, *buf;
1981 unsigned int offset;
1982 struct scatterlist *sg;
1983 struct scsi_data_buffer *sdb = scsi_in(scp);
1984
1985 /* better not to use temporary buffer. */
1986 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
1987 if (!buf)
1988 return ret;
1989
1990 offset = 0;
1991 scsi_for_each_sg(scp, sg, scsi_sg_count(scp), i) {
1992 kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
1993 if (!kaddr)
1994 goto out;
1995
1996 memcpy(buf + offset, kaddr + sg->offset, sg->length);
1997 offset += sg->length;
1998 kunmap_atomic(kaddr, KM_USER0);
1999 }
2000
2001 offset = 0;
2002 for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
2003 kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
2004 if (!kaddr)
2005 goto out;
2006
2007 for (j = 0; j < sg->length; j++)
2008 *(kaddr + sg->offset + j) ^= *(buf + offset + j);
2009
2010 offset += sg->length;
2011 kunmap_atomic(kaddr, KM_USER0);
2012 }
2013 ret = 0;
2014out:
2015 kfree(buf);
2016
2017 return ret;
2018}
2019
1951/* When timer goes off this function is called. */ 2020/* When timer goes off this function is called. */
1952static void timer_intr_handler(unsigned long indx) 2021static void timer_intr_handler(unsigned long indx)
1953{ 2022{
@@ -1981,6 +2050,7 @@ static int scsi_debug_slave_alloc(struct scsi_device * sdp)
1981 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 2050 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
1982 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", 2051 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
1983 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); 2052 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
2053 set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags);
1984 return 0; 2054 return 0;
1985} 2055}
1986 2056
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 0f55f5b24896..82251575a9b4 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -102,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
102#define READ_TOC 0x43 102#define READ_TOC 0x43
103#define LOG_SELECT 0x4c 103#define LOG_SELECT 0x4c
104#define LOG_SENSE 0x4d 104#define LOG_SENSE 0x4d
105#define XDWRITEREAD_10 0x53
105#define MODE_SELECT_10 0x55 106#define MODE_SELECT_10 0x55
106#define RESERVE_10 0x56 107#define RESERVE_10 0x56
107#define RELEASE_10 0x57 108#define RELEASE_10 0x57