[PATCH 8/8] hw/pci/pcie: Support forced PCIe native unplug
Dongli Zhang <[email protected]>
| Newsgroups | org.xenproject.lists.xen-devel,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
Support forced PCIe native unplug by implementing force_unplug method. The forced path completes the pending slot unplug immediately through the existing PCIe slot removal helper, clears the attention button pressed status bit, and notifies the hotplug event. Signed-off-by: Dongli Zhang <[email protected]> --- hw/pci/pcie.c | 20 ++++++++++++++++++++ hw/pci/pcie_port.c | 1 + include/hw/pci/pcie.h | 2 ++ 3 files changed, 23 insertions(+) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 4622c75e48..bd967ca73b 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -666,6 +666,26 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, pcie_cap_slot_push_attention_button(hotplug_pdev); } +void pcie_cap_slot_force_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); + uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; + uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); + + if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { + error_setg(errp, "Hot-unplug failed: " + "unsupported by the port device '%s'", + DEVICE(hotplug_pdev)->id); + return; + } + + pcie_cap_slot_do_unplug(hotplug_pdev); + pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_ABP); + hotplug_event_notify(hotplug_pdev); +} + /* pci express slot for pci express root/downstream port PCI express capability slot registers */ void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s) diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c index dbb6032160..4806c8289b 100644 --- a/hw/pci/pcie_port.c +++ b/hw/pci/pcie_port.c @@ -221,6 +221,7 @@ static void pcie_slot_class_init(ObjectClass *oc, const void *data) hc->plug = pcie_cap_slot_plug_cb; hc->unplug = pcie_cap_slot_unplug_cb; hc->unplug_request = pcie_cap_slot_unplug_request_cb; + hc->force_unplug = pcie_cap_slot_force_unplug_cb; hc->is_hotpluggable_bus = pcie_slot_is_hotpluggable_bus; } diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 71ba94874b..08c6c81f34 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -154,6 +154,8 @@ void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); +void pcie_cap_slot_force_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); void pcie_pasid_common_init(PCIDevice *dev, uint16_t offset, uint8_t pasid_width, bool exec_perm, bool priv_mod); -- 2.43.5