All of lore.kernel.org
 help / color / mirror / Atom feed
* RE: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained
  2015-03-23 21:06     ` K. Y. Srinivasan
  (?)
@ 2015-03-23 20:52     ` Long Li
  -1 siblings, 0 replies; 22+ messages in thread
From: Long Li @ 2015-03-23 20:52 UTC (permalink / raw)
  To: KY Srinivasan, gregkh, linux-kernel, devel, ohering, jbottomley,
	hch, linux-scsi, apw, vkuznets, jasowang



> -----Original Message-----
> From: devel [mailto:driverdev-devel-bounces@linuxdriverproject.org] On
> Behalf Of K. Y. Srinivasan
> Sent: Monday, March 23, 2015 2:07 PM
> To: gregkh@linuxfoundation.org; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; ohering@suse.com; jbottomley@parallels.com;
> hch@infradead.org; linux-scsi@vger.kernel.org; apw@canonical.com;
> vkuznets@redhat.com; jasowang@redhat.com
> Subject: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not
> chained
> 
> The current code assumes that the scatterlists presented are not chained.
> Fix the code to not make this assumption.
> 
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>

> ---
>  drivers/scsi/storvsc_drv.c |   98 +++++++++++++++++++++++++------------------
>  1 files changed, 57 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index
> 88f5d79..a599677 100644
> --- a/drivers/scsi/storvsc_drv.c
> +++ b/drivers/scsi/storvsc_drv.c
> @@ -626,19 +626,6 @@ cleanup:
>  	return NULL;
>  }
> 
> -/* Disgusting wrapper functions */
> -static inline unsigned long sg_kmap_atomic(struct scatterlist *sgl, int idx) -{
> -	void *addr = kmap_atomic(sg_page(sgl + idx));
> -	return (unsigned long)addr;
> -}
> -
> -static inline void sg_kunmap_atomic(unsigned long addr) -{
> -	kunmap_atomic((void *)addr);
> -}
> -
> -
>  /* Assume the original sgl has enough room */  static unsigned int
> copy_from_bounce_buffer(struct scatterlist *orig_sgl,
>  					    struct scatterlist *bounce_sgl, @@ -
> 653,32 +640,39 @@ static unsigned int copy_from_bounce_buffer(struct
> scatterlist *orig_sgl,
>  	unsigned long bounce_addr = 0;
>  	unsigned long dest_addr = 0;
>  	unsigned long flags;
> +	struct scatterlist *cur_dest_sgl;
> +	struct scatterlist *cur_src_sgl;
> 
>  	local_irq_save(flags);
> -
> +	cur_dest_sgl = orig_sgl;
> +	cur_src_sgl = bounce_sgl;
>  	for (i = 0; i < orig_sgl_count; i++) {
> -		dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
> +		dest_addr = (unsigned long)
> +				kmap_atomic(sg_page(cur_dest_sgl)) +
> +				cur_dest_sgl->offset;
>  		dest = dest_addr;
>  		destlen = orig_sgl[i].length;
> +		destlen = cur_dest_sgl->length;
> 
>  		if (bounce_addr == 0)
> -			bounce_addr = sg_kmap_atomic(bounce_sgl,j);
> +			bounce_addr = (unsigned long)kmap_atomic(
> +							sg_page(cur_src_sgl));
> 
>  		while (destlen) {
> -			src = bounce_addr + bounce_sgl[j].offset;
> -			srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
> +			src = bounce_addr + cur_src_sgl->offset;
> +			srclen = cur_src_sgl->length - cur_src_sgl->offset;
> 
>  			copylen = min(srclen, destlen);
>  			memcpy((void *)dest, (void *)src, copylen);
> 
>  			total_copied += copylen;
> -			bounce_sgl[j].offset += copylen;
> +			cur_src_sgl->offset += copylen;
>  			destlen -= copylen;
>  			dest += copylen;
> 
> -			if (bounce_sgl[j].offset == bounce_sgl[j].length) {
> +			if (cur_src_sgl->offset == cur_src_sgl->length) {
>  				/* full */
> -				sg_kunmap_atomic(bounce_addr);
> +				kunmap_atomic((void *)bounce_addr);
>  				j++;
> 
>  				/*
> @@ -692,21 +686,27 @@ static unsigned int copy_from_bounce_buffer(struct
> scatterlist *orig_sgl,
>  					/*
>  					 * We are done; cleanup and return.
>  					 */
> -					sg_kunmap_atomic(dest_addr -
> orig_sgl[i].offset);
> +					kunmap_atomic((void *)(dest_addr -
> +						cur_dest_sgl->offset));
>  					local_irq_restore(flags);
>  					return total_copied;
>  				}
> 
>  				/* if we need to use another bounce buffer */
> -				if (destlen || i != orig_sgl_count - 1)
> -					bounce_addr =
> sg_kmap_atomic(bounce_sgl,j);
> +				if (destlen || i != orig_sgl_count - 1) {
> +					cur_src_sgl = sg_next(cur_src_sgl);
> +					bounce_addr = (unsigned long)
> +							kmap_atomic(
> +							sg_page(cur_src_sgl));
> +				}
>  			} else if (destlen == 0 && i == orig_sgl_count - 1) {
>  				/* unmap the last bounce that is < PAGE_SIZE
> */
> -				sg_kunmap_atomic(bounce_addr);
> +				kunmap_atomic((void *)bounce_addr);
>  			}
>  		}
> 
> -		sg_kunmap_atomic(dest_addr - orig_sgl[i].offset);
> +		kunmap_atomic((void *)(dest_addr - cur_dest_sgl->offset));
> +		cur_dest_sgl = sg_next(cur_dest_sgl);
>  	}
> 
>  	local_irq_restore(flags);
> @@ -727,48 +727,61 @@ static unsigned int copy_to_bounce_buffer(struct
> scatterlist *orig_sgl,
>  	unsigned long bounce_addr = 0;
>  	unsigned long src_addr = 0;
>  	unsigned long flags;
> +	struct scatterlist *cur_src_sgl;
> +	struct scatterlist *cur_dest_sgl;
> 
>  	local_irq_save(flags);
> 
> +	cur_src_sgl = orig_sgl;
> +	cur_dest_sgl = bounce_sgl;
> +
>  	for (i = 0; i < orig_sgl_count; i++) {
> -		src_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
> +		src_addr = (unsigned long)
> +				kmap_atomic(sg_page(cur_src_sgl)) +
> +				cur_src_sgl->offset;
>  		src = src_addr;
> -		srclen = orig_sgl[i].length;
> +		srclen = cur_src_sgl->length;
> 
>  		if (bounce_addr == 0)
> -			bounce_addr = sg_kmap_atomic(bounce_sgl,j);
> +			bounce_addr = (unsigned long)
> +					kmap_atomic(sg_page(cur_dest_sgl));
> 
>  		while (srclen) {
>  			/* assume bounce offset always == 0 */
> -			dest = bounce_addr + bounce_sgl[j].length;
> -			destlen = PAGE_SIZE - bounce_sgl[j].length;
> +			dest = bounce_addr + cur_dest_sgl->length;
> +			destlen = PAGE_SIZE - cur_dest_sgl->length;
> 
>  			copylen = min(srclen, destlen);
>  			memcpy((void *)dest, (void *)src, copylen);
> 
>  			total_copied += copylen;
> -			bounce_sgl[j].length += copylen;
> +			cur_dest_sgl->length += copylen;
>  			srclen -= copylen;
>  			src += copylen;
> 
> -			if (bounce_sgl[j].length == PAGE_SIZE) {
> +			if (cur_dest_sgl->length == PAGE_SIZE) {
>  				/* full..move to next entry */
> -				sg_kunmap_atomic(bounce_addr);
> +				kunmap_atomic((void *)bounce_addr);
>  				bounce_addr = 0;
>  				j++;
>  			}
> 
>  			/* if we need to use another bounce buffer */
> -			if (srclen && bounce_addr == 0)
> -				bounce_addr = sg_kmap_atomic(bounce_sgl,
> j);
> +			if (srclen && bounce_addr == 0) {
> +				cur_dest_sgl = sg_next(cur_dest_sgl);
> +				bounce_addr = (unsigned long)
> +						kmap_atomic(
> +						sg_page(cur_dest_sgl));
> +			}
> 
>  		}
> 
> -		sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
> +		kunmap_atomic((void *)(src_addr - cur_src_sgl->offset));
> +		cur_src_sgl = sg_next(cur_src_sgl);
>  	}
> 
>  	if (bounce_addr)
> -		sg_kunmap_atomic(bounce_addr);
> +		kunmap_atomic((void *)bounce_addr);
> 
>  	local_irq_restore(flags);
> 
> @@ -1536,6 +1549,7 @@ static int storvsc_queuecommand(struct Scsi_Host
> *host, struct scsi_cmnd *scmnd)
>  	struct scatterlist *sgl;
>  	unsigned int sg_count = 0;
>  	struct vmscsi_request *vm_srb;
> +	struct scatterlist *cur_sgl;
> 
>  	if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
>  		/*
> @@ -1617,10 +1631,12 @@ static int storvsc_queuecommand(struct
> Scsi_Host *host, struct scsi_cmnd *scmnd)
>  		}
> 
>  		cmd_request->data_buffer.offset = sgl[0].offset;
> -
> -		for (i = 0; i < sg_count; i++)
> +		cur_sgl = sgl;
> +		for (i = 0; i < sg_count; i++) {
>  			cmd_request->data_buffer.pfn_array[i] =
> -				page_to_pfn(sg_page((&sgl[i])));
> +				page_to_pfn(sg_page((cur_sgl)));
> +			cur_sgl = sg_next(cur_sgl);
> +		}
> 
>  	} else if (scsi_sglist(scmnd)) {
>  		cmd_request->data_buffer.offset =
> --
> 1.7.4.1
> 
> _______________________________________________
> devel mailing list
> devel@linuxdriverproject.org
> http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply	[flat|nested] 22+ messages in thread

* RE: [PATCH 5/7] scsi: storvsc: Fix a bug in copy_from_bounce_buffer()
  2015-03-23 21:06     ` K. Y. Srinivasan
  (?)
@ 2015-03-23 20:52     ` Long Li
  -1 siblings, 0 replies; 22+ messages in thread
From: Long Li @ 2015-03-23 20:52 UTC (permalink / raw)
  To: KY Srinivasan, gregkh, linux-kernel, devel, ohering, jbottomley,
	hch, linux-scsi, apw, vkuznets, jasowang
  Cc: stable



> -----Original Message-----
> From: devel [mailto:driverdev-devel-bounces@linuxdriverproject.org] On
> Behalf Of K. Y. Srinivasan
> Sent: Monday, March 23, 2015 2:07 PM
> To: gregkh@linuxfoundation.org; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; ohering@suse.com; jbottomley@parallels.com;
> hch@infradead.org; linux-scsi@vger.kernel.org; apw@canonical.com;
> vkuznets@redhat.com; jasowang@redhat.com
> Cc: stable@vger.kernel.org
> Subject: [PATCH 5/7] scsi: storvsc: Fix a bug in copy_from_bounce_buffer()
> 
> We may exit this function without properly freeing up the maapings we may
> have acquired. Fix the bug.
> 
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>

> Cc: <stable@vger.kernel.org>
> ---
>  drivers/scsi/storvsc_drv.c |   15 ++++++++-------
>  1 files changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index
> 5c13eec..88f5d79 100644
> --- a/drivers/scsi/storvsc_drv.c
> +++ b/drivers/scsi/storvsc_drv.c
> @@ -754,21 +754,22 @@ static unsigned int copy_to_bounce_buffer(struct
> scatterlist *orig_sgl,
>  			if (bounce_sgl[j].length == PAGE_SIZE) {
>  				/* full..move to next entry */
>  				sg_kunmap_atomic(bounce_addr);
> +				bounce_addr = 0;
>  				j++;
> +			}
> 
> -				/* if we need to use another bounce buffer */
> -				if (srclen || i != orig_sgl_count - 1)
> -					bounce_addr =
> sg_kmap_atomic(bounce_sgl,j);
> +			/* if we need to use another bounce buffer */
> +			if (srclen && bounce_addr == 0)
> +				bounce_addr = sg_kmap_atomic(bounce_sgl,
> j);
> 
> -			} else if (srclen == 0 && i == orig_sgl_count - 1) {
> -				/* unmap the last bounce that is < PAGE_SIZE
> */
> -				sg_kunmap_atomic(bounce_addr);
> -			}
>  		}
> 
>  		sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
>  	}
> 
> +	if (bounce_addr)
> +		sg_kunmap_atomic(bounce_addr);
> +
>  	local_irq_restore(flags);
> 
>  	return total_copied;
> --
> 1.7.4.1
> 
> _______________________________________________
> devel mailing list
> devel@linuxdriverproject.org
> http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 0/7] scsi: storvsc: Miscellaneous enhancements and fixes
@ 2015-03-23 21:06 K. Y. Srinivasan
  2015-03-23 21:06 ` [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size K. Y. Srinivasan
  0 siblings, 1 reply; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

This patch-set addresses perf issues discovered on the Azure storage stack.
These patches also fix a couple of bugs.

K. Y. Srinivasan (7):
  scsi: storvsc: Increase the ring buffer size
  scsi: storvsc: Size the queue depth based on the ringbuffer size
  scsi: storvsc: Always send on the selected outgoing channel
  scsi: storvsc: Retrieve information about the capability of the
    target
  scsi: storvsc: Fix a bug in copy_from_bounce_buffer()
  scsi: storvsc: Don't assume that the scatterlist is not chained
  scsi: storvsc: Set the tablesize based on the information given by
    the host

 drivers/scsi/storvsc_drv.c |  231 ++++++++++++++++++++++++++++----------------
 1 files changed, 149 insertions(+), 82 deletions(-)

-- 
1.7.4.1


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size
  2015-03-23 21:06 [PATCH 0/7] scsi: storvsc: Miscellaneous enhancements and fixes K. Y. Srinivasan
@ 2015-03-23 21:06 ` K. Y. Srinivasan
  2015-03-23 21:06     ` K. Y. Srinivasan
                     ` (5 more replies)
  0 siblings, 6 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

Increase the default ring buffer size as this can significantly
improve performance especially on high latency storage back-ends.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index efc6e44..27fe850 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -308,7 +308,7 @@ enum storvsc_request_type {
  * This is the end of Protocol specific defines.
  */
 
-static int storvsc_ringbuffer_size = (20 * PAGE_SIZE);
+static int storvsc_ringbuffer_size = (256 * PAGE_SIZE);
 
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
  2015-03-23 21:06 ` [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size K. Y. Srinivasan
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  2015-03-23 21:06     ` K. Y. Srinivasan
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

Size the queue depth based on the ringbuffer size. Also accomodate for the
fact that we could have multiple channels (ringbuffers) per adaptor.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |   27 ++++++++++++++++-----------
 1 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 27fe850..5a12897 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -309,10 +309,15 @@ enum storvsc_request_type {
  */
 
 static int storvsc_ringbuffer_size = (256 * PAGE_SIZE);
+static u32 max_outstanding_req_per_channel;
+
+static int storvsc_vcpus_per_sub_channel = 4;
 
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 
+module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO);
+MODULE_PARM_DESC(vcpus_per_sub_channel, "Ratio of VCPUs to subchannels");
 /*
  * Timeout in seconds for all devices managed by this driver.
  */
@@ -320,7 +325,6 @@ static int storvsc_timeout = 180;
 
 static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
 
-#define STORVSC_MAX_IO_REQUESTS				200
 
 static void storvsc_on_channel_callback(void *context);
 
@@ -1376,7 +1380,6 @@ static int storvsc_do_io(struct hv_device *device,
 
 static int storvsc_device_configure(struct scsi_device *sdevice)
 {
-	scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS);
 
 	blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
 
@@ -1646,7 +1649,6 @@ static struct scsi_host_template scsi_driver = {
 	.eh_timed_out =		storvsc_eh_timed_out,
 	.slave_configure =	storvsc_device_configure,
 	.cmd_per_lun =		255,
-	.can_queue =		STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
 	.this_id =		-1,
 	/* no use setting to 0 since ll_blk_rw reset it to 1 */
 	/* currently 32 */
@@ -1686,6 +1688,7 @@ static int storvsc_probe(struct hv_device *device,
 			const struct hv_vmbus_device_id *dev_id)
 {
 	int ret;
+	int num_cpus = num_online_cpus();
 	struct Scsi_Host *host;
 	struct hv_host_device *host_dev;
 	bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
@@ -1694,6 +1697,7 @@ static int storvsc_probe(struct hv_device *device,
 	int max_luns_per_target;
 	int max_targets;
 	int max_channels;
+	int max_sub_channels = 0;
 
 	/*
 	 * Based on the windows host we are running on,
@@ -1719,12 +1723,18 @@ static int storvsc_probe(struct hv_device *device,
 		max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET;
 		max_targets = STORVSC_MAX_TARGETS;
 		max_channels = STORVSC_MAX_CHANNELS;
+		/*
+		 * On Windows8 and above, we support sub-channels for storage.
+		 * The number of sub-channels offerred is based on the number of
+		 * VCPUs in the guest.
+		 */
+		max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel);
 		break;
 	}
 
-	if (dev_id->driver_data == SFC_GUID)
-		scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS *
-					 STORVSC_FC_MAX_TARGETS);
+	scsi_driver.can_queue = (max_outstanding_req_per_channel *
+				 max_sub_channels + 1);
+
 	host = scsi_host_alloc(&scsi_driver,
 			       sizeof(struct hv_host_device));
 	if (!host)
@@ -1837,7 +1847,6 @@ static struct hv_driver storvsc_drv = {
 
 static int __init storvsc_drv_init(void)
 {
-	u32 max_outstanding_req_per_channel;
 
 	/*
 	 * Divide the ring buffer data size (which is 1 page less
@@ -1852,10 +1861,6 @@ static int __init storvsc_drv_init(void)
 		vmscsi_size_delta,
 		sizeof(u64)));
 
-	if (max_outstanding_req_per_channel <
-	    STORVSC_MAX_IO_REQUESTS)
-		return -EINVAL;
-
 	return vmbus_driver_register(&storvsc_drv);
 }
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang

Size the queue depth based on the ringbuffer size. Also accomodate for the
fact that we could have multiple channels (ringbuffers) per adaptor.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |   27 ++++++++++++++++-----------
 1 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 27fe850..5a12897 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -309,10 +309,15 @@ enum storvsc_request_type {
  */
 
 static int storvsc_ringbuffer_size = (256 * PAGE_SIZE);
+static u32 max_outstanding_req_per_channel;
+
+static int storvsc_vcpus_per_sub_channel = 4;
 
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 
+module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO);
+MODULE_PARM_DESC(vcpus_per_sub_channel, "Ratio of VCPUs to subchannels");
 /*
  * Timeout in seconds for all devices managed by this driver.
  */
@@ -320,7 +325,6 @@ static int storvsc_timeout = 180;
 
 static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
 
-#define STORVSC_MAX_IO_REQUESTS				200
 
 static void storvsc_on_channel_callback(void *context);
 
@@ -1376,7 +1380,6 @@ static int storvsc_do_io(struct hv_device *device,
 
 static int storvsc_device_configure(struct scsi_device *sdevice)
 {
-	scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS);
 
 	blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
 
@@ -1646,7 +1649,6 @@ static struct scsi_host_template scsi_driver = {
 	.eh_timed_out =		storvsc_eh_timed_out,
 	.slave_configure =	storvsc_device_configure,
 	.cmd_per_lun =		255,
-	.can_queue =		STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
 	.this_id =		-1,
 	/* no use setting to 0 since ll_blk_rw reset it to 1 */
 	/* currently 32 */
@@ -1686,6 +1688,7 @@ static int storvsc_probe(struct hv_device *device,
 			const struct hv_vmbus_device_id *dev_id)
 {
 	int ret;
+	int num_cpus = num_online_cpus();
 	struct Scsi_Host *host;
 	struct hv_host_device *host_dev;
 	bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
@@ -1694,6 +1697,7 @@ static int storvsc_probe(struct hv_device *device,
 	int max_luns_per_target;
 	int max_targets;
 	int max_channels;
+	int max_sub_channels = 0;
 
 	/*
 	 * Based on the windows host we are running on,
@@ -1719,12 +1723,18 @@ static int storvsc_probe(struct hv_device *device,
 		max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET;
 		max_targets = STORVSC_MAX_TARGETS;
 		max_channels = STORVSC_MAX_CHANNELS;
+		/*
+		 * On Windows8 and above, we support sub-channels for storage.
+		 * The number of sub-channels offerred is based on the number of
+		 * VCPUs in the guest.
+		 */
+		max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel);
 		break;
 	}
 
-	if (dev_id->driver_data == SFC_GUID)
-		scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS *
-					 STORVSC_FC_MAX_TARGETS);
+	scsi_driver.can_queue = (max_outstanding_req_per_channel *
+				 max_sub_channels + 1);
+
 	host = scsi_host_alloc(&scsi_driver,
 			       sizeof(struct hv_host_device));
 	if (!host)
@@ -1837,7 +1847,6 @@ static struct hv_driver storvsc_drv = {
 
 static int __init storvsc_drv_init(void)
 {
-	u32 max_outstanding_req_per_channel;
 
 	/*
 	 * Divide the ring buffer data size (which is 1 page less
@@ -1852,10 +1861,6 @@ static int __init storvsc_drv_init(void)
 		vmscsi_size_delta,
 		sizeof(u64)));
 
-	if (max_outstanding_req_per_channel <
-	    STORVSC_MAX_IO_REQUESTS)
-		return -EINVAL;
-
 	return vmbus_driver_register(&storvsc_drv);
 }
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH RESEND 3/7] scsi: storvsc: Always send on the selected outgoing channel
  2015-03-23 21:06 ` [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size K. Y. Srinivasan
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  2015-03-23 21:06     ` K. Y. Srinivasan
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

The current code always sent packets without data on the primary channel.
Properly distribute sending of packets with no data amongst all available
channels. I would like to thank Long Li for noticing this problem.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 5a12897..be8f12e 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1362,7 +1362,7 @@ static int storvsc_do_io(struct hv_device *device,
 				vmscsi_size_delta),
 				(unsigned long)request);
 	} else {
-		ret = vmbus_sendpacket(device->channel, vstor_packet,
+		ret = vmbus_sendpacket(outgoing_channel, vstor_packet,
 			       (sizeof(struct vstor_packet) -
 				vmscsi_size_delta),
 			       (unsigned long)request,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH RESEND 3/7] scsi: storvsc: Always send on the selected outgoing channel
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang

The current code always sent packets without data on the primary channel.
Properly distribute sending of packets with no data amongst all available
channels. I would like to thank Long Li for noticing this problem.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 5a12897..be8f12e 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1362,7 +1362,7 @@ static int storvsc_do_io(struct hv_device *device,
 				vmscsi_size_delta),
 				(unsigned long)request);
 	} else {
-		ret = vmbus_sendpacket(device->channel, vstor_packet,
+		ret = vmbus_sendpacket(outgoing_channel, vstor_packet,
 			       (sizeof(struct vstor_packet) -
 				vmscsi_size_delta),
 			       (unsigned long)request,
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH RESEND 4/7] scsi: storvsc: Retrieve information about the capability of the target
  2015-03-23 21:06 ` [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size K. Y. Srinivasan
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  2015-03-23 21:06     ` K. Y. Srinivasan
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

The storage protocol informs the guest of the I/O capabilities of the storage
stack. Retrieve this information and use it in the guest.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index be8f12e..5c13eec 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -377,6 +377,10 @@ struct storvsc_device {
 	unsigned char path_id;
 	unsigned char target_id;
 
+	/*
+	 * Max I/O, the device can support.
+	 */
+	u32   max_transfer_bytes;
 	/* Used for vsc/vsp channel reset process */
 	struct storvsc_cmd_request init_request;
 	struct storvsc_cmd_request reset_request;
@@ -974,6 +978,8 @@ static int storvsc_channel_init(struct hv_device *device)
 		    STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL)
 			process_sub_channels = true;
 	}
+	stor_device->max_transfer_bytes =
+		vstor_packet->storage_channel_properties.max_transfer_bytes;
 
 	memset(vstor_packet, 0, sizeof(struct vstor_packet));
 	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH RESEND 4/7] scsi: storvsc: Retrieve information about the capability of the target
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang

The storage protocol informs the guest of the I/O capabilities of the storage
stack. Retrieve this information and use it in the guest.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index be8f12e..5c13eec 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -377,6 +377,10 @@ struct storvsc_device {
 	unsigned char path_id;
 	unsigned char target_id;
 
+	/*
+	 * Max I/O, the device can support.
+	 */
+	u32   max_transfer_bytes;
 	/* Used for vsc/vsp channel reset process */
 	struct storvsc_cmd_request init_request;
 	struct storvsc_cmd_request reset_request;
@@ -974,6 +978,8 @@ static int storvsc_channel_init(struct hv_device *device)
 		    STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL)
 			process_sub_channels = true;
 	}
+	stor_device->max_transfer_bytes =
+		vstor_packet->storage_channel_properties.max_transfer_bytes;
 
 	memset(vstor_packet, 0, sizeof(struct vstor_packet));
 	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/7] scsi: storvsc: Fix a bug in copy_from_bounce_buffer()
  2015-03-23 21:06 ` [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size K. Y. Srinivasan
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  2015-03-23 21:06     ` K. Y. Srinivasan
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan, stable

We may exit this function without properly freeing up the maapings
we may have acquired. Fix the bug.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Cc: <stable@vger.kernel.org>
---
 drivers/scsi/storvsc_drv.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 5c13eec..88f5d79 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -754,21 +754,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 			if (bounce_sgl[j].length == PAGE_SIZE) {
 				/* full..move to next entry */
 				sg_kunmap_atomic(bounce_addr);
+				bounce_addr = 0;
 				j++;
+			}
 
-				/* if we need to use another bounce buffer */
-				if (srclen || i != orig_sgl_count - 1)
-					bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+			/* if we need to use another bounce buffer */
+			if (srclen && bounce_addr == 0)
+				bounce_addr = sg_kmap_atomic(bounce_sgl, j);
 
-			} else if (srclen == 0 && i == orig_sgl_count - 1) {
-				/* unmap the last bounce that is < PAGE_SIZE */
-				sg_kunmap_atomic(bounce_addr);
-			}
 		}
 
 		sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
 	}
 
+	if (bounce_addr)
+		sg_kunmap_atomic(bounce_addr);
+
 	local_irq_restore(flags);
 
 	return total_copied;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/7] scsi: storvsc: Fix a bug in copy_from_bounce_buffer()
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan, stable

We may exit this function without properly freeing up the maapings
we may have acquired. Fix the bug.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Cc: <stable@vger.kernel.org>
---
 drivers/scsi/storvsc_drv.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 5c13eec..88f5d79 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -754,21 +754,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 			if (bounce_sgl[j].length == PAGE_SIZE) {
 				/* full..move to next entry */
 				sg_kunmap_atomic(bounce_addr);
+				bounce_addr = 0;
 				j++;
+			}
 
-				/* if we need to use another bounce buffer */
-				if (srclen || i != orig_sgl_count - 1)
-					bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+			/* if we need to use another bounce buffer */
+			if (srclen && bounce_addr == 0)
+				bounce_addr = sg_kmap_atomic(bounce_sgl, j);
 
-			} else if (srclen == 0 && i == orig_sgl_count - 1) {
-				/* unmap the last bounce that is < PAGE_SIZE */
-				sg_kunmap_atomic(bounce_addr);
-			}
 		}
 
 		sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
 	}
 
+	if (bounce_addr)
+		sg_kunmap_atomic(bounce_addr);
+
 	local_irq_restore(flags);
 
 	return total_copied;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained
  2015-03-23 21:06 ` [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size K. Y. Srinivasan
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  2015-03-23 21:06     ` K. Y. Srinivasan
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

The current code assumes that the scatterlists presented are not chained.
Fix the code to not make this assumption.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |   98 +++++++++++++++++++++++++------------------
 1 files changed, 57 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 88f5d79..a599677 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -626,19 +626,6 @@ cleanup:
 	return NULL;
 }
 
-/* Disgusting wrapper functions */
-static inline unsigned long sg_kmap_atomic(struct scatterlist *sgl, int idx)
-{
-	void *addr = kmap_atomic(sg_page(sgl + idx));
-	return (unsigned long)addr;
-}
-
-static inline void sg_kunmap_atomic(unsigned long addr)
-{
-	kunmap_atomic((void *)addr);
-}
-
-
 /* Assume the original sgl has enough room */
 static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 					    struct scatterlist *bounce_sgl,
@@ -653,32 +640,39 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 	unsigned long bounce_addr = 0;
 	unsigned long dest_addr = 0;
 	unsigned long flags;
+	struct scatterlist *cur_dest_sgl;
+	struct scatterlist *cur_src_sgl;
 
 	local_irq_save(flags);
-
+	cur_dest_sgl = orig_sgl;
+	cur_src_sgl = bounce_sgl;
 	for (i = 0; i < orig_sgl_count; i++) {
-		dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
+		dest_addr = (unsigned long)
+				kmap_atomic(sg_page(cur_dest_sgl)) +
+				cur_dest_sgl->offset;
 		dest = dest_addr;
 		destlen = orig_sgl[i].length;
+		destlen = cur_dest_sgl->length;
 
 		if (bounce_addr == 0)
-			bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+			bounce_addr = (unsigned long)kmap_atomic(
+							sg_page(cur_src_sgl));
 
 		while (destlen) {
-			src = bounce_addr + bounce_sgl[j].offset;
-			srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
+			src = bounce_addr + cur_src_sgl->offset;
+			srclen = cur_src_sgl->length - cur_src_sgl->offset;
 
 			copylen = min(srclen, destlen);
 			memcpy((void *)dest, (void *)src, copylen);
 
 			total_copied += copylen;
-			bounce_sgl[j].offset += copylen;
+			cur_src_sgl->offset += copylen;
 			destlen -= copylen;
 			dest += copylen;
 
-			if (bounce_sgl[j].offset == bounce_sgl[j].length) {
+			if (cur_src_sgl->offset == cur_src_sgl->length) {
 				/* full */
-				sg_kunmap_atomic(bounce_addr);
+				kunmap_atomic((void *)bounce_addr);
 				j++;
 
 				/*
@@ -692,21 +686,27 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 					/*
 					 * We are done; cleanup and return.
 					 */
-					sg_kunmap_atomic(dest_addr - orig_sgl[i].offset);
+					kunmap_atomic((void *)(dest_addr -
+						cur_dest_sgl->offset));
 					local_irq_restore(flags);
 					return total_copied;
 				}
 
 				/* if we need to use another bounce buffer */
-				if (destlen || i != orig_sgl_count - 1)
-					bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+				if (destlen || i != orig_sgl_count - 1) {
+					cur_src_sgl = sg_next(cur_src_sgl);
+					bounce_addr = (unsigned long)
+							kmap_atomic(
+							sg_page(cur_src_sgl));
+				}
 			} else if (destlen == 0 && i == orig_sgl_count - 1) {
 				/* unmap the last bounce that is < PAGE_SIZE */
-				sg_kunmap_atomic(bounce_addr);
+				kunmap_atomic((void *)bounce_addr);
 			}
 		}
 
-		sg_kunmap_atomic(dest_addr - orig_sgl[i].offset);
+		kunmap_atomic((void *)(dest_addr - cur_dest_sgl->offset));
+		cur_dest_sgl = sg_next(cur_dest_sgl);
 	}
 
 	local_irq_restore(flags);
@@ -727,48 +727,61 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 	unsigned long bounce_addr = 0;
 	unsigned long src_addr = 0;
 	unsigned long flags;
+	struct scatterlist *cur_src_sgl;
+	struct scatterlist *cur_dest_sgl;
 
 	local_irq_save(flags);
 
+	cur_src_sgl = orig_sgl;
+	cur_dest_sgl = bounce_sgl;
+
 	for (i = 0; i < orig_sgl_count; i++) {
-		src_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
+		src_addr = (unsigned long)
+				kmap_atomic(sg_page(cur_src_sgl)) +
+				cur_src_sgl->offset;
 		src = src_addr;
-		srclen = orig_sgl[i].length;
+		srclen = cur_src_sgl->length;
 
 		if (bounce_addr == 0)
-			bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+			bounce_addr = (unsigned long)
+					kmap_atomic(sg_page(cur_dest_sgl));
 
 		while (srclen) {
 			/* assume bounce offset always == 0 */
-			dest = bounce_addr + bounce_sgl[j].length;
-			destlen = PAGE_SIZE - bounce_sgl[j].length;
+			dest = bounce_addr + cur_dest_sgl->length;
+			destlen = PAGE_SIZE - cur_dest_sgl->length;
 
 			copylen = min(srclen, destlen);
 			memcpy((void *)dest, (void *)src, copylen);
 
 			total_copied += copylen;
-			bounce_sgl[j].length += copylen;
+			cur_dest_sgl->length += copylen;
 			srclen -= copylen;
 			src += copylen;
 
-			if (bounce_sgl[j].length == PAGE_SIZE) {
+			if (cur_dest_sgl->length == PAGE_SIZE) {
 				/* full..move to next entry */
-				sg_kunmap_atomic(bounce_addr);
+				kunmap_atomic((void *)bounce_addr);
 				bounce_addr = 0;
 				j++;
 			}
 
 			/* if we need to use another bounce buffer */
-			if (srclen && bounce_addr == 0)
-				bounce_addr = sg_kmap_atomic(bounce_sgl, j);
+			if (srclen && bounce_addr == 0) {
+				cur_dest_sgl = sg_next(cur_dest_sgl);
+				bounce_addr = (unsigned long)
+						kmap_atomic(
+						sg_page(cur_dest_sgl));
+			}
 
 		}
 
-		sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
+		kunmap_atomic((void *)(src_addr - cur_src_sgl->offset));
+		cur_src_sgl = sg_next(cur_src_sgl);
 	}
 
 	if (bounce_addr)
-		sg_kunmap_atomic(bounce_addr);
+		kunmap_atomic((void *)bounce_addr);
 
 	local_irq_restore(flags);
 
@@ -1536,6 +1549,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 	struct scatterlist *sgl;
 	unsigned int sg_count = 0;
 	struct vmscsi_request *vm_srb;
+	struct scatterlist *cur_sgl;
 
 	if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
 		/*
@@ -1617,10 +1631,12 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 		}
 
 		cmd_request->data_buffer.offset = sgl[0].offset;
-
-		for (i = 0; i < sg_count; i++)
+		cur_sgl = sgl;
+		for (i = 0; i < sg_count; i++) {
 			cmd_request->data_buffer.pfn_array[i] =
-				page_to_pfn(sg_page((&sgl[i])));
+				page_to_pfn(sg_page((cur_sgl)));
+			cur_sgl = sg_next(cur_sgl);
+		}
 
 	} else if (scsi_sglist(scmnd)) {
 		cmd_request->data_buffer.offset =
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang

The current code assumes that the scatterlists presented are not chained.
Fix the code to not make this assumption.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/scsi/storvsc_drv.c |   98 +++++++++++++++++++++++++------------------
 1 files changed, 57 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 88f5d79..a599677 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -626,19 +626,6 @@ cleanup:
 	return NULL;
 }
 
-/* Disgusting wrapper functions */
-static inline unsigned long sg_kmap_atomic(struct scatterlist *sgl, int idx)
-{
-	void *addr = kmap_atomic(sg_page(sgl + idx));
-	return (unsigned long)addr;
-}
-
-static inline void sg_kunmap_atomic(unsigned long addr)
-{
-	kunmap_atomic((void *)addr);
-}
-
-
 /* Assume the original sgl has enough room */
 static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 					    struct scatterlist *bounce_sgl,
@@ -653,32 +640,39 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 	unsigned long bounce_addr = 0;
 	unsigned long dest_addr = 0;
 	unsigned long flags;
+	struct scatterlist *cur_dest_sgl;
+	struct scatterlist *cur_src_sgl;
 
 	local_irq_save(flags);
-
+	cur_dest_sgl = orig_sgl;
+	cur_src_sgl = bounce_sgl;
 	for (i = 0; i < orig_sgl_count; i++) {
-		dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
+		dest_addr = (unsigned long)
+				kmap_atomic(sg_page(cur_dest_sgl)) +
+				cur_dest_sgl->offset;
 		dest = dest_addr;
 		destlen = orig_sgl[i].length;
+		destlen = cur_dest_sgl->length;
 
 		if (bounce_addr == 0)
-			bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+			bounce_addr = (unsigned long)kmap_atomic(
+							sg_page(cur_src_sgl));
 
 		while (destlen) {
-			src = bounce_addr + bounce_sgl[j].offset;
-			srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
+			src = bounce_addr + cur_src_sgl->offset;
+			srclen = cur_src_sgl->length - cur_src_sgl->offset;
 
 			copylen = min(srclen, destlen);
 			memcpy((void *)dest, (void *)src, copylen);
 
 			total_copied += copylen;
-			bounce_sgl[j].offset += copylen;
+			cur_src_sgl->offset += copylen;
 			destlen -= copylen;
 			dest += copylen;
 
-			if (bounce_sgl[j].offset == bounce_sgl[j].length) {
+			if (cur_src_sgl->offset == cur_src_sgl->length) {
 				/* full */
-				sg_kunmap_atomic(bounce_addr);
+				kunmap_atomic((void *)bounce_addr);
 				j++;
 
 				/*
@@ -692,21 +686,27 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 					/*
 					 * We are done; cleanup and return.
 					 */
-					sg_kunmap_atomic(dest_addr - orig_sgl[i].offset);
+					kunmap_atomic((void *)(dest_addr -
+						cur_dest_sgl->offset));
 					local_irq_restore(flags);
 					return total_copied;
 				}
 
 				/* if we need to use another bounce buffer */
-				if (destlen || i != orig_sgl_count - 1)
-					bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+				if (destlen || i != orig_sgl_count - 1) {
+					cur_src_sgl = sg_next(cur_src_sgl);
+					bounce_addr = (unsigned long)
+							kmap_atomic(
+							sg_page(cur_src_sgl));
+				}
 			} else if (destlen == 0 && i == orig_sgl_count - 1) {
 				/* unmap the last bounce that is < PAGE_SIZE */
-				sg_kunmap_atomic(bounce_addr);
+				kunmap_atomic((void *)bounce_addr);
 			}
 		}
 
-		sg_kunmap_atomic(dest_addr - orig_sgl[i].offset);
+		kunmap_atomic((void *)(dest_addr - cur_dest_sgl->offset));
+		cur_dest_sgl = sg_next(cur_dest_sgl);
 	}
 
 	local_irq_restore(flags);
@@ -727,48 +727,61 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 	unsigned long bounce_addr = 0;
 	unsigned long src_addr = 0;
 	unsigned long flags;
+	struct scatterlist *cur_src_sgl;
+	struct scatterlist *cur_dest_sgl;
 
 	local_irq_save(flags);
 
+	cur_src_sgl = orig_sgl;
+	cur_dest_sgl = bounce_sgl;
+
 	for (i = 0; i < orig_sgl_count; i++) {
-		src_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
+		src_addr = (unsigned long)
+				kmap_atomic(sg_page(cur_src_sgl)) +
+				cur_src_sgl->offset;
 		src = src_addr;
-		srclen = orig_sgl[i].length;
+		srclen = cur_src_sgl->length;
 
 		if (bounce_addr == 0)
-			bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+			bounce_addr = (unsigned long)
+					kmap_atomic(sg_page(cur_dest_sgl));
 
 		while (srclen) {
 			/* assume bounce offset always == 0 */
-			dest = bounce_addr + bounce_sgl[j].length;
-			destlen = PAGE_SIZE - bounce_sgl[j].length;
+			dest = bounce_addr + cur_dest_sgl->length;
+			destlen = PAGE_SIZE - cur_dest_sgl->length;
 
 			copylen = min(srclen, destlen);
 			memcpy((void *)dest, (void *)src, copylen);
 
 			total_copied += copylen;
-			bounce_sgl[j].length += copylen;
+			cur_dest_sgl->length += copylen;
 			srclen -= copylen;
 			src += copylen;
 
-			if (bounce_sgl[j].length == PAGE_SIZE) {
+			if (cur_dest_sgl->length == PAGE_SIZE) {
 				/* full..move to next entry */
-				sg_kunmap_atomic(bounce_addr);
+				kunmap_atomic((void *)bounce_addr);
 				bounce_addr = 0;
 				j++;
 			}
 
 			/* if we need to use another bounce buffer */
-			if (srclen && bounce_addr == 0)
-				bounce_addr = sg_kmap_atomic(bounce_sgl, j);
+			if (srclen && bounce_addr == 0) {
+				cur_dest_sgl = sg_next(cur_dest_sgl);
+				bounce_addr = (unsigned long)
+						kmap_atomic(
+						sg_page(cur_dest_sgl));
+			}
 
 		}
 
-		sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
+		kunmap_atomic((void *)(src_addr - cur_src_sgl->offset));
+		cur_src_sgl = sg_next(cur_src_sgl);
 	}
 
 	if (bounce_addr)
-		sg_kunmap_atomic(bounce_addr);
+		kunmap_atomic((void *)bounce_addr);
 
 	local_irq_restore(flags);
 
@@ -1536,6 +1549,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 	struct scatterlist *sgl;
 	unsigned int sg_count = 0;
 	struct vmscsi_request *vm_srb;
+	struct scatterlist *cur_sgl;
 
 	if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
 		/*
@@ -1617,10 +1631,12 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 		}
 
 		cmd_request->data_buffer.offset = sgl[0].offset;
-
-		for (i = 0; i < sg_count; i++)
+		cur_sgl = sgl;
+		for (i = 0; i < sg_count; i++) {
 			cmd_request->data_buffer.pfn_array[i] =
-				page_to_pfn(sg_page((&sgl[i])));
+				page_to_pfn(sg_page((cur_sgl)));
+			cur_sgl = sg_next(cur_sgl);
+		}
 
 	} else if (scsi_sglist(scmnd)) {
 		cmd_request->data_buffer.offset =
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH V2 7/7] scsi: storvsc: Set the tablesize based on the information given by the host
  2015-03-23 21:06 ` [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size K. Y. Srinivasan
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  2015-03-23 21:06     ` K. Y. Srinivasan
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

Set the tablesize based on the information given by the host.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
	v2: Rebase the code and enable clustering

 drivers/scsi/storvsc_drv.c |   89 +++++++++++++++++++++++++++++++------------
 1 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index a599677..71871f2 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -351,7 +351,10 @@ struct storvsc_cmd_request {
 	/* Synchronize the request/response if needed */
 	struct completion wait_event;
 
-	struct hv_multipage_buffer data_buffer;
+	struct vmbus_channel_packet_multipage_buffer mpb;
+	struct vmbus_packet_mpb_array *payload;
+	u32 payload_sz;
+
 	struct vstor_packet vstor_packet;
 };
 
@@ -1133,10 +1136,14 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
 					 sense_hdr.ascq);
 
 	scsi_set_resid(scmnd,
-		cmd_request->data_buffer.len -
+		cmd_request->payload->range.len -
 		vm_srb->data_transfer_length);
 
 	scmnd->scsi_done(scmnd);
+
+	if (cmd_request->payload_sz >
+		sizeof(struct vmbus_channel_packet_multipage_buffer))
+		kfree(cmd_request->payload);
 }
 
 static void storvsc_on_io_completion(struct hv_device *device,
@@ -1338,7 +1345,7 @@ static int storvsc_dev_remove(struct hv_device *device)
 }
 
 static int storvsc_do_io(struct hv_device *device,
-			      struct storvsc_cmd_request *request)
+			 struct storvsc_cmd_request *request)
 {
 	struct storvsc_device *stor_device;
 	struct vstor_packet *vstor_packet;
@@ -1370,13 +1377,14 @@ static int storvsc_do_io(struct hv_device *device,
 
 
 	vstor_packet->vm_srb.data_transfer_length =
-	request->data_buffer.len;
+	request->payload->range.len;
 
 	vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
 
-	if (request->data_buffer.len) {
-		ret = vmbus_sendpacket_multipagebuffer(outgoing_channel,
-				&request->data_buffer,
+	if (request->payload->range.len) {
+
+		ret = vmbus_sendpacket_mpb_desc(outgoing_channel,
+				request->payload, request->payload_sz,
 				vstor_packet,
 				(sizeof(struct vstor_packet) -
 				vmscsi_size_delta),
@@ -1550,6 +1558,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 	unsigned int sg_count = 0;
 	struct vmscsi_request *vm_srb;
 	struct scatterlist *cur_sgl;
+	struct vmbus_packet_mpb_array  *payload;
+	u32 payload_sz;
+	u32 pfn_cnt;
+	u32 length;
 
 	if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
 		/*
@@ -1603,48 +1615,72 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 
 	memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length);
 
-	cmd_request->data_buffer.len = scsi_bufflen(scmnd);
-	if (scsi_sg_count(scmnd)) {
-		sgl = (struct scatterlist *)scsi_sglist(scmnd);
-		sg_count = scsi_sg_count(scmnd);
+	sgl = (struct scatterlist *)scsi_sglist(scmnd);
+	sg_count = scsi_sg_count(scmnd);
 
+	length = scsi_bufflen(scmnd);
+	payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb;
+	payload_sz = sizeof(cmd_request->mpb);
+
+	if (sg_count) {
 		/* check if we need to bounce the sgl */
 		if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
 			cmd_request->bounce_sgl =
-				create_bounce_buffer(sgl, scsi_sg_count(scmnd),
-						     scsi_bufflen(scmnd),
+				create_bounce_buffer(sgl, sg_count,
+						     length,
 						     vm_srb->data_in);
 			if (!cmd_request->bounce_sgl)
 				return SCSI_MLQUEUE_HOST_BUSY;
 
 			cmd_request->bounce_sgl_count =
-				ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >>
-					PAGE_SHIFT;
+				ALIGN(length, PAGE_SIZE) >> PAGE_SHIFT;
 
 			if (vm_srb->data_in == WRITE_TYPE)
 				copy_to_bounce_buffer(sgl,
-					cmd_request->bounce_sgl,
-					scsi_sg_count(scmnd));
+					cmd_request->bounce_sgl, sg_count);
 
 			sgl = cmd_request->bounce_sgl;
 			sg_count = cmd_request->bounce_sgl_count;
 		}
 
-		cmd_request->data_buffer.offset = sgl[0].offset;
+		pfn_cnt = DIV_ROUND_UP(sgl[0].offset + length, PAGE_SIZE);
+
+		if (pfn_cnt > MAX_PAGE_BUFFER_COUNT) {
+
+			payload_sz = (pfn_cnt * sizeof(void *) +
+				      sizeof(struct vmbus_packet_mpb_array));
+			payload = kmalloc(payload_sz, GFP_ATOMIC);
+			if (!payload) {
+				if (cmd_request->bounce_sgl_count)
+					destroy_bounce_buffer(
+					cmd_request->bounce_sgl,
+					cmd_request->bounce_sgl_count);
+
+					return SCSI_MLQUEUE_DEVICE_BUSY;
+			}
+		}
+
+		payload->range.len = length;
+		payload->range.offset = sgl[0].offset;
+
 		cur_sgl = sgl;
 		for (i = 0; i < sg_count; i++) {
-			cmd_request->data_buffer.pfn_array[i] =
+			payload->range.pfn_array[i] =
 				page_to_pfn(sg_page((cur_sgl)));
 			cur_sgl = sg_next(cur_sgl);
 		}
 
 	} else if (scsi_sglist(scmnd)) {
-		cmd_request->data_buffer.offset =
+		payload->range.len = length;
+		payload->range.offset =
 			virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1);
-		cmd_request->data_buffer.pfn_array[0] =
+		payload->range.pfn_array[0] =
 			virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT;
 	}
 
+	cmd_request->payload = payload;
+	cmd_request->payload_sz = payload_sz;
+
 	/* Invokes the vsc to start an IO */
 	ret = storvsc_do_io(dev, cmd_request);
 
@@ -1673,10 +1709,7 @@ static struct scsi_host_template scsi_driver = {
 	.slave_configure =	storvsc_device_configure,
 	.cmd_per_lun =		255,
 	.this_id =		-1,
-	/* no use setting to 0 since ll_blk_rw reset it to 1 */
-	/* currently 32 */
-	.sg_tablesize =		MAX_MULTIPAGE_BUFFER_COUNT,
-	.use_clustering =	DISABLE_CLUSTERING,
+	.use_clustering =	ENABLE_CLUSTERING,
 	/* Make sure we dont get a sg segment crosses a page boundary */
 	.dma_boundary =		PAGE_SIZE-1,
 	.no_write_same =	1,
@@ -1813,6 +1846,12 @@ static int storvsc_probe(struct hv_device *device,
 	/* max cmd length */
 	host->max_cmd_len = STORVSC_MAX_CMD_LEN;
 
+	/*
+	 * set the table size based on the info we got
+	 * from the host.
+	 */
+	host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT);
+
 	/* Register the HBA and start the scsi bus scan */
 	ret = scsi_add_host(host, &device->device);
 	if (ret != 0)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH V2 7/7] scsi: storvsc: Set the tablesize based on the information given by the host
@ 2015-03-23 21:06     ` K. Y. Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: K. Y. Srinivasan @ 2015-03-23 21:06 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, ohering, jbottomley, hch,
	linux-scsi, apw, vkuznets, jasowang

Set the tablesize based on the information given by the host.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
---
	v2: Rebase the code and enable clustering

 drivers/scsi/storvsc_drv.c |   89 +++++++++++++++++++++++++++++++------------
 1 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index a599677..71871f2 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -351,7 +351,10 @@ struct storvsc_cmd_request {
 	/* Synchronize the request/response if needed */
 	struct completion wait_event;
 
-	struct hv_multipage_buffer data_buffer;
+	struct vmbus_channel_packet_multipage_buffer mpb;
+	struct vmbus_packet_mpb_array *payload;
+	u32 payload_sz;
+
 	struct vstor_packet vstor_packet;
 };
 
@@ -1133,10 +1136,14 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
 					 sense_hdr.ascq);
 
 	scsi_set_resid(scmnd,
-		cmd_request->data_buffer.len -
+		cmd_request->payload->range.len -
 		vm_srb->data_transfer_length);
 
 	scmnd->scsi_done(scmnd);
+
+	if (cmd_request->payload_sz >
+		sizeof(struct vmbus_channel_packet_multipage_buffer))
+		kfree(cmd_request->payload);
 }
 
 static void storvsc_on_io_completion(struct hv_device *device,
@@ -1338,7 +1345,7 @@ static int storvsc_dev_remove(struct hv_device *device)
 }
 
 static int storvsc_do_io(struct hv_device *device,
-			      struct storvsc_cmd_request *request)
+			 struct storvsc_cmd_request *request)
 {
 	struct storvsc_device *stor_device;
 	struct vstor_packet *vstor_packet;
@@ -1370,13 +1377,14 @@ static int storvsc_do_io(struct hv_device *device,
 
 
 	vstor_packet->vm_srb.data_transfer_length =
-	request->data_buffer.len;
+	request->payload->range.len;
 
 	vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
 
-	if (request->data_buffer.len) {
-		ret = vmbus_sendpacket_multipagebuffer(outgoing_channel,
-				&request->data_buffer,
+	if (request->payload->range.len) {
+
+		ret = vmbus_sendpacket_mpb_desc(outgoing_channel,
+				request->payload, request->payload_sz,
 				vstor_packet,
 				(sizeof(struct vstor_packet) -
 				vmscsi_size_delta),
@@ -1550,6 +1558,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 	unsigned int sg_count = 0;
 	struct vmscsi_request *vm_srb;
 	struct scatterlist *cur_sgl;
+	struct vmbus_packet_mpb_array  *payload;
+	u32 payload_sz;
+	u32 pfn_cnt;
+	u32 length;
 
 	if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
 		/*
@@ -1603,48 +1615,72 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 
 	memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length);
 
-	cmd_request->data_buffer.len = scsi_bufflen(scmnd);
-	if (scsi_sg_count(scmnd)) {
-		sgl = (struct scatterlist *)scsi_sglist(scmnd);
-		sg_count = scsi_sg_count(scmnd);
+	sgl = (struct scatterlist *)scsi_sglist(scmnd);
+	sg_count = scsi_sg_count(scmnd);
 
+	length = scsi_bufflen(scmnd);
+	payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb;
+	payload_sz = sizeof(cmd_request->mpb);
+
+	if (sg_count) {
 		/* check if we need to bounce the sgl */
 		if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
 			cmd_request->bounce_sgl =
-				create_bounce_buffer(sgl, scsi_sg_count(scmnd),
-						     scsi_bufflen(scmnd),
+				create_bounce_buffer(sgl, sg_count,
+						     length,
 						     vm_srb->data_in);
 			if (!cmd_request->bounce_sgl)
 				return SCSI_MLQUEUE_HOST_BUSY;
 
 			cmd_request->bounce_sgl_count =
-				ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >>
-					PAGE_SHIFT;
+				ALIGN(length, PAGE_SIZE) >> PAGE_SHIFT;
 
 			if (vm_srb->data_in == WRITE_TYPE)
 				copy_to_bounce_buffer(sgl,
-					cmd_request->bounce_sgl,
-					scsi_sg_count(scmnd));
+					cmd_request->bounce_sgl, sg_count);
 
 			sgl = cmd_request->bounce_sgl;
 			sg_count = cmd_request->bounce_sgl_count;
 		}
 
-		cmd_request->data_buffer.offset = sgl[0].offset;
+		pfn_cnt = DIV_ROUND_UP(sgl[0].offset + length, PAGE_SIZE);
+
+		if (pfn_cnt > MAX_PAGE_BUFFER_COUNT) {
+
+			payload_sz = (pfn_cnt * sizeof(void *) +
+				      sizeof(struct vmbus_packet_mpb_array));
+			payload = kmalloc(payload_sz, GFP_ATOMIC);
+			if (!payload) {
+				if (cmd_request->bounce_sgl_count)
+					destroy_bounce_buffer(
+					cmd_request->bounce_sgl,
+					cmd_request->bounce_sgl_count);
+
+					return SCSI_MLQUEUE_DEVICE_BUSY;
+			}
+		}
+
+		payload->range.len = length;
+		payload->range.offset = sgl[0].offset;
+
 		cur_sgl = sgl;
 		for (i = 0; i < sg_count; i++) {
-			cmd_request->data_buffer.pfn_array[i] =
+			payload->range.pfn_array[i] =
 				page_to_pfn(sg_page((cur_sgl)));
 			cur_sgl = sg_next(cur_sgl);
 		}
 
 	} else if (scsi_sglist(scmnd)) {
-		cmd_request->data_buffer.offset =
+		payload->range.len = length;
+		payload->range.offset =
 			virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1);
-		cmd_request->data_buffer.pfn_array[0] =
+		payload->range.pfn_array[0] =
 			virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT;
 	}
 
+	cmd_request->payload = payload;
+	cmd_request->payload_sz = payload_sz;
+
 	/* Invokes the vsc to start an IO */
 	ret = storvsc_do_io(dev, cmd_request);
 
@@ -1673,10 +1709,7 @@ static struct scsi_host_template scsi_driver = {
 	.slave_configure =	storvsc_device_configure,
 	.cmd_per_lun =		255,
 	.this_id =		-1,
-	/* no use setting to 0 since ll_blk_rw reset it to 1 */
-	/* currently 32 */
-	.sg_tablesize =		MAX_MULTIPAGE_BUFFER_COUNT,
-	.use_clustering =	DISABLE_CLUSTERING,
+	.use_clustering =	ENABLE_CLUSTERING,
 	/* Make sure we dont get a sg segment crosses a page boundary */
 	.dma_boundary =		PAGE_SIZE-1,
 	.no_write_same =	1,
@@ -1813,6 +1846,12 @@ static int storvsc_probe(struct hv_device *device,
 	/* max cmd length */
 	host->max_cmd_len = STORVSC_MAX_CMD_LEN;
 
+	/*
+	 * set the table size based on the info we got
+	 * from the host.
+	 */
+	host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT);
+
 	/* Register the HBA and start the scsi bus scan */
 	ret = scsi_add_host(host, &device->device);
 	if (ret != 0)
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
  2015-03-23 21:06     ` K. Y. Srinivasan
  (?)
@ 2015-03-24  0:23     ` Venkatesh Srinivas
  2015-03-24  1:49         ` KY Srinivasan
  -1 siblings, 1 reply; 22+ messages in thread
From: Venkatesh Srinivas @ 2015-03-24  0:23 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, Linux Kernel Developers List, devel, ohering,
	James E.J. Bottomley, Christoph Hellwig, linux-scsi, apw,
	vkuznets, jasowang

On Mon, Mar 23, 2015 at 2:06 PM, K. Y. Srinivasan <kys@microsoft.com> wrote:
> Size the queue depth based on the ringbuffer size. Also accomodate for the
> fact that we could have multiple channels (ringbuffers) per adaptor.
>
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> Reviewed-by: Long Li <longli@microsoft.com>
> ---
>  drivers/scsi/storvsc_drv.c |   27 ++++++++++++++++-----------
>  1 files changed, 16 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
> index 27fe850..5a12897 100644
> --- a/drivers/scsi/storvsc_drv.c
> +++ b/drivers/scsi/storvsc_drv.c
> @@ -309,10 +309,15 @@ enum storvsc_request_type {
>   */
>
>  static int storvsc_ringbuffer_size = (256 * PAGE_SIZE);
> +static u32 max_outstanding_req_per_channel;
> +
> +static int storvsc_vcpus_per_sub_channel = 4;
>
>  module_param(storvsc_ringbuffer_size, int, S_IRUGO);
>  MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
>
> +module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO);
> +MODULE_PARM_DESC(vcpus_per_sub_channel, "Ratio of VCPUs to subchannels");
>  /*
>   * Timeout in seconds for all devices managed by this driver.
>   */
> @@ -320,7 +325,6 @@ static int storvsc_timeout = 180;
>
>  static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
>
> -#define STORVSC_MAX_IO_REQUESTS                                200
>
>  static void storvsc_on_channel_callback(void *context);
>
> @@ -1376,7 +1380,6 @@ static int storvsc_do_io(struct hv_device *device,
>
>  static int storvsc_device_configure(struct scsi_device *sdevice)
>  {
> -       scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS);
>
>         blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
>
> @@ -1646,7 +1649,6 @@ static struct scsi_host_template scsi_driver = {
>         .eh_timed_out =         storvsc_eh_timed_out,
>         .slave_configure =      storvsc_device_configure,
>         .cmd_per_lun =          255,
> -       .can_queue =            STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
>         .this_id =              -1,
>         /* no use setting to 0 since ll_blk_rw reset it to 1 */
>         /* currently 32 */
> @@ -1686,6 +1688,7 @@ static int storvsc_probe(struct hv_device *device,
>                         const struct hv_vmbus_device_id *dev_id)
>  {
>         int ret;
> +       int num_cpus = num_online_cpus();
>         struct Scsi_Host *host;
>         struct hv_host_device *host_dev;
>         bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
> @@ -1694,6 +1697,7 @@ static int storvsc_probe(struct hv_device *device,
>         int max_luns_per_target;
>         int max_targets;
>         int max_channels;
> +       int max_sub_channels = 0;
>
>         /*
>          * Based on the windows host we are running on,
> @@ -1719,12 +1723,18 @@ static int storvsc_probe(struct hv_device *device,
>                 max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET;
>                 max_targets = STORVSC_MAX_TARGETS;
>                 max_channels = STORVSC_MAX_CHANNELS;
> +               /*
> +                * On Windows8 and above, we support sub-channels for storage.
> +                * The number of sub-channels offerred is based on the number of
> +                * VCPUs in the guest.
> +                */
> +               max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel);
>                 break;
>         }
>
> -       if (dev_id->driver_data == SFC_GUID)
> -               scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS *
> -                                        STORVSC_FC_MAX_TARGETS);
> +       scsi_driver.can_queue = (max_outstanding_req_per_channel *
> +                                max_sub_channels + 1);
> +

If num_online_cpus() returned 1 - 3, can_queue will be set to 1 I
think. Is that desired?

>         host = scsi_host_alloc(&scsi_driver,
>                                sizeof(struct hv_host_device));
>         if (!host)
> @@ -1837,7 +1847,6 @@ static struct hv_driver storvsc_drv = {
>
>  static int __init storvsc_drv_init(void)
>  {
> -       u32 max_outstanding_req_per_channel;
>
>         /*
>          * Divide the ring buffer data size (which is 1 page less
> @@ -1852,10 +1861,6 @@ static int __init storvsc_drv_init(void)
>                 vmscsi_size_delta,
>                 sizeof(u64)));
>
> -       if (max_outstanding_req_per_channel <
> -           STORVSC_MAX_IO_REQUESTS)
> -               return -EINVAL;
> -
>         return vmbus_driver_register(&storvsc_drv);
>  }

-- vs;

^ permalink raw reply	[flat|nested] 22+ messages in thread

* RE: [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
  2015-03-24  0:23     ` Venkatesh Srinivas
@ 2015-03-24  1:49         ` KY Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: KY Srinivasan @ 2015-03-24  1:49 UTC (permalink / raw)
  To: Venkatesh Srinivas
  Cc: gregkh, Linux Kernel Developers List, devel, ohering,
	James E.J. Bottomley, Christoph Hellwig, linux-scsi, apw,
	vkuznets, jasowang

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 5057 bytes --]



> -----Original Message-----
> From: Venkatesh Srinivas [mailto:venkateshs@google.com]
> Sent: Monday, March 23, 2015 5:23 PM
> To: KY Srinivasan
> Cc: gregkh@linuxfoundation.org; Linux Kernel Developers List;
> devel@linuxdriverproject.org; ohering@suse.com; James E.J. Bottomley;
> Christoph Hellwig; linux-scsi@vger.kernel.org; apw@canonical.com;
> vkuznets@redhat.com; jasowang@redhat.com
> Subject: Re: [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based
> on the ringbuffer size
> 
> On Mon, Mar 23, 2015 at 2:06 PM, K. Y. Srinivasan <kys@microsoft.com>
> wrote:
> > Size the queue depth based on the ringbuffer size. Also accomodate for
> the
> > fact that we could have multiple channels (ringbuffers) per adaptor.
> >
> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> > Reviewed-by: Long Li <longli@microsoft.com>
> > ---
> >  drivers/scsi/storvsc_drv.c |   27 ++++++++++++++++-----------
> >  1 files changed, 16 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
> > index 27fe850..5a12897 100644
> > --- a/drivers/scsi/storvsc_drv.c
> > +++ b/drivers/scsi/storvsc_drv.c
> > @@ -309,10 +309,15 @@ enum storvsc_request_type {
> >   */
> >
> >  static int storvsc_ringbuffer_size = (256 * PAGE_SIZE);
> > +static u32 max_outstanding_req_per_channel;
> > +
> > +static int storvsc_vcpus_per_sub_channel = 4;
> >
> >  module_param(storvsc_ringbuffer_size, int, S_IRUGO);
> >  MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size
> (bytes)");
> >
> > +module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO);
> > +MODULE_PARM_DESC(vcpus_per_sub_channel, "Ratio of VCPUs to
> subchannels");
> >  /*
> >   * Timeout in seconds for all devices managed by this driver.
> >   */
> > @@ -320,7 +325,6 @@ static int storvsc_timeout = 180;
> >
> >  static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
> >
> > -#define STORVSC_MAX_IO_REQUESTS                                200
> >
> >  static void storvsc_on_channel_callback(void *context);
> >
> > @@ -1376,7 +1380,6 @@ static int storvsc_do_io(struct hv_device *device,
> >
> >  static int storvsc_device_configure(struct scsi_device *sdevice)
> >  {
> > -       scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS);
> >
> >         blk_queue_max_segment_size(sdevice->request_queue,
> PAGE_SIZE);
> >
> > @@ -1646,7 +1649,6 @@ static struct scsi_host_template scsi_driver = {
> >         .eh_timed_out =         storvsc_eh_timed_out,
> >         .slave_configure =      storvsc_device_configure,
> >         .cmd_per_lun =          255,
> > -       .can_queue =
> STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
> >         .this_id =              -1,
> >         /* no use setting to 0 since ll_blk_rw reset it to 1 */
> >         /* currently 32 */
> > @@ -1686,6 +1688,7 @@ static int storvsc_probe(struct hv_device *device,
> >                         const struct hv_vmbus_device_id *dev_id)
> >  {
> >         int ret;
> > +       int num_cpus = num_online_cpus();
> >         struct Scsi_Host *host;
> >         struct hv_host_device *host_dev;
> >         bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
> > @@ -1694,6 +1697,7 @@ static int storvsc_probe(struct hv_device *device,
> >         int max_luns_per_target;
> >         int max_targets;
> >         int max_channels;
> > +       int max_sub_channels = 0;
> >
> >         /*
> >          * Based on the windows host we are running on,
> > @@ -1719,12 +1723,18 @@ static int storvsc_probe(struct hv_device
> *device,
> >                 max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET;
> >                 max_targets = STORVSC_MAX_TARGETS;
> >                 max_channels = STORVSC_MAX_CHANNELS;
> > +               /*
> > +                * On Windows8 and above, we support sub-channels for storage.
> > +                * The number of sub-channels offerred is based on the number
> of
> > +                * VCPUs in the guest.
> > +                */
> > +               max_sub_channels = (num_cpus /
> storvsc_vcpus_per_sub_channel);
> >                 break;
> >         }
> >
> > -       if (dev_id->driver_data == SFC_GUID)
> > -               scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS *
> > -                                        STORVSC_FC_MAX_TARGETS);
> > +       scsi_driver.can_queue = (max_outstanding_req_per_channel *
> > +                                max_sub_channels + 1);
> > +
> 
> If num_online_cpus() returned 1 - 3, can_queue will be set to 1 I
> think. Is that desired?

can_ queue will be set  max_outstanding_req_per_channel in
this case. That is what is expected. We will always have the primary channel;
Additionally, if the guest has more than 4 VCPUs, the host will offer
Additional subchannels for each 4 VCPus in the guest. So for less than
4 VCPus in the guest, we will only have the primary channel.


Regards,

K. Y
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 22+ messages in thread

* RE: [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
@ 2015-03-24  1:49         ` KY Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: KY Srinivasan @ 2015-03-24  1:49 UTC (permalink / raw)
  To: Venkatesh Srinivas
  Cc: gregkh, Linux Kernel Developers List, devel, ohering,
	James E.J. Bottomley, Christoph Hellwig, linux-scsi, apw,
	vkuznets, jasowang



> -----Original Message-----
> From: Venkatesh Srinivas [mailto:venkateshs@google.com]
> Sent: Monday, March 23, 2015 5:23 PM
> To: KY Srinivasan
> Cc: gregkh@linuxfoundation.org; Linux Kernel Developers List;
> devel@linuxdriverproject.org; ohering@suse.com; James E.J. Bottomley;
> Christoph Hellwig; linux-scsi@vger.kernel.org; apw@canonical.com;
> vkuznets@redhat.com; jasowang@redhat.com
> Subject: Re: [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based
> on the ringbuffer size
> 
> On Mon, Mar 23, 2015 at 2:06 PM, K. Y. Srinivasan <kys@microsoft.com>
> wrote:
> > Size the queue depth based on the ringbuffer size. Also accomodate for
> the
> > fact that we could have multiple channels (ringbuffers) per adaptor.
> >
> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> > Reviewed-by: Long Li <longli@microsoft.com>
> > ---
> >  drivers/scsi/storvsc_drv.c |   27 ++++++++++++++++-----------
> >  1 files changed, 16 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
> > index 27fe850..5a12897 100644
> > --- a/drivers/scsi/storvsc_drv.c
> > +++ b/drivers/scsi/storvsc_drv.c
> > @@ -309,10 +309,15 @@ enum storvsc_request_type {
> >   */
> >
> >  static int storvsc_ringbuffer_size = (256 * PAGE_SIZE);
> > +static u32 max_outstanding_req_per_channel;
> > +
> > +static int storvsc_vcpus_per_sub_channel = 4;
> >
> >  module_param(storvsc_ringbuffer_size, int, S_IRUGO);
> >  MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size
> (bytes)");
> >
> > +module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO);
> > +MODULE_PARM_DESC(vcpus_per_sub_channel, "Ratio of VCPUs to
> subchannels");
> >  /*
> >   * Timeout in seconds for all devices managed by this driver.
> >   */
> > @@ -320,7 +325,6 @@ static int storvsc_timeout = 180;
> >
> >  static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
> >
> > -#define STORVSC_MAX_IO_REQUESTS                                200
> >
> >  static void storvsc_on_channel_callback(void *context);
> >
> > @@ -1376,7 +1380,6 @@ static int storvsc_do_io(struct hv_device *device,
> >
> >  static int storvsc_device_configure(struct scsi_device *sdevice)
> >  {
> > -       scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS);
> >
> >         blk_queue_max_segment_size(sdevice->request_queue,
> PAGE_SIZE);
> >
> > @@ -1646,7 +1649,6 @@ static struct scsi_host_template scsi_driver = {
> >         .eh_timed_out =         storvsc_eh_timed_out,
> >         .slave_configure =      storvsc_device_configure,
> >         .cmd_per_lun =          255,
> > -       .can_queue =
> STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
> >         .this_id =              -1,
> >         /* no use setting to 0 since ll_blk_rw reset it to 1 */
> >         /* currently 32 */
> > @@ -1686,6 +1688,7 @@ static int storvsc_probe(struct hv_device *device,
> >                         const struct hv_vmbus_device_id *dev_id)
> >  {
> >         int ret;
> > +       int num_cpus = num_online_cpus();
> >         struct Scsi_Host *host;
> >         struct hv_host_device *host_dev;
> >         bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
> > @@ -1694,6 +1697,7 @@ static int storvsc_probe(struct hv_device *device,
> >         int max_luns_per_target;
> >         int max_targets;
> >         int max_channels;
> > +       int max_sub_channels = 0;
> >
> >         /*
> >          * Based on the windows host we are running on,
> > @@ -1719,12 +1723,18 @@ static int storvsc_probe(struct hv_device
> *device,
> >                 max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET;
> >                 max_targets = STORVSC_MAX_TARGETS;
> >                 max_channels = STORVSC_MAX_CHANNELS;
> > +               /*
> > +                * On Windows8 and above, we support sub-channels for storage.
> > +                * The number of sub-channels offerred is based on the number
> of
> > +                * VCPUs in the guest.
> > +                */
> > +               max_sub_channels = (num_cpus /
> storvsc_vcpus_per_sub_channel);
> >                 break;
> >         }
> >
> > -       if (dev_id->driver_data == SFC_GUID)
> > -               scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS *
> > -                                        STORVSC_FC_MAX_TARGETS);
> > +       scsi_driver.can_queue = (max_outstanding_req_per_channel *
> > +                                max_sub_channels + 1);
> > +
> 
> If num_online_cpus() returned 1 - 3, can_queue will be set to 1 I
> think. Is that desired?

can_ queue will be set  max_outstanding_req_per_channel in
this case. That is what is expected. We will always have the primary channel;
Additionally, if the guest has more than 4 VCPUs, the host will offer
Additional subchannels for each 4 VCPus in the guest. So for less than
4 VCPus in the guest, we will only have the primary channel.


Regards,

K. Y

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained
  2015-03-23 21:06     ` K. Y. Srinivasan
  (?)
  (?)
@ 2015-03-24  8:56     ` Olaf Hering
  2015-03-24 16:29         ` KY Srinivasan
  -1 siblings, 1 reply; 22+ messages in thread
From: Olaf Hering @ 2015-03-24  8:56 UTC (permalink / raw)
  To: K. Y. Srinivasan
  Cc: gregkh, linux-kernel, devel, jbottomley, hch, linux-scsi, apw,
	vkuznets, jasowang

On Mon, Mar 23, K. Y. Srinivasan wrote:

> @@ -653,32 +640,39 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
>  	unsigned long bounce_addr = 0;
>  	unsigned long dest_addr = 0;
>  	unsigned long flags;
> +	struct scatterlist *cur_dest_sgl;
> +	struct scatterlist *cur_src_sgl;
>  
>  	local_irq_save(flags);
> -
> +	cur_dest_sgl = orig_sgl;
> +	cur_src_sgl = bounce_sgl;
>  	for (i = 0; i < orig_sgl_count; i++) {
> -		dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
> +		dest_addr = (unsigned long)
> +				kmap_atomic(sg_page(cur_dest_sgl)) +
> +				cur_dest_sgl->offset;
>  		dest = dest_addr;
>  		destlen = orig_sgl[i].length;
> +		destlen = cur_dest_sgl->length;

Double assignment.

Olaf

^ permalink raw reply	[flat|nested] 22+ messages in thread

* RE: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained
  2015-03-24  8:56     ` Olaf Hering
@ 2015-03-24 16:29         ` KY Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: KY Srinivasan @ 2015-03-24 16:29 UTC (permalink / raw)
  To: Olaf Hering
  Cc: gregkh, linux-kernel, devel, jbottomley, hch, linux-scsi, apw,
	vkuznets, jasowang

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1462 bytes --]



> -----Original Message-----
> From: Olaf Hering [mailto:olaf@aepfle.de]
> Sent: Tuesday, March 24, 2015 1:56 AM
> To: KY Srinivasan
> Cc: gregkh@linuxfoundation.org; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; jbottomley@parallels.com;
> hch@infradead.org; linux-scsi@vger.kernel.org; apw@canonical.com;
> vkuznets@redhat.com; jasowang@redhat.com
> Subject: Re: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not
> chained
> 
> On Mon, Mar 23, K. Y. Srinivasan wrote:
> 
> > @@ -653,32 +640,39 @@ static unsigned int
> copy_from_bounce_buffer(struct scatterlist *orig_sgl,
> >  	unsigned long bounce_addr = 0;
> >  	unsigned long dest_addr = 0;
> >  	unsigned long flags;
> > +	struct scatterlist *cur_dest_sgl;
> > +	struct scatterlist *cur_src_sgl;
> >
> >  	local_irq_save(flags);
> > -
> > +	cur_dest_sgl = orig_sgl;
> > +	cur_src_sgl = bounce_sgl;
> >  	for (i = 0; i < orig_sgl_count; i++) {
> > -		dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
> > +		dest_addr = (unsigned long)
> > +				kmap_atomic(sg_page(cur_dest_sgl)) +
> > +				cur_dest_sgl->offset;
> >  		dest = dest_addr;
> >  		destlen = orig_sgl[i].length;
> > +		destlen = cur_dest_sgl->length;
> 
> Double assignment.

Thanks Olaf; I will fix this and resubmit.

K. Y

> 
> Olaf
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 22+ messages in thread

* RE: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained
@ 2015-03-24 16:29         ` KY Srinivasan
  0 siblings, 0 replies; 22+ messages in thread
From: KY Srinivasan @ 2015-03-24 16:29 UTC (permalink / raw)
  To: Olaf Hering
  Cc: linux-scsi, gregkh, jasowang, linux-kernel, jbottomley, hch, apw, devel



> -----Original Message-----
> From: Olaf Hering [mailto:olaf@aepfle.de]
> Sent: Tuesday, March 24, 2015 1:56 AM
> To: KY Srinivasan
> Cc: gregkh@linuxfoundation.org; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; jbottomley@parallels.com;
> hch@infradead.org; linux-scsi@vger.kernel.org; apw@canonical.com;
> vkuznets@redhat.com; jasowang@redhat.com
> Subject: Re: [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not
> chained
> 
> On Mon, Mar 23, K. Y. Srinivasan wrote:
> 
> > @@ -653,32 +640,39 @@ static unsigned int
> copy_from_bounce_buffer(struct scatterlist *orig_sgl,
> >  	unsigned long bounce_addr = 0;
> >  	unsigned long dest_addr = 0;
> >  	unsigned long flags;
> > +	struct scatterlist *cur_dest_sgl;
> > +	struct scatterlist *cur_src_sgl;
> >
> >  	local_irq_save(flags);
> > -
> > +	cur_dest_sgl = orig_sgl;
> > +	cur_src_sgl = bounce_sgl;
> >  	for (i = 0; i < orig_sgl_count; i++) {
> > -		dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
> > +		dest_addr = (unsigned long)
> > +				kmap_atomic(sg_page(cur_dest_sgl)) +
> > +				cur_dest_sgl->offset;
> >  		dest = dest_addr;
> >  		destlen = orig_sgl[i].length;
> > +		destlen = cur_dest_sgl->length;
> 
> Double assignment.

Thanks Olaf; I will fix this and resubmit.

K. Y

> 
> Olaf

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2015-03-24 16:29 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-23 21:06 [PATCH 0/7] scsi: storvsc: Miscellaneous enhancements and fixes K. Y. Srinivasan
2015-03-23 21:06 ` [PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size K. Y. Srinivasan
2015-03-23 21:06   ` [PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size K. Y. Srinivasan
2015-03-23 21:06     ` K. Y. Srinivasan
2015-03-24  0:23     ` Venkatesh Srinivas
2015-03-24  1:49       ` KY Srinivasan
2015-03-24  1:49         ` KY Srinivasan
2015-03-23 21:06   ` [PATCH RESEND 3/7] scsi: storvsc: Always send on the selected outgoing channel K. Y. Srinivasan
2015-03-23 21:06     ` K. Y. Srinivasan
2015-03-23 21:06   ` [PATCH RESEND 4/7] scsi: storvsc: Retrieve information about the capability of the target K. Y. Srinivasan
2015-03-23 21:06     ` K. Y. Srinivasan
2015-03-23 21:06   ` [PATCH 5/7] scsi: storvsc: Fix a bug in copy_from_bounce_buffer() K. Y. Srinivasan
2015-03-23 21:06     ` K. Y. Srinivasan
2015-03-23 20:52     ` Long Li
2015-03-23 21:06   ` [PATCH 6/7] scsi: storvsc: Don't assume that the scatterlist is not chained K. Y. Srinivasan
2015-03-23 21:06     ` K. Y. Srinivasan
2015-03-23 20:52     ` Long Li
2015-03-24  8:56     ` Olaf Hering
2015-03-24 16:29       ` KY Srinivasan
2015-03-24 16:29         ` KY Srinivasan
2015-03-23 21:06   ` [PATCH V2 7/7] scsi: storvsc: Set the tablesize based on the information given by the host K. Y. Srinivasan
2015-03-23 21:06     ` K. Y. Srinivasan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.