aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/storvsc_drv.c108
1 files changed, 86 insertions, 22 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 367f66cc1f07..d6a42c000048 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -56,14 +56,18 @@
56 * V1 RC > 2008/1/31: 2.0 56 * V1 RC > 2008/1/31: 2.0
57 * Win7: 4.2 57 * Win7: 4.2
58 * Win8: 5.1 58 * Win8: 5.1
59 * Win8.1: 6.0
60 * Win10: 6.2
59 */ 61 */
60 62
61#define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ 63#define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
62 (((MINOR_) & 0xff))) 64 (((MINOR_) & 0xff)))
63 65
66#define VMSTOR_PROTO_VERSION_WIN6 VMSTOR_PROTO_VERSION(2, 0)
64#define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) 67#define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2)
65#define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) 68#define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1)
66 69#define VMSTOR_PROTO_VERSION_WIN8_1 VMSTOR_PROTO_VERSION(6, 0)
70#define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2)
67 71
68/* Packet structure describing virtual storage requests. */ 72/* Packet structure describing virtual storage requests. */
69enum vstor_packet_operation { 73enum vstor_packet_operation {
@@ -205,6 +209,45 @@ struct vmscsi_request {
205 209
206 210
207/* 211/*
212 * The list of storage protocols in order of preference.
213 */
214struct vmstor_protocol {
215 int protocol_version;
216 int sense_buffer_size;
217 int vmscsi_size_delta;
218};
219
220
221static const struct vmstor_protocol vmstor_protocols[] = {
222 {
223 VMSTOR_PROTO_VERSION_WIN10,
224 POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
225 0
226 },
227 {
228 VMSTOR_PROTO_VERSION_WIN8_1,
229 POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
230 0
231 },
232 {
233 VMSTOR_PROTO_VERSION_WIN8,
234 POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
235 0
236 },
237 {
238 VMSTOR_PROTO_VERSION_WIN7,
239 PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE,
240 sizeof(struct vmscsi_win8_extension),
241 },
242 {
243 VMSTOR_PROTO_VERSION_WIN6,
244 PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE,
245 sizeof(struct vmscsi_win8_extension),
246 }
247};
248
249
250/*
208 * This structure is sent during the intialization phase to get the different 251 * This structure is sent during the intialization phase to get the different
209 * properties of the channel. 252 * properties of the channel.
210 */ 253 */
@@ -864,7 +907,7 @@ static int storvsc_channel_init(struct hv_device *device)
864 struct storvsc_device *stor_device; 907 struct storvsc_device *stor_device;
865 struct storvsc_cmd_request *request; 908 struct storvsc_cmd_request *request;
866 struct vstor_packet *vstor_packet; 909 struct vstor_packet *vstor_packet;
867 int ret, t; 910 int ret, t, i;
868 int max_chns; 911 int max_chns;
869 bool process_sub_channels = false; 912 bool process_sub_channels = false;
870 913
@@ -904,36 +947,59 @@ static int storvsc_channel_init(struct hv_device *device)
904 goto cleanup; 947 goto cleanup;
905 948
906 949
907 /* reuse the packet for version range supported */ 950 for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) {
908 memset(vstor_packet, 0, sizeof(struct vstor_packet)); 951 /* reuse the packet for version range supported */
909 vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; 952 memset(vstor_packet, 0, sizeof(struct vstor_packet));
910 vstor_packet->flags = REQUEST_COMPLETION_FLAG; 953 vstor_packet->operation =
954 VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
955 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
911 956
912 vstor_packet->version.major_minor = vmstor_proto_version; 957 vstor_packet->version.major_minor =
958 vmstor_protocols[i].protocol_version;
913 959
914 /* 960 /*
915 * The revision number is only used in Windows; set it to 0. 961 * The revision number is only used in Windows; set it to 0.
916 */ 962 */
917 vstor_packet->version.revision = 0; 963 vstor_packet->version.revision = 0;
918 964
919 ret = vmbus_sendpacket(device->channel, vstor_packet, 965 ret = vmbus_sendpacket(device->channel, vstor_packet,
920 (sizeof(struct vstor_packet) - 966 (sizeof(struct vstor_packet) -
921 vmscsi_size_delta), 967 vmscsi_size_delta),
922 (unsigned long)request, 968 (unsigned long)request,
923 VM_PKT_DATA_INBAND, 969 VM_PKT_DATA_INBAND,
924 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 970 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
925 if (ret != 0) 971 if (ret != 0)
926 goto cleanup; 972 goto cleanup;
927 973
928 t = wait_for_completion_timeout(&request->wait_event, 5*HZ); 974 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
929 if (t == 0) { 975 if (t == 0) {
930 ret = -ETIMEDOUT; 976 ret = -ETIMEDOUT;
931 goto cleanup; 977 goto cleanup;
978 }
979
980 if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) {
981 ret = -EINVAL;
982 goto cleanup;
983 }
984
985 if (vstor_packet->status == 0) {
986 vmstor_proto_version =
987 vmstor_protocols[i].protocol_version;
988
989 sense_buffer_size =
990 vmstor_protocols[i].sense_buffer_size;
991
992 vmscsi_size_delta =
993 vmstor_protocols[i].vmscsi_size_delta;
994
995 break;
996 }
932 } 997 }
933 998
934 if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || 999 if (vstor_packet->status != 0) {
935 vstor_packet->status != 0) 1000 ret = -EINVAL;
936 goto cleanup; 1001 goto cleanup;
1002 }
937 1003
938 1004
939 memset(vstor_packet, 0, sizeof(struct vstor_packet)); 1005 memset(vstor_packet, 0, sizeof(struct vstor_packet));
@@ -1746,14 +1812,12 @@ static int storvsc_probe(struct hv_device *device,
1746 if (vmbus_proto_version < VERSION_WIN8) { 1812 if (vmbus_proto_version < VERSION_WIN8) {
1747 sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; 1813 sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
1748 vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); 1814 vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
1749 vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN7;
1750 max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; 1815 max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET;
1751 max_targets = STORVSC_IDE_MAX_TARGETS; 1816 max_targets = STORVSC_IDE_MAX_TARGETS;
1752 max_channels = STORVSC_IDE_MAX_CHANNELS; 1817 max_channels = STORVSC_IDE_MAX_CHANNELS;
1753 } else { 1818 } else {
1754 sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; 1819 sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
1755 vmscsi_size_delta = 0; 1820 vmscsi_size_delta = 0;
1756 vmstor_proto_version = VMSTOR_PROTO_VERSION_WIN8;
1757 max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; 1821 max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET;
1758 max_targets = STORVSC_MAX_TARGETS; 1822 max_targets = STORVSC_MAX_TARGETS;
1759 max_channels = STORVSC_MAX_CHANNELS; 1823 max_channels = STORVSC_MAX_CHANNELS;