summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPi-Hsun Shih <pihsun@chromium.org>2020-02-14 16:26:38 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-04-21 09:06:32 +0200
commit9194f2abf80304b7e40fc0b5a7b050bf721406d8 (patch)
tree2e9f5dcd41cceb74ae5c4e03a326a3b824a77bc3
parentce6d7c58433d37e944d241d9f8b7ebb6234290e2 (diff)
platform/chrome: cros_ec_rpmsg: Fix race with host event
commit f775ac78fcfc6bdc96bdda07029d11f2a5e84869 upstream. Host event can be sent by remoteproc by any time, and cros_ec_rpmsg_callback would be called after cros_ec_rpmsg_create_ept. But the cros_ec_device is initialized after that, which cause host event handler to use cros_ec_device that are not initialized properly yet. Fix this by don't schedule host event handler before cros_ec_register returns. Instead, remember that we have a pending host event, and schedule host event handler after cros_ec_register. Fixes: 71cddb7097e2 ("platform/chrome: cros_ec_rpmsg: Fix race with host command when probe failed.") Signed-off-by: Pi-Hsun Shih <pihsun@chromium.org> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/platform/chrome/cros_ec_rpmsg.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c
index bd068afe43b5..1b38bc8e164c 100644
--- a/drivers/platform/chrome/cros_ec_rpmsg.c
+++ b/drivers/platform/chrome/cros_ec_rpmsg.c
@@ -42,6 +42,8 @@ struct cros_ec_rpmsg {
struct completion xfer_ack;
struct work_struct host_event_work;
struct rpmsg_endpoint *ept;
+ bool has_pending_host_event;
+ bool probe_done;
};
/**
@@ -175,7 +177,14 @@ static int cros_ec_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
memcpy(ec_dev->din, resp->data, len);
complete(&ec_rpmsg->xfer_ack);
} else if (resp->type == HOST_EVENT_MARK) {
- schedule_work(&ec_rpmsg->host_event_work);
+ /*
+ * If the host event is sent before cros_ec_register is
+ * finished, queue the host event.
+ */
+ if (ec_rpmsg->probe_done)
+ schedule_work(&ec_rpmsg->host_event_work);
+ else
+ ec_rpmsg->has_pending_host_event = true;
} else {
dev_warn(ec_dev->dev, "rpmsg received invalid type = %d",
resp->type);
@@ -238,6 +247,11 @@ static int cros_ec_rpmsg_probe(struct rpmsg_device *rpdev)
return ret;
}
+ ec_rpmsg->probe_done = true;
+
+ if (ec_rpmsg->has_pending_host_event)
+ schedule_work(&ec_rpmsg->host_event_work);
+
return 0;
}