From nobody Thu Oct 2 22:52:50 2025 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2EA5334704 for ; Tue, 9 Sep 2025 12:30:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421045; cv=none; b=fQ66ze1tB9Oao45Gql6HESu6baYxVj9nLK8FbGRG2DUeZKV2JOsxSoWcmR0TH+R3FMsJMezU9xR6RB/TZapoMwmeqhnHnuxiyHqTPyRp+VopGDzCFMFQQ4hkgDOu0GXqnEUZEnnUayU8Ez/ObmioKfCbI2hvnthSZ3HVwdp92g4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421045; c=relaxed/simple; bh=dY2lLF3NAF75RLJg43VoI8WFxYQjrRkpfq0cWUdKBC4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rI9tyreoDtK5DJoRR5q/2A70BsZVa76wPt0ogxohxCHc+khBEm9FRQdLGOOCaMnxOJWnE1xEIpQ/d85UDBWP22njjxpo4VfqlrD8Wx24fLi/ARcoji2LfvsjGNFtdoFhSuk5kKPOmuKptTdXRBqddrLk1IDxDJb7+ICf413exMI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=Yweizecu; arc=none smtp.client-ip=209.85.218.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Yweizecu" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-b0415e03e25so750344466b.0 for ; Tue, 09 Sep 2025 05:30:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1757421041; x=1758025841; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aSLssCaJDALppdU5kT6wkNqD+9ziSVAOFWyEMcwXE4o=; b=YweizecukjmL9HIP11NEeTgbsXdy17p8WIkSqJo909I5iIxXQ1FjKC7XqEgPB2PNTL UrevGGBrTWw3kMx4yUl5w0MawMK1O+2lJqAKDI+zEC31Ok50fNchMlEQ8Adw4MhsmC7m LkopqlPyNgly5c5naCzI37DjvtMsZFSey+4Ac= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757421041; x=1758025841; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aSLssCaJDALppdU5kT6wkNqD+9ziSVAOFWyEMcwXE4o=; b=k9hyDF9PqmTKk19DxhQ6kem07DYaHYIDi764sVasWtUC6RkckR3M4JvxwT4JfuKJ9S N8iQXr6yu1mMmLLHkdzrckJzEdI2wetbIr1i0qNuvr1khbLU9Y8m9T1j67mYXmmXJKuC QtlG6KbrcczX7qqWviDrJIqDoIe5WNRTv/kCZefMaVV65+mjFpn34ew/r6F/vXWhp/xA NRGneiiN/A4wpjWPQ13UfAX8c07fcHhw6LyxD8hr7yghvIgrUMwtaUoOCs8wZvKhxhIF PlkGP5y/aCX+UeAid1nGc2P6vtAiQ1Is/LjxQgCLUTY9RxGl7py4UyD5OgorGq3cPa4N Qvqg== X-Forwarded-Encrypted: i=1; AJvYcCU829LTXRrSxV0yXL7kq9xr2d7veY7jZNvba8KIxLzxODQ2CFW9X1xSP0T7nt4MLVTHkjlqK1u5eZrdi8s=@vger.kernel.org X-Gm-Message-State: AOJu0YyyybkcfspGeEemdatGLUcOuTEM4K4Q9EHDKQ981qJm8QztJPOY i9iWKOA7nN9Gj3hLagR/vELlQ4JCRzlhxhFL+uUpGuuDpkhOX99VwL6Lr3JnfQYfcw== X-Gm-Gg: ASbGncvwz9Ie+K1ZHWvwWfoJ7U67x0cG35z2A54AjJkpTeDHdA5tveGOVMhk87e75D8 sYCig2Ww/wGkpyyBoJ6PH1HR/Rpnli8G9XOIwdJlGQbeha/R/RGm6uB53wUNnH5n0mX0YbcL/jn yd0RW3s6UmcjDu0aeSweUpGVJWxYIh2VWp2wU88kE2bvTe/qAt47ceuTAoIKBwZNWB5VC0eiv/D nyEa3OfrPb8iUpochtvXYl0Iet/unLby04w3YvGXVoKgViIlE0CbbaHAoPMtAmkwyYVzWPCDVaj 6OUld4FqskikN3gdsh1uUoa/pGAq/rfiUbzoeeC7PTdYoUcaIV5xQA2TC0wwHDAkSHkk8BJaXXo A7oXloQDTsP7hjvhtYv2/XLttYH0JKSMN8Hg+A3uzOvAuRrxRyVNwQTqttN8DlLFc1E6p4EV8Ys OCYaAvFsytEGjxaSGtR6Bp69ZrdokwWfHOEi6K X-Google-Smtp-Source: AGHT+IE16iHG878b0C3cu/M9l0FZasSEco+irvhp8UD7ksl2/950K4BbreEaXdQP9P+esGS33OjJhQ== X-Received: by 2002:a17:907:3ea2:b0:b01:8fa4:6bb0 with SMTP id a640c23a62f3a-b04b1687e20mr1097269766b.44.1757421040942; Tue, 09 Sep 2025 05:30:40 -0700 (PDT) Received: from akuchynski.c.googlers.com.com (240.225.32.34.bc.googleusercontent.com. [34.32.225.240]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b01902d0e99sm2409702166b.12.2025.09.09.05.30.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Sep 2025 05:30:40 -0700 (PDT) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , Tzung-Bi Shih , linux-usb@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Guenter Roeck , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, Andrei Kuchynski Subject: [PATCH RFC 1/5] usb: typec: Implement mode selection Date: Tue, 9 Sep 2025 12:30:24 +0000 Message-ID: <20250909123028.2127449-2-akuchynski@chromium.org> X-Mailer: git-send-email 2.51.0.384.g4c02a37b29-goog In-Reply-To: <20250909123028.2127449-1-akuchynski@chromium.org> References: <20250909123028.2127449-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch adds APIs for managing the alternate mode selection process, enabling the initiation and termination of mode entry based on each mode's priority. Signed-off-by: Andrei Kuchynski --- drivers/usb/typec/class.h | 4 + drivers/usb/typec/mode_selection.c | 345 +++++++++++++++++++++++++++++ drivers/usb/typec/mode_selection.h | 25 +++ include/linux/usb/typec_altmode.h | 11 + 4 files changed, 385 insertions(+) diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h index c53a04b9dc75..f3e731616f41 100644 --- a/drivers/usb/typec/class.h +++ b/drivers/usb/typec/class.h @@ -40,6 +40,10 @@ struct typec_partner { =20 struct usb_power_delivery *pd; =20 + struct list_head mode_list; + struct mutex mode_list_lock; + struct delayed_work mode_selection_work; + void (*attach)(struct typec_partner *partner, struct device *dev); void (*deattach)(struct typec_partner *partner, struct device *dev); }; diff --git a/drivers/usb/typec/mode_selection.c b/drivers/usb/typec/mode_se= lection.c index 2179bf25f5d4..dbeb94f7f3e6 100644 --- a/drivers/usb/typec/mode_selection.c +++ b/drivers/usb/typec/mode_selection.c @@ -3,10 +3,58 @@ * Copyright 2025 Google LLC. */ =20 +#include + #include "mode_selection.h" #include "class.h" #include "bus.h" =20 +/* Timeout for a mode entry attempt, ms */ +static const unsigned int mode_selection_timeout =3D 4000; +/* Delay between mode entry/exit attempts, ms */ +static const unsigned int mode_selection_delay =3D 1000; +/* Maximum retries for mode entry on busy status */ +static const unsigned int mode_entry_attempts =3D 4; + +/** + * enum ms_state - Specific mode selection states + * @MS_STATE_IDLE: The mode entry process has not started + * @MS_STATE_INPROGRESS: The mode entry process is currently underway + * @MS_STATE_ACTIVE: The mode has been successfully entered + * @MS_STATE_TIMEOUT: Mode entry failed due to a timeout + * @MS_STATE_FAILED: The mode driver reported the error + */ +enum ms_state { + MS_STATE_IDLE =3D 0, + MS_STATE_INPROGRESS, + MS_STATE_ACTIVE, + MS_STATE_TIMEOUT, + MS_STATE_FAILED, +}; + +/** + * struct mode_selection_state - State tracking for a specific Type-C mode + * @svid: The Standard or Vendor ID (SVID) for this alternate mode + * @name: Name of the alternate mode + * @priority: The mode priority. Lower values indicate a more preferred mo= de + * @enter: Flag indicating if the driver is currently attempting to enter = or + * exit the mode + * @attempt_count: Number of times the driver has attempted to enter the m= ode + * @state: The current mode selection state + * @error: The outcome of the last attempt to enter the mode + * @list: List head to link this mode state into a prioritized list + */ +struct mode_selection_state { + u16 svid; + const char *name; + unsigned int priority; + bool enter; + int attempt_count; + enum ms_state state; + int error; + struct list_head list; +}; + static int increment_duplicated_priority(struct device *dev, void *data) { struct typec_altmode **alt_target =3D (struct typec_altmode **)data; @@ -36,3 +84,300 @@ void typec_mode_set_priority(struct typec_altmode *alt, res =3D device_for_each_child(&port->dev, &alt, increment_duplicated_priority); } + +static void mode_list_clean(struct typec_partner *partner) +{ + struct mode_selection_state *ms, *tmp; + + list_for_each_entry_safe(ms, tmp, &partner->mode_list, list) { + list_del(&ms->list); + kfree(ms); + } +} + +/** + * mode_selection_next() - Process mode selection results and schedule next + * action + * @partner: pointer to the partner structure + * @ms: pointer to active mode_selection_state object that is on top in + * mode_list. + * + * The mutex protecting mode_list must be held by the caller when invoking= this + * function. + * + * This function evaluates the outcome of the previous mode entry or exit + * attempt. Based on this result, it determines the next mode to process a= nd + * schedules `mode_selection_work_fn()` if further actions are required. + * + * If the previous mode entry was successful, the mode selection sequence = is + * considered complete for the current cycle. + * + * If the previous mode entry failed, this function schedules + * `mode_selection_work_fn()` to attempt exiting the mode that was partial= ly + * activated but not fully entered. + * + * If the previous operation was an exit (after a failed entry attempt), + * the internal list of candidate modes is advanced to determine the next = mode + * to enter. + */ +static void mode_selection_next( + struct typec_partner *partner, struct mode_selection_state *ms) + + __must_hold(&partner->mode_list_lock) +{ + if (!ms->enter) { + list_del(&ms->list); + kfree(ms); + } else if (ms->state =3D=3D MS_STATE_INPROGRESS && !ms->error) { + list_del(&ms->list); + mode_list_clean(partner); + + ms->state =3D MS_STATE_ACTIVE; + list_add_tail(&ms->list, &partner->mode_list); + } else { + if (ms->error) { + ms->state =3D MS_STATE_FAILED; + dev_dbg(&partner->dev, "%s: entry mode error %pe\n", + ms->name, ERR_PTR(ms->error)); + } + if (ms->error !=3D -EBUSY || ms->attempt_count >=3D mode_entry_attempts) + ms->enter =3D false; + } + + ms =3D list_first_entry_or_null( + &partner->mode_list, struct mode_selection_state, list); + if (ms && ms->state !=3D MS_STATE_ACTIVE) + schedule_delayed_work(&partner->mode_selection_work, + msecs_to_jiffies(mode_selection_delay)); +} + +void typec_altmode_entry_complete(struct typec_altmode *altmode, + const int error) +{ + struct typec_partner *partner =3D to_typec_partner(altmode->dev.parent); + struct mode_selection_state *ms; + + mutex_lock(&partner->mode_list_lock); + + ms =3D list_first_entry_or_null( + &partner->mode_list, struct mode_selection_state, list); + if (ms) { + if (ms->svid =3D=3D altmode->svid && ms->state =3D=3D MS_STATE_INPROGRES= S) { + ms->error =3D error; + cancel_delayed_work(&partner->mode_selection_work); + mode_selection_next(partner, ms); + } + } + + mutex_unlock(&partner->mode_list_lock); +} +EXPORT_SYMBOL_GPL(typec_altmode_entry_complete); + +static int mode_selection_activate_altmode(struct device *dev, void *data) +{ + struct mode_selection_state *ms =3D (struct mode_selection_state *)data; + int error =3D -ENODEV; + int ret =3D 0; + + if (is_typec_altmode(dev)) { + struct typec_altmode *altmode =3D to_typec_altmode(dev); + + if (ms->svid =3D=3D altmode->svid) { + if (altmode->ops && altmode->ops->activate) + error =3D altmode->ops->activate(altmode, ms->enter); + else + error =3D -EOPNOTSUPP; + ret =3D 1; + } + } + + if (ms->enter) { + ms->attempt_count++; + ms->error =3D error; + } + + return ret; +} + +/** + * mode_selection_work_fn() - Activate entry into the upcoming mode + * @work: work structure + * + * This function works in conjunction with `mode_selection_next()`. + * It attempts to activate the next mode in the selection sequence. + * + * If the mode activation (`mode_selection_activate_altmode()`) fails, + * `mode_selection_next()` will be called to initiate a new selection cycl= e. + * + * Otherwise, the state is set to MS_STATE_INPROGRESS, and + * `mode_selection_work_fn()` is scheduled for a subsequent entry after a = timeout + * period. The alternate mode driver is expected to call back with the act= ual + * mode entry result. Upon this callback, `mode_selection_next()` will det= ermine + * the subsequent mode and re-schedule `mode_selection_work_fn()`. + */ +static void mode_selection_work_fn(struct work_struct *work) +{ + struct typec_partner *partner =3D container_of(work, struct typec_partner, + mode_selection_work.work); + struct mode_selection_state *ms; + + mutex_lock(&partner->mode_list_lock); + + ms =3D list_first_entry_or_null( + &partner->mode_list, struct mode_selection_state, list); + if (ms) { + if (ms->state =3D=3D MS_STATE_INPROGRESS) { + ms->state =3D MS_STATE_TIMEOUT; + mode_selection_next(partner, ms); + } else { + device_for_each_child(&partner->dev, ms, + mode_selection_activate_altmode); + + if (ms->enter && !ms->error) { + ms->state =3D MS_STATE_INPROGRESS; + schedule_delayed_work(&partner->mode_selection_work, + msecs_to_jiffies(mode_selection_timeout)); + } else + mode_selection_next(partner, ms); + } + } + + mutex_unlock(&partner->mode_list_lock); +} + +void typec_mode_selection_add_partner(struct typec_partner *partner) +{ + INIT_LIST_HEAD(&partner->mode_list); + mutex_init(&partner->mode_list_lock); + INIT_DELAYED_WORK(&partner->mode_selection_work, mode_selection_work_fn); +} + +void typec_mode_selection_remove_partner(struct typec_partner *partner) +{ + mutex_lock(&partner->mode_list_lock); + mode_list_clean(partner); + mutex_unlock(&partner->mode_list_lock); + + cancel_delayed_work_sync(&partner->mode_selection_work); + mutex_destroy(&partner->mode_list_lock); +} + +bool typec_mode_selection_is_pending(struct typec_partner *partner) +{ + struct mode_selection_state *ms =3D list_first_entry_or_null( + &partner->mode_list, struct mode_selection_state, list); + + return ms !=3D NULL; +} + +static int compare_priorities(void *priv, + const struct list_head *a, const struct list_head *b) +{ + struct mode_selection_state *msa =3D + container_of(a, struct mode_selection_state, list); + struct mode_selection_state *msb =3D + container_of(b, struct mode_selection_state, list); + + if (msa->priority < msb->priority) + return -1; + return 1; +} + +static int mode_add_to_list(struct device *dev, void *data) +{ + struct list_head *list =3D (struct list_head *)data; + struct mode_selection_state *ms; + + if (is_typec_altmode(dev)) { + struct typec_altmode *altmode =3D to_typec_altmode(dev); + const struct typec_altmode *pdev =3D typec_altmode_get_partner(altmode); + + if (pdev) { + ms =3D kzalloc(sizeof(struct mode_selection_state), GFP_KERNEL); + if (!ms) + return -ENOMEM; + + ms->svid =3D altmode->svid; + ms->name =3D altmode->desc; + ms->priority =3D pdev->priority; + ms->enter =3D true; + INIT_LIST_HEAD(&ms->list); + list_add_tail(&ms->list, list); + } + } + + return 0; +} + +/** + * typec_mode_selection_start() - Starts the mode selection process. + * @partner: pointer to the partner structure + * + * This function populates mode_list with pointers to + * `struct mode_selection_state` instances. The sequence is generated base= d on + * partner capabilities and prioritized according to the port's settings. + */ +int typec_mode_selection_start(struct typec_partner *partner) +{ + int ret; + + mutex_lock(&partner->mode_list_lock); + + if (typec_mode_selection_is_pending(partner)) + ret =3D -EALREADY; + else { + ret =3D device_for_each_child( + &partner->dev, &partner->mode_list, mode_add_to_list); + + if (ret) + mode_list_clean(partner); + else if (!list_empty(&partner->mode_list)) { + list_sort(NULL, &partner->mode_list, compare_priorities); + schedule_delayed_work(&partner->mode_selection_work, 0); + } + } + + mutex_unlock(&partner->mode_list_lock); + return ret; +} + +/** + * typec_mode_selection_reset() - Reset the mode selection process. + * @partner: pointer to the partner structure + * + * This function cancels ongoing mode selection and exits the currently ac= tive + * mode, if present. + * It returns -EINPROGRESS when a mode entry is ongoing, indicating that t= he + * reset cannot immediately complete. + */ +int typec_mode_selection_reset(struct typec_partner *partner) +{ + struct mode_selection_state *ms; + int ret =3D 0; + + mutex_lock(&partner->mode_list_lock); + + ms =3D list_first_entry_or_null( + &partner->mode_list, struct mode_selection_state, list); + if (ms) { + if (ms->state =3D=3D MS_STATE_ACTIVE) { + ms->enter =3D false; + device_for_each_child(&partner->dev, ms, + mode_selection_activate_altmode); + } else if (ms->state !=3D MS_STATE_IDLE) { + list_del(&ms->list); + mode_list_clean(partner); + + ms->attempt_count =3D mode_entry_attempts; + list_add(&ms->list, &partner->mode_list); + + ret =3D -EINPROGRESS; + } + + if (!ret) + mode_list_clean(partner); + } + + mutex_unlock(&partner->mode_list_lock); + return ret; +} diff --git a/drivers/usb/typec/mode_selection.h b/drivers/usb/typec/mode_se= lection.h index cbf5a37e6404..9049b5a25d63 100644 --- a/drivers/usb/typec/mode_selection.h +++ b/drivers/usb/typec/mode_selection.h @@ -4,3 +4,28 @@ =20 void typec_mode_set_priority(struct typec_altmode *alt, const unsigned int priority); + +/** + * The mode selection process follows a lifecycle tied to the USB-C partner + * device. The API is designed to first build a set of desired modes and t= hen + * trigger the selection process. The expected sequence of calls is as fol= lows: + * + * Creation and Configuration: + * Call typec_mode_selection_add_partner() when the partner device is bein= g set + * up. + * + * Execution: + * Call typec_mode_selection_start() to trigger the mode selection. + * typec_mode_selection_is_pending() returns true if the process is in pro= gress + * or complete. + * Call typec_mode_selection_reset() to stop the selection process and exit + * the currently active mode. + * + * Destruction: + * Before destroying a partner, call typec_mode_selection_remove_partner() + */ +void typec_mode_selection_add_partner(struct typec_partner *partner); +void typec_mode_selection_remove_partner(struct typec_partner *partner); +int typec_mode_selection_start(struct typec_partner *partner); +bool typec_mode_selection_is_pending(struct typec_partner *partner); +int typec_mode_selection_reset(struct typec_partner *partner); diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_al= tmode.h index 571c6e00b54f..fd9ee3ef8de3 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -219,4 +219,15 @@ void typec_altmode_unregister_driver(struct typec_altm= ode_driver *drv); module_driver(__typec_altmode_driver, typec_altmode_register_driver, \ typec_altmode_unregister_driver) =20 +/** + * typec_altmode_entry_complete - Complete an alternate mode entry request + * @altmode: Handle to the alternate mode. + * @result: Result of the entry operation. + * + * This function should be called by a driver to report the final result of + * an asynchronous alternate mode entry request. + */ +void typec_altmode_entry_complete(struct typec_altmode *altmode, + const int result); + #endif /* __USB_TYPEC_ALTMODE_H */ --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 22:52:50 2025 Received: from mail-ej1-f49.google.com (mail-ej1-f49.google.com [209.85.218.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8475A334738 for ; Tue, 9 Sep 2025 12:30:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421048; cv=none; b=fg5Ux8XdZm7B2DnGNJIvsdBVPfswkHUFvIphjO1+ZP2DVO6CbwXp6yrXKsC24Pyp2cX0SB5Ezg/qm11bv+/qhmjvD4lTYlUb9EbVUIvTmzP0phUlOnyhTi5S7ggZXjKnI1cqq2KmWHlRXWjD182T4cnWsFb3hcl27UZWCk4i1jY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421048; c=relaxed/simple; bh=fN049EH0gqurHLscXSdiFKelXsZTTlJy1FAhnjS+5tA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rDB9hqPignl5sqfF6T538Jd7uRD2NhOw/OOoMOcQfywbL3ac0iHMwy45S6IRAZpTXpUkyqxtBt9xUrzzSzvN50oE8v1mDS6utE/Mb48v7RIG49d9PPUyrcRsImRQEb2iS+h3DtK2hY05e3KM4ipcsE5vbu1mO7CYwelMToGXc4s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=m5Gq56iP; arc=none smtp.client-ip=209.85.218.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="m5Gq56iP" Received: by mail-ej1-f49.google.com with SMTP id a640c23a62f3a-b042cc39551so997395966b.0 for ; Tue, 09 Sep 2025 05:30:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1757421044; x=1758025844; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=h11TJTxgMeaGK+Qbd8Gn2b3zaXWavrJHEj+psQs667I=; b=m5Gq56iPJYfK5q9lLlzv10yE6n5JKbWQvFIfbV5kUfCLrufVIG/Qt7vktYVtoQHjSY v7f2b2qIaF4ih6E0830kvMi1UIWOlLKsKxFf/C30ANzF4xHRPvpd94RGx2uBDXJg76Dq KeeFevv7vAEv89iyOsMLHrpt4fyCG/EEvHH7s= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757421044; x=1758025844; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=h11TJTxgMeaGK+Qbd8Gn2b3zaXWavrJHEj+psQs667I=; b=kSXlvqQh/l7VQIsW+UNoKcr0ZaEQacjUF9/ltfyGAPDk2QCSV34cGmqZ3nEQkC2LzC SFgt6DpsA5faCnrqTku+FvEBKWk7/7rp4Cq1nOCeG25sLl1sz++xtk6HFic9KcN4zGIf tJzecQLqfBMCQyjDhcoNcG8++VzZMRXLD/oGqV7GIRsObBsuj2qQUqnHljh8sEWlNZd6 fWVl0ljw2VwuxE75j1vin7oL7WBqdPdrbX9oTf4XJjJ0KqdDS5wNP92snaZP9e5g7MEt P+0aO8BrReDJAs4bT6jdC3m+36dC747uz96GDZtiFT4MzijBGWsbm4MySA5wUr87YDT9 5SoQ== X-Forwarded-Encrypted: i=1; AJvYcCWYb8NpAw8sZCCwc+O8gAW8LaMSkrYZ3XVJh4bT8NFXouAoXIq9a2T74ZBP/FUIM+EcsM6L56omcAT5ojc=@vger.kernel.org X-Gm-Message-State: AOJu0Yyp0UpYZmVYYvCvSDQ5kgATj/zLsbeMBlEt0kBCF1Pjc5mgIqSk v9md0odAdPKt3DGwJIRqk+GPuBtyw1gUqI1yfr73dEl4/hYaU3/caZhl/xhJfKvxBg== X-Gm-Gg: ASbGncviHW1OydUayDBdg4/4n19RBQAYN4YuUwJ+f3iGa9FrRPERXuzzDboiT71pgJl I+9o7zWQiewDRDAJISZGJn/OoGbgyafIvB0IHeHhmCSiBAIX+F7dNLj7bxGzf813vDZvu00NeL4 drT+qmzSsxoUE8c9beNg59IL/kUkewLwr2pWLgsJdEz+TZOt3yLlKv8hQsIZLpQav8RteguzdRb fgGyTXfI0b0DOam7IJKo9xnJsrvpVdfe+/MEqRpYH+xpYg4UHdSL24ffgHWVDl0EsbYPLl/AtGE 5FFhgLuiXc7XsSMn2x8J/nZiYmqaiVyeKjjLNck2KX5Vs29wV7dFFArmawFKaOCn/jrEFIVIE52 rUArCmNSnirHcXWML5K6/kGBELiivoVGSuiqfH8zvbpJGjlYNSCYtex/eB2ffiJZnoR6TzG8Jep 7my6SadzgZ2Pke+vSsMQO0nVev/w== X-Google-Smtp-Source: AGHT+IHTbMUAWbZCStfN2KSvqbzF0cZzpg6HYKgjKjtANpkaaL7p64kwSsxCsJX84Bao/nA+lAnb5w== X-Received: by 2002:a17:907:c1d:b0:b04:6e26:7351 with SMTP id a640c23a62f3a-b04b172e8d6mr1302976866b.54.1757421043811; Tue, 09 Sep 2025 05:30:43 -0700 (PDT) Received: from akuchynski.c.googlers.com.com (240.225.32.34.bc.googleusercontent.com. [34.32.225.240]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b01902d0e99sm2409702166b.12.2025.09.09.05.30.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Sep 2025 05:30:43 -0700 (PDT) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , Tzung-Bi Shih , linux-usb@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Guenter Roeck , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, Andrei Kuchynski Subject: [PATCH RFC 2/5] usb: typec: Expose mode_selection attribute via sysfs Date: Tue, 9 Sep 2025 12:30:25 +0000 Message-ID: <20250909123028.2127449-3-akuchynski@chromium.org> X-Mailer: git-send-email 2.51.0.384.g4c02a37b29-goog In-Reply-To: <20250909123028.2127449-1-akuchynski@chromium.org> References: <20250909123028.2127449-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch introduces new sysfs attribute to enable user control over Type-C mode selection. Writing a boolean '1' to this attribute starts the mode selection process, while writing '0' stops it. Signed-off-by: Andrei Kuchynski --- Documentation/ABI/testing/sysfs-class-typec | 11 ++++++ drivers/usb/typec/class.c | 37 +++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/AB= I/testing/sysfs-class-typec index dab3e4e727b6..7addf0e69c5c 100644 --- a/Documentation/ABI/testing/sysfs-class-typec +++ b/Documentation/ABI/testing/sysfs-class-typec @@ -258,6 +258,17 @@ Description: The USB Modes that the partner device sup= ports. The active mode - usb3 (USB 3.2) - usb4 (USB4) =20 +What: /sys/class/typec/-partner/mode_selection +Date: August 2025 +Contact: Andrei Kuchynski +Description: Mode selection is activated by writing boolean 1 to the + file. Conversely, writing boolean 0 will cancel any ongoing selection + process and exit the currently active mode, if any. The attribute + returns "on" when mode selection is either in progress or complete, + and "off" otherwise. + This attribute is only present if the kernel supports AP driven mode + entry, where the Application Processor manages USB Type-C alt-modes. + USB Type-C cable devices (eg. /sys/class/typec/port0-cable/) =20 Note: Electronically Marked Cables will have a device also for one cable p= lug diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index aaab2e1e98b4..b66fe62f282d 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -763,6 +763,35 @@ static ssize_t number_of_alternate_modes_show(struct d= evice *dev, struct device_ } static DEVICE_ATTR_RO(number_of_alternate_modes); =20 +static ssize_t mode_selection_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const bool ret =3D typec_mode_selection_is_pending(to_typec_partner(dev)); + + return sprintf(buf, "%s\n", str_on_off(ret)); +} + +static ssize_t mode_selection_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct typec_partner *partner =3D to_typec_partner(dev); + bool start; + int ret =3D kstrtobool(buf, &start); + + if (!ret) { + if (start) + ret =3D typec_mode_selection_start(partner); + else + ret =3D typec_mode_selection_reset(partner); + } + + if (ret) + return ret; + + return size; +} +static DEVICE_ATTR_RW(mode_selection); + static struct attribute *typec_partner_attrs[] =3D { &dev_attr_accessory_mode.attr, &dev_attr_supports_usb_power_delivery.attr, @@ -770,6 +799,7 @@ static struct attribute *typec_partner_attrs[] =3D { &dev_attr_type.attr, &dev_attr_usb_mode.attr, &dev_attr_usb_power_delivery_revision.attr, + &dev_attr_mode_selection.attr, NULL }; =20 @@ -794,6 +824,10 @@ static umode_t typec_partner_attr_is_visible(struct ko= bject *kobj, struct attrib if (!get_pd_product_type(kobj_to_dev(kobj))) return 0; =20 + if (attr =3D=3D &dev_attr_mode_selection.attr) + if (!port->mode_control) + return 0; + return attr->mode; } =20 @@ -1097,6 +1131,8 @@ struct typec_partner *typec_register_partner(struct t= ypec_port *port, typec_partner_link_device(partner, port->usb3_dev); mutex_unlock(&port->partner_link_lock); =20 + typec_mode_selection_add_partner(partner); + return partner; } EXPORT_SYMBOL_GPL(typec_register_partner); @@ -1114,6 +1150,7 @@ void typec_unregister_partner(struct typec_partner *p= artner) if (IS_ERR_OR_NULL(partner)) return; =20 + typec_mode_selection_remove_partner(partner); port =3D to_typec_port(partner->dev.parent); =20 mutex_lock(&port->partner_link_lock); --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 22:52:50 2025 Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48D4D338F58 for ; Tue, 9 Sep 2025 12:30:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421050; cv=none; b=fYQycFPBNB9B9ci31dJq5qB4iyfX7gFbSBIyLzXzO2O8Xk0GRcMb/tTA92SoSNRTSy67m4G7vRNnEeQxYbtc5H6dKK+Cjwh6S/o1DBTzjkDI+nvJ/ghaq1YSaq1fySuODf17Zb1U0sy4O8RpCoE1BR26aDDliDegaozYnKgTwuE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421050; c=relaxed/simple; bh=nvs2gDcjL6C8NXVm+Q+MwxkLZX3yRe9EVozIv1TgODA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sMTcQPSvnjqjjXzUMcrwkDsZutqeuQmlHFGrPOH/aPbO9akDiCqqjBomMxz2hL/2THm1JYarl35nyOLYHzEWn3P1qoSqcyOCWJwDBsu/wdCDq8N2IGs0bW2x2lFvsi4YtXPWhrPDX+9mY6a/YWkigPrAsi9zzdAcMhEstydYaGE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=O4ZSzGJG; arc=none smtp.client-ip=209.85.218.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="O4ZSzGJG" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-b00a9989633so168600266b.0 for ; Tue, 09 Sep 2025 05:30:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1757421047; x=1758025847; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4WMeag17a1l945PqdAkCvwljw0rC07igvRdu/jbhGyo=; b=O4ZSzGJGE+qIUVIKHbi9EKJMkHR4OcfJyj1dStQ6Cish+IHffHfxdLh7GSfs2QJf3Y f51jcXko35kbky9zXTCXkly7VGpWNTK4DPsuVUWZQ+klOesbEEOr3jmyyRtaF7KA9HYW RJIVrwkvlRWzqABNiw90W6e+Onhuc2kYNlEDc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757421047; x=1758025847; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4WMeag17a1l945PqdAkCvwljw0rC07igvRdu/jbhGyo=; b=ZcefTx8ZNR8QlANXxoRCVdLzW0I40QNP9AyH63cUkwquOzN+olpAi1OPbsuarmZGAS sFmb7ZuzcU5rlP5GvpFf36Ue9ZU0MWqc/qYPn48X7Tx0tnpSNrURkuR+gXtiPwqdBTtW KClmj902v6qmoK+YJTSllYs96Qnxa2dVc5lZIVbPl3PSJgMELPor9SotpiPNPztUupwz Jq6gDxPH/gtYTKJFWMQAlRmwUSd8BkE7a64e59dAgw7KHEKz1Ba87+OlRhk9F5NtnEnq G7iPHAsAQ93WRJDScDI/82k1Ffhmio8S/+EXO15w092LcZGGT0uTUkg0v99Jq4VggWjx 8k8Q== X-Forwarded-Encrypted: i=1; AJvYcCWl9rZRAyf34Su6LyjAwaTNANn6qCsx//LilLGOEJ8W0NQovhdcg4WAuUFrIYXwDnUj0uiN1qSwpTcgt4k=@vger.kernel.org X-Gm-Message-State: AOJu0YweZsYfqTtIHrnxMRQR60D2Bau/r9S5PpPbKwrEIT95aXlPQOq/ ThdVcO3G0qWByINOPim/JmghMWY+YnhAhFZjx8etjQ5qvXEO1L1vHYHrcWeZhb2cBw== X-Gm-Gg: ASbGnctUirFkXbDWUMwD9W0Kl7j1B74Sw/rDBdLVruvcr8cU3M/yitlkiDZ6f5zyT3C KkvzvJstG9SiiHZKc4RaJQatZ9SpWdlu7qT6twyrbhHn/2ZxPQXD+WmSB8g5KGxGRIL+fiy/YKA dkoaVtuks3RPau3hKL8G1PirXXV7XtFvMCBw58g+XNAPv6CoNUZROrn2o9eu1GP8TgXwQw61/X6 VEkKfzbz3m033m3Wbsi5XJ5wHe+y3gc7hdXUTekwq6Q4Wq/vtUdCmIUQNdix0SiVomMVQL6pm/6 Ergne4w8CJ07Cj9ftK6uQmIaaFNHdkx//QCWkVOl66Cg2J4isJtkT62uD5ngPdAGHpnmJPqmvlf YgGzhmNvv2HeQw4g7S+pOsDHrgrC7U5XdDP4zT1dIO/LqJSZUQbJ26InKAq3tcpEgVMih0oB3C8 LptIOSMnZPSdv33itUHC2pzFHqrw== X-Google-Smtp-Source: AGHT+IFhBrHiIKFQDuEGLUi8nmmT8pVqq//MniH5jqrxhg+sNjRz6k9qHyzIb5oAJzhfDrVeqxv60A== X-Received: by 2002:a17:907:c2a:b0:b04:2c2e:50a5 with SMTP id a640c23a62f3a-b04b1f0d207mr1522958966b.16.1757421046612; Tue, 09 Sep 2025 05:30:46 -0700 (PDT) Received: from akuchynski.c.googlers.com.com (240.225.32.34.bc.googleusercontent.com. [34.32.225.240]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b01902d0e99sm2409702166b.12.2025.09.09.05.30.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Sep 2025 05:30:46 -0700 (PDT) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , Tzung-Bi Shih , linux-usb@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Guenter Roeck , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, Andrei Kuchynski Subject: [PATCH RFC 3/5] usb: typec: Report altmode entry status via callback Date: Tue, 9 Sep 2025 12:30:26 +0000 Message-ID: <20250909123028.2127449-4-akuchynski@chromium.org> X-Mailer: git-send-email 2.51.0.384.g4c02a37b29-goog In-Reply-To: <20250909123028.2127449-1-akuchynski@chromium.org> References: <20250909123028.2127449-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The Type-C mode selection logic requires feedback on the result of an alternate mode entry attempt. Call the `typec_mode_selection_altmode_complete()` callback to provide this final success or failure status. Signed-off-by: Andrei Kuchynski --- drivers/usb/typec/altmodes/displayport.c | 19 +++++++++++++++++-- drivers/usb/typec/altmodes/thunderbolt.c | 10 ++++++++++ include/linux/usb/typec_dp.h | 2 ++ include/linux/usb/typec_tbt.h | 3 +++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/a= ltmodes/displayport.c index 1dcb77faf85d..052d18b54f0a 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -293,16 +293,20 @@ static void dp_altmode_work(struct work_struct *work) header =3D DP_HEADER(dp, svdm_version, DP_CMD_STATUS_UPDATE); vdo =3D 1; ret =3D typec_altmode_vdm(dp->alt, header, &vdo, 2); - if (ret) + if (ret) { dev_err(&dp->alt->dev, "unable to send Status Update command (%d)\n", ret); + typec_altmode_entry_complete(dp->alt, ret); + } break; case DP_STATE_CONFIGURE: ret =3D dp_altmode_configure_vdm(dp, dp->data.conf); - if (ret) + if (ret) { dev_err(&dp->alt->dev, "unable to send Configure command (%d)\n", ret); + typec_altmode_entry_complete(dp->alt, ret); + } break; case DP_STATE_CONFIGURE_PRIME: ret =3D dp_altmode_configure_vdm_cable(dp, dp->data_prime.conf); @@ -371,6 +375,7 @@ static int dp_altmode_vdm(struct typec_altmode *alt, int cmd_type =3D PD_VDO_CMDT(hdr); int cmd =3D PD_VDO_CMD(hdr); int ret =3D 0; + int entry_result =3D 0; =20 mutex_lock(&dp->lock); =20 @@ -414,10 +419,14 @@ static int dp_altmode_vdm(struct typec_altmode *alt, switch (cmd) { case DP_CMD_STATUS_UPDATE: dp->state =3D DP_STATE_EXIT; + if (vdo) + entry_result =3D *(int *)vdo; break; case DP_CMD_CONFIGURE: dp->data.conf =3D 0; ret =3D dp_altmode_configured(dp); + if (vdo) + entry_result =3D *(int *)vdo; break; default: break; @@ -432,6 +441,12 @@ static int dp_altmode_vdm(struct typec_altmode *alt, =20 err_unlock: mutex_unlock(&dp->lock); + + if (!entry_result) + entry_result =3D ret; + if (entry_result || cmd =3D=3D DP_CMD_CONFIGURE) + typec_altmode_entry_complete(dp->alt, entry_result); + return ret; } =20 diff --git a/drivers/usb/typec/altmodes/thunderbolt.c b/drivers/usb/typec/a= ltmodes/thunderbolt.c index 6eadf7835f8f..765ba7348ac4 100644 --- a/drivers/usb/typec/altmodes/thunderbolt.c +++ b/drivers/usb/typec/altmodes/thunderbolt.c @@ -214,6 +214,7 @@ static int tbt_altmode_vdm(struct typec_altmode *alt, struct typec_thunderbolt_data data; int cmd_type =3D PD_VDO_CMDT(hdr); int cmd =3D PD_VDO_CMD(hdr); + int entry_result =3D 0; =20 mutex_lock(&tbt->lock); =20 @@ -248,6 +249,12 @@ static int tbt_altmode_vdm(struct typec_altmode *alt, switch (cmd) { case CMD_ENTER_MODE: dev_warn(&alt->dev, "Enter Mode refused\n"); + if (vdo) + entry_result =3D *(int *)vdo; + break; + case TBT_CMD_STATUS_UPDATE: + if (vdo) + entry_result =3D *(int *)vdo; break; default: break; @@ -262,6 +269,9 @@ static int tbt_altmode_vdm(struct typec_altmode *alt, =20 mutex_unlock(&tbt->lock); =20 + if (entry_result || cmd =3D=3D TBT_CMD_STATUS_UPDATE) + typec_altmode_entry_complete(alt, entry_result); + return 0; } =20 diff --git a/include/linux/usb/typec_dp.h b/include/linux/usb/typec_dp.h index acb0ad03bdac..c9fa68cd1265 100644 --- a/include/linux/usb/typec_dp.h +++ b/include/linux/usb/typec_dp.h @@ -44,10 +44,12 @@ enum { * commands: Status Update and Configure. * * @status will show for example the status of the HPD signal. + * @error will contain the error code, if applicable. */ struct typec_displayport_data { u32 status; u32 conf; + int error; }; =20 enum { diff --git a/include/linux/usb/typec_tbt.h b/include/linux/usb/typec_tbt.h index 55dcea12082c..57cbda5292bb 100644 --- a/include/linux/usb/typec_tbt.h +++ b/include/linux/usb/typec_tbt.h @@ -24,6 +24,9 @@ struct typec_thunderbolt_data { u32 enter_vdo; }; =20 +/* TBT3 alt mode specific commands */ +#define TBT_CMD_STATUS_UPDATE VDO_CMD_VENDOR(0) + /* TBT3 Device Discover Mode VDO bits */ #define TBT_MODE BIT(0) #define TBT_ADAPTER(_vdo_) FIELD_GET(BIT(16), _vdo_) --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 22:52:50 2025 Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9974321F39 for ; Tue, 9 Sep 2025 12:30:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421054; cv=none; b=Yb2uy2SsOqQuMkxwOPUUPqUqXVohqxIh8NhLQNr+fOGIOKs6VESq+sRpz73QGFv/+jyoOpyquDcGrxBypdCMknbuBdJ4FCzMPs/uVOx46I75oC7ibfcsqFPBX3d6XXv/LsRLTmj/QWa9Zfe0xrXVfJXITbaYdykrvTpC11t0Yjo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421054; c=relaxed/simple; bh=wo2Nci5KTZIZbP8CX9Xb4me0P/T5bVmP7HGaZVx1QBQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QUcThuCD0P9gu4dqxKJKNmCCmaMHtYruSAU8Z6KADDO5im5T3T9l5Rrd64zVbwClo/URphpNmqYVhvS4IAmRfo3Ymt+LJoEDX3+R4YZGGmmPe/42BbjcyVNhX22AcUwQEr1xL8wRt2gNZQEpQNQAOoa86eq66MLw/LVxWvOEXK4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=cjHZZsc0; arc=none smtp.client-ip=209.85.218.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="cjHZZsc0" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-b0449b1b56eso812006066b.1 for ; Tue, 09 Sep 2025 05:30:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1757421051; x=1758025851; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yeRnafoqGXMQLsLwS7RKCqhJvzceHCqSnadqMFnp/Eo=; b=cjHZZsc0aiXrbjIPGEpyS1c6lM7q+OZbd1XR0FWseu0TzNa11rQLPKVwfoVMXfvbiO Fe4CkuxYLV/vlJHERotzpYub+dNEnn+qwXXhZAkoOgij84piiGky2w9p53487RyRKZSX 47EzIugYwM39NUOsjKKlW1TavwTzMTkeT9TEY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757421051; x=1758025851; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yeRnafoqGXMQLsLwS7RKCqhJvzceHCqSnadqMFnp/Eo=; b=HWwp3ER1fpZIvr6mfP54OTcMUAlj3DXAZC/xD5XD7n8ii2yQUDtSciTSN3emf8W+rH eXKSRA6JXtOPxp1OOuoTS3zGVz3vfKvI79m1qA21YFIN2aFK9Wo7wkM2dEFmFuECGmmD Qk30/N7Y0a1oDKTHcpWYOcAXVd70DX5EOGPz5QaIxlZWP4jwy5Q4aeKVL+7iW858W41/ moQcI6eBgUpKmktbdLz0wH7+EdV6f63tSpNNyXpFEhWltfg6cBL2t12aHhvSgLvKp3vc PBeDKOkNy/C6+bVUGcbF2HXCPBRqodhSiiZ00Dyvs8zGaI5W/IYNE0ZXcewD4lv0AAju bd/w== X-Forwarded-Encrypted: i=1; AJvYcCWq6VufzBKtSkpUrQtZFkec3BAcxbDMmlp4AvfQqluqPd3ssqni6WbeyVwJcu05PoxpvNcORpD7zEEgLfk=@vger.kernel.org X-Gm-Message-State: AOJu0YwcmsLS5Aw8+0Sahte1042U0GsixgUfdohOH96SA6ZwCPc2+W35 1q18YA3Sf6WNkrzLIcfRW+Y8reaePWyU4D0B5z7UM2YMpakUpuuzwrqv2JraN1Iywg== X-Gm-Gg: ASbGncsFPb5xWBmyFToHgVkPbKhvxv1LfMHTyQzmGPONp0QJebaukzi0OJ6i980BGU1 4JsKNB4jnsKTfNuKjW4ts/Nk3wQzW2DcLXOEO95lgerGLW/FUvy1fso8lZ95Yad2Q8QShSlB2bR JvaZgtKkVy55XZR0tWD4ShzvzZk6Y9HcBswLE9l9H8pKPQqdmOxCSc/Ovx4s6O47E6XFnNi5+bk cQQPCTNcw+4Uz2UBYKubwUTj9fGn8+7AlsS2M58JddC/6XWfZsT6/KbhGFfa9g+G6K+H82iBee1 /oaZ1ISXRgxdwp8Ib5B2XmwU1VX7w0EcBm6bI4AY/60tS2ZpbkTbg7X7DmANYspOlhybTvJMh05 sYPqxEjvUKP0Yhq7PaaxtfIDGG39bstkR76Kj+11siDd+Q2Vuft8/RQXaUbJ37sqD7gmq8sakBv 4JR4SAM/YFE/uZ+8+kXHH14a+FQg== X-Google-Smtp-Source: AGHT+IHum5WD472d7fS2rBLDEJ4/Qj+9NWbX7rnTe/jOnY7UY4cYm3PCK7sxMJpUkyS12VpRXD21hw== X-Received: by 2002:a17:907:9410:b0:b04:f5a:8c13 with SMTP id a640c23a62f3a-b04b14b37c6mr1069077666b.15.1757421051199; Tue, 09 Sep 2025 05:30:51 -0700 (PDT) Received: from akuchynski.c.googlers.com.com (240.225.32.34.bc.googleusercontent.com. [34.32.225.240]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b01902d0e99sm2409702166b.12.2025.09.09.05.30.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Sep 2025 05:30:50 -0700 (PDT) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , Tzung-Bi Shih , linux-usb@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Guenter Roeck , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, Andrei Kuchynski Subject: [PATCH RFC 4/5] usb: typec: ucsi: displayport: Propagate DP altmode entry result Date: Tue, 9 Sep 2025 12:30:27 +0000 Message-ID: <20250909123028.2127449-5-akuchynski@chromium.org> X-Mailer: git-send-email 2.51.0.384.g4c02a37b29-goog In-Reply-To: <20250909123028.2127449-1-akuchynski@chromium.org> References: <20250909123028.2127449-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Reporting the error code via VDM back to the Type-C mode selection logic allows the detailed result to be propagated to user space. Signed-off-by: Andrei Kuchynski --- drivers/usb/typec/ucsi/displayport.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/= displayport.c index 8aae80b457d7..47c28646cfa9 100644 --- a/drivers/usb/typec/ucsi/displayport.c +++ b/drivers/usb/typec/ucsi/displayport.c @@ -234,14 +234,18 @@ static int ucsi_displayport_vdm(struct typec_altmode = *alt, =20 switch (cmd) { case DP_CMD_STATUS_UPDATE: - if (ucsi_displayport_status_update(dp)) + dp->data.error =3D ucsi_displayport_status_update(dp); + if (dp->data.error) { + dp->vdo_data =3D &dp->data.error; dp->header |=3D VDO_CMDT(CMDT_RSP_NAK); - else + } else dp->header |=3D VDO_CMDT(CMDT_RSP_ACK); break; case DP_CMD_CONFIGURE: dp->data.conf =3D *data; - if (ucsi_displayport_configure(dp)) { + dp->data.error =3D ucsi_displayport_configure(dp); + if (dp->data.error) { + dp->vdo_data =3D &dp->data.error; dp->header |=3D VDO_CMDT(CMDT_RSP_NAK); } else { dp->header |=3D VDO_CMDT(CMDT_RSP_ACK); --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 22:52:50 2025 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F96133CEBC for ; Tue, 9 Sep 2025 12:30:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421057; cv=none; b=YOSuglZL7e1EQ0IMbZ+bS0jM4kq3Y2+pOWnv5+3OCngZDZCHTjJo0BarhyNegtkMtjrT8bLnv/R43bt4wyDiIJiTGa237sB2zqIQ9VWCqtoRwWsWRSfuDPBvp2s1YXA4WxPhCWpLCE005QauwB2SVOpAfJxX/VY9R0xHXCEMMtM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757421057; c=relaxed/simple; bh=gg5T3nQ5VEwTdUPyYWVvxapRzmVgBSdtJ8K+4Q49glA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C/A9rJSWeFKtsKzpWrUE+xuC0Nv7r0hOZxyTu+6fWX9iy7nuvNEOPARbNP9XV3Ita1cd3wApDvwVzZE5OLXpszhLo61S1sNN60MlCJ0gifa0KAKl3EjFkoNz5yk5tanAelCKULx7TRlEgjFpd+QyyqXsS5gcnv4zwT2w9RZLSFk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=O2bJOfDx; arc=none smtp.client-ip=209.85.218.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="O2bJOfDx" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-b04b869abb9so445193566b.1 for ; Tue, 09 Sep 2025 05:30:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1757421054; x=1758025854; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=RNT/Kw+T/4QMdMG2OTf9bXi1NzKMHFpMs7iCOhh/C34=; b=O2bJOfDx7p2FU0M224/tMkwabpPtl7eI92bdAVAwgGeup2SFh5ciDsMvdN5TXhBarv QWCDtWPsB8KtauymC7CUjbPKFg9AXaGbloXaL+R+lC94DiEwDcS5XOxZ7+B96HDHi3IG pDEqZ0+GkamvSooB31wWM6V54KmySo5mTnqlg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757421054; x=1758025854; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RNT/Kw+T/4QMdMG2OTf9bXi1NzKMHFpMs7iCOhh/C34=; b=Xktl2HhZlxdm6g0yr0aNu2KgcIKhXJRFbBtmp7l2zzVdnBd+iBcWcz7r7Kgik27V/z xyaiCy2XDzNvCG2STC1dK10Q0kjFOiaSIPvAh35VDKIjm4wL9h4WwSo9qD8ZIkg1tg5i V4h3OAM1H2iILGKZj10k0o18FIw8+Rq4p08dplRbMOXsjSbNKpceayjiGVSMvXWI7McQ BZ76iyhZy9SqGUpCzaZ2NxqjhfQ7f8VfgZ4JhQMa1tPkJ49VK/R1VNrnrWMXnMJtQZZ0 h4iT0ESEQEr/ZMuAIogoj11p2lvY9JWFSHpEHogizgo/XXpCBPnHAPLH/8eAHp7klell 93Yg== X-Forwarded-Encrypted: i=1; AJvYcCW0ru6Yyx7khaFsgewSO4h4df9KRdqwSrenPBZaoTVzS0KwDVJMHr7gdAA5+ndjkl3iqPIQ2JsWihE0fD4=@vger.kernel.org X-Gm-Message-State: AOJu0Ywbfh4rO8Hozzy0aA5Qm+leXnyDKwffdeVEEkYCD+pgNQ506NI/ kE5LBc6DesYCRUzm9uHAOx1BWOstey3D+JAcFLWfm2CmSZzz3KEgL2nGnhhtfVRJ8w== X-Gm-Gg: ASbGncvyx6U6KRbJb34zVY3+W1UWBnYmHaErroT3D4jUclFx93t7XaqOg2nRLTvES9s K7YHlaVvsA5UpuWNZ7XGPITLu3dfSm2bzWh+yrUEzv70Rla27poq94s4z9t/EwPHzIw2sQd9T3+ 2OWJaIqtu2FJmr2t5vPaczsK+vhvVVKoQ/5SSEkwl38/LPwUxC7AxENoWtoaYfBF+xkrN9OWLHT 91MvMrEY5WhpcuGIBuAcH/Nca+1AMWhwI4CsiW7BGpUmMJkF91vRFsWC7ZzGfYIRgJbiGq4+F8u EUN94XBJ26cxtjhJEYNT2RMLd2wrMyzB3bVccvScKqoOAgvv3ybOWHLOMWoQGgXBYgzizsDl2+d JT5umbsGk7GCpvaJor2JS4C0z1YDFae53B4zCDDwhzLRcl6DkqonzTHOd7jZHpSNPWt6APHVTPk 3y1FGDF+/0CfKhLghMQpW0MBr/tg== X-Google-Smtp-Source: AGHT+IFl1zU3QtNbYbaVd7tuOLAD+b+6Y5jT0xWKmoM/3PaJcYRD7JjPcvpNTsrUunsVw5t/BWWYbA== X-Received: by 2002:a17:907:6d0d:b0:ae3:8c9b:bd61 with SMTP id a640c23a62f3a-b04b13fb3d7mr1122786466b.12.1757421053733; Tue, 09 Sep 2025 05:30:53 -0700 (PDT) Received: from akuchynski.c.googlers.com.com (240.225.32.34.bc.googleusercontent.com. [34.32.225.240]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b01902d0e99sm2409702166b.12.2025.09.09.05.30.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Sep 2025 05:30:53 -0700 (PDT) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , Tzung-Bi Shih , linux-usb@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Guenter Roeck , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, Andrei Kuchynski Subject: [PATCH RFC 5/5] platform/chrome: cros_ec_typec: Propagate altmode entry result Date: Tue, 9 Sep 2025 12:30:28 +0000 Message-ID: <20250909123028.2127449-6-akuchynski@chromium.org> X-Mailer: git-send-email 2.51.0.384.g4c02a37b29-goog In-Reply-To: <20250909123028.2127449-1-akuchynski@chromium.org> References: <20250909123028.2127449-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In the `cros_typec_configure_mux` function, which concludes the DP/TBT alternate mode entry, the error code should be reported back to the Type-C mode selection logic. This ensures a detailed result is conveyed to user space. To inform partner drivers about the result, the VDM mechanism is used: DP_CMD_STATUS_UPDATE for DP altmode and TBT_CMD_STATUS_UPDATE for TBT altmode. Signed-off-by: Andrei Kuchynski --- drivers/platform/chrome/cros_ec_typec.c | 9 ++++++ drivers/platform/chrome/cros_typec_altmode.c | 32 ++++++++++++++++++-- drivers/platform/chrome/cros_typec_altmode.h | 6 ++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chr= ome/cros_ec_typec.c index c0806c562bb9..18e627c9fc22 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -693,6 +693,7 @@ static int cros_typec_enable_dp(struct cros_typec_data = *typec, if (!ret) ret =3D typec_mux_set(port->mux, &port->state); =20 + dp_data.error =3D 0; if (!ret) ret =3D cros_typec_displayport_status_update(port->state.alt, port->state.data); @@ -782,8 +783,16 @@ static int cros_typec_configure_mux(struct cros_typec_= data *typec, int port_num, ret =3D cros_typec_enable_usb4(typec, port_num, pd_ctrl); } else if (port->mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { ret =3D cros_typec_enable_tbt(typec, port_num, pd_ctrl); + cros_typec_tbt_status_update( + port->port_altmode[CROS_EC_ALTMODE_TBT], ret); } else if (port->mux_flags & USB_PD_MUX_DP_ENABLED) { ret =3D cros_typec_enable_dp(typec, port_num, pd_ctrl); + if (ret) { + struct typec_displayport_data dp_data =3D {.error =3D ret}; + + cros_typec_displayport_status_update( + port->port_altmode[CROS_EC_ALTMODE_DP], &dp_data); + } } else if (port->mux_flags & USB_PD_MUX_SAFE_MODE) { ret =3D cros_typec_usb_safe_state(port); } else if (port->mux_flags & USB_PD_MUX_USB_ENABLED) { diff --git a/drivers/platform/chrome/cros_typec_altmode.c b/drivers/platfor= m/chrome/cros_typec_altmode.c index 557340b53af0..75c7e6af1320 100644 --- a/drivers/platform/chrome/cros_typec_altmode.c +++ b/drivers/platform/chrome/cros_typec_altmode.c @@ -28,6 +28,7 @@ struct cros_typec_altmode_data { =20 u16 sid; u8 mode; + int error; }; =20 struct cros_typec_dp_data { @@ -295,9 +296,16 @@ int cros_typec_displayport_status_update(struct typec_= altmode *altmode, =20 dp_data->data =3D *data; dp_data->pending_status_update =3D false; - adata->header |=3D VDO_CMDT(CMDT_RSP_ACK); - adata->vdo_data =3D &dp_data->data.status; - adata->vdo_size =3D 2; + if (data->error) { + adata->header |=3D VDO_CMDT(CMDT_RSP_NAK); + adata->error =3D dp_data->data.error; + adata->vdo_data =3D &adata->error; + adata->vdo_size =3D 2; + } else { + adata->header |=3D VDO_CMDT(CMDT_RSP_ACK); + adata->vdo_data =3D &dp_data->data.status; + adata->vdo_size =3D 2; + } schedule_work(&adata->work); =20 mutex_unlock(&adata->lock); @@ -370,4 +378,22 @@ cros_typec_register_thunderbolt(struct cros_typec_port= *port, =20 return alt; } + +int cros_typec_tbt_status_update(struct typec_altmode *alt, int error) +{ + struct cros_typec_altmode_data *adata =3D typec_altmode_get_drvdata(alt); + + mutex_lock(&adata->lock); + + adata->header =3D VDO(adata->sid, 1, SVDM_VER_2_0, TBT_CMD_STATUS_UPDATE); + adata->header |=3D VDO_CMDT(error ? CMDT_RSP_NAK : CMDT_RSP_ACK); + adata->error =3D error; + adata->vdo_data =3D &adata->error; + adata->vdo_size =3D 2; + schedule_work(&adata->work); + + mutex_unlock(&adata->lock); + + return 0; +} #endif diff --git a/drivers/platform/chrome/cros_typec_altmode.h b/drivers/platfor= m/chrome/cros_typec_altmode.h index 3f2aa95d065a..848a2b194b34 100644 --- a/drivers/platform/chrome/cros_typec_altmode.h +++ b/drivers/platform/chrome/cros_typec_altmode.h @@ -39,6 +39,7 @@ static inline int cros_typec_displayport_status_update(st= ruct typec_altmode *alt struct typec_altmode * cros_typec_register_thunderbolt(struct cros_typec_port *port, struct typec_altmode_desc *desc); +int cros_typec_tbt_status_update(struct typec_altmode *alt, int error); #else static inline struct typec_altmode * cros_typec_register_thunderbolt(struct cros_typec_port *port, @@ -46,6 +47,11 @@ cros_typec_register_thunderbolt(struct cros_typec_port *= port, { return typec_port_register_altmode(port->port, desc); } +static inline int cros_typec_tbt_status_update(struct typec_altmode *alt, + int error) +{ + return 0; +} #endif =20 #endif /* __CROS_TYPEC_ALTMODE_H__ */ --=20 2.51.0.384.g4c02a37b29-goog