|
@@ -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_1 VMSTOR_PROTO_VERSION(6, 0)
|
|
|
+#define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2)
|
|
|
|
|
|
/* Packet structure describing virtual storage requests. */
|
|
|
enum vstor_packet_operation {
|
|
@@ -204,6 +208,45 @@ struct vmscsi_request {
|
|
|
} __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
|
|
|
* properties of the channel.
|
|
@@ -864,7 +907,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;
|
|
|
|
|
@@ -904,36 +947,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 < 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_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;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 ||
|
|
|
- vstor_packet->status != 0)
|
|
|
+ if (vstor_packet->status != 0) {
|
|
|
+ ret = -EINVAL;
|
|
|
goto cleanup;
|
|
|
+ }
|
|
|
|
|
|
|
|
|
memset(vstor_packet, 0, sizeof(struct vstor_packet));
|
|
@@ -1746,14 +1812,12 @@ 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_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_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;
|