Merge tag 'acpi-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Aug 2018 20:39:52 +0000 (13:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Aug 2018 20:39:52 +0000 (13:39 -0700)
Pull ACPI updates from Rafael Wysocki:
 "These revert two ACPICA commits that are not needed any more, rework
  the property graphs support in ACPI to be more aligned with the
  analogous DT code, add some new quirks and remove one that isn't
  needed any more, add a special platform driver to enumerate multiple
  I2C devices hooked up to the same device object in the ACPI tables and
  update the battery and button drivers.

  Specifics:

   - Revert two ACPICA commits that are not needed any more (Erik
     Schmauss).

   - Rework property graph support in the ACPI device properties
     framework to make it behave more like the analogous DT code and
     update the documentation of it (Sakari Ailus).

   - Change the default ACPI device status after initialization to
     ACPI_STA_DEFAULT instead of 0 (Hans de Goede).

   - Add a special platform driver for enumerating multiple I2C devices
     hooked up to the same object in the ACPI tables (Hans de Goede).

   - Fix the ACPI battery driver to avoid reporting full capacity on
     systems without support for that and clean it up (Hans de Goede,
     Dmitry Rozhkov, Lucas Rangit Magasweran).

   - Add two system wakeup quirks to the ACPI EC driver (Aaron Ma, Mika
     Westerberg).

   - Add the touchscreen on Dell Venue Pro 7139 to the list of "always
     present" devices to make it work (Tristian Celestin).

   - Revert a special tables handling quirk for Dell XPS 9570 and
     Precision M5530 which is not needed any more (Kai Heng Feng).

   - Add support for a new OEM _OSI string to allow system vendors to
     work around issues with NVidia HDMI audio (Alex Hung).

   - Prevent the ACPI button driver from reporting excessive system
     wakeup events and clean it up (Ravi Chandra Sadineni, Randy
     Dunlap).

   - Clean up two minor code style issues in the ACPI core and GHES
     handling on ARM64 (Dongjiu Geng, John Garry, Tom Todd)"

* tag 'acpi-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (34 commits)
  platform/x86: Add ACPI i2c-multi-instantiate pseudo driver
  ACPI / x86: utils: Remove status workaround from acpi_device_always_present()
  ACPI / scan: Create platform device for fwnodes with multiple i2c devices
  ACPI / scan: Initialize status to ACPI_STA_DEFAULT
  ACPI / EC: Add another entry for Thinkpad X1 Carbon 6th
  ACPI: bus: Fix a pointer coding style issue
  arm64 / ACPI: clean the additional checks before calling ghes_notify_sea()
  ACPI / scan: Add static attribute to indirect_io_hosts[]
  ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity
  ACPI / EC: Use ec_no_wakeup on ThinkPad X1 Yoga 3rd
  ACPI / battery: get rid of negations in conditions
  ACPI / battery: use specialized print macros
  ACPI / battery: reorder headers alphabetically
  ACPI / battery: drop inclusion of init.h
  ACPI: battery: remove redundant old_present check on insertion
  ACPI: property: graph: Update graph documentation to use generic references
  ACPI: property: graph: Improve graph documentation for port/ep numbering
  ACPI: property: graph: Fix graph documentation
  ACPI: property: Update documentation for hierarchical data extension 1.1
  ACPI: property: Document key numbering for hierarchical data extension refs
  ...

28 files changed:
Documentation/acpi/dsd/data-node-references.txt [new file with mode: 0644]
Documentation/acpi/dsd/graph.txt
MAINTAINERS
arch/arm64/mm/fault.c
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/nsaccess.c
drivers/acpi/acpica/nssearch.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/button.c
drivers/acpi/ec.c
drivers/acpi/osi.c
drivers/acpi/property.c
drivers/acpi/scan.c
drivers/acpi/x86/utils.c
drivers/gpio/gpiolib-acpi.c
drivers/infiniband/hw/hns/hns_roce_hw_v1.c
drivers/media/v4l2-core/v4l2-fwnode.c
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/i2c-multi-instantiate.c [new file with mode: 0644]
include/acpi/acpixf.h
include/acpi/ghes.h
include/linux/acpi.h
include/linux/fwnode.h

diff --git a/Documentation/acpi/dsd/data-node-references.txt b/Documentation/acpi/dsd/data-node-references.txt
new file mode 100644 (file)
index 0000000..c387156
--- /dev/null
@@ -0,0 +1,89 @@
+Copyright (C) 2018 Intel Corporation
+Author: Sakari Ailus <sakari.ailus@linux.intel.com>
+
+
+Referencing hierarchical data nodes
+-----------------------------------
+
+ACPI in general allows referring to device objects in the tree only.
+Hierarchical data extension nodes may not be referred to directly, hence this
+document defines a scheme to implement such references.
+
+A reference consist of the device object name followed by one or more
+hierarchical data extension [1] keys. Specifically, the hierarchical data
+extension node which is referred to by the key shall lie directly under the
+parent object i.e. either the device object or another hierarchical data
+extension node.
+
+The keys in the hierarchical data nodes shall consist of the name of the node,
+"@" character and the number of the node in hexadecimal notation (without pre-
+or postfixes). The same ACPI object shall include the _DSD property extension
+with a property "reg" that shall have the same numerical value as the number of
+the node.
+
+In case a hierarchical data extensions node has no numerical value, then the
+"reg" property shall be omitted from the ACPI object's _DSD properties and the
+"@" character and the number shall be omitted from the hierarchical data
+extension key.
+
+
+Example
+-------
+
+       In the ASL snippet below, the "reference" _DSD property [2] contains a
+       device object reference to DEV0 and under that device object, a
+       hierarchical data extension key "node@1" referring to the NOD1 object
+       and lastly, a hierarchical data extension key "anothernode" referring to
+       the ANOD object which is also the final target node of the reference.
+
+       Device (DEV0)
+       {
+           Name (_DSD, Package () {
+               ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
+               Package () {
+                   Package () { "node@0", NOD0 },
+                   Package () { "node@1", NOD1 },
+               }
+           })
+           Name (NOD0, Package() {
+               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+               Package () {
+                   Package () { "random-property", 3 },
+               }
+           })
+           Name (NOD1, Package() {
+               ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
+               Package () {
+                   Package () { "anothernode", ANOD },
+               }
+           })
+           Name (ANOD, Package() {
+               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+               Package () {
+                   Package () { "random-property", 0 },
+               }
+           })
+       }
+
+       Device (DEV1)
+       {
+           Name (_DSD, Package () {
+               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+               Package () {
+                   Package () { "reference", ^DEV0, "node@1", "anothernode" },
+               }
+           })
+       }
+
+Please also see a graph example in graph.txt .
+
+References
+----------
+
+[1] Hierarchical Data Extension UUID For _DSD.
+    <URL:http://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf>,
+    referenced 2018-07-17.
+
+[2] Device Properties UUID For _DSD.
+    <URL:http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf>,
+    referenced 2016-10-04.
index ac09e3138b791213c9bdd4e74f698d818a6ecbd6..b9ce910781dcd09b9f308dac6218a0b3b27da7ed 100644 (file)
@@ -36,29 +36,41 @@ The port and endpoint concepts are very similar to those in Devicetree
 [3]. A port represents an interface in a device, and an endpoint
 represents a connection to that interface.
 
-All port nodes are located under the device's "_DSD" node in the
-hierarchical data extension tree. The property extension related to
-each port node must contain the key "port" and an integer value which
-is the number of the port. The object it refers to should be called "PRTX",
-where "X" is the number of the port.
-
-Further on, endpoints are located under the individual port nodes. The
-first hierarchical data extension package list entry of the endpoint
-nodes must begin with "endpoint" and must be followed by the number
-of the endpoint. The object it refers to should be called "EPXY", where
-"X" is the number of the port and "Y" is the number of the endpoint.
-
-Each port node contains a property extension key "port", the value of
-which is the number of the port node. The each endpoint is similarly numbered
-with a property extension key "endpoint". Port numbers must be unique within a
-device and endpoint numbers must be unique within a port.
+All port nodes are located under the device's "_DSD" node in the hierarchical
+data extension tree. The data extension related to each port node must begin
+with "port" and must be followed by the "@" character and the number of the port
+as its key. The target object it refers to should be called "PRTX", where "X" is
+the number of the port. An example of such a package would be:
+
+    Package() { "port@4", PRT4 }
+
+Further on, endpoints are located under the port nodes. The hierarchical
+data extension key of the endpoint nodes must begin with
+"endpoint" and must be followed by the "@" character and the number of the
+endpoint. The object it refers to should be called "EPXY", where "X" is the
+number of the port and "Y" is the number of the endpoint. An example of such a
+package would be:
+
+    Package() { "endpoint@0", EP40 }
+
+Each port node contains a property extension key "port", the value of which is
+the number of the port. Each endpoint is similarly numbered with a property
+extension key "reg", the value of which is the number of the endpoint. Port
+numbers must be unique within a device and endpoint numbers must be unique
+within a port. If a device object may only has a single port, then the number
+of that port shall be zero. Similarly, if a port may only have a single
+endpoint, the number of that endpoint shall be zero.
 
 The endpoint reference uses property extension with "remote-endpoint" property
 name followed by a reference in the same package. Such references consist of the
-the remote device reference, number of the port in the device and finally the
-number of the endpoint in that port. Individual references thus appear as:
+the remote device reference, the first package entry of the port data extension
+reference under the device and finally the first package entry of the endpoint
+data extension reference under the port. Individual references thus appear as:
 
-    Package() { device, port_number, endpoint_number }
+    Package() { device, "port@X", "endpoint@Y" }
+
+In the above example, "X" is the number of the port and "Y" is the number of the
+endpoint.
 
 The references to endpoints must be always done both ways, to the
 remote endpoint and back from the referred remote endpoint node.
@@ -76,24 +88,24 @@ A simple example of this is show below:
                },
                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
                Package () {
-                   Package () { "port0", "PRT0" },
+                   Package () { "port@0", PRT0 },
                }
            })
            Name (PRT0, Package() {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package () {
-                   Package () { "port", 0 },
+                   Package () { "reg", 0 },
                },
                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
                Package () {
-                   Package () { "endpoint0", "EP00" },
+                   Package () { "endpoint@0", EP00 },
                }
            })
            Name (EP00, Package() {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package () {
-                   Package () { "endpoint", 0 },
-                   Package () { "remote-endpoint", Package() { \_SB.PCI0.ISP, 4, 0 } },
+                   Package () { "reg", 0 },
+                   Package () { "remote-endpoint", Package() { \_SB.PCI0.ISP, "port@4", "endpoint@0" } },
                }
            })
        }
@@ -106,26 +118,26 @@ A simple example of this is show below:
            Name (_DSD, Package () {
                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
                Package () {
-                   Package () { "port4", "PRT4" },
+                   Package () { "port@4", PRT4 },
                }
            })
 
            Name (PRT4, Package() {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package () {
-                   Package () { "port", 4 }, /* CSI-2 port number */
+                   Package () { "reg", 4 }, /* CSI-2 port number */
                },
                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
                Package () {
-                   Package () { "endpoint0", "EP40" },
+                   Package () { "endpoint@0", EP40 },
                }
            })
 
            Name (EP40, Package() {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package () {
-                   Package () { "endpoint", 0 },
-                   Package () { "remote-endpoint", Package () { \_SB.PCI0.I2C2.CAM0, 0, 0 } },
+                   Package () { "reg", 0 },
+                   Package () { "remote-endpoint", Package () { \_SB.PCI0.I2C2.CAM0, "port@0", "endpoint@0" } },
                }
            })
        }
@@ -151,7 +163,7 @@ References
     referenced 2016-10-04.
 
 [5] Hierarchical Data Extension UUID For _DSD.
-    <URL:http://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.pdf>,
+    <URL:http://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf>,
     referenced 2016-10-04.
 
 [6] Advanced Configuration and Power Interface Specification.
index fefe315dc6b4d60012ccf32f2bfc8a37ca9ba968..3d6e7e7b30d5d26a056b74c112b62a75ddc4e874 100644 (file)
@@ -367,6 +367,12 @@ L: linux-acpi@vger.kernel.org
 S:     Maintained
 F:     drivers/acpi/arm64
 
+ACPI I2C MULTI INSTANTIATE DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/i2c-multi-instantiate.c
+
 ACPI PMIC DRIVERS
 M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 M:     Len Brown <lenb@kernel.org>
index b8eecc7b953135100ebc573e6f50c049aebd7d64..9ffe01d7042a0ace83fdfb271c961037aa8f9c88 100644 (file)
@@ -727,12 +727,7 @@ static const struct fault_info fault_info[] = {
 
 int handle_guest_sea(phys_addr_t addr, unsigned int esr)
 {
-       int ret = -ENOENT;
-
-       if (IS_ENABLED(CONFIG_ACPI_APEI_SEA))
-               ret = ghes_notify_sea();
-
-       return ret;
+       return ghes_notify_sea();
 }
 
 asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
index 51c386bf230d5ae024ced7de2da090f78e415da7..c5367bf5487fcf3a1ac466e990675871a7af16ae 100644 (file)
@@ -165,7 +165,6 @@ struct acpi_namespace_node {
 #define ANOBJ_EVALUATED                 0x20   /* Set on first evaluation of node */
 #define ANOBJ_ALLOCATED_BUFFER          0x40   /* Method AML buffer is dynamic (install_method) */
 
-#define IMPLICIT_EXTERNAL               0x02   /* iASL only: This object created implicitly via External */
 #define ANOBJ_IS_EXTERNAL               0x08   /* iASL only: This object created via External() */
 #define ANOBJ_METHOD_NO_RETVAL          0x10   /* iASL only: Method has no return value */
 #define ANOBJ_METHOD_SOME_NO_RETVAL     0x20   /* iASL only: Method has at least one return value */
index 220a718fbce986cafb8a31ec3d0565e72cf48d97..83a593e2155d7a71db823ab341acf903fb30cbea 100644 (file)
@@ -613,13 +613,6 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
                /* Special handling for the last segment (num_segments == 0) */
 
                else {
-#ifdef ACPI_ASL_COMPILER
-                       if (!acpi_gbl_disasm_flag
-                           && (this_node->flags & ANOBJ_IS_EXTERNAL)) {
-                               this_node->flags &= ~IMPLICIT_EXTERNAL;
-                       }
-#endif
-
                        /*
                         * Sanity typecheck of the target object:
                         *
index e9c9a63bb6a4f4218f417ab28489895c7067990d..f594ab75a5fe72cfd2be8b392dcb108edb243ad8 100644 (file)
@@ -381,7 +381,6 @@ acpi_ns_search_and_enter(u32 target_name,
        if (flags & ACPI_NS_EXTERNAL ||
            (walk_state && walk_state->opcode == AML_SCOPE_OP)) {
                new_node->flags |= ANOBJ_IS_EXTERNAL;
-               new_node->flags |= IMPLICIT_EXTERNAL;
        }
 #endif
 
index d79ad844c78fcee1e51cfa7cde066363e45f51ef..cb97b6105f5286fa6c11c8bf787a3e1b49baf52c 100644 (file)
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/async.h>
+#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/jiffies.h>
-#include <linux/async.h>
-#include <linux/dmi.h>
-#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <linux/types.h>
+
 #include <asm/unaligned.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
@@ -364,6 +364,20 @@ static enum power_supply_property energy_battery_props[] = {
        POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
+static enum power_supply_property energy_battery_full_cap_broken_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_POWER_NOW,
+       POWER_SUPPLY_PROP_ENERGY_NOW,
+       POWER_SUPPLY_PROP_MODEL_NAME,
+       POWER_SUPPLY_PROP_MANUFACTURER,
+       POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
 /* --------------------------------------------------------------------------
                                Battery Management
    -------------------------------------------------------------------------- */
@@ -577,8 +591,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
                battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
                (s16)(battery->rate_now) < 0) {
                battery->rate_now = abs((s16)battery->rate_now);
-               printk_once(KERN_WARNING FW_BUG
-                           "battery: (dis)charge rate invalid.\n");
+               pr_warn_once(FW_BUG "battery: (dis)charge rate invalid.\n");
        }
 
        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
@@ -799,6 +812,11 @@ static int sysfs_add_battery(struct acpi_battery *battery)
                battery->bat_desc.properties = charge_battery_props;
                battery->bat_desc.num_properties =
                        ARRAY_SIZE(charge_battery_props);
+       } else if (battery->full_charge_capacity == 0) {
+               battery->bat_desc.properties =
+                       energy_battery_full_cap_broken_props;
+               battery->bat_desc.num_properties =
+                       ARRAY_SIZE(energy_battery_full_cap_broken_props);
        } else {
                battery->bat_desc.properties = energy_battery_props;
                battery->bat_desc.num_properties =
@@ -918,10 +936,11 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
 
 static int acpi_battery_update(struct acpi_battery *battery, bool resume)
 {
-       int result, old_present = acpi_battery_present(battery);
-       result = acpi_battery_get_status(battery);
+       int result = acpi_battery_get_status(battery);
+
        if (result)
                return result;
+
        if (!acpi_battery_present(battery)) {
                sysfs_remove_battery(battery);
                battery->update_time = 0;
@@ -931,8 +950,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
        if (resume)
                return 0;
 
-       if (!battery->update_time ||
-           old_present != acpi_battery_present(battery)) {
+       if (!battery->update_time) {
                result = acpi_battery_get_info(battery);
                if (result)
                        return result;
@@ -1021,7 +1039,7 @@ static int acpi_battery_info_proc_show(struct seq_file *seq, void *offset)
                           acpi_battery_units(battery));
 
        seq_printf(seq, "battery technology:      %srechargeable\n",
-                  (!battery->technology)?"non-":"");
+                  battery->technology ? "" : "non-");
 
        if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
                seq_printf(seq, "design voltage:          unknown\n");
@@ -1112,11 +1130,12 @@ static int acpi_battery_alarm_proc_show(struct seq_file *seq, void *offset)
                goto end;
        }
        seq_printf(seq, "alarm:                   ");
-       if (!battery->alarm)
-               seq_printf(seq, "unsupported\n");
-       else
+       if (battery->alarm) {
                seq_printf(seq, "%u %sh\n", battery->alarm,
                                acpi_battery_units(battery));
+       } else {
+               seq_printf(seq, "unsupported\n");
+       }
       end:
        if (result)
                seq_printf(seq, "ERROR: Unable to read battery alarm\n");
@@ -1149,9 +1168,9 @@ static ssize_t acpi_battery_write_alarm(struct file *file,
        }
        result = acpi_battery_set_alarm(battery);
       end:
-       if (!result)
-               return count;
-       return result;
+       if (result)
+               return result;
+       return count;
 }
 
 static int acpi_battery_alarm_proc_open(struct inode *inode, struct file *file)
@@ -1170,8 +1189,7 @@ static const struct file_operations acpi_battery_alarm_fops = {
 
 static int acpi_battery_add_fs(struct acpi_device *device)
 {
-       printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
-                       " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
+       pr_warning(PREFIX "Deprecated procfs I/F for battery is loaded, please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
        if (!acpi_device_dir(device)) {
                acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
                                                     acpi_battery_dir);
@@ -1247,7 +1265,9 @@ static int battery_notify(struct notifier_block *nb,
                if (!acpi_battery_present(battery))
                        return 0;
 
-               if (!battery->bat) {
+               if (battery->bat) {
+                       acpi_battery_refresh(battery);
+               } else {
                        result = acpi_battery_get_info(battery);
                        if (result)
                                return result;
@@ -1255,8 +1275,7 @@ static int battery_notify(struct notifier_block *nb,
                        result = sysfs_add_battery(battery);
                        if (result)
                                return result;
-               } else
-                       acpi_battery_refresh(battery);
+               }
 
                acpi_battery_init_alarm(battery);
                acpi_battery_get_state(battery);
@@ -1398,7 +1417,7 @@ static int acpi_battery_add(struct acpi_device *device)
        }
 #endif
 
-       printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
+       pr_info(PREFIX "%s Slot [%s] (battery %s)\n",
                ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
                device->status.battery_present ? "present" : "absent");
 
index 84b4a62018eb1970e030535b1a7aa5d35b69b323..292088fcc6245ba2a683f02899750a1a70249701 100644 (file)
@@ -66,37 +66,10 @@ static int set_copy_dsdt(const struct dmi_system_id *id)
        return 0;
 }
 #endif
-static int set_gbl_term_list(const struct dmi_system_id *id)
-{
-       acpi_gbl_execute_tables_as_methods = 1;
-       return 0;
-}
 
-static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = {
-       /*
-        * Touchpad on Dell XPS 9570/Precision M5530 doesn't work under I2C
-        * mode.
-        * https://bugzilla.kernel.org/show_bug.cgi?id=198515
-        */
-       {
-               .callback = set_gbl_term_list,
-               .ident = "Dell Precision M5530",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Precision M5530"),
-               },
-       },
-       {
-               .callback = set_gbl_term_list,
-               .ident = "Dell XPS 15 9570",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9570"),
-               },
-       },
+static const struct dmi_system_id dsdt_dmi_table[] __initconst = {
        /*
         * Invoke DSDT corruption work-around on all Toshiba Satellite.
-        * DSDT will be copied to memory.
         * https://bugzilla.kernel.org/show_bug.cgi?id=14679
         */
        {
@@ -110,7 +83,7 @@ static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = {
        {}
 };
 #else
-static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = {
+static const struct dmi_system_id dsdt_dmi_table[] __initconst = {
        {}
 };
 #endif
@@ -962,7 +935,7 @@ static int acpi_device_probe(struct device *dev)
        return 0;
 }
 
-static int acpi_device_remove(struct device * dev)
+static int acpi_device_remove(struct device *dev)
 {
        struct acpi_device *acpi_dev = to_acpi_device(dev);
        struct acpi_driver *acpi_drv = acpi_dev->driver;
@@ -1060,8 +1033,11 @@ void __init acpi_early_init(void)
 
        acpi_permanent_mmap = true;
 
-       /* Check machine-specific quirks */
-       dmi_check_system(acpi_quirks_dmi_table);
+       /*
+        * If the machine falls into the DMI check table,
+        * DSDT will be copied to memory
+        */
+       dmi_check_system(dsdt_dmi_table);
 
        status = acpi_reallocate_root_table();
        if (ACPI_FAILURE(status)) {
index 2345a5ee2dbbccc9b9bb64f565b1ad5daaef8552..a19ff3977ac4ae46deac7685ef017bf482c21330 100644 (file)
@@ -21,6 +21,7 @@
 
 #define pr_fmt(fmt) "ACPI: button: " fmt
 
+#include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -235,9 +236,6 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
                button->last_time = ktime_get();
        }
 
-       if (state)
-               acpi_pm_wakeup_event(&device->dev);
-
        ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
        if (ret == NOTIFY_DONE)
                ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
@@ -252,7 +250,8 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
        return ret;
 }
 
-static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
+static int __maybe_unused acpi_button_state_seq_show(struct seq_file *seq,
+                                                    void *offset)
 {
        struct acpi_device *device = seq->private;
        int state;
@@ -366,7 +365,8 @@ int acpi_lid_open(void)
 }
 EXPORT_SYMBOL(acpi_lid_open);
 
-static int acpi_lid_update_state(struct acpi_device *device)
+static int acpi_lid_update_state(struct acpi_device *device,
+                                bool signal_wakeup)
 {
        int state;
 
@@ -374,6 +374,9 @@ static int acpi_lid_update_state(struct acpi_device *device)
        if (state < 0)
                return state;
 
+       if (state && signal_wakeup)
+               acpi_pm_wakeup_event(&device->dev);
+
        return acpi_lid_notify_state(device, state);
 }
 
@@ -384,7 +387,7 @@ static void acpi_lid_initialize_state(struct acpi_device *device)
                (void)acpi_lid_notify_state(device, 1);
                break;
        case ACPI_BUTTON_LID_INIT_METHOD:
-               (void)acpi_lid_update_state(device);
+               (void)acpi_lid_update_state(device, false);
                break;
        case ACPI_BUTTON_LID_INIT_IGNORE:
        default:
@@ -409,7 +412,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
                        users = button->input->users;
                        mutex_unlock(&button->input->mutex);
                        if (users)
-                               acpi_lid_update_state(device);
+                               acpi_lid_update_state(device, true);
                } else {
                        int keycode;
 
index 917f77f4cb556b9f4a1061c9b10dea72f8a9d81f..d4e5610e09c51beb8810a3bf5f4d42ee563288c5 100644 (file)
@@ -2045,6 +2045,20 @@ static const struct dmi_system_id acpi_ec_no_wakeup[] = {
                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Thinkpad X1 Carbon 6th"),
                },
        },
+       {
+               .ident = "ThinkPad X1 Carbon 6th",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Carbon 6th"),
+               },
+       },
+       {
+               .ident = "ThinkPad X1 Yoga 3rd",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Yoga 3rd"),
+               },
+       },
        { },
 };
 
index 8a8f43568510064571e42cf195680c30d5d46d9f..b2a16ed7e81a97da10129fcaea23ce93a4926f3c 100644 (file)
@@ -66,6 +66,14 @@ osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
         * be removed if both new and old graphics cards are supported.
         */
        {"Linux-Dell-Video", true},
+       /*
+        * Linux-Lenovo-NV-HDMI-Audio is used by BIOS to power on NVidia's HDMI
+        * audio device which is turned off for power-saving in Windows OS.
+        * This power management feature observed on some Lenovo Thinkpad
+        * systems which will not be able to output audio via HDMI without
+        * a BIOS workaround.
+        */
+       {"Linux-Lenovo-NV-HDMI-Audio", true},
 };
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
index 5815356ea6ad3fb584a63e4ebf076d09fda635d8..693cf05b0cc44ffba54427fa12abf3017830e0e1 100644 (file)
@@ -542,6 +542,23 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data,
        return 0;
 }
 
+static struct fwnode_handle *
+acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
+                                const char *childname)
+{
+       struct fwnode_handle *child;
+
+       /*
+        * Find first matching named child node of this fwnode.
+        * For ACPI this will be a data only sub-node.
+        */
+       fwnode_for_each_child_node(fwnode, child)
+               if (acpi_data_node_match(child, childname))
+                       return child;
+
+       return NULL;
+}
+
 /**
  * __acpi_node_get_property_reference - returns handle to the referenced object
  * @fwnode: Firmware node to get the property from
@@ -579,7 +596,7 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data,
  */
 int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
        const char *propname, size_t index, size_t num_args,
-       struct acpi_reference_args *args)
+       struct fwnode_reference_args *args)
 {
        const union acpi_object *element, *end;
        const union acpi_object *obj;
@@ -607,7 +624,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                if (ret)
                        return ret == -ENODEV ? -EINVAL : ret;
 
-               args->adev = device;
+               args->fwnode = acpi_fwnode_handle(device);
                args->nargs = 0;
                return 0;
        }
@@ -633,6 +650,8 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                u32 nargs, i;
 
                if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
+                       struct fwnode_handle *ref_fwnode;
+
                        ret = acpi_bus_get_device(element->reference.handle,
                                                  &device);
                        if (ret)
@@ -641,6 +660,19 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                        nargs = 0;
                        element++;
 
+                       /*
+                        * Find the referred data extension node under the
+                        * referred device node.
+                        */
+                       for (ref_fwnode = acpi_fwnode_handle(device);
+                            element < end && element->type == ACPI_TYPE_STRING;
+                            element++) {
+                               ref_fwnode = acpi_fwnode_get_named_child_node(
+                                       ref_fwnode, element->string.pointer);
+                               if (!ref_fwnode)
+                                       return -EINVAL;
+                       }
+
                        /* assume following integer elements are all args */
                        for (i = 0; element + i < end && i < num_args; i++) {
                                int type = element[i].type;
@@ -653,11 +685,11 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                                        return -EINVAL;
                        }
 
-                       if (nargs > MAX_ACPI_REFERENCE_ARGS)
+                       if (nargs > NR_FWNODE_REFERENCE_ARGS)
                                return -EINVAL;
 
                        if (idx == index) {
-                               args->adev = device;
+                               args->fwnode = ref_fwnode;
                                args->nargs = nargs;
                                for (i = 0; i < nargs; i++)
                                        args->args[i] = element[i].integer.value;
@@ -995,16 +1027,36 @@ struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode)
        return NULL;
 }
 
+/*
+ * Return true if the node is an ACPI graph node. Called on either ports
+ * or endpoints.
+ */
+static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
+                              const char *str)
+{
+       unsigned int len = strlen(str);
+       const char *name;
+
+       if (!len || !is_acpi_data_node(fwnode))
+               return false;
+
+       name = to_acpi_data_node(fwnode)->name;
+
+       return (fwnode_property_present(fwnode, "reg") &&
+               !strncmp(name, str, len) && name[len] == '@') ||
+               fwnode_property_present(fwnode, str);
+}
+
 /**
  * acpi_graph_get_next_endpoint - Get next endpoint ACPI firmware node
  * @fwnode: Pointer to the parent firmware node
  * @prev: Previous endpoint node or %NULL to get the first
  *
  * Looks up next endpoint ACPI firmware node below a given @fwnode. Returns
- * %NULL if there is no next endpoint, ERR_PTR() in case of error. In case
- * of success the next endpoint is returned.
+ * %NULL if there is no next endpoint or in case of error. In case of success
+ * the next endpoint is returned.
  */
-struct fwnode_handle *acpi_graph_get_next_endpoint(
+static struct fwnode_handle *acpi_graph_get_next_endpoint(
        const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
 {
        struct fwnode_handle *port = NULL;
@@ -1013,8 +1065,14 @@ struct fwnode_handle *acpi_graph_get_next_endpoint(
        if (!prev) {
                do {
                        port = fwnode_get_next_child_node(fwnode, port);
-                       /* Ports must have port property */
-                       if (fwnode_property_present(port, "port"))
+                       /*
+                        * The names of the port nodes begin with "port@"
+                        * followed by the number of the port node and they also
+                        * have a "reg" property that also has the number of the
+                        * port node. For compatibility reasons a node is also
+                        * recognised as a port node from the "port" property.
+                        */
+                       if (is_acpi_graph_node(port, "port"))
                                break;
                } while (port);
        } else {
@@ -1029,15 +1087,19 @@ struct fwnode_handle *acpi_graph_get_next_endpoint(
                port = fwnode_get_next_child_node(fwnode, port);
                if (!port)
                        break;
-               if (fwnode_property_present(port, "port"))
+               if (is_acpi_graph_node(port, "port"))
                        endpoint = fwnode_get_next_child_node(port, NULL);
        }
 
-       if (endpoint) {
-               /* Endpoints must have "endpoint" property */
-               if (!fwnode_property_present(endpoint, "endpoint"))
-                       return ERR_PTR(-EPROTO);
-       }
+       /*
+        * The names of the endpoint nodes begin with "endpoint@" followed by
+        * the number of the endpoint node and they also have a "reg" property
+        * that also has the number of the endpoint node. For compatibility
+        * reasons a node is also recognised as an endpoint node from the
+        * "endpoint" property.
+        */
+       if (!is_acpi_graph_node(endpoint, "endpoint"))
+               return NULL;
 
        return endpoint;
 }
@@ -1074,65 +1136,42 @@ static struct fwnode_handle *acpi_graph_get_child_prop_value(
 /**
  * acpi_graph_get_remote_enpoint - Parses and returns remote end of an endpoint
  * @fwnode: Endpoint firmware node pointing to a remote device
- * @parent: Firmware node of remote port parent is filled here if not %NULL
- * @port: Firmware node of remote port is filled here if not %NULL
  * @endpoint: Firmware node of remote endpoint is filled here if not %NULL
  *
- * Function parses remote end of ACPI firmware remote endpoint and fills in
- * fields requested by the caller. Returns %0 in case of success and
- * negative errno otherwise.
+ * Returns the remote endpoint corresponding to @__fwnode. NULL on error.
  */
-int acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode,
-                                  struct fwnode_handle **parent,
-                                  struct fwnode_handle **port,
-                                  struct fwnode_handle **endpoint)
+static struct fwnode_handle *
+acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
 {
        struct fwnode_handle *fwnode;
        unsigned int port_nr, endpoint_nr;
-       struct acpi_reference_args args;
+       struct fwnode_reference_args args;
        int ret;
 
        memset(&args, 0, sizeof(args));
        ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
                                               &args);
        if (ret)
-               return ret;
+               return NULL;
+
+       /* Direct endpoint reference? */
+       if (!is_acpi_device_node(args.fwnode))
+               return args.nargs ? NULL : args.fwnode;
 
        /*
         * Always require two arguments with the reference: port and
         * endpoint indices.
         */
        if (args.nargs != 2)
-               return -EPROTO;
+               return NULL;
 
-       fwnode = acpi_fwnode_handle(args.adev);
+       fwnode = args.fwnode;
        port_nr = args.args[0];
        endpoint_nr = args.args[1];
 
-       if (parent)
-               *parent = fwnode;
-
-       if (!port && !endpoint)
-               return 0;
-
        fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
-       if (!fwnode)
-               return -EPROTO;
-
-       if (port)
-               *port = fwnode;
-
-       if (!endpoint)
-               return 0;
 
-       fwnode = acpi_graph_get_child_prop_value(fwnode, "endpoint",
-                                                endpoint_nr);
-       if (!fwnode)
-               return -EPROTO;
-
-       *endpoint = fwnode;
-
-       return 0;
+       return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
 }
 
 static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
@@ -1186,70 +1225,14 @@ acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
                                   val, nval);
 }
 
-static struct fwnode_handle *
-acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
-                                const char *childname)
-{
-       struct fwnode_handle *child;
-
-       /*
-        * Find first matching named child node of this fwnode.
-        * For ACPI this will be a data only sub-node.
-        */
-       fwnode_for_each_child_node(fwnode, child)
-               if (acpi_data_node_match(child, childname))
-                       return child;
-
-       return NULL;
-}
-
 static int
 acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
                               const char *prop, const char *nargs_prop,
                               unsigned int args_count, unsigned int index,
                               struct fwnode_reference_args *args)
 {
-       struct acpi_reference_args acpi_args;
-       unsigned int i;
-       int ret;
-
-       ret = __acpi_node_get_property_reference(fwnode, prop, index,
-                                                args_count, &acpi_args);
-       if (ret < 0)
-               return ret;
-       if (!args)
-               return 0;
-
-       args->nargs = acpi_args.nargs;
-       args->fwnode = acpi_fwnode_handle(acpi_args.adev);
-
-       for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++)
-               args->args[i] = i < acpi_args.nargs ? acpi_args.args[i] : 0;
-
-       return 0;
-}
-
-static struct fwnode_handle *
-acpi_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
-                                   struct fwnode_handle *prev)
-{
-       struct fwnode_handle *endpoint;
-
-       endpoint = acpi_graph_get_next_endpoint(fwnode, prev);
-       if (IS_ERR(endpoint))
-               return NULL;
-
-       return endpoint;
-}
-
-static struct fwnode_handle *
-acpi_fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
-{
-       struct fwnode_handle *endpoint = NULL;
-
-       acpi_graph_get_remote_endpoint(fwnode, NULL, NULL, &endpoint);
-
-       return endpoint;
+       return __acpi_node_get_property_reference(fwnode, prop, index,
+                                                 args_count, args);
 }
 
 static struct fwnode_handle *
@@ -1265,8 +1248,10 @@ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
 
        endpoint->local_fwnode = fwnode;
 
-       fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
-       fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
+       if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
+               fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
+       if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
+               fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
 
        return 0;
 }
@@ -1292,9 +1277,9 @@ acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
                .get_named_child_node = acpi_fwnode_get_named_child_node, \
                .get_reference_args = acpi_fwnode_get_reference_args,   \
                .graph_get_next_endpoint =                              \
-                       acpi_fwnode_graph_get_next_endpoint,            \
+                       acpi_graph_get_next_endpoint,                   \
                .graph_get_remote_endpoint =                            \
-                       acpi_fwnode_graph_get_remote_endpoint,          \
+                       acpi_graph_get_remote_endpoint,                 \
                .graph_get_port_parent = acpi_fwnode_get_parent,        \
                .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
        };                                                              \
index 970dd87d347c786fbc25922464e6bc20c1dbb4ee..e1b6231cfa1c5b642e3b0ee78e81ff1c01278bb3 100644 (file)
@@ -1528,7 +1528,7 @@ static int acpi_check_serial_bus_slave(struct acpi_resource *ares, void *data)
 static bool acpi_is_indirect_io_slave(struct acpi_device *device)
 {
        struct acpi_device *parent = device->parent;
-       const struct acpi_device_id indirect_io_hosts[] = {
+       static const struct acpi_device_id indirect_io_hosts[] = {
                {"HISI0191", 0},
                {}
        };
@@ -1540,6 +1540,18 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
 {
        struct list_head resource_list;
        bool is_serial_bus_slave = false;
+       /*
+        * These devices have multiple I2cSerialBus resources and an i2c-client
+        * must be instantiated for each, each with its own i2c_device_id.
+        * Normally we only instantiate an i2c-client for the first resource,
+        * using the ACPI HID as id. These special cases are handled by the
+        * drivers/platform/x86/i2c-multi-instantiate.c driver, which knows
+        * which i2c_device_id to use for each resource.
+        */
+       static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
+               {"BSG1160", },
+               {}
+       };
 
        if (acpi_is_indirect_io_slave(device))
                return true;
@@ -1551,6 +1563,10 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
             fwnode_property_present(&device->fwnode, "baud")))
                return true;
 
+       /* Instantiate a pdev for the i2c-multi-instantiate drv to bind to */
+       if (!acpi_match_device_ids(device, i2c_multi_instantiate_ids))
+               return false;
+
        INIT_LIST_HEAD(&resource_list);
        acpi_dev_get_resources(device, &resource_list,
                               acpi_check_serial_bus_slave,
@@ -1612,7 +1628,8 @@ static int acpi_add_single_object(struct acpi_device **child,
         * Note this must be done before the get power-/wakeup_dev-flags calls.
         */
        if (type == ACPI_BUS_TYPE_DEVICE)
-               acpi_bus_get_status(device);
+               if (acpi_bus_get_status(device) < 0)
+                       acpi_set_device_status(device, 0);
 
        acpi_bus_get_power_flags(device);
        acpi_bus_get_wakeup_device_flags(device);
@@ -1690,7 +1707,7 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
                 * acpi_add_single_object updates this once we've an acpi_device
                 * so that acpi_bus_get_status' quirk handling can be used.
                 */
-               *sta = 0;
+               *sta = ACPI_STA_DEFAULT;
                break;
        case ACPI_TYPE_PROCESSOR:
                *type = ACPI_BUS_TYPE_PROCESSOR;
index ec5b0f190231c8b6ce6a98d99ae33347ad51054a..06c31ec3cc705d0abb4f86da90e64a3930c2154d 100644 (file)
@@ -62,14 +62,20 @@ static const struct always_present_id always_present_ids[] = {
         */
        ENTRY("INT0002", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}),
        /*
-        * On the Dell Venue 11 Pro 7130 the DSDT hides the touchscreen ACPI
-        * device until a certain time after _SB.PCI0.GFX0.LCD.LCD1._ON gets
-        * called has passed *and* _STA has been called at least 3 times since.
+        * On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides
+        * the touchscreen ACPI device until a certain time
+        * after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed
+        * *and* _STA has been called at least 3 times since.
         */
        ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
                DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
                DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
              }),
+       ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
+               DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
+             }),
+
        /*
         * The GPD win BIOS dated 20170221 has disabled the accelerometer, the
         * drivers sometimes cause crashes under Windows and this is how the
@@ -103,13 +109,9 @@ static const struct always_present_id always_present_ids[] = {
 
 bool acpi_device_always_present(struct acpi_device *adev)
 {
-       u32 *status = (u32 *)&adev->status;
-       u32 old_status = *status;
        bool ret = false;
        unsigned int i;
 
-       /* acpi_match_device_ids checks status, so set it to default */
-       *status = ACPI_STA_DEFAULT;
        for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) {
                if (acpi_match_device_ids(adev, always_present_ids[i].hid))
                        continue;
@@ -125,15 +127,9 @@ bool acpi_device_always_present(struct acpi_device *adev)
                    !dmi_check_system(always_present_ids[i].dmi_ids))
                        continue;
 
-               if (old_status != ACPI_STA_DEFAULT) /* Log only once */
-                       dev_info(&adev->dev,
-                                "Device [%s] is in always present list\n",
-                                adev->pnp.bus_id);
-
                ret = true;
                break;
        }
-       *status = old_status;
 
        return ret;
 }
index addd9fecc198360d03a4cfb420e1e2d6ecf90a67..c48ed9d89ff5f7b74eb03fb7ee079fa2b18e0dcf 100644 (file)
@@ -389,7 +389,7 @@ EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios);
 
 static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
                                      const char *name, int index,
-                                     struct acpi_reference_args *args,
+                                     struct fwnode_reference_args *args,
                                      unsigned int *quirks)
 {
        const struct acpi_gpio_mapping *gm;
@@ -401,7 +401,7 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
                if (!strcmp(name, gm->name) && gm->data && index < gm->size) {
                        const struct acpi_gpio_params *par = gm->data + index;
 
-                       args->adev = adev;
+                       args->fwnode = acpi_fwnode_handle(adev);
                        args->args[0] = par->crs_entry_index;
                        args->args[1] = par->line_index;
                        args->args[2] = par->active_low;
@@ -564,7 +564,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
                                     const char *propname, int index,
                                     struct acpi_gpio_lookup *lookup)
 {
-       struct acpi_reference_args args;
+       struct fwnode_reference_args args;
        unsigned int quirks = 0;
        int ret;
 
@@ -585,6 +585,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
         * The property was found and resolved, so need to lookup the GPIO based
         * on returned args.
         */
+       if (!to_acpi_device_node(args.fwnode))
+               return -EINVAL;
        if (args.nargs != 3)
                return -EPROTO;
 
@@ -592,8 +594,9 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
        lookup->pin_index = args.args[1];
        lookup->active_low = !!args.args[2];
 
-       lookup->info.adev = args.adev;
+       lookup->info.adev = to_acpi_device_node(args.fwnode);
        lookup->info.quirks = quirks;
+
        return 0;
 }
 
index 8013d69c5ac496fe5ddaa10b9e48ef80f5db3c5e..8444234ed092f8c4a7dc82a66da341ed5e93df39 100644 (file)
@@ -1435,7 +1435,7 @@ static int hns_roce_v1_reset(struct hns_roce_dev *hr_dev, bool dereset)
                }
                fwnode = &dsaf_node->fwnode;
        } else if (is_acpi_device_node(dev->fwnode)) {
-               struct acpi_reference_args args;
+               struct fwnode_reference_args args;
 
                ret = acpi_node_get_property_reference(dev->fwnode,
                                                       "dsaf-handle", 0, &args);
@@ -1443,7 +1443,7 @@ static int hns_roce_v1_reset(struct hns_roce_dev *hr_dev, bool dereset)
                        dev_err(dev, "could not find dsaf-handle\n");
                        return ret;
                }
-               fwnode = acpi_fwnode_handle(args.adev);
+               fwnode = args.fwnode;
        } else {
                dev_err(dev, "cannot read data from DT or ACPI\n");
                return -ENXIO;
@@ -4835,16 +4835,14 @@ static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev)
                                continue;
                        pdev = of_find_device_by_node(net_node);
                } else if (is_acpi_device_node(dev->fwnode)) {
-                       struct acpi_reference_args args;
-                       struct fwnode_handle *fwnode;
+                       struct fwnode_reference_args args;
 
                        ret = acpi_node_get_property_reference(dev->fwnode,
                                                               "eth-handle",
                                                               i, &args);
                        if (ret)
                                continue;
-                       fwnode = acpi_fwnode_handle(args.adev);
-                       pdev = hns_roce_find_pdev(fwnode);
+                       pdev = hns_roce_find_pdev(args.fwnode);
                } else {
                        dev_err(dev, "cannot read data from DT or ACPI\n");
                        return -ENXIO;
index 3f77aa3180357616b9631095fbbfcc3a7ffc13e4..82595cebc0b8c11354c3726b537fae7c1fce7937 100644 (file)
@@ -739,7 +739,7 @@ static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop(
        const char * const *props, unsigned int nprops)
 {
        struct fwnode_reference_args fwnode_args;
-       unsigned int *args = fwnode_args.args;
+       u64 *args = fwnode_args.args;
        struct fwnode_handle *child;
        int ret;
 
index 3188f553da35f7e4aeebcba2cdaffcc64ba6a3e1..078a04dc1182e9f6fe9d1316652307d7b9c5dc77 100644 (file)
@@ -836,19 +836,19 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
 #ifdef CONFIG_ACPI
 static struct acpi_device *acpi_phy_find_device(struct device *dev)
 {
-       struct acpi_reference_args args;
+       struct fwnode_reference_args args;
        struct fwnode_handle *fw_node;
        int status;
 
        fw_node = acpi_fwnode_handle(ACPI_COMPANION(dev));
        status = acpi_node_get_property_reference(fw_node, "phy-handle", 0,
                                                  &args);
-       if (ACPI_FAILURE(status)) {
+       if (ACPI_FAILURE(status) || !is_acpi_device_node(args.fwnode)) {
                dev_dbg(dev, "No matching phy in ACPI table\n");
                return NULL;
        }
 
-       return args.adev;
+       return to_acpi_device_node(args.fwnode);
 }
 #endif
 
index 9dcc5765f11fabf48dca14660047ceb19d3c8b49..794516718d9deaba84799ff86b64ff76cebaefd6 100644 (file)
@@ -708,7 +708,7 @@ hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb,
 
 static int hns_mac_register_phy(struct hns_mac_cb *mac_cb)
 {
-       struct acpi_reference_args args;
+       struct fwnode_reference_args args;
        struct platform_device *pdev;
        struct mii_bus *mii_bus;
        int rc;
@@ -722,13 +722,15 @@ static int hns_mac_register_phy(struct hns_mac_cb *mac_cb)
                        mac_cb->fw_port, "mdio-node", 0, &args);
        if (rc)
                return rc;
+       if (!is_acpi_device_node(args.fwnode))
+               return -EINVAL;
 
        addr = hns_mac_phy_parse_addr(mac_cb->dev, mac_cb->fw_port);
        if (addr < 0)
                return addr;
 
        /* dev address in adev */
-       pdev = hns_dsaf_find_platform_device(acpi_fwnode_handle(args.adev));
+       pdev = hns_dsaf_find_platform_device(args.fwnode);
        if (!pdev) {
                dev_err(mac_cb->dev, "mac%d mdio pdev is NULL\n",
                        mac_cb->mac_id);
index ef9ef703d13a0e0efff11404afb41532f571283f..5608f807d7ba427ac81c24efd325ccb4108a368d 100644 (file)
@@ -2377,7 +2377,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
                }
                priv->fwnode = &ae_node->fwnode;
        } else if (is_acpi_node(dev->fwnode)) {
-               struct acpi_reference_args args;
+               struct fwnode_reference_args args;
 
                if (acpi_dev_found(hns_enet_acpi_match[0].id))
                        priv->enet_ver = AE_VERSION_1;
@@ -2393,7 +2393,11 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
                        dev_err(dev, "not find ae-handle\n");
                        goto out_read_prop_fail;
                }
-               priv->fwnode = acpi_fwnode_handle(args.adev);
+               if (!is_acpi_device_node(args.fwnode)) {
+                       ret = -EINVAL;
+                       goto out_read_prop_fail;
+               }
+               priv->fwnode = args.fwnode;
        } else {
                dev_err(dev, "cannot read cfg data from OF or acpi\n");
                return -ENXIO;
index ac4d4883041537c3f4c6124acd6b52f141b6c89a..107d336453b2c3d15d804ba75ad843dc765a2e93 100644 (file)
@@ -1218,6 +1218,17 @@ config INTEL_CHTDC_TI_PWRBTN
          To compile this driver as a module, choose M here: the module
          will be called intel_chtdc_ti_pwrbtn.
 
+config I2C_MULTI_INSTANTIATE
+       tristate "I2C multi instantiate pseudo device driver"
+       depends on I2C && ACPI
+       help
+         Some ACPI-based systems list multiple i2c-devices in a single ACPI
+         firmware-node. This driver will instantiate separate i2c-clients
+         for each device in the firmware-node.
+
+         To compile this driver as a module, choose M here: the module
+         will be called i2c-multi-instantiate.
+
 endif # X86_PLATFORM_DEVICES
 
 config PMC_ATOM
index 2ba6cb7953384e8af9b150adca7775c3bea6ec29..50dc8f2809144cf23491b1ee473e874b7decc00f 100644 (file)
@@ -91,3 +91,4 @@ obj-$(CONFIG_PMC_ATOM)                += pmc_atom.o
 obj-$(CONFIG_MLX_PLATFORM)     += mlx-platform.o
 obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
 obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN)    += intel_chtdc_ti_pwrbtn.o
+obj-$(CONFIG_I2C_MULTI_INSTANTIATE)    += i2c-multi-instantiate.o
diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
new file mode 100644 (file)
index 0000000..5456581
--- /dev/null
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * I2C multi-instantiate driver, pseudo driver to instantiate multiple
+ * i2c-clients from a single fwnode.
+ *
+ * Copyright 2018 Hans de Goede <hdegoede@redhat.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+struct i2c_inst_data {
+       const char *type;
+       int gpio_irq_idx;
+};
+
+struct i2c_multi_inst_data {
+       int num_clients;
+       struct i2c_client *clients[0];
+};
+
+static int i2c_multi_inst_probe(struct platform_device *pdev)
+{
+       struct i2c_multi_inst_data *multi;
+       const struct acpi_device_id *match;
+       const struct i2c_inst_data *inst_data;
+       struct i2c_board_info board_info = {};
+       struct device *dev = &pdev->dev;
+       struct acpi_device *adev;
+       char name[32];
+       int i, ret;
+
+       match = acpi_match_device(dev->driver->acpi_match_table, dev);
+       if (!match) {
+               dev_err(dev, "Error ACPI match data is missing\n");
+               return -ENODEV;
+       }
+       inst_data = (const struct i2c_inst_data *)match->driver_data;
+
+       adev = ACPI_COMPANION(dev);
+
+       /* Count number of clients to instantiate */
+       for (i = 0; inst_data[i].type; i++) {}
+
+       multi = devm_kmalloc(dev,
+                       offsetof(struct i2c_multi_inst_data, clients[i]),
+                       GFP_KERNEL);
+       if (!multi)
+               return -ENOMEM;
+
+       multi->num_clients = i;
+
+       for (i = 0; i < multi->num_clients; i++) {
+               memset(&board_info, 0, sizeof(board_info));
+               strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE);
+               snprintf(name, sizeof(name), "%s-%s", match->id,
+                        inst_data[i].type);
+               board_info.dev_name = name;
+               board_info.irq = 0;
+               if (inst_data[i].gpio_irq_idx != -1) {
+                       ret = acpi_dev_gpio_irq_get(adev,
+                                                   inst_data[i].gpio_irq_idx);
+                       if (ret < 0) {
+                               dev_err(dev, "Error requesting irq at index %d: %d\n",
+                                       inst_data[i].gpio_irq_idx, ret);
+                               goto error;
+                       }
+                       board_info.irq = ret;
+               }
+               multi->clients[i] = i2c_acpi_new_device(dev, i, &board_info);
+               if (!multi->clients[i]) {
+                       dev_err(dev, "Error creating i2c-client, idx %d\n", i);
+                       ret = -ENODEV;
+                       goto error;
+               }
+       }
+
+       platform_set_drvdata(pdev, multi);
+       return 0;
+
+error:
+       while (--i >= 0)
+               i2c_unregister_device(multi->clients[i]);
+
+       return ret;
+}
+
+static int i2c_multi_inst_remove(struct platform_device *pdev)
+{
+       struct i2c_multi_inst_data *multi = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < multi->num_clients; i++)
+               i2c_unregister_device(multi->clients[i]);
+
+       return 0;
+}
+
+static const struct i2c_inst_data bsg1160_data[]  = {
+       { "bmc150_accel", 0 },
+       { "bmc150_magn", -1 },
+       { "bmg160", -1 },
+       {}
+};
+
+/*
+ * Note new device-ids must also be added to i2c_multi_instantiate_ids in
+ * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
+ */
+static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
+       { "BSG1160", (unsigned long)bsg1160_data },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
+
+static struct platform_driver i2c_multi_inst_driver = {
+       .driver = {
+               .name = "I2C multi instantiate pseudo device driver",
+               .acpi_match_table = ACPI_PTR(i2c_multi_inst_acpi_ids),
+       },
+       .probe = i2c_multi_inst_probe,
+       .remove = i2c_multi_inst_remove,
+};
+module_platform_driver(i2c_multi_inst_driver);
+
+MODULE_DESCRIPTION("I2C multi instantiate pseudo device driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
index 48d84f0d9547ad8d2c24057a9e780e74dec8045c..88072c92ace25af8a89b0966adf07018b914ca24 100644 (file)
@@ -12,7 +12,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20180531
+#define ACPI_CA_VERSION                 0x20180629
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index 1624e2be485c7012dbd39ffadf9520480a0cc5e8..82cb4eb225a4dfac0d129b4b0b565ea890e44046 100644 (file)
@@ -118,6 +118,10 @@ static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata)
             (void *)section - (void *)(estatus + 1) < estatus->data_length; \
             section = acpi_hest_get_next(section))
 
+#ifdef CONFIG_ACPI_APEI_SEA
 int ghes_notify_sea(void);
+#else
+static inline int ghes_notify_sea(void) { return -ENOENT; }
+#endif
 
 #endif /* GHES_H */
index e54f40974eb04ca516987ac3df89b0997b5ca0dd..de8d3d3fa6512e3e9382e23cf4fcd03c36b77097 100644 (file)
@@ -1058,27 +1058,20 @@ static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 
 /* Device properties */
 
-#define MAX_ACPI_REFERENCE_ARGS        8
-struct acpi_reference_args {
-       struct acpi_device *adev;
-       size_t nargs;
-       u64 args[MAX_ACPI_REFERENCE_ARGS];
-};
-
 #ifdef CONFIG_ACPI
 int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
                          acpi_object_type type, const union acpi_object **obj);
 int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                                const char *name, size_t index, size_t num_args,
-                               struct acpi_reference_args *args);
+                               struct fwnode_reference_args *args);
 
 static inline int acpi_node_get_property_reference(
                                const struct fwnode_handle *fwnode,
                                const char *name, size_t index,
-                               struct acpi_reference_args *args)
+                               struct fwnode_reference_args *args)
 {
        return __acpi_node_get_property_reference(fwnode, name, index,
-               MAX_ACPI_REFERENCE_ARGS, args);
+               NR_FWNODE_REFERENCE_ARGS, args);
 }
 
 int acpi_node_prop_get(const struct fwnode_handle *fwnode, const char *propname,
@@ -1096,14 +1089,6 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
                                            struct fwnode_handle *child);
 struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode);
 
-struct fwnode_handle *
-acpi_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
-                            struct fwnode_handle *prev);
-int acpi_graph_get_remote_endpoint(const struct fwnode_handle *fwnode,
-                                  struct fwnode_handle **remote,
-                                  struct fwnode_handle **port,
-                                  struct fwnode_handle **endpoint);
-
 struct acpi_probe_entry;
 typedef bool (*acpi_probe_entry_validate_subtbl)(struct acpi_subtable_header *,
                                                 struct acpi_probe_entry *);
@@ -1169,7 +1154,7 @@ static inline int acpi_dev_get_property(struct acpi_device *adev,
 static inline int
 __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                                const char *name, size_t index, size_t num_args,
-                               struct acpi_reference_args *args)
+                               struct fwnode_reference_args *args)
 {
        return -ENXIO;
 }
@@ -1177,7 +1162,7 @@ __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
 static inline int
 acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                                 const char *name, size_t index,
-                                struct acpi_reference_args *args)
+                                struct fwnode_reference_args *args)
 {
        return -ENXIO;
 }
index 4fe8f289b3f6f01d3b5ad94676e2239d208e5229..faebf0ca0686ce05bab67aa242767c8cdf098d39 100644 (file)
@@ -45,7 +45,7 @@ struct fwnode_endpoint {
 struct fwnode_reference_args {
        struct fwnode_handle *fwnode;
        unsigned int nargs;
-       unsigned int args[NR_FWNODE_REFERENCE_ARGS];
+       u64 args[NR_FWNODE_REFERENCE_ARGS];
 };
 
 /**