From: "K. Y. Srinivasan" <kys@microsoft.com>
To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org,
devel@linuxdriverproject.org, ohering@suse.com,
jbottomley@parallels.com, hch@infradead.org,
linux-scsi@vger.kernel.org
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Subject: [PATCH 3/5] Drivers: scsi: storvsc: Implement multi-channel support
Date: Tue, 4 Jun 2013 12:05:07 -0700 [thread overview]
Message-ID: <1370372709-10098-3-git-send-email-kys@microsoft.com> (raw)
In-Reply-To: <1370372709-10098-1-git-send-email-kys@microsoft.com>
Implement multi-channel support for the storage devices.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/scsi/storvsc_drv.c | 131 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 127 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 9451989..1d4d425 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -328,6 +328,8 @@ static int storvsc_timeout = 180;
#define STORVSC_MAX_IO_REQUESTS 128
+static void storvsc_on_channel_callback(void *context);
+
/*
* In Hyper-V, each port/path/target maps to 1 scsi host adapter. In
* reality, the path/target is not used (ie always set to 0) so our
@@ -364,6 +366,7 @@ struct storvsc_device {
bool destroy;
bool drain_notify;
+ bool open_sub_channel;
atomic_t num_outstanding_req;
struct Scsi_Host *host;
@@ -755,12 +758,104 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
return total_copied;
}
+static void handle_sc_creation(struct vmbus_channel *new_sc)
+{
+ struct hv_device *device = new_sc->primary_channel->device_obj;
+ struct storvsc_device *stor_device;
+ struct vmstorage_channel_properties props;
+
+ stor_device = get_out_stor_device(device);
+ if (!stor_device)
+ return;
+
+ if (stor_device->open_sub_channel == false)
+ return;
+
+ memset(&props, 0, sizeof(struct vmstorage_channel_properties));
+
+ vmbus_open(new_sc,
+ storvsc_ringbuffer_size,
+ storvsc_ringbuffer_size,
+ (void *)&props,
+ sizeof(struct vmstorage_channel_properties),
+ storvsc_on_channel_callback, new_sc);
+}
+
+static void handle_multichannel_storage(struct hv_device *device, int max_chns)
+{
+ struct storvsc_device *stor_device;
+ int num_cpus = num_online_cpus();
+ int num_sc;
+ struct storvsc_cmd_request *request;
+ struct vstor_packet *vstor_packet;
+ int ret, t;
+
+ num_sc = ((max_chns > num_cpus) ? num_cpus : max_chns);
+ stor_device = get_out_stor_device(device);
+ if (!stor_device)
+ return;
+
+ request = &stor_device->init_request;
+ vstor_packet = &request->vstor_packet;
+
+ stor_device->open_sub_channel = true;
+ /*
+ * Establish a handler for dealing with subchannels.
+ */
+ vmbus_set_sc_create_callback(device->channel, handle_sc_creation);
+
+ /*
+ * Check to see if sub-channels have already been created. This
+ * can happen when this driver is re-loaded after unloading.
+ */
+
+ if (vmbus_are_subchannels_present(device->channel))
+ return;
+
+ stor_device->open_sub_channel = false;
+ /*
+ * Request the host to create sub-channels.
+ */
+ memset(request, 0, sizeof(struct storvsc_cmd_request));
+ init_completion(&request->wait_event);
+ vstor_packet->operation = VSTOR_OPERATION_CREATE_SUB_CHANNELS;
+ vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+ vstor_packet->sub_channel_count = num_sc;
+
+ 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)
+ return;
+
+ t = wait_for_completion_timeout(&request->wait_event, 10*HZ);
+ if (t == 0)
+ return;
+
+ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+ vstor_packet->status != 0)
+ return;
+
+ /*
+ * Now that we created the sub-channels, invoke the check; this
+ * may trigger the callback.
+ */
+ stor_device->open_sub_channel = true;
+ vmbus_are_subchannels_present(device->channel);
+}
+
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 max_chns;
+ bool process_sub_channels = false;
stor_device = get_out_stor_device(device);
if (!stor_device)
@@ -855,6 +950,19 @@ static int storvsc_channel_init(struct hv_device *device)
vstor_packet->status != 0)
goto cleanup;
+ /*
+ * Check to see if multi-channel support is there.
+ * Hosts that implement protocol version of 5.1 and above
+ * 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 (vstor_packet->storage_channel_properties.flags &
+ STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL)
+ process_sub_channels = true;
+ }
+
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
@@ -879,6 +987,9 @@ static int storvsc_channel_init(struct hv_device *device)
vstor_packet->status != 0)
goto cleanup;
+ if (process_sub_channels)
+ handle_multichannel_storage(device, max_chns);
+
cleanup:
return ret;
@@ -1100,7 +1211,8 @@ static void storvsc_on_receive(struct hv_device *device,
static void storvsc_on_channel_callback(void *context)
{
- struct hv_device *device = (struct hv_device *)context;
+ struct vmbus_channel *channel = (struct vmbus_channel *)context;
+ struct hv_device *device;
struct storvsc_device *stor_device;
u32 bytes_recvd;
u64 request_id;
@@ -1108,13 +1220,17 @@ static void storvsc_on_channel_callback(void *context)
struct storvsc_cmd_request *request;
int ret;
+ if (channel->primary_channel != NULL)
+ device = channel->primary_channel->device_obj;
+ else
+ device = channel->device_obj;
stor_device = get_in_stor_device(device);
if (!stor_device)
return;
do {
- ret = vmbus_recvpacket(device->channel, packet,
+ ret = vmbus_recvpacket(channel, packet,
ALIGN((sizeof(struct vstor_packet) -
vmscsi_size_delta), 8),
&bytes_recvd, &request_id);
@@ -1155,7 +1271,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
ring_size,
(void *)&props,
sizeof(struct vmstorage_channel_properties),
- storvsc_on_channel_callback, device);
+ storvsc_on_channel_callback, device->channel);
if (ret != 0)
return ret;
@@ -1207,6 +1323,7 @@ static int storvsc_do_io(struct hv_device *device,
{
struct storvsc_device *stor_device;
struct vstor_packet *vstor_packet;
+ struct vmbus_channel *outgoing_channel;
int ret = 0;
vstor_packet = &request->vstor_packet;
@@ -1217,6 +1334,11 @@ static int storvsc_do_io(struct hv_device *device,
request->device = device;
+ /*
+ * Select an an appropriate channel to send the request out.
+ */
+
+ outgoing_channel = vmbus_get_outgoing_channel(device->channel);
vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
@@ -1234,7 +1356,7 @@ static int storvsc_do_io(struct hv_device *device,
vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
if (request->data_buffer.len) {
- ret = vmbus_sendpacket_multipagebuffer(device->channel,
+ ret = vmbus_sendpacket_multipagebuffer(outgoing_channel,
&request->data_buffer,
vstor_packet,
(sizeof(struct vstor_packet) -
@@ -1643,6 +1765,7 @@ static int storvsc_probe(struct hv_device *device,
}
stor_device->destroy = false;
+ stor_device->open_sub_channel = false;
init_waitqueue_head(&stor_device->waiting_to_drain);
stor_device->device = device;
stor_device->host = host;
--
1.7.4.1
next prev parent reply other threads:[~2013-06-04 19:05 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-04 19:04 [PATCH V3 0/5] Drivers: scsi: storvsc K. Y. Srinivasan
2013-06-04 19:05 ` [PATCH 1/5] Drivers: scsi: storvsc: Increase the value of scsi timeout for storvsc devices K. Y. Srinivasan
2013-06-04 19:05 ` [PATCH 2/5] Drivers: scsi: storvsc: Update the storage protocol to win8 level K. Y. Srinivasan
2013-06-04 19:05 ` K. Y. Srinivasan
2013-06-04 19:05 ` K. Y. Srinivasan [this message]
2013-06-27 3:22 ` [PATCH 3/5] Drivers: scsi: storvsc: Implement multi-channel support James Bottomley
2013-06-27 3:22 ` James Bottomley
2013-06-27 11:50 ` KY Srinivasan
2013-06-27 11:50 ` KY Srinivasan
2013-06-04 19:05 ` [PATCH 4/5] Drivers: scsi: storvsc: Support FC devices K. Y. Srinivasan
2013-06-04 19:05 ` [PATCH 5/5] Drivers: scsi: storvsc: Increase the value of STORVSC_MAX_IO_REQUESTS K. Y. Srinivasan
2013-06-04 19:05 ` K. Y. Srinivasan
2013-06-11 13:02 ` [PATCH V3 0/5] Drivers: scsi: storvsc KY Srinivasan
2013-06-17 13:32 ` KY Srinivasan
2013-06-26 12:58 ` KY Srinivasan
2013-06-27 3:39 ` James Bottomley
-- strict thread matches above, loose matches on Subject: below --
2013-06-03 23:18 [PATCH V2 " K. Y. Srinivasan
2013-06-03 23:21 ` [PATCH 1/5] Drivers: scsi: storvsc: Make the scsi timeout a module parameter K. Y. Srinivasan
2013-06-03 23:21 ` [PATCH 3/5] Drivers: scsi: storvsc: Implement multi-channel support K. Y. Srinivasan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1370372709-10098-3-git-send-email-kys@microsoft.com \
--to=kys@microsoft.com \
--cc=devel@linuxdriverproject.org \
--cc=gregkh@linuxfoundation.org \
--cc=hch@infradead.org \
--cc=jbottomley@parallels.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=ohering@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.