From 24e094d687a23878024589a854ce66a070b769cc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:16 +0100 Subject: [PATCH] greybus: connection: return error-valued pointer on creation errors Return an ERR_PTR on errors when creating connections. This allows driver probe to fail with a more informative error message as not all connection creation errors are due to memory exhaustion. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/connection.c | 22 +++++++++++++++------- drivers/staging/greybus/control.c | 6 ++++-- drivers/staging/greybus/legacy.c | 10 +++++++--- drivers/staging/greybus/svc.c | 5 +++-- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5d0edbe..99efe31 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -129,7 +129,8 @@ static void gb_connection_init_name(struct gb_connection *connection) * Serialised against concurrent create and destroy using the * gb_connection_mutex. * - * Return: A pointer to the new connection if successful, or NULL otherwise. + * Return: A pointer to the new connection if successful, or an ERR_PTR + * otherwise. */ static struct gb_connection * _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, @@ -139,6 +140,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; int ida_start, ida_end; + int ret; if (hd_cport_id < 0) { ida_start = 0; @@ -148,23 +150,27 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, ida_end = hd_cport_id + 1; } else { dev_err(&hd->dev, "cport %d not available\n", hd_cport_id); - return NULL; + return ERR_PTR(-EINVAL); } mutex_lock(&gb_connection_mutex); if (intf && gb_connection_intf_find(intf, cport_id)) { dev_err(&intf->dev, "cport %u already in use\n", cport_id); + ret = -EBUSY; goto err_unlock; } - hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); - if (hd_cport_id < 0) + ret = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); + if (ret < 0) goto err_unlock; + hd_cport_id = ret; connection = kzalloc(sizeof(*connection), GFP_KERNEL); - if (!connection) + if (!connection) { + ret = -ENOMEM; goto err_remove_ida; + } connection->hd_cport_id = hd_cport_id; connection->intf_cport_id = cport_id; @@ -181,8 +187,10 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1, dev_name(&hd->dev), hd_cport_id); - if (!connection->wq) + if (!connection->wq) { + ret = -ENOMEM; goto err_free_connection; + } kref_init(&connection->kref); @@ -209,7 +217,7 @@ err_remove_ida: err_unlock: mutex_unlock(&gb_connection_mutex); - return NULL; + return ERR_PTR(ret); } struct gb_connection * diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a766ec8..fb0bb1c 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -187,8 +187,10 @@ struct gb_control *gb_control_create(struct gb_interface *intf) return NULL; control->connection = gb_connection_create_control(intf); - if (!control->connection) { - dev_err(&intf->dev, "failed to create control connection\n"); + if (IS_ERR(control->connection)) { + dev_err(&intf->dev, + "failed to create control connection: %ld\n", + PTR_ERR(control->connection)); kfree(control); return NULL; } diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index fb0a82e..fc19b8b 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -133,7 +133,7 @@ static int legacy_probe(struct gb_bundle *bundle, struct legacy_data *data; struct gb_connection *connection; int i; - int ret = -ENOMEM; + int ret; dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x, num_cports = %zu\n", @@ -147,16 +147,20 @@ static int legacy_probe(struct gb_bundle *bundle, data->connections = kcalloc(data->num_cports, sizeof(*data->connections), GFP_KERNEL); - if (!data->connections) + if (!data->connections) { + ret = -ENOMEM; goto err_free_data; + } for (i = 0; i < data->num_cports; ++i) { cport_desc = &bundle->cport_desc[i]; connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id)); - if (!connection) + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); goto err_connections_destroy; + } connection->protocol_id = cport_desc->protocol_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 472997e..845f82d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -896,8 +896,9 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) } svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID); - if (!svc->connection) { - dev_err(&svc->dev, "failed to create connection\n"); + if (IS_ERR(svc->connection)) { + dev_err(&svc->dev, "failed to create connection: %ld\n", + PTR_ERR(svc->connection)); goto err_free_input; } -- 2.7.4