[PATCH 4/6] storvsc: use tagged SRB requests if supported by the device

2016-12-14 Thread kys
From: Long Li 

Properly set SRB flags when hosting device supports tagged queuing.
This patch improves the performance on Fiber Channel disks.

Signed-off-by: Long Li 
Reviewed-by: K. Y. Srinivasan 
Signed-off-by: K. Y. Srinivasan 
Cc: 
---
 drivers/scsi/storvsc_drv.c |9 +
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 63f6b1a..3209387 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -136,6 +136,8 @@ struct hv_fc_wwn_packet {
 #define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F00
 #define SRB_FLAGS_CLASS_DRIVER_RESERVED0xF000
 
+#define SP_UNTAGGED((unsigned char) ~0)
+#define SRB_SIMPLE_TAG_REQUEST 0x20
 
 /*
  * Platform neutral description of a scsi request -
@@ -1549,6 +1551,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *scmnd)
vm_srb->win8_extension.srb_flags |=
SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
 
+   if (scmnd->device->tagged_supported) {
+   vm_srb->win8_extension.srb_flags |=
+   (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE);
+   vm_srb->win8_extension.queue_tag = SP_UNTAGGED;
+   vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST;
+   }
+
/* Build the SRB */
switch (scmnd->sc_data_direction) {
case DMA_TO_DEVICE:
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/6] storvsc: Enable multi-queue support

2016-12-14 Thread kys
From: K. Y. Srinivasan 

Enable multi-q support. We will allocate the outgoing channel using
the following policy:

1. We will make every effort to pick a channel that is in the
   same NUMA node that is initiating the I/O
2. The mapping between the guest CPU and the outgoing channel
   is persistent.

Signed-off-by: K. Y. Srinivasan 
Reviewed-by: Long Li 
---
 drivers/scsi/storvsc_drv.c |  113 ++-
 1 files changed, 110 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 3b1c2f6..63f6b1a 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -458,6 +458,15 @@ struct storvsc_device {
 * Max I/O, the device can support.
 */
u32   max_transfer_bytes;
+   /*
+* Number of sub-channels we will open.
+*/
+   u16 num_sc;
+   struct vmbus_channel **stor_chns;
+   /*
+* Mask of CPUs bound to subchannels.
+*/
+   struct cpumask alloced_cpus;
/* Used for vsc/vsp channel reset process */
struct storvsc_cmd_request init_request;
struct storvsc_cmd_request reset_request;
@@ -635,6 +644,11 @@ static void handle_sc_creation(struct vmbus_channel 
*new_sc)
   (void *),
   sizeof(struct vmstorage_channel_properties),
   storvsc_on_channel_callback, new_sc);
+
+   if (new_sc->state == CHANNEL_OPENED_STATE) {
+   stor_device->stor_chns[new_sc->target_cpu] = new_sc;
+   cpumask_set_cpu(new_sc->target_cpu, _device->alloced_cpus);
+   }
 }
 
 static void  handle_multichannel_storage(struct hv_device *device, int 
max_chns)
@@ -651,6 +665,7 @@ static void  handle_multichannel_storage(struct hv_device 
*device, int max_chns)
if (!stor_device)
return;
 
+   stor_device->num_sc = num_sc;
request = _device->init_request;
vstor_packet = >vstor_packet;
 
@@ -838,6 +853,25 @@ static int storvsc_channel_init(struct hv_device *device, 
bool is_fc)
 * support multi-channel.
 */
max_chns = vstor_packet->storage_channel_properties.max_channel_cnt;
+
+   /*
+* Allocate state to manage the sub-channels.
+* We allocate an array based on the numbers of possible CPUs
+* (Hyper-V does not support cpu online/offline).
+* This Array will be sparseley populated with unique
+* channels - primary + sub-channels.
+* We will however populate all the slots to evenly distribute
+* the load.
+*/
+   stor_device->stor_chns = kzalloc(sizeof(void *) * num_possible_cpus(),
+GFP_KERNEL);
+   if (stor_device->stor_chns == NULL)
+   return -ENOMEM;
+
+   stor_device->stor_chns[device->channel->target_cpu] = device->channel;
+   cpumask_set_cpu(device->channel->target_cpu,
+   _device->alloced_cpus);
+
if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) {
if (vstor_packet->storage_channel_properties.flags &
STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL)
@@ -1198,17 +1232,64 @@ static int storvsc_dev_remove(struct hv_device *device)
/* Close the channel */
vmbus_close(device->channel);
 
+   kfree(stor_device->stor_chns);
kfree(stor_device);
return 0;
 }
 
+static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device,
+   u16 q_num)
+{
+   u16 slot = 0;
+   u16 hash_qnum;
+   struct cpumask alloced_mask;
+   int num_channels, tgt_cpu;
+
+   if (stor_device->num_sc == 0)
+   return stor_device->device->channel;
+
+   /*
+* Our channel array is sparsley populated and we
+* initiated I/O on a processor/hw-q that does not
+* currently have a designated channel. Fix this.
+* The strategy is simple:
+* I. Ensure NUMA locality
+* II. Distribute evenly (best effort)
+* III. Mapping is persistent.
+*/
+
+   cpumask_and(_mask, _device->alloced_cpus,
+   cpumask_of_node(cpu_to_node(q_num)));
+
+   num_channels = cpumask_weight(_mask);
+   if (num_channels == 0)
+   return stor_device->device->channel;
+
+   hash_qnum = q_num;
+   while (hash_qnum >= num_channels)
+   hash_qnum -= num_channels;
+
+   for_each_cpu(tgt_cpu, _mask) {
+   if (slot == hash_qnum)
+   break;
+   slot++;
+   }
+
+   stor_device->stor_chns[q_num] = stor_device->stor_chns[tgt_cpu];
+
+   return stor_device->stor_chns[q_num];
+}
+
+
 static int storvsc_do_io(struct hv_device *device,
-struct storvsc_cmd_request *request)
+ 

[PATCH 2/6] storvsc: Remove the restriction on max segment size

2016-12-14 Thread kys
From: K. Y. Srinivasan 

Remove the artificially imposed restriction on max segment size.

Signed-off-by: K. Y. Srinivasan 
Reviewed-by: Long Li 
---
 drivers/scsi/storvsc_drv.c |2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index ccb2101..3b1c2f6 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1267,8 +1267,6 @@ static int storvsc_do_io(struct hv_device *device,
 static int storvsc_device_configure(struct scsi_device *sdevice)
 {
 
-   blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
-
blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
 
blk_queue_rq_timeout(sdevice->request_queue, (storvsc_timeout * HZ));
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/6] storvsc: properly handle SRB_ERROR when sense message is present

2016-12-14 Thread kys
From: Long Li 

When sense message is present on error, we should pass along to the upper
layer to decide how to deal with the error.
This patch fixes connectivity issues with Fiber Channel devices.

Signed-off-by: Long Li 
Reviewed-by: K. Y. Srinivasan 
Signed-off-by: K. Y. Srinivasan 
Cc: 
---
 drivers/scsi/storvsc_drv.c |7 +++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 3209387..3c92dc2 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -925,6 +925,13 @@ static void storvsc_handle_error(struct vmscsi_request 
*vm_srb,
switch (SRB_STATUS(vm_srb->srb_status)) {
case SRB_STATUS_ERROR:
/*
+* Let upper layer deal with error when
+* sense message is present.
+*/
+
+   if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID)
+   break;
+   /*
 * If there is an error; offline the device since all
 * error recovery strategies would have already been
 * deployed on the host side. However, if the command
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/6] storvsc: Enable tracking of queue depth

2016-12-14 Thread kys
From: K. Y. Srinivasan 

Enable tracking of queue depth.

Signed-off-by: K. Y. Srinivasan 
Reviewed-by: Long Li 
---
 drivers/scsi/storvsc_drv.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 05526b7..ccb2101 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1550,6 +1550,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *scmnd)
/* Make sure we dont get a sg segment crosses a page boundary */
.dma_boundary = PAGE_SIZE-1,
.no_write_same =1,
+   .track_queue_depth =1,
 };
 
 enum {
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/6] storvsc: properly set residual data length on errors

2016-12-14 Thread kys
From: Long Li 

On I/O errors, the Windows driver doesn't set data_transfer_length
on error conditions other than SRB_STATUS_DATA_OVERRUN.
In these cases we need to set data_transfer_length to 0,
indicating there is no data transferred. On SRB_STATUS_DATA_OVERRUN,
data_transfer_length is set by the Windows driver to the actual data 
transferred.

Reported-by: Shiva Krishna 
Signed-off-by: Long Li 
Reviewed-by: K. Y. Srinivasan 
Signed-off-by: K. Y. Srinivasan 
Cc: 
---
 drivers/scsi/storvsc_drv.c |   16 +---
 1 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 3c92dc2..888e16e 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -377,6 +377,7 @@ enum storvsc_request_type {
 #define SRB_STATUS_SUCCESS 0x01
 #define SRB_STATUS_ABORTED 0x02
 #define SRB_STATUS_ERROR   0x04
+#define SRB_STATUS_DATA_OVERRUN0x12
 
 #define SRB_STATUS(status) \
(status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))
@@ -996,6 +997,7 @@ static void storvsc_command_completion(struct 
storvsc_cmd_request *cmd_request,
struct scsi_cmnd *scmnd = cmd_request->cmd;
struct scsi_sense_hdr sense_hdr;
struct vmscsi_request *vm_srb;
+   u32 data_transfer_length;
struct Scsi_Host *host;
u32 payload_sz = cmd_request->payload_sz;
void *payload = cmd_request->payload;
@@ -1003,6 +1005,7 @@ static void storvsc_command_completion(struct 
storvsc_cmd_request *cmd_request,
host = stor_dev->host;
 
vm_srb = _request->vstor_packet.vm_srb;
+   data_transfer_length = vm_srb->data_transfer_length;
 
scmnd->result = vm_srb->scsi_status;
 
@@ -1016,13 +1019,20 @@ static void storvsc_command_completion(struct 
storvsc_cmd_request *cmd_request,
 _hdr);
}
 
-   if (vm_srb->srb_status != SRB_STATUS_SUCCESS)
+   if (vm_srb->srb_status != SRB_STATUS_SUCCESS) {
storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc,
 sense_hdr.ascq);
+   /*
+* The Windows driver set data_transfer_length on
+* SRB_STATUS_DATA_OVERRUN. On other errors, this value
+* is untouched.  In these cases we set it to 0.
+*/
+   if (vm_srb->srb_status != SRB_STATUS_DATA_OVERRUN)
+   data_transfer_length = 0;
+   }
 
scsi_set_resid(scmnd,
-   cmd_request->payload->range.len -
-   vm_srb->data_transfer_length);
+   cmd_request->payload->range.len - data_transfer_length);
 
scmnd->scsi_done(scmnd);
 
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/6] storvsc: Miscellaneous fixes and enhancements

2016-12-14 Thread kys
From: K. Y. Srinivasan 

Miscellaneous fixes and enhancements.

K. Y. Srinivasan (3):
  storvsc: Enable tracking of queue depth
  storvsc: Remove the restriction on max segment size
  storvsc: Enable multi-queue support

Long Li (3):
  storvsc: use tagged SRB requests if supported by the device
  storvsc: properly handle SRB_ERROR when sense message is present
  storvsc: properly set residual data length on errors

 drivers/scsi/storvsc_drv.c |  148 +---
 1 files changed, 140 insertions(+), 8 deletions(-)

-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html