All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] PCI: hv: Do not wait forever on a device that has disappeared
@ 2018-05-23 21:12 ` Dexuan Cui
  0 siblings, 0 replies; 31+ messages in thread
From: Dexuan Cui @ 2018-05-23 21:12 UTC (permalink / raw)
  To: 'Lorenzo Pieralisi', 'Bjorn Helgaas',
	'linux-pci@vger.kernel.org',
	KY Srinivasan, Stephen Hemminger, 'olaf@aepfle.de',
	'apw@canonical.com', 'jasowang@redhat.com'
  Cc: 'marcelo.cerri@canonical.com',
	'vkuznets@redhat.com',
	Haiyang Zhang, 'driverdev-devel@linuxdriverproject.org',
	'linux-kernel@vger.kernel.org'


Before the guest finishes the device initialization, the device can be
removed anytime by the host, and after that the host won't respond to
the guest's request, so the guest should be prepared to handle this
case.

Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/pci/host/pci-hyperv.c | 46 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 34 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
index ad6a64d..248765f 100644
--- a/drivers/pci/host/pci-hyperv.c
+++ b/drivers/pci/host/pci-hyperv.c
@@ -556,6 +556,26 @@ static void put_pcichild(struct hv_pci_dev *hv_pcidev,
 static void get_hvpcibus(struct hv_pcibus_device *hv_pcibus);
 static void put_hvpcibus(struct hv_pcibus_device *hv_pcibus);
 
+/*
+ * There is no good way to get notified from vmbus_onoffer_rescind(),
+ * so let's use polling here, since this is not a hot path.
+ */
+static int wait_for_response(struct hv_device *hdev,
+			     struct completion *comp)
+{
+	while (true) {
+		if (hdev->channel->rescind) {
+			dev_warn_once(&hdev->device, "The device is gone.\n");
+			return -ENODEV;
+		}
+
+		if (wait_for_completion_timeout(comp, HZ / 10))
+			break;
+	}
+
+	return 0;
+}
+
 /**
  * devfn_to_wslot() - Convert from Linux PCI slot to Windows
  * @devfn:	The Linux representation of PCI slot
@@ -1569,7 +1589,8 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
 	if (ret)
 		goto error;
 
-	wait_for_completion(&comp_pkt.host_event);
+	if (wait_for_response(hbus->hdev, &comp_pkt.host_event))
+		goto error;
 
 	hpdev->desc = *desc;
 	refcount_set(&hpdev->refs, 1);
@@ -2070,15 +2091,16 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev)
 				sizeof(struct pci_version_request),
 				(unsigned long)pkt, VM_PKT_DATA_INBAND,
 				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+		if (!ret)
+			ret = wait_for_response(hdev, &comp_pkt.host_event);
+
 		if (ret) {
 			dev_err(&hdev->device,
-				"PCI Pass-through VSP failed sending version reqquest: %#x",
+				"PCI Pass-through VSP failed to request version: %d",
 				ret);
 			goto exit;
 		}
 
-		wait_for_completion(&comp_pkt.host_event);
-
 		if (comp_pkt.completion_status >= 0) {
 			pci_protocol_version = pci_protocol_versions[i];
 			dev_info(&hdev->device,
@@ -2287,11 +2309,12 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
 	ret = vmbus_sendpacket(hdev->channel, d0_entry, sizeof(*d0_entry),
 			       (unsigned long)pkt, VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (!ret)
+		ret = wait_for_response(hdev, &comp_pkt.host_event);
+
 	if (ret)
 		goto exit;
 
-	wait_for_completion(&comp_pkt.host_event);
-
 	if (comp_pkt.completion_status < 0) {
 		dev_err(&hdev->device,
 			"PCI Pass-through VSP failed D0 Entry with status %x\n",
@@ -2331,11 +2354,10 @@ static int hv_pci_query_relations(struct hv_device *hdev)
 
 	ret = vmbus_sendpacket(hdev->channel, &message, sizeof(message),
 			       0, VM_PKT_DATA_INBAND, 0);
-	if (ret)
-		return ret;
+	if (!ret)
+		ret = wait_for_response(hdev, &comp);
 
-	wait_for_completion(&comp);
-	return 0;
+	return ret;
 }
 
 /**
@@ -2405,11 +2427,11 @@ static int hv_send_resources_allocated(struct hv_device *hdev)
 				size_res, (unsigned long)pkt,
 				VM_PKT_DATA_INBAND,
 				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+		if (!ret)
+			ret = wait_for_response(hdev, &comp_pkt.host_event);
 		if (ret)
 			break;
 
-		wait_for_completion(&comp_pkt.host_event);
-
 		if (comp_pkt.completion_status < 0) {
 			ret = -EPROTO;
 			dev_err(&hdev->device,
-- 
2.7.4

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2018-05-31 21:16 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-23 21:12 [PATCH] PCI: hv: Do not wait forever on a device that has disappeared Dexuan Cui
2018-05-23 21:12 ` Dexuan Cui
2018-05-24 12:41 ` Lorenzo Pieralisi
2018-05-24 12:41   ` Lorenzo Pieralisi
2018-05-24 23:55   ` Dexuan Cui
2018-05-24 23:55     ` Dexuan Cui
2018-05-24 23:55     ` Dexuan Cui
2018-05-25 10:29     ` Lorenzo Pieralisi
2018-05-25 10:29       ` Lorenzo Pieralisi
2018-05-25 11:43 ` Haiyang Zhang
2018-05-25 11:43   ` Haiyang Zhang
2018-05-25 11:43   ` Haiyang Zhang
2018-05-25 13:56 ` Lorenzo Pieralisi
2018-05-25 13:56   ` Lorenzo Pieralisi
2018-05-29  0:19 ` Michael Kelley (EOSG)
2018-05-29  0:19   ` Michael Kelley (EOSG)
2018-05-29  0:19   ` Michael Kelley (EOSG)
2018-05-29 19:58   ` Dexuan Cui
2018-05-29 19:58     ` Dexuan Cui
2018-05-29 19:58     ` Dexuan Cui
2018-05-31 16:40     ` Michael Kelley (EOSG)
2018-05-31 16:40       ` Michael Kelley (EOSG)
2018-05-31 16:40       ` Michael Kelley (EOSG)
2018-05-31 21:01       ` Dexuan Cui
2018-05-31 21:01         ` Dexuan Cui
2018-05-31 21:01         ` Dexuan Cui
2018-05-29 21:20 ` Andy Shevchenko
2018-05-29 21:20   ` Andy Shevchenko
2018-05-29 21:28   ` Dexuan Cui
2018-05-29 21:28     ` Dexuan Cui
2018-05-29 21:28     ` Dexuan Cui

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.