Skip to content

Commit

Permalink
storvsc: Untangle the storage protocol negotiation from the vmbus pro…
Browse files Browse the repository at this point in the history
…tocol 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>
  • Loading branch information
Keith Mange authored and James Bottomley committed Aug 27, 2015
1 parent 2492fd7 commit 1a36310
Showing 1 changed file with 86 additions and 22 deletions.
108 changes: 86 additions & 22 deletions drivers/scsi/storvsc_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1a36310

Please sign in to comment.