aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2012-10-31 17:44:33 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-14 18:28:00 -0500
commit06f64c8f239a47b359c60301914c783b56b32c13 (patch)
tree3381ac14daf445c8c07fff9d130219eb6d8f4d61
parent77b67063bb6bce6d475e910d3b886a606d0d91f7 (diff)
driver core / ACPI: Move ACPI support to core device and driver types
With ACPI 5 we are starting to see devices that don't natively support discovery but can be enumerated with the help of the ACPI namespace. Typically, these devices can be represented in the Linux device driver model as platform devices or some serial bus devices, like SPI or I2C devices. Since we want to re-use existing drivers for those devices, we need a way for drivers to specify the ACPI IDs of supported devices, so that they can be matched against device nodes in the ACPI namespace. To this end, it is sufficient to add a pointer to an array of supported ACPI device IDs, that can be provided by the driver, to struct device. Moreover, things like ACPI power management need to have access to the ACPI handle of each supported device, because that handle is used to invoke AML methods associated with the corresponding ACPI device node. The ACPI handles of devices are now stored in the archdata member structure of struct device whose definition depends on the architecture and includes the ACPI handle only on x86 and ia64. Since the pointer to an array of supported ACPI IDs is added to struct device_driver in an architecture-independent way, it is logical to move the ACPI handle from archdata to struct device itself at the same time. This also makes code more straightforward in some places and follows the example of Device Trees that have a poiter to struct device_node in there too. This changeset is based on Mika Westerberg's work. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: H. Peter Anvin <hpa@zytor.com> Acked-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--arch/ia64/include/asm/device.h3
-rw-r--r--arch/x86/include/asm/device.h3
-rw-r--r--drivers/acpi/glue.c14
-rw-r--r--include/acpi/acpi_bus.h2
-rw-r--r--include/linux/device.h4
5 files changed, 11 insertions, 15 deletions
diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h
index d05e78f6db94..f69c32ffbe6a 100644
--- a/arch/ia64/include/asm/device.h
+++ b/arch/ia64/include/asm/device.h
@@ -7,9 +7,6 @@
7#define _ASM_IA64_DEVICE_H 7#define _ASM_IA64_DEVICE_H
8 8
9struct dev_archdata { 9struct dev_archdata {
10#ifdef CONFIG_ACPI
11 void *acpi_handle;
12#endif
13#ifdef CONFIG_INTEL_IOMMU 10#ifdef CONFIG_INTEL_IOMMU
14 void *iommu; /* hook for IOMMU specific extension */ 11 void *iommu; /* hook for IOMMU specific extension */
15#endif 12#endif
diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h
index 93e1c55f14ab..03dd72957d2f 100644
--- a/arch/x86/include/asm/device.h
+++ b/arch/x86/include/asm/device.h
@@ -2,9 +2,6 @@
2#define _ASM_X86_DEVICE_H 2#define _ASM_X86_DEVICE_H
3 3
4struct dev_archdata { 4struct dev_archdata {
5#ifdef CONFIG_ACPI
6 void *acpi_handle;
7#endif
8#ifdef CONFIG_X86_DEV_DMA_OPS 5#ifdef CONFIG_X86_DEV_DMA_OPS
9 struct dma_map_ops *dma_ops; 6 struct dma_map_ops *dma_ops;
10#endif 7#endif
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 08373086cd7e..2f3849aedc97 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -134,7 +134,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
134 char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; 134 char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
135 int retval = -EINVAL; 135 int retval = -EINVAL;
136 136
137 if (dev->archdata.acpi_handle) { 137 if (dev->acpi_handle) {
138 dev_warn(dev, "Drivers changed 'acpi_handle'\n"); 138 dev_warn(dev, "Drivers changed 'acpi_handle'\n");
139 return -EINVAL; 139 return -EINVAL;
140 } 140 }
@@ -169,7 +169,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
169 acpi_dev->physical_node_count++; 169 acpi_dev->physical_node_count++;
170 mutex_unlock(&acpi_dev->physical_node_lock); 170 mutex_unlock(&acpi_dev->physical_node_lock);
171 171
172 dev->archdata.acpi_handle = handle; 172 dev->acpi_handle = handle;
173 173
174 if (!physical_node->node_id) 174 if (!physical_node->node_id)
175 strcpy(physical_node_name, PHYSICAL_NODE_STRING); 175 strcpy(physical_node_name, PHYSICAL_NODE_STRING);
@@ -198,11 +198,10 @@ static int acpi_unbind_one(struct device *dev)
198 acpi_status status; 198 acpi_status status;
199 struct list_head *node, *next; 199 struct list_head *node, *next;
200 200
201 if (!dev->archdata.acpi_handle) 201 if (!dev->acpi_handle)
202 return 0; 202 return 0;
203 203
204 status = acpi_bus_get_device(dev->archdata.acpi_handle, 204 status = acpi_bus_get_device(dev->acpi_handle, &acpi_dev);
205 &acpi_dev);
206 if (ACPI_FAILURE(status)) 205 if (ACPI_FAILURE(status))
207 goto err; 206 goto err;
208 207
@@ -228,7 +227,7 @@ static int acpi_unbind_one(struct device *dev)
228 227
229 sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name); 228 sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
230 sysfs_remove_link(&dev->kobj, "firmware_node"); 229 sysfs_remove_link(&dev->kobj, "firmware_node");
231 dev->archdata.acpi_handle = NULL; 230 dev->acpi_handle = NULL;
232 /* acpi_bind_one increase refcnt by one */ 231 /* acpi_bind_one increase refcnt by one */
233 put_device(dev); 232 put_device(dev);
234 kfree(entry); 233 kfree(entry);
@@ -269,8 +268,7 @@ static int acpi_platform_notify(struct device *dev)
269 if (!ret) { 268 if (!ret) {
270 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 269 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
271 270
272 acpi_get_name(dev->archdata.acpi_handle, 271 acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
273 ACPI_FULL_PATHNAME, &buffer);
274 DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); 272 DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
275 kfree(buffer.pointer); 273 kfree(buffer.pointer);
276 } else 274 } else
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 0daa0fbd8654..bb1537c5e672 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -410,7 +410,7 @@ acpi_handle acpi_get_child(acpi_handle, u64);
410int acpi_is_root_bridge(acpi_handle); 410int acpi_is_root_bridge(acpi_handle);
411acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); 411acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
412struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); 412struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
413#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) 413#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->acpi_handle))
414 414
415int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); 415int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
416int acpi_disable_wakeup_device_power(struct acpi_device *dev); 416int acpi_disable_wakeup_device_power(struct acpi_device *dev);
diff --git a/include/linux/device.h b/include/linux/device.h
index 86ef6ab553b1..cc3aee57a46e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -190,6 +190,7 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus);
190 * @mod_name: Used for built-in modules. 190 * @mod_name: Used for built-in modules.
191 * @suppress_bind_attrs: Disables bind/unbind via sysfs. 191 * @suppress_bind_attrs: Disables bind/unbind via sysfs.
192 * @of_match_table: The open firmware table. 192 * @of_match_table: The open firmware table.
193 * @acpi_match_table: The ACPI match table.
193 * @probe: Called to query the existence of a specific device, 194 * @probe: Called to query the existence of a specific device,
194 * whether this driver can work with it, and bind the driver 195 * whether this driver can work with it, and bind the driver
195 * to a specific device. 196 * to a specific device.
@@ -223,6 +224,7 @@ struct device_driver {
223 bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ 224 bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
224 225
225 const struct of_device_id *of_match_table; 226 const struct of_device_id *of_match_table;
227 const struct acpi_device_id *acpi_match_table;
226 228
227 int (*probe) (struct device *dev); 229 int (*probe) (struct device *dev);
228 int (*remove) (struct device *dev); 230 int (*remove) (struct device *dev);
@@ -616,6 +618,7 @@ struct device_dma_parameters {
616 * @dma_mem: Internal for coherent mem override. 618 * @dma_mem: Internal for coherent mem override.
617 * @archdata: For arch-specific additions. 619 * @archdata: For arch-specific additions.
618 * @of_node: Associated device tree node. 620 * @of_node: Associated device tree node.
621 * @acpi_handle: Associated ACPI device node's namespace handle.
619 * @devt: For creating the sysfs "dev". 622 * @devt: For creating the sysfs "dev".
620 * @id: device instance 623 * @id: device instance
621 * @devres_lock: Spinlock to protect the resource of the device. 624 * @devres_lock: Spinlock to protect the resource of the device.
@@ -680,6 +683,7 @@ struct device {
680 struct dev_archdata archdata; 683 struct dev_archdata archdata;
681 684
682 struct device_node *of_node; /* associated device tree node */ 685 struct device_node *of_node; /* associated device tree node */
686 void *acpi_handle; /* associated ACPI device node */
683 687
684 dev_t devt; /* dev_t, creates the sysfs "dev" */ 688 dev_t devt; /* dev_t, creates the sysfs "dev" */
685 u32 id; /* device instance */ 689 u32 id; /* device instance */