@@ -15,6 +15,7 @@
#define NR_DEVSEC_BUSES 1
#define NR_DEVSEC_ROOT_PORTS 1
+#define NR_PLATFORM_STREAMS 4
#define NR_PORT_STREAMS 1
#define NR_ADDR_ASSOC 1
#define NR_DEVSEC_DEVS 1
@@ -589,6 +590,7 @@ static int __init devsec_bus_probe(struct platform_device *pdev)
struct devsec *devsec;
struct pci_sysdata *sd;
u64 mmio_size = SZ_64G;
+ struct pci_host_bridge *hb;
struct device *dev = &pdev->dev;
u64 mmio_start = iomem_resource.end + 1 - SZ_64G;
@@ -649,6 +651,9 @@ static int __init devsec_bus_probe(struct platform_device *pdev)
if (rc)
return rc;
+ hb = pci_find_host_bridge(devsec->bus);
+ pci_ide_init_nr_streams(hb, NR_PLATFORM_STREAMS);
+
pci_scan_child_bus(devsec->bus);
return 0;
@@ -688,5 +693,6 @@ static void __exit devsec_bus_exit(void)
}
module_exit(devsec_bus_exit);
+MODULE_IMPORT_NS("PCI_IDE");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Device Security Sample Infrastructure: TDISP Device Emulation");
@@ -4,6 +4,7 @@
#define dev_fmt(fmt) "devsec: " fmt
#include <linux/platform_device.h>
#include <linux/pci-tsm.h>
+#include <linux/pci-ide.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/tsm.h>
@@ -50,13 +51,83 @@ static void devsec_tsm_pci_remove(struct pci_tsm *tsm)
kfree(devsec_tsm);
}
+/* protected by tsm_ops lock */
+static DECLARE_BITMAP(devsec_stream_ids, NR_TSM_STREAMS);
+static struct pci_ide *devsec_streams[NR_TSM_STREAMS];
+
static int devsec_tsm_connect(struct pci_dev *pdev)
{
- return -ENXIO;
+ struct pci_dev *rp = pcie_find_root_port(pdev);
+ struct pci_ide *ide;
+ int rc, stream_id;
+
+ stream_id =
+ find_first_zero_bit(devsec_stream_ids, NR_TSM_STREAMS);
+ if (stream_id == NR_TSM_STREAMS)
+ return -EBUSY;
+ set_bit(stream_id, devsec_stream_ids);
+
+ ide = pci_ide_stream_alloc(pdev);
+ if (!ide) {
+ rc = -ENOMEM;
+ goto err_stream_alloc;
+ }
+
+ ide->stream_id = stream_id;
+ rc = pci_ide_stream_register(ide);
+ if (rc)
+ goto err_stream;
+
+ pci_ide_stream_setup(pdev, ide);
+ pci_ide_stream_setup(rp, ide);
+
+ rc = tsm_ide_stream_register(pdev, ide);
+ if (rc)
+ goto err_tsm;
+
+ /*
+ * Model a TSM that handled enabling the stream at
+ * tsm_ide_stream_register() time
+ */
+ pci_ide_stream_enable(pdev, ide);
+ devsec_streams[stream_id] = ide;
+
+ return 0;
+
+err_tsm:
+ pci_ide_stream_teardown(rp, ide);
+ pci_ide_stream_teardown(pdev, ide);
+ pci_ide_stream_unregister(ide);
+err_stream:
+ pci_ide_stream_free(ide);
+err_stream_alloc:
+ clear_bit(stream_id, devsec_stream_ids);
+
+ return rc;
}
static void devsec_tsm_disconnect(struct pci_dev *pdev)
{
+ struct pci_dev *rp = pcie_find_root_port(pdev);
+ struct pci_ide *ide;
+ int i;
+
+ for_each_set_bit(i, devsec_stream_ids, NR_TSM_STREAMS)
+ if (devsec_streams[i]->pdev == pdev)
+ break;
+
+ if (i >= NR_TSM_STREAMS)
+ return;
+
+ ide = devsec_streams[i];
+ devsec_streams[i] = NULL;
+ pci_ide_stream_disable(pdev, ide);
+ tsm_ide_stream_unregister(ide);
+ pci_ide_stream_teardown(rp, ide);
+ pci_ide_stream_teardown(pdev, ide);
+ pci_ide_stream_unregister(ide);
+ pci_ide_stream_free(ide);
+ clear_bit(i, devsec_stream_ids);
}
static const struct pci_tsm_ops devsec_pci_ops = {
Exercise common setup and teardown flows for a sample platform TSM driver that implements the TSM 'connect' and 'disconnect' flows. This is both a template for platform specific implementations and a simple integration test for the PCI core infrastructure + ABI. Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Lukas Wunner <lukas@wunner.de> Cc: Samuel Ortiz <sameo@rivosinc.com> Cc: Alexey Kardashevskiy <aik@amd.com> Cc: Xu Yilun <yilun.xu@linux.intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- samples/devsec/bus.c | 6 ++++ samples/devsec/tsm.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-)