From 7adeaae7132e06cd760b86576b8aefd2f0feb4d1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:37 +0100 Subject: [PATCH] greybus: svc: create svc along with host device Create svc device along with host-device and move the svc-connection to the svc structure. The svc connection is enabled when registering the host device, but as the SVC protocol is currently driven by the SVC, we need to defer registration of the svc device to the connection request handler. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/hd.c | 15 ++++---- drivers/staging/greybus/hd.h | 2 -- drivers/staging/greybus/svc.c | 68 ++++++++++++++++++++++++++++------- drivers/staging/greybus/svc.h | 5 +++ 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 469b31e00237..bff6861b8af7 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -21,8 +21,8 @@ static void gb_hd_release(struct device *dev) { struct gb_host_device *hd = to_gb_host_device(dev); - if (hd->svc_connection) - gb_connection_destroy(hd->svc_connection); + if (hd->svc) + gb_svc_put(hd->svc); ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); ida_destroy(&hd->cport_id_map); kfree(hd); @@ -95,10 +95,9 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, device_initialize(&hd->dev); dev_set_name(&hd->dev, "greybus%d", hd->bus_id); - hd->svc_connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, - GREYBUS_PROTOCOL_SVC); - if (!hd->svc_connection) { - dev_err(&hd->dev, "failed to create svc connection\n"); + hd->svc = gb_svc_create(hd); + if (!hd->svc) { + dev_err(&hd->dev, "failed to create svc\n"); put_device(&hd->dev); return ERR_PTR(-ENOMEM); } @@ -115,7 +114,7 @@ int gb_hd_add(struct gb_host_device *hd) if (ret) return ret; - ret = gb_connection_init(hd->svc_connection); + ret = gb_svc_add(hd->svc); if (ret) { device_del(&hd->dev); return ret; @@ -129,7 +128,7 @@ void gb_hd_del(struct gb_host_device *hd) { gb_interfaces_remove(hd); - gb_connection_exit(hd->svc_connection); + gb_svc_del(hd->svc); device_del(&hd->dev); } diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 5612b489dd24..d828129475cd 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -41,8 +41,6 @@ struct gb_host_device { size_t buffer_size_max; struct gb_svc *svc; - struct gb_connection *svc_connection; - /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); }; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 2a8f79e95b3c..c013083d79f6 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -661,6 +661,8 @@ static void gb_svc_release(struct device *dev) { struct gb_svc *svc = to_gb_svc(dev); + if (svc->connection) + gb_connection_destroy(svc->connection); ida_destroy(&svc->device_id_map); destroy_workqueue(svc->wq); kfree(svc); @@ -671,19 +673,18 @@ struct device_type greybus_svc_type = { .release = gb_svc_release, }; -static int gb_svc_connection_init(struct gb_connection *connection) +struct gb_svc *gb_svc_create(struct gb_host_device *hd) { - struct gb_host_device *hd = connection->hd; struct gb_svc *svc; svc = kzalloc(sizeof(*svc), GFP_KERNEL); if (!svc) - return -ENOMEM; + return NULL; svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev)); if (!svc->wq) { kfree(svc); - return -ENOMEM; + return NULL; } svc->dev.parent = &hd->dev; @@ -697,30 +698,71 @@ static int gb_svc_connection_init(struct gb_connection *connection) ida_init(&svc->device_id_map); svc->state = GB_SVC_STATE_RESET; - svc->connection = connection; svc->hd = hd; - connection->private = svc; - hd->svc = svc; + svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, + GREYBUS_PROTOCOL_SVC); + if (!svc->connection) { + dev_err(&svc->dev, "failed to create connection\n"); + put_device(&svc->dev); + return NULL; + } + + svc->connection->private = svc; - return 0; + return svc; } -static void gb_svc_connection_exit(struct gb_connection *connection) +int gb_svc_add(struct gb_svc *svc) { - struct gb_svc *svc = connection->private; + int ret; + /* + * The SVC protocol is currently driven by the SVC, so the SVC device + * is added from the connection request handler when enough + * information has been received. + */ + ret = gb_connection_init(svc->connection); + if (ret) + return ret; + + return 0; +} + +void gb_svc_del(struct gb_svc *svc) +{ + /* + * The SVC device may have been registered from the request handler. + */ if (device_is_registered(&svc->dev)) device_del(&svc->dev); - flush_workqueue(svc->wq); + gb_connection_exit(svc->connection); - connection->hd->svc = NULL; - connection->private = NULL; + flush_workqueue(svc->wq); +} +void gb_svc_put(struct gb_svc *svc) +{ put_device(&svc->dev); } +static int gb_svc_connection_init(struct gb_connection *connection) +{ + struct gb_svc *svc = connection->private; + + dev_dbg(&svc->dev, "%s\n", __func__); + + return 0; +} + +static void gb_svc_connection_exit(struct gb_connection *connection) +{ + struct gb_svc *svc = connection->private; + + dev_dbg(&svc->dev, "%s\n", __func__); +} + static struct gb_protocol svc_protocol = { .name = "svc", .id = GREYBUS_PROTOCOL_SVC, diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index ca0f71d059b1..b7cb7e4c6cf5 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -30,6 +30,11 @@ struct gb_svc { }; #define to_gb_svc(d) container_of(d, struct gb_svc, d) +struct gb_svc *gb_svc_create(struct gb_host_device *hd); +int gb_svc_add(struct gb_svc *svc); +void gb_svc_del(struct gb_svc *svc); +void gb_svc_put(struct gb_svc *svc); + int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, bool boot_over_unipro); -- 2.20.1