[PATCH v4 1/6] greybus: connection: Add greybus_data_rcvd_by_intf()
From: Ayush Singh
Date: Wed Oct 21 2026 - 07:40:11 EST
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@xxxxxxxxxxxxxxx>
---
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);
--
2.56.0