Commit 2566fae6 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

greybus: connection: clean up connection-creation interface

Clean up the connection-creation interface by clearly separating our two
types of connections: static and dynamic.

Add two convenience functions for creating static and dynamic connections.

A static connection is a pre-setup connection that is defined by a host
device and a host-device cport id. Specifically, the remote interface or
cport id need not be known. The SVC connection is a static connection.

A dynamic connection is defined by a host device and a remote interface
and cport id. This is our normal connections where the host-device cport
is (generally) allocated dynamically.

Note that the new generic interface is marked static, but can be
exported later to allow dynamic connections to be created also from
fixed host-device cports (e.g. for CSI).

Also note that a connection of either type is uniquely identified by its
host-device and host-device cport id once created.
Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent e4048006
...@@ -94,25 +94,32 @@ int svc_update_connection(struct gb_interface *intf, ...@@ -94,25 +94,32 @@ int svc_update_connection(struct gb_interface *intf,
} }
/* /*
* Set up a Greybus connection, representing the bidirectional link * gb_connection_create() - create a Greybus connection
* @hd: host device of the connection
* @hd_cport_id: host-device cport id, or -1 for dynamic allocation
* @intf: remote interface, or NULL for static connections
* @bundle: remote-interface bundle (may be NULL)
* @cport_id: remote-interface cport id, or 0 for static connections
* @protocol_id: protocol id
*
* Create a Greybus connection, representing the bidirectional link
* between a CPort on a (local) Greybus host device and a CPort on * between a CPort on a (local) Greybus host device and a CPort on
* another Greybus module. * another Greybus interface.
* *
* A connection also maintains the state of operations sent over the * A connection also maintains the state of operations sent over the
* connection. * connection.
* *
* Returns a pointer to the new connection if successful, or a null * Return: A pointer to the new connection if successful, or NULL otherwise.
* pointer otherwise.
*/ */
struct gb_connection * static struct gb_connection *
gb_connection_create_range(struct gb_host_device *hd, gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
struct gb_bundle *bundle, struct gb_interface *intf,
u16 cport_id, u8 protocol_id, u32 ida_start, struct gb_bundle *bundle, int cport_id,
u32 ida_end) u8 protocol_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 hd_cport_id; int ida_start, ida_end;
int retval; int retval;
u8 major = 0; u8 major = 0;
u8 minor = 1; u8 minor = 1;
...@@ -128,6 +135,17 @@ gb_connection_create_range(struct gb_host_device *hd, ...@@ -128,6 +135,17 @@ gb_connection_create_range(struct gb_host_device *hd,
return NULL; return NULL;
} }
if (hd_cport_id < 0) {
ida_start = 0;
ida_end = hd->num_cports;
} else if (hd_cport_id < hd->num_cports) {
ida_start = hd_cport_id;
ida_end = hd_cport_id + 1;
} else {
dev_err(&hd->dev, "cport %d not available\n", hd_cport_id);
return NULL;
}
hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);
if (hd_cport_id < 0) if (hd_cport_id < 0)
return NULL; return NULL;
...@@ -139,6 +157,7 @@ gb_connection_create_range(struct gb_host_device *hd, ...@@ -139,6 +157,7 @@ gb_connection_create_range(struct gb_host_device *hd,
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;
connection->hd = hd; connection->hd = hd;
connection->intf = intf;
connection->protocol_id = protocol_id; connection->protocol_id = protocol_id;
connection->major = major; connection->major = major;
...@@ -186,6 +205,23 @@ gb_connection_create_range(struct gb_host_device *hd, ...@@ -186,6 +205,23 @@ gb_connection_create_range(struct gb_host_device *hd,
return NULL; return NULL;
} }
struct gb_connection *
gb_connection_create_static(struct gb_host_device *hd,
u16 hd_cport_id, u8 protocol_id)
{
return gb_connection_create(hd, hd_cport_id, NULL, NULL, 0,
protocol_id);
}
struct gb_connection *
gb_connection_create_dynamic(struct gb_interface *intf,
struct gb_bundle *bundle,
u16 cport_id, u8 protocol_id)
{
return gb_connection_create(intf->hd, -1, intf, bundle, cport_id,
protocol_id);
}
static int gb_connection_hd_cport_enable(struct gb_connection *connection) static int gb_connection_hd_cport_enable(struct gb_connection *connection)
{ {
struct gb_host_device *hd = connection->hd; struct gb_host_device *hd = connection->hd;
...@@ -214,14 +250,6 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection) ...@@ -214,14 +250,6 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection)
hd->driver->cport_disable(hd, connection->hd_cport_id); hd->driver->cport_disable(hd, connection->hd_cport_id);
} }
struct gb_connection *gb_connection_create(struct gb_bundle *bundle,
u16 cport_id, u8 protocol_id)
{
return gb_connection_create_range(bundle->intf->hd, bundle,
cport_id, protocol_id,
0, bundle->intf->hd->num_cports);
}
/* /*
* Cancel all active operations on a connection. * Cancel all active operations on a connection.
* *
......
...@@ -23,6 +23,7 @@ enum gb_connection_state { ...@@ -23,6 +23,7 @@ enum gb_connection_state {
struct gb_connection { struct gb_connection {
struct gb_host_device *hd; struct gb_host_device *hd;
struct gb_interface *intf;
struct gb_bundle *bundle; struct gb_bundle *bundle;
struct kref kref; struct kref kref;
u16 hd_cport_id; u16 hd_cport_id;
...@@ -51,12 +52,12 @@ struct gb_connection { ...@@ -51,12 +52,12 @@ struct gb_connection {
int svc_update_connection(struct gb_interface *intf, int svc_update_connection(struct gb_interface *intf,
struct gb_connection *connection); struct gb_connection *connection);
struct gb_connection *gb_connection_create(struct gb_bundle *bundle,
u16 cport_id, u8 protocol_id); struct gb_connection *gb_connection_create_static(struct gb_host_device *hd,
struct gb_connection *gb_connection_create_range(struct gb_host_device *hd, u16 hd_cport_id, u8 protocol_id);
struct gb_bundle *bundle, struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf,
u16 cport_id, u8 protocol_id, u32 ida_start, struct gb_bundle *bundle, u16 cport_id,
u32 ida_end); u8 protocol_id);
void gb_connection_destroy(struct gb_connection *connection); void gb_connection_destroy(struct gb_connection *connection);
void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id,
......
...@@ -86,7 +86,8 @@ gb_interface_create_control_bundle_connection(struct gb_interface *intf) ...@@ -86,7 +86,8 @@ gb_interface_create_control_bundle_connection(struct gb_interface *intf)
return -ENOMEM; return -ENOMEM;
} }
connection = gb_connection_create(bundle, GB_CONTROL_CPORT_ID, connection = gb_connection_create_dynamic(intf, bundle,
GB_CONTROL_CPORT_ID,
GREYBUS_PROTOCOL_CONTROL); GREYBUS_PROTOCOL_CONTROL);
if (!connection) { if (!connection) {
dev_err(&intf->dev, "failed to create control connection\n"); dev_err(&intf->dev, "failed to create control connection\n");
......
...@@ -251,7 +251,8 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) ...@@ -251,7 +251,8 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle)
goto print_error_exit; goto print_error_exit;
} }
if (!gb_connection_create(bundle, cport_id, protocol_id)) if (!gb_connection_create_dynamic(intf, bundle, cport_id,
protocol_id))
goto exit; goto exit;
release_descriptor: release_descriptor:
......
...@@ -60,11 +60,8 @@ gb_ap_svc_connection_create(struct gb_host_device *hd) ...@@ -60,11 +60,8 @@ gb_ap_svc_connection_create(struct gb_host_device *hd)
{ {
struct gb_connection *connection; struct gb_connection *connection;
connection = gb_connection_create_range(hd, NULL, connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID,
GB_SVC_CPORT_ID, GREYBUS_PROTOCOL_SVC);
GREYBUS_PROTOCOL_SVC,
GB_SVC_CPORT_ID,
GB_SVC_CPORT_ID + 1);
return connection; return connection;
} }
......
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