greybus_data_rcvd() finds the receiving connection by its host-side CPort id. A host driver such as a software SVC sees only the remote end of a connection, the interface id and the interface CPort id, and cannot deliver data that way.
Add greybus_data_rcvd_by_intf(), which looks the connection up by interface id and interface CPort id and passes the data to it. It returns -EINVAL if no such connection exists. The first user is the gb-softsvc driver, added later in this series.
Signed-off-by: Ayush Singh ayush@beagleboard.org --- drivers/greybus/connection.c | 47 ++++++++++++++++++++++++++++++++++++++ include/linux/greybus/connection.h | 2 ++ 2 files changed, 49 insertions(+)
diff --git a/drivers/greybus/connection.c b/drivers/greybus/connection.c index bd04485decb3..ce8646299ce8 100644 --- a/drivers/greybus/connection.c +++ b/drivers/greybus/connection.c @@ -69,6 +69,32 @@ gb_connection_hd_find(struct gb_host_device *hd, u16 cport_id) return connection; }
+/* + * Returns a reference-counted pointer to the connection if found. + */ +static struct gb_connection * +gb_connection_hd_find_by_intf(struct gb_host_device *hd, u8 intf_id, + u16 intf_cport) +{ + struct gb_connection *connection; + unsigned long flags; + + spin_lock_irqsave(&gb_connections_lock, flags); + list_for_each_entry(connection, &hd->connections, hd_links) { + if (connection->intf && + connection->intf->interface_id == intf_id && + connection->intf_cport_id == intf_cport) { + gb_connection_get(connection); + goto found; + } + } + connection = NULL; +found: + spin_unlock_irqrestore(&gb_connections_lock, flags); + + return connection; +} + /* * Callback from the host driver to let us know that data has been * received on the bundle. @@ -91,6 +117,27 @@ void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, } EXPORT_SYMBOL_GPL(greybus_data_rcvd);
+/* + * Callback from a host driver that only knows the remote end of a connection + * (interface id and interface CPort id), such as a software SVC. + */ +int greybus_data_rcvd_by_intf(struct gb_host_device *hd, u8 intf_id, + u16 intf_cport, u8 *data, size_t length) +{ + struct gb_connection *connection; + + trace_gb_hd_in(hd); + + connection = gb_connection_hd_find_by_intf(hd, intf_id, intf_cport); + if (!connection) + return -EINVAL; + gb_connection_recv(connection, data, length); + gb_connection_put(connection); + + return 0; +} +EXPORT_SYMBOL_GPL(greybus_data_rcvd_by_intf); + static void gb_connection_kref_release(struct kref *kref) { struct gb_connection *connection; diff --git a/include/linux/greybus/connection.h b/include/linux/greybus/connection.h index d59b7fc1de3e..e8be67a936a6 100644 --- a/include/linux/greybus/connection.h +++ b/include/linux/greybus/connection.h @@ -92,6 +92,8 @@ void gb_connection_mode_switch_complete(struct gb_connection *connection);
void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); +int greybus_data_rcvd_by_intf(struct gb_host_device *hd, u8 intf_id, + u16 intf_cport, u8 *data, size_t length);
void gb_connection_latency_tag_enable(struct gb_connection *connection); void gb_connection_latency_tag_disable(struct gb_connection *connection);