linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/8]  ACPI overlays
@ 2016-07-01 20:19 Octavian Purdila
  2016-07-01 20:19 ` [PATCH v5 1/8] Documentation: acpi: add SSDT overlays documentation Octavian Purdila
                   ` (8 more replies)
  0 siblings, 9 replies; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

This patch set enables custom ACPI board configuration by adding
mechanisms in the Linux kernel for loading user defined SSDTs.

In order to support ACPI open-ended hardware configurations we need a
way to augment the ACPI configuration provided by the firmware
image. A common example is connecting sensors on I2C / SPI buses on
development boards.

Although this can be accomplished by creating a kernel platform driver
or recompiling the firmware image with updated ACPI tables, neither is
practical: the former proliferates board specific kernel code while
the latter requires access to firmware tools which are often not
publicly available.

Because ACPI supports external references in AML code a more practical
way to augment firmware ACPI configuration is by dynamically loading
user defined SSDT tables that contain the board specific information.

Currently it is possible to load SSDT overlays using the upgrade
initrd mechanism introduced in 4.7. This patch series adds support for
two more methods:

* From an EFI variable

 This is the preferred method, when EFI is supported on the platform,
 because it allows a persistent, OS independent way of storing and
 updating the user defined SSDTs. There is also work underway to
 implement EFI support for loading user defined SSDTs and using this
 method will make it easier to convert to the EFI loading mechanism
 when that will arrive.

* From userspace via configfs

 This is useful when we want to defer the operation to userspace for
 platform detection, loading the SSDTs from a custom partition, etc.


Changes from v4:

* EFI: use ucs2_as_utf8 and memcmp to check if the variable name
  matches the kernel command line parameter; fold the EFI ACPI table
  load code in the iterator function

* I2C/SPI: add more information in the commit logs about how the
  enumeration status is set and checked; also add a new check of the
  enumerated status for the ACPI device remove reconfiguration
  notification

Changes from v3:

* fix a bisectability issue reported by kbuild

* rework the enumeration fix to support PRP0001 enumeration; also,
  introduce acpi_device_set/clear_enumerated() for clarity

* clear the enumerated status for acpi_device when the I2C/SPI clients
  are removed (for example as a result of an adapter removal) to allow
  the devices to be re-enumerated later

Changes from v2:

* fix a few issues caught by the kbuild test robot

* add more configfs table attributes

* removed the initrd based loading functionality from this patch set
  as this can already be accomplished in 4.7 using the ACPI table
  upgrade mechanism

* rebased to 4.7-rc3

Changes from v1:

* rebased on top of the ACPI install from initrd table functionality;
  there is significant overlap between the 1st patch in this series
  and these patch [1] from Lv - I kept it in this series until the
  discussions around the taint and config option are resolved

* make sure EFI_RUNTIME_SERVICES are available before trying to use
  EFI variables to load tables

* rework the ACPI reconfiguration notifications to work on device
  granularity (device added or removed) instead of table granularity
  (table loaded or unloaded)

* add support for table unloading / device removal

* note that the last patch is just a hack to be able to test the table
  unload / device remove functionality, if someone wants to try out
  this patch set

[1] https://patchwork.kernel.org/patch/8795931/

Octavian Purdila (8):
  Documentation: acpi: add SSDT overlays documentation
  acpi: fix enumeration (visited) flags for bus rescans
  acpi: add support for ACPI reconfiguration notifiers
  i2c: add support for ACPI reconfigure notifications
  spi: add support for ACPI reconfigure notifications
  efi: load SSTDs from EFI variables
  acpi: add support for configfs
  acpi: add support for loading SSDTs via configfs

 Documentation/ABI/testing/configfs-acpi |  36 +++++
 Documentation/acpi/ssdt-overlays.txt    | 172 ++++++++++++++++++++
 Documentation/kernel-parameters.txt     |   7 +
 MAINTAINERS                             |   1 +
 drivers/acpi/Kconfig                    |   9 ++
 drivers/acpi/Makefile                   |   1 +
 drivers/acpi/bus.c                      |   9 ++
 drivers/acpi/configfs.c                 | 267 ++++++++++++++++++++++++++++++++
 drivers/acpi/internal.h                 |   3 +
 drivers/acpi/scan.c                     |  81 +++++++++-
 drivers/acpi/sysfs.c                    |   6 +-
 drivers/firmware/efi/efi.c              |  85 ++++++++++
 drivers/i2c/i2c-core.c                  | 175 ++++++++++++++++-----
 drivers/spi/spi.c                       | 100 +++++++++++-
 include/linux/acpi.h                    |  36 +++++
 15 files changed, 932 insertions(+), 56 deletions(-)
 create mode 100644 Documentation/ABI/testing/configfs-acpi
 create mode 100644 Documentation/acpi/ssdt-overlays.txt
 create mode 100644 drivers/acpi/configfs.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v5 1/8] Documentation: acpi: add SSDT overlays documentation
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
@ 2016-07-01 20:19 ` Octavian Purdila
  2016-07-07  9:25   ` Mika Westerberg
  2016-07-01 20:19 ` [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans Octavian Purdila
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 Documentation/acpi/ssdt-overlays.txt | 91 ++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 Documentation/acpi/ssdt-overlays.txt

diff --git a/Documentation/acpi/ssdt-overlays.txt b/Documentation/acpi/ssdt-overlays.txt
new file mode 100644
index 0000000..8050259
--- /dev/null
+++ b/Documentation/acpi/ssdt-overlays.txt
@@ -0,0 +1,91 @@
+
+In order to support ACPI open-ended hardware configurations (e.g. development
+boards) we need a way to augment the ACPI configuration provided by the firmware
+image. A common example is connecting sensors on I2C / SPI buses on development
+boards.
+
+Although this can be accomplished by creating a kernel platform driver or
+recompiling the firmware image with updated ACPI tables, neither is practical:
+the former proliferates board specific kernel code while the latter requires
+access to firmware tools which are often not publicly available.
+
+Because ACPI supports external references in AML code a more practical
+way to augment firmware ACPI configuration is by dynamically loading
+user defined SSDT tables that contain the board specific information.
+
+For example, to enumerate a Bosch BMA222E accelerometer on the I2C bus of the
+Minnowboard MAX development board exposed via the LSE connector [1], the
+following ASL code can be used:
+
+DefinitionBlock ("minnowmax.aml", "SSDT", 1, "Vendor", "Accel", 0x00000003)
+{
+    External (\_SB.I2C6, DeviceObj)
+
+    Scope (\_SB.I2C6)
+    {
+        Device (STAC)
+        {
+            Name (_ADR, Zero)
+            Name (_HID, "BMA222E")
+
+            Method (_CRS, 0, Serialized)
+            {
+                Name (RBUF, ResourceTemplate ()
+                {
+                    I2cSerialBus (0x0018, ControllerInitiated, 0x00061A80,
+                                  AddressingMode7Bit, "\\_SB.I2C6", 0x00,
+                                  ResourceConsumer, ,)
+                    GpioInt (Edge, ActiveHigh, Exclusive, PullDown, 0x0000,
+                             "\\_SB.GPO2", 0x00, ResourceConsumer, , )
+                    { // Pin list
+                        0
+                    }
+                })
+                Return (RBUF)
+            }
+        }
+    }
+}
+
+which can then be compiled to AML binary format:
+
+$ iasl minnowmax.asl
+
+Intel ACPI Component Architecture
+ASL Optimizing Compiler version 20140214-64 [Mar 29 2014]
+Copyright (c) 2000 - 2014 Intel Corporation
+
+ASL Input:     minnomax.asl - 30 lines, 614 bytes, 7 keywords
+AML Output:    minnowmax.aml - 165 bytes, 6 named objects, 1 executable opcodes
+
+[1] http://wiki.minnowboard.org/MinnowBoard_MAX#Low_Speed_Expansion_Connector_.28Top.29
+
+The resulting AML code can then be loaded by the kernel using one of the methods
+below.
+
+== Loading ACPI SSDTs from initrd ==
+
+This option allows loading of user defined SSDTs from initrd and it is useful
+when the system does not support EFI or when there is not enough EFI storage.
+
+It works in a similar way with initrd based ACPI tables override/upgrade: SSDT
+aml code must be placed in the first, uncompressed, initrd under the
+"kernel/firmware/acpi" path. Multiple files can be used and this will translate
+in loading multiple tables. Only SSDT and OEM tables are allowed. See
+initrd_table_override.txt for more details.
+
+Here is an example:
+
+# Add the raw ACPI tables to an uncompressed cpio archive.
+# They must be put into a /kernel/firmware/acpi directory inside the
+# cpio archive.
+# The uncompressed cpio archive must be the first.
+# Other, typically compressed cpio archives, must be
+# concatenated on top of the uncompressed one.
+mkdir -p kernel/firmware/acpi
+cp ssdt.aml kernel/firmware/acpi
+
+# Create the uncompressed cpio archive and concatenate the original initrd
+# on top:
+find kernel | cpio -H newc --create > /boot/instrumented_initrd
+cat /boot/initrd >>/boot/instrumented_initrd
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
  2016-07-01 20:19 ` [PATCH v5 1/8] Documentation: acpi: add SSDT overlays documentation Octavian Purdila
@ 2016-07-01 20:19 ` Octavian Purdila
  2016-07-06 15:03   ` Mika Westerberg
  2016-07-07  9:28   ` Mika Westerberg
  2016-07-01 20:19 ` [PATCH v5 3/8] acpi: add support for ACPI reconfiguration notifiers Octavian Purdila
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

If the ACPI tables changes as a result of a dinamically loaded table and
a bus rescan is required the enumeration/visited flag are not
consistent.

I2C/SPI are not directly enumerated in acpi_bus_attach(), however the
visited flag is set. This makes it impossible to check if an ACPI device
has already been enumerated by the I2C and SPI subsystems. To fix this
issue we only set the visited flags if the device is not I2C or SPI.

With this change we also need to remove setting visited to false from
acpi_bus_attach(), otherwise if we rescan already enumerated I2C/SPI
devices we try to re-enumerate them.

Note that I2C/SPI devices can be enumerated either via a scan handler
(when using PRP0001) or via regular device_attach(). In either case
the flow goes through acpi_default_enumeration() which makes it the
ideal place to mark the ACPI device as enumerated.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 drivers/acpi/scan.c  | 13 +++++++------
 include/linux/acpi.h | 18 ++++++++++++++++++
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5f28cf7..f80f8a7 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1406,7 +1406,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 	acpi_bus_get_flags(device);
 	device->flags.match_driver = false;
 	device->flags.initialized = true;
-	device->flags.visited = false;
+	acpi_device_clear_enumerated(device);
 	device_initialize(&device->dev);
 	dev_set_uevent_suppress(&device->dev, true);
 	acpi_init_coherency(device);
@@ -1683,8 +1683,10 @@ static void acpi_default_enumeration(struct acpi_device *device)
 	acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
 			       &is_spi_i2c_slave);
 	acpi_dev_free_resource_list(&resource_list);
-	if (!is_spi_i2c_slave)
+	if (!is_spi_i2c_slave) {
 		acpi_create_platform_device(device);
+		acpi_device_set_enumerated(device);
+	}
 }
 
 static const struct acpi_device_id generic_device_ids[] = {
@@ -1751,7 +1753,7 @@ static void acpi_bus_attach(struct acpi_device *device)
 	acpi_bus_get_status(device);
 	/* Skip devices that are not present. */
 	if (!acpi_device_is_present(device)) {
-		device->flags.visited = false;
+		acpi_device_clear_enumerated(device);
 		device->flags.power_manageable = 0;
 		return;
 	}
@@ -1766,7 +1768,7 @@ static void acpi_bus_attach(struct acpi_device *device)
 
 		device->flags.initialized = true;
 	}
-	device->flags.visited = false;
+
 	ret = acpi_scan_attach_handler(device);
 	if (ret < 0)
 		return;
@@ -1780,7 +1782,6 @@ static void acpi_bus_attach(struct acpi_device *device)
 		if (!ret && device->pnp.type.platform_id)
 			acpi_default_enumeration(device);
 	}
-	device->flags.visited = true;
 
  ok:
 	list_for_each_entry(child, &device->children, node)
@@ -1872,7 +1873,7 @@ void acpi_bus_trim(struct acpi_device *adev)
 	 */
 	acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
 	adev->flags.initialized = false;
-	adev->flags.visited = false;
+	acpi_device_clear_enumerated(adev);
 }
 EXPORT_SYMBOL_GPL(acpi_bus_trim);
 
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 288fac5..7089e99 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -532,6 +532,16 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+static inline void acpi_device_set_enumerated(struct acpi_device *adev)
+{
+	adev->flags.visited = true;
+}
+
+static inline void acpi_device_clear_enumerated(struct acpi_device *adev)
+{
+	adev->flags.visited = false;
+}
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
@@ -678,6 +688,14 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
 
 #define ACPI_PTR(_ptr)	(NULL)
 
+static inline void acpi_device_set_enumerated(struct acpi_device *adev)
+{
+}
+
+static inline void acpi_device_clear_enumerated(struct acpi_device *adev)
+{
+}
+
 #endif	/* !CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v5 3/8] acpi: add support for ACPI reconfiguration notifiers
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
  2016-07-01 20:19 ` [PATCH v5 1/8] Documentation: acpi: add SSDT overlays documentation Octavian Purdila
  2016-07-01 20:19 ` [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans Octavian Purdila
@ 2016-07-01 20:19 ` Octavian Purdila
  2016-07-07  9:34   ` Mika Westerberg
  2016-07-01 20:19 ` [PATCH v5 4/8] i2c: add support for ACPI reconfigure notifications Octavian Purdila
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

Add support for ACPI reconfiguration notifiers to allow subsystems to
react to changes in the ACPI tables that happen after the initial
enumeration. This is similar with the way dynamic device tree
notifications work.

The reconfigure notifications supported for now are device add and
device remove.

Since ACPICA allows only one table notification handler, this patch
makes the table notifier function generic and moves it out of the
sysfs specific code.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 drivers/acpi/bus.c      |  9 +++++++
 drivers/acpi/internal.h |  3 +++
 drivers/acpi/scan.c     | 68 ++++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/acpi/sysfs.c    |  6 ++---
 include/linux/acpi.h    | 18 +++++++++++++
 5 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 262ca31..97e270e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -990,6 +990,13 @@ void __init acpi_subsystem_init(void)
 	}
 }
 
+static acpi_status acpi_bus_table_handler(u32 event, void *table, void *context)
+{
+	acpi_scan_table_handler(event, table, context);
+
+	return acpi_sysfs_table_handler(event, table, context);
+}
+
 static int __init acpi_bus_init(void)
 {
 	int result;
@@ -1043,6 +1050,8 @@ static int __init acpi_bus_init(void)
 	 * _PDC control method may load dynamic SSDT tables,
 	 * and we need to install the table handler before that.
 	 */
+	status = acpi_install_table_handler(acpi_bus_table_handler, NULL);
+
 	acpi_sysfs_init();
 
 	acpi_early_processor_set_pdc();
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 27cc7fe..940218f 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -87,6 +87,9 @@ bool acpi_queue_hotplug_work(struct work_struct *work);
 void acpi_device_hotplug(struct acpi_device *adev, u32 src);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
 
+acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context);
+void acpi_scan_table_handler(u32 event, void *table, void *context);
+
 /* --------------------------------------------------------------------------
                      Device Node Initialization / Removal
    -------------------------------------------------------------------------- */
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f80f8a7..6a9b5cb 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -494,6 +494,8 @@ static void acpi_device_del(struct acpi_device *device)
 	device_del(&device->dev);
 }
 
+static BLOCKING_NOTIFIER_HEAD(acpi_reconfig_chain);
+
 static LIST_HEAD(acpi_device_del_list);
 static DEFINE_MUTEX(acpi_device_del_lock);
 
@@ -514,6 +516,9 @@ static void acpi_device_del_work_fn(struct work_struct *work_not_used)
 
 		mutex_unlock(&acpi_device_del_lock);
 
+		blocking_notifier_call_chain(&acpi_reconfig_chain,
+					     ACPI_RECONFIG_DEVICE_REMOVE, adev);
+
 		acpi_device_del(adev);
 		/*
 		 * Drop references to all power resources that might have been
@@ -1676,7 +1681,7 @@ static void acpi_default_enumeration(struct acpi_device *device)
 	bool is_spi_i2c_slave = false;
 
 	/*
-	 * Do not enemerate SPI/I2C slaves as they will be enuerated by their
+	 * Do not enemerate SPI/I2C slaves as they will be enumerated by their
 	 * respective parents.
 	 */
 	INIT_LIST_HEAD(&resource_list);
@@ -1686,6 +1691,9 @@ static void acpi_default_enumeration(struct acpi_device *device)
 	if (!is_spi_i2c_slave) {
 		acpi_create_platform_device(device);
 		acpi_device_set_enumerated(device);
+	} else {
+		blocking_notifier_call_chain(&acpi_reconfig_chain,
+					     ACPI_RECONFIG_DEVICE_ADD, device);
 	}
 }
 
@@ -1917,6 +1925,8 @@ static int acpi_bus_scan_fixed(void)
 	return result < 0 ? result : 0;
 }
 
+static bool acpi_scan_initialized;
+
 int __init acpi_scan_init(void)
 {
 	int result;
@@ -1961,6 +1971,8 @@ int __init acpi_scan_init(void)
 
 	acpi_update_all_gpes();
 
+	acpi_scan_initialized = true;
+
  out:
 	mutex_unlock(&acpi_scan_lock);
 	return result;
@@ -2004,3 +2016,57 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr)
 
 	return count;
 }
+
+struct acpi_table_events_work {
+	struct work_struct work;
+	void *table;
+	u32 event;
+};
+
+void acpi_table_events_fn(struct work_struct *work)
+{
+	struct acpi_table_events_work *tew;
+
+	tew = container_of(work, struct acpi_table_events_work, work);
+
+	if (tew->event == ACPI_TABLE_EVENT_LOAD) {
+		acpi_scan_lock_acquire();
+		acpi_bus_scan(ACPI_ROOT_OBJECT);
+		acpi_scan_lock_release();
+	}
+
+	kfree(tew);
+}
+
+void acpi_scan_table_handler(u32 event, void *table, void *context)
+{
+	struct acpi_table_events_work *tew;
+
+	if (!acpi_scan_initialized)
+		return;
+
+	if (event != ACPI_TABLE_EVENT_LOAD)
+		return;
+
+	tew = kmalloc(sizeof(*tew), GFP_KERNEL);
+	if (!tew)
+		return;
+
+	INIT_WORK(&tew->work, acpi_table_events_fn);
+	tew->table = table;
+	tew->event = event;
+
+	schedule_work(&tew->work);
+}
+
+int acpi_reconfig_notifier_register(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&acpi_reconfig_chain, nb);
+}
+EXPORT_SYMBOL(acpi_reconfig_notifier_register);
+
+int acpi_reconfig_notifier_unregister(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&acpi_reconfig_chain, nb);
+}
+EXPORT_SYMBOL(acpi_reconfig_notifier_unregister);
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 4b3a9e2..358165e 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -378,8 +378,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
 	return;
 }
 
-static acpi_status
-acpi_sysfs_table_handler(u32 event, void *table, void *context)
+acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context)
 {
 	struct acpi_table_attr *table_attr;
 
@@ -452,9 +451,8 @@ static int acpi_tables_sysfs_init(void)
 
 	kobject_uevent(tables_kobj, KOBJ_ADD);
 	kobject_uevent(dynamic_tables_kobj, KOBJ_ADD);
-	status = acpi_install_table_handler(acpi_sysfs_table_handler, NULL);
 
-	return ACPI_FAILURE(status) ? -EINVAL : 0;
+	return 0;
 err_dynamic_tables:
 	kobject_put(tables_kobj);
 err:
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 7089e99..ac93253 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -542,6 +542,14 @@ static inline void acpi_device_clear_enumerated(struct acpi_device *adev)
 	adev->flags.visited = false;
 }
 
+enum acpi_reconfig_event  {
+	ACPI_RECONFIG_DEVICE_ADD = 0,
+	ACPI_RECONFIG_DEVICE_REMOVE,
+};
+
+int acpi_reconfig_notifier_register(struct notifier_block *nb);
+int acpi_reconfig_notifier_unregister(struct notifier_block *nb);
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
@@ -696,6 +704,16 @@ static inline void acpi_device_clear_enumerated(struct acpi_device *adev)
 {
 }
 
+static inline int acpi_reconfig_notifier_register(struct notifier_block *nb)
+{
+	return -EINVAL;
+}
+
+static inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb)
+{
+	return -EINVAL;
+}
+
 #endif	/* !CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v5 4/8] i2c: add support for ACPI reconfigure notifications
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
                   ` (2 preceding siblings ...)
  2016-07-01 20:19 ` [PATCH v5 3/8] acpi: add support for ACPI reconfiguration notifiers Octavian Purdila
@ 2016-07-01 20:19 ` Octavian Purdila
  2016-07-04  0:34   ` Wolfram Sang
  2016-07-01 20:19 ` [PATCH v5 5/8] spi: " Octavian Purdila
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

This patch adds supports for I2C device enumeration and removal via
ACPI reconfiguration notifications that are send as a result of an
ACPI table load or unload operation.

The code is very similar with the device tree reconfiguration code
with only small differences in the way we test and set the enumerated
state of the device:

 * the equivalent of device tree's OF_POPULATED flag is the
   flags.visited field in the ACPI device and the following
   wrappers are used to manipulate it: acpi_device_enumerated(),
   acpi_device_set_enumerated() and acpi_device_clear_enumerated()

 * the device tree code checks of status of the OF_POPULATED flag to
   avoid trying to create duplicate Linux devices in two places: once
   when the controller is probed, and once when the reconfigure event
   is received; in the ACPI code the check is performed only once when
   the ACPI namespace is searched because this code path is invoked in
   both of the two mentioned cases

The rest of the enumeration handling is similar with device tree: when
the Linux device is unregistered the ACPI device is marked as not
enumerated; also, when a device remove notification is received we
check that the device is in the enumerated state before continuing
with the removal of the Linux device.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/i2c/i2c-core.c | 175 ++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 137 insertions(+), 38 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index af11b65..74e5aea 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -107,12 +107,11 @@ struct acpi_i2c_lookup {
 	acpi_handle device_handle;
 };
 
-static int acpi_i2c_find_address(struct acpi_resource *ares, void *data)
+static int acpi_i2c_fill_info(struct acpi_resource *ares, void *data)
 {
 	struct acpi_i2c_lookup *lookup = data;
 	struct i2c_board_info *info = lookup->info;
 	struct acpi_resource_i2c_serialbus *sb;
-	acpi_handle adapter_handle;
 	acpi_status status;
 
 	if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
@@ -122,80 +121,102 @@ static int acpi_i2c_find_address(struct acpi_resource *ares, void *data)
 	if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
 		return 1;
 
-	/*
-	 * Extract the ResourceSource and make sure that the handle matches
-	 * with the I2C adapter handle.
-	 */
 	status = acpi_get_handle(lookup->device_handle,
 				 sb->resource_source.string_ptr,
-				 &adapter_handle);
-	if (ACPI_SUCCESS(status) && adapter_handle == lookup->adapter_handle) {
-		info->addr = sb->slave_address;
-		if (sb->access_mode == ACPI_I2C_10BIT_MODE)
-			info->flags |= I2C_CLIENT_TEN;
-	}
+				 &lookup->adapter_handle);
+	if (!ACPI_SUCCESS(status))
+		return 1;
+
+	info->addr = sb->slave_address;
+	if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+		info->flags |= I2C_CLIENT_TEN;
 
 	return 1;
 }
 
-static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
-				       void *data, void **return_value)
+static int acpi_i2c_get_info(struct acpi_device *adev,
+			     struct i2c_board_info *info,
+			     acpi_handle *adapter_handle)
 {
-	struct i2c_adapter *adapter = data;
 	struct list_head resource_list;
-	struct acpi_i2c_lookup lookup;
 	struct resource_entry *entry;
-	struct i2c_board_info info;
-	struct acpi_device *adev;
+	struct acpi_i2c_lookup lookup;
 	int ret;
 
-	if (acpi_bus_get_device(handle, &adev))
-		return AE_OK;
-	if (acpi_bus_get_status(adev) || !adev->status.present)
-		return AE_OK;
+	if (acpi_bus_get_status(adev) || !adev->status.present ||
+	    acpi_device_enumerated(adev))
+		return -EINVAL;
 
-	memset(&info, 0, sizeof(info));
-	info.fwnode = acpi_fwnode_handle(adev);
+	memset(info, 0, sizeof(*info));
+	info->fwnode = acpi_fwnode_handle(adev);
 
 	memset(&lookup, 0, sizeof(lookup));
-	lookup.adapter_handle = ACPI_HANDLE(&adapter->dev);
-	lookup.device_handle = handle;
-	lookup.info = &info;
+	lookup.device_handle = acpi_device_handle(adev);
+	lookup.info = info;
 
-	/*
-	 * Look up for I2cSerialBus resource with ResourceSource that
-	 * matches with this adapter.
-	 */
+	/* Look up for I2cSerialBus resource */
 	INIT_LIST_HEAD(&resource_list);
 	ret = acpi_dev_get_resources(adev, &resource_list,
-				     acpi_i2c_find_address, &lookup);
+				     acpi_i2c_fill_info, &lookup);
 	acpi_dev_free_resource_list(&resource_list);
 
-	if (ret < 0 || !info.addr)
-		return AE_OK;
+	if (ret < 0 || !info->addr)
+		return -EINVAL;
+
+	*adapter_handle = lookup.adapter_handle;
 
 	/* Then fill IRQ number if any */
 	ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
 	if (ret < 0)
-		return AE_OK;
+		return -EINVAL;
 
 	resource_list_for_each_entry(entry, &resource_list) {
 		if (resource_type(entry->res) == IORESOURCE_IRQ) {
-			info.irq = entry->res->start;
+			info->irq = entry->res->start;
 			break;
 		}
 	}
 
 	acpi_dev_free_resource_list(&resource_list);
 
+	strlcpy(info->type, dev_name(&adev->dev), sizeof(info->type));
+
+	return 0;
+}
+
+static void acpi_i2c_register_device(struct i2c_adapter *adapter,
+				     struct acpi_device *adev,
+				     struct i2c_board_info *info)
+{
 	adev->power.flags.ignore_parent = true;
-	strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
-	if (!i2c_new_device(adapter, &info)) {
+	acpi_device_set_enumerated(adev);
+
+	if (!i2c_new_device(adapter, info)) {
 		adev->power.flags.ignore_parent = false;
 		dev_err(&adapter->dev,
 			"failed to add I2C device %s from ACPI\n",
 			dev_name(&adev->dev));
 	}
+}
+
+static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+				       void *data, void **return_value)
+{
+	struct i2c_adapter *adapter = data;
+	struct acpi_device *adev;
+	acpi_handle adapter_handle;
+	struct i2c_board_info info;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+
+	if (acpi_i2c_get_info(adev, &info, &adapter_handle))
+		return AE_OK;
+
+	if (adapter_handle != ACPI_HANDLE(&adapter->dev))
+		return AE_OK;
+
+	acpi_i2c_register_device(adapter, adev, &info);
 
 	return AE_OK;
 }
@@ -225,8 +246,80 @@ static void acpi_i2c_register_devices(struct i2c_adapter *adap)
 		dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
 }
 
+static int acpi_i2c_match_adapter(struct device *dev, void *data)
+{
+	struct i2c_adapter *adapter = i2c_verify_adapter(dev);
+
+	if (!adapter)
+		return 0;
+
+	return ACPI_HANDLE(dev) == (acpi_handle)data;
+}
+
+static int acpi_i2c_match_device(struct device *dev, void *data)
+{
+	return ACPI_COMPANION(dev) == data;
+}
+
+static struct i2c_adapter *acpi_i2c_find_adapter_by_handle(acpi_handle handle)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&i2c_bus_type, NULL, handle,
+			      acpi_i2c_match_adapter);
+	return dev ? i2c_verify_adapter(dev) : NULL;
+}
+
+static struct i2c_client *acpi_i2c_find_client_by_adev(struct acpi_device *adev)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&i2c_bus_type, NULL, adev, acpi_i2c_match_device);
+	return dev ? i2c_verify_client(dev) : NULL;
+}
+
+static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value,
+			   void *arg)
+{
+	struct acpi_device *adev = arg;
+	struct i2c_board_info info;
+	acpi_handle adapter_handle;
+	struct i2c_adapter *adapter;
+	struct i2c_client *client;
+
+	switch (value) {
+	case ACPI_RECONFIG_DEVICE_ADD:
+		if (acpi_i2c_get_info(adev, &info, &adapter_handle))
+			break;
+
+		adapter = acpi_i2c_find_adapter_by_handle(adapter_handle);
+		if (!adapter)
+			break;
+
+		acpi_i2c_register_device(adapter, adev, &info);
+		break;
+	case ACPI_RECONFIG_DEVICE_REMOVE:
+		if (!acpi_device_enumerated(adev))
+			break;
+
+		client = acpi_i2c_find_client_by_adev(adev);
+		if (!client)
+			break;
+
+		i2c_unregister_device(client);
+		put_device(&client->dev);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block i2c_acpi_notifier = {
+	.notifier_call = acpi_i2c_notify,
+};
 #else /* CONFIG_ACPI */
 static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { }
+extern struct notifier_block i2c_acpi_notifier;
 #endif /* CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI_I2C_OPREGION
@@ -1089,6 +1182,8 @@ void i2c_unregister_device(struct i2c_client *client)
 {
 	if (client->dev.of_node)
 		of_node_clear_flag(client->dev.of_node, OF_POPULATED);
+	if (ACPI_COMPANION(&client->dev))
+		acpi_device_clear_enumerated(ACPI_COMPANION(&client->dev));
 	device_unregister(&client->dev);
 }
 EXPORT_SYMBOL_GPL(i2c_unregister_device);
@@ -2117,6 +2212,8 @@ static int __init i2c_init(void)
 
 	if (IS_ENABLED(CONFIG_OF_DYNAMIC))
 		WARN_ON(of_reconfig_notifier_register(&i2c_of_notifier));
+	if (IS_ENABLED(CONFIG_ACPI))
+		WARN_ON(acpi_reconfig_notifier_register(&i2c_acpi_notifier));
 
 	return 0;
 
@@ -2132,6 +2229,8 @@ bus_err:
 
 static void __exit i2c_exit(void)
 {
+	if (IS_ENABLED(CONFIG_ACPI))
+		WARN_ON(acpi_reconfig_notifier_unregister(&i2c_acpi_notifier));
 	if (IS_ENABLED(CONFIG_OF_DYNAMIC))
 		WARN_ON(of_reconfig_notifier_unregister(&i2c_of_notifier));
 	i2c_del_driver(&dummy_driver);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v5 5/8] spi: add support for ACPI reconfigure notifications
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
                   ` (3 preceding siblings ...)
  2016-07-01 20:19 ` [PATCH v5 4/8] i2c: add support for ACPI reconfigure notifications Octavian Purdila
@ 2016-07-01 20:19 ` Octavian Purdila
  2016-07-03 12:10   ` Mark Brown
  2016-07-01 20:19 ` [PATCH v5 6/8] efi: load SSTDs from EFI variables Octavian Purdila
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

This patch adds supports for SPI device enumeration and removal via
ACPI reconfiguration notifications that are send as a result of an
ACPI table load or unload operation.

The code is very similar with the device tree reconfiguration code
with only small differences in the way we test and set the enumerated
state of the device:

 * the equivalent of device tree's OF_POPULATED flag is the
   flags.visited field in the ACPI device and the following wrappers
   are used to manipulate it: acpi_device_enumerated(),
   acpi_device_set_enumerated() and acpi_device_clear_enumerated()

 * the device tree code checks of status of the OF_POPULATED flag to
   avoid trying to create duplicate Linux devices in two places: once
   when the controller is probed, and once when the reconfigure event
   is received; in the ACPI code the check is performed only once when
   the ACPI namespace is searched because this code path is invoked in
   both of the two mentioned cases

The rest of the enumeration handling is similar with device tree: when
the Linux device is unregistered the ACPI device is marked as not
enumerated; also, when a device remove notification is received we
check that the device is in the enumerated state before continuing
with the removal of the Linux device.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/spi/spi.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 93 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 77e6e45..7589c8a 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -622,6 +622,8 @@ void spi_unregister_device(struct spi_device *spi)
 
 	if (spi->dev.of_node)
 		of_node_clear_flag(spi->dev.of_node, OF_POPULATED);
+	if (ACPI_COMPANION(&spi->dev))
+		acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev));
 	device_unregister(&spi->dev);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_device);
@@ -1646,18 +1648,15 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
 	return 1;
 }
 
-static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
-				       void *data, void **return_value)
+static acpi_status acpi_register_spi_device(struct spi_master *master,
+					    struct acpi_device *adev)
 {
-	struct spi_master *master = data;
 	struct list_head resource_list;
-	struct acpi_device *adev;
 	struct spi_device *spi;
 	int ret;
 
-	if (acpi_bus_get_device(handle, &adev))
-		return AE_OK;
-	if (acpi_bus_get_status(adev) || !adev->status.present)
+	if (acpi_bus_get_status(adev) || !adev->status.present ||
+	    acpi_device_enumerated(adev))
 		return AE_OK;
 
 	spi = spi_alloc_device(master);
@@ -1683,6 +1682,8 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
 	if (spi->irq < 0)
 		spi->irq = acpi_dev_gpio_irq_get(adev, 0);
 
+	acpi_device_set_enumerated(adev);
+
 	adev->power.flags.ignore_parent = true;
 	strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias));
 	if (spi_add_device(spi)) {
@@ -1695,6 +1696,18 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
 	return AE_OK;
 }
 
+static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
+				       void *data, void **return_value)
+{
+	struct spi_master *master = data;
+	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+
+	return acpi_register_spi_device(master, adev);
+}
+
 static void acpi_register_spi_devices(struct spi_master *master)
 {
 	acpi_status status;
@@ -3107,6 +3120,77 @@ static struct notifier_block spi_of_notifier = {
 extern struct notifier_block spi_of_notifier;
 #endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */
 
+#if IS_ENABLED(CONFIG_ACPI)
+static int spi_acpi_master_match(struct device *dev, const void *data)
+{
+	return ACPI_COMPANION(dev->parent) == data;
+}
+
+static int spi_acpi_device_match(struct device *dev, void *data)
+{
+	return ACPI_COMPANION(dev) == data;
+}
+
+static struct spi_master *acpi_spi_find_master_by_adev(struct acpi_device *adev)
+{
+	struct device *dev;
+
+	dev = class_find_device(&spi_master_class, NULL, adev,
+				spi_acpi_master_match);
+	if (!dev)
+		return NULL;
+
+	return container_of(dev, struct spi_master, dev);
+}
+
+static struct spi_device *acpi_spi_find_device_by_adev(struct acpi_device *adev)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&spi_bus_type, NULL, adev, spi_acpi_device_match);
+
+	return dev ? to_spi_device(dev) : NULL;
+}
+
+static int acpi_spi_notify(struct notifier_block *nb, unsigned long value,
+			   void *arg)
+{
+	struct acpi_device *adev = arg;
+	struct spi_master *master;
+	struct spi_device *spi;
+
+	switch (value) {
+	case ACPI_RECONFIG_DEVICE_ADD:
+		master = acpi_spi_find_master_by_adev(adev->parent);
+		if (!master)
+			break;
+
+		acpi_register_spi_device(master, adev);
+		put_device(&master->dev);
+		break;
+	case ACPI_RECONFIG_DEVICE_REMOVE:
+		if (!acpi_device_enumerated(adev))
+			break;
+
+		spi = acpi_spi_find_device_by_adev(adev);
+		if (!spi)
+			break;
+
+		spi_unregister_device(spi);
+		put_device(&spi->dev);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block spi_acpi_notifier = {
+	.notifier_call = acpi_spi_notify,
+};
+#else
+extern struct notifier_block spi_acpi_notifier;
+#endif
+
 static int __init spi_init(void)
 {
 	int	status;
@@ -3127,6 +3211,8 @@ static int __init spi_init(void)
 
 	if (IS_ENABLED(CONFIG_OF_DYNAMIC))
 		WARN_ON(of_reconfig_notifier_register(&spi_of_notifier));
+	if (IS_ENABLED(CONFIG_ACPI))
+		WARN_ON(acpi_reconfig_notifier_register(&spi_acpi_notifier));
 
 	return 0;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v5 6/8] efi: load SSTDs from EFI variables
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
                   ` (4 preceding siblings ...)
  2016-07-01 20:19 ` [PATCH v5 5/8] spi: " Octavian Purdila
@ 2016-07-01 20:19 ` Octavian Purdila
  2016-07-02  8:18   ` Geert Uytterhoeven
  2016-07-04 12:00   ` Matt Fleming
  2016-07-01 20:19 ` [PATCH v5 7/8] acpi: add support for configfs Octavian Purdila
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

This patch allows SSDTs to be loaded from EFI variables. It works by
specifying the EFI variable name containing the SSDT to be loaded. All
variables with the same name (regardless of the vendor GUID) will be
loaded.

Note that we can't use acpi_install_table and we must rely on the
dynamic ACPI table loading and bus re-scanning mechanisms. That is
because I2C/SPI controllers are initialized earlier then the EFI
subsystems and all I2C/SPI ACPI devices are enumerated when the
I2C/SPI controllers are initialized.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 Documentation/acpi/ssdt-overlays.txt | 67 ++++++++++++++++++++++++++++
 Documentation/kernel-parameters.txt  |  7 +++
 drivers/firmware/efi/efi.c           | 85 ++++++++++++++++++++++++++++++++++++
 3 files changed, 159 insertions(+)

diff --git a/Documentation/acpi/ssdt-overlays.txt b/Documentation/acpi/ssdt-overlays.txt
index 8050259..c4b57ba 100644
--- a/Documentation/acpi/ssdt-overlays.txt
+++ b/Documentation/acpi/ssdt-overlays.txt
@@ -89,3 +89,70 @@ cp ssdt.aml kernel/firmware/acpi
 # on top:
 find kernel | cpio -H newc --create > /boot/instrumented_initrd
 cat /boot/initrd >>/boot/instrumented_initrd
+
+== Loading ACPI SSDTs from EFI variables ==
+
+This is the preferred method, when EFI is supported on the platform, because it
+allows a persistent, OS independent way of storing the user defined SSDTs. There
+is also work underway to implement EFI support for loading user defined SSDTs
+and using this method will make it easier to convert to the EFI loading
+mechanism when that will arrive.
+
+In order to load SSDTs from an EFI variable the efivar_ssdt kernel command line
+parameter can be used. The argument for the option is the variable name to
+use. If there are multiple variables with the same name but with different
+vendor GUIDs, all of them will be loaded.
+
+In order to store the AML code in an EFI variable the efivarfs filesystem can be
+used. It is enabled and mounted by default in /sys/firmware/efi/efivars in all
+recent distribution.
+
+Creating a new file in /sys/firmware/efi/efivars will automatically create a new
+EFI variable. Updating a file in /sys/firmware/efi/efivars will update the EFI
+variable. Please note that the file name needs to be specially formatted as
+"Name-GUID" and that the first 4 bytes in the file (little-endian format)
+represent the attributes of the EFI variable (see EFI_VARIABLE_MASK in
+include/linux/efi.h). Writing to the file must also be done with one write
+operation.
+
+For example, you can use the following bash script to create/update an EFI
+variable with the content from a given file:
+
+#!/bin/sh -e
+
+while ! [ -z "$1" ]; do
+        case "$1" in
+        "-f") filename="$2"; shift;;
+        "-g") guid="$2"; shift;;
+        *) name="$1";;
+        esac
+        shift
+done
+
+usage()
+{
+        echo "Syntax: ${0##*/} -f filename [ -g guid ] name"
+        exit 1
+}
+
+[ -n "$name" -a -f "$filename" ] || usage
+
+EFIVARFS="/sys/firmware/efi/efivars"
+
+[ -d "$EFIVARFS" ] || exit 2
+
+if stat -tf $EFIVARFS | grep -q -v de5e81e4; then
+        mount -t efivarfs none $EFIVARFS
+fi
+
+# try to pick up an existing GUID
+[ -n "$guid" ] || guid=$(find "$EFIVARFS" -name "$name-*" | head -n1 | cut -f2- -d-)
+
+# use a randomly generated GUID
+[ -n "$guid" ] || guid="$(cat /proc/sys/kernel/random/uuid)"
+
+# efivarfs expects all of the data in one write
+tmp=$(mktemp)
+/bin/echo -ne "\007\000\000\000" | cat - $filename > $tmp
+dd if=$tmp of="$EFIVARFS/$name-$guid" bs=$(stat -c %s $tmp)
+rm $tmp
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 82b42c9..bbfb56f 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1185,6 +1185,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			Address Range Mirroring feature even if your box
 			doesn't support it.
 
+	efivar_ssdt=	[EFI; X86] Name of an EFI variable that contains an SSDT
+			that is to be dynamically loaded by Linux. If there are
+			multiple variables with the same name but with different
+			vendor GUIDs, all of them will be loaded. See
+			Documentation/acpi/ssdt-overlays.txt for details.
+
+
 	eisa_irq_edge=	[PARISC,HW]
 			See header of drivers/parisc/eisa.c.
 
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 05509f3..02f8efd 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -24,6 +24,9 @@
 #include <linux/of_fdt.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/ucs2_string.h>
 
 #include <asm/early_ioremap.h>
 
@@ -195,6 +198,85 @@ static void generic_ops_unregister(void)
 	efivars_unregister(&generic_efivars);
 }
 
+#if IS_ENABLED(CONFIG_ACPI)
+#define EFIVAR_SSDT_NAME_MAX	16
+static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX];
+static int __init efivar_ssdt_setup(char *str)
+{
+	if (strlen(str) < sizeof(efivar_ssdt))
+		memcpy(efivar_ssdt, str, strlen(str));
+	else
+		pr_warn("efivar_ssdt: name too long: %s\n", str);
+	return 0;
+}
+__setup("efivar_ssdt=", efivar_ssdt_setup);
+
+static __init int efivar_ssdt_iter(efi_char16_t *name, efi_guid_t vendor,
+				   unsigned long name_size, void *data)
+{
+	struct efivar_entry *entry = data;
+	char utf8_name[EFIVAR_SSDT_NAME_MAX];
+	int limit = min_t(unsigned long, EFIVAR_SSDT_NAME_MAX, name_size);
+	unsigned long size;
+	int err;
+
+	ucs2_as_utf8(utf8_name, name, limit - 1);
+	if (strncmp(utf8_name, efivar_ssdt, limit) != 0)
+		return 0;
+
+	pr_info("Loading SSDT from EFI variable %s\n", efivar_ssdt);
+
+	memcpy(entry->var.VariableName, name, name_size);
+	memcpy(&entry->var.VendorGuid, &vendor, sizeof(efi_guid_t));
+
+	err = efivar_entry_size(entry, &size);
+	if (err) {
+		pr_err("efivar_ssdt: failed to get var size\n");
+		return 0;
+	}
+
+	data = kmalloc(size, GFP_KERNEL);
+	if (!data)
+		return 0;
+
+	err = efivar_entry_get(entry, NULL, &size, data);
+	if (err) {
+		pr_err("efivar_ssdt: failed to get var data\n");
+		kfree(data);
+		return 0;
+	}
+
+	err = acpi_load_table(data);
+	if (err) {
+		pr_err("efivar_ssdt: failed to load table: %d\n", err);
+		kfree(data);
+	}
+
+	return 0;
+}
+
+static __init int efivar_ssdt_load(void)
+{
+	struct efivar_entry *entry;
+	/* We need a temporary empty list to be able to set duplicates
+	 * to true so that the efivar lock is dropped to allow us to
+	 * call efivar_entry_get from the iterator function.
+	 */
+	LIST_HEAD(tmp);
+	int ret;
+
+	/* efivar_entry is too big to allocate it on stack */
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+	ret = efivar_init(efivar_ssdt_iter, entry, true, &tmp);
+	kfree(entry);
+	return ret;
+}
+#else
+static inline int efivar_ssdt_load(void) { return 0; }
+#endif
+
 /*
  * We register the efi subsystem with the firmware subsystem and the
  * efivars subsystem with the efi subsystem, if the system was booted with
@@ -218,6 +300,9 @@ static int __init efisubsys_init(void)
 	if (error)
 		goto err_put;
 
+	if (efi_enabled(EFI_RUNTIME_SERVICES))
+		efivar_ssdt_load();
+
 	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
 	if (error) {
 		pr_err("efi: Sysfs attribute export failed with error %d.\n",
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v5 7/8] acpi: add support for configfs
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
                   ` (5 preceding siblings ...)
  2016-07-01 20:19 ` [PATCH v5 6/8] efi: load SSTDs from EFI variables Octavian Purdila
@ 2016-07-01 20:19 ` Octavian Purdila
  2016-07-07  9:39   ` Mika Westerberg
  2016-07-01 20:19 ` [PATCH v5 8/8] acpi: add support for loading SSDTs via configfs Octavian Purdila
  2016-07-06  0:34 ` [PATCH v5 0/8] ACPI overlays Rafael J. Wysocki
  8 siblings, 1 reply; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

Register the ACPI subsystem with configfs.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 Documentation/ABI/testing/configfs-acpi |  7 +++++
 MAINTAINERS                             |  1 +
 drivers/acpi/Kconfig                    |  9 ++++++
 drivers/acpi/Makefile                   |  1 +
 drivers/acpi/configfs.c                 | 53 +++++++++++++++++++++++++++++++++
 5 files changed, 71 insertions(+)
 create mode 100644 Documentation/ABI/testing/configfs-acpi
 create mode 100644 drivers/acpi/configfs.c

diff --git a/Documentation/ABI/testing/configfs-acpi b/Documentation/ABI/testing/configfs-acpi
new file mode 100644
index 0000000..17b19dc
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-acpi
@@ -0,0 +1,7 @@
+What:		/config/acpi
+Date:		July 2016
+KernelVersion:	4.8
+Contact:	linux-acpi@vger.kernel.org
+Description:
+		This represents the ACPI subsystem entry point directory. It
+		contains sub-groups corresponding to ACPI configurable options.
diff --git a/MAINTAINERS b/MAINTAINERS
index 16700e4..9c5365f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -288,6 +288,7 @@ F:	include/linux/acpi.h
 F:	include/acpi/
 F:	Documentation/acpi/
 F:	Documentation/ABI/testing/sysfs-bus-acpi
+F:	Documentation/ABI/testing/configfs-acpi
 F:	drivers/pci/*acpi*
 F:	drivers/pci/*/*acpi*
 F:	drivers/pci/*/*/*acpi*
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b7e2e77..a039433 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -521,4 +521,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_CONFIGFS
+	tristate "ACPI configfs support"
+	select CONFIGFS_FS
+	default n
+	help
+	  Select this option to enable support for ACPI configuration from
+	  userspace. The configurable ACPI groups will be visible under
+	  /config/acpi, assuming configfs is mounted under /config.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 251ce85..1dc2173 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -99,5 +99,6 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_CONFIGFS)	+= configfs.o
 
 video-objs			+= acpi_video.o video_detect.o
diff --git a/drivers/acpi/configfs.c b/drivers/acpi/configfs.c
new file mode 100644
index 0000000..44a72ff
--- /dev/null
+++ b/drivers/acpi/configfs.c
@@ -0,0 +1,53 @@
+/*
+ * ACPI configfs support
+ *
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/configfs.h>
+#include <linux/acpi.h>
+
+static struct config_item_type acpi_root_group_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem acpi_configfs = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "acpi",
+			.ci_type = &acpi_root_group_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(acpi_configfs.su_mutex),
+};
+
+static int __init acpi_configfs_init(void)
+{
+	int ret;
+	struct config_group *root = &acpi_configfs.su_group;
+
+	config_group_init(root);
+
+	ret = configfs_register_subsystem(&acpi_configfs);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+module_init(acpi_configfs_init);
+
+static void __exit acpi_configfs_exit(void)
+{
+	configfs_unregister_subsystem(&acpi_configfs);
+}
+module_exit(acpi_configfs_exit);
+
+MODULE_AUTHOR("Octavian Purdila <octavian.purdila@intel.com>");
+MODULE_DESCRIPTION("ACPI configfs support");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v5 8/8] acpi: add support for loading SSDTs via configfs
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
                   ` (6 preceding siblings ...)
  2016-07-01 20:19 ` [PATCH v5 7/8] acpi: add support for configfs Octavian Purdila
@ 2016-07-01 20:19 ` Octavian Purdila
  2016-07-07  9:42   ` Mika Westerberg
  2016-07-06  0:34 ` [PATCH v5 0/8] ACPI overlays Rafael J. Wysocki
  8 siblings, 1 reply; 24+ messages in thread
From: Octavian Purdila @ 2016-07-01 20:19 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown, Wolfram Sang
  Cc: Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez, Octavian Purdila

New tables can be loaded by creating directories under /config/table/
and writing the AML code into the aml table attribute. Various table
attributes will be readable once the table is successfully loaded.

Unloading tables is not supported at the moment, but it can be easily
implemented once ACPI loading functions provide a table handle to be
used for unloading.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 Documentation/ABI/testing/configfs-acpi |  29 +++++
 Documentation/acpi/ssdt-overlays.txt    |  14 +++
 drivers/acpi/configfs.c                 | 216 +++++++++++++++++++++++++++++++-
 3 files changed, 258 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/configfs-acpi b/Documentation/ABI/testing/configfs-acpi
index 17b19dc..4ab4e99 100644
--- a/Documentation/ABI/testing/configfs-acpi
+++ b/Documentation/ABI/testing/configfs-acpi
@@ -5,3 +5,32 @@ Contact:	linux-acpi@vger.kernel.org
 Description:
 		This represents the ACPI subsystem entry point directory. It
 		contains sub-groups corresponding to ACPI configurable options.
+
+What:		/config/acpi/table
+Date:		July 2016
+KernelVersion:	4.8
+Description:
+
+		This group contains the configuration for user defined ACPI
+		tables. The attributes of a user define table are:
+
+		aml 		- a binary attribute that the user can use to
+				fill in the ACPI aml definitions. Once the aml
+				data is written to this file and the file is
+				closed the table will be loaded and ACPI devices
+				will be enumerated. To check if the operation is
+				successful the user must check the error code
+				for close(). If the operation is successful,
+				subsequent writes to this attribute will fail.
+
+		The rest of the attributes are read-only and are valid only
+		after the table has been loaded by filling the aml entry:
+
+		signature 	- ASCII table signature
+		length 		- length of table in bytes, including the header
+		revision 	- ACPI Specification minor version number
+		oem_id 		- ASCII OEM identification
+		oem_table_id 	- ASCII OEM table identification
+		oem_revision 	- OEM revision number
+		asl_compiler_id - ASCII ASL compiler vendor ID
+		asl_compiler_revision - ASL compiler version
diff --git a/Documentation/acpi/ssdt-overlays.txt b/Documentation/acpi/ssdt-overlays.txt
index c4b57ba..5ae13f1 100644
--- a/Documentation/acpi/ssdt-overlays.txt
+++ b/Documentation/acpi/ssdt-overlays.txt
@@ -156,3 +156,17 @@ tmp=$(mktemp)
 /bin/echo -ne "\007\000\000\000" | cat - $filename > $tmp
 dd if=$tmp of="$EFIVARFS/$name-$guid" bs=$(stat -c %s $tmp)
 rm $tmp
+
+== Loading ACPI SSDTs from configfs ==
+
+This option allows loading of user defined SSDTs from userspace via the configfs
+interface. The CONFIG_ACPI_CONFIGFS option must be select and configfs must be
+mounted. In the following examples, we assume that configfs has been mounted in
+/config.
+
+New tables can be loading by creating new directories in /config/acpi/table/ and
+writing the SSDT aml code in the aml attribute:
+
+cd /config/acpi/table
+mkdir my_ssdt
+cat ~/ssdt.aml > my_ssdt/aml
diff --git a/drivers/acpi/configfs.c b/drivers/acpi/configfs.c
index 44a72ff..135cc0e 100644
--- a/drivers/acpi/configfs.c
+++ b/drivers/acpi/configfs.c
@@ -8,11 +8,222 @@
  * the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) "ACPI configfs: " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/configfs.h>
 #include <linux/acpi.h>
 
+static struct config_group *acpi_table_group;
+
+struct acpi_table {
+	struct config_item cfg;
+	struct acpi_table_header *header;
+};
+
+static ssize_t acpi_table_aml_write(struct config_item *cfg,
+				    const void *data, size_t size)
+{
+	const struct acpi_table_header *header = data;
+	struct acpi_table *table;
+	int ret;
+
+	table = container_of(cfg, struct acpi_table, cfg);
+
+	if (table->header) {
+		pr_err("table already loaded\n");
+		return -EBUSY;
+	}
+
+	if (header->length != size) {
+		pr_err("invalid table length\n");
+		return -EINVAL;
+	}
+
+	if (memcmp(header->signature, ACPI_SIG_SSDT, 4)) {
+		pr_err("invalid table signature\n");
+		return -EINVAL;
+	}
+
+	table = container_of(cfg, struct acpi_table, cfg);
+
+	table->header = kmemdup(header, header->length, GFP_KERNEL);
+	if (!table->header)
+		return -ENOMEM;
+
+	ret = acpi_load_table(table->header);
+	if (ret) {
+		kfree(table->header);
+		table->header = NULL;
+	}
+
+	return ret;
+}
+
+static inline struct acpi_table_header *get_header(struct config_item *cfg)
+{
+	struct acpi_table *table = container_of(cfg, struct acpi_table, cfg);
+
+	if (!table->header)
+		pr_err("table not loaded\n");
+
+	return table->header;
+}
+
+static ssize_t acpi_table_aml_read(struct config_item *cfg,
+				   void *data, size_t size)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	if (data)
+		memcpy(data, h, h->length);
+
+	return h->length;
+}
+
+#define MAX_ACPI_TABLE_SIZE (128 * 1024)
+
+CONFIGFS_BIN_ATTR(acpi_table_, aml, NULL, MAX_ACPI_TABLE_SIZE);
+
+struct configfs_bin_attribute *acpi_table_bin_attrs[] = {
+	&acpi_table_attr_aml,
+	NULL,
+};
+
+ssize_t acpi_table_signature_show(struct config_item *cfg, char *str)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	return sprintf(str, "%.*s\n", ACPI_NAME_SIZE, h->signature);
+}
+
+ssize_t acpi_table_length_show(struct config_item *cfg, char *str)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	return sprintf(str, "%d\n", h->length);
+}
+
+ssize_t acpi_table_revision_show(struct config_item *cfg, char *str)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	return sprintf(str, "%d\n", h->revision);
+}
+
+ssize_t acpi_table_oem_id_show(struct config_item *cfg, char *str)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	return sprintf(str, "%.*s\n", ACPI_OEM_ID_SIZE, h->oem_id);
+}
+
+ssize_t acpi_table_oem_table_id_show(struct config_item *cfg, char *str)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	return sprintf(str, "%.*s\n", ACPI_OEM_TABLE_ID_SIZE, h->oem_table_id);
+}
+
+ssize_t acpi_table_oem_revision_show(struct config_item *cfg, char *str)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	return sprintf(str, "%d\n", h->oem_revision);
+}
+
+ssize_t acpi_table_asl_compiler_id_show(struct config_item *cfg, char *str)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	return sprintf(str, "%.*s\n", ACPI_NAME_SIZE, h->asl_compiler_id);
+}
+
+ssize_t acpi_table_asl_compiler_revision_show(struct config_item *cfg,
+					      char *str)
+{
+	struct acpi_table_header *h = get_header(cfg);
+
+	if (!h)
+		return -EINVAL;
+
+	return sprintf(str, "%d\n", h->asl_compiler_revision);
+}
+
+CONFIGFS_ATTR_RO(acpi_table_, signature);
+CONFIGFS_ATTR_RO(acpi_table_, length);
+CONFIGFS_ATTR_RO(acpi_table_, revision);
+CONFIGFS_ATTR_RO(acpi_table_, oem_id);
+CONFIGFS_ATTR_RO(acpi_table_, oem_table_id);
+CONFIGFS_ATTR_RO(acpi_table_, oem_revision);
+CONFIGFS_ATTR_RO(acpi_table_, asl_compiler_id);
+CONFIGFS_ATTR_RO(acpi_table_, asl_compiler_revision);
+
+struct configfs_attribute *acpi_table_attrs[] = {
+	&acpi_table_attr_signature,
+	&acpi_table_attr_length,
+	&acpi_table_attr_revision,
+	&acpi_table_attr_oem_id,
+	&acpi_table_attr_oem_table_id,
+	&acpi_table_attr_oem_revision,
+	&acpi_table_attr_asl_compiler_id,
+	&acpi_table_attr_asl_compiler_revision,
+	NULL,
+};
+
+static struct config_item_type acpi_table_type = {
+	.ct_owner = THIS_MODULE,
+	.ct_bin_attrs = acpi_table_bin_attrs,
+	.ct_attrs = acpi_table_attrs,
+};
+
+static struct config_item *acpi_table_make_item(struct config_group *group,
+						const char *name)
+{
+	struct acpi_table *table;
+
+	table = kzalloc(sizeof(*table), GFP_KERNEL);
+	if (!table)
+		return ERR_PTR(-ENOMEM);
+
+	config_item_init_type_name(&table->cfg, name, &acpi_table_type);
+	return &table->cfg;
+}
+
+struct configfs_group_operations acpi_table_group_ops = {
+	.make_item = acpi_table_make_item,
+};
+
+static struct config_item_type acpi_tables_type = {
+	.ct_owner = THIS_MODULE,
+	.ct_group_ops = &acpi_table_group_ops,
+};
+
 static struct config_item_type acpi_root_group_type = {
 	.ct_owner = THIS_MODULE,
 };
@@ -38,12 +249,15 @@ static int __init acpi_configfs_init(void)
 	if (ret)
 		return ret;
 
-	return 0;
+	acpi_table_group = configfs_register_default_group(root, "table",
+							   &acpi_tables_type);
+	return PTR_ERR_OR_ZERO(acpi_table_group);
 }
 module_init(acpi_configfs_init);
 
 static void __exit acpi_configfs_exit(void)
 {
+	configfs_unregister_default_group(acpi_table_group);
 	configfs_unregister_subsystem(&acpi_configfs);
 }
 module_exit(acpi_configfs_exit);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 6/8] efi: load SSTDs from EFI variables
  2016-07-01 20:19 ` [PATCH v5 6/8] efi: load SSTDs from EFI variables Octavian Purdila
@ 2016-07-02  8:18   ` Geert Uytterhoeven
  2016-07-04 12:00   ` Matt Fleming
  1 sibling, 0 replies; 24+ messages in thread
From: Geert Uytterhoeven @ 2016-07-02  8:18 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, ACPI Devel Maling List, linux-efi,
	Linux I2C, linux-spi, linux-kernel, irina.tirdea,
	Crestez Dan Leonard

On Fri, Jul 1, 2016 at 10:19 PM, Octavian Purdila
<octavian.purdila@intel.com> wrote:
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c

> @@ -195,6 +198,85 @@ static void generic_ops_unregister(void)
>         efivars_unregister(&generic_efivars);
>  }
>
> +#if IS_ENABLED(CONFIG_ACPI)
> +#define EFIVAR_SSDT_NAME_MAX   16
> +static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX];

I think efivar_ssdt[] is used from __init functions only, so it can be
__initdata.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 5/8] spi: add support for ACPI reconfigure notifications
  2016-07-01 20:19 ` [PATCH v5 5/8] spi: " Octavian Purdila
@ 2016-07-03 12:10   ` Mark Brown
  0 siblings, 0 replies; 24+ messages in thread
From: Mark Brown @ 2016-07-03 12:10 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Wolfram Sang,
	Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez

[-- Attachment #1: Type: text/plain, Size: 287 bytes --]

On Fri, Jul 01, 2016 at 11:19:09PM +0300, Octavian Purdila wrote:
> This patch adds supports for SPI device enumeration and removal via
> ACPI reconfiguration notifications that are send as a result of an
> ACPI table load or unload operation.

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 4/8] i2c: add support for ACPI reconfigure notifications
  2016-07-01 20:19 ` [PATCH v5 4/8] i2c: add support for ACPI reconfigure notifications Octavian Purdila
@ 2016-07-04  0:34   ` Wolfram Sang
  0 siblings, 0 replies; 24+ messages in thread
From: Wolfram Sang @ 2016-07-04  0:34 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez

[-- Attachment #1: Type: text/plain, Size: 1653 bytes --]

On Fri, Jul 01, 2016 at 11:19:08PM +0300, Octavian Purdila wrote:
> This patch adds supports for I2C device enumeration and removal via
> ACPI reconfiguration notifications that are send as a result of an
> ACPI table load or unload operation.
> 
> The code is very similar with the device tree reconfiguration code
> with only small differences in the way we test and set the enumerated
> state of the device:
> 
>  * the equivalent of device tree's OF_POPULATED flag is the
>    flags.visited field in the ACPI device and the following
>    wrappers are used to manipulate it: acpi_device_enumerated(),
>    acpi_device_set_enumerated() and acpi_device_clear_enumerated()
> 
>  * the device tree code checks of status of the OF_POPULATED flag to
>    avoid trying to create duplicate Linux devices in two places: once
>    when the controller is probed, and once when the reconfigure event
>    is received; in the ACPI code the check is performed only once when
>    the ACPI namespace is searched because this code path is invoked in
>    both of the two mentioned cases
> 
> The rest of the enumeration handling is similar with device tree: when
> the Linux device is unregistered the ACPI device is marked as not
> enumerated; also, when a device remove notification is received we
> check that the device is in the enumerated state before continuing
> with the removal of the Linux device.
> 
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

It has Mika's ack already, but to make sure:

Acked-by: Wolfram Sang <wsa@the-dreams.de>


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 6/8] efi: load SSTDs from EFI variables
  2016-07-01 20:19 ` [PATCH v5 6/8] efi: load SSTDs from EFI variables Octavian Purdila
  2016-07-02  8:18   ` Geert Uytterhoeven
@ 2016-07-04 12:00   ` Matt Fleming
  1 sibling, 0 replies; 24+ messages in thread
From: Matt Fleming @ 2016-07-04 12:00 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Mark Brown, Wolfram Sang,
	Joel Becker, linux-acpi, linux-efi, linux-i2c, linux-spi,
	linux-kernel, irina.tirdea, leonard.crestez

(Sorry, didn't get chance to reply before you sent this version)

On Fri, 01 Jul, at 11:19:10PM, Octavian Purdila wrote:
> +
> +static __init int efivar_ssdt_load(void)
> +{
> +	struct efivar_entry *entry;
> +	/* We need a temporary empty list to be able to set duplicates
> +	 * to true so that the efivar lock is dropped to allow us to
> +	 * call efivar_entry_get from the iterator function.
> +	 */
> +	LIST_HEAD(tmp);
> +	int ret;

I suspect you actually want to enable duplicate detection though,
because that bug (GetNextVariable() returning the same variable over
and over) does exist in the wild and it isn't that much more work to
enable the check.

Yes, the stack-local list looks like the right approach, because you
don't need access to these entries once this function returns.

Just be sure to free all those entries after efivar_init(), which
doesn't need to be done under efivar_entry_iter_{begin,end}() because
no one can concurrently access the list anyway.

Also...

	/*
	 * Multi-line comments should look like this, with the empty
	 * first line.
	 */

> +
> +	/* efivar_entry is too big to allocate it on stack */
> +	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
> +	if (!entry)
> +		return -ENOMEM;
> +	ret = efivar_init(efivar_ssdt_iter, entry, true, &tmp);
> +	kfree(entry);
> +	return ret;
> +}
> +#else
> +static inline int efivar_ssdt_load(void) { return 0; }
> +#endif

My suggestion is,

  - Push the 'entry' allocation into efivar_ssdt_iter()
  - Add 'entry' to the stack-local tmp list via efivar_entry_add()
  - Iterate 'tmp' and free entries before returning from efivar_ssdt_load()

Make sense?

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 0/8]  ACPI overlays
  2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
                   ` (7 preceding siblings ...)
  2016-07-01 20:19 ` [PATCH v5 8/8] acpi: add support for loading SSDTs via configfs Octavian Purdila
@ 2016-07-06  0:34 ` Rafael J. Wysocki
  2016-07-06  6:29   ` Octavian Purdila
  8 siblings, 1 reply; 24+ messages in thread
From: Rafael J. Wysocki @ 2016-07-06  0:34 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Len Brown, Matt Fleming, Mark Brown, Wolfram Sang, Joel Becker,
	linux-acpi, linux-efi, linux-i2c, linux-spi, linux-kernel,
	irina.tirdea, leonard.crestez

On Friday, July 01, 2016 11:19:04 PM Octavian Purdila wrote:
> This patch set enables custom ACPI board configuration by adding
> mechanisms in the Linux kernel for loading user defined SSDTs.
> 
> In order to support ACPI open-ended hardware configurations we need a
> way to augment the ACPI configuration provided by the firmware
> image. A common example is connecting sensors on I2C / SPI buses on
> development boards.
> 
> Although this can be accomplished by creating a kernel platform driver
> or recompiling the firmware image with updated ACPI tables, neither is
> practical: the former proliferates board specific kernel code while
> the latter requires access to firmware tools which are often not
> publicly available.
> 
> Because ACPI supports external references in AML code a more practical
> way to augment firmware ACPI configuration is by dynamically loading
> user defined SSDT tables that contain the board specific information.
> 
> Currently it is possible to load SSDT overlays using the upgrade
> initrd mechanism introduced in 4.7. This patch series adds support for
> two more methods:
> 
> * From an EFI variable
> 
>  This is the preferred method, when EFI is supported on the platform,
>  because it allows a persistent, OS independent way of storing and
>  updating the user defined SSDTs. There is also work underway to
>  implement EFI support for loading user defined SSDTs and using this
>  method will make it easier to convert to the EFI loading mechanism
>  when that will arrive.
> 
> * From userspace via configfs
> 
>  This is useful when we want to defer the operation to userspace for
>  platform detection, loading the SSDTs from a custom partition, etc.
> 
> 
> Changes from v4:
> 
> * EFI: use ucs2_as_utf8 and memcmp to check if the variable name
>   matches the kernel command line parameter; fold the EFI ACPI table
>   load code in the iterator function
> 
> * I2C/SPI: add more information in the commit logs about how the
>   enumeration status is set and checked; also add a new check of the
>   enumerated status for the ACPI device remove reconfiguration
>   notification
> 
> Changes from v3:
> 
> * fix a bisectability issue reported by kbuild
> 
> * rework the enumeration fix to support PRP0001 enumeration; also,
>   introduce acpi_device_set/clear_enumerated() for clarity
> 
> * clear the enumerated status for acpi_device when the I2C/SPI clients
>   are removed (for example as a result of an adapter removal) to allow
>   the devices to be re-enumerated later
> 
> Changes from v2:
> 
> * fix a few issues caught by the kbuild test robot
> 
> * add more configfs table attributes
> 
> * removed the initrd based loading functionality from this patch set
>   as this can already be accomplished in 4.7 using the ACPI table
>   upgrade mechanism
> 
> * rebased to 4.7-rc3
> 
> Changes from v1:
> 
> * rebased on top of the ACPI install from initrd table functionality;
>   there is significant overlap between the 1st patch in this series
>   and these patch [1] from Lv - I kept it in this series until the
>   discussions around the taint and config option are resolved
> 
> * make sure EFI_RUNTIME_SERVICES are available before trying to use
>   EFI variables to load tables
> 
> * rework the ACPI reconfiguration notifications to work on device
>   granularity (device added or removed) instead of table granularity
>   (table loaded or unloaded)
> 
> * add support for table unloading / device removal
> 
> * note that the last patch is just a hack to be able to test the table
>   unload / device remove functionality, if someone wants to try out
>   this patch set
> 
> [1] https://patchwork.kernel.org/patch/8795931/
> 
> Octavian Purdila (8):
>   Documentation: acpi: add SSDT overlays documentation
>   acpi: fix enumeration (visited) flags for bus rescans
>   acpi: add support for ACPI reconfiguration notifiers
>   i2c: add support for ACPI reconfigure notifications
>   spi: add support for ACPI reconfigure notifications
>   efi: load SSTDs from EFI variables
>   acpi: add support for configfs
>   acpi: add support for loading SSDTs via configfs
> 
>  Documentation/ABI/testing/configfs-acpi |  36 +++++
>  Documentation/acpi/ssdt-overlays.txt    | 172 ++++++++++++++++++++
>  Documentation/kernel-parameters.txt     |   7 +
>  MAINTAINERS                             |   1 +
>  drivers/acpi/Kconfig                    |   9 ++
>  drivers/acpi/Makefile                   |   1 +
>  drivers/acpi/bus.c                      |   9 ++
>  drivers/acpi/configfs.c                 | 267 ++++++++++++++++++++++++++++++++
>  drivers/acpi/internal.h                 |   3 +
>  drivers/acpi/scan.c                     |  81 +++++++++-
>  drivers/acpi/sysfs.c                    |   6 +-
>  drivers/firmware/efi/efi.c              |  85 ++++++++++
>  drivers/i2c/i2c-core.c                  | 175 ++++++++++++++++-----
>  drivers/spi/spi.c                       | 100 +++++++++++-
>  include/linux/acpi.h                    |  36 +++++
>  15 files changed, 932 insertions(+), 56 deletions(-)
>  create mode 100644 Documentation/ABI/testing/configfs-acpi
>  create mode 100644 Documentation/acpi/ssdt-overlays.txt
>  create mode 100644 drivers/acpi/configfs.c

It looks like all patches in this series except for the [6/8] are good to go.

Do any of them depend on the [6/8]?

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 0/8] ACPI overlays
  2016-07-06  0:34 ` [PATCH v5 0/8] ACPI overlays Rafael J. Wysocki
@ 2016-07-06  6:29   ` Octavian Purdila
  0 siblings, 0 replies; 24+ messages in thread
From: Octavian Purdila @ 2016-07-06  6:29 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Len Brown, Matt Fleming, Mark Brown, Wolfram Sang, Joel Becker,
	linux-acpi, linux-efi, linux-i2c, linux-spi, lkml, Irina Tirdea,
	Leonard Crestez

On Wed, Jul 6, 2016 at 3:34 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Friday, July 01, 2016 11:19:04 PM Octavian Purdila wrote:
>> This patch set enables custom ACPI board configuration by adding
>> mechanisms in the Linux kernel for loading user defined SSDTs.
>>
>> In order to support ACPI open-ended hardware configurations we need a
>> way to augment the ACPI configuration provided by the firmware
>> image. A common example is connecting sensors on I2C / SPI buses on
>> development boards.
>>
>> Although this can be accomplished by creating a kernel platform driver
>> or recompiling the firmware image with updated ACPI tables, neither is
>> practical: the former proliferates board specific kernel code while
>> the latter requires access to firmware tools which are often not
>> publicly available.
>>
>> Because ACPI supports external references in AML code a more practical
>> way to augment firmware ACPI configuration is by dynamically loading
>> user defined SSDT tables that contain the board specific information.
>>
>> Currently it is possible to load SSDT overlays using the upgrade
>> initrd mechanism introduced in 4.7. This patch series adds support for
>> two more methods:
>>
>> * From an EFI variable
>>
>>  This is the preferred method, when EFI is supported on the platform,
>>  because it allows a persistent, OS independent way of storing and
>>  updating the user defined SSDTs. There is also work underway to
>>  implement EFI support for loading user defined SSDTs and using this
>>  method will make it easier to convert to the EFI loading mechanism
>>  when that will arrive.
>>
>> * From userspace via configfs
>>
>>  This is useful when we want to defer the operation to userspace for
>>  platform detection, loading the SSDTs from a custom partition, etc.
>>
>>
>> Changes from v4:
>>
>> * EFI: use ucs2_as_utf8 and memcmp to check if the variable name
>>   matches the kernel command line parameter; fold the EFI ACPI table
>>   load code in the iterator function
>>
>> * I2C/SPI: add more information in the commit logs about how the
>>   enumeration status is set and checked; also add a new check of the
>>   enumerated status for the ACPI device remove reconfiguration
>>   notification
>>
>> Changes from v3:
>>
>> * fix a bisectability issue reported by kbuild
>>
>> * rework the enumeration fix to support PRP0001 enumeration; also,
>>   introduce acpi_device_set/clear_enumerated() for clarity
>>
>> * clear the enumerated status for acpi_device when the I2C/SPI clients
>>   are removed (for example as a result of an adapter removal) to allow
>>   the devices to be re-enumerated later
>>
>> Changes from v2:
>>
>> * fix a few issues caught by the kbuild test robot
>>
>> * add more configfs table attributes
>>
>> * removed the initrd based loading functionality from this patch set
>>   as this can already be accomplished in 4.7 using the ACPI table
>>   upgrade mechanism
>>
>> * rebased to 4.7-rc3
>>
>> Changes from v1:
>>
>> * rebased on top of the ACPI install from initrd table functionality;
>>   there is significant overlap between the 1st patch in this series
>>   and these patch [1] from Lv - I kept it in this series until the
>>   discussions around the taint and config option are resolved
>>
>> * make sure EFI_RUNTIME_SERVICES are available before trying to use
>>   EFI variables to load tables
>>
>> * rework the ACPI reconfiguration notifications to work on device
>>   granularity (device added or removed) instead of table granularity
>>   (table loaded or unloaded)
>>
>> * add support for table unloading / device removal
>>
>> * note that the last patch is just a hack to be able to test the table
>>   unload / device remove functionality, if someone wants to try out
>>   this patch set
>>
>> [1] https://patchwork.kernel.org/patch/8795931/
>>
>> Octavian Purdila (8):
>>   Documentation: acpi: add SSDT overlays documentation
>>   acpi: fix enumeration (visited) flags for bus rescans
>>   acpi: add support for ACPI reconfiguration notifiers
>>   i2c: add support for ACPI reconfigure notifications
>>   spi: add support for ACPI reconfigure notifications
>>   efi: load SSTDs from EFI variables
>>   acpi: add support for configfs
>>   acpi: add support for loading SSDTs via configfs
>>
>>  Documentation/ABI/testing/configfs-acpi |  36 +++++
>>  Documentation/acpi/ssdt-overlays.txt    | 172 ++++++++++++++++++++
>>  Documentation/kernel-parameters.txt     |   7 +
>>  MAINTAINERS                             |   1 +
>>  drivers/acpi/Kconfig                    |   9 ++
>>  drivers/acpi/Makefile                   |   1 +
>>  drivers/acpi/bus.c                      |   9 ++
>>  drivers/acpi/configfs.c                 | 267 ++++++++++++++++++++++++++++++++
>>  drivers/acpi/internal.h                 |   3 +
>>  drivers/acpi/scan.c                     |  81 +++++++++-
>>  drivers/acpi/sysfs.c                    |   6 +-
>>  drivers/firmware/efi/efi.c              |  85 ++++++++++
>>  drivers/i2c/i2c-core.c                  | 175 ++++++++++++++++-----
>>  drivers/spi/spi.c                       | 100 +++++++++++-
>>  include/linux/acpi.h                    |  36 +++++
>>  15 files changed, 932 insertions(+), 56 deletions(-)
>>  create mode 100644 Documentation/ABI/testing/configfs-acpi
>>  create mode 100644 Documentation/acpi/ssdt-overlays.txt
>>  create mode 100644 drivers/acpi/configfs.c
>
> It looks like all patches in this series except for the [6/8] are good to go.
>
> Do any of them depend on the [6/8]?
>

Yes, 6/8 and 8/8 both touch Documentation/acpi/ssdt-overlays.txt, but
it should be trivial to fix 8/8 if we pull out 6/8.

I've send an updated v6 for 6/8 only that fixes the issue Matt and
Geert noticed, so maybe its worth waiting for a couple of days for
Matt's review.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans
  2016-07-01 20:19 ` [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans Octavian Purdila
@ 2016-07-06 15:03   ` Mika Westerberg
  2016-07-06 15:37     ` Octavian Purdila
  2016-07-07  9:28   ` Mika Westerberg
  1 sibling, 1 reply; 24+ messages in thread
From: Mika Westerberg @ 2016-07-06 15:03 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, linux-kernel, irina.tirdea, leonard.crestez

On Fri, Jul 01, 2016 at 11:19:06PM +0300, Octavian Purdila wrote:
> If the ACPI tables changes as a result of a dinamically loaded table and
> a bus rescan is required the enumeration/visited flag are not
> consistent.
> 
> I2C/SPI are not directly enumerated in acpi_bus_attach(), however the
> visited flag is set. This makes it impossible to check if an ACPI device
> has already been enumerated by the I2C and SPI subsystems. To fix this
> issue we only set the visited flags if the device is not I2C or SPI.
> 
> With this change we also need to remove setting visited to false from
> acpi_bus_attach(), otherwise if we rescan already enumerated I2C/SPI
> devices we try to re-enumerate them.
> 
> Note that I2C/SPI devices can be enumerated either via a scan handler
> (when using PRP0001) or via regular device_attach(). In either case
> the flow goes through acpi_default_enumeration() which makes it the
> ideal place to mark the ACPI device as enumerated.

Hmm, this somehow fails to enumerate PRP0001 devices.

I'm adding following SSDT to my initrd and the resulting device is never
enumerated on SPI bus (it exists in /sys/bus/acpi/devices). If I use
normal ACPI IDs (non-PRP0001) then it works fine.

/*
 * Minnowboard MAX
 *
 * http://wiki.minnowboard.org/MinnowBoard_MAX
 *
 * This adds Atmel AT25 compatible serial EEPROM to the SPI host controller
 * available on Minnowboard MAX low speed connector.
 */
DefinitionBlock ("at25.aml", "SSDT", 5, "INTEL", "AT25", 1)
{
    External (_SB_.SPI1, DeviceObj)

    Scope (\_SB.SPI1)
    {
        Device (EEP0) {
            Name (_HID, "PRP0001")
            Name (_DDN, "Atmel AT25 compatible EEPROM")
            Name (_CRS, ResourceTemplate () {
                SpiSerialBus (
                    1,                      // Chip select
                    PolarityLow,            // Chip select is active low
                    FourWireMode,           // Full duplex
                    8,                      // Bits per word is 8 (byte)
                    ControllerInitiated,    // Don't care
                    1000000,                // Initial bus speed is 1MHz
                    ClockPolarityLow,       // SPI mode 0
                    ClockPhaseFirst,        // SPI mode 0
                    "\\_SB.SPI1",           // SPI host controller
                    0                       // Must be 0
                )
            })

            /*
             * See Documentation/devicetree/bindings/eeprom/at25.txt for
             * more information about these bindings.
             */
            Name (_DSD, Package () {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package () {
                    Package () {"compatible", Package () {"atmel,at25"}},
                    Package () {"size", 1024},
                    Package () {"pagesize", 32},
                    Package () {"address-width", 16},
                }
            })
        }
    }
}

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans
  2016-07-06 15:03   ` Mika Westerberg
@ 2016-07-06 15:37     ` Octavian Purdila
  2016-07-06 21:09       ` Rafael J. Wysocki
  0 siblings, 1 reply; 24+ messages in thread
From: Octavian Purdila @ 2016-07-06 15:37 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, lkml, Irina Tirdea, Leonard Crestez

On Wed, Jul 6, 2016 at 6:03 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Fri, Jul 01, 2016 at 11:19:06PM +0300, Octavian Purdila wrote:
>> If the ACPI tables changes as a result of a dinamically loaded table and
>> a bus rescan is required the enumeration/visited flag are not
>> consistent.
>>
>> I2C/SPI are not directly enumerated in acpi_bus_attach(), however the
>> visited flag is set. This makes it impossible to check if an ACPI device
>> has already been enumerated by the I2C and SPI subsystems. To fix this
>> issue we only set the visited flags if the device is not I2C or SPI.
>>
>> With this change we also need to remove setting visited to false from
>> acpi_bus_attach(), otherwise if we rescan already enumerated I2C/SPI
>> devices we try to re-enumerate them.
>>
>> Note that I2C/SPI devices can be enumerated either via a scan handler
>> (when using PRP0001) or via regular device_attach(). In either case
>> the flow goes through acpi_default_enumeration() which makes it the
>> ideal place to mark the ACPI device as enumerated.
>
> Hmm, this somehow fails to enumerate PRP0001 devices.
>
> I'm adding following SSDT to my initrd and the resulting device is never
> enumerated on SPI bus (it exists in /sys/bus/acpi/devices). If I use
> normal ACPI IDs (non-PRP0001) then it works fine.
>

I specifically tested with PRP0001 via initrd with I2C, I am not sure
why it does not work on SPI. I'll give it a try tomorrow when I have
access to my setup.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans
  2016-07-06 15:37     ` Octavian Purdila
@ 2016-07-06 21:09       ` Rafael J. Wysocki
  2016-07-07  9:00         ` Mika Westerberg
  0 siblings, 1 reply; 24+ messages in thread
From: Rafael J. Wysocki @ 2016-07-06 21:09 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Mika Westerberg, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, lkml, Irina Tirdea, Leonard Crestez

On Wednesday, July 06, 2016 06:37:46 PM Octavian Purdila wrote:
> On Wed, Jul 6, 2016 at 6:03 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> > On Fri, Jul 01, 2016 at 11:19:06PM +0300, Octavian Purdila wrote:
> >> If the ACPI tables changes as a result of a dinamically loaded table and
> >> a bus rescan is required the enumeration/visited flag are not
> >> consistent.
> >>
> >> I2C/SPI are not directly enumerated in acpi_bus_attach(), however the
> >> visited flag is set. This makes it impossible to check if an ACPI device
> >> has already been enumerated by the I2C and SPI subsystems. To fix this
> >> issue we only set the visited flags if the device is not I2C or SPI.
> >>
> >> With this change we also need to remove setting visited to false from
> >> acpi_bus_attach(), otherwise if we rescan already enumerated I2C/SPI
> >> devices we try to re-enumerate them.
> >>
> >> Note that I2C/SPI devices can be enumerated either via a scan handler
> >> (when using PRP0001) or via regular device_attach(). In either case
> >> the flow goes through acpi_default_enumeration() which makes it the
> >> ideal place to mark the ACPI device as enumerated.
> >
> > Hmm, this somehow fails to enumerate PRP0001 devices.
> >
> > I'm adding following SSDT to my initrd and the resulting device is never
> > enumerated on SPI bus (it exists in /sys/bus/acpi/devices). If I use
> > normal ACPI IDs (non-PRP0001) then it works fine.
> >
> 
> I specifically tested with PRP0001 via initrd with I2C, I am not sure
> why it does not work on SPI. I'll give it a try tomorrow when I have
> access to my setup.

OK, I'll wait for this test to conclude before applying the series, then. :-)

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans
  2016-07-06 21:09       ` Rafael J. Wysocki
@ 2016-07-07  9:00         ` Mika Westerberg
  0 siblings, 0 replies; 24+ messages in thread
From: Mika Westerberg @ 2016-07-07  9:00 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Octavian Purdila, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, lkml, Irina Tirdea, Leonard Crestez

On Wed, Jul 06, 2016 at 11:09:44PM +0200, Rafael J. Wysocki wrote:
> On Wednesday, July 06, 2016 06:37:46 PM Octavian Purdila wrote:
> > On Wed, Jul 6, 2016 at 6:03 PM, Mika Westerberg
> > <mika.westerberg@linux.intel.com> wrote:
> > > On Fri, Jul 01, 2016 at 11:19:06PM +0300, Octavian Purdila wrote:
> > >> If the ACPI tables changes as a result of a dinamically loaded table and
> > >> a bus rescan is required the enumeration/visited flag are not
> > >> consistent.
> > >>
> > >> I2C/SPI are not directly enumerated in acpi_bus_attach(), however the
> > >> visited flag is set. This makes it impossible to check if an ACPI device
> > >> has already been enumerated by the I2C and SPI subsystems. To fix this
> > >> issue we only set the visited flags if the device is not I2C or SPI.
> > >>
> > >> With this change we also need to remove setting visited to false from
> > >> acpi_bus_attach(), otherwise if we rescan already enumerated I2C/SPI
> > >> devices we try to re-enumerate them.
> > >>
> > >> Note that I2C/SPI devices can be enumerated either via a scan handler
> > >> (when using PRP0001) or via regular device_attach(). In either case
> > >> the flow goes through acpi_default_enumeration() which makes it the
> > >> ideal place to mark the ACPI device as enumerated.
> > >
> > > Hmm, this somehow fails to enumerate PRP0001 devices.
> > >
> > > I'm adding following SSDT to my initrd and the resulting device is never
> > > enumerated on SPI bus (it exists in /sys/bus/acpi/devices). If I use
> > > normal ACPI IDs (non-PRP0001) then it works fine.
> > >
> > 
> > I specifically tested with PRP0001 via initrd with I2C, I am not sure
> > why it does not work on SPI. I'll give it a try tomorrow when I have
> > access to my setup.
> 
> OK, I'll wait for this test to conclude before applying the series, then. :-)

I tested again and it works fine. I probably had an older version of the
series applied or something like that. Now, I'm able to see my AT25 SPI
eeprom successfully probed:

[    7.264705] at25 spi-PRP0001:00: 1 KByte at25 eeprom, pagesize 32

Sorry about the confusion.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 1/8] Documentation: acpi: add SSDT overlays documentation
  2016-07-01 20:19 ` [PATCH v5 1/8] Documentation: acpi: add SSDT overlays documentation Octavian Purdila
@ 2016-07-07  9:25   ` Mika Westerberg
  0 siblings, 0 replies; 24+ messages in thread
From: Mika Westerberg @ 2016-07-07  9:25 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, linux-kernel, irina.tirdea, leonard.crestez

On Fri, Jul 01, 2016 at 11:19:05PM +0300, Octavian Purdila wrote:
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans
  2016-07-01 20:19 ` [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans Octavian Purdila
  2016-07-06 15:03   ` Mika Westerberg
@ 2016-07-07  9:28   ` Mika Westerberg
  1 sibling, 0 replies; 24+ messages in thread
From: Mika Westerberg @ 2016-07-07  9:28 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, linux-kernel, irina.tirdea, leonard.crestez

On Fri, Jul 01, 2016 at 11:19:06PM +0300, Octavian Purdila wrote:
> If the ACPI tables changes as a result of a dinamically loaded table and
> a bus rescan is required the enumeration/visited flag are not
> consistent.
> 
> I2C/SPI are not directly enumerated in acpi_bus_attach(), however the
> visited flag is set. This makes it impossible to check if an ACPI device
> has already been enumerated by the I2C and SPI subsystems. To fix this
> issue we only set the visited flags if the device is not I2C or SPI.
> 
> With this change we also need to remove setting visited to false from
> acpi_bus_attach(), otherwise if we rescan already enumerated I2C/SPI
> devices we try to re-enumerate them.
> 
> Note that I2C/SPI devices can be enumerated either via a scan handler
> (when using PRP0001) or via regular device_attach(). In either case
> the flow goes through acpi_default_enumeration() which makes it the
> ideal place to mark the ACPI device as enumerated.
> 
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 3/8] acpi: add support for ACPI reconfiguration notifiers
  2016-07-01 20:19 ` [PATCH v5 3/8] acpi: add support for ACPI reconfiguration notifiers Octavian Purdila
@ 2016-07-07  9:34   ` Mika Westerberg
  0 siblings, 0 replies; 24+ messages in thread
From: Mika Westerberg @ 2016-07-07  9:34 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, linux-kernel, irina.tirdea, leonard.crestez

On Fri, Jul 01, 2016 at 11:19:07PM +0300, Octavian Purdila wrote:
> Add support for ACPI reconfiguration notifiers to allow subsystems to
> react to changes in the ACPI tables that happen after the initial
> enumeration. This is similar with the way dynamic device tree
> notifications work.
> 
> The reconfigure notifications supported for now are device add and
> device remove.
> 
> Since ACPICA allows only one table notification handler, this patch
> makes the table notifier function generic and moves it out of the
> sysfs specific code.
> 
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>

One minor nitpick below but regardless of that,

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

> ---
>  drivers/acpi/bus.c      |  9 +++++++
>  drivers/acpi/internal.h |  3 +++
>  drivers/acpi/scan.c     | 68 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/acpi/sysfs.c    |  6 ++---
>  include/linux/acpi.h    | 18 +++++++++++++
>  5 files changed, 99 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
> index 262ca31..97e270e 100644
> --- a/drivers/acpi/bus.c
> +++ b/drivers/acpi/bus.c
> @@ -990,6 +990,13 @@ void __init acpi_subsystem_init(void)
>  	}
>  }
>  
> +static acpi_status acpi_bus_table_handler(u32 event, void *table, void *context)
> +{
> +	acpi_scan_table_handler(event, table, context);
> +
> +	return acpi_sysfs_table_handler(event, table, context);
> +}
> +
>  static int __init acpi_bus_init(void)
>  {
>  	int result;
> @@ -1043,6 +1050,8 @@ static int __init acpi_bus_init(void)
>  	 * _PDC control method may load dynamic SSDT tables,
>  	 * and we need to install the table handler before that.
>  	 */
> +	status = acpi_install_table_handler(acpi_bus_table_handler, NULL);
> +
>  	acpi_sysfs_init();
>  
>  	acpi_early_processor_set_pdc();
> diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> index 27cc7fe..940218f 100644
> --- a/drivers/acpi/internal.h
> +++ b/drivers/acpi/internal.h
> @@ -87,6 +87,9 @@ bool acpi_queue_hotplug_work(struct work_struct *work);
>  void acpi_device_hotplug(struct acpi_device *adev, u32 src);
>  bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
>  
> +acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context);
> +void acpi_scan_table_handler(u32 event, void *table, void *context);
> +
>  /* --------------------------------------------------------------------------
>                       Device Node Initialization / Removal
>     -------------------------------------------------------------------------- */
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index f80f8a7..6a9b5cb 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -494,6 +494,8 @@ static void acpi_device_del(struct acpi_device *device)
>  	device_del(&device->dev);
>  }
>  
> +static BLOCKING_NOTIFIER_HEAD(acpi_reconfig_chain);
> +
>  static LIST_HEAD(acpi_device_del_list);
>  static DEFINE_MUTEX(acpi_device_del_lock);
>  
> @@ -514,6 +516,9 @@ static void acpi_device_del_work_fn(struct work_struct *work_not_used)
>  
>  		mutex_unlock(&acpi_device_del_lock);
>  
> +		blocking_notifier_call_chain(&acpi_reconfig_chain,
> +					     ACPI_RECONFIG_DEVICE_REMOVE, adev);
> +
>  		acpi_device_del(adev);
>  		/*
>  		 * Drop references to all power resources that might have been
> @@ -1676,7 +1681,7 @@ static void acpi_default_enumeration(struct acpi_device *device)
>  	bool is_spi_i2c_slave = false;
>  
>  	/*
> -	 * Do not enemerate SPI/I2C slaves as they will be enuerated by their
> +	 * Do not enemerate SPI/I2C slaves as they will be enumerated by their

You could fix the other typo here while you are there

	enemerate -> enumerate

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 7/8] acpi: add support for configfs
  2016-07-01 20:19 ` [PATCH v5 7/8] acpi: add support for configfs Octavian Purdila
@ 2016-07-07  9:39   ` Mika Westerberg
  0 siblings, 0 replies; 24+ messages in thread
From: Mika Westerberg @ 2016-07-07  9:39 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, linux-kernel, irina.tirdea, leonard.crestez

On Fri, Jul 01, 2016 at 11:19:11PM +0300, Octavian Purdila wrote:
> Register the ACPI subsystem with configfs.
> 
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>

Couple of nitpicks below but regardless of those,

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

> ---
>  Documentation/ABI/testing/configfs-acpi |  7 +++++
>  MAINTAINERS                             |  1 +
>  drivers/acpi/Kconfig                    |  9 ++++++
>  drivers/acpi/Makefile                   |  1 +
>  drivers/acpi/configfs.c                 | 53 +++++++++++++++++++++++++++++++++
>  5 files changed, 71 insertions(+)
>  create mode 100644 Documentation/ABI/testing/configfs-acpi
>  create mode 100644 drivers/acpi/configfs.c
> 
> diff --git a/Documentation/ABI/testing/configfs-acpi b/Documentation/ABI/testing/configfs-acpi
> new file mode 100644
> index 0000000..17b19dc
> --- /dev/null
> +++ b/Documentation/ABI/testing/configfs-acpi
> @@ -0,0 +1,7 @@
> +What:		/config/acpi
> +Date:		July 2016
> +KernelVersion:	4.8
> +Contact:	linux-acpi@vger.kernel.org
> +Description:
> +		This represents the ACPI subsystem entry point directory. It
> +		contains sub-groups corresponding to ACPI configurable options.
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 16700e4..9c5365f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -288,6 +288,7 @@ F:	include/linux/acpi.h
>  F:	include/acpi/
>  F:	Documentation/acpi/
>  F:	Documentation/ABI/testing/sysfs-bus-acpi
> +F:	Documentation/ABI/testing/configfs-acpi
>  F:	drivers/pci/*acpi*
>  F:	drivers/pci/*/*acpi*
>  F:	drivers/pci/*/*/*acpi*
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index b7e2e77..a039433 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -521,4 +521,13 @@ config XPOWER_PMIC_OPREGION
>  
>  endif
>  
> +config ACPI_CONFIGFS
> +	tristate "ACPI configfs support"
> +	select CONFIGFS_FS
> +	default n

We default to n so this is not needed.

> +	help
> +	  Select this option to enable support for ACPI configuration from
> +	  userspace. The configurable ACPI groups will be visible under
> +	  /config/acpi, assuming configfs is mounted under /config.
> +
>  endif	# ACPI
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 251ce85..1dc2173 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -99,5 +99,6 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
>  obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
>  obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
>  obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
> +obj-$(CONFIG_ACPI_CONFIGFS)	+= configfs.o
>  
>  video-objs			+= acpi_video.o video_detect.o
> diff --git a/drivers/acpi/configfs.c b/drivers/acpi/configfs.c
> new file mode 100644
> index 0000000..44a72ff
> --- /dev/null
> +++ b/drivers/acpi/configfs.c
> @@ -0,0 +1,53 @@
> +/*
> + * ACPI configfs support
> + *
> + * Copyright (c) 2015 Intel Corporation

It is 2016 now.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v5 8/8] acpi: add support for loading SSDTs via configfs
  2016-07-01 20:19 ` [PATCH v5 8/8] acpi: add support for loading SSDTs via configfs Octavian Purdila
@ 2016-07-07  9:42   ` Mika Westerberg
  0 siblings, 0 replies; 24+ messages in thread
From: Mika Westerberg @ 2016-07-07  9:42 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Rafael J . Wysocki, Len Brown, Matt Fleming, Mark Brown,
	Wolfram Sang, Joel Becker, linux-acpi, linux-efi, linux-i2c,
	linux-spi, linux-kernel, irina.tirdea, leonard.crestez

On Fri, Jul 01, 2016 at 11:19:12PM +0300, Octavian Purdila wrote:
> New tables can be loaded by creating directories under /config/table/
> and writing the AML code into the aml table attribute. Various table
> attributes will be readable once the table is successfully loaded.
> 
> Unloading tables is not supported at the moment, but it can be easily
> implemented once ACPI loading functions provide a table handle to be
> used for unloading.
> 
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2016-07-07  9:42 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-01 20:19 [PATCH v5 0/8] ACPI overlays Octavian Purdila
2016-07-01 20:19 ` [PATCH v5 1/8] Documentation: acpi: add SSDT overlays documentation Octavian Purdila
2016-07-07  9:25   ` Mika Westerberg
2016-07-01 20:19 ` [PATCH v5 2/8] acpi: fix enumeration (visited) flags for bus rescans Octavian Purdila
2016-07-06 15:03   ` Mika Westerberg
2016-07-06 15:37     ` Octavian Purdila
2016-07-06 21:09       ` Rafael J. Wysocki
2016-07-07  9:00         ` Mika Westerberg
2016-07-07  9:28   ` Mika Westerberg
2016-07-01 20:19 ` [PATCH v5 3/8] acpi: add support for ACPI reconfiguration notifiers Octavian Purdila
2016-07-07  9:34   ` Mika Westerberg
2016-07-01 20:19 ` [PATCH v5 4/8] i2c: add support for ACPI reconfigure notifications Octavian Purdila
2016-07-04  0:34   ` Wolfram Sang
2016-07-01 20:19 ` [PATCH v5 5/8] spi: " Octavian Purdila
2016-07-03 12:10   ` Mark Brown
2016-07-01 20:19 ` [PATCH v5 6/8] efi: load SSTDs from EFI variables Octavian Purdila
2016-07-02  8:18   ` Geert Uytterhoeven
2016-07-04 12:00   ` Matt Fleming
2016-07-01 20:19 ` [PATCH v5 7/8] acpi: add support for configfs Octavian Purdila
2016-07-07  9:39   ` Mika Westerberg
2016-07-01 20:19 ` [PATCH v5 8/8] acpi: add support for loading SSDTs via configfs Octavian Purdila
2016-07-07  9:42   ` Mika Westerberg
2016-07-06  0:34 ` [PATCH v5 0/8] ACPI overlays Rafael J. Wysocki
2016-07-06  6:29   ` Octavian Purdila

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).