Re: [PATCH v5 5/5] PCI: endpoint: pci-epf-vntb: manage ntb_dev lifetime and fix vpci bus teardown
Manivannan Sadhasivam <[email protected]> Tue, 3 Mar 2026 10:52:05 +0530
| Newsgroups | dev.linux.lists.ntb,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <f3tt2dt63el5v7lzqabgnjcs2vrcj44xot2nrbkxjnqcpmyivs@o6xdl2aarsbi> |
On Thu, Feb 26, 2026 at 05:41:42PM +0900, Koichiro Den wrote: > Currently ntb_dev is embedded in epf_ntb, while configfs allows starting > or stopping controller and linking or unlinking functions as you want. > In fact, re-linking and re-starting is not possible with the embedded > design and leads to oopses. > > Allocate ntb_dev with devm and add a .remove callback to the pci driver > that calls ntb_unregister_device(). This allows a fresh device to be > created on the next .bind call. > > With these changes, the controller can now be stopped, a function > unlinked, configfs settings updated, and the controller re-linked and > restarted without rebooting the endpoint, as long as the underlying > pci_epc_ops .stop() operation is non-destructive, and .start() can > restore normal operations. > > Reviewed-by: Frank Li <[email protected]> > Signed-off-by: Koichiro Den <[email protected]> > --- > Changes since v4: > - Adjusted context due to commit: > dc693d606644 ("PCI: endpoint: pci-epf-vntb: Add MSI doorbell support") > > drivers/pci/endpoint/functions/pci-epf-vntb.c | 53 ++++++++++++++----- > 1 file changed, 40 insertions(+), 13 deletions(-) > > diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c > index f353e9a57194..41a2f42e8a39 100644 > --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c > +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c > @@ -120,7 +120,7 @@ struct epf_ntb_ctrl { > } __packed; > > struct epf_ntb { > - struct ntb_dev ntb; > + struct ntb_dev *ntb; > struct pci_epf *epf; > struct config_group group; > > @@ -147,10 +147,16 @@ struct epf_ntb { > void __iomem *vpci_mw_addr[MAX_MW]; > > struct delayed_work cmd_handler; > + > + struct pci_bus *vpci_bus; > }; > > #define to_epf_ntb(epf_group) container_of((epf_group), struct epf_ntb, group) > -#define ntb_ndev(__ntb) container_of(__ntb, struct epf_ntb, ntb) > + > +static inline struct epf_ntb *ntb_ndev(struct ntb_dev *ntb) Nit: No need of 'inline' keyword in a .c file. - Mani > +{ > + return (struct epf_ntb *)ntb->pdev->sysdata; > +} > > static struct pci_epf_header epf_ntb_header = { > .vendorid = PCI_ANY_ID, > @@ -176,7 +182,7 @@ static int epf_ntb_link_up(struct epf_ntb *ntb, bool link_up) > else > ntb->reg->link_status &= ~LINK_STATUS_UP; > > - ntb_link_event(&ntb->ntb); > + ntb_link_event(ntb->ntb); > return 0; > } > > @@ -264,7 +270,7 @@ static void epf_ntb_cmd_handler(struct work_struct *work) > for (i = 1; i < ntb->db_count && !ntb->msi_doorbell; i++) { > if (ntb->epf_db[i]) { > atomic64_or(1 << (i - 1), &ntb->db); > - ntb_db_event(&ntb->ntb, i); > + ntb_db_event(ntb->ntb, i); > ntb->epf_db[i] = 0; > } > } > @@ -333,7 +339,7 @@ static irqreturn_t epf_ntb_doorbell_handler(int irq, void *data) > for (i = 1; i < ntb->db_count; i++) > if (irq == ntb->epf->db_msg[i].virq) { > atomic64_or(1 << (i - 1), &ntb->db); > - ntb_db_event(&ntb->ntb, i); > + ntb_db_event(ntb->ntb, i); > } > > return IRQ_HANDLED; > @@ -1237,6 +1243,7 @@ static int vpci_scan_bus(void *sysdata) > pr_err("create pci bus failed\n"); > return -EINVAL; > } > + ndev->vpci_bus = vpci_bus; > > pci_bus_add_devices(vpci_bus); > > @@ -1281,7 +1288,7 @@ static int vntb_epf_mw_set_trans(struct ntb_dev *ndev, int pidx, int idx, > int ret; > struct device *dev; > > - dev = &ntb->ntb.dev; > + dev = &ntb->ntb->dev; > barno = ntb->epf_ntb_bar[BAR_MW1 + idx]; > epf_bar = &ntb->epf->bar[barno]; > epf_bar->phys_addr = addr; > @@ -1381,7 +1388,7 @@ static int vntb_epf_peer_db_set(struct ntb_dev *ndev, u64 db_bits) > ret = pci_epc_raise_irq(ntb->epf->epc, func_no, vfunc_no, > PCI_IRQ_MSI, interrupt_num + 1); > if (ret) > - dev_err(&ntb->ntb.dev, "Failed to raise IRQ\n"); > + dev_err(&ntb->ntb->dev, "Failed to raise IRQ\n"); > > return ret; > } > @@ -1468,9 +1475,12 @@ static int pci_vntb_probe(struct pci_dev *pdev, const struct pci_device_id *id) > struct epf_ntb *ndev = (struct epf_ntb *)pdev->sysdata; > struct device *dev = &pdev->dev; > > - ndev->ntb.pdev = pdev; > - ndev->ntb.topo = NTB_TOPO_NONE; > - ndev->ntb.ops = &vntb_epf_ops; > + ndev->ntb = devm_kzalloc(dev, sizeof(*ndev->ntb), GFP_KERNEL); > + if (!ndev->ntb) > + return -ENOMEM; > + ndev->ntb->pdev = pdev; > + ndev->ntb->topo = NTB_TOPO_NONE; > + ndev->ntb->ops = &vntb_epf_ops; > > ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); > if (ret) { > @@ -1478,7 +1488,7 @@ static int pci_vntb_probe(struct pci_dev *pdev, const struct pci_device_id *id) > return ret; > } > > - ret = ntb_register_device(&ndev->ntb); > + ret = ntb_register_device(ndev->ntb); > if (ret) { > dev_err(dev, "Failed to register NTB device\n"); > return ret; > @@ -1488,6 +1498,17 @@ static int pci_vntb_probe(struct pci_dev *pdev, const struct pci_device_id *id) > return 0; > } > > +static void pci_vntb_remove(struct pci_dev *pdev) > +{ > + struct epf_ntb *ndev = (struct epf_ntb *)pdev->sysdata; > + > + if (!ndev || !ndev->ntb) > + return; > + > + ntb_unregister_device(ndev->ntb); > + ndev->ntb = NULL; > +} > + > static struct pci_device_id pci_vntb_table[] = { > { > PCI_DEVICE(0xffff, 0xffff), > @@ -1499,6 +1520,7 @@ static struct pci_driver vntb_pci_driver = { > .name = "pci-vntb", > .id_table = pci_vntb_table, > .probe = pci_vntb_probe, > + .remove = pci_vntb_remove, > }; > > /* ============ PCIe EPF Driver Bind ====================*/ > @@ -1581,10 +1603,15 @@ static void epf_ntb_unbind(struct pci_epf *epf) > { > struct epf_ntb *ntb = epf_get_drvdata(epf); > > + pci_unregister_driver(&vntb_pci_driver); > + > + pci_lock_rescan_remove(); > + pci_stop_root_bus(ntb->vpci_bus); > + pci_remove_root_bus(ntb->vpci_bus); > + pci_unlock_rescan_remove(); > + > epf_ntb_epc_cleanup(ntb); > epf_ntb_config_spad_bar_free(ntb); > - > - pci_unregister_driver(&vntb_pci_driver); > } > > // EPF driver probe > -- > 2.51.0 > -- மணிவண்ணன் சதாசிவம்