diff --git a/Documentation/firmware-guide/acpi/index.rst b/Documentation/firmware-guide/acpi/index.rst index b6a42f4ffe032..b246902f523fe 100644 --- a/Documentation/firmware-guide/acpi/index.rst +++ b/Documentation/firmware-guide/acpi/index.rst @@ -14,7 +14,6 @@ ACPI Support dsd/phy enumeration osi - method-customizing method-tracing DSD-properties-rules debug diff --git a/Documentation/firmware-guide/acpi/method-customizing.rst b/Documentation/firmware-guide/acpi/method-customizing.rst deleted file mode 100644 index de3ebcaed4cf0..0000000000000 --- a/Documentation/firmware-guide/acpi/method-customizing.rst +++ /dev/null @@ -1,89 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -======================================= -Linux ACPI Custom Control Method How To -======================================= - -:Author: Zhang Rui - - -Linux supports customizing ACPI control methods at runtime. - -Users can use this to: - -1. override an existing method which may not work correctly, - or just for debugging purposes. -2. insert a completely new method in order to create a missing - method such as _OFF, _ON, _STA, _INI, etc. - -For these cases, it is far simpler to dynamically install a single -control method rather than override the entire DSDT, because kernel -rebuild/reboot is not needed and test result can be got in minutes. - -.. note:: - - - Only ACPI METHOD can be overridden, any other object types like - "Device", "OperationRegion", are not recognized. Methods - declared inside scope operators are also not supported. - - - The same ACPI control method can be overridden for many times, - and it's always the latest one that used by Linux/kernel. - - - To get the ACPI debug object output (Store (AAAA, Debug)), - please run:: - - echo 1 > /sys/module/acpi/parameters/aml_debug_output - - -1. override an existing method -============================== -a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT, - just run "cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat" -b) disassemble the table by running "iasl -d dsdt.dat". -c) rewrite the ASL code of the method and save it in a new file, -d) package the new file (psr.asl) to an ACPI table format. - Here is an example of a customized \_SB._AC._PSR method:: - - DefinitionBlock ("", "SSDT", 1, "", "", 0x20080715) - { - Method (\_SB_.AC._PSR, 0, NotSerialized) - { - Store ("In AC _PSR", Debug) - Return (ACON) - } - } - - Note that the full pathname of the method in ACPI namespace - should be used. -e) assemble the file to generate the AML code of the method. - e.g. "iasl -vw 6084 psr.asl" (psr.aml is generated as a result) - If parameter "-vw 6084" is not supported by your iASL compiler, - please try a newer version. -f) mount debugfs by "mount -t debugfs none /sys/kernel/debug" -g) override the old method via the debugfs by running - "cat /tmp/psr.aml > /sys/kernel/debug/acpi/custom_method" - -2. insert a new method -====================== -This is easier than overriding an existing method. -We just need to create the ASL code of the method we want to -insert and then follow the step c) ~ g) in section 1. - -3. undo your changes -==================== -The "undo" operation is not supported for a new inserted method -right now, i.e. we can not remove a method currently. -For an overridden method, in order to undo your changes, please -save a copy of the method original ASL code in step c) section 1, -and redo step c) ~ g) to override the method with the original one. - - -.. note:: We can use a kernel with multiple custom ACPI method running, - But each individual write to debugfs can implement a SINGLE - method override. i.e. if we want to insert/override multiple - ACPI methods, we need to redo step c) ~ g) for multiple times. - -.. note:: Be aware that root can mis-use this driver to modify arbitrary - memory and gain additional rights, if root's privileges got - restricted (for example if root is not allowed to load additional - modules after boot). diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 3c3f8037ebedd..c645bb453f3b7 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -449,20 +449,6 @@ config ACPI_HED which is used to report some hardware errors notified via SCI, mainly the corrected errors. -config ACPI_CUSTOM_METHOD - tristate "Allow ACPI methods to be inserted/replaced at run time" - depends on DEBUG_FS - help - This debug facility allows ACPI AML methods to be inserted and/or - replaced without rebooting the system. For details refer to: - Documentation/firmware-guide/acpi/method-customizing.rst. - - NOTE: This option is security sensitive, because it allows arbitrary - kernel memory to be written to by root (uid=0) users, allowing them - to bypass certain security measures (e.g. if root is not allowed to - load additional kernel modules after boot, this feature may be used - to override that restriction). - config ACPI_BGRT bool "Boottime Graphics Resource Table support" depends on EFI && (X86 || ARM64) diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 12ef8180d272c..8cc8c0d9c8732 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -101,7 +101,6 @@ obj-$(CONFIG_ACPI_SBS) += sbshc.o obj-$(CONFIG_ACPI_SBS) += sbs.o obj-$(CONFIG_ACPI_HED) += hed.o obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o -obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 99c28b7307c3d..7a0dd35d62c94 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -161,7 +161,7 @@ static void cpufreq_add_device(const char *name) pdev = platform_device_register_simple(name, PLATFORM_DEVID_NONE, NULL, 0); if (IS_ERR(pdev)) - pr_info("%s device creation failed: %ld\n", name, PTR_ERR(pdev)); + pr_info("%s device creation failed: %pe\n", name, pdev); } #ifdef CONFIG_X86 diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c index 33c3b16af556b..1d670dbe4d1dd 100644 --- a/drivers/acpi/acpi_tad.c +++ b/drivers/acpi/acpi_tad.c @@ -554,7 +554,7 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id) return acpi_tad_wake_set(dev, "_STV", timer_id, ACPI_TAD_WAKE_DISABLED); } -static int acpi_tad_remove(struct platform_device *pdev) +static void acpi_tad_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; acpi_handle handle = ACPI_HANDLE(dev); @@ -579,7 +579,6 @@ static int acpi_tad_remove(struct platform_device *pdev) pm_runtime_put_sync(dev); pm_runtime_disable(dev); acpi_remove_cmos_rtc_space_handler(handle); - return 0; } static int acpi_tad_probe(struct platform_device *pdev) @@ -684,7 +683,7 @@ static struct platform_driver acpi_tad_driver = { .acpi_match_table = acpi_tad_ids, }, .probe = acpi_tad_probe, - .remove = acpi_tad_remove, + .remove_new = acpi_tad_remove, }; MODULE_DEVICE_TABLE(acpi, acpi_tad_ids); diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 4afdda9db0195..1fda303882973 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -612,7 +612,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, static int acpi_video_device_EDID(struct acpi_video_device *device, - union acpi_object **edid, ssize_t length) + union acpi_object **edid, int length) { int status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -625,13 +625,11 @@ acpi_video_device_EDID(struct acpi_video_device *device, if (!device) return -ENODEV; - if (length == 128) - arg0.integer.value = 1; - else if (length == 256) - arg0.integer.value = 2; - else + if (!length || (length % 128)) return -EINVAL; + arg0.integer.value = length / 128; + status = acpi_evaluate_object(device->dev->handle, "_DDC", &args, &buffer); if (ACPI_FAILURE(status)) return -ENODEV; @@ -641,7 +639,8 @@ acpi_video_device_EDID(struct acpi_video_device *device, if (obj && obj->type == ACPI_TYPE_BUFFER) *edid = obj; else { - acpi_handle_info(device->dev->handle, "Invalid _DDC data\n"); + acpi_handle_debug(device->dev->handle, + "Invalid _DDC data for length %d\n", length); status = -EFAULT; kfree(obj); } @@ -1447,7 +1446,6 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, for (i = 0; i < video->attached_count; i++) { video_device = video->attached_array[i].bind_info; - length = 256; if (!video_device) continue; @@ -1478,18 +1476,14 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, continue; } - status = acpi_video_device_EDID(video_device, &buffer, length); - - if (ACPI_FAILURE(status) || !buffer || - buffer->type != ACPI_TYPE_BUFFER) { - length = 128; + for (length = 512; length > 0; length -= 128) { status = acpi_video_device_EDID(video_device, &buffer, length); - if (ACPI_FAILURE(status) || !buffer || - buffer->type != ACPI_TYPE_BUFFER) { - continue; - } + if (ACPI_SUCCESS(status)) + break; } + if (!length) + continue; *edid = buffer->buffer.pointer; return length; diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c index 8e9e001da38f5..14b24157799cd 100644 --- a/drivers/acpi/acpi_watchdog.c +++ b/drivers/acpi/acpi_watchdog.c @@ -179,7 +179,7 @@ void __init acpi_watchdog_init(void) pdev = platform_device_register_simple("wdat_wdt", PLATFORM_DEVID_NONE, resources, nresources); if (IS_ERR(pdev)) - pr_err("Device creation failed: %ld\n", PTR_ERR(pdev)); + pr_err("Device creation failed: %pe\n", pdev); kfree(resources); diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index ab2a82cb1b0b4..512067cac170d 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -1455,7 +1455,7 @@ static int ghes_probe(struct platform_device *ghes_dev) return rc; } -static int ghes_remove(struct platform_device *ghes_dev) +static void ghes_remove(struct platform_device *ghes_dev) { int rc; struct ghes *ghes; @@ -1492,8 +1492,15 @@ static int ghes_remove(struct platform_device *ghes_dev) break; case ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED: rc = apei_sdei_unregister_ghes(ghes); - if (rc) - return rc; + if (rc) { + /* + * Returning early results in a resource leak, but we're + * only here if stopping the hardware failed. + */ + dev_err(&ghes_dev->dev, "Failed to unregister ghes (%pe)\n", + ERR_PTR(rc)); + return; + } break; default: BUG(); @@ -1507,8 +1514,6 @@ static int ghes_remove(struct platform_device *ghes_dev) mutex_unlock(&ghes_devs_mutex); kfree(ghes); - - return 0; } static struct platform_driver ghes_platform_driver = { @@ -1516,7 +1521,7 @@ static struct platform_driver ghes_platform_driver = { .name = "GHES", }, .probe = ghes_probe, - .remove = ghes_remove, + .remove_new = ghes_remove, }; void __init acpi_ghes_init(void) diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 6aef1ee5e1bdb..20d757687e3d9 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c @@ -37,6 +37,20 @@ EXPORT_SYMBOL_GPL(hest_disable); static struct acpi_table_hest *__read_mostly hest_tab; +/* + * Since GHES_ASSIST is not supported, skip initialization of GHES_ASSIST + * structures for MCA. + * During HEST parsing, detected MCA error sources are cached from early + * table entries so that the Flags and Source Id fields from these cached + * values are then referred to in later table entries to determine if the + * encountered GHES_ASSIST structure should be initialized. + */ +static struct { + struct acpi_hest_ia_corrected *cmc; + struct acpi_hest_ia_machine_check *mc; + struct acpi_hest_ia_deferred_check *dmc; +} mces; + static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = { [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */ [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1, @@ -70,22 +84,54 @@ static int hest_esrc_len(struct acpi_hest_header *hest_hdr) cmc = (struct acpi_hest_ia_corrected *)hest_hdr; len = sizeof(*cmc) + cmc->num_hardware_banks * sizeof(struct acpi_hest_ia_error_bank); + mces.cmc = cmc; } else if (hest_type == ACPI_HEST_TYPE_IA32_CHECK) { struct acpi_hest_ia_machine_check *mc; mc = (struct acpi_hest_ia_machine_check *)hest_hdr; len = sizeof(*mc) + mc->num_hardware_banks * sizeof(struct acpi_hest_ia_error_bank); + mces.mc = mc; } else if (hest_type == ACPI_HEST_TYPE_IA32_DEFERRED_CHECK) { struct acpi_hest_ia_deferred_check *mc; mc = (struct acpi_hest_ia_deferred_check *)hest_hdr; len = sizeof(*mc) + mc->num_hardware_banks * sizeof(struct acpi_hest_ia_error_bank); + mces.dmc = mc; } BUG_ON(len == -1); return len; }; +/* + * GHES and GHESv2 structures share the same format, starting from + * Source Id and ending in Error Status Block Length (inclusive). + */ +static bool is_ghes_assist_struct(struct acpi_hest_header *hest_hdr) +{ + struct acpi_hest_generic *ghes; + u16 related_source_id; + + if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR && + hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR_V2) + return false; + + ghes = (struct acpi_hest_generic *)hest_hdr; + related_source_id = ghes->related_source_id; + + if (mces.cmc && mces.cmc->flags & ACPI_HEST_GHES_ASSIST && + related_source_id == mces.cmc->header.source_id) + return true; + if (mces.mc && mces.mc->flags & ACPI_HEST_GHES_ASSIST && + related_source_id == mces.mc->header.source_id) + return true; + if (mces.dmc && mces.dmc->flags & ACPI_HEST_GHES_ASSIST && + related_source_id == mces.dmc->header.source_id) + return true; + + return false; +} + typedef int (*apei_hest_func_t)(struct acpi_hest_header *hest_hdr, void *data); static int apei_hest_parse(apei_hest_func_t func, void *data) @@ -114,6 +160,11 @@ static int apei_hest_parse(apei_hest_func_t func, void *data) return -EINVAL; } + if (is_ghes_assist_struct(hest_hdr)) { + hest_hdr = (void *)hest_hdr + len; + continue; + } + rc = func(hest_hdr, data); if (rc) return rc; diff --git a/drivers/acpi/arm64/agdi.c b/drivers/acpi/arm64/agdi.c index 8b3c7d42b41bc..f5f21dd0d277e 100644 --- a/drivers/acpi/arm64/agdi.c +++ b/drivers/acpi/arm64/agdi.c @@ -58,7 +58,7 @@ static int agdi_probe(struct platform_device *pdev) return agdi_sdei_probe(pdev, adata); } -static int agdi_remove(struct platform_device *pdev) +static void agdi_remove(struct platform_device *pdev) { struct agdi_data *adata = dev_get_platdata(&pdev->dev); int err, i; @@ -67,7 +67,7 @@ static int agdi_remove(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "Failed to disable sdei-event #%d (%pe)\n", adata->sdei_event, ERR_PTR(err)); - return 0; + return; } for (i = 0; i < 3; i++) { @@ -81,8 +81,6 @@ static int agdi_remove(struct platform_device *pdev) if (err) dev_err(&pdev->dev, "Failed to unregister sdei-event #%d (%pe)\n", adata->sdei_event, ERR_PTR(err)); - - return 0; } static struct platform_driver agdi_driver = { @@ -90,7 +88,7 @@ static struct platform_driver agdi_driver = { .name = "agdi", }, .probe = agdi_probe, - .remove = agdi_remove, + .remove_new = agdi_remove, }; void __init acpi_agdi_init(void) diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c deleted file mode 100644 index d39a9b474727d..0000000000000 --- a/drivers/acpi/custom_method.c +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * custom_method.c - debugfs interface for customizing ACPI control method - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "internal.h" - -MODULE_LICENSE("GPL"); - -static struct dentry *cm_dentry; - -/* /sys/kernel/debug/acpi/custom_method */ - -static ssize_t cm_write(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - static char *buf; - static u32 max_size; - static u32 uncopied_bytes; - - struct acpi_table_header table; - acpi_status status; - int ret; - - ret = security_locked_down(LOCKDOWN_ACPI_TABLES); - if (ret) - return ret; - - if (!(*ppos)) { - /* parse the table header to get the table length */ - if (count <= sizeof(struct acpi_table_header)) - return -EINVAL; - if (copy_from_user(&table, user_buf, - sizeof(struct acpi_table_header))) - return -EFAULT; - uncopied_bytes = max_size = table.length; - /* make sure the buf is not allocated */ - kfree(buf); - buf = kzalloc(max_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - } - - if (buf == NULL) - return -EINVAL; - - if ((*ppos > max_size) || - (*ppos + count > max_size) || - (*ppos + count < count) || - (count > uncopied_bytes)) { - kfree(buf); - buf = NULL; - return -EINVAL; - } - - if (copy_from_user(buf + (*ppos), user_buf, count)) { - kfree(buf); - buf = NULL; - return -EFAULT; - } - - uncopied_bytes -= count; - *ppos += count; - - if (!uncopied_bytes) { - status = acpi_install_method(buf); - kfree(buf); - buf = NULL; - if (ACPI_FAILURE(status)) - return -EINVAL; - add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE); - } - - return count; -} - -static const struct file_operations cm_fops = { - .write = cm_write, - .llseek = default_llseek, -}; - -static int __init acpi_custom_method_init(void) -{ - cm_dentry = debugfs_create_file("custom_method", S_IWUSR, - acpi_debugfs_dir, NULL, &cm_fops); - return 0; -} - -static void __exit acpi_custom_method_exit(void) -{ - debugfs_remove(cm_dentry); -} - -module_init(acpi_custom_method_init); -module_exit(acpi_custom_method_exit); diff --git a/drivers/acpi/dptf/dptf_pch_fivr.c b/drivers/acpi/dptf/dptf_pch_fivr.c index 4919e7abe93f4..654aaa53c67f7 100644 --- a/drivers/acpi/dptf/dptf_pch_fivr.c +++ b/drivers/acpi/dptf/dptf_pch_fivr.c @@ -141,11 +141,9 @@ static int pch_fivr_add(struct platform_device *pdev) return 0; } -static int pch_fivr_remove(struct platform_device *pdev) +static void pch_fivr_remove(struct platform_device *pdev) { sysfs_remove_group(&pdev->dev.kobj, &pch_fivr_attribute_group); - - return 0; } static const struct acpi_device_id pch_fivr_device_ids[] = { @@ -159,7 +157,7 @@ MODULE_DEVICE_TABLE(acpi, pch_fivr_device_ids); static struct platform_driver pch_fivr_driver = { .probe = pch_fivr_add, - .remove = pch_fivr_remove, + .remove_new = pch_fivr_remove, .driver = { .name = "dptf_pch_fivr", .acpi_match_table = pch_fivr_device_ids, diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c index 86561eda939f7..b8187babbbbb5 100644 --- a/drivers/acpi/dptf/dptf_power.c +++ b/drivers/acpi/dptf/dptf_power.c @@ -209,7 +209,7 @@ static int dptf_power_add(struct platform_device *pdev) return 0; } -static int dptf_power_remove(struct platform_device *pdev) +static void dptf_power_remove(struct platform_device *pdev) { struct acpi_device *acpi_dev = platform_get_drvdata(pdev); @@ -221,8 +221,6 @@ static int dptf_power_remove(struct platform_device *pdev) sysfs_remove_group(&pdev->dev.kobj, &dptf_battery_attribute_group); else sysfs_remove_group(&pdev->dev.kobj, &dptf_power_attribute_group); - - return 0; } static const struct acpi_device_id int3407_device_ids[] = { @@ -242,7 +240,7 @@ MODULE_DEVICE_TABLE(acpi, int3407_device_ids); static struct platform_driver dptf_power_driver = { .probe = dptf_power_add, - .remove = dptf_power_remove, + .remove_new = dptf_power_remove, .driver = { .name = "dptf_power", .acpi_match_table = int3407_device_ids, diff --git a/drivers/acpi/evged.c b/drivers/acpi/evged.c index fe6b6792c8bba..11778c93254bf 100644 --- a/drivers/acpi/evged.c +++ b/drivers/acpi/evged.c @@ -173,10 +173,9 @@ static void ged_shutdown(struct platform_device *pdev) } } -static int ged_remove(struct platform_device *pdev) +static void ged_remove(struct platform_device *pdev) { ged_shutdown(pdev); - return 0; } static const struct acpi_device_id ged_acpi_ids[] = { @@ -186,7 +185,7 @@ static const struct acpi_device_id ged_acpi_ids[] = { static struct platform_driver ged_driver = { .probe = ged_probe, - .remove = ged_remove, + .remove_new = ged_remove, .shutdown = ged_shutdown, .driver = { .name = MODULE_NAME, diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c index 9dccbae9e8ea7..ff72e4ef87389 100644 --- a/drivers/acpi/fan_core.c +++ b/drivers/acpi/fan_core.c @@ -387,7 +387,7 @@ static int acpi_fan_probe(struct platform_device *pdev) return result; } -static int acpi_fan_remove(struct platform_device *pdev) +static void acpi_fan_remove(struct platform_device *pdev) { struct acpi_fan *fan = platform_get_drvdata(pdev); @@ -399,8 +399,6 @@ static int acpi_fan_remove(struct platform_device *pdev) sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling"); sysfs_remove_link(&fan->cdev->device.kobj, "device"); thermal_cooling_device_unregister(fan->cdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -446,7 +444,7 @@ static const struct dev_pm_ops acpi_fan_pm = { static struct platform_driver acpi_fan_driver = { .probe = acpi_fan_probe, - .remove = acpi_fan_remove, + .remove_new = acpi_fan_remove, .driver = { .name = "acpi-fan", .acpi_match_table = fan_device_ids, diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index d6cb2c27a23b2..741bcc9d6d6aa 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -111,7 +111,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) snprintf(name, sizeof(name), "%llu", sun); pci_slot = pci_create_slot(pci_bus, device, name, NULL); if (IS_ERR(pci_slot)) { - pr_err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot)); + pr_err("pci_create_slot returned %pe\n", pci_slot); kfree(slot); return AE_OK; } diff --git a/drivers/acpi/pfr_telemetry.c b/drivers/acpi/pfr_telemetry.c index 843f678ade0c2..998264a7333d6 100644 --- a/drivers/acpi/pfr_telemetry.c +++ b/drivers/acpi/pfr_telemetry.c @@ -347,13 +347,11 @@ static const struct file_operations acpi_pfrt_log_fops = { .llseek = noop_llseek, }; -static int acpi_pfrt_log_remove(struct platform_device *pdev) +static void acpi_pfrt_log_remove(struct platform_device *pdev) { struct pfrt_log_device *pfrt_log_dev = platform_get_drvdata(pdev); misc_deregister(&pfrt_log_dev->miscdev); - - return 0; } static void pfrt_log_put_idx(void *data) @@ -427,7 +425,7 @@ static struct platform_driver acpi_pfrt_log_driver = { .acpi_match_table = acpi_pfrt_log_ids, }, .probe = acpi_pfrt_log_probe, - .remove = acpi_pfrt_log_remove, + .remove_new = acpi_pfrt_log_remove, }; module_platform_driver(acpi_pfrt_log_driver); diff --git a/drivers/acpi/pfr_update.c b/drivers/acpi/pfr_update.c index 98267f163e2bd..8b2910995fc1a 100644 --- a/drivers/acpi/pfr_update.c +++ b/drivers/acpi/pfr_update.c @@ -489,13 +489,11 @@ static const struct file_operations acpi_pfru_fops = { .llseek = noop_llseek, }; -static int acpi_pfru_remove(struct platform_device *pdev) +static void acpi_pfru_remove(struct platform_device *pdev) { struct pfru_device *pfru_dev = platform_get_drvdata(pdev); misc_deregister(&pfru_dev->miscdev); - - return 0; } static void pfru_put_idx(void *data) @@ -567,7 +565,7 @@ static struct platform_driver acpi_pfru_driver = { .acpi_match_table = acpi_pfru_ids, }, .probe = acpi_pfru_probe, - .remove = acpi_pfru_remove, + .remove_new = acpi_pfru_remove, }; module_platform_driver(acpi_pfru_driver); diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index bc65ebfcdf767..90c3d2eab9e99 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -428,7 +428,7 @@ bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) } EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration); -int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) +static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bool *skip) { struct acpi_device *adev = ACPI_COMPANION(controller_parent); const struct dmi_system_id *dmi_id; @@ -436,8 +436,6 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s u64 uid; int ret; - *skip = false; - ret = acpi_dev_uid_to_integer(adev, &uid); if (ret) return 0; @@ -463,7 +461,6 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s return 0; } -EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration); bool acpi_quirk_skip_gpio_event_handlers(void) { @@ -478,8 +475,41 @@ bool acpi_quirk_skip_gpio_event_handlers(void) return (quirks & ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS); } EXPORT_SYMBOL_GPL(acpi_quirk_skip_gpio_event_handlers); +#else +static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bool *skip) +{ + return 0; +} #endif +int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) +{ + struct acpi_device *adev = ACPI_COMPANION(controller_parent); + + *skip = false; + + /* + * The DELL0501 ACPI HID represents an UART (CID is set to PNP0501) with + * a backlight-controller attached. There is no separate ACPI device with + * an UartSerialBusV2() resource to model the backlight-controller. + * Set skip to true so that the tty core creates a serdev ctrl device. + * The backlight driver will manually create the serdev client device. + */ + if (acpi_dev_hid_match(adev, "DELL0501")) { + *skip = true; + /* + * Create a platform dev for dell-uart-backlight to bind to. + * This is a static device, so no need to store the result. + */ + platform_device_register_simple("dell-uart-backlight", PLATFORM_DEVID_NONE, + NULL, 0); + return 0; + } + + return acpi_dmi_skip_serdev_enumeration(controller_parent, skip); +} +EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration); + /* Lists of PMIC ACPI HIDs with an (often better) native charger driver */ static const struct { const char *hid; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index f67aa93ba53ed..5de954e2b18aa 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -749,6 +749,7 @@ bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *s bool acpi_quirk_skip_acpi_ac_and_battery(void); int acpi_install_cmos_rtc_space_handler(acpi_handle handle); void acpi_remove_cmos_rtc_space_handler(acpi_handle handle); +int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip); #else static inline bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status) @@ -766,23 +767,22 @@ static inline int acpi_install_cmos_rtc_space_handler(acpi_handle handle) static inline void acpi_remove_cmos_rtc_space_handler(acpi_handle handle) { } +static inline int +acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) +{ + *skip = false; + return 0; +} #endif #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev); -int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip); bool acpi_quirk_skip_gpio_event_handlers(void); #else static inline bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) { return false; } -static inline int -acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) -{ - *skip = false; - return 0; -} static inline bool acpi_quirk_skip_gpio_event_handlers(void) { return false;