Loading drivers/rpmsg/qcom_glink_native.c +43 −5 Original line number Diff line number Diff line /* * Copyright (c) 2016-2017, Linaro Ltd * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -126,6 +126,8 @@ struct glink_core_rx_intent { * @lcids: idr of all channels with a known local channel id * @rcids: idr of all channels with a known remote channel id * @in_reset: reset status of this edge * @tx_avail_notify: Waitqueue for pending tx tasks * @sent_read_notify: flag to check cmd sent or not * @ilc: ipc logging context reference */ struct qcom_glink { Loading Loading @@ -159,6 +161,9 @@ struct qcom_glink { bool intentless; wait_queue_head_t tx_avail_notify; bool sent_read_notify; void *ilc; }; Loading Loading @@ -350,6 +355,22 @@ static void qcom_glink_pipe_reset(struct qcom_glink *glink) glink->rx_pipe->reset(glink->rx_pipe); } static void qcom_glink_send_read_notify(struct qcom_glink *glink) { struct glink_msg msg; msg.cmd = cpu_to_le16(RPM_CMD_READ_NOTIF); msg.param1 = 0; msg.param2 = 0; GLINK_INFO(glink->ilc, "send READ NOTIFY cmd\n"); qcom_glink_tx_write(glink, &msg, sizeof(msg), NULL, 0); mbox_send_message(glink->mbox_chan, NULL); mbox_client_txdone(glink->mbox_chan, 0); } static int qcom_glink_tx(struct qcom_glink *glink, const void *hdr, size_t hlen, const void *data, size_t dlen, bool wait) Loading @@ -373,17 +394,27 @@ static int qcom_glink_tx(struct qcom_glink *glink, goto out; } if (atomic_read(&glink->in_reset)) { ret = -ECONNRESET; goto out; if (!glink->sent_read_notify) { glink->sent_read_notify = true; qcom_glink_send_read_notify(glink); } /* Wait without holding the tx_lock */ spin_unlock_irqrestore(&glink->tx_lock, flags); usleep_range(10000, 15000); wait_event_timeout(glink->tx_avail_notify, (qcom_glink_tx_avail(glink) >= tlen || atomic_read(&glink->in_reset)), 10 * HZ); spin_lock_irqsave(&glink->tx_lock, flags); if (atomic_read(&glink->in_reset)) { ret = -ECONNRESET; goto out; } if (qcom_glink_tx_avail(glink) >= tlen) glink->sent_read_notify = false; } qcom_glink_tx_write(glink, hdr, hlen, data, dlen); Loading Loading @@ -1151,6 +1182,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) unsigned int cmd; int ret = 0; /* To wakeup any blocking writers */ wake_up_all(&glink->tx_avail_notify); for (;;) { avail = qcom_glink_rx_avail(glink); if (avail < sizeof(msg)) Loading Loading @@ -1899,6 +1933,9 @@ static void qcom_glink_notif_reset(void *data) return; atomic_inc(&glink->in_reset); /* To wakeup any blocking writers */ wake_up_all(&glink->tx_avail_notify); spin_lock_irqsave(&glink->idr_lock, flags); idr_for_each_entry(&glink->lcids, channel, cid) { wake_up(&channel->intent_req_event); Loading Loading @@ -1935,6 +1972,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, spin_lock_init(&glink->rx_lock); INIT_LIST_HEAD(&glink->rx_queue); INIT_WORK(&glink->rx_work, qcom_glink_work); init_waitqueue_head(&glink->tx_avail_notify); spin_lock_init(&glink->idr_lock); idr_init(&glink->lcids); Loading Loading
drivers/rpmsg/qcom_glink_native.c +43 −5 Original line number Diff line number Diff line /* * Copyright (c) 2016-2017, Linaro Ltd * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -126,6 +126,8 @@ struct glink_core_rx_intent { * @lcids: idr of all channels with a known local channel id * @rcids: idr of all channels with a known remote channel id * @in_reset: reset status of this edge * @tx_avail_notify: Waitqueue for pending tx tasks * @sent_read_notify: flag to check cmd sent or not * @ilc: ipc logging context reference */ struct qcom_glink { Loading Loading @@ -159,6 +161,9 @@ struct qcom_glink { bool intentless; wait_queue_head_t tx_avail_notify; bool sent_read_notify; void *ilc; }; Loading Loading @@ -350,6 +355,22 @@ static void qcom_glink_pipe_reset(struct qcom_glink *glink) glink->rx_pipe->reset(glink->rx_pipe); } static void qcom_glink_send_read_notify(struct qcom_glink *glink) { struct glink_msg msg; msg.cmd = cpu_to_le16(RPM_CMD_READ_NOTIF); msg.param1 = 0; msg.param2 = 0; GLINK_INFO(glink->ilc, "send READ NOTIFY cmd\n"); qcom_glink_tx_write(glink, &msg, sizeof(msg), NULL, 0); mbox_send_message(glink->mbox_chan, NULL); mbox_client_txdone(glink->mbox_chan, 0); } static int qcom_glink_tx(struct qcom_glink *glink, const void *hdr, size_t hlen, const void *data, size_t dlen, bool wait) Loading @@ -373,17 +394,27 @@ static int qcom_glink_tx(struct qcom_glink *glink, goto out; } if (atomic_read(&glink->in_reset)) { ret = -ECONNRESET; goto out; if (!glink->sent_read_notify) { glink->sent_read_notify = true; qcom_glink_send_read_notify(glink); } /* Wait without holding the tx_lock */ spin_unlock_irqrestore(&glink->tx_lock, flags); usleep_range(10000, 15000); wait_event_timeout(glink->tx_avail_notify, (qcom_glink_tx_avail(glink) >= tlen || atomic_read(&glink->in_reset)), 10 * HZ); spin_lock_irqsave(&glink->tx_lock, flags); if (atomic_read(&glink->in_reset)) { ret = -ECONNRESET; goto out; } if (qcom_glink_tx_avail(glink) >= tlen) glink->sent_read_notify = false; } qcom_glink_tx_write(glink, hdr, hlen, data, dlen); Loading Loading @@ -1151,6 +1182,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) unsigned int cmd; int ret = 0; /* To wakeup any blocking writers */ wake_up_all(&glink->tx_avail_notify); for (;;) { avail = qcom_glink_rx_avail(glink); if (avail < sizeof(msg)) Loading Loading @@ -1899,6 +1933,9 @@ static void qcom_glink_notif_reset(void *data) return; atomic_inc(&glink->in_reset); /* To wakeup any blocking writers */ wake_up_all(&glink->tx_avail_notify); spin_lock_irqsave(&glink->idr_lock, flags); idr_for_each_entry(&glink->lcids, channel, cid) { wake_up(&channel->intent_req_event); Loading Loading @@ -1935,6 +1972,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, spin_lock_init(&glink->rx_lock); INIT_LIST_HEAD(&glink->rx_queue); INIT_WORK(&glink->rx_work, qcom_glink_work); init_waitqueue_head(&glink->tx_avail_notify); spin_lock_init(&glink->idr_lock); idr_init(&glink->lcids); Loading