From: Michael Grzeschik m.grzeschik@pengutronix.de
[ Upstream commit 0f7bbef1794dc87141897f804e5871a293aa174b ]
Since the typec connectors can have many muxes or switches for different lanes (sbu, usb2, usb3) going into different modal states (usb2, usb3, audio, debug) all of them will be called on typec_switch_set and typec_mux_set. But not all of them will be handling the expected mode.
If one of the mux or switch will come back with EOPTNOSUPP this is no reason to stop running through the next ones. Therefor we skip this particular error value and continue calling the next.
Signed-off-by: Michael Grzeschik m.grzeschik@pengutronix.de Reviewed-by: Heikki Krogerus heikki.krogerus@linux.intel.com Link: https://lore.kernel.org/r/20250404-ml-topic-typec-mux-v1-1-22c0526381ba@peng... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org ---
This appears to be a recent Linux kernel tree. Let me simulate what the issue would be by looking at the original problematic code. Based on the commit diff provided, the issue is:
**Original problematic code:** ```c ret = sw_dev->set(sw_dev, orientation); if (ret) return ret; ```
**Fixed code:** ```c ret = sw_dev->set(sw_dev, orientation); if (ret && ret != -EOPNOTSUPP) return ret; ```
Now I can analyze this commit properly:
**Analysis:**
**YES** - This commit should be backported to stable kernel trees.
**Detailed Analysis:**
1. **Bug Description**: The commit fixes a functional bug where multiple USB Type-C muxes/switches connected to a single connector would fail to be configured if any one of them returned `-EOPNOTSUPP` (Operation Not Supported). This is a common scenario in modern Type-C connectors that have separate muxes for different signal paths (SBU, USB2, USB3, etc.).
2. **Specific Code Changes**: - In `typec_switch_set()` at line 217: Changes `if (ret)` to `if (ret && ret != -EOPNOTSUPP)` - In `typec_mux_set()` at line 381: Changes `if (ret)` to `if (ret && ret != -EOPNOTSUPP)`
3. **Problem Impact**: Before this fix, when `typec_set_orientation()` or `typec_set_mode()` were called: - The functions would iterate through all mux/switch devices - If ANY mux returned `-EOPNOTSUPP` (which is legitimate - some muxes only handle specific modes), the entire operation would fail - This prevented other muxes that COULD handle the mode from being configured - Result: Type-C connectors with multiple muxes would not work properly
4. **Risk Assessment**: - **Very Low Risk**: The change only affects error handling logic - **Minimal Code Change**: Only two lines changed, both adding the same condition - **Backward Compatible**: Does not change API or behavior for successful cases - **Well-Contained**: Limited to the USB Type-C mux subsystem
5. **Stable Tree Criteria Met**: - ✅ **Important Bug Fix**: Fixes functional issues with Type-C connectors - ✅ **Minimal Risk**: Very small, contained change - ✅ **No New Features**: Pure bug fix, no new functionality - ✅ **Clear Side Effects**: No unintended side effects beyond fixing the issue - ✅ **Affects Users**: Type-C devices with multiple muxes (common in modern systems) would malfunction
6. **Evidence from Mux Drivers**: The examination of actual mux drivers like `fsa4480.c` and `gpio-sbu-mux.c` shows they legitimately return `-EOPNOTSUPP` for unsupported modes, confirming this is expected behavior that should not abort the entire chain.
7. **Comparison to Similar Commits**: Unlike the provided reference commits which were mostly cleanups or minor features (all marked NO for backport), this addresses a clear functional bug affecting real- world hardware configurations.
This commit follows the stable tree rules perfectly: it's an important bugfix with minimal risk that affects users with multi-mux Type-C hardware configurations.
drivers/usb/typec/mux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index 941735c731619..a74f8e1a28c21 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c @@ -214,7 +214,7 @@ int typec_switch_set(struct typec_switch *sw, sw_dev = sw->sw_devs[i];
ret = sw_dev->set(sw_dev, orientation); - if (ret) + if (ret && ret != -EOPNOTSUPP) return ret; }
@@ -421,7 +421,7 @@ int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state) mux_dev = mux->mux_devs[i];
ret = mux_dev->set(mux_dev, state); - if (ret) + if (ret && ret != -EOPNOTSUPP) return ret; }