lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 08 Nov 2012 01:46:24 +0100
From:	"Rafael J. Wysocki" <rjw@...k.pl>
To:	Mika Westerberg <mika.westerberg@...ux.intel.com>
Cc:	Bjorn Helgaas <bhelgaas@...gle.com>, linux-kernel@...r.kernel.org,
	lenb@...nel.org, rafael.j.wysocki@...el.com,
	broonie@...nsource.wolfsonmicro.com, grant.likely@...retlab.ca,
	linus.walleij@...aro.org, khali@...ux-fr.org, ben-linux@...ff.org,
	w.sang@...gutronix.de, mathias.nyman@...ux.intel.com,
	linux-acpi@...r.kernel.org
Subject: Re: [PATCH 2/3] spi / ACPI: add ACPI enumeration support

On Wednesday, November 07, 2012 03:05:48 PM Mika Westerberg wrote:
> On Wed, Nov 07, 2012 at 12:14:31PM +0100, Rafael J. Wysocki wrote:
> > > So is the idea now that the ACPI core parses the resources and passes them
> > > forward via struct acpi_device? I'm just wondering how to proceed with
> > > these I2C and SPI enumeration patches.
> > 
> > Well, we definitely don't want to duplicate what drivers/pnp/pnpacpi/rsparser.c
> > does, so the idea is to move the code from there to the core in such a way that
> > both the SPI/I2C patches and the PNP layer can use it.
> 
> Ok.
> 
> > I'll have some prototype code ready shortly, hopefully, and I'll post it
> > in that form for comments (and so that you know what to expect).
> 
> Sounds good. Thanks!

There you go.

I haven't even try to compile it, so most likely it breaks things left, right
and in between, but I hope it shows the idea.

It does a couple of things at the same time, so it should be split into a few
simpler patches.  First, it moves some code from drivers/pnp/pnpacpi/rsparser.c
to a new file drivers/acpi/resource.c and makes pnpacpi use functions from
there.  Second, it changes acpi_platform.c to use those functions too.
Finally, it adds a list of ACPI resources to struct acpi_device and
makes acpi_platform.c use that list intead of evaluating _CRS and parsing its
output with acpi_walk_resources().

While changing acpi_platform.c I noticed that we had a bug in there, because
GSIs were registered for the struct acpi_device object, although they should be
registered for the struct platform_device one created by that code.  I didn't
try to fix that in the patch below, but it generally needs fixing.

Thanks,
Rafael


Prototype, no sign-off.
---
 drivers/acpi/Makefile          |    1 
 drivers/acpi/acpi_platform.c   |  122 +++++-------------
 drivers/acpi/resource.c        |  269 +++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/scan.c            |   48 +++++++
 drivers/pnp/base.h             |    2 
 drivers/pnp/pnpacpi/rsparser.c |  150 +---------------------
 drivers/pnp/resource.c         |   16 ++
 include/acpi/acpi_bus.h        |    6 
 8 files changed, 386 insertions(+), 228 deletions(-)

Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -259,6 +259,11 @@ struct acpi_device_physical_node {
 	struct device *dev;
 };
 
+struct acpi_resource_list_entry {
+	struct list_head node;
+	struct acpi_resource resource;
+};
+
 /* set maximum of physical nodes to 32 for expansibility */
 #define ACPI_MAX_PHYSICAL_NODE	32
 
@@ -269,6 +274,7 @@ struct acpi_device {
 	struct acpi_device *parent;
 	struct list_head children;
 	struct list_head node;
+	struct list_head resources;	/* Device resources. */
 	struct list_head wakeup_list;
 	struct acpi_device_status status;
 	struct acpi_device_flags flags;
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -670,6 +670,8 @@ end:
 
 static void acpi_device_unregister(struct acpi_device *device, int type)
 {
+	struct acpi_resource_list_entry *entry, *s;
+
 	mutex_lock(&acpi_device_lock);
 	if (device->parent)
 		list_del(&device->node);
@@ -681,6 +683,9 @@ static void acpi_device_unregister(struc
 
 	acpi_device_remove_files(device);
 	device_unregister(&device->dev);
+
+	list_for_each_entry_safe(entry, s, &device->resources, node)
+		kfree(entry);
 }
 
 /* --------------------------------------------------------------------------
@@ -990,6 +995,40 @@ static void acpi_bus_get_wakeup_device_f
 				"error in _DSW or _PSW evaluation\n"));
 }
 
+static acpi_status acpi_bus_add_resource(struct acpi_resource *res,
+					 void *context)
+{
+	struct list_head *list = context;
+	struct acpi_resource_list_entry *entry;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return AE_NO_MEMORY;
+
+	entry->resource = *res;
+	list_add_tail(&entry->node, list);
+	return AE_OK;
+}
+
+static int acpi_bus_get_resources(struct acpi_device *adev)
+{
+	acpi_status status;
+	int ret = 0;
+
+	status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
+				     acpi_bus_add_resource, &adev->resources);
+	if (ACPI_FAILURE(status)) {
+		switch(status) {
+		case AE_NO_MEMORY:
+			ret = -ENOMEM;
+			break;
+		default:
+			ret = -EIO;
+		}
+	}
+	return ret;
+}
+
 static void acpi_bus_add_power_resource(acpi_handle handle);
 
 static int acpi_bus_get_power_flags(struct acpi_device *device)
@@ -1412,6 +1451,15 @@ static int acpi_add_single_object(struct
 	acpi_device_set_id(device);
 
 	/*
+	 * Device Resources
+	 * ----------------
+	 */
+	INIT_LIST_HEAD(&device->resources);
+	result = acpi_bus_get_resources(device);
+	if (result)
+		goto end;
+
+	/*
 	 * Power Management
 	 * ----------------
 	 */
Index: linux-pm/drivers/acpi/resource.c
===================================================================
--- /dev/null
+++ linux-pm/drivers/acpi/resource.c
@@ -0,0 +1,269 @@
+/*
+ * drivers/acpi/resource.c - ACPI device resources management.
+ *
+ * Copyright (C) 2012, Intel Corp.
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@...el.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/ioport.h>
+
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+
+static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect,
+						bool window)
+{
+	unsigned long flags = IORESOURCE_MEM;
+
+	if (len == 0)
+		flags |= IORESOURCE_DISABLED;
+
+	if (write_protect == ACPI_READ_WRITE_MEMORY)
+		flags |= IORESOURCE_MEM_WRITEABLE;
+
+	if (window)
+		flags |= IORESOURCE_WINDOW;
+
+	return flags;
+}
+
+static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
+				     u8 write_protect)
+{
+	res->start = start;
+	res->end = start + len - 1;
+	res->flags = acpi_dev_memresource_flags(len, write_protect, false);
+}
+
+/**
+ * acpi_dev_resource_memory - Extract ACPI memory resource information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents a memory resource and
+ * if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
+{
+	struct acpi_resource_memory24 *memory24;
+	struct acpi_resource_memory32 *memory32;
+	struct acpi_resource_fixed_memory32 *fixed_memory32;
+
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_MEMORY24:
+		memory24 = &ares->data.memory24;
+		acpi_dev_get_memresource(res, memory24->minimum,
+					 memory24->address_length,
+					 memory24->write_protect);
+		break;
+	case ACPI_RESOURCE_TYPE_MEMORY32:
+		memory32 = &ares->data.memory32;
+		acpi_dev_get_memresource(res, memory32->minimum,
+					 memory32->address_length,
+					 memory32->write_protect);
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+		fixed_memory32 = &ares->data.fixed_memory32;
+		acpi_dev_get_memresource(res, fixed_memory32->address,
+					 fixed_memory32->address_length,
+					 fixed_memory32->write_protect);
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
+
+static void acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode,
+				      bool window)
+{
+	int flags = IORESOURCE_IO;
+
+	if (io_decode == ACPI_DECODE_16)
+		flags |= IORESOURCE_IO_16BIT_ADDR;
+
+	if (start > end || end >= 0x10003)
+		flags |= IORESOURCE_DISABLED;
+
+	if (window)
+		flags |= IORESOURCE_WINDOW;
+
+	return flags;
+}
+
+static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
+				    u8 io_decode)
+{
+	u64 end = start + len - 1;
+
+	res->start = start;
+	res->end = end;
+	res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false);
+}
+
+/**
+ * acpi_dev_resource_io - Extract ACPI I/O resource information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an I/O resource and
+ * if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
+{
+	struct acpi_resource_io *io;
+	struct acpi_resource_fixed_io *fixed_io;
+
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_IO:
+		io = &ares->data.io;
+		acpi_dev_get_ioresource(res, io->minimum,
+					  io->address_length,
+					  io->io_decode);
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO
+		fixed_io = &res->data.fixed_io;
+		acpi_dev_get_ioresource(res, fixed_io->address,
+					  fixed_io->address_length,
+					  ACPI_DECODE_10);
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
+
+/**
+ * acpi_dev_resource_address_space - Extract ACPI address space information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an address space resource
+ * and if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_address_space(struct acpi_resource *ares,
+				     struct resource *res)
+{
+	acpi_status status;
+	struct acpi_resource_address64 addr;
+	bool window;
+	u64 len;
+	u8 io_decode;
+
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		break;
+	default:
+		return false;
+	}
+
+	status = acpi_resource_to_address64(ares, &addr);
+	if (ACPI_FAILURE(status))
+		return true;
+
+	res->start = addr.minimum;
+	res->end = addr.maximum;
+	window = addr.producer_consumer == ACPI_PRODUCER;
+
+	switch(resource_type) {
+	case ACPI_MEMORY_RANGE:
+		len = addr.maximum - addr.minimum + 1;
+		res->flags = acpi_dev_memresource_flags(len,
+						addr.info.mem.write_protect,
+						window);
+		break;
+	case ACPI_IO_RANGE:
+		io_decode = addr.granularity == 0xfff ?
+				ACPI_DECODE_10 : ACPI_DECODE_16;
+		res->flags = acpi_dev_ioresource_flags(addr.minimum,
+						       addr.maximum,
+						       io_decode, window);
+		break;
+	case ACPI_BUS_NUMBER_RANGE:
+		res->flags = IORESOURCE_BUS;
+		break;
+	default:
+		res->flags = 0;
+	}
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
+
+/**
+ * acpi_dev_resource_ext_address_space - Extract ACPI address space information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an extended address space
+ * resource and if that's the case, use the information in it to populate the
+ * generic resource object pointed to by @res.
+ */
+bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
+					 struct resource *res)
+{
+	acpi_status status;
+	struct acpi_resource_extended_address64 *ext_addr;
+	bool window;
+	u64 len;
+	u8 io_decode;
+
+	if (res->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
+		return false;
+
+	ext_addr = &res->data.ext_address64;
+
+	res->start = ext_addr->minimum;
+	res->end = ext_addr->maximum;
+	window = ext_addr->producer_consumer == ACPI_PRODUCER;
+
+	switch(resource_type) {
+	case ACPI_MEMORY_RANGE:
+		len = ext_addr->maximum - ext_addr->minimum + 1;
+		res->flags = acpi_dev_memresource_flags(len,
+					ext_addr->info.mem.write_protect,
+					window);
+		break;
+	case ACPI_IO_RANGE:
+		io_decode = ext_addr->granularity == 0xfff ?
+				ACPI_DECODE_10 : ACPI_DECODE_16;
+		res->flags = acpi_dev_ioresource_flags(ext_addr->minimum,
+						       ext_addr->maximum,
+						       io_decode, window);
+		break;
+	case ACPI_BUS_NUMBER_RANGE:
+		res->flags = IORESOURCE_BUS;
+		break;
+	default:
+		res->flags = 0;
+	}
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
Index: linux-pm/drivers/acpi/Makefile
===================================================================
--- linux-pm.orig/drivers/acpi/Makefile
+++ linux-pm/drivers/acpi/Makefile
@@ -33,6 +33,7 @@ acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o
 #
 acpi-y				+= bus.o glue.o
 acpi-y				+= scan.o
+acpi-y				+= resource.o
 acpi-y				+= processor_core.o
 acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
Index: linux-pm/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- linux-pm.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux-pm/drivers/pnp/pnpacpi/rsparser.c
@@ -177,23 +177,6 @@ static int dma_flags(struct pnp_dev *dev
 	return flags;
 }
 
-static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
-					       u64 len, int io_decode,
-					       int window)
-{
-	int flags = 0;
-	u64 end = start + len - 1;
-
-	if (io_decode == ACPI_DECODE_16)
-		flags |= IORESOURCE_IO_16BIT_ADDR;
-	if (len == 0 || end >= 0x10003)
-		flags |= IORESOURCE_DISABLED;
-	if (window)
-		flags |= IORESOURCE_WINDOW;
-
-	pnp_add_io_resource(dev, start, end, flags);
-}
-
 /*
  * Device CSRs that do not appear in PCI config space should be described
  * via ACPI.  This would normally be done with Address Space Descriptors
@@ -249,83 +232,6 @@ static void pnpacpi_parse_allocated_vend
 	}
 }
 
-static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
-						u64 start, u64 len,
-						int write_protect, int window)
-{
-	int flags = 0;
-	u64 end = start + len - 1;
-
-	if (len == 0)
-		flags |= IORESOURCE_DISABLED;
-	if (write_protect == ACPI_READ_WRITE_MEMORY)
-		flags |= IORESOURCE_MEM_WRITEABLE;
-	if (window)
-		flags |= IORESOURCE_WINDOW;
-
-	pnp_add_mem_resource(dev, start, end, flags);
-}
-
-static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
-						u64 start, u64 len)
-{
-	u64 end = start + len - 1;
-
-	pnp_add_bus_resource(dev, start, end);
-}
-
-static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
-						  struct acpi_resource *res)
-{
-	struct acpi_resource_address64 addr, *p = &addr;
-	acpi_status status;
-	int window;
-	u64 len;
-
-	status = acpi_resource_to_address64(res, p);
-	if (!ACPI_SUCCESS(status)) {
-		dev_warn(&dev->dev, "failed to convert resource type %d\n",
-			 res->type);
-		return;
-	}
-
-	/* Windows apparently computes length rather than using _LEN */
-	len = p->maximum - p->minimum + 1;
-	window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
-
-	if (p->resource_type == ACPI_MEMORY_RANGE)
-		pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
-			p->info.mem.write_protect, window);
-	else if (p->resource_type == ACPI_IO_RANGE)
-		pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
-			p->granularity == 0xfff ? ACPI_DECODE_10 :
-				ACPI_DECODE_16, window);
-	else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
-		pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
-}
-
-static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
-						      struct acpi_resource *res)
-{
-	struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
-	int window;
-	u64 len;
-
-	/* Windows apparently computes length rather than using _LEN */
-	len = p->maximum - p->minimum + 1;
-	window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
-
-	if (p->resource_type == ACPI_MEMORY_RANGE)
-		pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
-			p->info.mem.write_protect, window);
-	else if (p->resource_type == ACPI_IO_RANGE)
-		pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
-			p->granularity == 0xfff ? ACPI_DECODE_10 :
-				ACPI_DECODE_16, window);
-	else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
-		pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
-}
-
 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 					      void *data)
 {
@@ -339,8 +245,17 @@ static acpi_status pnpacpi_allocated_res
 	struct acpi_resource_memory32 *memory32;
 	struct acpi_resource_fixed_memory32 *fixed_memory32;
 	struct acpi_resource_extended_irq *extended_irq;
+	struct resource r;
 	int i, flags;
 
+	if (acpi_dev_resource_memory(res, &r)
+	    || acpi_dev_resource_io(res, &r)
+	    || acpi_dev_resource_address_space(res, &r)
+	    || acpi_dev_resource_ext_address_space(res, &r))
+		pnp_add_resource(dev, &r);
+		return AE_OK;
+	}
+
 	switch (res->type) {
 	case ACPI_RESOURCE_TYPE_IRQ:
 		/*
@@ -383,26 +298,10 @@ static acpi_status pnpacpi_allocated_res
 		pnp_add_dma_resource(dev, dma->channels[0], flags);
 		break;
 
-	case ACPI_RESOURCE_TYPE_IO:
-		io = &res->data.io;
-		pnpacpi_parse_allocated_ioresource(dev,
-			io->minimum,
-			io->address_length,
-			io->io_decode, 0);
-		break;
-
 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 		break;
 
-	case ACPI_RESOURCE_TYPE_FIXED_IO:
-		fixed_io = &res->data.fixed_io;
-		pnpacpi_parse_allocated_ioresource(dev,
-			fixed_io->address,
-			fixed_io->address_length,
-			ACPI_DECODE_10, 0);
-		break;
-
 	case ACPI_RESOURCE_TYPE_VENDOR:
 		vendor_typed = &res->data.vendor_typed;
 		pnpacpi_parse_allocated_vendor(dev, vendor_typed);
@@ -411,37 +310,6 @@ static acpi_status pnpacpi_allocated_res
 	case ACPI_RESOURCE_TYPE_END_TAG:
 		break;
 
-	case ACPI_RESOURCE_TYPE_MEMORY24:
-		memory24 = &res->data.memory24;
-		pnpacpi_parse_allocated_memresource(dev,
-			memory24->minimum,
-			memory24->address_length,
-			memory24->write_protect, 0);
-		break;
-	case ACPI_RESOURCE_TYPE_MEMORY32:
-		memory32 = &res->data.memory32;
-		pnpacpi_parse_allocated_memresource(dev,
-			memory32->minimum,
-			memory32->address_length,
-			memory32->write_protect, 0);
-		break;
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		fixed_memory32 = &res->data.fixed_memory32;
-		pnpacpi_parse_allocated_memresource(dev,
-			fixed_memory32->address,
-			fixed_memory32->address_length,
-			fixed_memory32->write_protect, 0);
-		break;
-	case ACPI_RESOURCE_TYPE_ADDRESS16:
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		pnpacpi_parse_allocated_address_space(dev, res);
-		break;
-
-	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
-		pnpacpi_parse_allocated_ext_address_space(dev, res);
-		break;
-
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		extended_irq = &res->data.extended_irq;
 
Index: linux-pm/drivers/pnp/base.h
===================================================================
--- linux-pm.orig/drivers/pnp/base.h
+++ linux-pm/drivers/pnp/base.h
@@ -159,6 +159,8 @@ struct pnp_resource {
 
 void pnp_free_resource(struct pnp_resource *pnp_res);
 
+struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
+				      struct resource *res);
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
 					  int flags);
 struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
Index: linux-pm/drivers/pnp/resource.c
===================================================================
--- linux-pm.orig/drivers/pnp/resource.c
+++ linux-pm/drivers/pnp/resource.c
@@ -503,6 +503,22 @@ static struct pnp_resource *pnp_new_reso
 	return pnp_res;
 }
 
+struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
+				      struct resource *res)
+{
+	struct pnp_resource *pnp_res;
+
+	pnp_res = pnp_new_resource(dev);
+	if (!pnp_res) {
+		dev_err(&dev->dev, "can't add resource %pR\n", res);
+		return NULL;
+	}
+
+	pnp_res->res = *res;
+	dev_dbg(&dev->dev, "%pR\n", res);
+	return pnp_res;
+}
+
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
 					  int flags)
 {
Index: linux-pm/drivers/acpi/acpi_platform.c
===================================================================
--- linux-pm.orig/drivers/acpi/acpi_platform.c
+++ linux-pm/drivers/acpi/acpi_platform.c
@@ -19,76 +19,30 @@
 
 ACPI_MODULE_NAME("platform");
 
-struct resource_info {
-	struct device *dev;
-	struct resource *res;
-	size_t n, cur;
-};
-
-static acpi_status acpi_platform_count_resources(struct acpi_resource *res,
-						 void *data)
+static acpi_status acpi_platform_resource_size(struct acpi_resource *res)
 {
-	struct acpi_resource_extended_irq *acpi_xirq;
-	struct resource_info *ri = data;
-
-	switch (res->type) {
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-	case ACPI_RESOURCE_TYPE_IRQ:
-		ri->n++;
-		break;
-	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
-		acpi_xirq = &res->data.extended_irq;
-		ri->n += acpi_xirq->interrupt_count;
-		break;
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-		if (res->data.address32.resource_type == ACPI_IO_RANGE)
-			ri->n++;
-		break;
-	}
-
-	return AE_OK;
+	return res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ ?
+			res->data.extended_irq.interrupt_count : 1;
 }
 
-static acpi_status acpi_platform_add_resources(struct acpi_resource *res,
-					       void *data)
+static acpi_status acpi_platform_add_resource(struct device *dev,
+					      struct acpi_resource *res,
+					      struct resource *resources,
+					      unsigned int count)
 {
-	struct acpi_resource_fixed_memory32 *acpi_mem;
-	struct acpi_resource_address32 *acpi_add32;
 	struct acpi_resource_extended_irq *acpi_xirq;
 	struct acpi_resource_irq *acpi_irq;
-	struct resource_info *ri = data;
-	struct resource *r;
+	struct resource *r = resources + count;
 	int irq, i;
 
-	switch (res->type) {
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		acpi_mem = &res->data.fixed_memory32;
-		r = &ri->res[ri->cur++];
-
-		r->start = acpi_mem->address;
-		r->end = r->start + acpi_mem->address_length - 1;
-		r->flags = IORESOURCE_MEM;
-
-		dev_dbg(ri->dev, "Memory32Fixed %pR\n", r);
-		break;
-
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-		acpi_add32 = &res->data.address32;
-
-		if (acpi_add32->resource_type == ACPI_IO_RANGE) {
-			r = &ri->res[ri->cur++];
-			r->start = acpi_add32->minimum;
-			r->end = r->start + acpi_add32->address_length - 1;
-			r->flags = IORESOURCE_IO;
-			dev_dbg(ri->dev, "Address32 %pR\n", r);
-		}
-		break;
+	if (acpi_dev_resource_memory(res, &r)
+	    || acpi_dev_resource_address_space(res, &r))
+		return 1;
 
+	switch (res->type) {
 	case ACPI_RESOURCE_TYPE_IRQ:
 		acpi_irq = &res->data.irq;
-		r = &ri->res[ri->cur++];
-
-		irq = acpi_register_gsi(ri->dev,
+		irq = acpi_register_gsi(dev,
 					acpi_irq->interrupts[0],
 					acpi_irq->triggering,
 					acpi_irq->polarity);
@@ -96,15 +50,13 @@ static acpi_status acpi_platform_add_res
 		r->start = r->end = irq;
 		r->flags = IORESOURCE_IRQ;
 
-		dev_dbg(ri->dev, "IRQ %pR\n", r);
-		break;
+		dev_dbg(dev, "Interrupt %pR\n", r);
+		return 1;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		acpi_xirq = &res->data.extended_irq;
-
-		for (i = 0; i < acpi_xirq->interrupt_count; i++, ri->cur++) {
-			r = &ri->res[ri->cur];
-			irq = acpi_register_gsi(ri->dev,
+		for (i = 0; i < acpi_xirq->interrupt_count; i++, r++) {
+			irq = acpi_register_gsi(dev,
 						acpi_xirq->interrupts[i],
 						acpi_xirq->triggering,
 						acpi_xirq->polarity);
@@ -112,12 +64,12 @@ static acpi_status acpi_platform_add_res
 			r->start = r->end = irq;
 			r->flags = IORESOURCE_IRQ;
 
-			dev_dbg(ri->dev, "Interrupt %pR\n", r);
+			dev_dbg(dev, "Interrupt %pR\n", r);
 		}
-		break;
+		return i;
 	}
 
-	return AE_OK;
+	return 0;
 }
 
 static acpi_status acpi_platform_get_device_uid(struct acpi_device *adev,
@@ -154,7 +106,9 @@ struct platform_device *acpi_create_plat
 	struct platform_device *pdev = NULL;
 	struct acpi_device *acpi_parent;
 	struct device *parent = NULL;
-	struct resource_info ri;
+	struct acpi_resource_list_entry *entry;
+	struct resource *resources;
+	unsigned int count = 0;
 	acpi_status status;
 	int devid;
 
@@ -170,29 +124,22 @@ struct platform_device *acpi_create_plat
 	memset(&ri, 0, sizeof(ri));
 
 	/* First, count the resources. */
-	status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
-				     acpi_platform_count_resources, &ri);
-	if (ACPI_FAILURE(status) || !ri.n)
-		return NULL;
+	list_for_each_entry(entry, &adev->resources, node)
+		count += acpi_platform_resource_size(&entry->resource);
 
 	/* Next, allocate memory for all the resources and populate it. */
-	ri.dev = &adev->dev;
-	ri.res = kzalloc(ri.n * sizeof(struct resource), GFP_KERNEL);
-	if (!ri.res) {
+	resources = kalloc(count * sizeof(struct resource), GFP_KERNEL);
+	if (!resources) {
 		dev_err(&adev->dev,
 			"failed to allocate memory for resources\n");
 		return NULL;
 	}
 
-	status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
-				     acpi_platform_add_resources, &ri);
-	if (ACPI_FAILURE(status)) {
-		dev_err(&adev->dev, "failed to walk resources\n");
-		goto out;
-	}
-
-	if (WARN_ON(ri.n != ri.cur))
-		goto out;
+	count = 0;
+	list_for_each_entry(entry, &adev->resources, node)
+		count += acpi_platform_add_resource(&adev->dev,
+						    &entry->resource,
+						    resources, count);
 
 	/*
 	 * If the ACPI node has a parent and that parent has a physical device
@@ -215,7 +162,8 @@ struct platform_device *acpi_create_plat
 		mutex_unlock(&acpi_parent->physical_node_lock);
 	}
 	pdev = platform_device_register_resndata(parent, acpi_device_hid(adev),
-						 devid, ri.res, ri.n, NULL, 0);
+						 devid, resources, count,
+						 NULL, 0);
 	if (IS_ERR(pdev)) {
 		dev_err(&adev->dev, "platform device creation failed: %ld\n",
 			PTR_ERR(pdev));
@@ -226,7 +174,7 @@ struct platform_device *acpi_create_plat
 	}
 
  out:
-	kfree(ri.res);
+	kfree(resources);
 	return pdev;
 }
 

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ