Commit 909a8ec8 authored by Long Li's avatar Long Li Committed by Thadeu Lima de Souza Cascardo

UBUNTU: SAUCE: pci-hyperv: properly handle pci bus remove

BugLink: http://bugs.launchpad.net/bugs/1665097

hv_pci_devices_present is called in hv_pci_remove when we remove a PCI
device from host (e.g. by disabling SRIOV on a device). In hv_pci_remove,
the bus is already removed before the call, so we don't need to rescan the
bus in the workqueue scheduled from hv_pci_devices_present. By introducing
status hv_pcibus_removed, we can avoid this situation.
Signed-off-by: default avatarLong Li <longli@microsoft.com>
Reported-by: default avatarXiaofeng Wang <xiaofwan@redhat.com>
Signed-off-by: default avatarJoseph Salisbury <joseph.salisbury@canonical.com>
Acked-by: default avatarTim Gardner <tim.gardner@canonical.com>
Acked-by: default avatarBrad Figg <brad.figg@canonical.com>
Signed-off-by: default avatarThadeu Lima de Souza Cascardo <cascardo@canonical.com>
parent ecc705cb
...@@ -350,6 +350,7 @@ enum hv_pcibus_state { ...@@ -350,6 +350,7 @@ enum hv_pcibus_state {
hv_pcibus_init = 0, hv_pcibus_init = 0,
hv_pcibus_probed, hv_pcibus_probed,
hv_pcibus_installed, hv_pcibus_installed,
hv_pcibus_removed,
hv_pcibus_maximum hv_pcibus_maximum
}; };
...@@ -1484,13 +1485,24 @@ static void pci_devices_present_work(struct work_struct *work) ...@@ -1484,13 +1485,24 @@ static void pci_devices_present_work(struct work_struct *work)
put_pcichild(hpdev, hv_pcidev_ref_initial); put_pcichild(hpdev, hv_pcidev_ref_initial);
} }
/* Tell the core to rescan bus because there may have been changes. */ switch (hbus->state) {
if (hbus->state == hv_pcibus_installed) { case hv_pcibus_installed:
/*
* Tell the core to rescan bus
* because there may have been changes.
*/
pci_lock_rescan_remove(); pci_lock_rescan_remove();
pci_scan_child_bus(hbus->pci_bus); pci_scan_child_bus(hbus->pci_bus);
pci_unlock_rescan_remove(); pci_unlock_rescan_remove();
} else { break;
case hv_pcibus_init:
case hv_pcibus_probed:
survey_child_resources(hbus); survey_child_resources(hbus);
break;
default:
break;
} }
up(&hbus->enum_sem); up(&hbus->enum_sem);
...@@ -2165,6 +2177,7 @@ static int hv_pci_probe(struct hv_device *hdev, ...@@ -2165,6 +2177,7 @@ static int hv_pci_probe(struct hv_device *hdev,
hbus = kzalloc(sizeof(*hbus), GFP_KERNEL); hbus = kzalloc(sizeof(*hbus), GFP_KERNEL);
if (!hbus) if (!hbus)
return -ENOMEM; return -ENOMEM;
hbus->state = hv_pcibus_init;
/* /*
* The PCI bus "domain" is what is called "segment" in ACPI and * The PCI bus "domain" is what is called "segment" in ACPI and
...@@ -2307,6 +2320,7 @@ static int hv_pci_remove(struct hv_device *hdev) ...@@ -2307,6 +2320,7 @@ static int hv_pci_remove(struct hv_device *hdev)
pci_stop_root_bus(hbus->pci_bus); pci_stop_root_bus(hbus->pci_bus);
pci_remove_root_bus(hbus->pci_bus); pci_remove_root_bus(hbus->pci_bus);
pci_unlock_rescan_remove(); pci_unlock_rescan_remove();
hbus->state = hv_pcibus_removed;
} }
ret = hv_send_resources_released(hdev); ret = hv_send_resources_released(hdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment