PCI: hv: Reorganize the code in preparation of hibernation
authorDexuan Cui <decui@microsoft.com>
Mon, 25 Nov 2019 05:33:51 +0000 (21:33 -0800)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tue, 26 Nov 2019 10:31:33 +0000 (10:31 +0000)
There is no functional change. This is just preparatory for a later
patch which adds the hibernation support for the pci-hyperv driver.

Signed-off-by: Dexuan Cui <decui@microsoft.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
drivers/pci/controller/pci-hyperv.c

index f1f3002..65f18f8 100644 (file)
@@ -2379,7 +2379,9 @@ static void hv_pci_onchannelcallback(void *context)
  * failing if the host doesn't support the necessary protocol
  * level.
  */
-static int hv_pci_protocol_negotiation(struct hv_device *hdev)
+static int hv_pci_protocol_negotiation(struct hv_device *hdev,
+                                      enum pci_protocol_version_t version[],
+                                      int num_version)
 {
        struct pci_version_request *version_req;
        struct hv_pci_compl comp_pkt;
@@ -2403,8 +2405,8 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev)
        version_req = (struct pci_version_request *)&pkt->message;
        version_req->message_type.type = PCI_QUERY_PROTOCOL_VERSION;
 
-       for (i = 0; i < ARRAY_SIZE(pci_protocol_versions); i++) {
-               version_req->protocol_version = pci_protocol_versions[i];
+       for (i = 0; i < num_version; i++) {
+               version_req->protocol_version = version[i];
                ret = vmbus_sendpacket(hdev->channel, version_req,
                                sizeof(struct pci_version_request),
                                (unsigned long)pkt, VM_PKT_DATA_INBAND,
@@ -2420,7 +2422,7 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev)
                }
 
                if (comp_pkt.completion_status >= 0) {
-                       pci_protocol_version = pci_protocol_versions[i];
+                       pci_protocol_version = version[i];
                        dev_info(&hdev->device,
                                "PCI VMBus probing: Using version %#x\n",
                                pci_protocol_version);
@@ -2930,7 +2932,8 @@ static int hv_pci_probe(struct hv_device *hdev,
 
        hv_set_drvdata(hdev, hbus);
 
-       ret = hv_pci_protocol_negotiation(hdev);
+       ret = hv_pci_protocol_negotiation(hdev, pci_protocol_versions,
+                                         ARRAY_SIZE(pci_protocol_versions));
        if (ret)
                goto close;
 
@@ -3011,7 +3014,7 @@ free_bus:
        return ret;
 }
 
-static void hv_pci_bus_exit(struct hv_device *hdev)
+static int hv_pci_bus_exit(struct hv_device *hdev, bool hibernating)
 {
        struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
        struct {
@@ -3027,16 +3030,20 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
         * access the per-channel ringbuffer any longer.
         */
        if (hdev->channel->rescind)
-               return;
+               return 0;
 
-       /* Delete any children which might still exist. */
-       memset(&relations, 0, sizeof(relations));
-       hv_pci_devices_present(hbus, &relations);
+       if (!hibernating) {
+               /* Delete any children which might still exist. */
+               memset(&relations, 0, sizeof(relations));
+               hv_pci_devices_present(hbus, &relations);
+       }
 
        ret = hv_send_resources_released(hdev);
-       if (ret)
+       if (ret) {
                dev_err(&hdev->device,
                        "Couldn't send resources released packet(s)\n");
+               return ret;
+       }
 
        memset(&pkt.teardown_packet, 0, sizeof(pkt.teardown_packet));
        init_completion(&comp_pkt.host_event);
@@ -3049,8 +3056,13 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
                               (unsigned long)&pkt.teardown_packet,
                               VM_PKT_DATA_INBAND,
                               VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-       if (!ret)
-               wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ);
+       if (ret)
+               return ret;
+
+       if (wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ) == 0)
+               return -ETIMEDOUT;
+
+       return 0;
 }
 
 /**
@@ -3062,6 +3074,7 @@ static void hv_pci_bus_exit(struct hv_device *hdev)
 static int hv_pci_remove(struct hv_device *hdev)
 {
        struct hv_pcibus_device *hbus;
+       int ret;
 
        hbus = hv_get_drvdata(hdev);
        if (hbus->state == hv_pcibus_installed) {
@@ -3074,7 +3087,7 @@ static int hv_pci_remove(struct hv_device *hdev)
                hbus->state = hv_pcibus_removed;
        }
 
-       hv_pci_bus_exit(hdev);
+       ret = hv_pci_bus_exit(hdev, false);
 
        vmbus_close(hdev->channel);
 
@@ -3091,7 +3104,7 @@ static int hv_pci_remove(struct hv_device *hdev)
        hv_put_dom_num(hbus->sysdata.domain);
 
        free_page((unsigned long)hbus);
-       return 0;
+       return ret;
 }
 
 static const struct hv_vmbus_device_id hv_pci_id_table[] = {