Message ID | 20240106160935.45487-3-hdegoede@redhat.com |
---|---|
State | New |
Headers | show |
Series | i2c-i801 / dell-smo8800: Move instantiation of lis3lv02d i2c_client from i2c-i801 to dell-smo8800 | expand |
On Sat, 2024-01-06 at 18:24 +0200, Andy Shevchenko wrote: > + Cc people from tags of 72921427d46b ("string.h: Add str_has_prefix() helper > function"). See below why. > > + if (!strstarts(adap->name, "SMBus I801 adapter")) > > + return 0; > > Bah, we have str_has_prefix() and this, much older one... > Steven? Others? I mean we can do something about this duplication, right? coccinelle? @@ expression a, b; @@ - strstarts(a, b) + str_has_prefix(a, b)
Hi Hans, kernel test robot noticed the following build warnings: [auto build test WARNING on linus/master] [also build test WARNING on v6.7] [cannot apply to wsa/i2c/for-next next-20240112] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Hans-de-Goede/platform-x86-dell-smo8800-Change-probe-ordering-a-bit/20240107-001715 base: linus/master patch link: https://lore.kernel.org/r/20240106160935.45487-3-hdegoede%40redhat.com patch subject: [PATCH v2 2/6] platform/x86: dell-smo8800: Move instantiation of lis3lv02d i2c_client from i2c-i801 to dell-smo8800 config: x86_64-buildonly-randconfig-001-20240113 (https://download.01.org/0day-ci/archive/20240113/202401131227.HL4y41DY-lkp@intel.com/config) compiler: gcc-12 (Debian 12.2.0-14) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240113/202401131227.HL4y41DY-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202401131227.HL4y41DY-lkp@intel.com/ All warnings (new ones prefixed by >>): In function 'smo8800_instantiate_i2c_client', inlined from 'smo8800_probe' at drivers/platform/x86/dell/dell-smo8800.c:240:2: >> drivers/platform/x86/dell/dell-smo8800.c:188:21: warning: argument 1 null where non-null expected [-Wnonnull] 188 | if (strcmp(dmi_product_name, | ^~~~~~~~~~~~~~~~~~~~~~~~ 189 | dell_lis3lv02d_devices[i].dmi_product_name) == 0) { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from include/linux/bitmap.h:12, from include/linux/cpumask.h:12, from include/linux/smp.h:13, from include/linux/lockdep.h:14, from include/linux/mutex.h:17, from include/linux/kernfs.h:11, from include/linux/sysfs.h:16, from include/linux/kobject.h:20, from include/linux/device/bus.h:17, from drivers/platform/x86/dell/dell-smo8800.c:14: include/linux/string.h: In function 'smo8800_probe': include/linux/string.h:89:12: note: in a call to function 'strcmp' declared 'nonnull' 89 | extern int strcmp(const char *,const char *); | ^~~~~~ vim +188 drivers/platform/x86/dell/dell-smo8800.c 173 174 static void smo8800_instantiate_i2c_client(struct smo8800_device *smo8800) 175 { 176 struct i2c_board_info info = { }; 177 struct i2c_adapter *adap = NULL; 178 const char *dmi_product_name; 179 u8 addr = 0; 180 int i; 181 182 bus_for_each_dev(&i2c_bus_type, NULL, &adap, smo8800_find_i801); 183 if (!adap) 184 return; 185 186 dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); 187 for (i = 0; i < ARRAY_SIZE(dell_lis3lv02d_devices); ++i) { > 188 if (strcmp(dmi_product_name, 189 dell_lis3lv02d_devices[i].dmi_product_name) == 0) { 190 addr = dell_lis3lv02d_devices[i].i2c_addr; 191 break; 192 } 193 } 194 195 if (!addr) { 196 dev_warn(smo8800->dev, 197 "Accelerometer lis3lv02d is present on SMBus but its address is unknown, skipping registration\n"); 198 goto put_adapter; 199 } 200 201 info.addr = addr; 202 strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE); 203 204 smo8800->i2c_dev = i2c_new_client_device(adap, &info); 205 if (IS_ERR(smo8800->i2c_dev)) { 206 dev_err_probe(smo8800->dev, PTR_ERR(smo8800->i2c_dev), 207 "registering accel i2c_client\n"); 208 smo8800->i2c_dev = NULL; 209 } else { 210 dev_info(smo8800->dev, "Registered %s accelerometer on address 0x%02x\n", 211 info.type, info.addr); 212 } 213 put_adapter: 214 i2c_put_adapter(adap); 215 } 216
Hi Hans, kernel test robot noticed the following build errors: [auto build test ERROR on linus/master] [also build test ERROR on v6.7] [cannot apply to wsa/i2c/for-next next-20240112] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Hans-de-Goede/platform-x86-dell-smo8800-Change-probe-ordering-a-bit/20240107-001715 base: linus/master patch link: https://lore.kernel.org/r/20240106160935.45487-3-hdegoede%40redhat.com patch subject: [PATCH v2 2/6] platform/x86: dell-smo8800: Move instantiation of lis3lv02d i2c_client from i2c-i801 to dell-smo8800 config: i386-buildonly-randconfig-005-20240113 (https://download.01.org/0day-ci/archive/20240113/202401131552.PbjGXHjA-lkp@intel.com/config) compiler: gcc-12 (Debian 12.2.0-14) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240113/202401131552.PbjGXHjA-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202401131552.PbjGXHjA-lkp@intel.com/ All error/warnings (new ones prefixed by >>): drivers/platform/x86/dell/dell-smo8800.c: In function 'smo8800_find_i801': >> drivers/platform/x86/dell/dell-smo8800.c:144:21: error: implicit declaration of function 'i2c_get_adapter'; did you mean 'i2c_get_adapdata'? [-Werror=implicit-function-declaration] 144 | *adap_ret = i2c_get_adapter(adap->nr); | ^~~~~~~~~~~~~~~ | i2c_get_adapdata >> drivers/platform/x86/dell/dell-smo8800.c:144:19: warning: assignment to 'struct i2c_adapter *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 144 | *adap_ret = i2c_get_adapter(adap->nr); | ^ drivers/platform/x86/dell/dell-smo8800.c: In function 'smo8800_instantiate_i2c_client': >> drivers/platform/x86/dell/dell-smo8800.c:204:28: error: implicit declaration of function 'i2c_new_client_device' [-Werror=implicit-function-declaration] 204 | smo8800->i2c_dev = i2c_new_client_device(adap, &info); | ^~~~~~~~~~~~~~~~~~~~~ >> drivers/platform/x86/dell/dell-smo8800.c:204:26: warning: assignment to 'struct i2c_client *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 204 | smo8800->i2c_dev = i2c_new_client_device(adap, &info); | ^ >> drivers/platform/x86/dell/dell-smo8800.c:214:9: error: implicit declaration of function 'i2c_put_adapter' [-Werror=implicit-function-declaration] 214 | i2c_put_adapter(adap); | ^~~~~~~~~~~~~~~ drivers/platform/x86/dell/dell-smo8800.c: In function 'smo8800_probe': >> drivers/platform/x86/dell/dell-smo8800.c:267:9: error: implicit declaration of function 'i2c_unregister_device'; did you mean 'pci_unregister_driver'? [-Werror=implicit-function-declaration] 267 | i2c_unregister_device(smo8800->i2c_dev); | ^~~~~~~~~~~~~~~~~~~~~ | pci_unregister_driver cc1: some warnings being treated as errors vim +144 drivers/platform/x86/dell/dell-smo8800.c 129 130 static int smo8800_find_i801(struct device *dev, void *data) 131 { 132 struct i2c_adapter *adap, **adap_ret = data; 133 134 adap = i2c_verify_adapter(dev); 135 if (!adap) 136 return 0; 137 138 if (!strstarts(adap->name, "SMBus I801 adapter")) 139 return 0; 140 141 if (pci_match_id(i801_idf_ids, to_pci_dev(adap->dev.parent))) 142 return 0; /* Only register client on main SMBus channel */ 143 > 144 *adap_ret = i2c_get_adapter(adap->nr); 145 return 1; 146 } 147 148 /* 149 * Accelerometer's I2C address is not specified in DMI nor ACPI, 150 * so it is needed to define mapping table based on DMI product names. 151 */ 152 static const struct { 153 const char *dmi_product_name; 154 unsigned short i2c_addr; 155 } dell_lis3lv02d_devices[] = { 156 /* 157 * Dell platform team told us that these Latitude devices have 158 * ST microelectronics accelerometer at I2C address 0x29. 159 */ 160 { "Latitude E5250", 0x29 }, 161 { "Latitude E5450", 0x29 }, 162 { "Latitude E5550", 0x29 }, 163 { "Latitude E6440", 0x29 }, 164 { "Latitude E6440 ATG", 0x29 }, 165 { "Latitude E6540", 0x29 }, 166 /* 167 * Additional individual entries were added after verification. 168 */ 169 { "Latitude 5480", 0x29 }, 170 { "Vostro V131", 0x1d }, 171 { "Vostro 5568", 0x29 }, 172 }; 173 174 static void smo8800_instantiate_i2c_client(struct smo8800_device *smo8800) 175 { 176 struct i2c_board_info info = { }; 177 struct i2c_adapter *adap = NULL; 178 const char *dmi_product_name; 179 u8 addr = 0; 180 int i; 181 182 bus_for_each_dev(&i2c_bus_type, NULL, &adap, smo8800_find_i801); 183 if (!adap) 184 return; 185 186 dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); 187 for (i = 0; i < ARRAY_SIZE(dell_lis3lv02d_devices); ++i) { 188 if (strcmp(dmi_product_name, 189 dell_lis3lv02d_devices[i].dmi_product_name) == 0) { 190 addr = dell_lis3lv02d_devices[i].i2c_addr; 191 break; 192 } 193 } 194 195 if (!addr) { 196 dev_warn(smo8800->dev, 197 "Accelerometer lis3lv02d is present on SMBus but its address is unknown, skipping registration\n"); 198 goto put_adapter; 199 } 200 201 info.addr = addr; 202 strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE); 203 > 204 smo8800->i2c_dev = i2c_new_client_device(adap, &info); 205 if (IS_ERR(smo8800->i2c_dev)) { 206 dev_err_probe(smo8800->dev, PTR_ERR(smo8800->i2c_dev), 207 "registering accel i2c_client\n"); 208 smo8800->i2c_dev = NULL; 209 } else { 210 dev_info(smo8800->dev, "Registered %s accelerometer on address 0x%02x\n", 211 info.type, info.addr); 212 } 213 put_adapter: > 214 i2c_put_adapter(adap); 215 } 216 217 static int smo8800_probe(struct platform_device *device) 218 { 219 int err; 220 struct smo8800_device *smo8800; 221 222 smo8800 = devm_kzalloc(&device->dev, sizeof(*smo8800), GFP_KERNEL); 223 if (!smo8800) { 224 dev_err(&device->dev, "failed to allocate device data\n"); 225 return -ENOMEM; 226 } 227 228 smo8800->dev = &device->dev; 229 smo8800->miscdev.minor = MISC_DYNAMIC_MINOR; 230 smo8800->miscdev.name = "freefall"; 231 smo8800->miscdev.fops = &smo8800_misc_fops; 232 233 init_waitqueue_head(&smo8800->misc_wait); 234 235 err = platform_get_irq(device, 0); 236 if (err < 0) 237 return err; 238 smo8800->irq = err; 239 240 smo8800_instantiate_i2c_client(smo8800); 241 242 err = misc_register(&smo8800->miscdev); 243 if (err) { 244 dev_err(&device->dev, "failed to register misc dev: %d\n", err); 245 goto error_unregister_i2c_client; 246 } 247 248 err = request_threaded_irq(smo8800->irq, smo8800_interrupt_quick, 249 smo8800_interrupt_thread, 250 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 251 DRIVER_NAME, smo8800); 252 if (err) { 253 dev_err(&device->dev, 254 "failed to request thread for IRQ %d: %d\n", 255 smo8800->irq, err); 256 goto error; 257 } 258 259 dev_dbg(&device->dev, "device /dev/freefall registered with IRQ %d\n", 260 smo8800->irq); 261 platform_set_drvdata(device, smo8800); 262 return 0; 263 264 error: 265 misc_deregister(&smo8800->miscdev); 266 error_unregister_i2c_client: > 267 i2c_unregister_device(smo8800->i2c_dev); 268 return err; 269 } 270
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 070999139c6d..595e263ba623 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -975,6 +975,10 @@ static const struct i2c_algorithm smbus_algorithm = { #define FEATURES_ICH4 (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER | \ FEATURE_HOST_NOTIFY) +/* + * NOTE: If new models with FEATURE_IDF are added please also update + * i801_idf_ids[] in drivers/platform/x86/dell-smo8800.c + */ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) }, { PCI_DEVICE_DATA(INTEL, 82801AB_3, 0) }, @@ -1141,125 +1145,6 @@ static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap) } } -/* NOTE: Keep this list in sync with drivers/platform/x86/dell-smo8800.c */ -static const char *const acpi_smo8800_ids[] = { - "SMO8800", - "SMO8801", - "SMO8810", - "SMO8811", - "SMO8820", - "SMO8821", - "SMO8830", - "SMO8831", -}; - -static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - struct acpi_device_info *info; - acpi_status status; - char *hid; - int i; - - status = acpi_get_object_info(obj_handle, &info); - if (ACPI_FAILURE(status)) - return AE_OK; - - if (!(info->valid & ACPI_VALID_HID)) - goto smo88xx_not_found; - - hid = info->hardware_id.string; - if (!hid) - goto smo88xx_not_found; - - i = match_string(acpi_smo8800_ids, ARRAY_SIZE(acpi_smo8800_ids), hid); - if (i < 0) - goto smo88xx_not_found; - - kfree(info); - - *return_value = NULL; - return AE_CTRL_TERMINATE; - -smo88xx_not_found: - kfree(info); - return AE_OK; -} - -static bool is_dell_system_with_lis3lv02d(void) -{ - void *err = ERR_PTR(-ENOENT); - - if (!dmi_match(DMI_SYS_VENDOR, "Dell Inc.")) - return false; - - /* - * Check that ACPI device SMO88xx is present and is functioning. - * Function acpi_get_devices() already filters all ACPI devices - * which are not present or are not functioning. - * ACPI device SMO88xx represents our ST microelectronics lis3lv02d - * accelerometer but unfortunately ACPI does not provide any other - * information (like I2C address). - */ - acpi_get_devices(NULL, check_acpi_smo88xx_device, NULL, &err); - - return !IS_ERR(err); -} - -/* - * Accelerometer's I2C address is not specified in DMI nor ACPI, - * so it is needed to define mapping table based on DMI product names. - */ -static const struct { - const char *dmi_product_name; - unsigned short i2c_addr; -} dell_lis3lv02d_devices[] = { - /* - * Dell platform team told us that these Latitude devices have - * ST microelectronics accelerometer at I2C address 0x29. - */ - { "Latitude E5250", 0x29 }, - { "Latitude E5450", 0x29 }, - { "Latitude E5550", 0x29 }, - { "Latitude E6440", 0x29 }, - { "Latitude E6440 ATG", 0x29 }, - { "Latitude E6540", 0x29 }, - /* - * Additional individual entries were added after verification. - */ - { "Latitude 5480", 0x29 }, - { "Vostro V131", 0x1d }, - { "Vostro 5568", 0x29 }, -}; - -static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv) -{ - struct i2c_board_info info; - const char *dmi_product_name; - int i; - - dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); - for (i = 0; i < ARRAY_SIZE(dell_lis3lv02d_devices); ++i) { - if (strcmp(dmi_product_name, - dell_lis3lv02d_devices[i].dmi_product_name) == 0) - break; - } - - if (i == ARRAY_SIZE(dell_lis3lv02d_devices)) { - dev_warn(&priv->pci_dev->dev, - "Accelerometer lis3lv02d is present on SMBus but its" - " address is unknown, skipping registration\n"); - return; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = dell_lis3lv02d_devices[i].i2c_addr; - strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE); - i2c_new_client_device(&priv->adapter, &info); -} - /* Register optional slaves */ static void i801_probe_optional_slaves(struct i801_priv *priv) { @@ -1279,9 +1164,6 @@ static void i801_probe_optional_slaves(struct i801_priv *priv) if (dmi_name_in_vendors("FUJITSU")) dmi_walk(dmi_check_onboard_devices, &priv->adapter); - if (is_dell_system_with_lis3lv02d()) - register_dell_lis3lv02d_i2c_device(priv); - /* Instantiate SPD EEPROMs unless the SMBus is multiplexed */ #if IS_ENABLED(CONFIG_I2C_MUX_GPIO) if (!priv->mux_pdev) diff --git a/drivers/platform/x86/dell/dell-smo8800.c b/drivers/platform/x86/dell/dell-smo8800.c index 87339cc78880..c674e3392270 100644 --- a/drivers/platform/x86/dell/dell-smo8800.c +++ b/drivers/platform/x86/dell/dell-smo8800.c @@ -4,18 +4,23 @@ * * Copyright (C) 2012 Sonal Santan <sonal.santan@gmail.com> * Copyright (C) 2014 Pali Rohár <pali@kernel.org> + * Copyright (C) 2023 Hans de Goede <hansg@kernel.org> * * This is loosely based on lis3lv02d driver. */ #define DRIVER_NAME "smo8800" +#include <linux/device/bus.h> +#include <linux/dmi.h> #include <linux/fs.h> +#include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/mod_devicetable.h> #include <linux/module.h> +#include <linux/pci.h> #include <linux/platform_device.h> #include <linux/uaccess.h> @@ -26,6 +31,7 @@ struct smo8800_device { unsigned long misc_opened; /* whether the device is open */ wait_queue_head_t misc_wait; /* Wait queue for the misc dev */ struct device *dev; /* acpi device */ + struct i2c_client *i2c_dev; /* i2c_client for lis3lv02d */ }; static irqreturn_t smo8800_interrupt_quick(int irq, void *data) @@ -103,6 +109,111 @@ static const struct file_operations smo8800_misc_fops = { .release = smo8800_misc_release, }; +/* + * On 2 older PCH generations, Patsburg (for Sandy Bridge and Ivybridge) and + * Wellsburg (for Haswell and Broadwell), the PCH has 3 extra i2c-i801 + * compatible SMBusses called 'Integrated Device Function' busses. These have + * FEATURE_IDF set in the i801_ids[] table in i2c-i801.c. + * The ST microelectronics accelerometer is connected to the main SMBus + * so the IDF controllers should be skipped. + */ +static const struct pci_device_id i801_idf_ids[] = { + { PCI_VDEVICE(INTEL, 0x1d70) }, /* Patsburg IFD0 */ + { PCI_VDEVICE(INTEL, 0x1d71) }, /* Patsburg IFD1 */ + { PCI_VDEVICE(INTEL, 0x1d72) }, /* Patsburg IFD2 */ + { PCI_VDEVICE(INTEL, 0x8d7d) }, /* Wellsburg MS0 */ + { PCI_VDEVICE(INTEL, 0x8d7e) }, /* Wellsburg MS1 */ + { PCI_VDEVICE(INTEL, 0x8d7f) }, /* Wellsburg MS2 */ + {} +}; + +static int smo8800_find_i801(struct device *dev, void *data) +{ + struct i2c_adapter *adap, **adap_ret = data; + + adap = i2c_verify_adapter(dev); + if (!adap) + return 0; + + if (!strstarts(adap->name, "SMBus I801 adapter")) + return 0; + + if (pci_match_id(i801_idf_ids, to_pci_dev(adap->dev.parent))) + return 0; /* Only register client on main SMBus channel */ + + *adap_ret = i2c_get_adapter(adap->nr); + return 1; +} + +/* + * Accelerometer's I2C address is not specified in DMI nor ACPI, + * so it is needed to define mapping table based on DMI product names. + */ +static const struct { + const char *dmi_product_name; + unsigned short i2c_addr; +} dell_lis3lv02d_devices[] = { + /* + * Dell platform team told us that these Latitude devices have + * ST microelectronics accelerometer at I2C address 0x29. + */ + { "Latitude E5250", 0x29 }, + { "Latitude E5450", 0x29 }, + { "Latitude E5550", 0x29 }, + { "Latitude E6440", 0x29 }, + { "Latitude E6440 ATG", 0x29 }, + { "Latitude E6540", 0x29 }, + /* + * Additional individual entries were added after verification. + */ + { "Latitude 5480", 0x29 }, + { "Vostro V131", 0x1d }, + { "Vostro 5568", 0x29 }, +}; + +static void smo8800_instantiate_i2c_client(struct smo8800_device *smo8800) +{ + struct i2c_board_info info = { }; + struct i2c_adapter *adap = NULL; + const char *dmi_product_name; + u8 addr = 0; + int i; + + bus_for_each_dev(&i2c_bus_type, NULL, &adap, smo8800_find_i801); + if (!adap) + return; + + dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + for (i = 0; i < ARRAY_SIZE(dell_lis3lv02d_devices); ++i) { + if (strcmp(dmi_product_name, + dell_lis3lv02d_devices[i].dmi_product_name) == 0) { + addr = dell_lis3lv02d_devices[i].i2c_addr; + break; + } + } + + if (!addr) { + dev_warn(smo8800->dev, + "Accelerometer lis3lv02d is present on SMBus but its address is unknown, skipping registration\n"); + goto put_adapter; + } + + info.addr = addr; + strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE); + + smo8800->i2c_dev = i2c_new_client_device(adap, &info); + if (IS_ERR(smo8800->i2c_dev)) { + dev_err_probe(smo8800->dev, PTR_ERR(smo8800->i2c_dev), + "registering accel i2c_client\n"); + smo8800->i2c_dev = NULL; + } else { + dev_info(smo8800->dev, "Registered %s accelerometer on address 0x%02x\n", + info.type, info.addr); + } +put_adapter: + i2c_put_adapter(adap); +} + static int smo8800_probe(struct platform_device *device) { int err; @@ -126,10 +237,12 @@ static int smo8800_probe(struct platform_device *device) return err; smo8800->irq = err; + smo8800_instantiate_i2c_client(smo8800); + err = misc_register(&smo8800->miscdev); if (err) { dev_err(&device->dev, "failed to register misc dev: %d\n", err); - return err; + goto error_unregister_i2c_client; } err = request_threaded_irq(smo8800->irq, smo8800_interrupt_quick, @@ -150,6 +263,8 @@ static int smo8800_probe(struct platform_device *device) error: misc_deregister(&smo8800->miscdev); +error_unregister_i2c_client: + i2c_unregister_device(smo8800->i2c_dev); return err; } @@ -160,9 +275,9 @@ static void smo8800_remove(struct platform_device *device) free_irq(smo8800->irq, smo8800); misc_deregister(&smo8800->miscdev); dev_dbg(&device->dev, "device /dev/freefall unregistered\n"); + i2c_unregister_device(smo8800->i2c_dev); } -/* NOTE: Keep this list in sync with drivers/i2c/busses/i2c-i801.c */ static const struct acpi_device_id smo8800_ids[] = { { "SMO8800", 0 }, { "SMO8801", 0 }, @@ -189,3 +304,5 @@ module_platform_driver(smo8800_driver); MODULE_DESCRIPTION("Dell Latitude freefall driver (ACPI SMO88XX)"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sonal Santan, Pali Rohár"); +/* Ensure the i2c-801 driver is loaded for i2c_client instantiation */ +MODULE_SOFTDEP("pre: i2c-i801");
It is not necessary to handle the Dell specific instantiation of i2c_client-s for SMO8xxx ACPI devices without an ACPI I2cResource inside the generic i801 I2C adapter driver. The kernel already instantiates platform_device-s for these ACPI devices and the drivers/platform/x86/dell/dell-smo8800.c driver binds to these platform drivers. Move the i2c_client instantiation from the generic i2c-i801 driver to the Dell specific dell-smo8800 driver. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- Changes in v2: - Use a pci_device_id table to check for IDF (non main) i2c-i801 SMBusses - Add a comment documenting the IDF PCI device ids --- drivers/i2c/busses/i2c-i801.c | 126 +---------------------- drivers/platform/x86/dell/dell-smo8800.c | 121 +++++++++++++++++++++- 2 files changed, 123 insertions(+), 124 deletions(-)