diff options
author | Sumit Garg <sumit.garg@linaro.org> | 2019-01-29 11:19:35 +0530 |
---|---|---|
committer | Jens Wiklander <jens.wiklander@linaro.org> | 2019-02-01 15:12:46 +0100 |
commit | 0fc1db9d105915021260eb241661b8e96f5c0f1a (patch) | |
tree | 5e5d608e2a01aaeec416ade44d47036638ad7289 /drivers/tee | |
parent | 42bf4152d8a79f89f5456dee63a1f364fbce2dd6 (diff) |
tee: add bus driver framework for TEE based devices
Introduce a generic TEE bus driver concept for TEE based kernel drivers
which would like to communicate with TEE based devices/services. Also
add support in module device table for these new TEE based devices.
In this TEE bus concept, devices/services are identified via Universally
Unique Identifier (UUID) and drivers register a table of device UUIDs
which they can support.
So this TEE bus framework registers following apis:
- match(): Iterates over the driver UUID table to find a corresponding
match for device UUID. If a match is found, then this particular device
is probed via corresponding probe api registered by the driver. This
process happens whenever a device or a driver is registered with TEE
bus.
- uevent(): Notifies user-space (udev) whenever a new device is registered
on this bus for auto-loading of modularized drivers.
Also this framework allows for device enumeration to be specific to
corresponding TEE implementation like OP-TEE etc.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
Reviewed-by: Bhupesh Sharma <bhsharma@redhat.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'drivers/tee')
-rw-r--r-- | drivers/tee/tee_core.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index adf2588282fc..25f3b9cc8908 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -15,7 +15,6 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include <linux/cdev.h> -#include <linux/device.h> #include <linux/fs.h> #include <linux/idr.h> #include <linux/module.h> @@ -1040,6 +1039,39 @@ int tee_client_invoke_func(struct tee_context *ctx, } EXPORT_SYMBOL_GPL(tee_client_invoke_func); +static int tee_client_device_match(struct device *dev, + struct device_driver *drv) +{ + const struct tee_client_device_id *id_table; + struct tee_client_device *tee_device; + + id_table = to_tee_client_driver(drv)->id_table; + tee_device = to_tee_client_device(dev); + + while (!uuid_is_null(&id_table->uuid)) { + if (uuid_equal(&tee_device->id.uuid, &id_table->uuid)) + return 1; + id_table++; + } + + return 0; +} + +static int tee_client_device_uevent(struct device *dev, + struct kobj_uevent_env *env) +{ + uuid_t *dev_id = &to_tee_client_device(dev)->id.uuid; + + return add_uevent_var(env, "MODALIAS=tee:%pUb", dev_id); +} + +struct bus_type tee_bus_type = { + .name = "tee", + .match = tee_client_device_match, + .uevent = tee_client_device_uevent, +}; +EXPORT_SYMBOL_GPL(tee_bus_type); + static int __init tee_init(void) { int rc; @@ -1053,18 +1085,32 @@ static int __init tee_init(void) rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee"); if (rc) { pr_err("failed to allocate char dev region\n"); - class_destroy(tee_class); - tee_class = NULL; + goto out_unreg_class; + } + + rc = bus_register(&tee_bus_type); + if (rc) { + pr_err("failed to register tee bus\n"); + goto out_unreg_chrdev; } + return 0; + +out_unreg_chrdev: + unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); +out_unreg_class: + class_destroy(tee_class); + tee_class = NULL; + return rc; } static void __exit tee_exit(void) { + bus_unregister(&tee_bus_type); + unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); class_destroy(tee_class); tee_class = NULL; - unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); } subsys_initcall(tee_init); |