[PATCH 1/1] scsi: storvsc: Support manual scan of FC hosts on Hyper-V
The default user scan function associated with FC (fc_user_scan) is not suitable for FC hosts on Hyper-V since we don't have an rport associated with FC host on Hyper-V . Set it to NULL so we can support manual scan of FC targets on Hyper-V. Signed-off-by: K. Y. Srinivasan Tested-by: Long Li Reviewed-by: Long Li --- 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 132b168..8aec590 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1776,6 +1776,12 @@ static int __init storvsc_drv_init(void) * Install Hyper-V specific timeout handler. */ fc_transport_template->eh_timed_out = storvsc_eh_timed_out; + /* +* The default user scan function associated with FC (fc_user_scan) +* is not suitable for FC hosts on Hyper-V. Set it to NULL so we can +* support manual scan of FC targets on Hyper-V. +*/ + fc_transport_template->user_scan = NULL; #endif ret = vmbus_driver_register(&storvsc_drv); -- 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 v4 1/1] scsi: storvsc: Fix a build issue reported by kbuild test robot
tree: https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgit.kernel.org%2fpub%2fscm%2flinux%2fkernel%2fgit%2ftorvalds%2flinux.git&data=01%7c01%7ckys%40microsoft.com%7ce2e0622715844b79ad7108d32796ec3c%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=ubr4GbBaNS%2ftOz%2buJBk0CL9N0UNG9x2TidLgy6Yovg4%3d master head: 03c21cb775a313f1ff19be59c5d02df3e3526471 commit: dac582417bc449b1f7f572d3f1dd9d23eec15cc9 storvsc: Properly support Fibre Channel devices date: 3 weeks ago config: x86_64-randconfig-s3-01281016 (attached as .config) reproduce: git checkout dac582417bc449b1f7f572d3f1dd9d23eec15cc9 # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): drivers/built-in.o: In function `storvsc_remove': >> storvsc_drv.c:(.text+0x213af7): undefined reference to `fc_remove_host' drivers/built-in.o: In function `storvsc_drv_init': >> storvsc_drv.c:(.init.text+0xcbcc): undefined reference to >> `fc_attach_transport' >> storvsc_drv.c:(.init.text+0xcc06): undefined reference to >> `fc_release_transport' drivers/built-in.o: In function `storvsc_drv_exit': >> storvsc_drv.c:(.exit.text+0x123c): undefined reference to >> `fc_release_transport' With this commit, the storvsc driver depends on FC atttributes. Make this dependency explicit. Signed-off-by: K. Y. Srinivasan Reported-by: Fengguang Wu --- v1 - v4: Incorporated suggestions from James Bottomley drivers/scsi/Kconfig |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 64eed87..166de0c 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -594,6 +594,7 @@ config XEN_SCSI_FRONTEND config HYPERV_STORAGE tristate "Microsoft Hyper-V virtual storage driver" depends on SCSI && HYPERV + depends on m || SCSI_FC_ATTRS != m default HYPERV help Select this option to enable the Hyper-V virtual storage driver. -- 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/1] scsi: storvsc: Fix a build issue reported by kbuild test robot
tree: https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgit.kernel.org%2fpub%2fscm%2flinux%2fkernel%2fgit%2ftorvalds%2flinux.git&data=01%7c01%7ckys%40microsoft.com%7ce2e0622715844b79ad7108d32796ec3c%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=ubr4GbBaNS%2ftOz%2buJBk0CL9N0UNG9x2TidLgy6Yovg4%3d master head: 03c21cb775a313f1ff19be59c5d02df3e3526471 commit: dac582417bc449b1f7f572d3f1dd9d23eec15cc9 storvsc: Properly support Fibre Channel devices date: 3 weeks ago config: x86_64-randconfig-s3-01281016 (attached as .config) reproduce: git checkout dac582417bc449b1f7f572d3f1dd9d23eec15cc9 # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): drivers/built-in.o: In function `storvsc_remove': >> storvsc_drv.c:(.text+0x213af7): undefined reference to `fc_remove_host' drivers/built-in.o: In function `storvsc_drv_init': >> storvsc_drv.c:(.init.text+0xcbcc): undefined reference to >> `fc_attach_transport' >> storvsc_drv.c:(.init.text+0xcc06): undefined reference to >> `fc_release_transport' drivers/built-in.o: In function `storvsc_drv_exit': >> storvsc_drv.c:(.exit.text+0x123c): undefined reference to >> `fc_release_transport' With this commit, the storvsc driver depends on FC atttributes. Make this dependency explicit. Signed-off-by: K. Y. Srinivasan Reported-by: Fengguang Wu --- drivers/scsi/Kconfig |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 64eed87..24365c3 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -594,6 +594,7 @@ config XEN_SCSI_FRONTEND config HYPERV_STORAGE tristate "Microsoft Hyper-V virtual storage driver" depends on SCSI && HYPERV + depends on SCSI_FC_ATTRS default HYPERV help Select this option to enable the Hyper-V virtual storage driver. -- 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 V2 1/1] scsi: storvsc: Fix a build issue reported by kbuild test robot
tree: https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgit.kernel.org%2fpub%2fscm%2flinux%2fkernel%2fgit%2ftorvalds%2flinux.git&data=01%7c01%7ckys%40microsoft.com%7ce2e0622715844b79ad7108d32796ec3c%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=ubr4GbBaNS%2ftOz%2buJBk0CL9N0UNG9x2TidLgy6Yovg4%3d master head: 03c21cb775a313f1ff19be59c5d02df3e3526471 commit: dac582417bc449b1f7f572d3f1dd9d23eec15cc9 storvsc: Properly support Fibre Channel devices date: 3 weeks ago config: x86_64-randconfig-s3-01281016 (attached as .config) reproduce: git checkout dac582417bc449b1f7f572d3f1dd9d23eec15cc9 # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): drivers/built-in.o: In function `storvsc_remove': >> storvsc_drv.c:(.text+0x213af7): undefined reference to `fc_remove_host' drivers/built-in.o: In function `storvsc_drv_init': >> storvsc_drv.c:(.init.text+0xcbcc): undefined reference to >> `fc_attach_transport' >> storvsc_drv.c:(.init.text+0xcc06): undefined reference to >> `fc_release_transport' drivers/built-in.o: In function `storvsc_drv_exit': >> storvsc_drv.c:(.exit.text+0x123c): undefined reference to >> `fc_release_transport' With this commit, the storvsc driver depends on FC atttributes. Make this dependency explicit. Signed-off-by: K. Y. Srinivasan Reported-by: Fengguang Wu --- V2: Fixed the dependency based on suggestion by James Bottomley drivers/scsi/Kconfig |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 64eed87..ce0d07b 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -594,6 +594,7 @@ config XEN_SCSI_FRONTEND config HYPERV_STORAGE tristate "Microsoft Hyper-V virtual storage driver" depends on SCSI && HYPERV + depends on SCSI_FC_ATTRS || SCSI_FC_ATTRS !=m default HYPERV help Select this option to enable the Hyper-V virtual storage driver. -- 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/1] scsi: storvsc: Fix a build issue reported by kbuild test robot
tree: https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgit.kernel.org%2fpub%2fscm%2flinux%2fkernel%2fgit%2ftorvalds%2flinux.git&data=01%7c01%7ckys%40microsoft.com%7ce2e0622715844b79ad7108d32796ec3c%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=ubr4GbBaNS%2ftOz%2buJBk0CL9N0UNG9x2TidLgy6Yovg4%3d master head: 03c21cb775a313f1ff19be59c5d02df3e3526471 commit: dac582417bc449b1f7f572d3f1dd9d23eec15cc9 storvsc: Properly support Fibre Channel devices date: 3 weeks ago config: x86_64-randconfig-s3-01281016 (attached as .config) reproduce: git checkout dac582417bc449b1f7f572d3f1dd9d23eec15cc9 # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): drivers/built-in.o: In function `storvsc_remove': >> storvsc_drv.c:(.text+0x213af7): undefined reference to `fc_remove_host' drivers/built-in.o: In function `storvsc_drv_init': >> storvsc_drv.c:(.init.text+0xcbcc): undefined reference to >> `fc_attach_transport' >> storvsc_drv.c:(.init.text+0xcc06): undefined reference to >> `fc_release_transport' drivers/built-in.o: In function `storvsc_drv_exit': >> storvsc_drv.c:(.exit.text+0x123c): undefined reference to >> `fc_release_transport' With this commit, the storvsc driver depends on FC atttributes. Make this dependency explicit. Signed-off-by: K. Y. Srinivasan Reported-by: Fengguang Wu --- drivers/scsi/Kconfig |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 64eed87..24365c3 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -594,6 +594,7 @@ config XEN_SCSI_FRONTEND config HYPERV_STORAGE tristate "Microsoft Hyper-V virtual storage driver" depends on SCSI && HYPERV + depends on SCSI_FC_ATTRS default HYPERV help Select this option to enable the Hyper-V virtual storage driver. -- 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 V2 0/2] scsi: storvsc: Miscellaneous fixes
Some miscellaneous fixes. V2: addressed comments from Hannes Reinecke K. Y. Srinivasan (2): scsi: storvsc: Install the storvsc specific timeout handler for FC devices scsi: storvsc: Use the specified target ID in device lookup drivers/scsi/storvsc_drv.c | 16 +++- 1 files changed, 11 insertions(+), 5 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
[PATCH V2 2/2] scsi: storvsc: Use the specified target ID in device lookup
The current code assumes that there is only one target in device lookup. Fix this bug. This will alow us to correctly handle hot reomoval of LUNs. Signed-off-by: K. Y. Srinivasan Reviewed-by: Alex Ng Tested-by: Vivek Yadav --- V2: Made lun and target_id unsigned 8 bit entities - Hannes Reinecke drivers/scsi/storvsc_drv.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 622f64a..132b168 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -478,19 +478,18 @@ struct hv_host_device { struct storvsc_scan_work { struct work_struct work; struct Scsi_Host *host; - uint lun; + u8 lun; + u8 tgt_id; }; static void storvsc_device_scan(struct work_struct *work) { struct storvsc_scan_work *wrk; - uint lun; struct scsi_device *sdev; wrk = container_of(work, struct storvsc_scan_work, work); - lun = wrk->lun; - sdev = scsi_device_lookup(wrk->host, 0, 0, lun); + sdev = scsi_device_lookup(wrk->host, 0, wrk->tgt_id, wrk->lun); if (!sdev) goto done; scsi_rescan_device(&sdev->sdev_gendev); @@ -541,7 +540,7 @@ static void storvsc_remove_lun(struct work_struct *work) if (!scsi_host_get(wrk->host)) goto done; - sdev = scsi_device_lookup(wrk->host, 0, 0, wrk->lun); + sdev = scsi_device_lookup(wrk->host, 0, wrk->tgt_id, wrk->lun); if (sdev) { scsi_remove_device(sdev); @@ -941,6 +940,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, wrk->host = host; wrk->lun = vm_srb->lun; + wrk->tgt_id = vm_srb->target_id; INIT_WORK(&wrk->work, process_err_fn); schedule_work(&wrk->work); } -- 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 V2 1/2] scsi: storvsc: Install the storvsc specific timeout handler for FC devices
The default timeout routine used for FC transport is not suitable for FC devices managed by storvsc since FC devices managed by storvsc driver do not have an rport associated with them. Use the time out handler used for SCSI devices for FC devices as well. Signed-off-by: K. Y. Srinivasan Reviewed-by: Alex Ng Tested-by: Vivek Yadav --- 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 41c115c..622f64a 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -42,6 +42,7 @@ #include #include #include +#include /* * All wire protocol details (storage protocol between the guest and the host) @@ -1770,6 +1771,11 @@ static int __init storvsc_drv_init(void) fc_transport_template = fc_attach_transport(&fc_transport_functions); if (!fc_transport_template) return -ENODEV; + + /* +* Install Hyper-V specific timeout handler. +*/ + fc_transport_template->eh_timed_out = storvsc_eh_timed_out; #endif ret = vmbus_driver_register(&storvsc_drv); -- 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 V4 4/4] scsi: storvsc: Tighten up the interrupt path
On the interrupt path, we repeatedly establish the pointer to the storvsc_device. While the compiler does inline get_in_stor_device() (and other static functions) in the call chain in the interrupt path, the compiler is repeatedly inlining the call to get_in_stor_device() each time it is invoked. The return value of get_in_stor_device() can be cached in the interrupt path since there is higher level serialization in place to ensure correct handling when the module unload races with the processing of an incoming message from the host. Optimize this code path by caching the pointer to storvsc_device and passing it as an argument. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Tested-by: Alex Ng --- Added Reviewed-by: Hannes Reinecke Added additional details to the commit log - James Bottomley drivers/scsi/storvsc_drv.c | 23 --- 1 files changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 811f276..41c115c 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -945,19 +945,16 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, } -static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) +static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, + struct storvsc_device *stor_dev) { struct scsi_cmnd *scmnd = cmd_request->cmd; - struct hv_host_device *host_dev = shost_priv(scmnd->device->host); struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; struct Scsi_Host *host; - struct storvsc_device *stor_dev; - struct hv_device *dev = host_dev->dev; u32 payload_sz = cmd_request->payload_sz; void *payload = cmd_request->payload; - stor_dev = get_in_stor_device(dev); host = stor_dev->host; vm_srb = &cmd_request->vstor_packet.vm_srb; @@ -987,14 +984,13 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) kfree(payload); } -static void storvsc_on_io_completion(struct hv_device *device, +static void storvsc_on_io_completion(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { - struct storvsc_device *stor_device; struct vstor_packet *stor_pkt; + struct hv_device *device = stor_device->device; - stor_device = hv_get_drvdata(device); stor_pkt = &request->vstor_packet; /* @@ -1049,7 +1045,7 @@ static void storvsc_on_io_completion(struct hv_device *device, stor_pkt->vm_srb.data_transfer_length = vstor_packet->vm_srb.data_transfer_length; - storvsc_command_completion(request); + storvsc_command_completion(request, stor_device); if (atomic_dec_and_test(&stor_device->num_outstanding_req) && stor_device->drain_notify) @@ -1058,21 +1054,19 @@ static void storvsc_on_io_completion(struct hv_device *device, } -static void storvsc_on_receive(struct hv_device *device, +static void storvsc_on_receive(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { struct storvsc_scan_work *work; - struct storvsc_device *stor_device; switch (vstor_packet->operation) { case VSTOR_OPERATION_COMPLETE_IO: - storvsc_on_io_completion(device, vstor_packet, request); + storvsc_on_io_completion(stor_device, vstor_packet, request); break; case VSTOR_OPERATION_REMOVE_DEVICE: case VSTOR_OPERATION_ENUMERATE_BUS: - stor_device = get_in_stor_device(device); work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC); if (!work) return; @@ -1083,7 +1077,6 @@ static void storvsc_on_receive(struct hv_device *device, break; case VSTOR_OPERATION_FCHBA_DATA: - stor_device = get_in_stor_device(device); cache_wwn(stor_device, vstor_packet); #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) fc_host_node_name(stor_device->host) = stor_device->node_name; @@ -1133,7 +1126,7 @@ static void storvsc_on_channel_callback(void *context) vmscsi_size_delta)); complete(&request->wait_event); } else { - storvsc_on_receive(device, + storvsc_on_receive(stor_device, (struct
[PATCH V4 1/4] scsi: storvsc: Fix a bug in the layout of the hv_fc_wwn_packet
The hv_fc_wwn_packet is exchanged over vmbus. Make the definition in Linux match the Window's definition. Signed-off-by: K. Y. Srinivasan Reviewed-by: Johannes Thumshirn Reviewed-by: Long Li Reviewed-by: Hannes Reinecke Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c |5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index c41f674..00bb4bd 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -92,9 +92,8 @@ enum vstor_packet_operation { */ struct hv_fc_wwn_packet { - boolprimary_active; - u8 reserved1; - u8 reserved2; + u8 primary_active; + u8 reserved1[3]; u8 primary_port_wwn[8]; u8 primary_node_wwn[8]; u8 secondary_port_wwn[8]; -- 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 V4 0/4] scsi: storvsc: Properly support FC hosts
Properly support FC hosts. Additional cleanup patches are also included. V2: Comments from Dan Carpenter and from Johannes Thumshirn addressed. V3: Fixed build issues reported by kbuild test robot V4: Addressed comments from Hannes and James. K. Y. Srinivasan (4): scsi: storvsc: Fix a bug in the layout of the hv_fc_wwn_packet scsi: storvsc: Properly support Fibre Channel devices scsi: storvsc: Refactor the code in storvsc_channel_init() scsi: storvsc: Tighten up the interrupt path drivers/scsi/storvsc_drv.c | 275 +-- 1 files changed, 160 insertions(+), 115 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
[PATCH V4 3/4] scsi: storvsc: Refactor the code in storvsc_channel_init()
The function storvsc_channel_init() repeatedly interacts with the host to extract various channel properties. Refactor this code to eliminate code repetition. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Reviewed-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Tested-by: Alex Ng --- V2: Fixed error paths - Dan Carpenter V4: Added Reviewed-by: Hannes Reinecke drivers/scsi/storvsc_drv.c | 126 1 files changed, 46 insertions(+), 80 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index cfbb289..811f276 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -723,29 +723,17 @@ static void cache_wwn(struct storvsc_device *stor_device, } } -static int storvsc_channel_init(struct hv_device *device, bool is_fc) + +static int storvsc_execute_vstor_op(struct hv_device *device, + struct storvsc_cmd_request *request, + bool status_check) { - struct storvsc_device *stor_device; - struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; - int ret, t, i; - int max_chns; - bool process_sub_channels = false; - - stor_device = get_out_stor_device(device); - if (!stor_device) - return -ENODEV; + int ret, t; - request = &stor_device->init_request; vstor_packet = &request->vstor_packet; - /* -* Now, initiate the vsc/vsp initialization protocol on the open -* channel -*/ - memset(request, 0, sizeof(struct storvsc_cmd_request)); init_completion(&request->wait_event); - vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; ret = vmbus_sendpacket(device->channel, vstor_packet, @@ -761,17 +749,50 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) if (t == 0) return -ETIMEDOUT; + if (!status_check) + return ret; + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || vstor_packet->status != 0) return -EINVAL; + return ret; +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) +{ + struct storvsc_device *stor_device; + struct storvsc_cmd_request *request; + struct vstor_packet *vstor_packet; + int ret, i; + int max_chns; + bool process_sub_channels = false; + + stor_device = get_out_stor_device(device); + if (!stor_device) + return -ENODEV; + + request = &stor_device->init_request; + vstor_packet = &request->vstor_packet; + + /* +* Now, initiate the vsc/vsp initialization protocol on the open +* channel +*/ + memset(request, 0, sizeof(struct storvsc_cmd_request)); + vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; + ret = storvsc_execute_vstor_op(device, request, true); + if (ret) + return ret; + /* +* Query host supported protocol version. +*/ for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { /* reuse the packet for version range supported */ memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; vstor_packet->version.major_minor = vmstor_protocols[i].protocol_version; @@ -780,20 +801,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) * The revision number is only used in Windows; set it to 0. */ vstor_packet->version.revision = 0; - - ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - vmscsi_size_delta), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + ret = storvsc_execute_vstor_op(device, request, false); if (ret != 0) return ret; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) - return -ETIMEDOUT; - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) return -EINVAL; @@ -817,26 +828,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_
[PATCH V4 2/4] scsi: storvsc: Properly support Fibre Channel devices
For FC devices managed by this driver, atttach the appropriate transport template. This will allow us to create the appropriate sysfs files for these devices. With this we can publish the wwn for both the port and the node. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Tested-by: Alex Ng --- V2: Fixed error paths - Dan Carpenter V3: Fixed build issues reported by kbuild test robot V4: Handle configuration of SCSI_FC_ATTRS correctly (both module and built in) drivers/scsi/storvsc_drv.c | 181 --- 1 files changed, 134 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 00bb4bd..cfbb289 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -41,6 +41,7 @@ #include #include #include +#include /* * All wire protocol details (storage protocol between the guest and the host) @@ -397,6 +398,9 @@ static int storvsc_timeout = 180; static int msft_blist_flags = BLIST_TRY_VPD_PAGES; +#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) +static struct scsi_transport_template *fc_transport_template; +#endif static void storvsc_on_channel_callback(void *context); @@ -456,6 +460,11 @@ struct storvsc_device { /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; + /* +* Currently active port and node names for FC devices. +*/ + u64 node_name; + u64 port_name; }; struct hv_host_device { @@ -695,7 +704,26 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) vmbus_are_subchannels_present(device->channel); } -static int storvsc_channel_init(struct hv_device *device) +static void cache_wwn(struct storvsc_device *stor_device, + struct vstor_packet *vstor_packet) +{ + /* +* Cache the currently active port and node ww names. +*/ + if (vstor_packet->wwn_packet.primary_active) { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_port_wwn); + } else { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_port_wwn); + } +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) { struct storvsc_device *stor_device; struct storvsc_cmd_request *request; @@ -727,19 +755,15 @@ static int storvsc_channel_init(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + vstor_packet->status != 0) + return -EINVAL; for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { @@ -764,18 +788,14 @@ static int storvsc_channel_init(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) { - ret = -EINVAL; - goto cleanup; - } + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) + return -EINVAL; if (vstor_packet->status == 0) { vmstor_proto_version = @@ -791,10 +811,8 @@ static int storvsc_channel_init(struct hv_device *device) } } - if (vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + if (vstor_packet->status != 0) + return -EINVAL; memset(vstor_packet, 0, sizeof(struct vstor_packet)); @@ -809
[PATCH V3 2/4] scsi: storvsc: Properly support Fibre Channel devices
For FC devices managed by this driver, atttach the appropriate transport template. This will allow us to create the appropriate sysfs files for these devices. With this we can publish the wwn for both the port and the node. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Tested-by: Alex Ng --- V2: Fixed error paths - Dan Carpenter V3: Fixed build issues reported by kbuild test robot drivers/scsi/storvsc_drv.c | 181 --- 1 files changed, 134 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 00bb4bd..220b794 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -41,6 +41,7 @@ #include #include #include +#include /* * All wire protocol details (storage protocol between the guest and the host) @@ -397,6 +398,9 @@ static int storvsc_timeout = 180; static int msft_blist_flags = BLIST_TRY_VPD_PAGES; +#ifdef CONFIG_SCSI_FC_ATTRS +static struct scsi_transport_template *fc_transport_template; +#endif static void storvsc_on_channel_callback(void *context); @@ -456,6 +460,11 @@ struct storvsc_device { /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; + /* +* Currently active port and node names for FC devices. +*/ + u64 node_name; + u64 port_name; }; struct hv_host_device { @@ -695,7 +704,26 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) vmbus_are_subchannels_present(device->channel); } -static int storvsc_channel_init(struct hv_device *device) +static void cache_wwn(struct storvsc_device *stor_device, + struct vstor_packet *vstor_packet) +{ + /* +* Cache the currently active port and node ww names. +*/ + if (vstor_packet->wwn_packet.primary_active) { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_port_wwn); + } else { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_port_wwn); + } +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) { struct storvsc_device *stor_device; struct storvsc_cmd_request *request; @@ -727,19 +755,15 @@ static int storvsc_channel_init(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + vstor_packet->status != 0) + return -EINVAL; for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { @@ -764,18 +788,14 @@ static int storvsc_channel_init(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) { - ret = -EINVAL; - goto cleanup; - } + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) + return -EINVAL; if (vstor_packet->status == 0) { vmstor_proto_version = @@ -791,10 +811,8 @@ static int storvsc_channel_init(struct hv_device *device) } } - if (vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + if (vstor_packet->status != 0) + return -EINVAL; memset(vstor_packet, 0, sizeof(struct vstor_packet)); @@ -809,19 +827,15 @@ static int storvsc_channel_init(struct hv_device *device)
[PATCH V3 4/4] scsi: storvsc: Tighten up the interrupt path
On the interrupt path, we repeatedly establish the pointer to the storvsc_device. Fix this. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Reviewed-by: Johannes Thumshirn Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c | 23 --- 1 files changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index d6ca4f2..b68aebe 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -945,19 +945,16 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, } -static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) +static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, + struct storvsc_device *stor_dev) { struct scsi_cmnd *scmnd = cmd_request->cmd; - struct hv_host_device *host_dev = shost_priv(scmnd->device->host); struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; struct Scsi_Host *host; - struct storvsc_device *stor_dev; - struct hv_device *dev = host_dev->dev; u32 payload_sz = cmd_request->payload_sz; void *payload = cmd_request->payload; - stor_dev = get_in_stor_device(dev); host = stor_dev->host; vm_srb = &cmd_request->vstor_packet.vm_srb; @@ -987,14 +984,13 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) kfree(payload); } -static void storvsc_on_io_completion(struct hv_device *device, +static void storvsc_on_io_completion(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { - struct storvsc_device *stor_device; struct vstor_packet *stor_pkt; + struct hv_device *device = stor_device->device; - stor_device = hv_get_drvdata(device); stor_pkt = &request->vstor_packet; /* @@ -1049,7 +1045,7 @@ static void storvsc_on_io_completion(struct hv_device *device, stor_pkt->vm_srb.data_transfer_length = vstor_packet->vm_srb.data_transfer_length; - storvsc_command_completion(request); + storvsc_command_completion(request, stor_device); if (atomic_dec_and_test(&stor_device->num_outstanding_req) && stor_device->drain_notify) @@ -1058,21 +1054,19 @@ static void storvsc_on_io_completion(struct hv_device *device, } -static void storvsc_on_receive(struct hv_device *device, +static void storvsc_on_receive(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { struct storvsc_scan_work *work; - struct storvsc_device *stor_device; switch (vstor_packet->operation) { case VSTOR_OPERATION_COMPLETE_IO: - storvsc_on_io_completion(device, vstor_packet, request); + storvsc_on_io_completion(stor_device, vstor_packet, request); break; case VSTOR_OPERATION_REMOVE_DEVICE: case VSTOR_OPERATION_ENUMERATE_BUS: - stor_device = get_in_stor_device(device); work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC); if (!work) return; @@ -1083,7 +1077,6 @@ static void storvsc_on_receive(struct hv_device *device, break; case VSTOR_OPERATION_FCHBA_DATA: - stor_device = get_in_stor_device(device); cache_wwn(stor_device, vstor_packet); #ifdef CONFIG_SCSI_FC_ATTRS fc_host_node_name(stor_device->host) = stor_device->node_name; @@ -1133,7 +1126,7 @@ static void storvsc_on_channel_callback(void *context) vmscsi_size_delta)); complete(&request->wait_event); } else { - storvsc_on_receive(device, + storvsc_on_receive(stor_device, (struct vstor_packet *)packet, request); } -- 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 V3 3/4] scsi: storvsc: Refactor the code in storvsc_channel_init()
The function storvsc_channel_init() repeatedly interacts with the host to extract various channel properties. Refactor this code to eliminate code repetition. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Reviewed-by: Johannes Thumshirn Tested-by: Alex Ng --- V2: Fixed error paths - Dan Carpenter drivers/scsi/storvsc_drv.c | 126 1 files changed, 46 insertions(+), 80 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 220b794..d6ca4f2 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -723,29 +723,17 @@ static void cache_wwn(struct storvsc_device *stor_device, } } -static int storvsc_channel_init(struct hv_device *device, bool is_fc) + +static int storvsc_execute_vstor_op(struct hv_device *device, + struct storvsc_cmd_request *request, + bool status_check) { - struct storvsc_device *stor_device; - struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; - int ret, t, i; - int max_chns; - bool process_sub_channels = false; - - stor_device = get_out_stor_device(device); - if (!stor_device) - return -ENODEV; + int ret, t; - request = &stor_device->init_request; vstor_packet = &request->vstor_packet; - /* -* Now, initiate the vsc/vsp initialization protocol on the open -* channel -*/ - memset(request, 0, sizeof(struct storvsc_cmd_request)); init_completion(&request->wait_event); - vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; ret = vmbus_sendpacket(device->channel, vstor_packet, @@ -761,17 +749,50 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) if (t == 0) return -ETIMEDOUT; + if (!status_check) + return ret; + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || vstor_packet->status != 0) return -EINVAL; + return ret; +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) +{ + struct storvsc_device *stor_device; + struct storvsc_cmd_request *request; + struct vstor_packet *vstor_packet; + int ret, i; + int max_chns; + bool process_sub_channels = false; + + stor_device = get_out_stor_device(device); + if (!stor_device) + return -ENODEV; + + request = &stor_device->init_request; + vstor_packet = &request->vstor_packet; + + /* +* Now, initiate the vsc/vsp initialization protocol on the open +* channel +*/ + memset(request, 0, sizeof(struct storvsc_cmd_request)); + vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; + ret = storvsc_execute_vstor_op(device, request, true); + if (ret) + return ret; + /* +* Query host supported protocol version. +*/ for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { /* reuse the packet for version range supported */ memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; vstor_packet->version.major_minor = vmstor_protocols[i].protocol_version; @@ -780,20 +801,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) * The revision number is only used in Windows; set it to 0. */ vstor_packet->version.revision = 0; - - ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - vmscsi_size_delta), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + ret = storvsc_execute_vstor_op(device, request, false); if (ret != 0) return ret; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) - return -ETIMEDOUT; - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) return -EINVAL; @@ -817,26 +828,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES; - vstor_packet->flags =
[PATCH V3 0/4] scsi: storvsc: Properly support FC hosts
Properly support FC hosts. Additional cleanup patches are also included. V2: Comments from Dan Carpenter and from Johannes Thumshirn addressed. V3: Fixed build issues reported by kbuild test robot K. Y. Srinivasan (4): scsi: storvsc: Fix a bug in the layout of the hv_fc_wwn_packet scsi: storvsc: Properly support Fibre Channel devices scsi: storvsc: Refactor the code in storvsc_channel_init() scsi: storvsc: Tighten up the interrupt path drivers/scsi/storvsc_drv.c | 275 +-- 1 files changed, 160 insertions(+), 115 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
[PATCH V3 1/4] scsi: storvsc: Fix a bug in the layout of the hv_fc_wwn_packet
The hv_fc_wwn_packet is exchanged over vmbus. Make the definition in Linux match the Window's definition. Signed-off-by: K. Y. Srinivasan Reviewed-by: Johannes Thumshirn Reviewed-by: Long Li Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c |5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index c41f674..00bb4bd 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -92,9 +92,8 @@ enum vstor_packet_operation { */ struct hv_fc_wwn_packet { - boolprimary_active; - u8 reserved1; - u8 reserved2; + u8 primary_active; + u8 reserved1[3]; u8 primary_port_wwn[8]; u8 primary_node_wwn[8]; u8 secondary_port_wwn[8]; -- 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 V2 4/4] scsi: storvsc: Tighten up the interrupt path
On the interrupt path, we repeatedly establish the pointer to the storvsc_device. Fix this. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Reviewed-by: Johannes Thumshirn Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c | 23 --- 1 files changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 947f812..3d3d157 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -943,19 +943,16 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, } -static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) +static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, + struct storvsc_device *stor_dev) { struct scsi_cmnd *scmnd = cmd_request->cmd; - struct hv_host_device *host_dev = shost_priv(scmnd->device->host); struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; struct Scsi_Host *host; - struct storvsc_device *stor_dev; - struct hv_device *dev = host_dev->dev; u32 payload_sz = cmd_request->payload_sz; void *payload = cmd_request->payload; - stor_dev = get_in_stor_device(dev); host = stor_dev->host; vm_srb = &cmd_request->vstor_packet.vm_srb; @@ -985,14 +982,13 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) kfree(payload); } -static void storvsc_on_io_completion(struct hv_device *device, +static void storvsc_on_io_completion(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { - struct storvsc_device *stor_device; struct vstor_packet *stor_pkt; + struct hv_device *device = stor_device->device; - stor_device = hv_get_drvdata(device); stor_pkt = &request->vstor_packet; /* @@ -1047,7 +1043,7 @@ static void storvsc_on_io_completion(struct hv_device *device, stor_pkt->vm_srb.data_transfer_length = vstor_packet->vm_srb.data_transfer_length; - storvsc_command_completion(request); + storvsc_command_completion(request, stor_device); if (atomic_dec_and_test(&stor_device->num_outstanding_req) && stor_device->drain_notify) @@ -1056,21 +1052,19 @@ static void storvsc_on_io_completion(struct hv_device *device, } -static void storvsc_on_receive(struct hv_device *device, +static void storvsc_on_receive(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { struct storvsc_scan_work *work; - struct storvsc_device *stor_device; switch (vstor_packet->operation) { case VSTOR_OPERATION_COMPLETE_IO: - storvsc_on_io_completion(device, vstor_packet, request); + storvsc_on_io_completion(stor_device, vstor_packet, request); break; case VSTOR_OPERATION_REMOVE_DEVICE: case VSTOR_OPERATION_ENUMERATE_BUS: - stor_device = get_in_stor_device(device); work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC); if (!work) return; @@ -1081,7 +1075,6 @@ static void storvsc_on_receive(struct hv_device *device, break; case VSTOR_OPERATION_FCHBA_DATA: - stor_device = get_in_stor_device(device); cache_wwn(stor_device, vstor_packet); fc_host_node_name(stor_device->host) = stor_device->node_name; fc_host_port_name(stor_device->host) = stor_device->port_name; @@ -1129,7 +1122,7 @@ static void storvsc_on_channel_callback(void *context) vmscsi_size_delta)); complete(&request->wait_event); } else { - storvsc_on_receive(device, + storvsc_on_receive(stor_device, (struct vstor_packet *)packet, request); } -- 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 V2 3/4] scsi: storvsc: Refactor the code in storvsc_channel_init()
The function storvsc_channel_init() repeatedly interacts with the host to extract various channel properties. Refactor this code to eliminate code repetition. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Reviewed-by: Johannes Thumshirn Tested-by: Alex Ng --- V2: Fixed error paths - Dan Carpenter drivers/scsi/storvsc_drv.c | 126 1 files changed, 46 insertions(+), 80 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index ab9828c..947f812 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -721,29 +721,17 @@ static void cache_wwn(struct storvsc_device *stor_device, } } -static int storvsc_channel_init(struct hv_device *device, bool is_fc) + +static int storvsc_execute_vstor_op(struct hv_device *device, + struct storvsc_cmd_request *request, + bool status_check) { - struct storvsc_device *stor_device; - struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; - int ret, t, i; - int max_chns; - bool process_sub_channels = false; - - stor_device = get_out_stor_device(device); - if (!stor_device) - return -ENODEV; + int ret, t; - request = &stor_device->init_request; vstor_packet = &request->vstor_packet; - /* -* Now, initiate the vsc/vsp initialization protocol on the open -* channel -*/ - memset(request, 0, sizeof(struct storvsc_cmd_request)); init_completion(&request->wait_event); - vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; ret = vmbus_sendpacket(device->channel, vstor_packet, @@ -759,17 +747,50 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) if (t == 0) return -ETIMEDOUT; + if (!status_check) + return ret; + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || vstor_packet->status != 0) return -EINVAL; + return ret; +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) +{ + struct storvsc_device *stor_device; + struct storvsc_cmd_request *request; + struct vstor_packet *vstor_packet; + int ret, i; + int max_chns; + bool process_sub_channels = false; + + stor_device = get_out_stor_device(device); + if (!stor_device) + return -ENODEV; + + request = &stor_device->init_request; + vstor_packet = &request->vstor_packet; + + /* +* Now, initiate the vsc/vsp initialization protocol on the open +* channel +*/ + memset(request, 0, sizeof(struct storvsc_cmd_request)); + vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; + ret = storvsc_execute_vstor_op(device, request, true); + if (ret) + return ret; + /* +* Query host supported protocol version. +*/ for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { /* reuse the packet for version range supported */ memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; vstor_packet->version.major_minor = vmstor_protocols[i].protocol_version; @@ -778,20 +799,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) * The revision number is only used in Windows; set it to 0. */ vstor_packet->version.revision = 0; - - ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - vmscsi_size_delta), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + ret = storvsc_execute_vstor_op(device, request, false); if (ret != 0) return ret; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) - return -ETIMEDOUT; - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) return -EINVAL; @@ -815,26 +826,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES; - vstor_packet->flags =
[PATCH V2 2/4] scsi: storvsc: Properly support Fibre Channel devices
For FC devices managed by this driver, atttach the appropriate transport template. This will allow us to create the appropriate sysfs files for these devices. With this we can publish the wwn for both the port and the node. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Tested-by: Alex Ng --- V2: Fixed error paths - Dan Carpenter drivers/scsi/storvsc_drv.c | 162 +++- 1 files changed, 115 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 00bb4bd..ab9828c 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -41,6 +41,7 @@ #include #include #include +#include /* * All wire protocol details (storage protocol between the guest and the host) @@ -397,6 +398,7 @@ static int storvsc_timeout = 180; static int msft_blist_flags = BLIST_TRY_VPD_PAGES; +static struct scsi_transport_template *fc_transport_template; static void storvsc_on_channel_callback(void *context); @@ -456,6 +458,11 @@ struct storvsc_device { /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; + /* +* Currently active port and node names for FC devices. +*/ + u64 node_name; + u64 port_name; }; struct hv_host_device { @@ -695,7 +702,26 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) vmbus_are_subchannels_present(device->channel); } -static int storvsc_channel_init(struct hv_device *device) +static void cache_wwn(struct storvsc_device *stor_device, + struct vstor_packet *vstor_packet) +{ + /* +* Cache the currently active port and node ww names. +*/ + if (vstor_packet->wwn_packet.primary_active) { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_port_wwn); + } else { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_port_wwn); + } +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) { struct storvsc_device *stor_device; struct storvsc_cmd_request *request; @@ -727,19 +753,15 @@ static int storvsc_channel_init(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + vstor_packet->status != 0) + return -EINVAL; for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { @@ -764,18 +786,14 @@ static int storvsc_channel_init(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) { - ret = -EINVAL; - goto cleanup; - } + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) + return -EINVAL; if (vstor_packet->status == 0) { vmstor_proto_version = @@ -791,10 +809,8 @@ static int storvsc_channel_init(struct hv_device *device) } } - if (vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + if (vstor_packet->status != 0) + return -EINVAL; memset(vstor_packet, 0, sizeof(struct vstor_packet)); @@ -809,19 +825,15 @@ static int storvsc_channel_init(struct hv_device *device) VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0
[PATCH V2 1/4] scsi: storvsc: Fix a bug in the layout of the hv_fc_wwn_packet
The hv_fc_wwn_packet is exchanged over vmbus. Make the definition in Linux match the Window's definition. Signed-off-by: K. Y. Srinivasan Reviewed-by: Johannes Thumshirn Reviewed-by: Long Li Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c |5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index c41f674..00bb4bd 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -92,9 +92,8 @@ enum vstor_packet_operation { */ struct hv_fc_wwn_packet { - boolprimary_active; - u8 reserved1; - u8 reserved2; + u8 primary_active; + u8 reserved1[3]; u8 primary_port_wwn[8]; u8 primary_node_wwn[8]; u8 secondary_port_wwn[8]; -- 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 V2 0/4] scsi: storvsc: Properly support FC hosts
Properly support FC hosts. Additional cleanup patches are also included. In this version I have adddressed comments from Dan Carpenter and from Johannes Thumshirn . K. Y. Srinivasan (4): scsi: storvsc: Fix a bug in the layout of the hv_fc_wwn_packet scsi: storvsc: Properly support Fibre Channel devices scsi: storvsc: Refactor the code in storvsc_channel_init() scsi: storvsc: Tighten up the interrupt path drivers/scsi/storvsc_drv.c | 256 1 files changed, 141 insertions(+), 115 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
[PATCH 1/4] scsi: storvsc: Fix a bug in the layout of the hv_fc_wwn_packet
The hv_fc_wwn_packet is exchanged over vmbus. Make the definition in Linux match the Window's definition. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c |5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index c41f674..00bb4bd 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -92,9 +92,8 @@ enum vstor_packet_operation { */ struct hv_fc_wwn_packet { - boolprimary_active; - u8 reserved1; - u8 reserved2; + u8 primary_active; + u8 reserved1[3]; u8 primary_port_wwn[8]; u8 primary_node_wwn[8]; u8 secondary_port_wwn[8]; -- 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 4/4] scsi: storvsc: Tighten up the interrupt path
On the interrupt path, we repeatedly establish the pointer to the storvsc_device. Fix this. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c | 23 --- 1 files changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 6f18e94..8ba9908 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -958,19 +958,16 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, } -static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) +static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, + struct storvsc_device *stor_dev) { struct scsi_cmnd *scmnd = cmd_request->cmd; - struct hv_host_device *host_dev = shost_priv(scmnd->device->host); struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; struct Scsi_Host *host; - struct storvsc_device *stor_dev; - struct hv_device *dev = host_dev->dev; u32 payload_sz = cmd_request->payload_sz; void *payload = cmd_request->payload; - stor_dev = get_in_stor_device(dev); host = stor_dev->host; vm_srb = &cmd_request->vstor_packet.vm_srb; @@ -1000,14 +997,13 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) kfree(payload); } -static void storvsc_on_io_completion(struct hv_device *device, +static void storvsc_on_io_completion(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { - struct storvsc_device *stor_device; struct vstor_packet *stor_pkt; + struct hv_device *device = stor_device->device; - stor_device = hv_get_drvdata(device); stor_pkt = &request->vstor_packet; /* @@ -1062,7 +1058,7 @@ static void storvsc_on_io_completion(struct hv_device *device, stor_pkt->vm_srb.data_transfer_length = vstor_packet->vm_srb.data_transfer_length; - storvsc_command_completion(request); + storvsc_command_completion(request, stor_device); if (atomic_dec_and_test(&stor_device->num_outstanding_req) && stor_device->drain_notify) @@ -1071,21 +1067,19 @@ static void storvsc_on_io_completion(struct hv_device *device, } -static void storvsc_on_receive(struct hv_device *device, +static void storvsc_on_receive(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { struct storvsc_scan_work *work; - struct storvsc_device *stor_device; switch (vstor_packet->operation) { case VSTOR_OPERATION_COMPLETE_IO: - storvsc_on_io_completion(device, vstor_packet, request); + storvsc_on_io_completion(stor_device, vstor_packet, request); break; case VSTOR_OPERATION_REMOVE_DEVICE: case VSTOR_OPERATION_ENUMERATE_BUS: - stor_device = get_in_stor_device(device); work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC); if (!work) return; @@ -1096,7 +1090,6 @@ static void storvsc_on_receive(struct hv_device *device, break; case VSTOR_OPERATION_FCHBA_DATA: - stor_device = get_in_stor_device(device); cache_wwn(stor_device, vstor_packet); fc_host_node_name(stor_device->host) = stor_device->node_name; fc_host_port_name(stor_device->host) = stor_device->port_name; @@ -1144,7 +1137,7 @@ static void storvsc_on_channel_callback(void *context) vmscsi_size_delta)); complete(&request->wait_event); } else { - storvsc_on_receive(device, + storvsc_on_receive(stor_device, (struct vstor_packet *)packet, request); } -- 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 2/4] scsi: storvsc: Properly support Fibre Channel devices
For FC devices managed by this driver, atttach the appropriate transport template. This will allow us to create the appropriate sysfs files for these devices. With this we can publish the wwn for both the port and the node. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c | 100 +-- 1 files changed, 95 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 00bb4bd..b94d471 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -41,6 +41,7 @@ #include #include #include +#include /* * All wire protocol details (storage protocol between the guest and the host) @@ -397,6 +398,7 @@ static int storvsc_timeout = 180; static int msft_blist_flags = BLIST_TRY_VPD_PAGES; +static struct scsi_transport_template *fc_transport_template; static void storvsc_on_channel_callback(void *context); @@ -456,6 +458,11 @@ struct storvsc_device { /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; + /* +* Currently active port and node names for FC devices. +*/ + u64 node_name; + u64 port_name; }; struct hv_host_device { @@ -695,7 +702,26 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) vmbus_are_subchannels_present(device->channel); } -static int storvsc_channel_init(struct hv_device *device) +static void cache_wwn(struct storvsc_device *stor_device, + struct vstor_packet *vstor_packet) +{ + /* +* Cache the currently active port and node ww names. +*/ + if (vstor_packet->wwn_packet.primary_active) { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_port_wwn); + } else { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_port_wwn); + } +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) { struct storvsc_device *stor_device; struct storvsc_cmd_request *request; @@ -837,6 +863,40 @@ static int storvsc_channel_init(struct hv_device *device) stor_device->max_transfer_bytes = vstor_packet->storage_channel_properties.max_transfer_bytes; + if (!is_fc) + goto done; + + memset(vstor_packet, 0, sizeof(struct vstor_packet)); + vstor_packet->operation = VSTOR_OPERATION_FCHBA_DATA; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; + + ret = vmbus_sendpacket(device->channel, vstor_packet, + (sizeof(struct vstor_packet) - + vmscsi_size_delta), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + + if (ret != 0) + goto cleanup; + + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || + vstor_packet->status != 0) + goto cleanup; + + /* +* Cache the currently active port and node ww names. +*/ + cache_wwn(stor_device, vstor_packet); + +done: + memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; @@ -1076,6 +1136,12 @@ static void storvsc_on_receive(struct hv_device *device, schedule_work(&work->work); break; + case VSTOR_OPERATION_FCHBA_DATA: + stor_device = get_in_stor_device(device); + cache_wwn(stor_device, vstor_packet); + fc_host_node_name(stor_device->host) = stor_device->node_name; + fc_host_port_name(stor_device->host) = stor_device->port_name; + break; default: break; } @@ -1131,7 +1197,8 @@ static void storvsc_on_channel_callback(void *context) return; } -static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) +static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size, + bool is_fc) { struct vmstorage_channel_properties props; int ret; @@ -1148,7 +1215,7 @@ static i
[PATCH 3/4] scsi: storvsc: Refactor the code in storvsc_channel_init()
The function storvsc_channel_init() repeatedly interacts with the host to extract various channel properties. Refactor this code to eliminate code repetition. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Tested-by: Alex Ng --- drivers/scsi/storvsc_drv.c | 155 1 files changed, 57 insertions(+), 98 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index b94d471..6f18e94 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -721,29 +721,16 @@ static void cache_wwn(struct storvsc_device *stor_device, } } -static int storvsc_channel_init(struct hv_device *device, bool is_fc) +static int storvsc_execute_vstor_op(struct hv_device *device, + struct storvsc_cmd_request *request, + bool status_check) { - struct storvsc_device *stor_device; - struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; - int ret, t, i; - int max_chns; - bool process_sub_channels = false; - - stor_device = get_out_stor_device(device); - if (!stor_device) - return -ENODEV; + int ret, t; - request = &stor_device->init_request; vstor_packet = &request->vstor_packet; - /* -* Now, initiate the vsc/vsp initialization protocol on the open -* channel -*/ - memset(request, 0, sizeof(struct storvsc_cmd_request)); init_completion(&request->wait_event); - vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; ret = vmbus_sendpacket(device->channel, vstor_packet, @@ -753,27 +740,62 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + goto done; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); if (t == 0) { ret = -ETIMEDOUT; - goto cleanup; + goto done; } + if (!status_check) + goto done; + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || vstor_packet->status != 0) { ret = -EINVAL; - goto cleanup; + goto done; } +done: + return ret; +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) +{ + struct storvsc_device *stor_device; + struct storvsc_cmd_request *request; + struct vstor_packet *vstor_packet; + int ret, i; + int max_chns; + bool process_sub_channels = false; + + stor_device = get_out_stor_device(device); + if (!stor_device) + return -ENODEV; + + request = &stor_device->init_request; + vstor_packet = &request->vstor_packet; + + /* +* Now, initiate the vsc/vsp initialization protocol on the open +* channel +*/ + memset(request, 0, sizeof(struct storvsc_cmd_request)); + vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; + ret = storvsc_execute_vstor_op(device, request, true); + if (ret) + goto cleanup; + + /* +* Query host supported protocol version. +*/ for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { /* reuse the packet for version range supported */ memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; vstor_packet->version.major_minor = vmstor_protocols[i].protocol_version; @@ -783,20 +805,9 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) */ vstor_packet->version.revision = 0; - ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - vmscsi_size_delta), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) - goto cleanup; - - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; + ret = storvsc_execute_vstor_op(device, request, false); + if (ret) goto cleanup; - } if (
[PATCH 0/4] scsi: storvsc: Properly support FC hosts
Properly support FC hosts. Additional cleanup patches are also included. K. Y. Srinivasan (4): scsi: storvsc: Fix a bug in the layout of the hv_fc_wwn_packet scsi: storvsc: Properly support Fibre Channel devices scsi: storvsc: Refactor the code in storvsc_channel_init() scsi: storvsc: Tighten up the interrupt path drivers/scsi/storvsc_drv.c | 235 ++-- 1 files changed, 138 insertions(+), 97 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
[PATCH 1/1] scsi: storvsc: Fix a bug in the handling of SRB status flags
SRB status can have additional information. Mask these out before processing SRB status. This patch was sent as part of a collection of patches more than a year ago. While the rest of the patches in the set were comitted, this patch was not. I woulod like to thank Olaf for noticing that this patch was not committed upstream. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li --- drivers/scsi/storvsc_drv.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 072c11e..face2e6 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -349,11 +349,14 @@ enum storvsc_request_type { */ #define SRB_STATUS_AUTOSENSE_VALID 0x80 +#define SRB_STATUS_QUEUE_FROZEN0x40 #define SRB_STATUS_INVALID_LUN 0x20 #define SRB_STATUS_SUCCESS 0x01 #define SRB_STATUS_ABORTED 0x02 #define SRB_STATUS_ERROR 0x04 +#define SRB_STATUS(status) \ + (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) /* * This is the end of Protocol specific defines. */ @@ -858,7 +861,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, void (*process_err_fn)(struct work_struct *work); bool do_work = false; - switch (vm_srb->srb_status) { + switch (SRB_STATUS(vm_srb->srb_status)) { case SRB_STATUS_ERROR: /* * If there is an error; offline the device since all -- 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/1] storvsc: get rid of bounce buffer
From: Vitaly Kuznetsov Storvsc driver needs to ensure there are no 'holes' in the presented sg list (all segments in the middle of the list need to be of PAGE_SIZE). When a hole is detected storvsc driver creates a 'bounce sgl' without holes and copies data over with copy_{to,from}_bounce_buffer() functions. Setting virt_boundary_mask to PAGE_SIZE - 1 guarantees we'll never see such holes so we can significantly simplify the driver. This is also supposed to bring us some performance improvement for certain workloads as we eliminate copying. Reported-by: Radim Kr.má Signed-off-by: Vitaly Kuznetsov Reviewed-by: K. Y. Srinivasan Tested-by: Alex Ng Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 286 +--- 1 files changed, 5 insertions(+), 281 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 9c8db21..072c11e 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -393,9 +393,6 @@ static void storvsc_on_channel_callback(void *context); struct storvsc_cmd_request { struct scsi_cmnd *cmd; - unsigned int bounce_sgl_count; - struct scatterlist *bounce_sgl; - struct hv_device *device; /* Synchronize the request/response if needed */ @@ -586,241 +583,6 @@ get_in_err: } -static void destroy_bounce_buffer(struct scatterlist *sgl, - unsigned int sg_count) -{ - int i; - struct page *page_buf; - - for (i = 0; i < sg_count; i++) { - page_buf = sg_page((&sgl[i])); - if (page_buf != NULL) - __free_page(page_buf); - } - - kfree(sgl); -} - -static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count) -{ - int i; - - /* No need to check */ - if (sg_count < 2) - return -1; - - /* We have at least 2 sg entries */ - for (i = 0; i < sg_count; i++) { - if (i == 0) { - /* make sure 1st one does not have hole */ - if (sgl[i].offset + sgl[i].length != PAGE_SIZE) - return i; - } else if (i == sg_count - 1) { - /* make sure last one does not have hole */ - if (sgl[i].offset != 0) - return i; - } else { - /* make sure no hole in the middle */ - if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0) - return i; - } - } - return -1; -} - -static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl, - unsigned int sg_count, - unsigned int len, - int write) -{ - int i; - int num_pages; - struct scatterlist *bounce_sgl; - struct page *page_buf; - unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE); - - num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT; - - bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC); - if (!bounce_sgl) - return NULL; - - sg_init_table(bounce_sgl, num_pages); - for (i = 0; i < num_pages; i++) { - page_buf = alloc_page(GFP_ATOMIC); - if (!page_buf) - goto cleanup; - sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0); - } - - return bounce_sgl; - -cleanup: - destroy_bounce_buffer(bounce_sgl, num_pages); - return NULL; -} - -/* Assume the original sgl has enough room */ -static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, - struct scatterlist *bounce_sgl, - unsigned int orig_sgl_count, - unsigned int bounce_sgl_count) -{ - int i; - int j = 0; - unsigned long src, dest; - unsigned int srclen, destlen, copylen; - unsigned int total_copied = 0; - 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 = (unsigned long) - kmap_atomic(sg_page(cur_dest_sgl)) + - cur_dest_sgl->offset; - dest = dest_addr; - destlen = cur_dest_sgl->length; - - if (bounce_addr == 0) - bounce_addr = (unsigned long)kmap_atomic( -
[PATCH 2/3] scsi: introduce short_inquiry flag for broken host adapters
From: Vitaly Kuznetsov Some host adapters (e.g. Hyper-V storvsc) are known for not respecting the SPC-2/3/4 requirement for 'INQUIRY data (see table ...) shall contain at least 36 bytes'. As a result we get tons on 'scsi 0:7:1:1: scsi scan: INQUIRY result too short (5), using 36' messages on console. This can be problematic for slow consoles. Introduce short_inquiry host template flag to avoid printing error messages for such adapters. Signed-off-by: Vitaly Kuznetsov Reviewed-by: K. Y. Srinivasan Tested-by: Alex Ng Signed-off-by: K. Y. Srinivasan --- drivers/scsi/scsi_scan.c |7 --- drivers/scsi/storvsc_drv.c |1 + include/scsi/scsi_host.h |6 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 01ad016..5e325ce 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -701,9 +701,10 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, * strings. */ if (sdev->inquiry_len < 36) { - sdev_printk(KERN_INFO, sdev, - "scsi scan: INQUIRY result too short (%d)," - " using 36\n", sdev->inquiry_len); + if (!sdev->host->hostt->short_inquiry) + sdev_printk(KERN_INFO, sdev, + "scsi scan: INQUIRY result too short (%d)," + " using 36\n", sdev->inquiry_len); sdev->inquiry_len = 36; } diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 40c43ae..bce131b 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1781,6 +1781,7 @@ static struct scsi_host_template scsi_driver = { /* Make sure we dont get a sg segment crosses a page boundary */ .dma_boundary = PAGE_SIZE-1, .no_write_same =1, + .short_inquiry =1, }; enum { diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index e113c75..7b022af 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -454,6 +454,12 @@ struct scsi_host_template { unsigned no_async_abort:1; /* +* True if this host adapter returns short (<36 bytes) responses to +* some INQUIRY requests. +*/ + unsigned short_inquiry:1; + + /* * Countdown for host blocking with no commands outstanding. */ unsigned int max_host_blocked; -- 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 RESEND 3/3] storvsc: Don't set the SRB_FLAGS_QUEUE_ACTION_ENABLE flag
Don't set the SRB_FLAGS_QUEUE_ACTION_ENABLE flag since we are not specifying tags. Qlogic driver does not work correctly if the SRB_FLAGS_QUEUE_ACTION_ENABLE is set and no action tag is specified. Signed-off-by: K. Y. Srinivasan Tested-by: Vivek Yadav Reviewed-by: Long Li --- drivers/scsi/storvsc_drv.c |3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index bce131b..9c8db21 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1647,8 +1647,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) vm_srb->win8_extension.time_out_value = 60; vm_srb->win8_extension.srb_flags |= - (SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER); + SRB_FLAGS_DISABLE_SYNCH_TRANSFER; /* Build the SRB */ switch (scmnd->sc_data_direction) { -- 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/3] scsi_scan: don't dump trace when scsi_prep_async_scan() is called twice
From: Vitaly Kuznetsov The only user of scsi_prep_async_scan() is scsi_scan_host() and it handles the situation correctly. Move 'called twice' reporting to debug level as well. The issue is observed on Hyper-V: on any device add/remove event storvsc driver calls scsi_scan_host() and in case previous scan is still running we get the message and stack dump on console. Signed-off-by: Vitaly Kuznetsov Reviewed-by: K. Y. Srinivasan Tested-by: Alex Ng Signed-off-by: K. Y. Srinivasan --- drivers/scsi/scsi_scan.c |3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index f9f3f82..01ad016 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1712,8 +1712,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) return NULL; if (shost->async_scan) { - shost_printk(KERN_INFO, shost, "%s called twice\n", __func__); - dump_stack(); + shost_printk(KERN_DEBUG, shost, "%s called twice\n", __func__); return NULL; } -- 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/3] scsi: Some miscellaneous fixes
Some miscellaneous fixes. K. Y. Srinivasan (1): storvsc: Don't set the SRB_FLAGS_QUEUE_ACTION_ENABLE flag Vitaly Kuznetsov (2): scsi_scan: don't dump trace when scsi_prep_async_scan() is called twice scsi: introduce short_inquiry flag for broken host adapters drivers/scsi/scsi_scan.c | 10 +- drivers/scsi/storvsc_drv.c |4 ++-- include/scsi/scsi_host.h |6 ++ 3 files changed, 13 insertions(+), 7 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
[PATCH 1/1] storvsc: Don't set the SRB_FLAGS_QUEUE_ACTION_ENABLE flag
Don't set the SRB_FLAGS_QUEUE_ACTION_ENABLE flag since we are not specifying tags. Signed-off-by: K. Y. Srinivasan Cc: sta...@vger.kernel.org --- drivers/scsi/storvsc_drv.c |3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 40c43ae..ad8c4bc 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1647,8 +1647,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) vm_srb->win8_extension.time_out_value = 60; vm_srb->win8_extension.srb_flags |= - (SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER); + SRB_FLAGS_DISABLE_SYNCH_TRANSFER; /* Build the SRB */ switch (scmnd->sc_data_direction) { -- 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/1] scsi: storvsc: Use ARRAY_SIZE() to compute the elements in the protocol array
Rather than hard coding the number of elements in the array, use the ARRAY_SIZE() macro to compute the number of elements in the array. This would minimize the changes needed when we have to extend the protocols supported. This was suggested by Johannes Thumshirn . Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c |5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 64fa305..4dffc3b 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -226,9 +226,8 @@ struct vmstor_protocol { int vmscsi_size_delta; }; -#define VMSTOR_NUM_PROTOCOLS5 -const struct vmstor_protocol vmstor_protocols[VMSTOR_NUM_PROTOCOLS] = { +const struct vmstor_protocol vmstor_protocols[] = { { VMSTOR_PROTO_VERSION_WIN10, POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, @@ -959,7 +958,7 @@ static int storvsc_channel_init(struct hv_device *device) } - for (i = 0; i < VMSTOR_NUM_PROTOCOLS; i++) { + for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { /* reuse the packet for version range supported */ memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = -- 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/1] Drivers: hv: vmbus: fix init_vp_index() for reloading hv_netvsc
From: Dexuan Cui This fixes the recent commit 3b71107d73b16074afa7658f3f0fcf837aabfe24: Drivers: hv: vmbus: Further improve CPU affiliation logic Without the fix, reloading hv_netvsc hangs the guest. Signed-off-by: Dexuan Cui Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 17 + 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 3ab4753..8a4105c 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -204,6 +204,8 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) spin_lock_irqsave(&vmbus_connection.channel_lock, flags); list_del(&channel->listentry); spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); + + primary_channel = channel; } else { primary_channel = channel->primary_channel; spin_lock_irqsave(&primary_channel->lock, flags); @@ -211,6 +213,14 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) primary_channel->num_sc--; spin_unlock_irqrestore(&primary_channel->lock, flags); } + + /* +* We need to free the bit for init_vp_index() to work in the case +* of sub-channel, when we reload drivers like hv_netvsc. +*/ + cpumask_clear_cpu(channel->target_cpu, + &primary_channel->alloced_cpus_in_node); + free_channel(channel); } @@ -457,6 +467,13 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui continue; } + /* +* NOTE: in the case of sub-channel, we clear the sub-channel +* related bit(s) in primary->alloced_cpus_in_node in +* hv_process_channel_removal(), so when we reload drivers +* like hv_netvsc in SMP guest, here we're able to re-allocate +* bit from primary->alloced_cpus_in_node. +*/ if (!cpumask_test_cpu(cur_cpu, &primary->alloced_cpus_in_node)) { cpumask_set_cpu(cur_cpu, -- 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 RESEND V2 7/7] scsi: storvsc: Set the error code correctly in failure conditions
In the function storvsc_channel_init(), error code was not getting set correctly in some of the failure cases. Fix this issue. Signed-off-by: K. Y. Srinivasan Reported-by: Dan Carpenter --- drivers/scsi/storvsc_drv.c | 12 +--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 021cbdf..aac8297 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -960,8 +960,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } for (i = 0; i < VMSTOR_NUM_PROTOCOLS; i++) { @@ -1040,8 +1042,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } /* * Check to see if multi-channel support is there. @@ -1078,8 +1082,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } if (process_sub_channels) handle_multichannel_storage(device, max_chns); -- 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 RESEND V2 4/7] scsi: storvsc: use correct defaults for values determined by protocol negotiation
From: Keith Mange Use correct defaults for values determined by protocol negotiation, instead of resetting them with every scsi controller. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 33 +++-- 1 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index f29871e..6f38cdf 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -151,19 +151,17 @@ struct hv_fc_wwn_packet { /* * Sense buffer size changed in win8; have a run-time - * variable to track the size we should use. + * variable to track the size we should use. This value will + * likely change during protocol negotiation but it is valid + * to start by assuming pre-Win8. */ -static int sense_buffer_size; +static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; /* - * The size of the vmscsi_request has changed in win8. The - * additional size is because of new elements added to the - * structure. These elements are valid only when we are talking - * to a win8 host. - * Track the correction to size we need to apply. - */ - -static int vmscsi_size_delta; + * The storage protocol version is determined during the + * initial exchange with the host. It will indicate which + * storage functionality is available in the host. +*/ static int vmstor_proto_version; struct vmscsi_win8_extension { @@ -209,6 +207,17 @@ struct vmscsi_request { /* + * The size of the vmscsi_request has changed in win8. The + * additional size is because of new elements added to the + * structure. These elements are valid only when we are talking + * to a win8 host. + * Track the correction to size we need to apply. This value + * will likely change during protocol negotiation but it is + * valid to start by assuming pre-Win8. + */ +static int vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); + +/* * The list of storage protocols in order of preference. */ struct vmstor_protocol { @@ -1810,14 +1819,10 @@ static int storvsc_probe(struct hv_device *device, */ if (vmbus_proto_version < VERSION_WIN8) { - sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { - sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = 0; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; -- 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 RESEND V2 1/7] scsi: storvsc: Rather than look for sets of specific protocol versions, make decisions based on ranges.
From: Keith Mange Rather than look for sets of specific protocol versions, make decisions based on ranges. This will be safer and require fewer changes going forward as we add more storage protocol versions. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 11 +++ 1 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 3c6584f..582f3b5 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -988,8 +988,7 @@ static int storvsc_channel_init(struct hv_device *device) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; - if ((vmbus_proto_version != VERSION_WIN7) && - (vmbus_proto_version != VERSION_WS2008)) { + if (vmbus_proto_version >= VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; @@ -1758,9 +1757,7 @@ static int storvsc_probe(struct hv_device *device, * set state to properly communicate with the host. */ - switch (vmbus_proto_version) { - case VERSION_WS2008: - case VERSION_WIN7: + if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmstor_current_major = VMSTOR_WIN7_MAJOR; @@ -1768,8 +1765,7 @@ static int storvsc_probe(struct hv_device *device, max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; - break; - default: + } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; vmstor_current_major = VMSTOR_WIN8_MAJOR; @@ -1783,7 +1779,6 @@ static int storvsc_probe(struct hv_device *device, * VCPUs in the guest. */ max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); - break; } scsi_driver.can_queue = (max_outstanding_req_per_channel * -- 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 RESEND V2 6/7] scsi: storvsc: Allow write_same when host is windows 10
From: Keith Mange Allow WRITE_SAME for Windows10 and above hosts. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c |6 +- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 58fa47a..021cbdf 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1488,7 +1488,8 @@ static int storvsc_device_configure(struct scsi_device *sdevice) /* * If the host is WIN8 or WIN8 R2, claim conformance to SPC-3 -* if the device is a MSFT virtual device. +* if the device is a MSFT virtual device. If the host is +* WIN10 or newer, allow write_same. */ if (!strncmp(sdevice->vendor, "Msft", 4)) { switch (vmstor_proto_version) { @@ -1497,6 +1498,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice) sdevice->scsi_level = SCSI_SPC_3; break; } + + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN10) + sdevice->no_write_same = 0; } return 0; -- 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 RESEND V2 2/7] scsi: storvsc: Use a single value to track protocol versions
From: Keith Mange Use a single value to track protocol versions to simplify comparisons and to be consistent with vmbus version tracking. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 35 +-- 1 files changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 582f3b5..5f9d133 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -58,12 +58,11 @@ * Win8: 5.1 */ +#define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) MAJOR_) & 0xff) << 8) | \ + (((MINOR_) & 0xff))) -#define VMSTOR_WIN7_MAJOR 4 -#define VMSTOR_WIN7_MINOR 2 - -#define VMSTOR_WIN8_MAJOR 5 -#define VMSTOR_WIN8_MINOR 1 +#define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) +#define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) /* Packet structure describing virtual storage requests. */ @@ -161,8 +160,7 @@ static int sense_buffer_size; */ static int vmscsi_size_delta; -static int vmstor_current_major; -static int vmstor_current_minor; +static int vmstor_proto_version; struct vmscsi_win8_extension { /* @@ -481,18 +479,6 @@ done: kfree(wrk); } -/* - * Major/minor macros. Minor version is in LSB, meaning that earlier flat - * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). - */ - -static inline u16 storvsc_get_version(u8 major, u8 minor) -{ - u16 version; - - version = ((major << 8) | minor); - return version; -} /* * We can get incoming messages from the host that are not in response to @@ -930,8 +916,7 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = - storvsc_get_version(vmstor_current_major, vmstor_current_minor); + vstor_packet->version.major_minor = vmstor_proto_version; /* * The revision number is only used in Windows; set it to 0. @@ -1562,7 +1547,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) u32 payload_sz; u32 length; - if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { + if (vmstor_proto_version <= VMSTOR_PROTO_VERSION_WIN8) { /* * On legacy hosts filter unimplemented commands. * Future hosts are expected to correctly handle @@ -1760,16 +1745,14 @@ static int storvsc_probe(struct hv_device *device, if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); - vmstor_current_major = VMSTOR_WIN7_MAJOR; - vmstor_current_minor = VMSTOR_WIN7_MINOR; + vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN7; max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; - vmstor_current_major = VMSTOR_WIN8_MAJOR; - vmstor_current_minor = VMSTOR_WIN8_MINOR; + vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN8; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; -- 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 RESEND V2 5/7] scsi: storvsc: use storage protocol version to determine storage capabilities
From: Keith Mange Use storage protocol version instead of vmbus protocol version when determining storage capabilities. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 6f38cdf..58fa47a 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1049,7 +1049,7 @@ static int storvsc_channel_init(struct hv_device *device) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; - if (vmbus_proto_version >= VERSION_WIN8) { + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; @@ -1491,9 +1491,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice) * if the device is a MSFT virtual device. */ if (!strncmp(sdevice->vendor, "Msft", 4)) { - switch (vmbus_proto_version) { - case VERSION_WIN8: - case VERSION_WIN8_1: + switch (vmstor_proto_version) { + case VMSTOR_PROTO_VERSION_WIN8: + case VMSTOR_PROTO_VERSION_WIN8_1: sdevice->scsi_level = SCSI_SPC_3; break; } -- 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 RESEND V2 3/7] scsi: storvsc: Untangle the storage protocol negotiation from the vmbus protocol negotiation.
From: Keith Mange Currently we are making decisions based on vmbus protocol versions that have been negotiated; use storage potocol versions instead. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 109 +++- 1 files changed, 87 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5f9d133..f29871e 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -56,14 +56,18 @@ * V1 RC > 2008/1/31: 2.0 * Win7: 4.2 * Win8: 5.1 + * Win8.1: 6.0 + * Win10: 6.2 */ #define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) MAJOR_) & 0xff) << 8) | \ (((MINOR_) & 0xff))) +#define VMSTOR_PROTO_VERSION_WIN6 VMSTOR_PROTO_VERSION(2, 0) #define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) #define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) - +#define VMSTOR_PROTO_VERSION_WIN8_1VMSTOR_PROTO_VERSION(6, 0) +#define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2) /* Packet structure describing virtual storage requests. */ enum vstor_packet_operation { @@ -205,6 +209,46 @@ struct vmscsi_request { /* + * The list of storage protocols in order of preference. + */ +struct vmstor_protocol { + int protocol_version; + int sense_buffer_size; + int vmscsi_size_delta; +}; + +#define VMSTOR_NUM_PROTOCOLS5 + +const struct vmstor_protocol vmstor_protocols[VMSTOR_NUM_PROTOCOLS] = { + { + VMSTOR_PROTO_VERSION_WIN10, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN8_1, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN8, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN7, + PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, + sizeof(struct vmscsi_win8_extension), + }, + { + VMSTOR_PROTO_VERSION_WIN6, + PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, + sizeof(struct vmscsi_win8_extension), + } +}; + + +/* * This structure is sent during the intialization phase to get the different * properties of the channel. */ @@ -871,7 +915,7 @@ static int storvsc_channel_init(struct hv_device *device) struct storvsc_device *stor_device; struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; - int ret, t; + int ret, t, i; int max_chns; bool process_sub_channels = false; @@ -911,36 +955,59 @@ static int storvsc_channel_init(struct hv_device *device) goto cleanup; - /* reuse the packet for version range supported */ - memset(vstor_packet, 0, sizeof(struct vstor_packet)); - vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; + for (i = 0; i < VMSTOR_NUM_PROTOCOLS; i++) { + /* reuse the packet for version range supported */ + memset(vstor_packet, 0, sizeof(struct vstor_packet)); + vstor_packet->operation = + VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = vmstor_proto_version; + vstor_packet->version.major_minor = + vmstor_protocols[i].protocol_version; - /* -* The revision number is only used in Windows; set it to 0. -*/ - vstor_packet->version.revision = 0; + /* +* The revision number is only used in Windows; set it to 0. +*/ + vstor_packet->version.revision = 0; - ret = vmbus_sendpacket(device->channel, vstor_packet, + ret = vmbus_sendpacket(device->channel, vstor_packet, (sizeof(struct vstor_packet) - vmscsi_size_delta), (unsigned long)request, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) - goto cleanup; + if (ret != 0) + goto cleanup; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + +
[PATCH RESEND V2 0/7] scsi: storvsc: Some miscellaneous cleanup
Cleanup version handling as well as base feature detection on storage version as opposed to host version. In this version, I have addressed comments from Dan Carpenter. K. Y. Srinivasan (1): scsi: storvsc: Set the error code correctly in failure conditions Keith Mange (6): scsi: storvsc: Rather than look for sets of specific protocol versions, make decisions based on ranges. scsi: storvsc: Use a single value to track protocol versions scsi: storvsc: Untangle the storage protocol negotiation from the vmbus protocol negotiation. scsi: storvsc: use correct defaults for values determined by protocol negotiation scsi: storvsc: use storage protocol version to determine storage capabilities scsi: storvsc: Allow write_same when host is windows 10 drivers/scsi/storvsc_drv.c | 206 1 files changed, 132 insertions(+), 74 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
[PATCH V2 4/7] scsi: storvsc: use correct defaults for values determined by protocol negotiation
From: Keith Mange Use correct defaults for values determined by protocol negotiation, instead of resetting them with every scsi controller. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 33 +++-- 1 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index f29871e..6f38cdf 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -151,19 +151,17 @@ struct hv_fc_wwn_packet { /* * Sense buffer size changed in win8; have a run-time - * variable to track the size we should use. + * variable to track the size we should use. This value will + * likely change during protocol negotiation but it is valid + * to start by assuming pre-Win8. */ -static int sense_buffer_size; +static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; /* - * The size of the vmscsi_request has changed in win8. The - * additional size is because of new elements added to the - * structure. These elements are valid only when we are talking - * to a win8 host. - * Track the correction to size we need to apply. - */ - -static int vmscsi_size_delta; + * The storage protocol version is determined during the + * initial exchange with the host. It will indicate which + * storage functionality is available in the host. +*/ static int vmstor_proto_version; struct vmscsi_win8_extension { @@ -209,6 +207,17 @@ struct vmscsi_request { /* + * The size of the vmscsi_request has changed in win8. The + * additional size is because of new elements added to the + * structure. These elements are valid only when we are talking + * to a win8 host. + * Track the correction to size we need to apply. This value + * will likely change during protocol negotiation but it is + * valid to start by assuming pre-Win8. + */ +static int vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); + +/* * The list of storage protocols in order of preference. */ struct vmstor_protocol { @@ -1810,14 +1819,10 @@ static int storvsc_probe(struct hv_device *device, */ if (vmbus_proto_version < VERSION_WIN8) { - sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { - sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = 0; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; -- 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 V2 2/7] scsi: storvsc: Use a single value to track protocol versions
From: Keith Mange Use a single value to track protocol versions to simplify comparisons and to be consistent with vmbus version tracking. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 35 +-- 1 files changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 582f3b5..5f9d133 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -58,12 +58,11 @@ * Win8: 5.1 */ +#define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) MAJOR_) & 0xff) << 8) | \ + (((MINOR_) & 0xff))) -#define VMSTOR_WIN7_MAJOR 4 -#define VMSTOR_WIN7_MINOR 2 - -#define VMSTOR_WIN8_MAJOR 5 -#define VMSTOR_WIN8_MINOR 1 +#define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) +#define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) /* Packet structure describing virtual storage requests. */ @@ -161,8 +160,7 @@ static int sense_buffer_size; */ static int vmscsi_size_delta; -static int vmstor_current_major; -static int vmstor_current_minor; +static int vmstor_proto_version; struct vmscsi_win8_extension { /* @@ -481,18 +479,6 @@ done: kfree(wrk); } -/* - * Major/minor macros. Minor version is in LSB, meaning that earlier flat - * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). - */ - -static inline u16 storvsc_get_version(u8 major, u8 minor) -{ - u16 version; - - version = ((major << 8) | minor); - return version; -} /* * We can get incoming messages from the host that are not in response to @@ -930,8 +916,7 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = - storvsc_get_version(vmstor_current_major, vmstor_current_minor); + vstor_packet->version.major_minor = vmstor_proto_version; /* * The revision number is only used in Windows; set it to 0. @@ -1562,7 +1547,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) u32 payload_sz; u32 length; - if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { + if (vmstor_proto_version <= VMSTOR_PROTO_VERSION_WIN8) { /* * On legacy hosts filter unimplemented commands. * Future hosts are expected to correctly handle @@ -1760,16 +1745,14 @@ static int storvsc_probe(struct hv_device *device, if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); - vmstor_current_major = VMSTOR_WIN7_MAJOR; - vmstor_current_minor = VMSTOR_WIN7_MINOR; + vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN7; max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; - vmstor_current_major = VMSTOR_WIN8_MAJOR; - vmstor_current_minor = VMSTOR_WIN8_MINOR; + vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN8; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; -- 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 V2 6/7] scsi: storvsc: Allow write_same when host is windows 10
From: Keith Mange Allow WRITE_SAME for Windows10 and above hosts. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c |6 +- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 58fa47a..021cbdf 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1488,7 +1488,8 @@ static int storvsc_device_configure(struct scsi_device *sdevice) /* * If the host is WIN8 or WIN8 R2, claim conformance to SPC-3 -* if the device is a MSFT virtual device. +* if the device is a MSFT virtual device. If the host is +* WIN10 or newer, allow write_same. */ if (!strncmp(sdevice->vendor, "Msft", 4)) { switch (vmstor_proto_version) { @@ -1497,6 +1498,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice) sdevice->scsi_level = SCSI_SPC_3; break; } + + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN10) + sdevice->no_write_same = 0; } return 0; -- 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 V2 7/7] scsi: storvsc: Set the error code correctly in failure conditions
In the function storvsc_channel_init(), error code was not getting set correctly in some of the failure cases. Fix this issue. Signed-off-by: K. Y. Srinivasan Reported-by: Dan Carpenter --- drivers/scsi/storvsc_drv.c | 12 +--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 021cbdf..aac8297 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -960,8 +960,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } for (i = 0; i < VMSTOR_NUM_PROTOCOLS; i++) { @@ -1040,8 +1042,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } /* * Check to see if multi-channel support is there. @@ -1078,8 +1082,10 @@ static int storvsc_channel_init(struct hv_device *device) } if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) + vstor_packet->status != 0) { + ret = -EINVAL; goto cleanup; + } if (process_sub_channels) handle_multichannel_storage(device, max_chns); -- 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 V2 3/7] scsi: storvsc: Untangle the storage protocol negotiation from the vmbus protocol negotiation.
From: Keith Mange Currently we are making decisions based on vmbus protocol versions that have been negotiated; use storage potocol versions instead. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 109 +++- 1 files changed, 87 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5f9d133..f29871e 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -56,14 +56,18 @@ * V1 RC > 2008/1/31: 2.0 * Win7: 4.2 * Win8: 5.1 + * Win8.1: 6.0 + * Win10: 6.2 */ #define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) MAJOR_) & 0xff) << 8) | \ (((MINOR_) & 0xff))) +#define VMSTOR_PROTO_VERSION_WIN6 VMSTOR_PROTO_VERSION(2, 0) #define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) #define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) - +#define VMSTOR_PROTO_VERSION_WIN8_1VMSTOR_PROTO_VERSION(6, 0) +#define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2) /* Packet structure describing virtual storage requests. */ enum vstor_packet_operation { @@ -205,6 +209,46 @@ struct vmscsi_request { /* + * The list of storage protocols in order of preference. + */ +struct vmstor_protocol { + int protocol_version; + int sense_buffer_size; + int vmscsi_size_delta; +}; + +#define VMSTOR_NUM_PROTOCOLS5 + +const struct vmstor_protocol vmstor_protocols[VMSTOR_NUM_PROTOCOLS] = { + { + VMSTOR_PROTO_VERSION_WIN10, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN8_1, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN8, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN7, + PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, + sizeof(struct vmscsi_win8_extension), + }, + { + VMSTOR_PROTO_VERSION_WIN6, + PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, + sizeof(struct vmscsi_win8_extension), + } +}; + + +/* * This structure is sent during the intialization phase to get the different * properties of the channel. */ @@ -871,7 +915,7 @@ static int storvsc_channel_init(struct hv_device *device) struct storvsc_device *stor_device; struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; - int ret, t; + int ret, t, i; int max_chns; bool process_sub_channels = false; @@ -911,36 +955,59 @@ static int storvsc_channel_init(struct hv_device *device) goto cleanup; - /* reuse the packet for version range supported */ - memset(vstor_packet, 0, sizeof(struct vstor_packet)); - vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; + for (i = 0; i < VMSTOR_NUM_PROTOCOLS; i++) { + /* reuse the packet for version range supported */ + memset(vstor_packet, 0, sizeof(struct vstor_packet)); + vstor_packet->operation = + VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = vmstor_proto_version; + vstor_packet->version.major_minor = + vmstor_protocols[i].protocol_version; - /* -* The revision number is only used in Windows; set it to 0. -*/ - vstor_packet->version.revision = 0; + /* +* The revision number is only used in Windows; set it to 0. +*/ + vstor_packet->version.revision = 0; - ret = vmbus_sendpacket(device->channel, vstor_packet, + ret = vmbus_sendpacket(device->channel, vstor_packet, (sizeof(struct vstor_packet) - vmscsi_size_delta), (unsigned long)request, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) - goto cleanup; + if (ret != 0) + goto cleanup; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + +
[PATCH V2 1/7] scsi: storvsc: Rather than look for sets of specific protocol versions, make decisions based on ranges.
From: Keith Mange Rather than look for sets of specific protocol versions, make decisions based on ranges. This will be safer and require fewer changes going forward as we add more storage protocol versions. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 11 +++ 1 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 3c6584f..582f3b5 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -988,8 +988,7 @@ static int storvsc_channel_init(struct hv_device *device) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; - if ((vmbus_proto_version != VERSION_WIN7) && - (vmbus_proto_version != VERSION_WS2008)) { + if (vmbus_proto_version >= VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; @@ -1758,9 +1757,7 @@ static int storvsc_probe(struct hv_device *device, * set state to properly communicate with the host. */ - switch (vmbus_proto_version) { - case VERSION_WS2008: - case VERSION_WIN7: + if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmstor_current_major = VMSTOR_WIN7_MAJOR; @@ -1768,8 +1765,7 @@ static int storvsc_probe(struct hv_device *device, max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; - break; - default: + } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; vmstor_current_major = VMSTOR_WIN8_MAJOR; @@ -1783,7 +1779,6 @@ static int storvsc_probe(struct hv_device *device, * VCPUs in the guest. */ max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); - break; } scsi_driver.can_queue = (max_outstanding_req_per_channel * -- 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 V2 5/7] scsi: storvsc: use storage protocol version to determine storage capabilities
From: Keith Mange Use storage protocol version instead of vmbus protocol version when determining storage capabilities. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 6f38cdf..58fa47a 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1049,7 +1049,7 @@ static int storvsc_channel_init(struct hv_device *device) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; - if (vmbus_proto_version >= VERSION_WIN8) { + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; @@ -1491,9 +1491,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice) * if the device is a MSFT virtual device. */ if (!strncmp(sdevice->vendor, "Msft", 4)) { - switch (vmbus_proto_version) { - case VERSION_WIN8: - case VERSION_WIN8_1: + switch (vmstor_proto_version) { + case VMSTOR_PROTO_VERSION_WIN8: + case VMSTOR_PROTO_VERSION_WIN8_1: sdevice->scsi_level = SCSI_SPC_3; break; } -- 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 V2 0/7] scsi: storvsc: Some miscellaneous cleanup
Cleanup version handling as well as base feature detection on storage version as opposed to host version. In this version, I have addressed comments from Dan Carpenter. K. Y. Srinivasan (1): scsi: storvsc: Set the error code correctly in failure conditions Keith Mange (6): scsi: storvsc: Rather than look for sets of specific protocol versions, make decisions based on ranges. scsi: storvsc: Use a single value to track protocol versions scsi: storvsc: Untangle the storage protocol negotiation from the vmbus protocol negotiation. scsi: storvsc: use correct defaults for values determined by protocol negotiation scsi: storvsc: use storage protocol version to determine storage capabilities scsi: storvsc: Allow write_same when host is windows 10 drivers/scsi/storvsc_drv.c | 206 1 files changed, 132 insertions(+), 74 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
[PATCH 6/6] scsi: storvsc: Allow write_same when host is windows 10
From: keith.ma...@microsoft.com Allow WRITE_SAME for Windows10 and above hosts. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c |6 +- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 58fa47a..021cbdf 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1488,7 +1488,8 @@ static int storvsc_device_configure(struct scsi_device *sdevice) /* * If the host is WIN8 or WIN8 R2, claim conformance to SPC-3 -* if the device is a MSFT virtual device. +* if the device is a MSFT virtual device. If the host is +* WIN10 or newer, allow write_same. */ if (!strncmp(sdevice->vendor, "Msft", 4)) { switch (vmstor_proto_version) { @@ -1497,6 +1498,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice) sdevice->scsi_level = SCSI_SPC_3; break; } + + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN10) + sdevice->no_write_same = 0; } return 0; -- 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] scsi: storvsc: Rather than look for sets of specific protocol versions, make decisions based on ranges.
From: keith.ma...@microsoft.com Rather than look for sets of specific protocol versions, make decisions based on ranges. This will be safer and require fewer changes going forward as we add more storage protocol versions. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 11 +++ 1 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 3c6584f..582f3b5 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -988,8 +988,7 @@ static int storvsc_channel_init(struct hv_device *device) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; - if ((vmbus_proto_version != VERSION_WIN7) && - (vmbus_proto_version != VERSION_WS2008)) { + if (vmbus_proto_version >= VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; @@ -1758,9 +1757,7 @@ static int storvsc_probe(struct hv_device *device, * set state to properly communicate with the host. */ - switch (vmbus_proto_version) { - case VERSION_WS2008: - case VERSION_WIN7: + if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmstor_current_major = VMSTOR_WIN7_MAJOR; @@ -1768,8 +1765,7 @@ static int storvsc_probe(struct hv_device *device, max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; - break; - default: + } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; vmstor_current_major = VMSTOR_WIN8_MAJOR; @@ -1783,7 +1779,6 @@ static int storvsc_probe(struct hv_device *device, * VCPUs in the guest. */ max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); - break; } scsi_driver.can_queue = (max_outstanding_req_per_channel * -- 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] hv:scsi:Untangle the storage protocol negotiation from the vmbus protocol negotiation.
From: keith.ma...@microsoft.com Currently we are making decisions based on vmbus protocol versions that have been negotiated; use storage potocol versions instead. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 109 +++- 1 files changed, 87 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5f9d133..f29871e 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -56,14 +56,18 @@ * V1 RC > 2008/1/31: 2.0 * Win7: 4.2 * Win8: 5.1 + * Win8.1: 6.0 + * Win10: 6.2 */ #define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) MAJOR_) & 0xff) << 8) | \ (((MINOR_) & 0xff))) +#define VMSTOR_PROTO_VERSION_WIN6 VMSTOR_PROTO_VERSION(2, 0) #define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) #define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) - +#define VMSTOR_PROTO_VERSION_WIN8_1VMSTOR_PROTO_VERSION(6, 0) +#define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2) /* Packet structure describing virtual storage requests. */ enum vstor_packet_operation { @@ -205,6 +209,46 @@ struct vmscsi_request { /* + * The list of storage protocols in order of preference. + */ +struct vmstor_protocol { + int protocol_version; + int sense_buffer_size; + int vmscsi_size_delta; +}; + +#define VMSTOR_NUM_PROTOCOLS5 + +const struct vmstor_protocol vmstor_protocols[VMSTOR_NUM_PROTOCOLS] = { + { + VMSTOR_PROTO_VERSION_WIN10, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN8_1, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN8, + POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, + 0 + }, + { + VMSTOR_PROTO_VERSION_WIN7, + PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, + sizeof(struct vmscsi_win8_extension), + }, + { + VMSTOR_PROTO_VERSION_WIN6, + PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, + sizeof(struct vmscsi_win8_extension), + } +}; + + +/* * This structure is sent during the intialization phase to get the different * properties of the channel. */ @@ -871,7 +915,7 @@ static int storvsc_channel_init(struct hv_device *device) struct storvsc_device *stor_device; struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; - int ret, t; + int ret, t, i; int max_chns; bool process_sub_channels = false; @@ -911,36 +955,59 @@ static int storvsc_channel_init(struct hv_device *device) goto cleanup; - /* reuse the packet for version range supported */ - memset(vstor_packet, 0, sizeof(struct vstor_packet)); - vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->flags = REQUEST_COMPLETION_FLAG; + for (i = 0; i < VMSTOR_NUM_PROTOCOLS; i++) { + /* reuse the packet for version range supported */ + memset(vstor_packet, 0, sizeof(struct vstor_packet)); + vstor_packet->operation = + VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = vmstor_proto_version; + vstor_packet->version.major_minor = + vmstor_protocols[i].protocol_version; - /* -* The revision number is only used in Windows; set it to 0. -*/ - vstor_packet->version.revision = 0; + /* +* The revision number is only used in Windows; set it to 0. +*/ + vstor_packet->version.revision = 0; - ret = vmbus_sendpacket(device->channel, vstor_packet, + ret = vmbus_sendpacket(device->channel, vstor_packet, (sizeof(struct vstor_packet) - vmscsi_size_delta), (unsigned long)request, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) - goto cleanup; + if (ret != 0) + goto cleanup; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + if (t == 0) { + ret = -ETIMEDOUT; + goto cleanup; + } + +
[PATCH 4/6] scsi: storvsc: use correct defaults for values determined by protocol negotiation
From: keith.ma...@microsoft.com Use correct defaults for values determined by protocol negotiation, instead of resetting them with every scsi controller. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 33 +++-- 1 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index f29871e..6f38cdf 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -151,19 +151,17 @@ struct hv_fc_wwn_packet { /* * Sense buffer size changed in win8; have a run-time - * variable to track the size we should use. + * variable to track the size we should use. This value will + * likely change during protocol negotiation but it is valid + * to start by assuming pre-Win8. */ -static int sense_buffer_size; +static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; /* - * The size of the vmscsi_request has changed in win8. The - * additional size is because of new elements added to the - * structure. These elements are valid only when we are talking - * to a win8 host. - * Track the correction to size we need to apply. - */ - -static int vmscsi_size_delta; + * The storage protocol version is determined during the + * initial exchange with the host. It will indicate which + * storage functionality is available in the host. +*/ static int vmstor_proto_version; struct vmscsi_win8_extension { @@ -209,6 +207,17 @@ struct vmscsi_request { /* + * The size of the vmscsi_request has changed in win8. The + * additional size is because of new elements added to the + * structure. These elements are valid only when we are talking + * to a win8 host. + * Track the correction to size we need to apply. This value + * will likely change during protocol negotiation but it is + * valid to start by assuming pre-Win8. + */ +static int vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); + +/* * The list of storage protocols in order of preference. */ struct vmstor_protocol { @@ -1810,14 +1819,10 @@ static int storvsc_probe(struct hv_device *device, */ if (vmbus_proto_version < VERSION_WIN8) { - sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { - sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = 0; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; -- 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] scsi: storvsc: use storage protocol version to determine storage capabilities
From: keith.ma...@microsoft.com Use storage protocol version instead of vmbus protocol version when determining storage capabilities. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 6f38cdf..58fa47a 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1049,7 +1049,7 @@ static int storvsc_channel_init(struct hv_device *device) * support multi-channel. */ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; - if (vmbus_proto_version >= VERSION_WIN8) { + if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) { if (vstor_packet->storage_channel_properties.flags & STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) process_sub_channels = true; @@ -1491,9 +1491,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice) * if the device is a MSFT virtual device. */ if (!strncmp(sdevice->vendor, "Msft", 4)) { - switch (vmbus_proto_version) { - case VERSION_WIN8: - case VERSION_WIN8_1: + switch (vmstor_proto_version) { + case VMSTOR_PROTO_VERSION_WIN8: + case VMSTOR_PROTO_VERSION_WIN8_1: sdevice->scsi_level = SCSI_SPC_3; break; } -- 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 2/6] scsi: storvsc: Use a single value to track protocol versions
From: keith.ma...@microsoft.com Use a single value to track protocol versions to simplify comparisons and to be consistent with vmbus version tracking. Tested-by: Alex Ng Signed-off-by: Keith Mange Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 35 +-- 1 files changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 582f3b5..5f9d133 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -58,12 +58,11 @@ * Win8: 5.1 */ +#define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) MAJOR_) & 0xff) << 8) | \ + (((MINOR_) & 0xff))) -#define VMSTOR_WIN7_MAJOR 4 -#define VMSTOR_WIN7_MINOR 2 - -#define VMSTOR_WIN8_MAJOR 5 -#define VMSTOR_WIN8_MINOR 1 +#define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) +#define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) /* Packet structure describing virtual storage requests. */ @@ -161,8 +160,7 @@ static int sense_buffer_size; */ static int vmscsi_size_delta; -static int vmstor_current_major; -static int vmstor_current_minor; +static int vmstor_proto_version; struct vmscsi_win8_extension { /* @@ -481,18 +479,6 @@ done: kfree(wrk); } -/* - * Major/minor macros. Minor version is in LSB, meaning that earlier flat - * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). - */ - -static inline u16 storvsc_get_version(u8 major, u8 minor) -{ - u16 version; - - version = ((major << 8) | minor); - return version; -} /* * We can get incoming messages from the host that are not in response to @@ -930,8 +916,7 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = - storvsc_get_version(vmstor_current_major, vmstor_current_minor); + vstor_packet->version.major_minor = vmstor_proto_version; /* * The revision number is only used in Windows; set it to 0. @@ -1562,7 +1547,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) u32 payload_sz; u32 length; - if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { + if (vmstor_proto_version <= VMSTOR_PROTO_VERSION_WIN8) { /* * On legacy hosts filter unimplemented commands. * Future hosts are expected to correctly handle @@ -1760,16 +1745,14 @@ static int storvsc_probe(struct hv_device *device, if (vmbus_proto_version < VERSION_WIN8) { sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); - vmstor_current_major = VMSTOR_WIN7_MAJOR; - vmstor_current_minor = VMSTOR_WIN7_MINOR; + vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN7; max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_targets = STORVSC_IDE_MAX_TARGETS; max_channels = STORVSC_IDE_MAX_CHANNELS; } else { sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; - vmstor_current_major = VMSTOR_WIN8_MAJOR; - vmstor_current_minor = VMSTOR_WIN8_MINOR; + vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN8; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; -- 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] scsi: storvsc: Some miscellaneous cleanup
Cleanup version handling as well as base feature detection on storage version as opposed to host version. keith.ma...@microsoft.com (6): scsi: storvsc: Rather than look for sets of specific protocol versions, make decisions based on ranges. scsi: storvsc: Use a single value to track protocol versions hv:scsi:Untangle the storage protocol negotiation from the vmbus protocol negotiation. scsi: storvsc: use correct defaults for values determined by protocol negotiation scsi: storvsc: use storage protocol version to determine storage capabilities scsi: storvsc: Allow write_same when host is windows 10 drivers/scsi/storvsc_drv.c | 194 1 files changed, 123 insertions(+), 71 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
[PATCH 1/1] scsi: storvsc: Set the SRB flags correctly when no data transfer is needed
Set the SRB flags correctly when there is no data transfer. Cc: Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li --- drivers/scsi/storvsc_drv.c |3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index d9dad90..3c6584f 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1600,8 +1600,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) break; default: vm_srb->data_in = UNKNOWN_TYPE; - vm_srb->win8_extension.srb_flags |= (SRB_FLAGS_DATA_IN | -SRB_FLAGS_DATA_OUT); + vm_srb->win8_extension.srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; break; } -- 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/1] scsi: storvsc: Set the SRB flags correctly when no data transfer is needed
Set the SRB flags correctly when there is no data transfer. Cc: Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li --- drivers/scsi/storvsc_drv.c |3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index d9dad90..3c6584f 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1600,8 +1600,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) break; default: vm_srb->data_in = UNKNOWN_TYPE; - vm_srb->win8_extension.srb_flags |= (SRB_FLAGS_DATA_IN | -SRB_FLAGS_DATA_OUT); + vm_srb->win8_extension.srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; break; } -- 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 V2 3/7] scsi: storvsc: Always send on the selected outgoing channel
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 Reviewed-by: Long Li --- 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 7f569f9..0ba7f2c 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 -- 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 V2 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 Reviewed-by: Long Li Cc: --- 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 cdf048b..f8e4dd9 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 -- 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 V2 1/7] scsi: storvsc: Increase the ring buffer size
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 Reviewed-by: Long Li --- 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 -- 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 V2 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 Reviewed-by: Long Li --- V2: Got rid of double assignment. Olaf Hering drivers/scsi/storvsc_drv.c | 99 +-- 1 files changed, 57 insertions(+), 42 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index f8e4dd9..4156e29 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,38 @@ 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 +685,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].off
[PATCH V2 4/7] scsi: storvsc: Retrieve information about the capability of the target
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 Reviewed-by: Long Li --- 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 0ba7f2c..cdf048b 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 -- 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 V2 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
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 Reviewed-by: Long Li --- v2: Fixed a bug in computing queue depth: Venkatesh Srinivas 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..7f569f9 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_REQUESTS200 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 -- 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 7/7] scsi: storvsc: Set the tablesize based on the information given by the host
Set the tablesize based on the information given by the host. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li Tested-by: Long Li --- 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 4156e29..d9dad90 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; }; @@ -1103,6 +1106,8 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) struct Scsi_Host *host; struct storvsc_device *stor_dev; struct hv_device *dev = host_dev->dev; + u32 payload_sz = cmd_request->payload_sz; + void *payload = cmd_request->payload; stor_dev = get_in_stor_device(dev); host = stor_dev->host; @@ -1132,10 +1137,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 (payload_sz > + sizeof(struct vmbus_channel_packet_multipage_buffer)) + kfree(payload); } static void storvsc_on_io_completion(struct hv_device *device, @@ -1337,7 +1346,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; @@ -1369,13 +1378,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), @@ -1549,6 +1559,9 @@ 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 length; if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { /* @@ -1602,48 +1615,71 @@ 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;
[PATCH V2 0/7] scsi: storvsc: Miscellaneous enhancements and fixes
This patch-set addresses perf issues discovered on the Azure storage stack. These patches also fix a couple of bugs. As in the first version of this patch-set, some of the patches are simply a resend. I have bumped up the version number of all patches though. In this version, I have addressed issues raised by Olaf Hering , Long Li and Venkatesh Srinivas 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 | 232 1 files changed, 149 insertions(+), 83 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
[PATCH RESEND 1/7] scsi: storvsc: Increase the ring buffer size
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 Reviewed-by: Long Li --- 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 -- 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 RESEND 4/7] scsi: storvsc: Retrieve information about the capability of the target
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 Reviewed-by: Long Li --- 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 -- 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/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 --- 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->offs
[PATCH RESEND 2/7] scsi: storvsc: Size the queue depth based on the ringbuffer size
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 Reviewed-by: Long Li --- 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_REQUESTS200 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 -- 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 V2 7/7] scsi: storvsc: Set the tablesize based on the information given by the host
Set the tablesize based on the information given by the host. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li --- 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);
[PATCH RESEND 3/7] scsi: storvsc: Always send on the selected outgoing channel
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 Reviewed-by: Long Li --- 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 -- 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/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 Cc: --- 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 -- 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/7] scsi: storvsc: Miscellaneous enhancements and fixes
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 -- 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/3] scsi: storvsc: Retrieve information about the capability of the target
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 Reviewed-by: Long Li --- 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 -- 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/3] scsi: storvsc: Enable clustering
Signed-off-by: K. Y. Srinivasan --- 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 a36c232..d7ebf00 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1693,7 +1693,7 @@ static struct scsi_host_template scsi_driver = { .slave_configure = storvsc_device_configure, .cmd_per_lun = 255, .this_id = -1, - .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, -- 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 2/3] scsi: storvsc: Set the tablesize based on the information given by the host
Set the tablesize based on what the host has informed us. Signed-off-by: K. Y. Srinivasan Reviewed-by: Long Li --- drivers/scsi/storvsc_drv.c | 70 ++- 1 files changed, 55 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5c13eec..a36c232 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; }; @@ -1119,10 +1122,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, @@ -1324,7 +1331,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; @@ -1356,13 +1363,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), @@ -1535,6 +1543,10 @@ 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 vmbus_packet_mpb_array *payload; + u32 payload_sz; + u32 pfn_cnt; + u32 length; if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { /* @@ -1588,7 +1600,11 @@ 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); + sgl = (struct scatterlist *)scsi_sglist(scmnd); + length = scsi_bufflen(scmnd); + payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; + payload_sz = sizeof(cmd_request->mpb); + if (scsi_sg_count(scmnd)) { sgl = (struct scatterlist *)scsi_sglist(scmnd); sg_count = scsi_sg_count(scmnd); @@ -1615,19 +1631,40 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) 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 = kzalloc(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; for (i = 0; i < sg_count; i++) - cmd_request->data_buffer.pfn_array[i] = + payload->range.pfn_array[i] = page_to_pfn(sg_page((&sgl[
[PATCH 0/3] scsi: storvsc: Increase the tablesize based on host's capabilities
Presently, storvsc limits the I/O size arbitrarily. Make this configurable based on what the host advertises. K. Y. Srinivasan (3): scsi: storvsc: Retrieve information about the capability of the target scsi: storvsc: Set the tablesize based on the information given by the host scsi: storvsc: Enable clustering drivers/scsi/storvsc_drv.c | 78 +++- 1 files changed, 62 insertions(+), 16 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
[PATCH 2/3] scsi: storvsc: Size the queue depth based on the ringbuffer size
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 Reviewed-by: Long Li --- 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_REQUESTS200 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 -- 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/3] scsi: storvsc: Always send on the selected outgoing channel
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 Reviewed-by: Long Li --- 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 -- 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/3] scsi: storvsc: Increase the ring buffer size
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 Reviewed-by: Long Li --- 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 -- 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/3] scsi: storvsc: Some enhancements
While testing on some high latency storage backends, to get the advertised IOPS, we have to increase the size of the ringbuffer. Address this issue. K. Y. Srinivasan (3): 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 drivers/scsi/storvsc_drv.c | 30 +- 1 files changed, 17 insertions(+), 13 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
[PATCH 1/4] Drivers: scsi: storvsc: In responce to a scan event, scan the host
The virtual HBA that storvsc implements can support multiple channels and targets. So, scan the host when the host notifies that a scan is needed. Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 19 +++ 1 files changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index e3ba251..0a96fef 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -426,21 +426,16 @@ done: kfree(wrk); } -static void storvsc_bus_scan(struct work_struct *work) +static void storvsc_host_scan(struct work_struct *work) { struct storvsc_scan_work *wrk; - int id, order_id; + struct Scsi_Host *host; wrk = container_of(work, struct storvsc_scan_work, work); - for (id = 0; id < wrk->host->max_id; ++id) { - if (wrk->host->reverse_ordering) - order_id = wrk->host->max_id - id - 1; - else - order_id = id; - - scsi_scan_target(&wrk->host->shost_gendev, 0, - order_id, SCAN_WILD_CARD, 1); - } + host = wrk->host; + + scsi_scan_host(host); + kfree(wrk); } @@ -1198,7 +1193,7 @@ static void storvsc_on_receive(struct hv_device *device, if (!work) return; - INIT_WORK(&work->work, storvsc_bus_scan); + INIT_WORK(&work->work, storvsc_host_scan); work->host = stor_device->host; schedule_work(&work->work); break; -- 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 2/4] Drivers: scsi: storvsc: Force discovery of LUNs that may have been removed.
The host asks the guest to scan when a LUN is removed or added. The only way a guest can identify the removed LUN is when an I/O is attempted on a removed LUN - the SRB status code indicates that the LUN is invalid. We currently handle this SRB status and remove the device. Rather than waiting for an I/O to remove the device, force the discovery of LUNs that may have been removed prior to discovering LUNs that may have been added. Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 26 ++ 1 files changed, 26 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 0a96fef..a7163c6 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -430,10 +430,36 @@ static void storvsc_host_scan(struct work_struct *work) { struct storvsc_scan_work *wrk; struct Scsi_Host *host; + struct scsi_device *sdev; + unsigned long flags; wrk = container_of(work, struct storvsc_scan_work, work); host = wrk->host; + /* +* Before scanning the host, first check to see if any of the +* currrently known devices have been hot removed. We issue a +* "unit ready" command against all currently known devices. +* This I/O will result in an error for devices that have been +* removed. As part of handling the I/O error, we remove the device. +* +* When a LUN is added or removed, the host sends us a signal to +* scan the host. Thus we are forced to discover the LUNs that +* may have been removed this way. +*/ + mutex_lock(&host->scan_mutex); + spin_lock_irqsave(host->host_lock, flags); + list_for_each_entry(sdev, &host->__devices, siblings) { + spin_unlock_irqrestore(host->host_lock, flags); + scsi_test_unit_ready(sdev, 1, 1, NULL); + spin_lock_irqsave(host->host_lock, flags); + continue; + } + spin_unlock_irqrestore(host->host_lock, flags); + mutex_unlock(&host->scan_mutex); + /* +* Now scan the host to discover LUNs that may have been added. +*/ scsi_scan_host(host); kfree(wrk); -- 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/4] Drivers: scsi: storvsc: Fix a bug in storvsc limits
Commit 4cd83ecdac20d30725b4f96e5d7814a1e290bc7e changed the limits to reflect the values on the host. It turns out that WS2008R2 cannot correctly handle these new limits. Fix this bug by setting the limits based on the host. Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 15 --- 1 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index a7163c6..fdc5164 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1782,6 +1782,9 @@ static int storvsc_probe(struct hv_device *device, bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); int target = 0; struct storvsc_device *stor_device; + int max_luns_per_target; + int max_targets; + int max_channels; /* * Based on the windows host we are running on, @@ -1795,12 +1798,18 @@ static int storvsc_probe(struct hv_device *device, vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmstor_current_major = VMSTOR_WIN7_MAJOR; vmstor_current_minor = VMSTOR_WIN7_MINOR; + max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; + max_targets = STORVSC_IDE_MAX_TARGETS; + max_channels = STORVSC_IDE_MAX_CHANNELS; break; default: sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = 0; vmstor_current_major = VMSTOR_WIN8_MAJOR; vmstor_current_minor = VMSTOR_WIN8_MINOR; + max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; + max_targets = STORVSC_MAX_TARGETS; + max_channels = STORVSC_MAX_CHANNELS; break; } @@ -1848,9 +1857,9 @@ static int storvsc_probe(struct hv_device *device, break; case SCSI_GUID: - host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; - host->max_id = STORVSC_MAX_TARGETS; - host->max_channel = STORVSC_MAX_CHANNELS - 1; + host->max_lun = max_luns_per_target; + host->max_id = max_targets; + host->max_channel = max_channels - 1; break; default: -- 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/4] Drivers: scsi: storvsc: Fix miscellaneous issues
The first two patches in this series are a resend; these were submitted some months ago and as far as I know, there were no outstanding issues. Win8 and win8 r2 hosts do support SPC-3 features but claim SPC-2 compliance. This issue is fixed here as well. K. Y. Srinivasan (4): Drivers: scsi: storvsc: In responce to a scan event, scan the host Drivers: scsi: storvsc: Force discovery of LUNs that may have been removed. Drivers: scsi: storvsc: Fix a bug in storvsc limits Drivers: scsi: storvsc: Force SPC-3 compliance on win8 and win8 r2 hosts drivers/scsi/storvsc_drv.c | 71 +++ 1 files changed, 57 insertions(+), 14 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
[PATCH 4/4] Drivers: scsi: storvsc: Force SPC-3 compliance on win8 and win8 r2 hosts
On win8 and win8 r2 hosts force SPC-3 compliance for MSFT virtual disks. Ubuntu has been carrying a similar patch outside the tree for a while now. Starting with win10, the host will support SPC-3 compliance. Based on all the testing that has been done on win8 and win8 r2 hosts, we are comfortable claiming SPC-3 compliance on these hosts as well. This will enable TRIM support on these hosts. Suggested by: James Bottomley Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 13 + 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index fdc5164..7487e07 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1468,6 +1468,19 @@ static int storvsc_device_configure(struct scsi_device *sdevice) */ sdevice->sdev_bflags |= msft_blist_flags; + /* +* If the host is WIN8 or WIN8 R2, claim conformance to SPC-3 +* if the device is a MSFT virtual device. +*/ + if (!strncmp(sdevice->vendor, "Msft", 4)) { + switch (vmbus_proto_version) { + case VERSION_WIN8: + case VERSION_WIN8_1: + sdevice->scsi_level = SCSI_SPC_3; + break; + } + } + return 0; } -- 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/1] Drivers: scsi: storvsc: Get rid of warning messages
Get rid of the warning messages since they will clutter up various system logs and are of questionable value to the end user. For debugging purposes, this information can be gotten by setting the scsi log level appropriately. Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 12 1 files changed, 0 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index fecac5d0..733e5f7 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1152,24 +1152,12 @@ static void storvsc_on_io_completion(struct hv_device *device, stor_pkt->vm_srb.sense_info_length = vstor_packet->vm_srb.sense_info_length; - if (vstor_packet->vm_srb.scsi_status != 0 || - vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS){ - dev_warn(&device->device, -"cmd 0x%x scsi status 0x%x srb status 0x%x\n", -stor_pkt->vm_srb.cdb[0], -vstor_packet->vm_srb.scsi_status, -vstor_packet->vm_srb.srb_status); - } if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) { /* CHECK_CONDITION */ if (vstor_packet->vm_srb.srb_status & SRB_STATUS_AUTOSENSE_VALID) { /* autosense data available */ - dev_warn(&device->device, -"stor pkt %p autosense data valid - len %d\n", -request, -vstor_packet->vm_srb.sense_info_length); memcpy(request->sense_buffer, vstor_packet->vm_srb.sense_data, -- 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/2] Drivers: scsi: storvsc: In responce to a scan event, scan the host
The virtual HBA that storvsc implements can support multiple channels and targets. So, scan the host when the host notifies that a scan is needed. Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 19 +++ 1 files changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 15ba695..02d1db6 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -426,21 +426,16 @@ done: kfree(wrk); } -static void storvsc_bus_scan(struct work_struct *work) +static void storvsc_host_scan(struct work_struct *work) { struct storvsc_scan_work *wrk; - int id, order_id; + struct Scsi_Host *host; wrk = container_of(work, struct storvsc_scan_work, work); - for (id = 0; id < wrk->host->max_id; ++id) { - if (wrk->host->reverse_ordering) - order_id = wrk->host->max_id - id - 1; - else - order_id = id; - - scsi_scan_target(&wrk->host->shost_gendev, 0, - order_id, SCAN_WILD_CARD, 1); - } + host = wrk->host; + + scsi_scan_host(host); + kfree(wrk); } @@ -1209,7 +1204,7 @@ static void storvsc_on_receive(struct hv_device *device, if (!work) return; - INIT_WORK(&work->work, storvsc_bus_scan); + INIT_WORK(&work->work, storvsc_host_scan); work->host = stor_device->host; schedule_work(&work->work); break; -- 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/2] Drivers: scsi: storvsc: Fix issues with hot-add/remove of LUNs
This patch-set addresses issues with LUN hot-add and remove. When the host notifies the guest that a scan is needed, scan the host. Also, prior to discovering new devices that may have been added, ensure we handle the LUN remove case first. K. Y. Srinivasan (2): Drivers: scsi: storvsc: In responce to a scan event, scan the host Drivers: scsi: storvsc: Force discovery of LUNs that may have been removed. drivers/scsi/storvsc_drv.c | 43 --- 1 files changed, 32 insertions(+), 11 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
[PATCH 2/2] Drivers: scsi: storvsc: Force discovery of LUNs that may have been removed.
The host asks the guest to scan when a LUN is removed or added. The only way a guest can identify the removed LUN is when an I/O is attempted on a removed LUN - the SRB status code indicates that the LUN is invalid. We currently handle this SRB status and remove the device. Rather than waiting for an I/O to remove the device, force the discovery of LUNs that may have been removed prior to discovering LUNs that may have been added. Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 26 ++ 1 files changed, 26 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 02d1db6..fb38ca9 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -430,10 +430,36 @@ static void storvsc_host_scan(struct work_struct *work) { struct storvsc_scan_work *wrk; struct Scsi_Host *host; + struct scsi_device *sdev; + unsigned long flags; wrk = container_of(work, struct storvsc_scan_work, work); host = wrk->host; + /* +* Before scanning the host, first check to see if any of the +* currrently known devices have been hot removed. We issue a +* "unit ready" command against all currently known devices. +* This I/O will result in an error for devices that have been +* removed. As part of handling the I/O error, we remove the device. +* +* When a LUN is added or removed, the host sends us a signal to +* scan the host. Thus we are forced to discover the LUNs that +* may have been removed this way. +*/ + mutex_lock(&host->scan_mutex); + spin_lock_irqsave(host->host_lock, flags); + list_for_each_entry(sdev, &host->__devices, siblings) { + spin_unlock_irqrestore(host->host_lock, flags); + scsi_test_unit_ready(sdev, 1, 1, NULL); + spin_lock_irqsave(host->host_lock, flags); + continue; + } + spin_unlock_irqrestore(host->host_lock, flags); + mutex_unlock(&host->scan_mutex); + /* +* Now scan the host to discover LUNs that may have been added. +*/ scsi_scan_host(host); kfree(wrk); -- 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/1] Drivers: scsi: storvsc: Add blist flags
Add blist flags to permit the reading of the VPD pages even when the target may claim SPC-2 compliance. MSFT targets currently claim SPC-2 compliance while they implement post SPC-2 features. With this patch we can correctly handle WRITE_SAME_16 issues. Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 29d0329..15ba695 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -327,6 +327,8 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); */ static int storvsc_timeout = 180; +static int msft_blist_flags = BLIST_TRY_VPD_PAGES; + #define STORVSC_MAX_IO_REQUESTS200 static void storvsc_on_channel_callback(void *context); @@ -1449,6 +1451,14 @@ static int storvsc_device_configure(struct scsi_device *sdevice) sdevice->no_write_same = 1; + /* +* Add blist flags to permit the reading of the VPD pages even when +* the target may claim SPC-2 compliance. MSFT targets currently +* claim SPC-2 compliance while they implement post SPC-2 features. +* With this patch we can correctly handle WRITE_SAME_16 issues. +*/ + sdevice->sdev_bflags |= msft_blist_flags; + return 0; } -- 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/1] Drivers: scsi: storvsc: Add blist flags
Add blist flags to permit the reading of the VPD pages even when the target may claim SPC-2 compliance. MSFT targets currently claim SPC-2 compliance while they implement post SPC-2 features. With this patch we can correctly handle WRITE_SAME_16 issues. Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 13 + 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 29d0329..2a58dc4 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -42,6 +42,7 @@ #include #include #include +#include "scsi_priv.h" /* * All wire protocol details (storage protocol between the guest and the host) @@ -327,6 +328,8 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); */ static int storvsc_timeout = 180; +static int msft_blist_flags = BLIST_TRY_VPD_PAGES; + #define STORVSC_MAX_IO_REQUESTS200 static void storvsc_on_channel_callback(void *context); @@ -1438,6 +1441,8 @@ static void storvsc_device_destroy(struct scsi_device *sdevice) static int storvsc_device_configure(struct scsi_device *sdevice) { + int blist_flags; + scsi_adjust_queue_depth(sdevice, MSG_SIMPLE_TAG, STORVSC_MAX_IO_REQUESTS); @@ -1449,6 +1454,14 @@ static int storvsc_device_configure(struct scsi_device *sdevice) sdevice->no_write_same = 1; + blist_flags = scsi_get_device_flags_keyed(sdevice, "Msft", + "Virtual Disk", + SCSI_DEVINFO_GLOBAL); + + if (blist_flags != msft_blist_flags) + scsi_dev_info_list_add_keyed(1, "Msft", "Virtual Disk", NULL, +msft_blist_flags, +SCSI_DEVINFO_GLOBAL); return 0; } -- 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 V3 4/7] Drivers: scsi: storvsc: Fix a bug in handling VMBUS protocol version
Based on the negotiated VMBUS protocol version, we adjust the size of the storage protocol messages. The two sizes we currently handle are pre-win8 and post-win8. In WS2012 R2, we are negotiating higher VMBUS protocol version than the win8 version. Make adjustments to correctly handle this. In this version of the patch I have addressed comments from Christoph Hellwig Signed-off-by: K. Y. Srinivasan Cc: --- drivers/scsi/storvsc_drv.c | 17 ++--- 1 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 8f8847e..7e8a642 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1752,19 +1752,22 @@ static int storvsc_probe(struct hv_device *device, * set state to properly communicate with the host. */ - if (vmbus_proto_version == VERSION_WIN8) { - sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = 0; - vmstor_current_major = VMSTOR_WIN8_MAJOR; - vmstor_current_minor = VMSTOR_WIN8_MINOR; - } else { + switch (vmbus_proto_version) { + case VERSION_WS2008: + case VERSION_WIN7: sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmstor_current_major = VMSTOR_WIN7_MAJOR; vmstor_current_minor = VMSTOR_WIN7_MINOR; + break; + default: + sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; + vmscsi_size_delta = 0; + vmstor_current_major = VMSTOR_WIN8_MAJOR; + vmstor_current_minor = VMSTOR_WIN8_MINOR; + break; } - if (dev_id->driver_data == SFC_GUID) scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * STORVSC_FC_MAX_TARGETS); -- 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/7] Drivers: scsi: storvsc: Implement a timedout handler
On Azure, we have seen instances of unbounded I/O latencies. To deal with this issue, implement handler that can reset the timeout. Note that the host gaurantees that it will respond to each command that has been issued. Signed-off-by: K. Y. Srinivasan Cc: --- drivers/scsi/storvsc_drv.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 7e8a642..3516761 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -1518,6 +1519,14 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) return SUCCESS; } +static enum blk_eh_timer_return storvsc_timeout_handler(struct scsi_cmnd *scmnd) +{ + /* +* The host will respond; ask for more time. +*/ + return BLK_EH_RESET_TIMER; +} + static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) { bool allowed = true; @@ -1697,6 +1706,7 @@ static struct scsi_host_template scsi_driver = { .bios_param = storvsc_get_chs, .queuecommand = storvsc_queuecommand, .eh_host_reset_handler =storvsc_host_reset_handler, + .eh_timed_out = storvsc_timeout_handler, .slave_alloc = storvsc_device_alloc, .slave_destroy =storvsc_device_destroy, .slave_configure = storvsc_device_configure, -- 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 V3 2/7] Drivers: scsi: storvsc: Set cmd_per_lun to reflect value supported by the Host
Set cmd_per_lun to reflect value supported by the Host. In this version of the patch I have addressed comments from Christoph Hellwig Signed-off-by: K. Y. Srinivasan Cc: --- 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 8938b13..cebcef7 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1690,7 +1690,7 @@ static struct scsi_host_template scsi_driver = { .slave_alloc = storvsc_device_alloc, .slave_destroy =storvsc_device_destroy, .slave_configure = storvsc_device_configure, - .cmd_per_lun = 1, + .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 */ -- 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