* [PATCH RFC 1/2] PCI: Add controller reset method
2026-07-24 23:08 [PATCH RFC 0/2] Support Hyper-V vPCI controller reset method wei.liu
@ 2026-07-24 23:08 ` wei.liu
2026-07-24 23:16 ` sashiko-bot
2026-07-24 23:08 ` [PATCH RFC 2/2] PCI: hv: Add vPCI device reset support wei.liu
1 sibling, 1 reply; 5+ messages in thread
From: wei.liu @ 2026-07-24 23:08 UTC (permalink / raw)
To: Linux on Hyper-V List, linux-pci; +Cc: Wei Liu, Bjorn Helgaas, open list
From: Wei Liu <wei.liu@kernel.org>
Some PCI controllers provide a function reset mechanism that is not
advertised in PCI configuration space. Allow them to expose it through an
optional pci_ops callback.
Add the controller reset method to the standard reset_method interface.
Prefer FLR and AF FLR by default, and use the controller operation before
PM and bus reset fallbacks.
Signed-off-by: Wei Liu <wei.liu@kernel.org>
---
drivers/pci/pci.c | 22 ++++++++++++++++++++++
include/linux/pci.h | 3 ++-
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 77b17b13ee61..4e55da202cad 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4962,6 +4962,27 @@ static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
return rc;
}
+static int pci_controller_reset(struct pci_dev *dev, bool probe)
+{
+ int rc;
+
+ if (!dev->bus->ops->reset)
+ return -ENOTTY;
+
+ if (probe)
+ return dev->bus->ops->reset(dev, probe);
+
+ rc = pci_dev_reset_iommu_prepare(dev);
+ if (rc) {
+ pci_err(dev, "failed to stop IOMMU for a PCI reset: %d\n", rc);
+ return rc;
+ }
+
+ rc = dev->bus->ops->reset(dev, probe);
+ pci_dev_reset_iommu_done(dev);
+ return rc;
+}
+
static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
{
struct pci_dev *bridge;
@@ -5094,6 +5115,7 @@ const struct pci_reset_fn_method pci_reset_fn_methods[] = {
{ pci_dev_acpi_reset, .name = "acpi" },
{ pcie_reset_flr, .name = "flr" },
{ pci_af_flr, .name = "af_flr" },
+ { pci_controller_reset, .name = "controller" },
{ pci_pm_reset, .name = "pm" },
{ pci_reset_bus_function, .name = "bus" },
{ cxl_reset_bus_function, .name = "cxl_bus" },
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 64b308b6e61c..d7759ee70670 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -52,7 +52,7 @@
PCI_STATUS_PARITY)
/* Number of reset methods used in pci_reset_fn_methods array in pci.c */
-#define PCI_NUM_RESET_METHODS 8
+#define PCI_NUM_RESET_METHODS 9
#define PCI_RESET_PROBE true
#define PCI_RESET_DO_RESET false
@@ -875,6 +875,7 @@ struct pci_ops {
void __iomem *(*map_bus)(struct pci_bus *bus, unsigned int devfn, int where);
int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
+ int (*reset)(struct pci_dev *dev, bool probe);
};
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH RFC 2/2] PCI: hv: Add vPCI device reset support
2026-07-24 23:08 [PATCH RFC 0/2] Support Hyper-V vPCI controller reset method wei.liu
2026-07-24 23:08 ` [PATCH RFC 1/2] PCI: Add " wei.liu
@ 2026-07-24 23:08 ` wei.liu
2026-07-24 23:25 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: wei.liu @ 2026-07-24 23:08 UTC (permalink / raw)
To: Linux on Hyper-V List, linux-pci
Cc: Wei Liu, K. Y. Srinivasan, Haiyang Zhang, Dexuan Cui, Long Li,
Jonathan Corbet, Shuah Khan, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Bjorn Helgaas, open list:DOCUMENTATION, open list
From: Wei Liu <wei.liu@kernel.org>
Hyper-V vPCI protocol version 1.5 adds a RESET_DEVICE request for projected
PCI functions. Negotiate the new protocol version and issue the request
through the vPCI VMBus channel from the PCI controller reset callback.
Use the existing VMBus response path. Return -ENOTTY when the host reports
STATUS_NOT_SUPPORTED so PCI core may try another reset method.
Signed-off-by: Wei Liu <wei.liu@kernel.org>
---
Documentation/virt/hyperv/vpci.rst | 2 +-
drivers/pci/controller/pci-hyperv.c | 61 +++++++++++++++++++++++++++++
2 files changed, 62 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 cfc8fa403dad..d3c0fd5e1d8e 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
};
@@ -1397,10 +1401,66 @@ static int hv_pcifront_write_config(struct pci_bus *bus, unsigned int devfn,
return PCIBIOS_SUCCESSFUL;
}
+static int hv_pcifront_reset(struct pci_dev *pdev, bool probe)
+{
+ struct hv_pcibus_device *hbus =
+ container_of(pdev->bus->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;
+
+ /* Device reset was added in vPCI protocol version 1.5. */
+ if (hbus->protocol_version < PCI_PROTOCOL_VERSION_1_5)
+ return -ENOTTY;
+
+ /* Hyper-V exposes projected functions directly on the root bus. */
+ if (!pci_is_root_bus(pdev->bus))
+ return -ENOTTY;
+
+ if (probe)
+ return 0;
+
+ /* 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);
+ 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,
.write = hv_pcifront_write_config,
+ .reset = hv_pcifront_reset,
};
/*
@@ -1996,6 +2056,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,
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread