]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
usb: typec: Introduce mode_selection bit
authorAndrei Kuchynski <akuchynski@chromium.org>
Mon, 19 Jan 2026 13:18:22 +0000 (13:18 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Jan 2026 16:18:01 +0000 (17:18 +0100)
The port driver sets this bit for an alternate mode description to indicate
support for the mode selection feature. Once set, individual Alt Mode
drivers will no longer attempt to activate their respective modes within
their probe functions. This prevents race conditions and non-prioritized
activation.
The bit is not set by default. If left unset, the system retains the
current behavior where Alt Mode drivers manage their own activation logic.

Signed-off-by: Andrei Kuchynski <akuchynski@chromium.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://patch.msgid.link/20260119131824.2529334-6-akuchynski@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/altmodes/displayport.c
drivers/usb/typec/altmodes/thunderbolt.c
drivers/usb/typec/class.c
include/linux/usb/typec.h
include/linux/usb/typec_altmode.h

index d96ab106a980bd44590f8dbb5d7596d0e4e2c235..d185688a16b13f3392a6837b026af282beb36629 100644 (file)
@@ -804,8 +804,10 @@ int dp_altmode_probe(struct typec_altmode *alt)
        if (plug)
                typec_altmode_set_drvdata(plug, dp);
 
-       dp->state = plug ? DP_STATE_ENTER_PRIME : DP_STATE_ENTER;
-       schedule_work(&dp->work);
+       if (!alt->mode_selection) {
+               dp->state = plug ? DP_STATE_ENTER_PRIME : DP_STATE_ENTER;
+               schedule_work(&dp->work);
+       }
 
        return 0;
 }
index 6eadf7835f8f6c8bc34c16a3c66dc3f6a42aac5b..c4c5da6154da95e9ee7b874a25aebead7b7c830a 100644 (file)
@@ -307,7 +307,7 @@ static int tbt_altmode_probe(struct typec_altmode *alt)
        typec_altmode_set_drvdata(alt, tbt);
        typec_altmode_set_ops(alt, &tbt_altmode_ops);
 
-       if (tbt_ready(alt)) {
+       if (!alt->mode_selection && tbt_ready(alt)) {
                if (tbt->plug[TYPEC_PLUG_SOP_P])
                        tbt->state = TBT_STATE_SOP_P_ENTER;
                else if (tbt->plug[TYPEC_PLUG_SOP_PP])
index a48c4471251840bd5ac291df3d452968e97f7911..dbba53f0249772ba1f1e58b86ffce46af0fab343 100644 (file)
@@ -655,6 +655,7 @@ typec_register_altmode(struct device *parent,
        alt->adev.svid = desc->svid;
        alt->adev.mode = desc->mode;
        alt->adev.vdo = desc->vdo;
+       alt->adev.mode_selection = desc->mode_selection;
        alt->roles = desc->roles;
        alt->id = id;
 
index dbb259d88526646678da4aa254b5ae039b319533..d61ec38216fa9c777f03f8c8ab5d2e92097b3ad7 100644 (file)
@@ -155,6 +155,7 @@ struct typec_altmode_desc {
        /* Only used with ports */
        enum typec_port_data    roles;
        bool                    inactive;
+       bool                    mode_selection;
 };
 
 void typec_partner_set_pd_revision(struct typec_partner *partner, u16 pd_revision);
index 70026f5f8f99714e6d294776842c919b03c66540..0513d333b7977210357b2f1ad2eeae538fe4e392 100644 (file)
@@ -37,6 +37,7 @@ struct typec_altmode {
        u32                             vdo;
        unsigned int                    active:1;
        u8                              priority;
+       bool                    mode_selection;
 
        char                            *desc;
        const struct typec_altmode_ops  *ops;