[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251114150738.32426-13-damien.riegel@silabs.com>
Date: Fri, 14 Nov 2025 10:07:38 -0500
From: Damien Riégel <damien.riegel@...abs.com>
To: greybus-dev@...ts.linaro.org, Johan Hovold <johan@...nel.org>,
Alex Elder <elder@...nel.org>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
linux-kernel@...r.kernel.org
Cc: Silicon Labs Kernel Team <linux-devel@...abs.com>,
Damien Riégel <damien.riegel@...abs.com>
Subject: [RFC PATCH v2 12/12] greybus: cpc: let host device drivers dequeue TX frames
This lets the CPC host device drivers dequeue frames when it's
convenient for them to do so, instead of forcing each to them to
implement a queue to store pending skbs.
The callback is changed from `transmit` to `wake_tx` and let CPC core
notify these drivers when there is something to transmit.
Signed-off-by: Damien Riégel <damien.riegel@...abs.com>
---
drivers/greybus/cpc/host.c | 49 +++++++++++++++++++++++++++++++++++---
drivers/greybus/cpc/host.h | 10 ++++++--
2 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/drivers/greybus/cpc/host.c b/drivers/greybus/cpc/host.c
index 0f9aa394690..7ae5bb0666f 100644
--- a/drivers/greybus/cpc/host.c
+++ b/drivers/greybus/cpc/host.c
@@ -156,6 +156,7 @@ static struct gb_hd_driver cpc_gb_driver = {
static void cpc_hd_init(struct cpc_host_device *cpc_hd)
{
mutex_init(&cpc_hd->lock);
+ skb_queue_head_init(&cpc_hd->tx_queue);
}
struct cpc_host_device *cpc_hd_create(struct cpc_hd_driver *driver, struct device *parent)
@@ -163,7 +164,7 @@ struct cpc_host_device *cpc_hd_create(struct cpc_hd_driver *driver, struct devic
struct cpc_host_device *cpc_hd;
struct gb_host_device *hd;
- if (!driver->transmit) {
+ if (!driver->wake_tx) {
dev_err(parent, "missing mandatory callback\n");
return ERR_PTR(-EINVAL);
}
@@ -232,13 +233,55 @@ EXPORT_SYMBOL_GPL(cpc_hd_rcvd);
* @cpc_hd: Host device to send SKB over.
* @skb: SKB to send.
*/
-int cpc_hd_send_skb(struct cpc_host_device *cpc_hd, struct sk_buff *skb)
+void cpc_hd_send_skb(struct cpc_host_device *cpc_hd, struct sk_buff *skb)
{
const struct cpc_hd_driver *drv = cpc_hd->driver;
- return drv->transmit(cpc_hd, skb);
+ mutex_lock(&cpc_hd->lock);
+ skb_queue_tail(&cpc_hd->tx_queue, skb);
+ mutex_unlock(&cpc_hd->lock);
+
+ drv->wake_tx(cpc_hd);
}
+/**
+ * cpc_hd_tx_queue_empty() - Check if transmit queue is empty.
+ * @cpc_hd: CPC Host Device.
+ *
+ * Return: True if transmit queue is empty, false otherwise.
+ */
+bool cpc_hd_tx_queue_empty(struct cpc_host_device *cpc_hd)
+{
+ bool empty;
+
+ mutex_lock(&cpc_hd->lock);
+ empty = skb_queue_empty(&cpc_hd->tx_queue);
+ mutex_unlock(&cpc_hd->lock);
+
+ return empty;
+}
+EXPORT_SYMBOL_GPL(cpc_hd_tx_queue_empty);
+
+/**
+ * cpc_hd_dequeue() - Get the next SKB that was queued for transmission.
+ * @cpc_hd: CPC Host Device.
+ *
+ * Get an SKB that was previously queued by cpc_hd_send_skb().
+ *
+ * Return: An SKB, or %NULL if queue was empty.
+ */
+struct sk_buff *cpc_hd_dequeue(struct cpc_host_device *cpc_hd)
+{
+ struct sk_buff *skb;
+
+ mutex_lock(&cpc_hd->lock);
+ skb = skb_dequeue(&cpc_hd->tx_queue);
+ mutex_unlock(&cpc_hd->lock);
+
+ return skb;
+}
+EXPORT_SYMBOL_GPL(cpc_hd_dequeue);
+
MODULE_DESCRIPTION("Greybus over CPC");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Silicon Laboratories, Inc.");
diff --git a/drivers/greybus/cpc/host.h b/drivers/greybus/cpc/host.h
index 07bb4eb5fb8..2c47e167ac1 100644
--- a/drivers/greybus/cpc/host.h
+++ b/drivers/greybus/cpc/host.h
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/greybus.h>
#include <linux/mutex.h>
+#include <linux/skbuff.h>
#include <linux/types.h>
#define GB_CPC_MSG_SIZE_MAX 2048
@@ -18,7 +19,7 @@ struct cpc_cport;
struct cpc_host_device;
struct cpc_hd_driver {
- int (*transmit)(struct cpc_host_device *hd, struct sk_buff *skb);
+ int (*wake_tx)(struct cpc_host_device *cpc_hd);
};
/**
@@ -33,6 +34,8 @@ struct cpc_host_device {
const struct cpc_hd_driver *driver;
struct mutex lock; /* Synchronize access to cports */
+ struct sk_buff_head tx_queue;
+
struct cpc_cport *cports[GB_CPC_NUM_CPORTS];
};
@@ -47,6 +50,9 @@ 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, struct sk_buff *skb);
-int cpc_hd_send_skb(struct cpc_host_device *cpc_hd, struct sk_buff *skb);
+void cpc_hd_send_skb(struct cpc_host_device *cpc_hd, struct sk_buff *skb);
+
+bool cpc_hd_tx_queue_empty(struct cpc_host_device *cpc_hd);
+struct sk_buff *cpc_hd_dequeue(struct cpc_host_device *cpc_hd);
#endif
--
2.49.0
Powered by blists - more mailing lists