Commit 24e094d6 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

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: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 96c2af5c
...@@ -129,7 +129,8 @@ static void gb_connection_init_name(struct gb_connection *connection) ...@@ -129,7 +129,8 @@ static void gb_connection_init_name(struct gb_connection *connection)
* Serialised against concurrent create and destroy using the * Serialised against concurrent create and destroy using the
* gb_connection_mutex. * 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 * static struct gb_connection *
_gb_connection_create(struct gb_host_device *hd, int hd_cport_id, _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, ...@@ -139,6 +140,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
struct gb_connection *connection; struct gb_connection *connection;
struct ida *id_map = &hd->cport_id_map; struct ida *id_map = &hd->cport_id_map;
int ida_start, ida_end; int ida_start, ida_end;
int ret;
if (hd_cport_id < 0) { if (hd_cport_id < 0) {
ida_start = 0; ida_start = 0;
...@@ -148,23 +150,27 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, ...@@ -148,23 +150,27 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
ida_end = hd_cport_id + 1; ida_end = hd_cport_id + 1;
} else { } else {
dev_err(&hd->dev, "cport %d not available\n", hd_cport_id); dev_err(&hd->dev, "cport %d not available\n", hd_cport_id);
return NULL; return ERR_PTR(-EINVAL);
} }
mutex_lock(&gb_connection_mutex); mutex_lock(&gb_connection_mutex);
if (intf && gb_connection_intf_find(intf, cport_id)) { if (intf && gb_connection_intf_find(intf, cport_id)) {
dev_err(&intf->dev, "cport %u already in use\n", cport_id); dev_err(&intf->dev, "cport %u already in use\n", cport_id);
ret = -EBUSY;
goto err_unlock; goto err_unlock;
} }
hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); ret = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);
if (hd_cport_id < 0) if (ret < 0)
goto err_unlock; goto err_unlock;
hd_cport_id = ret;
connection = kzalloc(sizeof(*connection), GFP_KERNEL); connection = kzalloc(sizeof(*connection), GFP_KERNEL);
if (!connection) if (!connection) {
ret = -ENOMEM;
goto err_remove_ida; goto err_remove_ida;
}
connection->hd_cport_id = hd_cport_id; connection->hd_cport_id = hd_cport_id;
connection->intf_cport_id = cport_id; connection->intf_cport_id = cport_id;
...@@ -181,8 +187,10 @@ _gb_connection_create(struct gb_host_device *hd, int hd_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, connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1,
dev_name(&hd->dev), hd_cport_id); dev_name(&hd->dev), hd_cport_id);
if (!connection->wq) if (!connection->wq) {
ret = -ENOMEM;
goto err_free_connection; goto err_free_connection;
}
kref_init(&connection->kref); kref_init(&connection->kref);
...@@ -209,7 +217,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, ...@@ -209,7 +217,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
err_unlock: err_unlock:
mutex_unlock(&gb_connection_mutex); mutex_unlock(&gb_connection_mutex);
return NULL; return ERR_PTR(ret);
} }
struct gb_connection * struct gb_connection *
......
...@@ -187,8 +187,10 @@ struct gb_control *gb_control_create(struct gb_interface *intf) ...@@ -187,8 +187,10 @@ struct gb_control *gb_control_create(struct gb_interface *intf)
return NULL; return NULL;
control->connection = gb_connection_create_control(intf); control->connection = gb_connection_create_control(intf);
if (!control->connection) { if (IS_ERR(control->connection)) {
dev_err(&intf->dev, "failed to create control connection\n"); dev_err(&intf->dev,
"failed to create control connection: %ld\n",
PTR_ERR(control->connection));
kfree(control); kfree(control);
return NULL; return NULL;
} }
......
...@@ -133,7 +133,7 @@ static int legacy_probe(struct gb_bundle *bundle, ...@@ -133,7 +133,7 @@ static int legacy_probe(struct gb_bundle *bundle,
struct legacy_data *data; struct legacy_data *data;
struct gb_connection *connection; struct gb_connection *connection;
int i; int i;
int ret = -ENOMEM; int ret;
dev_dbg(&bundle->dev, dev_dbg(&bundle->dev,
"%s - bundle class = 0x%02x, num_cports = %zu\n", "%s - bundle class = 0x%02x, num_cports = %zu\n",
...@@ -147,16 +147,20 @@ static int legacy_probe(struct gb_bundle *bundle, ...@@ -147,16 +147,20 @@ static int legacy_probe(struct gb_bundle *bundle,
data->connections = kcalloc(data->num_cports, data->connections = kcalloc(data->num_cports,
sizeof(*data->connections), sizeof(*data->connections),
GFP_KERNEL); GFP_KERNEL);
if (!data->connections) if (!data->connections) {
ret = -ENOMEM;
goto err_free_data; goto err_free_data;
}
for (i = 0; i < data->num_cports; ++i) { for (i = 0; i < data->num_cports; ++i) {
cport_desc = &bundle->cport_desc[i]; cport_desc = &bundle->cport_desc[i];
connection = gb_connection_create(bundle, connection = gb_connection_create(bundle,
le16_to_cpu(cport_desc->id)); le16_to_cpu(cport_desc->id));
if (!connection) if (IS_ERR(connection)) {
ret = PTR_ERR(connection);
goto err_connections_destroy; goto err_connections_destroy;
}
connection->protocol_id = cport_desc->protocol_id; connection->protocol_id = cport_desc->protocol_id;
......
...@@ -896,8 +896,9 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) ...@@ -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); svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID);
if (!svc->connection) { if (IS_ERR(svc->connection)) {
dev_err(&svc->dev, "failed to create connection\n"); dev_err(&svc->dev, "failed to create connection: %ld\n",
PTR_ERR(svc->connection));
goto err_free_input; goto err_free_input;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment