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: Alex Ng <alexng@microsoft.com> Signed-off-by: Keith Mange <keith.mange@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
This commit is contained in:
Родитель
2492fd7a60
Коммит
1a3631081d
|
@ -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 {
|
||||||
} __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)
|
||||||
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)
|
||||||
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,
|
||||||
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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче