Commit 1a363108 authored by Keith Mange's avatar Keith Mange Committed by James Bottomley

storvsc: Untangle the storage protocol negotiation from the vmbus protocol negotiation.

Currently we are making decisions based on vmbus protocol versions
that have been negotiated; use storage potocol versions instead.

[jejb: fold ARRAY_SIZE conversion suggested by Johannes Thumshirn
<jthumshirn@suse.de>
make vmstor_protocol static]
Tested-by: default avatarAlex Ng <alexng@microsoft.com>
Signed-off-by: default avatarKeith Mange <keith.mange@microsoft.com>
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent 2492fd7a
...@@ -56,14 +56,18 @@ ...@@ -56,14 +56,18 @@
* V1 RC > 2008/1/31: 2.0 * V1 RC > 2008/1/31: 2.0
* Win7: 4.2 * Win7: 4.2
* Win8: 5.1 * Win8: 5.1
* Win8.1: 6.0
* Win10: 6.2
*/ */
#define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ #define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
(((MINOR_) & 0xff))) (((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_WIN7 VMSTOR_PROTO_VERSION(4, 2)
#define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) #define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1)
#define VMSTOR_PROTO_VERSION_WIN8_1 VMSTOR_PROTO_VERSION(6, 0)
#define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2)
/* Packet structure describing virtual storage requests. */ /* Packet structure describing virtual storage requests. */
enum vstor_packet_operation { enum vstor_packet_operation {
...@@ -204,6 +208,45 @@ struct vmscsi_request { ...@@ -204,6 +208,45 @@ struct vmscsi_request {
} __attribute((packed)); } __attribute((packed));
/*
* The list of storage protocols in order of preference.
*/
struct vmstor_protocol {
int protocol_version;
int sense_buffer_size;
int vmscsi_size_delta;
};
static const struct vmstor_protocol vmstor_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 * This structure is sent during the intialization phase to get the different
* properties of the channel. * properties of the channel.
...@@ -864,7 +907,7 @@ static int storvsc_channel_init(struct hv_device *device) ...@@ -864,7 +907,7 @@ static int storvsc_channel_init(struct hv_device *device)
struct storvsc_device *stor_device; struct storvsc_device *stor_device;
struct storvsc_cmd_request *request; struct storvsc_cmd_request *request;
struct vstor_packet *vstor_packet; struct vstor_packet *vstor_packet;
int ret, t; int ret, t, i;
int max_chns; int max_chns;
bool process_sub_channels = false; bool process_sub_channels = false;
...@@ -904,36 +947,59 @@ static int storvsc_channel_init(struct hv_device *device) ...@@ -904,36 +947,59 @@ static int storvsc_channel_init(struct hv_device *device)
goto cleanup; goto cleanup;
/* reuse the packet for version range supported */ for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) {
memset(vstor_packet, 0, sizeof(struct vstor_packet)); /* reuse the packet for version range supported */
vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->flags = REQUEST_COMPLETION_FLAG; 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. * The revision number is only used in Windows; set it to 0.
*/ */
vstor_packet->version.revision = 0; vstor_packet->version.revision = 0;
ret = vmbus_sendpacket(device->channel, vstor_packet, ret = vmbus_sendpacket(device->channel, vstor_packet,
(sizeof(struct vstor_packet) - (sizeof(struct vstor_packet) -
vmscsi_size_delta), vmscsi_size_delta),
(unsigned long)request, (unsigned long)request,
VM_PKT_DATA_INBAND, VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
if (ret != 0) if (ret != 0)
goto cleanup; goto cleanup;
t = wait_for_completion_timeout(&request->wait_event, 5*HZ); t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) { if (t == 0) {
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto cleanup; goto cleanup;
}
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) {
ret = -EINVAL;
goto cleanup;
}
if (vstor_packet->status == 0) {
vmstor_proto_version =
vmstor_protocols[i].protocol_version;
sense_buffer_size =
vmstor_protocols[i].sense_buffer_size;
vmscsi_size_delta =
vmstor_protocols[i].vmscsi_size_delta;
break;
}
} }
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || if (vstor_packet->status != 0) {
vstor_packet->status != 0) ret = -EINVAL;
goto cleanup; goto cleanup;
}
memset(vstor_packet, 0, sizeof(struct vstor_packet)); memset(vstor_packet, 0, sizeof(struct vstor_packet));
...@@ -1746,14 +1812,12 @@ static int storvsc_probe(struct hv_device *device, ...@@ -1746,14 +1812,12 @@ static int storvsc_probe(struct hv_device *device,
if (vmbus_proto_version < VERSION_WIN8) { if (vmbus_proto_version < VERSION_WIN8) {
sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN7;
max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET;
max_targets = STORVSC_IDE_MAX_TARGETS; max_targets = STORVSC_IDE_MAX_TARGETS;
max_channels = STORVSC_IDE_MAX_CHANNELS; max_channels = STORVSC_IDE_MAX_CHANNELS;
} else { } else {
sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
vmscsi_size_delta = 0; vmscsi_size_delta = 0;
vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN8;
max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET;
max_targets = STORVSC_MAX_TARGETS; max_targets = STORVSC_MAX_TARGETS;
max_channels = STORVSC_MAX_CHANNELS; max_channels = STORVSC_MAX_CHANNELS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment