Преглед изворни кода

[hyperv] Ignore unsolicited VMBus messages

In some high-end Azure instances (e.g. NC6) we may receive an
unsolicited VMBUS_OFFER_CHANNEL message for a PCIe pass-through device
some time after completing the bus enumeration.  This currently causes
apparently random failures due to unexpected VMBus message types.

Fix by ignoring any unsolicited VMBus messages.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown пре 7 година
родитељ
комит
321af68b72
1 измењених фајлова са 43 додато и 39 уклоњено
  1. 43
    39
      src/interface/hyperv/vmbus.c

+ 43
- 39
src/interface/hyperv/vmbus.c Прегледај датотеку

@@ -90,12 +90,12 @@ static int vmbus_post_empty_message ( struct hv_hypervisor *hv,
90 90
 }
91 91
 
92 92
 /**
93
- * Wait for received message
93
+ * Wait for received message of any type
94 94
  *
95 95
  * @v hv		Hyper-V hypervisor
96 96
  * @ret rc		Return status code
97 97
  */
98
-static int vmbus_wait_for_message ( struct hv_hypervisor *hv ) {
98
+static int vmbus_wait_for_any_message ( struct hv_hypervisor *hv ) {
99 99
 	struct vmbus *vmbus = hv->vmbus;
100 100
 	int rc;
101 101
 
@@ -116,6 +116,38 @@ static int vmbus_wait_for_message ( struct hv_hypervisor *hv ) {
116 116
 	return 0;
117 117
 }
118 118
 
119
+/**
120
+ * Wait for received message of a specified type, ignoring any others
121
+ *
122
+ * @v hv		Hyper-V hypervisor
123
+ * @v type		Message type
124
+ * @ret rc		Return status code
125
+ */
126
+static int vmbus_wait_for_message ( struct hv_hypervisor *hv,
127
+				    unsigned int type ) {
128
+	struct vmbus *vmbus = hv->vmbus;
129
+	const struct vmbus_message_header *header = &vmbus->message->header;
130
+	int rc;
131
+
132
+	/* Loop until specified message arrives, or until an error occurs */
133
+	while ( 1 ) {
134
+
135
+		/* Wait for message */
136
+		if ( ( rc = vmbus_wait_for_any_message ( hv ) ) != 0 )
137
+			return rc;
138
+
139
+		/* Check for requested message type */
140
+		if ( header->type == cpu_to_le32 ( type ) )
141
+			return 0;
142
+
143
+		/* Ignore any other messages (e.g. due to additional
144
+		 * channels being offered at runtime).
145
+		 */
146
+		DBGC ( vmbus, "VMBUS %p ignoring message type %d (expecting "
147
+		       "%d)\n", vmbus, le32_to_cpu ( header->type ), type );
148
+	}
149
+}
150
+
119 151
 /**
120 152
  * Initiate contact
121 153
  *
@@ -144,15 +176,10 @@ static int vmbus_initiate_contact ( struct hv_hypervisor *hv,
144 176
 		return rc;
145 177
 
146 178
 	/* Wait for response */
147
-	if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 )
179
+	if ( ( rc = vmbus_wait_for_message ( hv, VMBUS_VERSION_RESPONSE ) ) !=0)
148 180
 		return rc;
149 181
 
150 182
 	/* Check response */
151
-	if ( version->header.type != cpu_to_le32 ( VMBUS_VERSION_RESPONSE ) ) {
152
-		DBGC ( vmbus, "VMBUS %p unexpected version response type %d\n",
153
-		       vmbus, le32_to_cpu ( version->header.type ) );
154
-		return -EPROTO;
155
-	}
156 183
 	if ( ! version->supported ) {
157 184
 		DBGC ( vmbus, "VMBUS %p requested version not supported\n",
158 185
 		       vmbus );
@@ -178,8 +205,6 @@ static int vmbus_initiate_contact ( struct hv_hypervisor *hv,
178 205
  * @ret rc		Return status code
179 206
  */
180 207
 static int vmbus_unload ( struct hv_hypervisor *hv ) {
181
-	struct vmbus *vmbus = hv->vmbus;
182
-	const struct vmbus_message_header *header = &vmbus->message->header;
183 208
 	int rc;
184 209
 
185 210
 	/* Post message */
@@ -187,16 +212,9 @@ static int vmbus_unload ( struct hv_hypervisor *hv ) {
187 212
 		return rc;
188 213
 
189 214
 	/* Wait for response */
190
-	if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 )
215
+	if ( ( rc = vmbus_wait_for_message ( hv, VMBUS_UNLOAD_RESPONSE ) ) != 0)
191 216
 		return rc;
192 217
 
193
-	/* Check response */
194
-	if ( header->type != cpu_to_le32 ( VMBUS_UNLOAD_RESPONSE ) ) {
195
-		DBGC ( vmbus, "VMBUS %p unexpected unload response type %d\n",
196
-		       vmbus, le32_to_cpu ( header->type ) );
197
-		return -EPROTO;
198
-	}
199
-
200 218
 	return 0;
201 219
 }
202 220
 
@@ -290,15 +308,10 @@ int vmbus_establish_gpadl ( struct vmbus_device *vmdev, userptr_t data,
290 308
 		return rc;
291 309
 
292 310
 	/* Wait for response */
293
-	if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 )
311
+	if ( ( rc = vmbus_wait_for_message ( hv, VMBUS_GPADL_CREATED ) ) != 0 )
294 312
 		return rc;
295 313
 
296 314
 	/* Check response */
297
-	if ( created->header.type != cpu_to_le32 ( VMBUS_GPADL_CREATED ) ) {
298
-		DBGC ( vmdev, "VMBUS %s unexpected GPADL response type %d\n",
299
-		       vmdev->dev.name, le32_to_cpu ( created->header.type ) );
300
-		return -EPROTO;
301
-	}
302 315
 	if ( created->channel != cpu_to_le32 ( vmdev->channel ) ) {
303 316
 		DBGC ( vmdev, "VMBUS %s unexpected GPADL channel %d\n",
304 317
 		       vmdev->dev.name, le32_to_cpu ( created->channel ) );
@@ -346,15 +359,10 @@ int vmbus_gpadl_teardown ( struct vmbus_device *vmdev, unsigned int gpadl ) {
346 359
 		return rc;
347 360
 
348 361
 	/* Wait for response */
349
-	if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 )
362
+	if ( ( rc = vmbus_wait_for_message ( hv, VMBUS_GPADL_TORNDOWN ) ) != 0 )
350 363
 		return rc;
351 364
 
352 365
 	/* Check response */
353
-	if ( torndown->header.type != cpu_to_le32 ( VMBUS_GPADL_TORNDOWN ) ) {
354
-		DBGC ( vmdev, "VMBUS %s unexpected GPADL response type %d\n",
355
-		       vmdev->dev.name, le32_to_cpu ( torndown->header.type ) );
356
-		return -EPROTO;
357
-	}
358 366
 	if ( torndown->gpadl != cpu_to_le32 ( gpadl ) ) {
359 367
 		DBGC ( vmdev, "VMBUS %s unexpected GPADL ID %#08x\n",
360 368
 		       vmdev->dev.name, le32_to_cpu ( torndown->gpadl ) );
@@ -443,15 +451,11 @@ int vmbus_open ( struct vmbus_device *vmdev,
443 451
 		return rc;
444 452
 
445 453
 	/* Wait for response */
446
-	if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 )
454
+	if ( ( rc = vmbus_wait_for_message ( hv,
455
+					     VMBUS_OPEN_CHANNEL_RESULT ) ) != 0)
447 456
 		return rc;
448 457
 
449 458
 	/* Check response */
450
-	if ( opened->header.type != cpu_to_le32 ( VMBUS_OPEN_CHANNEL_RESULT ) ){
451
-		DBGC ( vmdev, "VMBUS %s unexpected open response type %d\n",
452
-		       vmdev->dev.name, le32_to_cpu ( opened->header.type ) );
453
-		return -EPROTO;
454
-	}
455 459
 	if ( opened->channel != cpu_to_le32 ( vmdev->channel ) ) {
456 460
 		DBGC ( vmdev, "VMBUS %s unexpected opened channel %#08x\n",
457 461
 		       vmdev->dev.name, le32_to_cpu ( opened->channel ) );
@@ -1136,8 +1140,8 @@ static int vmbus_probe_channels ( struct hv_hypervisor *hv,
1136 1140
 	while ( 1 ) {
1137 1141
 
1138 1142
 		/* Wait for response */
1139
-		if ( ( rc = vmbus_wait_for_message ( hv ) ) != 0 )
1140
-			goto err_wait_for_message;
1143
+		if ( ( rc = vmbus_wait_for_any_message ( hv ) ) != 0 )
1144
+			goto err_wait_for_any_message;
1141 1145
 
1142 1146
 		/* Handle response */
1143 1147
 		if ( header->type == cpu_to_le32 ( VMBUS_OFFER_CHANNEL ) ) {
@@ -1223,7 +1227,7 @@ static int vmbus_probe_channels ( struct hv_hypervisor *hv,
1223 1227
 	}
1224 1228
  err_unexpected_offer:
1225 1229
  err_alloc_vmdev:
1226
- err_wait_for_message:
1230
+ err_wait_for_any_message:
1227 1231
 	/* Free any devices allocated (but potentially not yet probed) */
1228 1232
 	list_for_each_entry_safe ( vmdev, tmp, &parent->children,
1229 1233
 				   dev.siblings ) {

Loading…
Откажи
Сачувај