From b5b42b24d7830fa18537691860bd4c217f513969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Piwi=C5=84ski?= Date: Mon, 7 Oct 2019 17:48:18 +0200 Subject: [PATCH 01/10] ACPI: video: update doc for acpi_video_bus_DOS() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit efaa14c: "Starting from win8, MS backlight control driver will set bit 2 of the parameter of control method _DOS, to inform firmware it should not perform any automatic brightness changes. This mostly affects hotkey notification deliver - if we do not set this bit, on hotkey press, firmware may choose to adjust brightness level instead of sending out notification and doing nothing." win7: https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/BrightnessCtrl.docx "To avoid problems that might occur if both the system firmware and the monitor driver control the brightness of the display, the display miniport driver should set bit 2 of the argument to the _DOS method. Setting this bit notifies the system firmware that it should not perform any automatic display brightness changes. The WDDM driver must set this particular bit because it controls the _DOS method. The other bits in the _DOS method control the behavior of the firmware in response to the display switch hot keys." win8: http://read.pudn.com/downloads193/doc/907411/Brightness.doc Signed-off-by: Kacper Piwiński Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_video.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 4f325e47519f..2f380e7381d6 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -699,9 +699,13 @@ acpi_video_device_EDID(struct acpi_video_device *device, * event notify code. * lcd_flag : * 0. The system BIOS should automatically control the brightness level - * of the LCD when the power changes from AC to DC + * of the LCD when: + * - the power changes from AC to DC (ACPI appendix B) + * - a brightness hotkey gets pressed (implied by Win7/8 backlight docs) * 1. The system BIOS should NOT automatically control the brightness - * level of the LCD when the power changes from AC to DC. + * level of the LCD when: + * - the power changes from AC to DC (ACPI appendix B) + * - a brightness hotkey gets pressed (implied by Win7/8 backlight docs) * Return Value: * -EINVAL wrong arg. */ From ac36d37e943635fc072e9d4f47e40a48fbcdb3f0 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 9 Oct 2019 15:04:33 +0200 Subject: [PATCH 02/10] ACPI: Always build evged in Although the Generic Event Device is a Hardware-reduced platfom device in principle, it should not be restricted to ACPI_REDUCED_HARDWARE_ONLY. Kernels supporting both fixed and hardware-reduced ACPI platforms should be able to probe the GED when dynamically detecting that a platform is hardware-reduced. For that, the driver must be unconditionally built in. Signed-off-by: Arjan van de Ven Signed-off-by: Samuel Ortiz Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 5d361e4e3405..ef1ac4d127da 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -48,7 +48,7 @@ acpi-y += acpi_pnp.o acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o acpi-y += power.o acpi-y += event.o -acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o +acpi-y += evged.o acpi-y += sysfs.o acpi-y += property.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o From 2e127203d1165851bcbec4863c63a3e3cc72021c Mon Sep 17 00:00:00 2001 From: James Pack Date: Sat, 12 Oct 2019 23:07:23 -0400 Subject: [PATCH 03/10] ACPI: Documentation: Minor spelling fix in namespace.rst Very minor spelling fix in ACPI documentation (typo in namespace.rst). Signed-off-by: James Pack Signed-off-by: Rafael J. Wysocki --- Documentation/firmware-guide/acpi/namespace.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/firmware-guide/acpi/namespace.rst b/Documentation/firmware-guide/acpi/namespace.rst index 835521baeb89..3eb763d6656d 100644 --- a/Documentation/firmware-guide/acpi/namespace.rst +++ b/Documentation/firmware-guide/acpi/namespace.rst @@ -261,7 +261,7 @@ Description Tables contain information used for the creation of the struct acpi_device objects represented by the given row (xSDT means DSDT or SSDT). -The forth column of the above table indicates the 'bus_id' generation +The fourth column of the above table indicates the 'bus_id' generation rule of the struct acpi_device object: _HID: From 8373f8c6a447d53b25d505905be06bdafcbd6f7b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 1 Oct 2019 17:27:20 +0300 Subject: [PATCH 04/10] ACPI / utils: Describe function parameters in kernel-doc Kernel documentation script complains that some of the function parameters are not described: drivers/acpi/utils.c:462: warning: Function parameter or member 'handle' not described in 'acpi_handle_path' drivers/acpi/utils.c:484: warning: Function parameter or member 'level' not described in 'acpi_handle_printk' drivers/acpi/utils.c:484: warning: Function parameter or member 'handle' not described in 'acpi_handle_printk' drivers/acpi/utils.c:484: warning: Function parameter or member 'fmt' not described in 'acpi_handle_printk' drivers/acpi/utils.c:513: warning: Function parameter or member 'descriptor' not described in '__acpi_handle_debug' drivers/acpi/utils.c:513: warning: Function parameter or member 'handle' not described in '__acpi_handle_debug' drivers/acpi/utils.c:513: warning: Function parameter or member 'fmt' not described in '__acpi_handle_debug' Describe function parameters where it's appropriate. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/utils.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index e3974a8f8fd4..dbd1c4cfd7d1 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -455,6 +455,7 @@ EXPORT_SYMBOL(acpi_evaluate_ost); /** * acpi_handle_path: Return the object path of handle + * @handle: ACPI device handle * * Caller must free the returned buffer */ @@ -473,6 +474,9 @@ static char *acpi_handle_path(acpi_handle handle) /** * acpi_handle_printk: Print message with ACPI prefix and object path + * @level: log level + * @handle: ACPI device handle + * @fmt: format string * * This function is called through acpi_handle_ macros and prints * a message with ACPI prefix and object path. This function acquires @@ -501,6 +505,9 @@ EXPORT_SYMBOL(acpi_handle_printk); #if defined(CONFIG_DYNAMIC_DEBUG) /** * __acpi_handle_debug: pr_debug with ACPI prefix and object path + * @descriptor: Dynamic Debug descriptor + * @handle: ACPI device handle + * @fmt: format string * * This function is called through acpi_handle_debug macro and debug * prints a message with ACPI prefix and object path. This function From a814dcc269830c9dbb8a83731cfc6fc5dd787f8d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 1 Oct 2019 17:27:21 +0300 Subject: [PATCH 05/10] ACPI / utils: Move acpi_dev_get_first_match_dev() under CONFIG_ACPI We have a stub defined for the acpi_dev_get_first_match_dev() in acpi.h for the case when CONFIG_ACPI=n. Moreover, acpi_dev_put(), counterpart function, is already placed under CONFIG_ACPI. Thus, move acpi_dev_get_first_match_dev() under CONFIG_ACPI as well. Fixes: 817b4d64da03 ("ACPI / utils: Introduce acpi_dev_get_first_match_dev() helper") Reported-by: kbuild test robot Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Cc: 5.2+ # 5.2+ Signed-off-by: Rafael J. Wysocki --- include/acpi/acpi_bus.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 175f7b40c585..3f6fddeb7519 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -78,9 +78,6 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev, bool acpi_dev_found(const char *hid); bool acpi_dev_present(const char *hid, const char *uid, s64 hrv); -struct acpi_device * -acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv); - #ifdef CONFIG_ACPI #include @@ -683,6 +680,9 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev) adev->power.states[ACPI_STATE_D3_HOT].flags.explicit_set); } +struct acpi_device * +acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv); + static inline void acpi_dev_put(struct acpi_device *adev) { put_device(&adev->dev); From 35009c807488ccd5a01cbf102033695e52794b68 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 1 Oct 2019 17:27:22 +0300 Subject: [PATCH 06/10] ACPI / utils: Introduce acpi_dev_hid_uid_match() helper There are users outside of ACPI realm which reimplementing the comparator function to check if the given device matches to given HID and UID. For better utilization, introduce a helper for everyone to use. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/utils.c | 25 +++++++++++++++++++++++++ include/acpi/acpi_bus.h | 2 ++ include/linux/acpi.h | 8 ++++++++ 3 files changed, 35 insertions(+) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index dbd1c4cfd7d1..804ac0df58ec 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -701,6 +701,31 @@ bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs) } EXPORT_SYMBOL(acpi_check_dsm); +/** + * acpi_dev_hid_uid_match - Match device by supplied HID and UID + * @adev: ACPI device to match. + * @hid2: Hardware ID of the device. + * @uid2: Unique ID of the device, pass NULL to not check _UID. + * + * Matches HID and UID in @adev with given @hid2 and @uid2. + * Returns true if matches. + */ +bool acpi_dev_hid_uid_match(struct acpi_device *adev, + const char *hid2, const char *uid2) +{ + const char *hid1 = acpi_device_hid(adev); + const char *uid1 = acpi_device_uid(adev); + + if (strcmp(hid1, hid2)) + return false; + + if (!uid2) + return true; + + return uid1 && !strcmp(uid1, uid2); +} +EXPORT_SYMBOL(acpi_dev_hid_uid_match); + /** * acpi_dev_found - Detect presence of a given ACPI device in the namespace. * @hid: Hardware ID of the device. diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 3f6fddeb7519..0c23fd0548d1 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -680,6 +680,8 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev) adev->power.states[ACPI_STATE_D3_HOT].flags.explicit_set); } +bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2); + struct acpi_device * acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 8b4e516bac00..0f37a7d5fa77 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -678,6 +678,14 @@ static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv) return false; } +struct acpi_device; + +static inline bool +acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2) +{ + return false; +} + static inline struct acpi_device * acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv) { From 7e70c8acf2bfea90f8bcf46bb6fc51e26723e480 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 1 Oct 2019 17:27:23 +0300 Subject: [PATCH 07/10] ACPI / LPSS: Switch to use acpi_dev_hid_uid_match() Since we have a generic helper, drop custom implementation in the driver. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 60bbc5090abe..1e520ea16042 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -478,31 +478,16 @@ static const struct lpss_device_links lpss_device_links[] = { {"80860F41", "5", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, }; -static bool hid_uid_match(struct acpi_device *adev, - const char *hid2, const char *uid2) -{ - const char *hid1 = acpi_device_hid(adev); - const char *uid1 = acpi_device_uid(adev); - - if (strcmp(hid1, hid2)) - return false; - - if (!uid2) - return true; - - return uid1 && !strcmp(uid1, uid2); -} - static bool acpi_lpss_is_supplier(struct acpi_device *adev, const struct lpss_device_links *link) { - return hid_uid_match(adev, link->supplier_hid, link->supplier_uid); + return acpi_dev_hid_uid_match(adev, link->supplier_hid, link->supplier_uid); } static bool acpi_lpss_is_consumer(struct acpi_device *adev, const struct lpss_device_links *link) { - return hid_uid_match(adev, link->consumer_hid, link->consumer_uid); + return acpi_dev_hid_uid_match(adev, link->consumer_hid, link->consumer_uid); } struct hid_uid { @@ -518,7 +503,7 @@ static int match_hid_uid(struct device *dev, const void *data) if (!adev) return 0; - return hid_uid_match(adev, id->hid, id->uid); + return acpi_dev_hid_uid_match(adev, id->hid, id->uid); } static struct device *acpi_lpss_find_device(const char *hid, const char *uid) From 4f3cde3a24ce874973ee21269da16024c77a159c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 1 Oct 2019 17:27:24 +0300 Subject: [PATCH 08/10] mmc: sdhci-acpi: Switch to use acpi_dev_hid_uid_match() Since we have a generic helper, drop custom implementation in the driver. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Acked-by: Adrian Hunter Signed-off-by: Rafael J. Wysocki --- drivers/mmc/host/sdhci-acpi.c | 49 ++++++++++++----------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 1604f512c7bd..105e73d4a3b9 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -61,7 +61,7 @@ struct sdhci_acpi_slot { mmc_pm_flag_t pm_caps; unsigned int flags; size_t priv_size; - int (*probe_slot)(struct platform_device *, const char *, const char *); + int (*probe_slot)(struct platform_device *, struct acpi_device *); int (*remove_slot)(struct platform_device *); int (*free_slot)(struct platform_device *pdev); int (*setup_host)(struct platform_device *pdev); @@ -325,12 +325,10 @@ static bool sdhci_acpi_cht_pci_wifi(unsigned int vendor, unsigned int device, * wifi card in the expected slot with an ACPI companion node, is used to * indicate that acpi_device_fix_up_power() should be avoided. */ -static inline bool sdhci_acpi_no_fixup_child_power(const char *hid, - const char *uid) +static inline bool sdhci_acpi_no_fixup_child_power(struct acpi_device *adev) { return sdhci_acpi_cht() && - !strcmp(hid, "80860F14") && - !strcmp(uid, "2") && + acpi_dev_hid_uid_match(adev, "80860F14", "2") && sdhci_acpi_cht_pci_wifi(0x14e4, 0x43ec, 0, 28); } @@ -345,8 +343,7 @@ static inline bool sdhci_acpi_byt_defer(struct device *dev) return false; } -static inline bool sdhci_acpi_no_fixup_child_power(const char *hid, - const char *uid) +static inline bool sdhci_acpi_no_fixup_child_power(struct acpi_device *adev) { return false; } @@ -375,19 +372,18 @@ out: return ret; } -static int intel_probe_slot(struct platform_device *pdev, const char *hid, - const char *uid) +static int intel_probe_slot(struct platform_device *pdev, struct acpi_device *adev) { struct sdhci_acpi_host *c = platform_get_drvdata(pdev); struct intel_host *intel_host = sdhci_acpi_priv(c); struct sdhci_host *host = c->host; - if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") && + if (acpi_dev_hid_uid_match(adev, "80860F14", "1") && sdhci_readl(host, SDHCI_CAPABILITIES) == 0x446cc8b2 && sdhci_readl(host, SDHCI_CAPABILITIES_1) == 0x00000807) host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */ - if (hid && !strcmp(hid, "80865ACA")) + if (acpi_dev_hid_uid_match(adev, "80865ACA", NULL)) host->mmc_host_ops.get_cd = bxt_get_cd; intel_dsm_init(intel_host, &pdev->dev, host->mmc); @@ -473,8 +469,7 @@ static irqreturn_t sdhci_acpi_qcom_handler(int irq, void *ptr) return IRQ_HANDLED; } -static int qcom_probe_slot(struct platform_device *pdev, const char *hid, - const char *uid) +static int qcom_probe_slot(struct platform_device *pdev, struct acpi_device *adev) { struct sdhci_acpi_host *c = platform_get_drvdata(pdev); struct sdhci_host *host = c->host; @@ -482,7 +477,7 @@ static int qcom_probe_slot(struct platform_device *pdev, const char *hid, *irq = -EINVAL; - if (strcmp(hid, "QCOM8051")) + if (!acpi_dev_hid_uid_match(adev, "QCOM8051", NULL)) return 0; *irq = platform_get_irq(pdev, 1); @@ -501,14 +496,12 @@ static int qcom_free_slot(struct platform_device *pdev) struct sdhci_host *host = c->host; struct acpi_device *adev; int *irq = sdhci_acpi_priv(c); - const char *hid; adev = ACPI_COMPANION(dev); if (!adev) return -ENODEV; - hid = acpi_device_hid(adev); - if (strcmp(hid, "QCOM8051")) + if (!acpi_dev_hid_uid_match(adev, "QCOM8051", NULL)) return 0; if (*irq < 0) @@ -583,7 +576,7 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_amd = { }; static int sdhci_acpi_emmc_amd_probe_slot(struct platform_device *pdev, - const char *hid, const char *uid) + struct acpi_device *adev) { struct sdhci_acpi_host *c = platform_get_drvdata(pdev); struct sdhci_host *host = c->host; @@ -654,17 +647,12 @@ static const struct acpi_device_id sdhci_acpi_ids[] = { }; MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids); -static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid, - const char *uid) +static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(struct acpi_device *adev) { const struct sdhci_acpi_uid_slot *u; for (u = sdhci_acpi_uids; u->hid; u++) { - if (strcmp(u->hid, hid)) - continue; - if (!u->uid) - return u->slot; - if (uid && !strcmp(u->uid, uid)) + if (acpi_dev_hid_uid_match(adev, u->hid, u->uid)) return u->slot; } return NULL; @@ -680,22 +668,17 @@ static int sdhci_acpi_probe(struct platform_device *pdev) struct resource *iomem; resource_size_t len; size_t priv_size; - const char *hid; - const char *uid; int err; device = ACPI_COMPANION(dev); if (!device) return -ENODEV; - hid = acpi_device_hid(device); - uid = acpi_device_uid(device); - - slot = sdhci_acpi_get_slot(hid, uid); + slot = sdhci_acpi_get_slot(device); /* Power on the SDHCI controller and its children */ acpi_device_fix_up_power(device); - if (!sdhci_acpi_no_fixup_child_power(hid, uid)) { + if (!sdhci_acpi_no_fixup_child_power(device)) { list_for_each_entry(child, &device->children, node) if (child->status.present && child->status.enabled) acpi_device_fix_up_power(child); @@ -745,7 +728,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) if (c->slot) { if (c->slot->probe_slot) { - err = c->slot->probe_slot(pdev, hid, uid); + err = c->slot->probe_slot(pdev, device); if (err) goto err_free; } From ae5e6c6439c3d0ac8e9c71523790ba1ff6887894 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 1 Oct 2019 17:27:25 +0300 Subject: [PATCH 09/10] iommu/amd: Switch to use acpi_dev_hid_uid_match() Since we have a generic helper, drop custom implementation in the driver. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Reviewed-by: Jerry Snitselaar Signed-off-by: Rafael J. Wysocki --- drivers/iommu/amd_iommu.c | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 2369b8af81f3..40f3cf44aa98 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -124,30 +124,6 @@ static struct lock_class_key reserved_rbtree_key; * ****************************************************************************/ -static inline int match_hid_uid(struct device *dev, - struct acpihid_map_entry *entry) -{ - struct acpi_device *adev = ACPI_COMPANION(dev); - const char *hid, *uid; - - if (!adev) - return -ENODEV; - - hid = acpi_device_hid(adev); - uid = acpi_device_uid(adev); - - if (!hid || !(*hid)) - return -ENODEV; - - if (!uid || !(*uid)) - return strcmp(hid, entry->hid); - - if (!(*entry->uid)) - return strcmp(hid, entry->hid); - - return (strcmp(hid, entry->hid) || strcmp(uid, entry->uid)); -} - static inline u16 get_pci_device_id(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -158,10 +134,14 @@ static inline u16 get_pci_device_id(struct device *dev) static inline int get_acpihid_device_id(struct device *dev, struct acpihid_map_entry **entry) { + struct acpi_device *adev = ACPI_COMPANION(dev); struct acpihid_map_entry *p; + if (!adev) + return -ENODEV; + list_for_each_entry(p, &acpihid_map, list) { - if (!match_hid_uid(dev, p)) { + if (acpi_dev_hid_uid_match(adev, p->hid, p->uid)) { if (entry) *entry = p; return p->devid; From cb0701acfa7e3fe9e919cf2aa2aa939b7fd603c2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 30 Aug 2019 17:34:32 +0300 Subject: [PATCH 10/10] ACPI: platform: Unregister stale platform devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When commit 68bdb6773289 ("ACPI: add support for ACPI reconfiguration notifiers") introduced reconfiguration notifiers, it missed the point that the ACPI table, which might be loaded and then unloaded via ConfigFS, could contain devices that were not enumerated by their parents. In such cases, the stale platform device is dangling in the system while the rest of the devices from the same table are already gone. Introduce acpi_platform_device_remove_notify() notifier that, in similar way to I²C or SPI buses, unregisters the platform devices on table removal event. Fixes: 68bdb6773289 ("ACPI: add support for ACPI reconfiguration notifiers") Depends-on: 00500147cbd3 ("drivers: Introduce device lookup variants by ACPI_COMPANION device") Signed-off-by: Andy Shevchenko [ rjw: Changelog & function rename ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_platform.c | 43 ++++++++++++++++++++++++++++++++++++ drivers/acpi/scan.c | 1 + 2 files changed, 44 insertions(+) diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 00ec4f2bf015..c05050f474cd 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -31,6 +31,44 @@ static const struct acpi_device_id forbidden_id_list[] = { {"", 0}, }; +static struct platform_device *acpi_platform_device_find_by_companion(struct acpi_device *adev) +{ + struct device *dev; + + dev = bus_find_device_by_acpi_dev(&platform_bus_type, adev); + return dev ? to_platform_device(dev) : NULL; +} + +static int acpi_platform_device_remove_notify(struct notifier_block *nb, + unsigned long value, void *arg) +{ + struct acpi_device *adev = arg; + struct platform_device *pdev; + + switch (value) { + case ACPI_RECONFIG_DEVICE_ADD: + /* Nothing to do here */ + break; + case ACPI_RECONFIG_DEVICE_REMOVE: + if (!acpi_device_enumerated(adev)) + break; + + pdev = acpi_platform_device_find_by_companion(adev); + if (!pdev) + break; + + platform_device_unregister(pdev); + put_device(&pdev->dev); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block acpi_platform_notifier = { + .notifier_call = acpi_platform_device_remove_notify, +}; + static void acpi_platform_fill_resource(struct acpi_device *adev, const struct resource *src, struct resource *dest) { @@ -130,3 +168,8 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, return pdev; } EXPORT_SYMBOL_GPL(acpi_create_platform_device); + +void __init acpi_platform_init(void) +{ + acpi_reconfig_notifier_register(&acpi_platform_notifier); +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index aad6be5c0af0..915650bf519f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2174,6 +2174,7 @@ int __init acpi_scan_init(void) acpi_pci_root_init(); acpi_pci_link_init(); acpi_processor_init(); + acpi_platform_init(); acpi_lpss_init(); acpi_apd_init(); acpi_cmos_rtc_init();