Merge tag 'char-misc-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[deliverable/linux.git] / drivers / pci / host / pci-hyperv.c
index f2559b6497467057f93f65e4d83580f7d5388c44..7e9b2de2aa24b64306a764d127348db9f91cbe9f 100644 (file)
@@ -553,6 +553,8 @@ static void _hv_pcifront_read_config(struct hv_pci_dev *hpdev, int where,
                spin_lock_irqsave(&hpdev->hbus->config_lock, flags);
                /* Choose the function to be read. (See comment above) */
                writel(hpdev->desc.win_slot.slot, hpdev->hbus->cfg_addr);
+               /* Make sure the function was chosen before we start reading. */
+               mb();
                /* Read from that function's config space. */
                switch (size) {
                case 1:
@@ -565,6 +567,11 @@ static void _hv_pcifront_read_config(struct hv_pci_dev *hpdev, int where,
                        *val = readl(addr);
                        break;
                }
+               /*
+                * Make sure the write was done before we release the spinlock
+                * allowing consecutive reads/writes.
+                */
+               mb();
                spin_unlock_irqrestore(&hpdev->hbus->config_lock, flags);
        } else {
                dev_err(&hpdev->hbus->hdev->device,
@@ -592,6 +599,8 @@ static void _hv_pcifront_write_config(struct hv_pci_dev *hpdev, int where,
                spin_lock_irqsave(&hpdev->hbus->config_lock, flags);
                /* Choose the function to be written. (See comment above) */
                writel(hpdev->desc.win_slot.slot, hpdev->hbus->cfg_addr);
+               /* Make sure the function was chosen before we start writing. */
+               wmb();
                /* Write to that function's config space. */
                switch (size) {
                case 1:
@@ -604,6 +613,11 @@ static void _hv_pcifront_write_config(struct hv_pci_dev *hpdev, int where,
                        writel(val, addr);
                        break;
                }
+               /*
+                * Make sure the write was done before we release the spinlock
+                * allowing consecutive reads/writes.
+                */
+               mb();
                spin_unlock_irqrestore(&hpdev->hbus->config_lock, flags);
        } else {
                dev_err(&hpdev->hbus->hdev->device,
@@ -2268,11 +2282,6 @@ static int hv_pci_remove(struct hv_device *hdev)
 
        hbus = hv_get_drvdata(hdev);
 
-       ret = hv_send_resources_released(hdev);
-       if (ret)
-               dev_err(&hdev->device,
-                       "Couldn't send resources released packet(s)\n");
-
        memset(&pkt.teardown_packet, 0, sizeof(pkt.teardown_packet));
        init_completion(&comp_pkt.host_event);
        pkt.teardown_packet.completion_func = hv_pci_generic_compl;
@@ -2295,6 +2304,11 @@ static int hv_pci_remove(struct hv_device *hdev)
                pci_unlock_rescan_remove();
        }
 
+       ret = hv_send_resources_released(hdev);
+       if (ret)
+               dev_err(&hdev->device,
+                       "Couldn't send resources released packet(s)\n");
+
        vmbus_close(hdev->channel);
 
        /* Delete any children which might still exist. */
This page took 0.026054 seconds and 5 git commands to generate.