rpmsg: glink: do not serve intent request if no callback present
Sometime remote may try to send packet before receive callback is assigned. Which can result in dropping of packets on apps. Acknowledge intent request but queue the intent only when receive callback assignment is complete. Change-Id: Ie366c24e204db7f1609e2345ee3324cb00f56f3e Signed-off-by: Deepak Kumar Singh <deesin@codeaurora.org>
This commit is contained in:
@@ -96,6 +96,7 @@ struct glink_core_rx_intent {
|
|||||||
size_t size;
|
size_t size;
|
||||||
bool reuse;
|
bool reuse;
|
||||||
bool in_use;
|
bool in_use;
|
||||||
|
bool advertised;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
|
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
@@ -768,6 +769,15 @@ static int qcom_glink_advertise_intent(struct qcom_glink *glink,
|
|||||||
__le32 liid;
|
__le32 liid;
|
||||||
} __packed;
|
} __packed;
|
||||||
struct command cmd;
|
struct command cmd;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&channel->intent_lock, flags);
|
||||||
|
if (intent->advertised) {
|
||||||
|
spin_unlock_irqrestore(&channel->intent_lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
intent->advertised = true;
|
||||||
|
spin_unlock_irqrestore(&channel->intent_lock, flags);
|
||||||
|
|
||||||
cmd.id = cpu_to_le16(RPM_CMD_INTENT);
|
cmd.id = cpu_to_le16(RPM_CMD_INTENT);
|
||||||
cmd.lcid = cpu_to_le16(channel->lcid);
|
cmd.lcid = cpu_to_le16(channel->lcid);
|
||||||
@@ -873,6 +883,7 @@ static void qcom_glink_handle_intent_req(struct qcom_glink *glink,
|
|||||||
struct glink_core_rx_intent *intent = NULL;
|
struct glink_core_rx_intent *intent = NULL;
|
||||||
struct glink_core_rx_intent *tmp;
|
struct glink_core_rx_intent *tmp;
|
||||||
struct glink_channel *channel;
|
struct glink_channel *channel;
|
||||||
|
struct rpmsg_endpoint *ept;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int iid;
|
int iid;
|
||||||
|
|
||||||
@@ -898,8 +909,9 @@ static void qcom_glink_handle_intent_req(struct qcom_glink *glink,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ept = &channel->ept;
|
||||||
intent = qcom_glink_alloc_intent(glink, channel, size, false);
|
intent = qcom_glink_alloc_intent(glink, channel, size, false);
|
||||||
if (intent)
|
if (intent && ept->cb)
|
||||||
qcom_glink_advertise_intent(glink, channel, intent);
|
qcom_glink_advertise_intent(glink, channel, intent);
|
||||||
|
|
||||||
qcom_glink_send_intent_req_ack(glink, channel, !!intent);
|
qcom_glink_send_intent_req_ack(glink, channel, !!intent);
|
||||||
@@ -1399,16 +1411,31 @@ static int qcom_glink_announce_create(struct rpmsg_device *rpdev)
|
|||||||
struct device_node *np = rpdev->dev.of_node;
|
struct device_node *np = rpdev->dev.of_node;
|
||||||
struct qcom_glink *glink = channel->glink;
|
struct qcom_glink *glink = channel->glink;
|
||||||
struct glink_core_rx_intent *intent;
|
struct glink_core_rx_intent *intent;
|
||||||
|
struct glink_core_rx_intent *tmp;
|
||||||
const struct property *prop = NULL;
|
const struct property *prop = NULL;
|
||||||
__be32 defaults[] = { cpu_to_be32(SZ_1K), cpu_to_be32(5) };
|
__be32 defaults[] = { cpu_to_be32(SZ_1K), cpu_to_be32(5) };
|
||||||
int num_intents;
|
int num_intents;
|
||||||
int num_groups = 1;
|
int num_groups = 1;
|
||||||
__be32 *val = defaults;
|
__be32 *val = defaults;
|
||||||
|
unsigned long flags;
|
||||||
|
int iid;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
if (glink->intentless || !completion_done(&channel->open_ack))
|
if (glink->intentless || !completion_done(&channel->open_ack))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/*Serve any pending intent request*/
|
||||||
|
spin_lock_irqsave(&channel->intent_lock, flags);
|
||||||
|
idr_for_each_entry(&channel->liids, tmp, iid) {
|
||||||
|
if (!tmp->reuse && !tmp->advertised) {
|
||||||
|
intent = tmp;
|
||||||
|
spin_unlock_irqrestore(&channel->intent_lock, flags);
|
||||||
|
qcom_glink_advertise_intent(glink, channel, intent);
|
||||||
|
spin_lock_irqsave(&channel->intent_lock, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&channel->intent_lock, flags);
|
||||||
|
|
||||||
prop = of_find_property(np, "qcom,intents", NULL);
|
prop = of_find_property(np, "qcom,intents", NULL);
|
||||||
if (prop) {
|
if (prop) {
|
||||||
val = prop->value;
|
val = prop->value;
|
||||||
|
|||||||
Reference in New Issue
Block a user