On Wed, Apr 10, 2024 at 12:07:40PM +0200, Lukas Wunner wrote: > --- a/drivers/pci/hotplug/pciehp_core.c > +++ b/drivers/pci/hotplug/pciehp_core.c > @@ -152,6 +152,25 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) > return 0; > } > > +static bool pciehp_device_replaced(struct controller *ctrl) > +{ > + struct pci_dev *pdev; I've realized this needs to be + struct pci_dev *pdev __free(pci_dev_put); to avoid leaking a ref on the child device. For testing purposes, the patch should still be fine without this change, but I'll have to fix this up if/when submitting a proper patch. > + u32 reg; > + > + pdev = pci_get_slot(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0)); > + if (!pdev) > + return true; > + > + if (!pci_bus_read_dev_vendor_id(ctrl->pcie->port->subordinate, > + PCI_DEVFN(0, 0), ®, 0)) > + return true; > + > + if (reg != (pdev->vendor | (pdev->device << 16))) > + return true; > + > + return false; > +} > + > /** > * pciehp_check_presence() - synthesize event if presence has changed > * @ctrl: controller to check > @@ -172,7 +191,8 @@ static void pciehp_check_presence(struct controller *ctrl) > > occupied = pciehp_card_present_or_link_active(ctrl); > if ((occupied > 0 && (ctrl->state == OFF_STATE || > - ctrl->state == BLINKINGON_STATE)) || > + ctrl->state == BLINKINGON_STATE || > + pciehp_device_replaced(ctrl))) || > (!occupied && (ctrl->state == ON_STATE || > ctrl->state == BLINKINGOFF_STATE))) > pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC);