Take advantage of the padding bytes present in the Greybus header to
store the CPort ID and minize overhead. This technique is already used
by the es2 driver.
Signed-off-by: Damien Riégel <damien.riegel@silabs.com>
---
drivers/greybus/cpc/cpc.h | 3 +++
drivers/greybus/cpc/cport.c | 29 +++++++++++++++++++++++++++++
drivers/greybus/cpc/host.c | 13 ++++++++++++-
drivers/greybus/cpc/host.h | 2 +-
4 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/drivers/greybus/cpc/cpc.h b/drivers/greybus/cpc/cpc.h
index 7e032f6cf50..0f2d204d86d 100644
--- a/drivers/greybus/cpc/cpc.h
+++ b/drivers/greybus/cpc/cpc.h
@@ -24,6 +24,9 @@ struct cpc_cport {
struct cpc_cport *cpc_cport_alloc(u16 cport_id, gfp_t gfp_mask);
void cpc_cport_release(struct cpc_cport *cport);
+void cpc_cport_pack(struct gb_operation_msg_hdr *gb_hdr, u16 cport_id);
+u16 cpc_cport_unpack(struct gb_operation_msg_hdr *gb_hdr);
+
int cpc_cport_transmit(struct cpc_cport *cport, struct sk_buff *skb);
struct cpc_skb_cb {
diff --git a/drivers/greybus/cpc/cport.c b/drivers/greybus/cpc/cport.c
index ed0b8e8b0d7..0fc4ff0c5bb 100644
--- a/drivers/greybus/cpc/cport.c
+++ b/drivers/greybus/cpc/cport.c
@@ -3,6 +3,9 @@
* Copyright (c) 2025, Silicon Laboratories, Inc.
*/
+#include <linux/unaligned.h>
+#include <linux/skbuff.h>
+
#include "cpc.h"
#include "host.h"
@@ -31,6 +34,27 @@ void cpc_cport_release(struct cpc_cport *cport)
kfree(cport);
}
+/**
+ * cpc_cport_pack() - Pack CPort ID into Greybus Operation Message header.
+ * @gb_hdr: Greybus operation message header.
+ * @cport_id: CPort ID to pack.
+ */
+void cpc_cport_pack(struct gb_operation_msg_hdr *gb_hdr, u16 cport_id)
+{
+ put_unaligned_le16(cport_id, gb_hdr->pad);
+}
+
+/**
+ * cpc_cport_unpack() - Unpack CPort ID from Greybus Operation Message header.
+ * @gb_hdr: Greybus operation message header.
+ *
+ * Return: CPort ID packed in the header.
+ */
+u16 cpc_cport_unpack(struct gb_operation_msg_hdr *gb_hdr)
+{
+ return get_unaligned_le16(gb_hdr->pad);
+}
+
/**
* cpc_cport_transmit() - Transmit skb over cport.
* @cport: cport.
@@ -39,6 +63,11 @@ void cpc_cport_release(struct cpc_cport *cport)
int cpc_cport_transmit(struct cpc_cport *cport, struct sk_buff *skb)
{
struct cpc_host_device *cpc_hd = cport->cpc_hd;
+ struct gb_operation_msg_hdr *gb_hdr;
+
+ /* Inject cport ID in Greybus header */
+ gb_hdr = (struct gb_operation_msg_hdr *)skb->data;
+ cpc_cport_pack(gb_hdr, cport->id);
return cpc_hd_send_skb(cpc_hd, skb);
}
diff --git a/drivers/greybus/cpc/host.c b/drivers/greybus/cpc/host.c
index 2ca938c2b48..1d81c624dd6 100644
--- a/drivers/greybus/cpc/host.c
+++ b/drivers/greybus/cpc/host.c
@@ -204,8 +204,19 @@ void cpc_hd_message_sent(struct sk_buff *skb, int status)
}
EXPORT_SYMBOL_GPL(cpc_hd_message_sent);
-void cpc_hd_rcvd(struct cpc_host_device *cpc_hd, u16 cport_id, u8 *data, size_t length)
+void cpc_hd_rcvd(struct cpc_host_device *cpc_hd, u8 *data, size_t length)
{
+ struct gb_operation_msg_hdr *gb_hdr;
+ u16 cport_id;
+
+ /* Prevent an out-of-bound access if called with non-sensical parameters. */
+ if (!data || length < sizeof(*gb_hdr))
+ return;
+
+ /* Retrieve cport ID that was packed in Greybus header */
+ gb_hdr = (struct gb_operation_msg_hdr *)data;
+ cport_id = cpc_cport_unpack(gb_hdr);
+
greybus_data_rcvd(cpc_hd->gb_hd, cport_id, data, length);
}
EXPORT_SYMBOL_GPL(cpc_hd_rcvd);
diff --git a/drivers/greybus/cpc/host.h b/drivers/greybus/cpc/host.h
index 104d61e3bc5..86d205fcb59 100644
--- a/drivers/greybus/cpc/host.h
+++ b/drivers/greybus/cpc/host.h
@@ -45,7 +45,7 @@ struct cpc_host_device *cpc_hd_create(struct cpc_hd_driver *driver, struct devic
int cpc_hd_add(struct cpc_host_device *cpc_hd);
void cpc_hd_put(struct cpc_host_device *cpc_hd);
void cpc_hd_del(struct cpc_host_device *cpc_hd);
-void cpc_hd_rcvd(struct cpc_host_device *cpc_hd, u16 cport_id, u8 *data, size_t length);
+void cpc_hd_rcvd(struct cpc_host_device *cpc_hd, u8 *data, size_t length);
void cpc_hd_message_sent(struct sk_buff *skb, int status);
int cpc_hd_send_skb(struct cpc_host_device *cpc_hd, struct sk_buff *skb);
--
2.49.0