* [PATCH 1/2] PCI: use reset_root_port() for bus reset of devices on a root bus @ 2026-10-16 23:59 Hamza Mahfooz 2026-10-16 23:59 ` [PATCH 2/2] PCI: hv: add vPCI device reset support Hamza Mahfooz 0 siblings, 1 reply; 3+ messages in thread From: Hamza Mahfooz @ 2026-10-16 23:59 UTC (permalink / raw) To: linux-hyperv Cc: Haiyang Zhang, Wei Liu, Dexuan Cui, Jonathan Corbet, Randy Dunlap, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, linux-doc, linux-pci, Hamza Mahfooz The "bus" reset method resets a device by asserting Secondary Bus Reset on its upstream bridge, so it is not available for a device on a root bus, which has no upstream bridge. Some platforms have no Root Ports and expose PCI devices directly on a root bus, e.g., Hyper-V vPCI places each assigned PCI function directly on the root bus of a virtual host bridge. Such a device has no reset method at all if it supports neither FLR nor PM reset, even if the platform is able to reset it. pci_host_bridge::reset_root_port() already allows a host bridge to reset a device on a root bus in a platform-specific way, so far only in place of a Secondary Bus Reset by a Root Port. Use it for the "bus" reset method of a device that is the only device on a root bus, and wait for the device to become ready afterwards, as is done for other reset methods. Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> --- drivers/pci/pci.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8cc6a89130b5..fd4e958d6b99 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4924,18 +4924,46 @@ int pci_bridge_secondary_bus_reset(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_bridge_secondary_bus_reset); +static int pci_root_bus_reset(struct pci_dev *dev, bool probe) +{ + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus); + int rc; + + /* + * Bridges, e.g., Root Ports, are not eligible. Check the header type + * because dev->subordinate is not set up yet when the reset methods + * are probed during enumeration. + */ + if (pci_is_bridge(dev) || !host->reset_root_port) + return -ENOTTY; + + if (probe) + return 0; + + rc = host->reset_root_port(host, dev); + if (rc) + return rc; + + return pci_dev_wait(dev, "bus reset", PCIE_RESET_READY_POLL_MS); +} + static int pci_parent_bus_reset(struct pci_dev *dev, bool probe) { struct pci_dev *pdev; - if (pci_is_root_bus(dev->bus) || dev->subordinate || - !dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) + if (dev->subordinate || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) return -ENOTTY; list_for_each_entry(pdev, &dev->bus->devices, bus_list) if (pdev != dev) return -ENOTTY; + if (pci_is_root_bus(dev->bus)) + return pci_root_bus_reset(dev, probe); + + if (!dev->bus->self) + return -ENOTTY; + if (probe) return 0; -- 2.56.0 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] PCI: hv: add vPCI device reset support 2026-10-16 23:59 [PATCH 1/2] PCI: use reset_root_port() for bus reset of devices on a root bus Hamza Mahfooz @ 2026-10-16 23:59 ` Hamza Mahfooz 2026-10-17 0:12 ` sashiko-bot 0 siblings, 1 reply; 3+ messages in thread From: Hamza Mahfooz @ 2026-10-16 23:59 UTC (permalink / raw) To: linux-hyperv Cc: Haiyang Zhang, Wei Liu, Dexuan Cui, Jonathan Corbet, Randy Dunlap, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, linux-doc, linux-pci, Hamza Mahfooz Hyper-V vPCI protocol version 1.5 adds a RESET_DEVICE request for projected PCI functions. Negotiate the new protocol version and, when it is in use, implement the pci_host_bridge::reset_root_port() callback by issuing the request through the vPCI VMBus channel. Hyper-V has no Root Ports and exposes projected functions directly on the root bus, so PCI core uses the callback for the "bus" reset method of a function that is the only one on its vPCI bus. Use the existing VMBus response path. Return -ENOTTY when the host reports STATUS_NOT_SUPPORTED so PCI core may try another reset method. Co-developed-by: Wei Liu <wei.liu@kernel.org> Signed-off-by: Wei Liu <wei.liu@kernel.org> Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> --- Documentation/virt/hyperv/vpci.rst | 2 +- drivers/pci/controller/pci-hyperv.c | 54 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Documentation/virt/hyperv/vpci.rst b/Documentation/virt/hyperv/vpci.rst index b65b2126ede3..6bfee7225c14 100644 --- a/Documentation/virt/hyperv/vpci.rst +++ b/Documentation/virt/hyperv/vpci.rst @@ -65,7 +65,7 @@ exchange messages with the vPCI VSP for the purpose of setting up and configuring the vPCI device in Linux. Once the device is fully configured in Linux as a PCI device, the VMBus channel is used only if Linux changes the vCPU to be interrupted -in the guest, or if the vPCI device is removed from +in the guest, or if the vPCI device is reset or removed from the VM while the VM is running. The ongoing operation of the device happens directly between the Linux device driver for the device and the hardware, with VMBus and the VMBus channel diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 85d826f8f68d..790bf533a7e3 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -68,6 +68,7 @@ enum pci_protocol_version_t { PCI_PROTOCOL_VERSION_1_2 = PCI_MAKE_VERSION(1, 2), /* RS1 */ PCI_PROTOCOL_VERSION_1_3 = PCI_MAKE_VERSION(1, 3), /* Vibranium */ PCI_PROTOCOL_VERSION_1_4 = PCI_MAKE_VERSION(1, 4), /* WS2022 */ + PCI_PROTOCOL_VERSION_1_5 = PCI_MAKE_VERSION(1, 5), /* GE, device reset */ }; #define CPU_AFFINITY_ALL -1ULL @@ -77,6 +78,7 @@ enum pci_protocol_version_t { * first. */ static enum pci_protocol_version_t pci_protocol_versions[] = { + PCI_PROTOCOL_VERSION_1_5, PCI_PROTOCOL_VERSION_1_4, PCI_PROTOCOL_VERSION_1_3, PCI_PROTOCOL_VERSION_1_2, @@ -90,6 +92,7 @@ static enum pci_protocol_version_t pci_protocol_versions[] = { #define MAX_SUPPORTED_MSI_MESSAGES 0x400 #define STATUS_REVISION_MISMATCH 0xC0000059 +#define STATUS_NOT_SUPPORTED 0xC00000BB /* space for 32bit serial number as string */ #define SLOT_NAME_SIZE 11 @@ -136,6 +139,7 @@ enum pci_message_type { PCI_BUS_RELATIONS2 = PCI_MESSAGE_BASE + 0x19, PCI_RESOURCES_ASSIGNED3 = PCI_MESSAGE_BASE + 0x1A, PCI_CREATE_INTERRUPT_MESSAGE3 = PCI_MESSAGE_BASE + 0x1B, + PCI_RESET_DEVICE = PCI_MESSAGE_BASE + 0x1C, PCI_MESSAGE_MAXIMUM }; @@ -1416,6 +1420,52 @@ static int hv_pcifront_write_config(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_SUCCESSFUL; } +static int hv_pci_reset_device(struct pci_host_bridge *bridge, + struct pci_dev *pdev) +{ + struct hv_pcibus_device *hbus = + container_of(bridge->sysdata, struct hv_pcibus_device, sysdata); + struct pci_child_message reset = {}; + struct hv_pci_compl comp_pkt; + struct pci_packet pkt = { + .completion_func = hv_pci_generic_compl, + .compl_ctxt = &comp_pkt, + }; + enum hv_pcibus_state state; + int ret; + + /* Do not take state_lock: eject holds it while removing/locking pdev. */ + state = READ_ONCE(hbus->state); + if (state != hv_pcibus_probed && state != hv_pcibus_installed) + return -ENODEV; + + init_completion(&comp_pkt.host_event); + reset.message_type.type = PCI_RESET_DEVICE; + reset.wslot.slot = devfn_to_wslot(pdev->devfn); + + ret = vmbus_sendpacket(hbus->hdev->channel, &reset, sizeof(reset), + (unsigned long)&pkt, VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (ret) + return ret; + + ret = wait_for_response(hbus->hdev, &comp_pkt.host_event, + "PCI_RESET_DEVICE"); + if (ret) + return ret; + + if (comp_pkt.completion_status == STATUS_NOT_SUPPORTED) + return -ENOTTY; + + if (comp_pkt.completion_status) { + pci_err(pdev, "Hyper-V device reset failed: %#x\n", + comp_pkt.completion_status); + return -EIO; + } + + return 0; +} + /* PCIe operations */ static struct pci_ops hv_pcifront_ops = { .read = hv_pcifront_read_config, @@ -2017,6 +2067,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) break; case PCI_PROTOCOL_VERSION_1_4: + case PCI_PROTOCOL_VERSION_1_5: size = hv_compose_msi_req_v3(&ctxt.int_pkts.v3, cpu, hpdev->desc.win_slot.slot, @@ -2546,6 +2597,9 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus) bridge->sysdata = &hbus->sysdata; bridge->ops = &hv_pcifront_ops; + if (hbus->protocol_version >= PCI_PROTOCOL_VERSION_1_5) + bridge->reset_root_port = hv_pci_reset_device; + error = pci_scan_root_bus_bridge(bridge); if (error) return error; -- 2.56.0 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 2/2] PCI: hv: add vPCI device reset support 2026-10-16 23:59 ` [PATCH 2/2] PCI: hv: add vPCI device reset support Hamza Mahfooz @ 2026-10-17 0:12 ` sashiko-bot 0 siblings, 0 replies; 3+ messages in thread From: sashiko-bot @ 2026-10-17 0:12 UTC (permalink / raw) To: Hamza Mahfooz, linux-hyperv; +Cc: linux-pci Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] PCI: hv: hv_pci_reset_device() passes 3 arguments to wait_for_response() -- commit 5767f2b6950e5dc7da0b5c142f971d8282c27a56 Author: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> PCI: hv: add vPCI device reset support This commit negotiates Hyper-V vPCI protocol version 1.5 and implements the reset_root_port() callback on pci_host_bridge by sending a PCI_RESET_DEVICE request over the vPCI VMBus channel. > diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c > index 89816a2bd7cd3..4bb4ca6da1f7b 100644 > --- a/drivers/pci/controller/pci-hyperv.c > +++ b/drivers/pci/controller/pci-hyperv.c [ ... ] > @@ -1397,6 +1401,52 @@ static int hv_pcifront_write_config(struct pci_bus *bus, unsigned int devfn, > return PCIBIOS_SUCCESSFUL; > } > > +static int hv_pci_reset_device(struct pci_host_bridge *bridge, > + struct pci_dev *pdev) > +{ > + struct hv_pcibus_device *hbus = > + container_of(bridge->sysdata, struct hv_pcibus_device, sysdata); > + struct pci_child_message reset = {}; > + struct hv_pci_compl comp_pkt; > + struct pci_packet pkt = { > + .completion_func = hv_pci_generic_compl, > + .compl_ctxt = &comp_pkt, > + }; > + enum hv_pcibus_state state; > + int ret; > + > + /* Do not take state_lock: eject holds it while removing/locking pdev. */ > + state = READ_ONCE(hbus->state); > + if (state != hv_pcibus_probed && state != hv_pcibus_installed) > + return -ENODEV; > + > + init_completion(&comp_pkt.host_event); > + reset.message_type.type = PCI_RESET_DEVICE; > + reset.wslot.slot = devfn_to_wslot(pdev->devfn); > + > + ret = vmbus_sendpacket(hbus->hdev->channel, &reset, sizeof(reset), > + (unsigned long)&pkt, VM_PKT_DATA_INBAND, > + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); > + if (ret) > + return ret; > + > + ret = wait_for_response(hbus->hdev, &comp_pkt.host_event, > + "PCI_RESET_DEVICE"); [Severity: Low] Does this compile when CONFIG_PCI_HYPERV is enabled? In drivers/pci/controller/pci-hyperv.c, wait_for_response() only accepts two arguments: static int wait_for_response(struct hv_device *hdev, struct completion *comp) Passing "PCI_RESET_DEVICE" as a third argument in hv_pci_reset_device() causes the build to fail with too many arguments to wait_for_response(). > + if (ret) > + return ret; > + > + if (comp_pkt.completion_status == STATUS_NOT_SUPPORTED) > + return -ENOTTY; > + > + if (comp_pkt.completion_status) { > + pci_err(pdev, "Hyper-V device reset failed: %#x\n", > + comp_pkt.completion_status); > + return -EIO; > + } > + > + return 0; > +} [ ... ] -- Sashiko AI review · https://sashiko.dev/#/patchset/20261016235940.942090-1-hamzamahfooz@linux.microsoft.com?part=2 ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-17 0:12 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-16 23:59 [PATCH 1/2] PCI: use reset_root_port() for bus reset of devices on a root bus Hamza Mahfooz 2026-10-16 23:59 ` [PATCH 2/2] PCI: hv: add vPCI device reset support Hamza Mahfooz 2026-10-17 0:12 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox