From 2adaefb1458f67b3f71111fcf6a15670ab64101d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:02 +0100 Subject: greybus: hd: make host device a device Make the host device a proper device in the kernel device model. Host devices will be our new greybus-bus root devices. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/hd.c | 59 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 10 deletions(-) (limited to 'drivers/staging/greybus/hd.c') diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 3446fec..88d2f01 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -14,26 +14,30 @@ #include "greybus.h" -static DEFINE_MUTEX(hd_mutex); +static struct ida gb_hd_bus_id_map; -static void free_hd(struct kref *kref) +static void gb_hd_release(struct device *dev) { - struct gb_host_device *hd; - - hd = container_of(kref, struct gb_host_device, kref); + struct gb_host_device *hd = to_gb_host_device(dev); + ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); ida_destroy(&hd->cport_id_map); kfree(hd); - mutex_unlock(&hd_mutex); } +struct device_type greybus_hd_type = { + .name = "greybus_host_device", + .release = gb_hd_release, +}; + struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, struct device *parent, size_t buffer_size_max, size_t num_cports) { struct gb_host_device *hd; + int ret; /* * Validate that the driver implements all of the callbacks @@ -68,8 +72,21 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, if (!hd) return ERR_PTR(-ENOMEM); - kref_init(&hd->kref); - hd->parent = parent; + hd->dev.parent = parent; + hd->dev.bus = &greybus_bus_type; + hd->dev.type = &greybus_hd_type; + hd->dev.dma_mask = hd->dev.parent->dma_mask; + device_initialize(&hd->dev); + + ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL); + if (ret < 0) { + kfree(hd); + return ERR_PTR(ret); + } + + hd->bus_id = ret; + dev_set_name(&hd->dev, "greybus%d", hd->bus_id); + hd->driver = driver; INIT_LIST_HEAD(&hd->interfaces); INIT_LIST_HEAD(&hd->connections); @@ -83,6 +100,12 @@ EXPORT_SYMBOL_GPL(gb_hd_create); int gb_hd_add(struct gb_host_device *hd) { + int ret; + + ret = device_add(&hd->dev); + if (ret) + return ret; + /* * Initialize AP's SVC protocol connection: * @@ -93,8 +116,10 @@ int gb_hd_add(struct gb_host_device *hd) * time we will create a fully initialized svc-connection, as we need * endo-id and AP's interface id for that. */ - if (!gb_ap_svc_connection_create(hd)) + if (!gb_ap_svc_connection_create(hd)) { + device_del(&hd->dev); return -ENOMEM; + } return 0; } @@ -113,11 +138,25 @@ void gb_hd_del(struct gb_host_device *hd) /* Is the SVC still using the partially uninitialized connection ? */ if (hd->initial_svc_connection) gb_connection_destroy(hd->initial_svc_connection); + + device_del(&hd->dev); } EXPORT_SYMBOL_GPL(gb_hd_del); void gb_hd_put(struct gb_host_device *hd) { - kref_put_mutex(&hd->kref, free_hd, &hd_mutex); + put_device(&hd->dev); } EXPORT_SYMBOL_GPL(gb_hd_put); + +int __init gb_hd_init(void) +{ + ida_init(&gb_hd_bus_id_map); + + return 0; +} + +void gb_hd_exit(void) +{ + ida_destroy(&gb_hd_bus_id_map); +} -- cgit v1.1