@@ -77,6 +77,8 @@ struct glink_core_rx_intent {
7777 bool reuse ;
7878 bool in_use ;
7979 u32 offset ;
80+
81+ struct list_head node ;
8082};
8183
8284/**
@@ -139,6 +141,8 @@ enum {
139141 * @rcid: channel id, in remote space
140142 * @intent_lock: lock for protection of @liids
141143 * @liids: idr of all local intents
144+ * @intent_work: worker responsible for transmitting rx_done packets
145+ * @done_intents: list of intents that needs to be announced rx_done
142146 * @buf: receive buffer, for gathering fragments
143147 * @buf_offset: write offset in @buf
144148 * @buf_size: size of current @buf
@@ -161,6 +165,8 @@ struct glink_channel {
161165
162166 spinlock_t intent_lock ;
163167 struct idr liids ;
168+ struct work_struct intent_work ;
169+ struct list_head done_intents ;
164170
165171 struct glink_core_rx_intent * buf ;
166172 int buf_offset ;
@@ -180,15 +186,19 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;
180186#define RPM_CMD_CLOSE 3
181187#define RPM_CMD_OPEN_ACK 4
182188#define RPM_CMD_INTENT 5
189+ #define RPM_CMD_RX_DONE 6
183190#define RPM_CMD_RX_INTENT_REQ 7
184191#define RPM_CMD_RX_INTENT_REQ_ACK 8
185192#define RPM_CMD_TX_DATA 9
186193#define RPM_CMD_CLOSE_ACK 11
187194#define RPM_CMD_TX_DATA_CONT 12
188195#define RPM_CMD_READ_NOTIF 13
196+ #define RPM_CMD_RX_DONE_W_REUSE 14
189197
190198#define GLINK_FEATURE_INTENTLESS BIT(1)
191199
200+ static void qcom_glink_rx_done_work (struct work_struct * work );
201+
192202static struct glink_channel * qcom_glink_alloc_channel (struct qcom_glink * glink ,
193203 const char * name )
194204{
@@ -201,12 +211,16 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
201211 /* Setup glink internal glink_channel data */
202212 spin_lock_init (& channel -> recv_lock );
203213 spin_lock_init (& channel -> intent_lock );
214+
204215 channel -> glink = glink ;
205216 channel -> name = kstrdup (name , GFP_KERNEL );
206217
207218 init_completion (& channel -> open_req );
208219 init_completion (& channel -> open_ack );
209220
221+ INIT_LIST_HEAD (& channel -> done_intents );
222+ INIT_WORK (& channel -> intent_work , qcom_glink_rx_done_work );
223+
210224 idr_init (& channel -> liids );
211225 kref_init (& channel -> refcount );
212226
@@ -402,6 +416,70 @@ static void qcom_glink_send_close_ack(struct qcom_glink *glink,
402416 qcom_glink_tx (glink , & req , sizeof (req ), NULL , 0 , true);
403417}
404418
419+ static void qcom_glink_rx_done_work (struct work_struct * work )
420+ {
421+ struct glink_channel * channel = container_of (work , struct glink_channel ,
422+ intent_work );
423+ struct qcom_glink * glink = channel -> glink ;
424+ struct glink_core_rx_intent * intent , * tmp ;
425+ struct {
426+ u16 id ;
427+ u16 lcid ;
428+ u32 liid ;
429+ } __packed cmd ;
430+
431+ unsigned int cid = channel -> lcid ;
432+ unsigned int iid ;
433+ bool reuse ;
434+ unsigned long flags ;
435+
436+ spin_lock_irqsave (& channel -> intent_lock , flags );
437+ list_for_each_entry_safe (intent , tmp , & channel -> done_intents , node ) {
438+ list_del (& intent -> node );
439+ spin_unlock_irqrestore (& channel -> intent_lock , flags );
440+ iid = intent -> id ;
441+ reuse = intent -> reuse ;
442+
443+ cmd .id = reuse ? RPM_CMD_RX_DONE_W_REUSE : RPM_CMD_RX_DONE ;
444+ cmd .lcid = cid ;
445+ cmd .liid = iid ;
446+
447+ qcom_glink_tx (glink , & cmd , sizeof (cmd ), NULL , 0 , true);
448+ if (!reuse ) {
449+ kfree (intent -> data );
450+ kfree (intent );
451+ }
452+ spin_lock_irqsave (& channel -> intent_lock , flags );
453+ }
454+ spin_unlock_irqrestore (& channel -> intent_lock , flags );
455+ }
456+
457+ static void qcom_glink_rx_done (struct qcom_glink * glink ,
458+ struct glink_channel * channel ,
459+ struct glink_core_rx_intent * intent )
460+ {
461+ /* We don't send RX_DONE to intentless systems */
462+ if (glink -> intentless ) {
463+ kfree (intent -> data );
464+ kfree (intent );
465+ return ;
466+ }
467+
468+ /* Take it off the tree of receive intents */
469+ if (!intent -> reuse ) {
470+ spin_lock (& channel -> intent_lock );
471+ idr_remove (& channel -> liids , intent -> id );
472+ spin_unlock (& channel -> intent_lock );
473+ }
474+
475+ /* Schedule the sending of a rx_done indication */
476+ spin_lock (& channel -> intent_lock );
477+ list_add_tail (& intent -> node , & channel -> done_intents );
478+ spin_unlock (& channel -> intent_lock );
479+
480+ schedule_work (& channel -> intent_work );
481+ }
482+
405483/**
406484 * qcom_glink_receive_version() - receive version/features from remote system
407485 *
@@ -718,6 +796,8 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
718796
719797 intent -> offset = 0 ;
720798 channel -> buf = NULL ;
799+
800+ qcom_glink_rx_done (glink , channel , intent );
721801 }
722802
723803advance_rx :
@@ -1106,6 +1186,9 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)
11061186 if (WARN (!channel , "close request on unknown channel\n" ))
11071187 return ;
11081188
1189+ /* cancel pending rx_done work */
1190+ cancel_work_sync (& channel -> intent_work );
1191+
11091192 if (channel -> rpdev ) {
11101193 strncpy (chinfo .name , channel -> name , sizeof (chinfo .name ));
11111194 chinfo .src = RPMSG_ADDR_ANY ;
0 commit comments