1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */ 3 4 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 5 6 #include <linux/tsm.h> 7 #include <linux/pci.h> 8 #include <linux/rwsem.h> 9 #include <linux/device.h> 10 #include <linux/module.h> 11 #include <linux/cleanup.h> 12 #include <linux/pci-tsm.h> 13 #include <linux/pci-ide.h> 14 15 static struct class *tsm_class; 16 static DECLARE_RWSEM(tsm_rwsem); 17 static DEFINE_IDA(tsm_ida); 18 19 static int match_id(struct device *dev, const void *data) 20 { 21 struct tsm_dev *tsm_dev = container_of(dev, struct tsm_dev, dev); 22 int id = *(const int *)data; 23 24 return tsm_dev->id == id; 25 } 26 27 struct tsm_dev *find_tsm_dev(int id) 28 { 29 struct device *dev = class_find_device(tsm_class, NULL, &id, match_id); 30 31 if (!dev) 32 return NULL; 33 return container_of(dev, struct tsm_dev, dev); 34 } 35 36 static struct tsm_dev *alloc_tsm_dev(struct device *parent) 37 { 38 struct device *dev; 39 int id; 40 41 struct tsm_dev *tsm_dev __free(kfree) = 42 kzalloc(sizeof(*tsm_dev), GFP_KERNEL); 43 if (!tsm_dev) 44 return ERR_PTR(-ENOMEM); 45 46 id = ida_alloc(&tsm_ida, GFP_KERNEL); 47 if (id < 0) 48 return ERR_PTR(id); 49 50 tsm_dev->id = id; 51 dev = &tsm_dev->dev; 52 dev->parent = parent; 53 dev->class = tsm_class; 54 device_initialize(dev); 55 56 return no_free_ptr(tsm_dev); 57 } 58 59 static struct tsm_dev *tsm_register_pci_or_reset(struct tsm_dev *tsm_dev, 60 struct pci_tsm_ops *pci_ops) 61 { 62 int rc; 63 64 if (!pci_ops) 65 return tsm_dev; 66 67 tsm_dev->pci_ops = pci_ops; 68 rc = pci_tsm_register(tsm_dev); 69 if (rc) { 70 dev_err(tsm_dev->dev.parent, 71 "PCI/TSM registration failure: %d\n", rc); 72 device_unregister(&tsm_dev->dev); 73 return ERR_PTR(rc); 74 } 75 76 /* Notify TSM userspace that PCI/TSM operations are now possible */ 77 kobject_uevent(&tsm_dev->dev.kobj, KOBJ_CHANGE); 78 return tsm_dev; 79 } 80 81 struct tsm_dev *tsm_register(struct device *parent, struct pci_tsm_ops *pci_ops) 82 { 83 struct tsm_dev *tsm_dev __free(put_tsm_dev) = alloc_tsm_dev(parent); 84 struct device *dev; 85 int rc; 86 87 if (IS_ERR(tsm_dev)) 88 return tsm_dev; 89 90 dev = &tsm_dev->dev; 91 rc = dev_set_name(dev, "tsm%d", tsm_dev->id); 92 if (rc) 93 return ERR_PTR(rc); 94 95 rc = device_add(dev); 96 if (rc) 97 return ERR_PTR(rc); 98 99 return tsm_register_pci_or_reset(no_free_ptr(tsm_dev), pci_ops); 100 } 101 EXPORT_SYMBOL_GPL(tsm_register); 102 103 void tsm_unregister(struct tsm_dev *tsm_dev) 104 { 105 if (tsm_dev->pci_ops) 106 pci_tsm_unregister(tsm_dev); 107 device_unregister(&tsm_dev->dev); 108 } 109 EXPORT_SYMBOL_GPL(tsm_unregister); 110 111 /* must be invoked between tsm_register / tsm_unregister */ 112 int tsm_ide_stream_register(struct pci_ide *ide) 113 { 114 struct pci_dev *pdev = ide->pdev; 115 struct pci_tsm *tsm = pdev->tsm; 116 struct tsm_dev *tsm_dev = tsm->tsm_dev; 117 int rc; 118 119 rc = sysfs_create_link(&tsm_dev->dev.kobj, &pdev->dev.kobj, ide->name); 120 if (rc) 121 return rc; 122 123 ide->tsm_dev = tsm_dev; 124 return 0; 125 } 126 EXPORT_SYMBOL_GPL(tsm_ide_stream_register); 127 128 void tsm_ide_stream_unregister(struct pci_ide *ide) 129 { 130 struct tsm_dev *tsm_dev = ide->tsm_dev; 131 132 ide->tsm_dev = NULL; 133 sysfs_remove_link(&tsm_dev->dev.kobj, ide->name); 134 } 135 EXPORT_SYMBOL_GPL(tsm_ide_stream_unregister); 136 137 static void tsm_release(struct device *dev) 138 { 139 struct tsm_dev *tsm_dev = container_of(dev, typeof(*tsm_dev), dev); 140 141 ida_free(&tsm_ida, tsm_dev->id); 142 kfree(tsm_dev); 143 } 144 145 static int __init tsm_init(void) 146 { 147 tsm_class = class_create("tsm"); 148 if (IS_ERR(tsm_class)) 149 return PTR_ERR(tsm_class); 150 151 tsm_class->dev_release = tsm_release; 152 return 0; 153 } 154 module_init(tsm_init) 155 156 static void __exit tsm_exit(void) 157 { 158 class_destroy(tsm_class); 159 } 160 module_exit(tsm_exit) 161 162 MODULE_LICENSE("GPL"); 163 MODULE_DESCRIPTION("TEE Security Manager Class Device"); 164