lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20260205-smaug-type_c-v1-1-d6e556bf6640@tecnico.ulisboa.pt>
Date: Thu, 05 Feb 2026 10:04:09 +0000
From: Diogo Ivo <diogo.ivo@...nico.ulisboa.pt>
To: Benson Leung <bleung@...omium.org>, 
 Abhishek Pandit-Subedi <abhishekpandit@...omium.org>, 
 Jameson Thies <jthies@...gle.com>, 
 Andrei Kuchynski <akuchynski@...omium.org>, 
 Tzung-Bi Shih <tzungbi@...nel.org>, Guenter Roeck <groeck@...omium.org>
Cc: chrome-platform@...ts.linux.dev, linux-kernel@...r.kernel.org, 
 Diogo Ivo <diogo.ivo@...nico.ulisboa.pt>
Subject: [PATCH] platform/chrome: cros_ec_typec: Skip Type-C mux handling
 in EC-driven devices

Currently the code assumes that the EC firmware will leave Type-C mux
handling logic to the AP, exposing an interface to query and change the
mux state via a request from the AP. However, in devices such as Smaug
the EC automatically takes care of mux configuration and only USB role
switching needs to be handled by the AP. In fact, in such devices this
interface is not exposed by the EC making the whole process fail,
including role switching.

Fix this by first separating Type-C mux handling and USB role switching,
explicitly querying the behaviour of the EC and execute each part
conditionally according to what the EC reported.

Signed-off-by: Diogo Ivo <diogo.ivo@...nico.ulisboa.pt>
---
 drivers/platform/chrome/cros_ec_typec.c | 49 +++++++++++++++++++++++----------
 drivers/platform/chrome/cros_ec_typec.h |  2 +-
 2 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index b712bcff6fb2..bd7e6c365cab 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -751,11 +751,10 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
 	}
 
 	/* No change needs to be made, let's exit early. */
-	if (port->mux_flags == resp.flags && port->role == pd_ctrl->role)
+	if (port->mux_flags == resp.flags)
 		return 0;
 
 	port->mux_flags = resp.flags;
-	port->role = pd_ctrl->role;
 
 	if (port->mux_flags == USB_PD_MUX_NONE) {
 		ret = cros_typec_usb_disconnect_state(port);
@@ -771,12 +770,6 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
 	if (ret)
 		return ret;
 
-	ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw,
-					pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA
-					? USB_ROLE_HOST : USB_ROLE_DEVICE);
-	if (ret)
-		return ret;
-
 	if (port->mux_flags & USB_PD_MUX_USB4_ENABLED) {
 		ret = cros_typec_enable_usb4(typec, port_num, pd_ctrl);
 	} else if (port->mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) {
@@ -822,6 +815,25 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
 	return ret;
 }
 
+static int cros_typec_set_role(struct cros_typec_data *typec, int port_num,
+			       struct ec_response_usb_pd_control_v1 *resp)
+{
+	enum usb_role cur_role = usb_role_switch_get_role(typec->ports[port_num]->role_sw);
+	enum usb_role role = resp->role & PD_CTRL_RESP_ROLE_DATA ? USB_ROLE_HOST :
+								   USB_ROLE_DEVICE;
+	bool connected = resp->enabled & PD_CTRL_RESP_ENABLED_CONNECTED;
+	int ret;
+
+	if (!connected || cur_role == role)
+		return 0;
+
+	ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw, role);
+	if (ret)
+		dev_err(typec->dev, "Failed USB role switch, err = %d\n", ret);
+
+	return ret;
+}
+
 static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
 		int port_num, struct ec_response_usb_pd_control *resp)
 {
@@ -1251,27 +1263,32 @@ 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);
+	if (typec->ap_driven_mux) {
+		/* 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);
 	dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
 
-	if (typec->pd_ctrl_ver != 0)
+	if (typec->pd_ctrl_ver != 0) {
+		ret = cros_typec_set_role(typec, port_num,
+			(struct ec_response_usb_pd_control_v1 *)&resp);
 		cros_typec_set_port_params_v1(typec, port_num,
 			(struct ec_response_usb_pd_control_v1 *)&resp);
-	else
+	} else {
 		cros_typec_set_port_params_v0(typec, port_num,
 			(struct ec_response_usb_pd_control *) &resp);
+	}
 
 	if (typec->typec_cmd_supported)
 		cros_typec_handle_status(typec, port_num);
 
-	return 0;
+	return ret;
 }
 
 static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
@@ -1375,6 +1392,8 @@ static int cros_typec_probe(struct platform_device *pdev)
 	typec->needs_mux_ack = cros_ec_check_features(ec_dev, EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK);
 	typec->ap_driven_altmode = cros_ec_check_features(
 		ec_dev, EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY);
+	typec->ap_driven_mux = cros_ec_check_features(
+		ec_dev, EC_FEATURE_USBC_SS_MUX_VIRTUAL);
 
 	ret = cros_ec_cmd(typec->ec, 0, EC_CMD_USB_PD_PORTS, NULL, 0,
 			  &resp, sizeof(resp));
diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h
index f9c31f04c102..9698f27169c6 100644
--- a/drivers/platform/chrome/cros_ec_typec.h
+++ b/drivers/platform/chrome/cros_ec_typec.h
@@ -41,6 +41,7 @@ struct cros_typec_data {
 	bool typec_cmd_supported;
 	bool needs_mux_ack;
 	bool ap_driven_altmode;
+	bool ap_driven_mux;
 };
 
 /* Per port data. */
@@ -65,7 +66,6 @@ struct cros_typec_port {
 	/* Variables keeping track of switch state. */
 	struct typec_mux_state state;
 	uint8_t mux_flags;
-	uint8_t role;
 
 	struct typec_altmode *port_altmode[CROS_EC_ALTMODE_MAX];
 

---
base-commit: 1cf43b664b8b2f9cd04b9906193713e4b693dac7
change-id: 20260128-smaug-type_c-d34b9510fb5e

Best regards,
-- 
Diogo Ivo <diogo.ivo@...nico.ulisboa.pt>


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ