[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251114150738.32426-11-damien.riegel@silabs.com>
Date: Fri, 14 Nov 2025 10:07:36 -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 10/12] greybus: cpc: use holding queue instead of sending out immediately
As the first step to handle remote's RX window, store the skb in a
sk_buff_head list, instead of sending a message immediately when pushed
by Greybus.
skbs are still sent out straight away, but now there is a place to store
away if the remote's RX window is too small.
Signed-off-by: Damien Riégel <damien.riegel@...abs.com>
---
drivers/greybus/cpc/cpc.h | 9 ++++++---
drivers/greybus/cpc/cport.c | 21 ++++++++++++---------
drivers/greybus/cpc/host.c | 4 +++-
drivers/greybus/cpc/protocol.c | 25 ++++++++++++++++++++++++-
4 files changed, 45 insertions(+), 14 deletions(-)
diff --git a/drivers/greybus/cpc/cpc.h b/drivers/greybus/cpc/cpc.h
index bec2580e358..d5ad3b0846f 100644
--- a/drivers/greybus/cpc/cpc.h
+++ b/drivers/greybus/cpc/cpc.h
@@ -9,15 +9,16 @@
#include <linux/device.h>
#include <linux/greybus.h>
#include <linux/mutex.h>
+#include <linux/skbuff.h>
#include <linux/types.h>
-struct sk_buff;
/**
* struct cpc_cport - CPC cport
* @id: cport ID
* @cpc_hd: pointer to the CPC host device this cport belongs to
* @lock: mutex to synchronize accesses to tcb and other attributes
+ * @holding_queue: list of frames queued to be sent
* @tcb: Transmission Control Block
*/
struct cpc_cport {
@@ -26,6 +27,8 @@ struct cpc_cport {
struct cpc_host_device *cpc_hd;
struct mutex lock; /* Synchronize access to state variables */
+ struct sk_buff_head holding_queue;
+
/*
* @ack: current acknowledge number
* @seq: current sequence number
@@ -42,7 +45,7 @@ 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);
+void cpc_cport_transmit(struct cpc_cport *cport, struct sk_buff *skb);
struct cpc_skb_cb {
struct cpc_cport *cport;
@@ -58,7 +61,7 @@ struct cpc_skb_cb {
#define CPC_SKB_CB(__skb) ((struct cpc_skb_cb *)&((__skb)->cb[0]))
-void cpc_protocol_prepare_header(struct sk_buff *skb, u8 ack);
void cpc_protocol_on_data(struct cpc_cport *cport, struct sk_buff *skb);
+void __cpc_protocol_write_head(struct cpc_cport *cport);
#endif
diff --git a/drivers/greybus/cpc/cport.c b/drivers/greybus/cpc/cport.c
index 35a148abbed..f850da7acfb 100644
--- a/drivers/greybus/cpc/cport.c
+++ b/drivers/greybus/cpc/cport.c
@@ -7,7 +7,6 @@
#include <linux/skbuff.h>
#include "cpc.h"
-#include "host.h"
/**
* cpc_cport_tcb_reset() - Reset cport's TCB to initial values.
@@ -38,15 +37,23 @@ struct cpc_cport *cpc_cport_alloc(u16 cport_id, gfp_t gfp_mask)
cpc_cport_tcb_reset(cport);
mutex_init(&cport->lock);
+ skb_queue_head_init(&cport->holding_queue);
return cport;
}
void cpc_cport_release(struct cpc_cport *cport)
{
+ skb_queue_purge(&cport->holding_queue);
kfree(cport);
}
+static void cpc_cport_queue_skb(struct cpc_cport *cport, struct sk_buff *skb)
+{
+ __skb_header_release(skb);
+ __skb_queue_tail(&cport->holding_queue, skb);
+}
+
/**
* cpc_cport_pack() - Pack CPort ID into Greybus Operation Message header.
* @gb_hdr: Greybus operation message header.
@@ -73,11 +80,9 @@ u16 cpc_cport_unpack(struct gb_operation_msg_hdr *gb_hdr)
* @cport: cport.
* @skb: skb to be transmitted.
*/
-int cpc_cport_transmit(struct cpc_cport *cport, struct sk_buff *skb)
+void 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;
- u8 ack;
/* Inject cport ID in Greybus header */
gb_hdr = (struct gb_operation_msg_hdr *)skb->data;
@@ -89,11 +94,9 @@ int cpc_cport_transmit(struct cpc_cport *cport, struct sk_buff *skb)
CPC_SKB_CB(skb)->cpc_flags = CPC_SKB_FLAG_REQ_ACK;
cport->tcb.seq++;
- ack = cport->tcb.ack;
+
+ cpc_cport_queue_skb(cport, skb);
+ __cpc_protocol_write_head(cport);
mutex_unlock(&cport->lock);
-
- cpc_protocol_prepare_header(skb, ack);
-
- return cpc_hd_send_skb(cpc_hd, skb);
}
diff --git a/drivers/greybus/cpc/host.c b/drivers/greybus/cpc/host.c
index 9173d5ab5a1..27f02120266 100644
--- a/drivers/greybus/cpc/host.c
+++ b/drivers/greybus/cpc/host.c
@@ -63,7 +63,9 @@ static int cpc_hd_message_send(struct cpc_host_device *cpc_hd, u16 cport_id,
CPC_SKB_CB(skb)->cport = cport;
CPC_SKB_CB(skb)->gb_message = message;
- return cpc_cport_transmit(cport, skb);
+ cpc_cport_transmit(cport, skb);
+
+ return 0;
}
static int cpc_hd_cport_allocate(struct cpc_host_device *cpc_hd, int cport_id, unsigned long flags)
diff --git a/drivers/greybus/cpc/protocol.c b/drivers/greybus/cpc/protocol.c
index 63b4127fcea..272eafd79b0 100644
--- a/drivers/greybus/cpc/protocol.c
+++ b/drivers/greybus/cpc/protocol.c
@@ -15,7 +15,7 @@ static bool cpc_skb_is_sequenced(struct sk_buff *skb)
return CPC_SKB_CB(skb)->cpc_flags & CPC_SKB_FLAG_REQ_ACK;
}
-void cpc_protocol_prepare_header(struct sk_buff *skb, u8 ack)
+static void cpc_protocol_prepare_header(struct sk_buff *skb, u8 ack)
{
struct cpc_header *hdr;
@@ -86,3 +86,26 @@ void cpc_protocol_on_data(struct cpc_cport *cport, struct sk_buff *skb)
greybus_data_rcvd(cport->cpc_hd->gb_hd, cport->id, skb->data, skb->len);
}
}
+
+static void __cpc_protocol_write_skb(struct cpc_cport *cport, struct sk_buff *skb, u8 ack)
+{
+ cpc_protocol_prepare_header(skb, ack);
+
+ cpc_hd_send_skb(cport->cpc_hd, skb);
+}
+
+/* Write skbs at the head of holding queue */
+void __cpc_protocol_write_head(struct cpc_cport *cport)
+{
+ struct sk_buff *skb;
+ u8 ack;
+
+ ack = cport->tcb.ack;
+
+ /* For each SKB in the holding queue, clone it and pass it to lower layer */
+ while ((skb = skb_peek(&cport->holding_queue))) {
+ skb_unlink(skb, &cport->holding_queue);
+
+ __cpc_protocol_write_skb(cport, skb, ack);
+ }
+}
--
2.49.0
Powered by blists - more mailing lists