Skip to content

Commit 1d2ea36

Browse files
Sricharan Randersson
authored andcommitted
rpmsg: glink: Add rx done command
Send RX data receive ack to remote and also inform that local intent buffer is used and freed. This informs the remote to request for next set of intent buffers before doing a send operation. Acked-by: Arun Kumar Neelakantam <aneela@codeaurora.org> Signed-off-by: Sricharan R <sricharan@codeaurora.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
1 parent b88eee9 commit 1d2ea36

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

drivers/rpmsg/qcom_glink_native.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
192202
static 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

723803
advance_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

Comments
 (0)