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.

platform/x86: thinkpad_acpi: Move subdriver initialization to tpacpi_pdriver's probe.

It was reported that if subdrivers assigned devres resources inside
ibm_init_struct's .init callbacks, driver binding would fail with the
following error message:

platform thinkpad_acpi: Resources present before probing

Let the driver core manage the lifetimes of the subdrivers and children
devices, by initializing them inside tpacpi_driver's .probe callback.
This is appropriate because these subdrivers usually expose sysfs groups
and the driver core manages this automatically to avoid races.

One immediate benefit of this, is that we are now able to use devres
inside .init subdriver callbacks.

platform_create_bundle is specifically used because it makes the
driver's probe type synchronous and returns an ERR_PTR if attachment
failed.

Additionally, to make error handling simpler, allocate the input device
using devm_input_allocate_device().

Reported-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Closes: https://lore.kernel.org/platform-driver-x86/20250208091438.5972-1-mpearson-lenovo@squebb.ca/#t
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
Link: https://lore.kernel.org/r/20250215000302.19753-2-kuurtb@gmail.com
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

authored by

Kurt Borja and committed by
Ilpo Järvinen
38b9ab80 c5855d20

+62 -74
+62 -74
drivers/platform/x86/thinkpad_acpi.c
··· 367 367 u32 beep_needs_two_args:1; 368 368 u32 mixer_no_level_control:1; 369 369 u32 battery_force_primary:1; 370 - u32 input_device_registered:1; 371 - u32 platform_drv_registered:1; 372 370 u32 sensors_pdrv_registered:1; 373 371 u32 hotkey_poll_active:1; 374 372 u32 has_adaptive_kbd:1; ··· 11813 11815 11814 11816 static void thinkpad_acpi_module_exit(void) 11815 11817 { 11816 - struct ibm_struct *ibm, *itmp; 11817 - 11818 11818 tpacpi_lifecycle = TPACPI_LIFE_EXITING; 11819 11819 11820 11820 if (tpacpi_hwmon) 11821 11821 hwmon_device_unregister(tpacpi_hwmon); 11822 11822 if (tp_features.sensors_pdrv_registered) 11823 11823 platform_driver_unregister(&tpacpi_hwmon_pdriver); 11824 - if (tp_features.platform_drv_registered) 11825 - platform_driver_unregister(&tpacpi_pdriver); 11826 - 11827 - list_for_each_entry_safe_reverse(ibm, itmp, 11828 - &tpacpi_all_drivers, 11829 - all_drivers) { 11830 - ibm_exit(ibm); 11831 - } 11832 - 11833 - dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); 11834 - 11835 - if (tpacpi_inputdev) { 11836 - if (tp_features.input_device_registered) 11837 - input_unregister_device(tpacpi_inputdev); 11838 - else 11839 - input_free_device(tpacpi_inputdev); 11840 - } 11841 - 11842 11824 if (tpacpi_sensors_pdev) 11843 11825 platform_device_unregister(tpacpi_sensors_pdev); 11844 - if (tpacpi_pdev) 11826 + 11827 + if (tpacpi_pdev) { 11828 + platform_driver_unregister(&tpacpi_pdriver); 11845 11829 platform_device_unregister(tpacpi_pdev); 11830 + } 11831 + 11846 11832 if (proc_dir) 11847 11833 remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); 11848 11834 if (tpacpi_wq) ··· 11838 11856 kfree(thinkpad_id.nummodel_str); 11839 11857 } 11840 11858 11859 + static void tpacpi_subdrivers_release(void *data) 11860 + { 11861 + struct ibm_struct *ibm, *itmp; 11862 + 11863 + list_for_each_entry_safe_reverse(ibm, itmp, &tpacpi_all_drivers, all_drivers) 11864 + ibm_exit(ibm); 11865 + 11866 + dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); 11867 + } 11868 + 11869 + static int __init tpacpi_pdriver_probe(struct platform_device *pdev) 11870 + { 11871 + int ret; 11872 + 11873 + devm_mutex_init(&pdev->dev, &tpacpi_inputdev_send_mutex); 11874 + 11875 + tpacpi_inputdev = devm_input_allocate_device(&pdev->dev); 11876 + if (!tpacpi_inputdev) 11877 + return -ENOMEM; 11878 + 11879 + tpacpi_inputdev->name = "ThinkPad Extra Buttons"; 11880 + tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0"; 11881 + tpacpi_inputdev->id.bustype = BUS_HOST; 11882 + tpacpi_inputdev->id.vendor = thinkpad_id.vendor; 11883 + tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; 11884 + tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 11885 + tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev; 11886 + 11887 + /* Init subdriver dependencies */ 11888 + tpacpi_detect_brightness_capabilities(); 11889 + 11890 + /* Init subdrivers */ 11891 + for (unsigned int i = 0; i < ARRAY_SIZE(ibms_init); i++) { 11892 + ret = ibm_init(&ibms_init[i]); 11893 + if (ret >= 0 && *ibms_init[i].param) 11894 + ret = ibms_init[i].data->write(ibms_init[i].param); 11895 + if (ret < 0) { 11896 + tpacpi_subdrivers_release(NULL); 11897 + return ret; 11898 + } 11899 + } 11900 + 11901 + ret = devm_add_action_or_reset(&pdev->dev, tpacpi_subdrivers_release, NULL); 11902 + if (ret) 11903 + return ret; 11904 + 11905 + ret = input_register_device(tpacpi_inputdev); 11906 + if (ret < 0) 11907 + pr_err("unable to register input device\n"); 11908 + 11909 + return ret; 11910 + } 11841 11911 11842 11912 static int __init thinkpad_acpi_module_init(void) 11843 11913 { 11844 11914 const struct dmi_system_id *dmi_id; 11845 - int ret, i; 11915 + int ret; 11846 11916 acpi_object_type obj_type; 11847 11917 11848 11918 tpacpi_lifecycle = TPACPI_LIFE_INIT; ··· 11954 11920 tp_features.quirks = dmi_id->driver_data; 11955 11921 11956 11922 /* Device initialization */ 11957 - tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, PLATFORM_DEVID_NONE, 11958 - NULL, 0); 11923 + tpacpi_pdev = platform_create_bundle(&tpacpi_pdriver, tpacpi_pdriver_probe, 11924 + NULL, 0, NULL, 0); 11959 11925 if (IS_ERR(tpacpi_pdev)) { 11960 11926 ret = PTR_ERR(tpacpi_pdev); 11961 11927 tpacpi_pdev = NULL; 11962 - pr_err("unable to register platform device\n"); 11928 + pr_err("unable to register platform device/driver bundle\n"); 11963 11929 thinkpad_acpi_module_exit(); 11964 11930 return ret; 11965 11931 } 11932 + 11966 11933 tpacpi_sensors_pdev = platform_device_register_simple( 11967 11934 TPACPI_HWMON_DRVR_NAME, 11968 11935 PLATFORM_DEVID_NONE, NULL, 0); ··· 11975 11940 return ret; 11976 11941 } 11977 11942 11978 - mutex_init(&tpacpi_inputdev_send_mutex); 11979 - tpacpi_inputdev = input_allocate_device(); 11980 - if (!tpacpi_inputdev) { 11981 - thinkpad_acpi_module_exit(); 11982 - return -ENOMEM; 11983 - } else { 11984 - /* Prepare input device, but don't register */ 11985 - tpacpi_inputdev->name = "ThinkPad Extra Buttons"; 11986 - tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0"; 11987 - tpacpi_inputdev->id.bustype = BUS_HOST; 11988 - tpacpi_inputdev->id.vendor = thinkpad_id.vendor; 11989 - tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; 11990 - tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 11991 - tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev; 11992 - } 11993 - 11994 - /* Init subdriver dependencies */ 11995 - tpacpi_detect_brightness_capabilities(); 11996 - 11997 - /* Init subdrivers */ 11998 - for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 11999 - ret = ibm_init(&ibms_init[i]); 12000 - if (ret >= 0 && *ibms_init[i].param) 12001 - ret = ibms_init[i].data->write(ibms_init[i].param); 12002 - if (ret < 0) { 12003 - thinkpad_acpi_module_exit(); 12004 - return ret; 12005 - } 12006 - } 12007 - 12008 11943 tpacpi_lifecycle = TPACPI_LIFE_RUNNING; 12009 - 12010 - ret = platform_driver_register(&tpacpi_pdriver); 12011 - if (ret) { 12012 - pr_err("unable to register main platform driver\n"); 12013 - thinkpad_acpi_module_exit(); 12014 - return ret; 12015 - } 12016 - tp_features.platform_drv_registered = 1; 12017 11944 12018 11945 ret = platform_driver_register(&tpacpi_hwmon_pdriver); 12019 11946 if (ret) { ··· 11993 11996 pr_err("unable to register hwmon device\n"); 11994 11997 thinkpad_acpi_module_exit(); 11995 11998 return ret; 11996 - } 11997 - 11998 - ret = input_register_device(tpacpi_inputdev); 11999 - if (ret < 0) { 12000 - pr_err("unable to register input device\n"); 12001 - thinkpad_acpi_module_exit(); 12002 - return ret; 12003 - } else { 12004 - tp_features.input_device_registered = 1; 12005 11999 } 12006 12000 12007 12001 return 0;