From 664de6a26b7f17eebca896c3e18201b15d5c7b19 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Wed, 26 Jan 2022 14:22:33 -0800 Subject: [PATCH 1/9] MAINTAINERS: platform-chrome: Add new chrome-platform@lists.linux.dev list Chrome Platform now has a mailing list. Signed-off-by: Benson Leung Reviewed-by: Prashant Malani Link: https://lore.kernel.org/r/20220126222233.2852280-1-bleung@chromium.org --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ea3e6c914384..cad7b0fff9f4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4537,6 +4537,7 @@ F: drivers/input/touchscreen/chipone_icn8505.c CHROME HARDWARE PLATFORM SUPPORT M: Benson Leung +L: chrome-platform@lists.linux.dev S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git F: drivers/platform/chrome/ @@ -4544,6 +4545,7 @@ F: drivers/platform/chrome/ CHROMEOS EC CODEC DRIVER M: Cheng-Yi Chiang R: Guenter Roeck +L: chrome-platform@lists.linux.dev S: Maintained F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml F: sound/soc/codecs/cros_ec_codec.* @@ -4551,6 +4553,7 @@ F: sound/soc/codecs/cros_ec_codec.* CHROMEOS EC SUBDRIVERS M: Benson Leung R: Guenter Roeck +L: chrome-platform@lists.linux.dev S: Maintained F: drivers/power/supply/cros_usbpd-charger.c N: cros_ec @@ -4558,11 +4561,13 @@ N: cros-ec CHROMEOS EC USB TYPE-C DRIVER M: Prashant Malani +L: chrome-platform@lists.linux.dev S: Maintained F: drivers/platform/chrome/cros_ec_typec.c CHROMEOS EC USB PD NOTIFY DRIVER M: Prashant Malani +L: chrome-platform@lists.linux.dev S: Maintained F: drivers/platform/chrome/cros_usbpd_notify.c F: include/linux/platform_data/cros_usbpd_notify.h From 53eeb07381f2fa426807df6a68fc580b8463dae4 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 27 Jan 2022 19:16:59 +0000 Subject: [PATCH 2/9] platform/chrome: cros_ec_typec: Make try power role optional Some boards prefer not to specify a try-power-role. Update the port property parsing logic to not error out in case a try-power-role is not specified. Cc: Heikki Krogerus Signed-off-by: Prashant Malani Acked-by: Heikki Krogerus Link: https://lore.kernel.org/chrome-platform/20220127191659.3560810-1-pmalani@chromium.org/ --- drivers/platform/chrome/cros_ec_typec.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 5de0bfb0bc4d..ee12658009e5 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -115,17 +115,18 @@ static int cros_typec_parse_port_props(struct typec_capability *cap, return ret; cap->data = ret; + /* Try-power-role is optional. */ ret = fwnode_property_read_string(fwnode, "try-power-role", &buf); if (ret) { - dev_err(dev, "try-power-role not found: %d\n", ret); - return ret; + dev_warn(dev, "try-power-role not found: %d\n", ret); + cap->prefer_role = TYPEC_NO_PREFERRED_ROLE; + } else { + ret = typec_find_power_role(buf); + if (ret < 0) + return ret; + cap->prefer_role = ret; } - ret = typec_find_power_role(buf); - if (ret < 0) - return ret; - cap->prefer_role = ret; - cap->fwnode = fwnode; return 0; From ffebd90532728086007038986900426544e3df4e Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Wed, 26 Jan 2022 19:02:20 +0000 Subject: [PATCH 3/9] platform/chrome: cros_ec_typec: Check for EC device The Type C ACPI device on older Chromebooks is not generated correctly (since their EC firmware doesn't support the new commands required). In such cases, the crafted ACPI device doesn't have an EC parent, and it is therefore not useful (it shouldn't be generated in the first place since the EC firmware doesn't support any of the Type C commands). To handle devices which use these older firmware revisions, check for the parent EC device handle, and fail the probe if it's not found. Fixes: fdc6b21e2444 ("platform/chrome: Add Type C connector class driver") Reported-by: Alyssa Ross Reviewed-by: Tzung-Bi Shih Signed-off-by: Prashant Malani Acked-by: Heikki Krogerus Reviewed-by: Alyssa Ross Tested-by: Alyssa Ross Link: https://lore.kernel.org/r/20220126190219.3095419-1-pmalani@chromium.org Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_typec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index ee12658009e5..c6f17e3ef72d 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -1076,7 +1076,13 @@ static int cros_typec_probe(struct platform_device *pdev) return -ENOMEM; typec->dev = dev; + typec->ec = dev_get_drvdata(pdev->dev.parent); + if (!typec->ec) { + dev_err(dev, "couldn't find parent EC device\n"); + return -ENODEV; + } + platform_set_drvdata(pdev, typec); ret = cros_typec_get_cmd_version(typec); From 53a0023c64509ac0fa3961f321659a6fb0b62794 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 8 Feb 2022 18:47:18 +0000 Subject: [PATCH 4/9] platform/chrome: cros_ec_typec: Move mux flag checks Move mux and role flag checks inside of cros_typec_configure_mux(), which is a more logical location for them. Signed-off-by: Prashant Malani Reviewed-by: Tzung-Bi Shih Link: https://lore.kernel.org/chrome-platform/20220208184721.1697194-2-pmalani@chromium.org/ --- drivers/platform/chrome/cros_ec_typec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index c6f17e3ef72d..58d08dd02f65 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -521,6 +521,13 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, enum typec_orientation orientation; int ret; + /* No change needs to be made, let's exit early. */ + if (port->mux_flags == mux_flags && port->role == pd_ctrl->role) + return 0; + + port->mux_flags = mux_flags; + port->role = pd_ctrl->role; + if (mux_flags == USB_PD_MUX_NONE) { ret = cros_typec_usb_disconnect_state(port); goto mux_ack; @@ -983,13 +990,6 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) return 0; } - /* No change needs to be made, let's exit early. */ - if (typec->ports[port_num]->mux_flags == mux_resp.flags && - typec->ports[port_num]->role == resp.role) - return 0; - - typec->ports[port_num]->mux_flags = mux_resp.flags; - typec->ports[port_num]->role = resp.role; ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp); if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); From 0d8495dc0321ff1f9f3d50edfa45c7f34194d0c6 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 8 Feb 2022 18:47:20 +0000 Subject: [PATCH 5/9] platform/chrome: cros_ec_typec: Get mux state inside configure_mux Move the function which gets current mux state inside the cros_typec_configure_mux() function. It is better to group those bits of functionality together, and it makes it easier to move around cros_typec_configure_mux() later. While we are doing this, also inline the cros_typec_get_mux_info() inside of cros_typec_configure_mux(). Signed-off-by: Prashant Malani Reviewed-by: Tzung-Bi Shih Link: https://lore.kernel.org/chrome-platform/20220208184721.1697194-3-pmalani@chromium.org/ --- drivers/platform/chrome/cros_ec_typec.c | 55 +++++++++++-------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 58d08dd02f65..3d34ece7f790 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -513,27 +513,38 @@ static int cros_typec_enable_usb4(struct cros_typec_data *typec, } static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, - uint8_t mux_flags, struct ec_response_usb_pd_control_v2 *pd_ctrl) { struct cros_typec_port *port = typec->ports[port_num]; + struct ec_response_usb_pd_mux_info resp; + struct ec_params_usb_pd_mux_info req = { + .port = port_num, + }; struct ec_params_usb_pd_mux_ack mux_ack; enum typec_orientation orientation; int ret; + ret = cros_ec_command(typec->ec, 0, EC_CMD_USB_PD_MUX_INFO, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) { + dev_warn(typec->dev, "Failed to get mux info for port: %d, err = %d\n", + port_num, ret); + return ret; + } + /* No change needs to be made, let's exit early. */ - if (port->mux_flags == mux_flags && port->role == pd_ctrl->role) + if (port->mux_flags == resp.flags && port->role == pd_ctrl->role) return 0; - port->mux_flags = mux_flags; + port->mux_flags = resp.flags; port->role = pd_ctrl->role; - if (mux_flags == USB_PD_MUX_NONE) { + if (port->mux_flags == USB_PD_MUX_NONE) { ret = cros_typec_usb_disconnect_state(port); goto mux_ack; } - if (mux_flags & USB_PD_MUX_POLARITY_INVERTED) + if (port->mux_flags & USB_PD_MUX_POLARITY_INVERTED) orientation = TYPEC_ORIENTATION_REVERSE; else orientation = TYPEC_ORIENTATION_NORMAL; @@ -548,22 +559,22 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; - if (mux_flags & USB_PD_MUX_USB4_ENABLED) { + if (port->mux_flags & USB_PD_MUX_USB4_ENABLED) { ret = cros_typec_enable_usb4(typec, port_num, pd_ctrl); - } else if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { + } else if (port->mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); - } else if (mux_flags & USB_PD_MUX_DP_ENABLED) { + } else if (port->mux_flags & USB_PD_MUX_DP_ENABLED) { ret = cros_typec_enable_dp(typec, port_num, pd_ctrl); - } else if (mux_flags & USB_PD_MUX_SAFE_MODE) { + } else if (port->mux_flags & USB_PD_MUX_SAFE_MODE) { ret = cros_typec_usb_safe_state(port); - } else if (mux_flags & USB_PD_MUX_USB_ENABLED) { + } else if (port->mux_flags & USB_PD_MUX_USB_ENABLED) { port->state.alt = NULL; port->state.mode = TYPEC_STATE_USB; ret = typec_mux_set(port->mux, &port->state); } else { dev_dbg(typec->dev, "Unrecognized mode requested, mux flags: %x\n", - mux_flags); + port->mux_flags); } mux_ack: @@ -638,17 +649,6 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec, } } -static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num, - struct ec_response_usb_pd_mux_info *resp) -{ - struct ec_params_usb_pd_mux_info req = { - .port = port_num, - }; - - return cros_ec_command(typec->ec, 0, EC_CMD_USB_PD_MUX_INFO, &req, - sizeof(req), resp, sizeof(*resp)); -} - /* * Helper function to register partner/plug altmodes. */ @@ -946,7 +946,6 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) { struct ec_params_usb_pd_control req; struct ec_response_usb_pd_control_v2 resp; - struct ec_response_usb_pd_mux_info mux_resp; int ret; if (port_num < 0 || port_num >= typec->num_ports) { @@ -982,15 +981,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) cros_typec_handle_status(typec, port_num); /* Update the switches if they exist, according to requested state */ - ret = cros_typec_get_mux_info(typec, port_num, &mux_resp); - if (ret < 0) { - dev_warn(typec->dev, - "Failed to get mux info for port: %d, err = %d\n", - port_num, ret); - return 0; - } - - ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp); + ret = cros_typec_configure_mux(typec, port_num, &resp); if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); From af34f115b3b74cf70d8842c436374b08feada143 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 8 Feb 2022 18:47:22 +0000 Subject: [PATCH 6/9] platform/chrome: cros_ec_typec: Configure muxes at start of port update There are situations where the mux state reported by the Embedded Controller (EC), might lag the partner "connected" state. So, the mux state might still suggest that a partner is connected, while the PD "connected" state, being in Try.SNK (for example) suggests that the partner is disconnected. In such a scenario, we will end up sending a disconnect command to the mux driver, followed by a connect command, since the mux is configured later. Avoid this by configuring the mux before registering/disconnecting a partner. Signed-off-by: Prashant Malani Reviewed-by: Benson Leung Link: https://lore.kernel.org/chrome-platform/20220208184721.1697194-4-pmalani@chromium.org/ --- drivers/platform/chrome/cros_ec_typec.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 3d34ece7f790..3019e29f200d 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -965,6 +965,11 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) if (ret < 0) return ret; + /* Update the switches if they exist, according to requested state */ + ret = cros_typec_configure_mux(typec, port_num, &resp); + if (ret) + dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); + dev_dbg(typec->dev, "Enabled %d: 0x%hhx\n", port_num, resp.enabled); dev_dbg(typec->dev, "Role %d: 0x%hhx\n", port_num, resp.role); dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity); @@ -980,12 +985,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) if (typec->typec_cmd_supported) cros_typec_handle_status(typec, port_num); - /* Update the switches if they exist, according to requested state */ - ret = cros_typec_configure_mux(typec, port_num, &resp); - if (ret) - dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); - - return ret; + return 0; } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) From b579f139e47037cf98808ccf7511a6deb02f3b18 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 8 Feb 2022 18:47:24 +0000 Subject: [PATCH 7/9] platform/chrome: cros_ec_typec: Update mux flags during partner removal In cros_typec_remove_partner(), we call cros_typec_usb_disconnect_state() which sets the switches/muxes to be in a disconnected state. This also happens in cros_typec_configure_mux(). However, unlike there, here the mux_flags variable hasn't been updated to reflect that a disconnection has occurred. Update the flag here accordingly. Signed-off-by: Prashant Malani Reviewed-by: Tzung-Bi Shih Link: https://lore.kernel.org/chrome-platform/20220208184721.1697194-5-pmalani@chromium.org/ --- drivers/platform/chrome/cros_ec_typec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 3019e29f200d..4bd2752c0823 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -228,6 +228,7 @@ static void cros_typec_remove_partner(struct cros_typec_data *typec, cros_typec_unregister_altmodes(typec, port_num, true); cros_typec_usb_disconnect_state(port); + port->mux_flags = USB_PD_MUX_NONE; typec_unregister_partner(port->partner); port->partner = NULL; From eabd9a3807e17e211690e6c40f1405b427b64c48 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 21 Jan 2022 16:13:01 -0800 Subject: [PATCH 8/9] platform: chrome: Split trace include file cros_ec_trace.h defined 5 tracing events, 2 for cros_ec_proto and 3 for cros_ec_sensorhub_ring. These 2 files are in different kernel modules, the traces are defined twice in the kernel which leads to problem enabling only some traces. Move sensorhub traces from cros_ec_trace.h to cros_ec_sensorhub_trace.h and enable them only in cros_ec_sensorhub kernel module. Check we can now enable any single traces: without this patch, we can only enable all sensorhub traces or none. Fixes: d453ceb6549a ("platform/chrome: sensorhub: Add trace events for sample") Signed-off-by: Gwendal Grignou Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20220122001301.640337-1-gwendal@chromium.org Signed-off-by: Benson Leung --- drivers/platform/chrome/Makefile | 3 +- .../platform/chrome/cros_ec_sensorhub_ring.c | 3 +- .../platform/chrome/cros_ec_sensorhub_trace.h | 123 ++++++++++++++++++ drivers/platform/chrome/cros_ec_trace.h | 95 -------------- 4 files changed, 127 insertions(+), 97 deletions(-) create mode 100644 drivers/platform/chrome/cros_ec_sensorhub_trace.h diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index f901d2e43166..88cbc434c06b 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -2,6 +2,7 @@ # tell define_trace.h where to find the cros ec trace header CFLAGS_cros_ec_trace.o:= -I$(src) +CFLAGS_cros_ec_sensorhub_ring.o:= -I$(src) obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o @@ -20,7 +21,7 @@ obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_chardev.o obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o -cros-ec-sensorhub-objs := cros_ec_sensorhub.o cros_ec_sensorhub_ring.o cros_ec_trace.o +cros-ec-sensorhub-objs := cros_ec_sensorhub.o cros_ec_sensorhub_ring.o obj-$(CONFIG_CROS_EC_SENSORHUB) += cros-ec-sensorhub.o obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o obj-$(CONFIG_CROS_USBPD_LOGGER) += cros_usbpd_logger.o diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c b/drivers/platform/chrome/cros_ec_sensorhub_ring.c index 98e37080f760..71948dade0e2 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c +++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c @@ -17,7 +17,8 @@ #include #include -#include "cros_ec_trace.h" +#define CREATE_TRACE_POINTS +#include "cros_ec_sensorhub_trace.h" /* Precision of fixed point for the m values from the filter */ #define M_PRECISION BIT(23) diff --git a/drivers/platform/chrome/cros_ec_sensorhub_trace.h b/drivers/platform/chrome/cros_ec_sensorhub_trace.h new file mode 100644 index 000000000000..57d9b4785969 --- /dev/null +++ b/drivers/platform/chrome/cros_ec_sensorhub_trace.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Trace events for the ChromeOS Sensorhub kernel module + * + * Copyright 2021 Google LLC. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM cros_ec + +#if !defined(_CROS_EC_SENSORHUB_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) +#define _CROS_EC_SENSORHUB_TRACE_H_ + +#include +#include + +#include + +TRACE_EVENT(cros_ec_sensorhub_timestamp, + TP_PROTO(u32 ec_sample_timestamp, u32 ec_fifo_timestamp, s64 fifo_timestamp, + s64 current_timestamp, s64 current_time), + TP_ARGS(ec_sample_timestamp, ec_fifo_timestamp, fifo_timestamp, current_timestamp, + current_time), + TP_STRUCT__entry( + __field(u32, ec_sample_timestamp) + __field(u32, ec_fifo_timestamp) + __field(s64, fifo_timestamp) + __field(s64, current_timestamp) + __field(s64, current_time) + __field(s64, delta) + ), + TP_fast_assign( + __entry->ec_sample_timestamp = ec_sample_timestamp; + __entry->ec_fifo_timestamp = ec_fifo_timestamp; + __entry->fifo_timestamp = fifo_timestamp; + __entry->current_timestamp = current_timestamp; + __entry->current_time = current_time; + __entry->delta = current_timestamp - current_time; + ), + TP_printk("ec_ts: %9u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld", + __entry->ec_sample_timestamp, + __entry->ec_fifo_timestamp, + __entry->fifo_timestamp, + __entry->current_timestamp, + __entry->current_time, + __entry->delta + ) +); + +TRACE_EVENT(cros_ec_sensorhub_data, + TP_PROTO(u32 ec_sensor_num, u32 ec_fifo_timestamp, s64 fifo_timestamp, + s64 current_timestamp, s64 current_time), + TP_ARGS(ec_sensor_num, ec_fifo_timestamp, fifo_timestamp, current_timestamp, current_time), + TP_STRUCT__entry( + __field(u32, ec_sensor_num) + __field(u32, ec_fifo_timestamp) + __field(s64, fifo_timestamp) + __field(s64, current_timestamp) + __field(s64, current_time) + __field(s64, delta) + ), + TP_fast_assign( + __entry->ec_sensor_num = ec_sensor_num; + __entry->ec_fifo_timestamp = ec_fifo_timestamp; + __entry->fifo_timestamp = fifo_timestamp; + __entry->current_timestamp = current_timestamp; + __entry->current_time = current_time; + __entry->delta = current_timestamp - current_time; + ), + TP_printk("ec_num: %4u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld", + __entry->ec_sensor_num, + __entry->ec_fifo_timestamp, + __entry->fifo_timestamp, + __entry->current_timestamp, + __entry->current_time, + __entry->delta + ) +); + +TRACE_EVENT(cros_ec_sensorhub_filter, + TP_PROTO(struct cros_ec_sensors_ts_filter_state *state, s64 dx, s64 dy), + TP_ARGS(state, dx, dy), + TP_STRUCT__entry( + __field(s64, dx) + __field(s64, dy) + __field(s64, median_m) + __field(s64, median_error) + __field(s64, history_len) + __field(s64, x) + __field(s64, y) + ), + TP_fast_assign( + __entry->dx = dx; + __entry->dy = dy; + __entry->median_m = state->median_m; + __entry->median_error = state->median_error; + __entry->history_len = state->history_len; + __entry->x = state->x_offset; + __entry->y = state->y_offset; + ), + TP_printk("dx: %12lld. dy: %12lld median_m: %12lld median_error: %12lld len: %lld x: %12lld y: %12lld", + __entry->dx, + __entry->dy, + __entry->median_m, + __entry->median_error, + __entry->history_len, + __entry->x, + __entry->y + ) +); + + +#endif /* _CROS_EC_SENSORHUB_TRACE_H_ */ + +/* this part must be outside header guard */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE cros_ec_sensorhub_trace + +#include diff --git a/drivers/platform/chrome/cros_ec_trace.h b/drivers/platform/chrome/cros_ec_trace.h index 7e7cfc98657a..9bb5cd2c98b8 100644 --- a/drivers/platform/chrome/cros_ec_trace.h +++ b/drivers/platform/chrome/cros_ec_trace.h @@ -15,7 +15,6 @@ #include #include #include -#include #include @@ -71,100 +70,6 @@ TRACE_EVENT(cros_ec_request_done, __entry->retval) ); -TRACE_EVENT(cros_ec_sensorhub_timestamp, - TP_PROTO(u32 ec_sample_timestamp, u32 ec_fifo_timestamp, s64 fifo_timestamp, - s64 current_timestamp, s64 current_time), - TP_ARGS(ec_sample_timestamp, ec_fifo_timestamp, fifo_timestamp, current_timestamp, - current_time), - TP_STRUCT__entry( - __field(u32, ec_sample_timestamp) - __field(u32, ec_fifo_timestamp) - __field(s64, fifo_timestamp) - __field(s64, current_timestamp) - __field(s64, current_time) - __field(s64, delta) - ), - TP_fast_assign( - __entry->ec_sample_timestamp = ec_sample_timestamp; - __entry->ec_fifo_timestamp = ec_fifo_timestamp; - __entry->fifo_timestamp = fifo_timestamp; - __entry->current_timestamp = current_timestamp; - __entry->current_time = current_time; - __entry->delta = current_timestamp - current_time; - ), - TP_printk("ec_ts: %9u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld", - __entry->ec_sample_timestamp, - __entry->ec_fifo_timestamp, - __entry->fifo_timestamp, - __entry->current_timestamp, - __entry->current_time, - __entry->delta - ) -); - -TRACE_EVENT(cros_ec_sensorhub_data, - TP_PROTO(u32 ec_sensor_num, u32 ec_fifo_timestamp, s64 fifo_timestamp, - s64 current_timestamp, s64 current_time), - TP_ARGS(ec_sensor_num, ec_fifo_timestamp, fifo_timestamp, current_timestamp, current_time), - TP_STRUCT__entry( - __field(u32, ec_sensor_num) - __field(u32, ec_fifo_timestamp) - __field(s64, fifo_timestamp) - __field(s64, current_timestamp) - __field(s64, current_time) - __field(s64, delta) - ), - TP_fast_assign( - __entry->ec_sensor_num = ec_sensor_num; - __entry->ec_fifo_timestamp = ec_fifo_timestamp; - __entry->fifo_timestamp = fifo_timestamp; - __entry->current_timestamp = current_timestamp; - __entry->current_time = current_time; - __entry->delta = current_timestamp - current_time; - ), - TP_printk("ec_num: %4u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld", - __entry->ec_sensor_num, - __entry->ec_fifo_timestamp, - __entry->fifo_timestamp, - __entry->current_timestamp, - __entry->current_time, - __entry->delta - ) -); - -TRACE_EVENT(cros_ec_sensorhub_filter, - TP_PROTO(struct cros_ec_sensors_ts_filter_state *state, s64 dx, s64 dy), - TP_ARGS(state, dx, dy), - TP_STRUCT__entry( - __field(s64, dx) - __field(s64, dy) - __field(s64, median_m) - __field(s64, median_error) - __field(s64, history_len) - __field(s64, x) - __field(s64, y) - ), - TP_fast_assign( - __entry->dx = dx; - __entry->dy = dy; - __entry->median_m = state->median_m; - __entry->median_error = state->median_error; - __entry->history_len = state->history_len; - __entry->x = state->x_offset; - __entry->y = state->y_offset; - ), - TP_printk("dx: %12lld. dy: %12lld median_m: %12lld median_error: %12lld len: %lld x: %12lld y: %12lld", - __entry->dx, - __entry->dy, - __entry->median_m, - __entry->median_error, - __entry->history_len, - __entry->x, - __entry->y - ) -); - - #endif /* _CROS_EC_TRACE_H_ */ /* this part must be outside header guard */ From 0e8eb5e8acbad19ac2e1856b2fb2320184299b33 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 9 Feb 2022 13:11:30 +0800 Subject: [PATCH 9/9] platform/chrome: cros_ec_debugfs: detach log reader wq from devm Debugfs console_log uses devm memory (e.g. debug_info in cros_ec_console_log_poll()). However, lifecycles of device and debugfs are independent. An use-after-free issue is observed if userland program operates the debugfs after the memory has been freed. The call trace: do_raw_spin_lock _raw_spin_lock_irqsave remove_wait_queue ep_unregister_pollwait ep_remove do_epoll_ctl A Python example to reproduce the issue: ... import select ... p = select.epoll() ... f = open('/sys/kernel/debug/cros_scp/console_log') ... p.register(f, select.POLLIN) ... p.poll(1) [(4, 1)] # 4=fd, 1=select.POLLIN [ shutdown cros_scp at the point ] ... p.poll(1) [(4, 16)] # 4=fd, 16=select.POLLHUP ... p.unregister(f) An use-after-free issue raises here. It called epoll_ctl with EPOLL_CTL_DEL which in turn to use the workqueue in the devm (i.e. log_wq). Detaches log reader's workqueue from devm to make sure it is persistent even if the device has been removed. Signed-off-by: Tzung-Bi Shih Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220209051130.386175-1-tzungbi@google.com Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_debugfs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index 272c89837d74..0dbceee87a4b 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c @@ -25,6 +25,9 @@ #define CIRC_ADD(idx, size, value) (((idx) + (value)) & ((size) - 1)) +/* waitqueue for log readers */ +static DECLARE_WAIT_QUEUE_HEAD(cros_ec_debugfs_log_wq); + /** * struct cros_ec_debugfs - EC debugging information. * @@ -33,7 +36,6 @@ * @log_buffer: circular buffer for console log information * @read_msg: preallocated EC command and buffer to read console log * @log_mutex: mutex to protect circular buffer - * @log_wq: waitqueue for log readers * @log_poll_work: recurring task to poll EC for new console log data * @panicinfo_blob: panicinfo debugfs blob */ @@ -44,7 +46,6 @@ struct cros_ec_debugfs { struct circ_buf log_buffer; struct cros_ec_command *read_msg; struct mutex log_mutex; - wait_queue_head_t log_wq; struct delayed_work log_poll_work; /* EC panicinfo */ struct debugfs_blob_wrapper panicinfo_blob; @@ -107,7 +108,7 @@ static void cros_ec_console_log_work(struct work_struct *__work) buf_space--; } - wake_up(&debug_info->log_wq); + wake_up(&cros_ec_debugfs_log_wq); } mutex_unlock(&debug_info->log_mutex); @@ -141,7 +142,7 @@ static ssize_t cros_ec_console_log_read(struct file *file, char __user *buf, mutex_unlock(&debug_info->log_mutex); - ret = wait_event_interruptible(debug_info->log_wq, + ret = wait_event_interruptible(cros_ec_debugfs_log_wq, CIRC_CNT(cb->head, cb->tail, LOG_SIZE)); if (ret < 0) return ret; @@ -173,7 +174,7 @@ static __poll_t cros_ec_console_log_poll(struct file *file, struct cros_ec_debugfs *debug_info = file->private_data; __poll_t mask = 0; - poll_wait(file, &debug_info->log_wq, wait); + poll_wait(file, &cros_ec_debugfs_log_wq, wait); mutex_lock(&debug_info->log_mutex); if (CIRC_CNT(debug_info->log_buffer.head, @@ -377,7 +378,6 @@ static int cros_ec_create_console_log(struct cros_ec_debugfs *debug_info) debug_info->log_buffer.tail = 0; mutex_init(&debug_info->log_mutex); - init_waitqueue_head(&debug_info->log_wq); debugfs_create_file("console_log", S_IFREG | 0444, debug_info->dir, debug_info, &cros_ec_console_log_fops);