Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1421858 > unrolled thread
| Started by | Octavian Purdila <octavian.purdila@intel.com> |
|---|---|
| First post | 2016-06-14 14:20 +0200 |
| Last post | 2016-06-15 12:40 +0200 |
| Articles | 4 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v3 0/8] ACPI overlays Octavian Purdila <octavian.purdila@intel.com> - 2016-06-14 14:20 +0200
[PATCH v3 4/8] i2c: add support for ACPI reconfigure notifications Octavian Purdila <octavian.purdila@intel.com> - 2016-06-14 14:20 +0200
Re: [PATCH v3 4/8] i2c: add support for ACPI reconfigure notifications Wolfram Sang <wsa@the-dreams.de> - 2016-06-15 08:30 +0200
Re: [PATCH v3 4/8] i2c: add support for ACPI reconfigure notifications Octavian Purdila <octavian.purdila@intel.com> - 2016-06-15 12:40 +0200
| From | Octavian Purdila <octavian.purdila@intel.com> |
|---|---|
| Date | 2016-06-14 14:20 +0200 |
| Subject | [PATCH v3 0/8] ACPI overlays |
| Message-ID | <rJVu1-4HM-3@gated-at.bofh.it> |
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 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 | 79 +++++++++- drivers/acpi/sysfs.c | 6 +- drivers/firmware/efi/efi.c | 106 +++++++++++++ drivers/i2c/i2c-core.c | 170 +++++++++++++++----- drivers/spi/spi.c | 94 ++++++++++- include/linux/acpi.h | 18 +++ 15 files changed, 924 insertions(+), 54 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
[toc] | [next] | [standalone]
| From | Octavian Purdila <octavian.purdila@intel.com> |
|---|---|
| Date | 2016-06-14 14:20 +0200 |
| Subject | [PATCH v3 4/8] i2c: add support for ACPI reconfigure notifications |
| Message-ID | <rJVu2-4HM-27@gated-at.bofh.it> |
| In reply to | #1421858 |
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.
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
drivers/i2c/i2c-core.c | 170 ++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 132 insertions(+), 38 deletions(-)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index af11b65..18f7b19 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)) {
+ adev->flags.visited = true;
+
+ 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,77 @@ 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:
+ 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
@@ -2117,6 +2207,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 +2224,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
[toc] | [prev] | [next] | [standalone]
| From | Wolfram Sang <wsa@the-dreams.de> |
|---|---|
| Date | 2016-06-15 08:30 +0200 |
| Subject | Re: [PATCH v3 4/8] i2c: add support for ACPI reconfigure notifications |
| Message-ID | <rKcuS-7lr-17@gated-at.bofh.it> |
| In reply to | #1421859 |
[Multipart message — attachments visible in raw view] — view raw
On Tue, Jun 14, 2016 at 06:17:22PM +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. > > Signed-off-by: Octavian Purdila <octavian.purdila@intel.com> What happened to Mika's reviewed-by?
[toc] | [prev] | [next] | [standalone]
| From | Octavian Purdila <octavian.purdila@intel.com> |
|---|---|
| Date | 2016-06-15 12:40 +0200 |
| Subject | Re: [PATCH v3 4/8] i2c: add support for ACPI reconfigure notifications |
| Message-ID | <rKgoN-1mz-15@gated-at.bofh.it> |
| In reply to | #1422653 |
On Wed, Jun 15, 2016 at 9:27 AM, Wolfram Sang <wsa@the-dreams.de> wrote: > On Tue, Jun 14, 2016 at 06:17:22PM +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. >> >> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com> > > What happened to Mika's reviewed-by? > Missed that, I will send a new series soon to correct a bisectability issues reported by kbuild and I'll add with Mika's reviewed-bys.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web