Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

i3c: master: Move bus_init error suppression

Prepare to fix improper Mx positive error propagation in later commits
by handling Mx error codes where the i3c_ccc_cmd command is allocated.
The CCC DISEC to broadcast address is invoked with
i3c_master_enec_disec_locked() and yields error I3C_ERROR_M2 if there
are no devices active on the bus. This is expected at the bus
initialization stage, where it is not known yet that there are no active
devices on the bus. Add bool suppress_m2 argument to
i3c_master_enec_disec_locked() and update the call site at
i3c_master_bus_init() with the exact corner case to not require
propagating positive Mx error codes. Other call site should not suppress
the error code, for example, if a driver requests to peripheral to
disable events and the transfer is not acknowledged, this is an error
and should not proceed.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Jorge Marques <jorge.marques@analog.com>
Link: https://patch.msgid.link/20260323-ad4062-positive-error-fix-v3-3-30bdc68004be@analog.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

Jorge Marques and committed by
Alexandre Belloni
49775afa 42247fff

+15 -8
+15 -8
drivers/i3c/master.c
··· 1086 1086 EXPORT_SYMBOL_GPL(i3c_master_entdaa_locked); 1087 1087 1088 1088 static int i3c_master_enec_disec_locked(struct i3c_master_controller *master, 1089 - u8 addr, bool enable, u8 evts) 1089 + u8 addr, bool enable, u8 evts, 1090 + bool suppress_m2) 1090 1091 { 1091 1092 struct i3c_ccc_events *events; 1092 1093 struct i3c_ccc_cmd_dest dest; ··· 1106 1105 &dest, 1); 1107 1106 ret = i3c_master_send_ccc_cmd_locked(master, &cmd); 1108 1107 i3c_ccc_cmd_dest_cleanup(&dest); 1108 + 1109 + if (suppress_m2 && ret && cmd.err == I3C_ERROR_M2) 1110 + ret = 0; 1109 1111 1110 1112 return ret; 1111 1113 } ··· 1130 1126 int i3c_master_disec_locked(struct i3c_master_controller *master, u8 addr, 1131 1127 u8 evts) 1132 1128 { 1133 - return i3c_master_enec_disec_locked(master, addr, false, evts); 1129 + return i3c_master_enec_disec_locked(master, addr, false, evts, false); 1134 1130 } 1135 1131 EXPORT_SYMBOL_GPL(i3c_master_disec_locked); 1136 1132 ··· 1151 1147 int i3c_master_enec_locked(struct i3c_master_controller *master, u8 addr, 1152 1148 u8 evts) 1153 1149 { 1154 - return i3c_master_enec_disec_locked(master, addr, true, evts); 1150 + return i3c_master_enec_disec_locked(master, addr, true, evts, false); 1155 1151 } 1156 1152 EXPORT_SYMBOL_GPL(i3c_master_enec_locked); 1157 1153 ··· 2138 2134 goto err_bus_cleanup; 2139 2135 } 2140 2136 2141 - /* Disable all slave events before starting DAA. */ 2142 - ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR, 2143 - I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR | 2144 - I3C_CCC_EVENT_HJ); 2145 - if (ret && ret != I3C_ERROR_M2) 2137 + /* 2138 + * Disable all slave events before starting DAA. When no active device 2139 + * is on the bus, returns Mx error code M2, this error is ignored. 2140 + */ 2141 + ret = i3c_master_enec_disec_locked(master, I3C_BROADCAST_ADDR, false, 2142 + I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR | 2143 + I3C_CCC_EVENT_HJ, true); 2144 + if (ret) 2146 2145 goto err_bus_cleanup; 2147 2146 2148 2147 /*