aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2013-06-04 15:05:06 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-06-26 23:12:31 -0400
commit8b612fa23f13a51f5ee8eb318fe05eef63dc3de9 (patch)
treee6e136020e40a6b6c334a44f5b5fa7844d5cff52 /drivers/scsi
parent893def38211980cf9581a74dfdc66be4d77a1db6 (diff)
[SCSI] storvsc: Update the storage protocol to win8 level
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/storvsc_drv.c203
1 files changed, 168 insertions, 35 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index ede8694781d6..945198910460 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -55,10 +55,15 @@
55 * V1 RC < 2008/1/31: 1.0 55 * V1 RC < 2008/1/31: 1.0
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 */ 59 */
59 60
60#define VMSTOR_CURRENT_MAJOR 4 61
61#define VMSTOR_CURRENT_MINOR 2 62#define VMSTOR_WIN7_MAJOR 4
63#define VMSTOR_WIN7_MINOR 2
64
65#define VMSTOR_WIN8_MAJOR 5
66#define VMSTOR_WIN8_MINOR 1
62 67
63 68
64/* Packet structure describing virtual storage requests. */ 69/* Packet structure describing virtual storage requests. */
@@ -74,18 +79,103 @@ enum vstor_packet_operation {
74 VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9, 79 VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9,
75 VSTOR_OPERATION_QUERY_PROPERTIES = 10, 80 VSTOR_OPERATION_QUERY_PROPERTIES = 10,
76 VSTOR_OPERATION_ENUMERATE_BUS = 11, 81 VSTOR_OPERATION_ENUMERATE_BUS = 11,
77 VSTOR_OPERATION_MAXIMUM = 11 82 VSTOR_OPERATION_FCHBA_DATA = 12,
83 VSTOR_OPERATION_CREATE_SUB_CHANNELS = 13,
84 VSTOR_OPERATION_MAXIMUM = 13
85};
86
87/*
88 * WWN packet for Fibre Channel HBA
89 */
90
91struct hv_fc_wwn_packet {
92 bool primary_active;
93 u8 reserved1;
94 u8 reserved2;
95 u8 primary_port_wwn[8];
96 u8 primary_node_wwn[8];
97 u8 secondary_port_wwn[8];
98 u8 secondary_node_wwn[8];
78}; 99};
79 100
101
102
103/*
104 * SRB Flag Bits
105 */
106
107#define SRB_FLAGS_QUEUE_ACTION_ENABLE 0x00000002
108#define SRB_FLAGS_DISABLE_DISCONNECT 0x00000004
109#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER 0x00000008
110#define SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x00000010
111#define SRB_FLAGS_DISABLE_AUTOSENSE 0x00000020
112#define SRB_FLAGS_DATA_IN 0x00000040
113#define SRB_FLAGS_DATA_OUT 0x00000080
114#define SRB_FLAGS_NO_DATA_TRANSFER 0x00000000
115#define SRB_FLAGS_UNSPECIFIED_DIRECTION (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)
116#define SRB_FLAGS_NO_QUEUE_FREEZE 0x00000100
117#define SRB_FLAGS_ADAPTER_CACHE_ENABLE 0x00000200
118#define SRB_FLAGS_FREE_SENSE_BUFFER 0x00000400
119
120/*
121 * This flag indicates the request is part of the workflow for processing a D3.
122 */
123#define SRB_FLAGS_D3_PROCESSING 0x00000800
124#define SRB_FLAGS_IS_ACTIVE 0x00010000
125#define SRB_FLAGS_ALLOCATED_FROM_ZONE 0x00020000
126#define SRB_FLAGS_SGLIST_FROM_POOL 0x00040000
127#define SRB_FLAGS_BYPASS_LOCKED_QUEUE 0x00080000
128#define SRB_FLAGS_NO_KEEP_AWAKE 0x00100000
129#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE 0x00200000
130#define SRB_FLAGS_PORT_DRIVER_SENSEHASPORT 0x00400000
131#define SRB_FLAGS_DONT_START_NEXT_PACKET 0x00800000
132#define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F000000
133#define SRB_FLAGS_CLASS_DRIVER_RESERVED 0xF0000000
134
135
80/* 136/*
81 * Platform neutral description of a scsi request - 137 * Platform neutral description of a scsi request -
82 * this remains the same across the write regardless of 32/64 bit 138 * this remains the same across the write regardless of 32/64 bit
83 * note: it's patterned off the SCSI_PASS_THROUGH structure 139 * note: it's patterned off the SCSI_PASS_THROUGH structure
84 */ 140 */
85#define STORVSC_MAX_CMD_LEN 0x10 141#define STORVSC_MAX_CMD_LEN 0x10
86#define STORVSC_SENSE_BUFFER_SIZE 0x12 142
143#define POST_WIN7_STORVSC_SENSE_BUFFER_SIZE 0x14
144#define PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE 0x12
145
146#define STORVSC_SENSE_BUFFER_SIZE 0x14
87#define STORVSC_MAX_BUF_LEN_WITH_PADDING 0x14 147#define STORVSC_MAX_BUF_LEN_WITH_PADDING 0x14
88 148
149/*
150 * Sense buffer size changed in win8; have a run-time
151 * variable to track the size we should use.
152 */
153static int sense_buffer_size;
154
155/*
156 * The size of the vmscsi_request has changed in win8. The
157 * additional size is because of new elements added to the
158 * structure. These elements are valid only when we are talking
159 * to a win8 host.
160 * Track the correction to size we need to apply.
161 */
162
163static int vmscsi_size_delta;
164static int vmstor_current_major;
165static int vmstor_current_minor;
166
167struct vmscsi_win8_extension {
168 /*
169 * The following were added in Windows 8
170 */
171 u16 reserve;
172 u8 queue_tag;
173 u8 queue_action;
174 u32 srb_flags;
175 u32 time_out_value;
176 u32 queue_sort_ey;
177} __packed;
178
89struct vmscsi_request { 179struct vmscsi_request {
90 u16 length; 180 u16 length;
91 u8 srb_status; 181 u8 srb_status;
@@ -108,6 +198,11 @@ struct vmscsi_request {
108 u8 sense_data[STORVSC_SENSE_BUFFER_SIZE]; 198 u8 sense_data[STORVSC_SENSE_BUFFER_SIZE];
109 u8 reserved_array[STORVSC_MAX_BUF_LEN_WITH_PADDING]; 199 u8 reserved_array[STORVSC_MAX_BUF_LEN_WITH_PADDING];
110 }; 200 };
201 /*
202 * The following was added in win8.
203 */
204 struct vmscsi_win8_extension win8_extension;
205
111} __attribute((packed)); 206} __attribute((packed));
112 207
113 208
@@ -115,22 +210,18 @@ struct vmscsi_request {
115 * This structure is sent during the intialization phase to get the different 210 * This structure is sent during the intialization phase to get the different
116 * properties of the channel. 211 * properties of the channel.
117 */ 212 */
213
214#define STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL 0x1
215
118struct vmstorage_channel_properties { 216struct vmstorage_channel_properties {
119 u16 protocol_version; 217 u32 reserved;
120 u8 path_id; 218 u16 max_channel_cnt;
121 u8 target_id; 219 u16 reserved1;
122 220
123 /* Note: port number is only really known on the client side */ 221 u32 flags;
124 u32 port_number;
125 u32 flags;
126 u32 max_transfer_bytes; 222 u32 max_transfer_bytes;
127 223
128 /* 224 u64 reserved2;
129 * This id is unique for each channel and will correspond with
130 * vendor specific data in the inquiry data.
131 */
132
133 u64 unique_id;
134} __packed; 225} __packed;
135 226
136/* This structure is sent during the storage protocol negotiations. */ 227/* This structure is sent during the storage protocol negotiations. */
@@ -175,6 +266,15 @@ struct vstor_packet {
175 266
176 /* Used during version negotiations. */ 267 /* Used during version negotiations. */
177 struct vmstorage_protocol_version version; 268 struct vmstorage_protocol_version version;
269
270 /* Fibre channel address packet */
271 struct hv_fc_wwn_packet wwn_packet;
272
273 /* Number of sub-channels to create */
274 u16 sub_channel_count;
275
276 /* This will be the maximum of the union members */
277 u8 buffer[0x34];
178 }; 278 };
179} __packed; 279} __packed;
180 280
@@ -679,7 +779,8 @@ static int storvsc_channel_init(struct hv_device *device)
679 vstor_packet->flags = REQUEST_COMPLETION_FLAG; 779 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
680 780
681 ret = vmbus_sendpacket(device->channel, vstor_packet, 781 ret = vmbus_sendpacket(device->channel, vstor_packet,
682 sizeof(struct vstor_packet), 782 (sizeof(struct vstor_packet) -
783 vmscsi_size_delta),
683 (unsigned long)request, 784 (unsigned long)request,
684 VM_PKT_DATA_INBAND, 785 VM_PKT_DATA_INBAND,
685 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 786 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -703,7 +804,7 @@ static int storvsc_channel_init(struct hv_device *device)
703 vstor_packet->flags = REQUEST_COMPLETION_FLAG; 804 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
704 805
705 vstor_packet->version.major_minor = 806 vstor_packet->version.major_minor =
706 storvsc_get_version(VMSTOR_CURRENT_MAJOR, VMSTOR_CURRENT_MINOR); 807 storvsc_get_version(vmstor_current_major, vmstor_current_minor);
707 808
708 /* 809 /*
709 * The revision number is only used in Windows; set it to 0. 810 * The revision number is only used in Windows; set it to 0.
@@ -711,7 +812,8 @@ static int storvsc_channel_init(struct hv_device *device)
711 vstor_packet->version.revision = 0; 812 vstor_packet->version.revision = 0;
712 813
713 ret = vmbus_sendpacket(device->channel, vstor_packet, 814 ret = vmbus_sendpacket(device->channel, vstor_packet,
714 sizeof(struct vstor_packet), 815 (sizeof(struct vstor_packet) -
816 vmscsi_size_delta),
715 (unsigned long)request, 817 (unsigned long)request,
716 VM_PKT_DATA_INBAND, 818 VM_PKT_DATA_INBAND,
717 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 819 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -732,11 +834,10 @@ static int storvsc_channel_init(struct hv_device *device)
732 memset(vstor_packet, 0, sizeof(struct vstor_packet)); 834 memset(vstor_packet, 0, sizeof(struct vstor_packet));
733 vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES; 835 vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
734 vstor_packet->flags = REQUEST_COMPLETION_FLAG; 836 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
735 vstor_packet->storage_channel_properties.port_number =
736 stor_device->port_number;
737 837
738 ret = vmbus_sendpacket(device->channel, vstor_packet, 838 ret = vmbus_sendpacket(device->channel, vstor_packet,
739 sizeof(struct vstor_packet), 839 (sizeof(struct vstor_packet) -
840 vmscsi_size_delta),
740 (unsigned long)request, 841 (unsigned long)request,
741 VM_PKT_DATA_INBAND, 842 VM_PKT_DATA_INBAND,
742 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 843 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -754,16 +855,13 @@ static int storvsc_channel_init(struct hv_device *device)
754 vstor_packet->status != 0) 855 vstor_packet->status != 0)
755 goto cleanup; 856 goto cleanup;
756 857
757 stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
758 stor_device->target_id
759 = vstor_packet->storage_channel_properties.target_id;
760
761 memset(vstor_packet, 0, sizeof(struct vstor_packet)); 858 memset(vstor_packet, 0, sizeof(struct vstor_packet));
762 vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; 859 vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
763 vstor_packet->flags = REQUEST_COMPLETION_FLAG; 860 vstor_packet->flags = REQUEST_COMPLETION_FLAG;
764 861
765 ret = vmbus_sendpacket(device->channel, vstor_packet, 862 ret = vmbus_sendpacket(device->channel, vstor_packet,
766 sizeof(struct vstor_packet), 863 (sizeof(struct vstor_packet) -
864 vmscsi_size_delta),
767 (unsigned long)request, 865 (unsigned long)request,
768 VM_PKT_DATA_INBAND, 866 VM_PKT_DATA_INBAND,
769 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 867 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -1017,7 +1115,8 @@ static void storvsc_on_channel_callback(void *context)
1017 1115
1018 do { 1116 do {
1019 ret = vmbus_recvpacket(device->channel, packet, 1117 ret = vmbus_recvpacket(device->channel, packet,
1020 ALIGN(sizeof(struct vstor_packet), 8), 1118 ALIGN((sizeof(struct vstor_packet) -
1119 vmscsi_size_delta), 8),
1021 &bytes_recvd, &request_id); 1120 &bytes_recvd, &request_id);
1022 if (ret == 0 && bytes_recvd > 0) { 1121 if (ret == 0 && bytes_recvd > 0) {
1023 1122
@@ -1028,7 +1127,8 @@ static void storvsc_on_channel_callback(void *context)
1028 (request == &stor_device->reset_request)) { 1127 (request == &stor_device->reset_request)) {
1029 1128
1030 memcpy(&request->vstor_packet, packet, 1129 memcpy(&request->vstor_packet, packet,
1031 sizeof(struct vstor_packet)); 1130 (sizeof(struct vstor_packet) -
1131 vmscsi_size_delta));
1032 complete(&request->wait_event); 1132 complete(&request->wait_event);
1033 } else { 1133 } else {
1034 storvsc_on_receive(device, 1134 storvsc_on_receive(device,
@@ -1121,10 +1221,11 @@ static int storvsc_do_io(struct hv_device *device,
1121 1221
1122 vstor_packet->flags |= REQUEST_COMPLETION_FLAG; 1222 vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
1123 1223
1124 vstor_packet->vm_srb.length = sizeof(struct vmscsi_request); 1224 vstor_packet->vm_srb.length = (sizeof(struct vmscsi_request) -
1225 vmscsi_size_delta);
1125 1226
1126 1227
1127 vstor_packet->vm_srb.sense_info_length = STORVSC_SENSE_BUFFER_SIZE; 1228 vstor_packet->vm_srb.sense_info_length = sense_buffer_size;
1128 1229
1129 1230
1130 vstor_packet->vm_srb.data_transfer_length = 1231 vstor_packet->vm_srb.data_transfer_length =
@@ -1136,11 +1237,13 @@ static int storvsc_do_io(struct hv_device *device,
1136 ret = vmbus_sendpacket_multipagebuffer(device->channel, 1237 ret = vmbus_sendpacket_multipagebuffer(device->channel,
1137 &request->data_buffer, 1238 &request->data_buffer,
1138 vstor_packet, 1239 vstor_packet,
1139 sizeof(struct vstor_packet), 1240 (sizeof(struct vstor_packet) -
1241 vmscsi_size_delta),
1140 (unsigned long)request); 1242 (unsigned long)request);
1141 } else { 1243 } else {
1142 ret = vmbus_sendpacket(device->channel, vstor_packet, 1244 ret = vmbus_sendpacket(device->channel, vstor_packet,
1143 sizeof(struct vstor_packet), 1245 (sizeof(struct vstor_packet) -
1246 vmscsi_size_delta),
1144 (unsigned long)request, 1247 (unsigned long)request,
1145 VM_PKT_DATA_INBAND, 1248 VM_PKT_DATA_INBAND,
1146 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 1249 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -1264,7 +1367,8 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
1264 vstor_packet->vm_srb.path_id = stor_device->path_id; 1367 vstor_packet->vm_srb.path_id = stor_device->path_id;
1265 1368
1266 ret = vmbus_sendpacket(device->channel, vstor_packet, 1369 ret = vmbus_sendpacket(device->channel, vstor_packet,
1267 sizeof(struct vstor_packet), 1370 (sizeof(struct vstor_packet) -
1371 vmscsi_size_delta),
1268 (unsigned long)&stor_device->reset_request, 1372 (unsigned long)&stor_device->reset_request,
1269 VM_PKT_DATA_INBAND, 1373 VM_PKT_DATA_INBAND,
1270 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 1374 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -1349,18 +1453,28 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
1349 scmnd->host_scribble = (unsigned char *)cmd_request; 1453 scmnd->host_scribble = (unsigned char *)cmd_request;
1350 1454
1351 vm_srb = &cmd_request->vstor_packet.vm_srb; 1455 vm_srb = &cmd_request->vstor_packet.vm_srb;
1456 vm_srb->win8_extension.time_out_value = 60;
1352 1457
1353 1458
1354 /* Build the SRB */ 1459 /* Build the SRB */
1355 switch (scmnd->sc_data_direction) { 1460 switch (scmnd->sc_data_direction) {
1356 case DMA_TO_DEVICE: 1461 case DMA_TO_DEVICE:
1357 vm_srb->data_in = WRITE_TYPE; 1462 vm_srb->data_in = WRITE_TYPE;
1463 vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT;
1464 vm_srb->win8_extension.srb_flags |=
1465 (SRB_FLAGS_QUEUE_ACTION_ENABLE |
1466 SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
1358 break; 1467 break;
1359 case DMA_FROM_DEVICE: 1468 case DMA_FROM_DEVICE:
1360 vm_srb->data_in = READ_TYPE; 1469 vm_srb->data_in = READ_TYPE;
1470 vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN;
1471 vm_srb->win8_extension.srb_flags |=
1472 (SRB_FLAGS_QUEUE_ACTION_ENABLE |
1473 SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
1361 break; 1474 break;
1362 default: 1475 default:
1363 vm_srb->data_in = UNKNOWN_TYPE; 1476 vm_srb->data_in = UNKNOWN_TYPE;
1477 vm_srb->win8_extension.srb_flags = 0;
1364 break; 1478 break;
1365 } 1479 }
1366 1480
@@ -1492,6 +1606,24 @@ static int storvsc_probe(struct hv_device *device,
1492 int target = 0; 1606 int target = 0;
1493 struct storvsc_device *stor_device; 1607 struct storvsc_device *stor_device;
1494 1608
1609 /*
1610 * Based on the windows host we are running on,
1611 * set state to properly communicate with the host.
1612 */
1613
1614 if (vmbus_proto_version == VERSION_WIN8) {
1615 sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
1616 vmscsi_size_delta = 0;
1617 vmstor_current_major = VMSTOR_WIN8_MAJOR;
1618 vmstor_current_minor = VMSTOR_WIN8_MINOR;
1619 } else {
1620 sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
1621 vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
1622 vmstor_current_major = VMSTOR_WIN7_MAJOR;
1623 vmstor_current_minor = VMSTOR_WIN7_MINOR;
1624 }
1625
1626
1495 host = scsi_host_alloc(&scsi_driver, 1627 host = scsi_host_alloc(&scsi_driver,
1496 sizeof(struct hv_host_device)); 1628 sizeof(struct hv_host_device));
1497 if (!host) 1629 if (!host)
@@ -1601,7 +1733,8 @@ static int __init storvsc_drv_init(void)
1601 max_outstanding_req_per_channel = 1733 max_outstanding_req_per_channel =
1602 ((storvsc_ringbuffer_size - PAGE_SIZE) / 1734 ((storvsc_ringbuffer_size - PAGE_SIZE) /
1603 ALIGN(MAX_MULTIPAGE_BUFFER_PACKET + 1735 ALIGN(MAX_MULTIPAGE_BUFFER_PACKET +
1604 sizeof(struct vstor_packet) + sizeof(u64), 1736 sizeof(struct vstor_packet) + sizeof(u64) -
1737 vmscsi_size_delta,
1605 sizeof(u64))); 1738 sizeof(u64)));
1606 1739
1607 if (max_outstanding_req_per_channel < 1740 if (max_outstanding_req_per_channel <