diff options
-rw-r--r-- | drivers/scsi/storvsc_drv.c | 108 |
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. */ |
69 | enum vstor_packet_operation { | 73 | enum 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 | */ | ||
214 | struct vmstor_protocol { | ||
215 | int protocol_version; | ||
216 | int sense_buffer_size; | ||
217 | int vmscsi_size_delta; | ||
218 | }; | ||
219 | |||
220 | |||
221 | static 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; |