On Mon, Dec 01, 2025 at 12:11:00AM +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.
Signed-off-by: Koichiro Den den@valinux.co.jp
drivers/pci/endpoint/functions/pci-epf-vntb.c | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-)
...
@@ -1097,7 +1103,6 @@ static int vpci_scan_bus(void *sysdata) { struct pci_bus *vpci_bus; struct epf_ntb *ndev = sysdata;
Unneccsary change here.
Frank Li
LIST_HEAD(resources); static struct resource busn_res = { .start = 0, @@ -1115,6 +1120,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);
@@ -1159,7 +1165,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;
@@ -1259,7 +1265,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;
} @@ -1346,9 +1352,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) {
@@ -1356,7 +1365,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;
@@ -1366,6 +1375,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), @@ -1377,6 +1397,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 ====================*/ @@ -1459,10 +1480,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.48.1