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

mfd: cs42l43: Use devres for remove as well

Currently the device is powered down in the remove callback, however
all other clean up is done through devres. The problem here is the
MFD children are cleaned up through devres. As this happens after
the remove callback has run, this leads to the incorrect ordering
where the child remove functions run after the device has been powered
down. Put the power down into devres as well such that everything runs
in the expected order.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20241205115822.2371719-4-ckeepax@opensource.cirrus.com
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Charles Keepax and committed by
Lee Jones
0f35dc4b 47dde1a0

+13 -27
-8
drivers/mfd/cs42l43-i2c.c
··· 56 56 return cs42l43_dev_probe(cs42l43); 57 57 } 58 58 59 - static void cs42l43_i2c_remove(struct i2c_client *i2c) 60 - { 61 - struct cs42l43 *cs42l43 = dev_get_drvdata(&i2c->dev); 62 - 63 - cs42l43_dev_remove(cs42l43); 64 - } 65 - 66 59 #if IS_ENABLED(CONFIG_OF) 67 60 static const struct of_device_id cs42l43_of_match[] = { 68 61 { .compatible = "cirrus,cs42l43", }, ··· 81 88 }, 82 89 83 90 .probe = cs42l43_i2c_probe, 84 - .remove = cs42l43_i2c_remove, 85 91 }; 86 92 module_i2c_driver(cs42l43_i2c_driver); 87 93
-10
drivers/mfd/cs42l43-sdw.c
··· 187 187 return cs42l43_dev_probe(cs42l43); 188 188 } 189 189 190 - static int cs42l43_sdw_remove(struct sdw_slave *sdw) 191 - { 192 - struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev); 193 - 194 - cs42l43_dev_remove(cs42l43); 195 - 196 - return 0; 197 - } 198 - 199 190 static const struct sdw_device_id cs42l43_sdw_id[] = { 200 191 SDW_SLAVE_ENTRY(0x01FA, 0x4243, 0), 201 192 {} ··· 200 209 }, 201 210 202 211 .probe = cs42l43_sdw_probe, 203 - .remove = cs42l43_sdw_remove, 204 212 .id_table = cs42l43_sdw_id, 205 213 .ops = &cs42l43_sdw_ops, 206 214 };
+13 -8
drivers/mfd/cs42l43.c
··· 1038 1038 return 0; 1039 1039 } 1040 1040 1041 + static void cs42l43_dev_remove(void *data) 1042 + { 1043 + struct cs42l43 *cs42l43 = data; 1044 + 1045 + cancel_work_sync(&cs42l43->boot_work); 1046 + 1047 + cs42l43_power_down(cs42l43); 1048 + } 1049 + 1041 1050 int cs42l43_dev_probe(struct cs42l43 *cs42l43) 1042 1051 { 1043 1052 int i, ret; ··· 1093 1084 if (ret) 1094 1085 return ret; 1095 1086 1087 + ret = devm_add_action_or_reset(cs42l43->dev, cs42l43_dev_remove, cs42l43); 1088 + if (ret) 1089 + return ret; 1090 + 1096 1091 pm_runtime_set_autosuspend_delay(cs42l43->dev, CS42L43_AUTOSUSPEND_TIME_MS); 1097 1092 pm_runtime_use_autosuspend(cs42l43->dev); 1098 1093 pm_runtime_set_active(cs42l43->dev); ··· 1114 1101 return 0; 1115 1102 } 1116 1103 EXPORT_SYMBOL_NS_GPL(cs42l43_dev_probe, MFD_CS42L43); 1117 - 1118 - void cs42l43_dev_remove(struct cs42l43 *cs42l43) 1119 - { 1120 - cancel_work_sync(&cs42l43->boot_work); 1121 - 1122 - cs42l43_power_down(cs42l43); 1123 - } 1124 - EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, MFD_CS42L43); 1125 1104 1126 1105 static int cs42l43_suspend(struct device *dev) 1127 1106 {
-1
drivers/mfd/cs42l43.h
··· 25 25 bool cs42l43_volatile_register(struct device *dev, unsigned int reg); 26 26 27 27 int cs42l43_dev_probe(struct cs42l43 *cs42l43); 28 - void cs42l43_dev_remove(struct cs42l43 *cs42l43); 29 28 30 29 #endif /* CS42L43_CORE_INT_H */