public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 00/28] PNP: convert fixed tables to lists, v3
@ 2008-06-17 22:58 Bjorn Helgaas
  2008-06-17 22:58 ` [patch 01/28] PNP: add detail to debug resource dump Bjorn Helgaas
                   ` (28 more replies)
  0 siblings, 29 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

This patch series contains all my PNP patches that are not yet in Linus'
tree, including both the "convert resource table to dynamic list" series
and the "convert resource options to unified dynamic list" series.

This series should replace all the PNP patches in -mm from
    pnp-add-detail-to-debug-resource-dump.patch
    ...
    not-for-merging-pnp-changes-suspend-oops.patch
except for isa-set-24-bit-dma_mask-for-isa-devices.patch, which got
stuck in the middle but isn't really PNP-related.

I'll be on vacation for the rest of the week, so I won't be able to
respond to any issues until Monday.

Here are the significant changes since the last posting:

    - When replacing pnp_resource_table, the PNPACPI resource encoders
      have to explicitly handle disabled resources; previously any
      unused slots in the table were implicitly disabled.  This should
      fix Jiri Slaby's oops on suspend/resume (though he hasn't tested
      this version).
      
      This change is in the patch titled "PNP: replace pnp_resource_table
      with dynamically allocated resources".
      
    - Added a new patch to keep disabled IRQ and DMA resources when parsing
      current config.  This fixes a bug in the current (2.6.25) PNPACPI
      code: consider a device with (mem, irq0, irq1, io), where irq0 is
      disabled.  If we drop irq0 when parsing the _CRS, we will mistakenly
      put irq1 in the irq0 slot when we encode resources for an _SRS call.

    - Added a new patch to avoid interrupts used by an IDE controller in
      compatibility mode.  https://bugzilla.novell.com/show_bug.cgi?id=375836

    - Added a new PNPACPI patch to support HP vendor-specific descriptors.
      This has long been supported by arch/ia64/kernel/acpi-ext.c, which
      provides an hp_acpi_csr_space() interface, but I think it's better
      and more generic to support it in PNPACPI.

Changes since v2 of "convert resource options to unified dynamic list":

    - fixed bisection problem in quirk_ad1815_mpu_resources()
    - fixed checkpatch warning in pnp_show_options()
      (pnp-convert-resource-options-to-single-linked-list-checkpatch-fixes.patch)
    - replaced pnp_independent_option() with literal 0
    - fixed coding style in pnp/manager.c
    - added EXPORT_SYMBOL(pnp_possible_config)
      (pnp-add-pnp_possible_config-can-a-device-could-be-configured-this-way-fix.patch)

Bjorn
-- 

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

* [patch 01/28] PNP: add detail to debug resource dump
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 02/28] PNP: remove pnp_resource.index Bjorn Helgaas
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-better-resource-dump --]
[-- Type: text/plain, Size: 2480 bytes --]

In the debug resource dump, decode the flags and indicate when
a resource is disabled or has been automatically assigned.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work10/drivers/pnp/support.c
===================================================================
--- work10.orig/drivers/pnp/support.c	2008-05-02 11:18:50.000000000 -0600
+++ work10/drivers/pnp/support.c	2008-05-05 09:39:03.000000000 -0600
@@ -63,28 +63,46 @@ void dbg_pnp_show_resources(struct pnp_d
 	for (i = 0; i < PNP_MAX_IRQ; i++) {
 		res = pnp_get_resource(dev, IORESOURCE_IRQ, i);
 		if (res && !(res->flags & IORESOURCE_UNSET))
-			dev_dbg(&dev->dev, "  irq %lld flags %#lx\n",
-				(unsigned long long) res->start, res->flags);
+			dev_dbg(&dev->dev, "  irq %lld flags %#lx%s%s\n",
+				(unsigned long long) res->start, res->flags,
+				res->flags & IORESOURCE_DISABLED ?
+					" DISABLED" : "",
+				res->flags & IORESOURCE_AUTO ?
+					" AUTO" : "");
 	}
 	for (i = 0; i < PNP_MAX_DMA; i++) {
 		res = pnp_get_resource(dev, IORESOURCE_DMA, i);
 		if (res && !(res->flags & IORESOURCE_UNSET))
-			dev_dbg(&dev->dev, "  dma %lld flags %#lx\n",
-				(unsigned long long) res->start, res->flags);
+			dev_dbg(&dev->dev, "  dma %lld flags %#lx%s%s\n",
+				(unsigned long long) res->start, res->flags,
+				res->flags & IORESOURCE_DISABLED ?
+					" DISABLED" : "",
+				res->flags & IORESOURCE_AUTO ?
+					" AUTO" : "");
 	}
 	for (i = 0; i < PNP_MAX_PORT; i++) {
 		res = pnp_get_resource(dev, IORESOURCE_IO, i);
 		if (res && !(res->flags & IORESOURCE_UNSET))
-			dev_dbg(&dev->dev, "  io  %#llx-%#llx flags %#lx\n",
+			dev_dbg(&dev->dev, "  io  %#llx-%#llx flags %#lx"
+				"%s%s\n",
 				(unsigned long long) res->start,
-				(unsigned long long) res->end, res->flags);
+				(unsigned long long) res->end, res->flags,
+				res->flags & IORESOURCE_DISABLED ?
+					" DISABLED" : "",
+				res->flags & IORESOURCE_AUTO ?
+					" AUTO" : "");
 	}
 	for (i = 0; i < PNP_MAX_MEM; i++) {
 		res = pnp_get_resource(dev, IORESOURCE_MEM, i);
 		if (res && !(res->flags & IORESOURCE_UNSET))
-			dev_dbg(&dev->dev, "  mem %#llx-%#llx flags %#lx\n",
+			dev_dbg(&dev->dev, "  mem %#llx-%#llx flags %#lx"
+				"%s%s\n",
 				(unsigned long long) res->start,
-				(unsigned long long) res->end, res->flags);
+				(unsigned long long) res->end, res->flags,
+				res->flags & IORESOURCE_DISABLED ?
+					" DISABLED" : "",
+				res->flags & IORESOURCE_AUTO ?
+					" AUTO" : "");
 	}
 #endif
 }

-- 

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

* [patch 02/28] PNP: remove pnp_resource.index
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
  2008-06-17 22:58 ` [patch 01/28] PNP: add detail to debug resource dump Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 03/28] PNP: add pnp_resource_type() internal interface Bjorn Helgaas
                   ` (26 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-remove-pnp_resource-index --]
[-- Type: text/plain, Size: 9050 bytes --]

We used pnp_resource.index to keep track of which ISAPNP configuration
register a resource should be written to.  We needed this only to
handle the case where a register is disabled but a subsequent register
in the same set is enabled.

Rather than explicitly maintaining the pnp_resource.index, this patch
adds a resource every time we read an ISAPNP configuration register
and marks the resource as IORESOURCE_DISABLED when appropriate.  This
makes the position in the pnp_resource_table always correspond to the
config register index.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

---
 drivers/pnp/base.h        |    1 
 drivers/pnp/interface.c   |   20 ++---------
 drivers/pnp/isapnp/core.c |   80 ++++++++++++++--------------------------------
 drivers/pnp/manager.c     |    4 --
 4 files changed, 29 insertions(+), 76 deletions(-)

Index: work10/drivers/pnp/base.h
===================================================================
--- work10.orig/drivers/pnp/base.h	2008-05-15 15:22:36.000000000 -0600
+++ work10/drivers/pnp/base.h	2008-05-15 15:23:24.000000000 -0600
@@ -57,7 +57,6 @@ struct pnp_resource *pnp_get_pnp_resourc
 
 struct pnp_resource {
 	struct resource res;
-	unsigned int index;		/* ISAPNP config register index */
 };
 
 struct pnp_resource_table {
Index: work10/drivers/pnp/interface.c
===================================================================
--- work10.orig/drivers/pnp/interface.c	2008-05-15 15:22:36.000000000 -0600
+++ work10/drivers/pnp/interface.c	2008-05-15 15:23:24.000000000 -0600
@@ -320,7 +320,6 @@ pnp_set_current_resources(struct device 
 			  const char *ubuf, size_t count)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
-	struct pnp_resource *pnp_res;
 	char *buf = (void *)ubuf;
 	int retval = 0;
 	resource_size_t start, end;
@@ -368,7 +367,6 @@ pnp_set_current_resources(struct device 
 		goto done;
 	}
 	if (!strnicmp(buf, "set", 3)) {
-		int nport = 0, nmem = 0, nirq = 0, ndma = 0;
 		if (dev->active)
 			goto done;
 		buf += 3;
@@ -391,10 +389,7 @@ pnp_set_current_resources(struct device 
 					end = simple_strtoul(buf, &buf, 0);
 				} else
 					end = start;
-				pnp_res = pnp_add_io_resource(dev, start, end,
-							      0);
-				if (pnp_res)
-					pnp_res->index = nport++;
+				pnp_add_io_resource(dev, start, end, 0);
 				continue;
 			}
 			if (!strnicmp(buf, "mem", 3)) {
@@ -411,10 +406,7 @@ pnp_set_current_resources(struct device 
 					end = simple_strtoul(buf, &buf, 0);
 				} else
 					end = start;
-				pnp_res = pnp_add_mem_resource(dev, start, end,
-							       0);
-				if (pnp_res)
-					pnp_res->index = nmem++;
+				pnp_add_mem_resource(dev, start, end, 0);
 				continue;
 			}
 			if (!strnicmp(buf, "irq", 3)) {
@@ -422,9 +414,7 @@ pnp_set_current_resources(struct device 
 				while (isspace(*buf))
 					++buf;
 				start = simple_strtoul(buf, &buf, 0);
-				pnp_res = pnp_add_irq_resource(dev, start, 0);
-				if (pnp_res)
-					pnp_res->index = nirq++;
+				pnp_add_irq_resource(dev, start, 0);
 				continue;
 			}
 			if (!strnicmp(buf, "dma", 3)) {
@@ -432,9 +422,7 @@ pnp_set_current_resources(struct device 
 				while (isspace(*buf))
 					++buf;
 				start = simple_strtoul(buf, &buf, 0);
-				pnp_res = pnp_add_dma_resource(dev, start, 0);
-				if (pnp_res)
-					pnp_res->index = ndma++;
+				pnp_add_dma_resource(dev, start, 0);
 				continue;
 			}
 			break;
Index: work10/drivers/pnp/isapnp/core.c
===================================================================
--- work10.orig/drivers/pnp/isapnp/core.c	2008-05-15 15:21:53.000000000 -0600
+++ work10/drivers/pnp/isapnp/core.c	2008-05-15 15:23:24.000000000 -0600
@@ -928,7 +928,6 @@ EXPORT_SYMBOL(isapnp_write_byte);
 
 static int isapnp_get_resources(struct pnp_dev *dev)
 {
-	struct pnp_resource *pnp_res;
 	int i, ret;
 
 	dev_dbg(&dev->dev, "get resources\n");
@@ -940,35 +939,23 @@ static int isapnp_get_resources(struct p
 
 	for (i = 0; i < ISAPNP_MAX_PORT; i++) {
 		ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
-		if (ret) {
-			pnp_res = pnp_add_io_resource(dev, ret, ret, 0);
-			if (pnp_res)
-				pnp_res->index = i;
-		}
+		pnp_add_io_resource(dev, ret, ret,
+				    ret == 0 ? IORESOURCE_DISABLED : 0);
 	}
 	for (i = 0; i < ISAPNP_MAX_MEM; i++) {
 		ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8;
-		if (ret) {
-			pnp_res = pnp_add_mem_resource(dev, ret, ret, 0);
-			if (pnp_res)
-				pnp_res->index = i;
-		}
+		pnp_add_mem_resource(dev, ret, ret,
+				     ret == 0 ? IORESOURCE_DISABLED : 0);
 	}
 	for (i = 0; i < ISAPNP_MAX_IRQ; i++) {
 		ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8;
-		if (ret) {
-			pnp_res = pnp_add_irq_resource(dev, ret, 0);
-			if (pnp_res)
-				pnp_res->index = i;
-		}
+		pnp_add_irq_resource(dev, ret,
+				     ret == 0 ? IORESOURCE_DISABLED : 0);
 	}
 	for (i = 0; i < ISAPNP_MAX_DMA; i++) {
 		ret = isapnp_read_byte(ISAPNP_CFG_DMA + i);
-		if (ret != 4) {
-			pnp_res = pnp_add_dma_resource(dev, ret, 0);
-			if  (pnp_res)
-				pnp_res->index = i;
-		}
+		pnp_add_dma_resource(dev, ret,
+				     ret == 4 ? IORESOURCE_DISABLED : 0);
 	}
 
 __end:
@@ -978,62 +965,49 @@ __end:
 
 static int isapnp_set_resources(struct pnp_dev *dev)
 {
-	struct pnp_resource *pnp_res;
 	struct resource *res;
-	int tmp, index;
+	int tmp;
 
 	dev_dbg(&dev->dev, "set resources\n");
 	isapnp_cfg_begin(dev->card->number, dev->number);
 	dev->active = 1;
 	for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
-		pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
-		if (!pnp_res)
-			continue;
-		res = &pnp_res->res;
-		if (pnp_resource_valid(res)) {
-			index = pnp_res->index;
+		res = pnp_get_resource(dev, IORESOURCE_IO, tmp);
+		if (res && pnp_resource_valid(res) &&
+		    !(res->flags & IORESOURCE_DISABLED)) {
 			dev_dbg(&dev->dev, "  set io  %d to %#llx\n",
-				index, (unsigned long long) res->start);
-			isapnp_write_word(ISAPNP_CFG_PORT + (index << 1),
+				tmp, (unsigned long long) res->start);
+			isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
 					  res->start);
 		}
 	}
 	for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
-		pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp);
-		if (!pnp_res)
-			continue;
-		res = &pnp_res->res;
-		if (pnp_resource_valid(res)) {
+		res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp);
+		if (res && pnp_resource_valid(res) &&
+		    !(res->flags & IORESOURCE_DISABLED)) {
 			int irq = res->start;
 			if (irq == 2)
 				irq = 9;
-			index = pnp_res->index;
-			dev_dbg(&dev->dev, "  set irq %d to %d\n", index, irq);
-			isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq);
+			dev_dbg(&dev->dev, "  set irq %d to %d\n", tmp, irq);
+			isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq);
 		}
 	}
 	for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
-		pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp);
-		if (!pnp_res)
-			continue;
-		res = &pnp_res->res;
-		if (pnp_resource_valid(res)) {
-			index = pnp_res->index;
+		res = pnp_get_resource(dev, IORESOURCE_DMA, tmp);
+		if (res && pnp_resource_valid(res) &&
+		    !(res->flags & IORESOURCE_DISABLED)) {
 			dev_dbg(&dev->dev, "  set dma %d to %lld\n",
-				index, (unsigned long long) res->start);
-			isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start);
+				tmp, (unsigned long long) res->start);
+			isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start);
 		}
 	}
 	for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
-		pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp);
-		if (!pnp_res)
-			continue;
-		res = &pnp_res->res;
-		if (pnp_resource_valid(res)) {
-			index = pnp_res->index;
+		res = pnp_get_resource(dev, IORESOURCE_MEM, tmp);
+		if (res && pnp_resource_valid(res) &&
+		    !(res->flags & IORESOURCE_DISABLED)) {
 			dev_dbg(&dev->dev, "  set mem %d to %#llx\n",
-				index, (unsigned long long) res->start);
-			isapnp_write_word(ISAPNP_CFG_MEM + (index << 3),
+				tmp, (unsigned long long) res->start);
+			isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
 					  (res->start >> 8) & 0xffff);
 		}
 	}
Index: work10/drivers/pnp/manager.c
===================================================================
--- work10.orig/drivers/pnp/manager.c	2008-05-15 15:21:53.000000000 -0600
+++ work10/drivers/pnp/manager.c	2008-05-15 15:23:24.000000000 -0600
@@ -40,7 +40,6 @@ static int pnp_assign_port(struct pnp_de
 	}
 
 	/* set the initial values */
-	pnp_res->index = idx;
 	res->flags |= rule->flags | IORESOURCE_IO;
 	res->flags &= ~IORESOURCE_UNSET;
 
@@ -90,7 +89,6 @@ static int pnp_assign_mem(struct pnp_dev
 	}
 
 	/* set the initial values */
-	pnp_res->index = idx;
 	res->flags |= rule->flags | IORESOURCE_MEM;
 	res->flags &= ~IORESOURCE_UNSET;
 
@@ -155,7 +153,6 @@ static int pnp_assign_irq(struct pnp_dev
 	}
 
 	/* set the initial values */
-	pnp_res->index = idx;
 	res->flags |= rule->flags | IORESOURCE_IRQ;
 	res->flags &= ~IORESOURCE_UNSET;
 
@@ -214,7 +211,6 @@ static void pnp_assign_dma(struct pnp_de
 	}
 
 	/* set the initial values */
-	pnp_res->index = idx;
 	res->flags |= rule->flags | IORESOURCE_DMA;
 	res->flags &= ~IORESOURCE_UNSET;
 

-- 

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

* [patch 03/28] PNP: add pnp_resource_type() internal interface
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
  2008-06-17 22:58 ` [patch 01/28] PNP: add detail to debug resource dump Bjorn Helgaas
  2008-06-17 22:58 ` [patch 02/28] PNP: remove pnp_resource.index Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 04/28] PNP: add pnp_resource_type_name() helper function Bjorn Helgaas
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-add-pnp_resource_type --]
[-- Type: text/plain, Size: 1284 bytes --]

Given a struct resource, this returns the type (IO, MEM, IRQ, DMA).

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work10/drivers/pnp/base.h
===================================================================
--- work10.orig/drivers/pnp/base.h	2008-05-15 15:23:24.000000000 -0600
+++ work10/drivers/pnp/base.h	2008-05-15 15:23:27.000000000 -0600
@@ -46,6 +46,7 @@ int pnp_check_dma(struct pnp_dev *dev, s
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
 
 void pnp_init_resource(struct resource *res);
+int pnp_resource_type(struct resource *res);
 
 struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
 					  unsigned int type, unsigned int num);
Index: work10/drivers/pnp/resource.c
===================================================================
--- work10.orig/drivers/pnp/resource.c	2008-05-15 15:22:36.000000000 -0600
+++ work10/drivers/pnp/resource.c	2008-05-15 15:23:27.000000000 -0600
@@ -499,6 +499,12 @@ int pnp_check_dma(struct pnp_dev *dev, s
 #endif
 }
 
+int pnp_resource_type(struct resource *res)
+{
+	return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
+			     IORESOURCE_IRQ | IORESOURCE_DMA);
+}
+
 struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
 					  unsigned int type, unsigned int num)
 {

-- 

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

* [patch 04/28] PNP: add pnp_resource_type_name() helper function
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (2 preceding siblings ...)
  2008-06-17 22:58 ` [patch 03/28] PNP: add pnp_resource_type() internal interface Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 05/28] PNP: make pnp_{port,mem,etc}_start(), et al work for invalid resources Bjorn Helgaas
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-add-resource-type-name --]
[-- Type: text/plain, Size: 1527 bytes --]

This patch adds a "pnp_resource_type_name(struct resource *)" that
returns the string resource type.  This will be used by the sysfs
"show resources" function and the debug resource dump function.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work10/drivers/pnp/base.h
===================================================================
--- work10.orig/drivers/pnp/base.h	2008-05-15 15:23:27.000000000 -0600
+++ work10/drivers/pnp/base.h	2008-05-15 15:23:29.000000000 -0600
@@ -43,6 +43,7 @@ int pnp_check_mem(struct pnp_dev *dev, s
 int pnp_check_irq(struct pnp_dev *dev, struct resource *res);
 int pnp_check_dma(struct pnp_dev *dev, struct resource *res);
 
+char *pnp_resource_type_name(struct resource *res);
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
 
 void pnp_init_resource(struct resource *res);
Index: work10/drivers/pnp/support.c
===================================================================
--- work10.orig/drivers/pnp/support.c	2008-05-15 15:23:23.000000000 -0600
+++ work10/drivers/pnp/support.c	2008-05-15 15:23:29.000000000 -0600
@@ -52,6 +52,21 @@ void pnp_eisa_id_to_string(u32 id, char 
 	str[7] = '\0';
 }
 
+char *pnp_resource_type_name(struct resource *res)
+{
+	switch (pnp_resource_type(res)) {
+	case IORESOURCE_IO:
+		return "io";
+	case IORESOURCE_MEM:
+		return "mem";
+	case IORESOURCE_IRQ:
+		return "irq";
+	case IORESOURCE_DMA:
+		return "dma";
+	}
+	return NULL;
+}
+
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
 {
 #ifdef DEBUG

-- 

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

* [patch 05/28] PNP: make pnp_{port,mem,etc}_start(), et al work for invalid resources
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (3 preceding siblings ...)
  2008-06-17 22:58 ` [patch 04/28] PNP: add pnp_resource_type_name() helper function Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 06/28] PNP: replace pnp_resource_table with dynamically allocated resources Bjorn Helgaas
                   ` (23 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-make-accessors-work-for-invalid-bars --]
[-- Type: text/plain, Size: 5068 bytes --]

Some callers use pnp_port_start() and similar functions without
making sure the resource is valid.  This patch makes us fall
back to returning the initial values if the resource is not
valid or not even present.

This mostly preserves the previous behavior, where we would just
return the initial values set by pnp_init_resource_table().  The
original 2.6.25 code didn't range-check the "bar", so it would
return garbage if the bar exceeded the table size.  This code
returns sensible values instead.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work10/include/linux/pnp.h
===================================================================
--- work10.orig/include/linux/pnp.h	2008-05-14 16:57:23.000000000 -0600
+++ work10/include/linux/pnp.h	2008-05-14 17:04:30.000000000 -0600
@@ -40,19 +40,31 @@ static inline resource_size_t pnp_resour
 static inline resource_size_t pnp_port_start(struct pnp_dev *dev,
 					     unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_IO, bar)->start;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar);
+
+	if (pnp_resource_valid(res))
+		return res->start;
+	return 0;
 }
 
 static inline resource_size_t pnp_port_end(struct pnp_dev *dev,
 					   unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_IO, bar)->end;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar);
+
+	if (pnp_resource_valid(res))
+		return res->end;
+	return 0;
 }
 
 static inline unsigned long pnp_port_flags(struct pnp_dev *dev,
 					   unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_IO, bar)->flags;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar);
+
+	if (pnp_resource_valid(res))
+		return res->flags;
+	return IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
 }
 
 static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar)
@@ -63,25 +75,41 @@ static inline int pnp_port_valid(struct 
 static inline resource_size_t pnp_port_len(struct pnp_dev *dev,
 					   unsigned int bar)
 {
-	return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_IO, bar));
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar);
+
+	if (pnp_resource_valid(res))
+		return pnp_resource_len(res);
+	return 0;
 }
 
 
 static inline resource_size_t pnp_mem_start(struct pnp_dev *dev,
 					    unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_MEM, bar)->start;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar);
+
+	if (pnp_resource_valid(res))
+		return res->start;
+	return 0;
 }
 
 static inline resource_size_t pnp_mem_end(struct pnp_dev *dev,
 					  unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_MEM, bar)->end;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar);
+
+	if (pnp_resource_valid(res))
+		return res->end;
+	return 0;
 }
 
 static inline unsigned long pnp_mem_flags(struct pnp_dev *dev, unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_MEM, bar)->flags;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar);
+
+	if (pnp_resource_valid(res))
+		return res->flags;
+	return IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
 }
 
 static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar)
@@ -92,18 +120,30 @@ static inline int pnp_mem_valid(struct p
 static inline resource_size_t pnp_mem_len(struct pnp_dev *dev,
 					  unsigned int bar)
 {
-	return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_MEM, bar));
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar);
+
+	if (pnp_resource_valid(res))
+		return pnp_resource_len(res);
+	return 0;
 }
 
 
 static inline resource_size_t pnp_irq(struct pnp_dev *dev, unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->start;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_IRQ, bar);
+
+	if (pnp_resource_valid(res))
+		return res->start;
+	return -1;
 }
 
 static inline unsigned long pnp_irq_flags(struct pnp_dev *dev, unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->flags;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_IRQ, bar);
+
+	if (pnp_resource_valid(res))
+		return res->flags;
+	return IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
 }
 
 static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar)
@@ -114,12 +154,20 @@ static inline int pnp_irq_valid(struct p
 
 static inline resource_size_t pnp_dma(struct pnp_dev *dev, unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_DMA, bar)->start;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_DMA, bar);
+
+	if (pnp_resource_valid(res))
+		return res->start;
+	return -1;
 }
 
 static inline unsigned long pnp_dma_flags(struct pnp_dev *dev, unsigned int bar)
 {
-	return pnp_get_resource(dev, IORESOURCE_DMA, bar)->flags;
+	struct resource *res = pnp_get_resource(dev, IORESOURCE_DMA, bar);
+
+	if (pnp_resource_valid(res))
+		return res->flags;
+	return IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
 }
 
 static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar)

-- 

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

* [patch 06/28] PNP: replace pnp_resource_table with dynamically allocated resources
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (4 preceding siblings ...)
  2008-06-17 22:58 ` [patch 05/28] PNP: make pnp_{port,mem,etc}_start(), et al work for invalid resources Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 07/28] PNPACPI: keep disabled resources when parsing current config Bjorn Helgaas
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-convert-to-lists --]
[-- Type: text/plain, Size: 43710 bytes --]

PNP used to have a fixed-size pnp_resource_table for tracking the
resources used by a device.  This table often overflowed, so we've
had to increase the table size, which wastes memory because most
devices have very few resources.

This patch replaces the table with a linked list of resources where
the entries are allocated on demand.

This removes messages like these:

    pnpacpi: exceeded the max number of IO resources
    00:01: too many I/O port resources

References:

    http://bugzilla.kernel.org/show_bug.cgi?id=9535
    http://bugzilla.kernel.org/show_bug.cgi?id=9740
    http://lkml.org/lkml/2007/11/30/110

This patch also changes the way PNP uses the IORESOURCE_UNSET,
IORESOURCE_AUTO, and IORESOURCE_DISABLED flags.

Prior to this patch, the pnp_resource_table entries used the flags
like this:

    IORESOURCE_UNSET
	This table entry is unused and available for use.  When this flag
	is set, we shouldn't look at anything else in the resource structure.
	This flag is set when a resource table entry is initialized.

    IORESOURCE_AUTO
	This resource was assigned automatically by pnp_assign_{io,mem,etc}().

	This flag is set when a resource table entry is initialized and
	cleared whenever we discover a resource setting by reading an ISAPNP
	config register, parsing a PNPBIOS resource data stream, parsing an
	ACPI _CRS list, or interpreting a sysfs "set" command.

	Resources marked IORESOURCE_AUTO are reinitialized and marked as
	IORESOURCE_UNSET by pnp_clean_resource_table() in these cases:

	    - before we attempt to assign resources automatically,
	    - if we fail to assign resources automatically,
	    - after disabling a device

    IORESOURCE_DISABLED
	Set by pnp_assign_{io,mem,etc}() when automatic assignment fails.
	Also set by PNPBIOS and PNPACPI for:

	    - invalid IRQs or GSI registration failures
	    - invalid DMA channels
	    - I/O ports above 0x10000
	    - mem ranges with negative length

After this patch, there is no pnp_resource_table, and the resource list
entries use the flags like this:

    IORESOURCE_UNSET
	This flag is no longer used in PNP.  Instead of keeping
	IORESOURCE_UNSET entries in the resource list, we remove
	entries from the list and free them.

    IORESOURCE_AUTO
	No change in meaning: it still means the resource was assigned
	automatically by pnp_assign_{port,mem,etc}(), but these functions
	now set the bit explicitly.

	We still "clean" a device's resource list in the same places,
	but rather than reinitializing IORESOURCE_AUTO entries, we
	just remove them from the list.

	Note that IORESOURCE_AUTO entries are always at the end of the
	list, so removing them doesn't reorder other list entries.
	This is because non-IORESOURCE_AUTO entries are added by the
	ISAPNP, PNPBIOS, or PNPACPI "get resources" methods and by the
	sysfs "set" command.  In each of these cases, we completely free
	the resource list first.

    IORESOURCE_DISABLED
	In addition to the cases where we used to set this flag, ISAPNP now
	adds an IORESOURCE_DISABLED resource when it reads a configuration
	register with a "disabled" value.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

---
 drivers/pnp/base.h             |   18 ---
 drivers/pnp/core.c             |   25 +++-
 drivers/pnp/interface.c        |   60 ++++-------
 drivers/pnp/isapnp/core.c      |   12 --
 drivers/pnp/manager.c          |  218 ++++++++++-------------------------------
 drivers/pnp/pnpacpi/rsparser.c |  131 ++++++++++++++++--------
 drivers/pnp/pnpbios/rsparser.c |   95 ++++++++++++-----
 drivers/pnp/quirks.c           |    3 
 drivers/pnp/resource.c         |   86 +++-------------
 drivers/pnp/support.c          |   72 +++++--------
 drivers/pnp/system.c           |    4 
 include/linux/pnp.h            |   20 ++-
 12 files changed, 323 insertions(+), 421 deletions(-)

Index: work14/drivers/pnp/base.h
===================================================================
--- work14.orig/drivers/pnp/base.h	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/base.h	2008-06-17 14:45:35.000000000 -0600
@@ -46,27 +46,15 @@ int pnp_check_dma(struct pnp_dev *dev, s
 char *pnp_resource_type_name(struct resource *res);
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
 
-void pnp_init_resource(struct resource *res);
+void pnp_free_resources(struct pnp_dev *dev);
 int pnp_resource_type(struct resource *res);
 
-struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
-					  unsigned int type, unsigned int num);
-
-#define PNP_MAX_PORT		40
-#define PNP_MAX_MEM		24
-#define PNP_MAX_IRQ		 2
-#define PNP_MAX_DMA		 2
-
 struct pnp_resource {
+	struct list_head list;
 	struct resource res;
 };
 
-struct pnp_resource_table {
-	struct pnp_resource port[PNP_MAX_PORT];
-	struct pnp_resource mem[PNP_MAX_MEM];
-	struct pnp_resource dma[PNP_MAX_DMA];
-	struct pnp_resource irq[PNP_MAX_IRQ];
-};
+void pnp_free_resource(struct pnp_resource *pnp_res);
 
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
 					  int flags);
Index: work14/drivers/pnp/core.c
===================================================================
--- work14.orig/drivers/pnp/core.c	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/core.c	2008-06-17 14:45:35.000000000 -0600
@@ -99,6 +99,21 @@ static void pnp_free_ids(struct pnp_dev 
 	}
 }
 
+void pnp_free_resource(struct pnp_resource *pnp_res)
+{
+	list_del(&pnp_res->list);
+	kfree(pnp_res);
+}
+
+void pnp_free_resources(struct pnp_dev *dev)
+{
+	struct pnp_resource *pnp_res, *tmp;
+
+	list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
+		pnp_free_resource(pnp_res);
+	}
+}
+
 static void pnp_release_device(struct device *dmdev)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
@@ -106,7 +121,7 @@ static void pnp_release_device(struct de
 	pnp_free_option(dev->independent);
 	pnp_free_option(dev->dependent);
 	pnp_free_ids(dev);
-	kfree(dev->res);
+	pnp_free_resources(dev);
 	kfree(dev);
 }
 
@@ -119,12 +134,7 @@ struct pnp_dev *pnp_alloc_dev(struct pnp
 	if (!dev)
 		return NULL;
 
-	dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
-	if (!dev->res) {
-		kfree(dev);
-		return NULL;
-	}
-
+	INIT_LIST_HEAD(&dev->resources);
 	dev->protocol = protocol;
 	dev->number = id;
 	dev->dma_mask = DMA_24BIT_MASK;
@@ -140,7 +150,6 @@ struct pnp_dev *pnp_alloc_dev(struct pnp
 
 	dev_id = pnp_add_id(dev, pnpid);
 	if (!dev_id) {
-		kfree(dev->res);
 		kfree(dev);
 		return NULL;
 	}
Index: work14/drivers/pnp/interface.c
===================================================================
--- work14.orig/drivers/pnp/interface.c	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/interface.c	2008-06-17 14:45:35.000000000 -0600
@@ -269,46 +269,38 @@ static ssize_t pnp_show_current_resource
 		pnp_printf(buffer, "disabled\n");
 
 	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
-		if (pnp_resource_valid(res)) {
-			pnp_printf(buffer, "io");
-			if (res->flags & IORESOURCE_DISABLED)
-				pnp_printf(buffer, " disabled\n");
-			else
-				pnp_printf(buffer, " 0x%llx-0x%llx\n",
-					   (unsigned long long) res->start,
-					   (unsigned long long) res->end);
-		}
+		pnp_printf(buffer, "io");
+		if (res->flags & IORESOURCE_DISABLED)
+			pnp_printf(buffer, " disabled\n");
+		else
+			pnp_printf(buffer, " 0x%llx-0x%llx\n",
+				   (unsigned long long) res->start,
+				   (unsigned long long) res->end);
 	}
 	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
-		if (pnp_resource_valid(res)) {
-			pnp_printf(buffer, "mem");
-			if (res->flags & IORESOURCE_DISABLED)
-				pnp_printf(buffer, " disabled\n");
-			else
-				pnp_printf(buffer, " 0x%llx-0x%llx\n",
-					   (unsigned long long) res->start,
-					   (unsigned long long) res->end);
-		}
+		pnp_printf(buffer, "mem");
+		if (res->flags & IORESOURCE_DISABLED)
+			pnp_printf(buffer, " disabled\n");
+		else
+			pnp_printf(buffer, " 0x%llx-0x%llx\n",
+				   (unsigned long long) res->start,
+				   (unsigned long long) res->end);
 	}
 	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
-		if (pnp_resource_valid(res)) {
-			pnp_printf(buffer, "irq");
-			if (res->flags & IORESOURCE_DISABLED)
-				pnp_printf(buffer, " disabled\n");
-			else
-				pnp_printf(buffer, " %lld\n",
-					   (unsigned long long) res->start);
-		}
+		pnp_printf(buffer, "irq");
+		if (res->flags & IORESOURCE_DISABLED)
+			pnp_printf(buffer, " disabled\n");
+		else
+			pnp_printf(buffer, " %lld\n",
+				   (unsigned long long) res->start);
 	}
 	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
-		if (pnp_resource_valid(res)) {
-			pnp_printf(buffer, "dma");
-			if (res->flags & IORESOURCE_DISABLED)
-				pnp_printf(buffer, " disabled\n");
-			else
-				pnp_printf(buffer, " %lld\n",
-					   (unsigned long long) res->start);
-		}
+		pnp_printf(buffer, "dma");
+		if (res->flags & IORESOURCE_DISABLED)
+			pnp_printf(buffer, " disabled\n");
+		else
+			pnp_printf(buffer, " %lld\n",
+				   (unsigned long long) res->start);
 	}
 	ret = (buffer->curr - buf);
 	kfree(buffer);
Index: work14/drivers/pnp/isapnp/core.c
===================================================================
--- work14.orig/drivers/pnp/isapnp/core.c	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/isapnp/core.c	2008-06-17 14:47:29.000000000 -0600
@@ -973,8 +973,7 @@ static int isapnp_set_resources(struct p
 	dev->active = 1;
 	for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
 		res = pnp_get_resource(dev, IORESOURCE_IO, tmp);
-		if (res && pnp_resource_valid(res) &&
-		    !(res->flags & IORESOURCE_DISABLED)) {
+		if (pnp_resource_enabled(res)) {
 			dev_dbg(&dev->dev, "  set io  %d to %#llx\n",
 				tmp, (unsigned long long) res->start);
 			isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
@@ -983,8 +982,7 @@ static int isapnp_set_resources(struct p
 	}
 	for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
 		res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp);
-		if (res && pnp_resource_valid(res) &&
-		    !(res->flags & IORESOURCE_DISABLED)) {
+		if (pnp_resource_enabled(res)) {
 			int irq = res->start;
 			if (irq == 2)
 				irq = 9;
@@ -994,8 +992,7 @@ static int isapnp_set_resources(struct p
 	}
 	for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
 		res = pnp_get_resource(dev, IORESOURCE_DMA, tmp);
-		if (res && pnp_resource_valid(res) &&
-		    !(res->flags & IORESOURCE_DISABLED)) {
+		if (pnp_resource_enabled(res)) {
 			dev_dbg(&dev->dev, "  set dma %d to %lld\n",
 				tmp, (unsigned long long) res->start);
 			isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start);
@@ -1003,8 +1000,7 @@ static int isapnp_set_resources(struct p
 	}
 	for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
 		res = pnp_get_resource(dev, IORESOURCE_MEM, tmp);
-		if (res && pnp_resource_valid(res) &&
-		    !(res->flags & IORESOURCE_DISABLED)) {
+		if (pnp_resource_enabled(res)) {
 			dev_dbg(&dev->dev, "  set mem %d to %#llx\n",
 				tmp, (unsigned long long) res->start);
 			isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
Index: work14/drivers/pnp/manager.c
===================================================================
--- work14.orig/drivers/pnp/manager.c	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/manager.c	2008-06-17 14:45:35.000000000 -0600
@@ -19,40 +19,30 @@ DEFINE_MUTEX(pnp_res_mutex);
 
 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
 {
-	struct pnp_resource *pnp_res;
-	struct resource *res;
+	struct resource *res, local_res;
 
-	pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx);
-	if (!pnp_res) {
-		dev_err(&dev->dev, "too many I/O port resources\n");
-		/* pretend we were successful so at least the manager won't try again */
-		return 1;
-	}
-
-	res = &pnp_res->res;
-
-	/* check if this resource has been manually set, if so skip */
-	if (!(res->flags & IORESOURCE_AUTO)) {
+	res = pnp_get_resource(dev, IORESOURCE_IO, idx);
+	if (res) {
 		dev_dbg(&dev->dev, "  io %d already set to %#llx-%#llx "
 			"flags %#lx\n", idx, (unsigned long long) res->start,
 			(unsigned long long) res->end, res->flags);
 		return 1;
 	}
 
-	/* set the initial values */
-	res->flags |= rule->flags | IORESOURCE_IO;
-	res->flags &= ~IORESOURCE_UNSET;
+	res = &local_res;
+	res->flags = rule->flags | IORESOURCE_AUTO;
+	res->start = 0;
+	res->end = 0;
 
 	if (!rule->size) {
 		res->flags |= IORESOURCE_DISABLED;
 		dev_dbg(&dev->dev, "  io %d disabled\n", idx);
-		return 1;	/* skip disabled resource requests */
+		goto __add;
 	}
 
 	res->start = rule->min;
 	res->end = res->start + rule->size - 1;
 
-	/* run through until pnp_check_port is happy */
 	while (!pnp_check_port(dev, res)) {
 		res->start += rule->align;
 		res->end = res->start + rule->size - 1;
@@ -61,38 +51,29 @@ static int pnp_assign_port(struct pnp_de
 			return 0;
 		}
 	}
-	dev_dbg(&dev->dev, "  assign io  %d %#llx-%#llx\n", idx,
-		(unsigned long long) res->start, (unsigned long long) res->end);
+
+__add:
+	pnp_add_io_resource(dev, res->start, res->end, res->flags);
 	return 1;
 }
 
 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
 {
-	struct pnp_resource *pnp_res;
-	struct resource *res;
-
-	pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx);
-	if (!pnp_res) {
-		dev_err(&dev->dev, "too many memory resources\n");
-		/* pretend we were successful so at least the manager won't try again */
-		return 1;
-	}
-
-	res = &pnp_res->res;
+	struct resource *res, local_res;
 
-	/* check if this resource has been manually set, if so skip */
-	if (!(res->flags & IORESOURCE_AUTO)) {
+	res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
+	if (res) {
 		dev_dbg(&dev->dev, "  mem %d already set to %#llx-%#llx "
 			"flags %#lx\n", idx, (unsigned long long) res->start,
 			(unsigned long long) res->end, res->flags);
 		return 1;
 	}
 
-	/* set the initial values */
-	res->flags |= rule->flags | IORESOURCE_MEM;
-	res->flags &= ~IORESOURCE_UNSET;
+	res = &local_res;
+	res->flags = rule->flags | IORESOURCE_AUTO;
+	res->start = 0;
+	res->end = 0;
 
-	/* convert pnp flags to standard Linux flags */
 	if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
 		res->flags |= IORESOURCE_READONLY;
 	if (rule->flags & IORESOURCE_MEM_CACHEABLE)
@@ -105,13 +86,12 @@ static int pnp_assign_mem(struct pnp_dev
 	if (!rule->size) {
 		res->flags |= IORESOURCE_DISABLED;
 		dev_dbg(&dev->dev, "  mem %d disabled\n", idx);
-		return 1;	/* skip disabled resource requests */
+		goto __add;
 	}
 
 	res->start = rule->min;
 	res->end = res->start + rule->size - 1;
 
-	/* run through until pnp_check_mem is happy */
 	while (!pnp_check_mem(dev, res)) {
 		res->start += rule->align;
 		res->end = res->start + rule->size - 1;
@@ -120,15 +100,15 @@ static int pnp_assign_mem(struct pnp_dev
 			return 0;
 		}
 	}
-	dev_dbg(&dev->dev, "  assign mem %d %#llx-%#llx\n", idx,
-		(unsigned long long) res->start, (unsigned long long) res->end);
+
+__add:
+	pnp_add_mem_resource(dev, res->start, res->end, res->flags);
 	return 1;
 }
 
 static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
 {
-	struct pnp_resource *pnp_res;
-	struct resource *res;
+	struct resource *res, local_res;
 	int i;
 
 	/* IRQ priority: this table is good for i386 */
@@ -136,58 +116,48 @@ static int pnp_assign_irq(struct pnp_dev
 		5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
 	};
 
-	pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx);
-	if (!pnp_res) {
-		dev_err(&dev->dev, "too many IRQ resources\n");
-		/* pretend we were successful so at least the manager won't try again */
-		return 1;
-	}
-
-	res = &pnp_res->res;
-
-	/* check if this resource has been manually set, if so skip */
-	if (!(res->flags & IORESOURCE_AUTO)) {
+	res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
+	if (res) {
 		dev_dbg(&dev->dev, "  irq %d already set to %d flags %#lx\n",
 			idx, (int) res->start, res->flags);
 		return 1;
 	}
 
-	/* set the initial values */
-	res->flags |= rule->flags | IORESOURCE_IRQ;
-	res->flags &= ~IORESOURCE_UNSET;
+	res = &local_res;
+	res->flags = rule->flags | IORESOURCE_AUTO;
+	res->start = -1;
+	res->end = -1;
 
 	if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
 		res->flags |= IORESOURCE_DISABLED;
 		dev_dbg(&dev->dev, "  irq %d disabled\n", idx);
-		return 1;	/* skip disabled resource requests */
+		goto __add;
 	}
 
 	/* TBD: need check for >16 IRQ */
 	res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
 	if (res->start < PNP_IRQ_NR) {
 		res->end = res->start;
-		dev_dbg(&dev->dev, "  assign irq %d %d\n", idx,
-			(int) res->start);
-		return 1;
+		goto __add;
 	}
 	for (i = 0; i < 16; i++) {
 		if (test_bit(xtab[i], rule->map)) {
 			res->start = res->end = xtab[i];
-			if (pnp_check_irq(dev, res)) {
-				dev_dbg(&dev->dev, "  assign irq %d %d\n", idx,
-					(int) res->start);
-				return 1;
-			}
+			if (pnp_check_irq(dev, res))
+				goto __add;
 		}
 	}
 	dev_dbg(&dev->dev, "  couldn't assign irq %d\n", idx);
 	return 0;
+
+__add:
+	pnp_add_irq_resource(dev, res->start, res->flags);
+	return 1;
 }
 
 static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
 {
-	struct pnp_resource *pnp_res;
-	struct resource *res;
+	struct resource *res, local_res;
 	int i;
 
 	/* DMA priority: this table is good for i386 */
@@ -195,127 +165,47 @@ static void pnp_assign_dma(struct pnp_de
 		1, 3, 5, 6, 7, 0, 2, 4
 	};
 
-	pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx);
-	if (!pnp_res) {
-		dev_err(&dev->dev, "too many DMA resources\n");
-		return;
-	}
-
-	res = &pnp_res->res;
-
-	/* check if this resource has been manually set, if so skip */
-	if (!(res->flags & IORESOURCE_AUTO)) {
+	res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
+	if (res) {
 		dev_dbg(&dev->dev, "  dma %d already set to %d flags %#lx\n",
 			idx, (int) res->start, res->flags);
 		return;
 	}
 
-	/* set the initial values */
-	res->flags |= rule->flags | IORESOURCE_DMA;
-	res->flags &= ~IORESOURCE_UNSET;
+	res = &local_res;
+	res->flags = rule->flags | IORESOURCE_AUTO;
+	res->start = -1;
+	res->end = -1;
 
 	for (i = 0; i < 8; i++) {
 		if (rule->map & (1 << xtab[i])) {
 			res->start = res->end = xtab[i];
-			if (pnp_check_dma(dev, res)) {
-				dev_dbg(&dev->dev, "  assign dma %d %d\n", idx,
-					(int) res->start);
-				return;
-			}
+			if (pnp_check_dma(dev, res))
+				goto __add;
 		}
 	}
 #ifdef MAX_DMA_CHANNELS
 	res->start = res->end = MAX_DMA_CHANNELS;
 #endif
-	res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
+	res->flags |= IORESOURCE_DISABLED;
 	dev_dbg(&dev->dev, "  disable dma %d\n", idx);
-}
 
-void pnp_init_resource(struct resource *res)
-{
-	unsigned long type;
-
-	type = res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
-			     IORESOURCE_IRQ | IORESOURCE_DMA);
-
-	res->name = NULL;
-	res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET;
-	if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) {
-		res->start = -1;
-		res->end = -1;
-	} else {
-		res->start = 0;
-		res->end = 0;
-	}
+__add:
+	pnp_add_dma_resource(dev, res->start, res->flags);
 }
 
-/**
- * pnp_init_resources - Resets a resource table to default values.
- * @table: pointer to the desired resource table
- */
 void pnp_init_resources(struct pnp_dev *dev)
 {
-	struct resource *res;
-	int idx;
-
-	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
-		res = &dev->res->irq[idx].res;
-		res->flags = IORESOURCE_IRQ;
-		pnp_init_resource(res);
-	}
-	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
-		res = &dev->res->dma[idx].res;
-		res->flags = IORESOURCE_DMA;
-		pnp_init_resource(res);
-	}
-	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
-		res = &dev->res->port[idx].res;
-		res->flags = IORESOURCE_IO;
-		pnp_init_resource(res);
-	}
-	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
-		res = &dev->res->mem[idx].res;
-		res->flags = IORESOURCE_MEM;
-		pnp_init_resource(res);
-	}
+	pnp_free_resources(dev);
 }
 
-/**
- * pnp_clean_resources - clears resources that were not manually set
- * @res: the resources to clean
- */
 static void pnp_clean_resource_table(struct pnp_dev *dev)
 {
-	struct resource *res;
-	int idx;
+	struct pnp_resource *pnp_res, *tmp;
 
-	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
-		res = &dev->res->irq[idx].res;
-		if (res->flags & IORESOURCE_AUTO) {
-			res->flags = IORESOURCE_IRQ;
-			pnp_init_resource(res);
-		}
-	}
-	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
-		res = &dev->res->dma[idx].res;
-		if (res->flags & IORESOURCE_AUTO) {
-			res->flags = IORESOURCE_DMA;
-			pnp_init_resource(res);
-		}
-	}
-	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
-		res = &dev->res->port[idx].res;
-		if (res->flags & IORESOURCE_AUTO) {
-			res->flags = IORESOURCE_IO;
-			pnp_init_resource(res);
-		}
-	}
-	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
-		res = &dev->res->mem[idx].res;
-		if (res->flags & IORESOURCE_AUTO) {
-			res->flags = IORESOURCE_MEM;
-			pnp_init_resource(res);
-		}
+	list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
+		if (pnp_res->res.flags & IORESOURCE_AUTO)
+			pnp_free_resource(pnp_res);
 	}
 }
 
Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 14:44:52.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 14:47:29.000000000 -0600
@@ -806,6 +806,13 @@ static void pnpacpi_encode_irq(struct pn
 	struct acpi_resource_irq *irq = &resource->data.irq;
 	int triggering, polarity, shareable;
 
+	if (!pnp_resource_enabled(p)) {
+		irq->interrupt_count = 0;
+		dev_dbg(&dev->dev, "  encode irq (%s)\n",
+			p ? "disabled" : "missing");
+		return;
+	}
+
 	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
 	irq->triggering = triggering;
 	irq->polarity = polarity;
@@ -828,6 +835,13 @@ static void pnpacpi_encode_ext_irq(struc
 	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
 	int triggering, polarity, shareable;
 
+	if (!pnp_resource_enabled(p)) {
+		extended_irq->interrupt_count = 0;
+		dev_dbg(&dev->dev, "  encode extended irq (%s)\n",
+			p ? "disabled" : "missing");
+		return;
+	}
+
 	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
 	extended_irq->producer_consumer = ACPI_CONSUMER;
 	extended_irq->triggering = triggering;
@@ -848,6 +862,13 @@ static void pnpacpi_encode_dma(struct pn
 {
 	struct acpi_resource_dma *dma = &resource->data.dma;
 
+	if (!pnp_resource_enabled(p)) {
+		dma->channel_count = 0;
+		dev_dbg(&dev->dev, "  encode dma (%s)\n",
+			p ? "disabled" : "missing");
+		return;
+	}
+
 	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
 	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
 	case IORESOURCE_DMA_TYPEA:
@@ -889,17 +910,21 @@ static void pnpacpi_encode_io(struct pnp
 {
 	struct acpi_resource_io *io = &resource->data.io;
 
-	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
-	io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
-	    ACPI_DECODE_16 : ACPI_DECODE_10;
-	io->minimum = p->start;
-	io->maximum = p->end;
-	io->alignment = 0;	/* Correct? */
-	io->address_length = p->end - p->start + 1;
-
-	dev_dbg(&dev->dev, "  encode io %#llx-%#llx decode %#x\n",
-		(unsigned long long) p->start, (unsigned long long) p->end,
-		io->io_decode);
+	if (pnp_resource_enabled(p)) {
+		/* Note: pnp_assign_port copies pnp_port->flags into p->flags */
+		io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
+		    ACPI_DECODE_16 : ACPI_DECODE_10;
+		io->minimum = p->start;
+		io->maximum = p->end;
+		io->alignment = 0;	/* Correct? */
+		io->address_length = p->end - p->start + 1;
+	} else {
+		io->minimum = 0;
+		io->address_length = 0;
+	}
+
+	dev_dbg(&dev->dev, "  encode io %#x-%#x decode %#x\n", io->minimum,
+		io->minimum + io->address_length - 1, io->io_decode);
 }
 
 static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
@@ -908,11 +933,16 @@ static void pnpacpi_encode_fixed_io(stru
 {
 	struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
 
-	fixed_io->address = p->start;
-	fixed_io->address_length = p->end - p->start + 1;
+	if (pnp_resource_enabled(p)) {
+		fixed_io->address = p->start;
+		fixed_io->address_length = p->end - p->start + 1;
+	} else {
+		fixed_io->address = 0;
+		fixed_io->address_length = 0;
+	}
 
-	dev_dbg(&dev->dev, "  encode fixed_io %#llx-%#llx\n",
-		(unsigned long long) p->start, (unsigned long long) p->end);
+	dev_dbg(&dev->dev, "  encode fixed_io %#x-%#x\n", fixed_io->address,
+		fixed_io->address + fixed_io->address_length - 1);
 }
 
 static void pnpacpi_encode_mem24(struct pnp_dev *dev,
@@ -921,17 +951,22 @@ static void pnpacpi_encode_mem24(struct 
 {
 	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
 
-	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
-	memory24->write_protect =
-	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
-	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	memory24->minimum = p->start;
-	memory24->maximum = p->end;
-	memory24->alignment = 0;
-	memory24->address_length = p->end - p->start + 1;
+	if (pnp_resource_enabled(p)) {
+		/* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */
+		memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
+		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
+		memory24->minimum = p->start;
+		memory24->maximum = p->end;
+		memory24->alignment = 0;
+		memory24->address_length = p->end - p->start + 1;
+	} else {
+		memory24->minimum = 0;
+		memory24->address_length = 0;
+	}
 
-	dev_dbg(&dev->dev, "  encode mem24 %#llx-%#llx write_protect %#x\n",
-		(unsigned long long) p->start, (unsigned long long) p->end,
+	dev_dbg(&dev->dev, "  encode mem24 %#x-%#x write_protect %#x\n",
+		memory24->minimum,
+		memory24->minimum + memory24->address_length - 1,
 		memory24->write_protect);
 }
 
@@ -941,16 +976,21 @@ static void pnpacpi_encode_mem32(struct 
 {
 	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
 
-	memory32->write_protect =
-	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
-	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	memory32->minimum = p->start;
-	memory32->maximum = p->end;
-	memory32->alignment = 0;
-	memory32->address_length = p->end - p->start + 1;
+	if (pnp_resource_enabled(p)) {
+		memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
+		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
+		memory32->minimum = p->start;
+		memory32->maximum = p->end;
+		memory32->alignment = 0;
+		memory32->address_length = p->end - p->start + 1;
+	} else {
+		memory32->minimum = 0;
+		memory32->alignment = 0;
+	}
 
-	dev_dbg(&dev->dev, "  encode mem32 %#llx-%#llx write_protect %#x\n",
-		(unsigned long long) p->start, (unsigned long long) p->end,
+	dev_dbg(&dev->dev, "  encode mem32 %#x-%#x write_protect %#x\n",
+		memory32->minimum,
+		memory32->minimum + memory32->address_length - 1,
 		memory32->write_protect);
 }
 
@@ -960,15 +1000,20 @@ static void pnpacpi_encode_fixed_mem32(s
 {
 	struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
 
-	fixed_memory32->write_protect =
-	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
-	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	fixed_memory32->address = p->start;
-	fixed_memory32->address_length = p->end - p->start + 1;
-
-	dev_dbg(&dev->dev, "  encode fixed_mem32 %#llx-%#llx "
-		"write_protect %#x\n",
-		(unsigned long long) p->start, (unsigned long long) p->end,
+	if (pnp_resource_enabled(p)) {
+		fixed_memory32->write_protect =
+		    p->flags & IORESOURCE_MEM_WRITEABLE ?
+		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
+		fixed_memory32->address = p->start;
+		fixed_memory32->address_length = p->end - p->start + 1;
+	} else {
+		fixed_memory32->address = 0;
+		fixed_memory32->address_length = 0;
+	}
+
+	dev_dbg(&dev->dev, "  encode fixed_mem32 %#x-%#x write_protect %#x\n",
+		fixed_memory32->address,
+		fixed_memory32->address + fixed_memory32->address_length - 1,
 		fixed_memory32->write_protect);
 }
 
Index: work14/drivers/pnp/pnpbios/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpbios/rsparser.c	2008-06-17 14:44:52.000000000 -0600
+++ work14/drivers/pnp/pnpbios/rsparser.c	2008-06-17 14:47:29.000000000 -0600
@@ -526,8 +526,16 @@ len_err:
 static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
 			       struct resource *res)
 {
-	unsigned long base = res->start;
-	unsigned long len = res->end - res->start + 1;
+	unsigned long base;
+	unsigned long len;
+
+	if (pnp_resource_enabled(res)) {
+		base = res->start;
+		len = res->end - res->start + 1;
+	} else {
+		base = 0;
+		len = 0;
+	}
 
 	p[4] = (base >> 8) & 0xff;
 	p[5] = ((base >> 8) >> 8) & 0xff;
@@ -536,15 +544,22 @@ static void pnpbios_encode_mem(struct pn
 	p[10] = (len >> 8) & 0xff;
 	p[11] = ((len >> 8) >> 8) & 0xff;
 
-	dev_dbg(&dev->dev, "  encode mem %#llx-%#llx\n",
-		(unsigned long long) res->start, (unsigned long long) res->end);
+	dev_dbg(&dev->dev, "  encode mem %#lx-%#lx\n", base, base + len - 1);
 }
 
 static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
 				 struct resource *res)
 {
-	unsigned long base = res->start;
-	unsigned long len = res->end - res->start + 1;
+	unsigned long base;
+	unsigned long len;
+
+	if (pnp_resource_enabled(res)) {
+		base = res->start;
+		len = res->end - res->start + 1;
+	} else {
+		base = 0;
+		len = 0;
+	}
 
 	p[4] = base & 0xff;
 	p[5] = (base >> 8) & 0xff;
@@ -559,15 +574,22 @@ static void pnpbios_encode_mem32(struct 
 	p[18] = (len >> 16) & 0xff;
 	p[19] = (len >> 24) & 0xff;
 
-	dev_dbg(&dev->dev, "  encode mem32 %#llx-%#llx\n",
-		(unsigned long long) res->start, (unsigned long long) res->end);
+	dev_dbg(&dev->dev, "  encode mem32 %#lx-%#lx\n", base, base + len - 1);
 }
 
 static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
 				       struct resource *res)
 {
-	unsigned long base = res->start;
-	unsigned long len = res->end - res->start + 1;
+	unsigned long base;
+	unsigned long len;
+
+	if (pnp_resource_enabled(res)) {
+		base = res->start;
+		len = res->end - res->start + 1;
+	} else {
+		base = 0;
+		len = 0;
+	}
 
 	p[4] = base & 0xff;
 	p[5] = (base >> 8) & 0xff;
@@ -578,40 +600,54 @@ static void pnpbios_encode_fixed_mem32(s
 	p[10] = (len >> 16) & 0xff;
 	p[11] = (len >> 24) & 0xff;
 
-	dev_dbg(&dev->dev, "  encode fixed_mem32 %#llx-%#llx\n",
-		(unsigned long long) res->start, (unsigned long long) res->end);
+	dev_dbg(&dev->dev, "  encode fixed_mem32 %#lx-%#lx\n", base,
+		base + len - 1);
 }
 
 static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
 			       struct resource *res)
 {
-	unsigned long map = 0;
+	unsigned long map;
+
+	if (pnp_resource_enabled(res))
+		map = 1 << res->start;
+	else
+		map = 0;
 
-	map = 1 << res->start;
 	p[1] = map & 0xff;
 	p[2] = (map >> 8) & 0xff;
 
-	dev_dbg(&dev->dev, "  encode irq %llu\n",
-		(unsigned long long)res->start);
+	dev_dbg(&dev->dev, "  encode irq mask %#lx\n", map);
 }
 
 static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
 			       struct resource *res)
 {
-	unsigned long map = 0;
+	unsigned long map;
+
+	if (pnp_resource_enabled(res))
+		map = 1 << res->start;
+	else
+		map = 0;
 
-	map = 1 << res->start;
 	p[1] = map & 0xff;
 
-	dev_dbg(&dev->dev, "  encode dma %llu\n",
-		(unsigned long long)res->start);
+	dev_dbg(&dev->dev, "  encode dma mask %#lx\n", map);
 }
 
 static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
 				struct resource *res)
 {
-	unsigned long base = res->start;
-	unsigned long len = res->end - res->start + 1;
+	unsigned long base;
+	unsigned long len;
+
+	if (pnp_resource_enabled(res)) {
+		base = res->start;
+		len = res->end - res->start + 1;
+	} else {
+		base = 0;
+		len = 0;
+	}
 
 	p[2] = base & 0xff;
 	p[3] = (base >> 8) & 0xff;
@@ -619,8 +655,7 @@ static void pnpbios_encode_port(struct p
 	p[5] = (base >> 8) & 0xff;
 	p[7] = len & 0xff;
 
-	dev_dbg(&dev->dev, "  encode io %#llx-%#llx\n",
-		(unsigned long long) res->start, (unsigned long long) res->end);
+	dev_dbg(&dev->dev, "  encode io %#lx-%#lx\n", base, base + len - 1);
 }
 
 static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
@@ -629,12 +664,20 @@ static void pnpbios_encode_fixed_port(st
 	unsigned long base = res->start;
 	unsigned long len = res->end - res->start + 1;
 
+	if (pnp_resource_enabled(res)) {
+		base = res->start;
+		len = res->end - res->start + 1;
+	} else {
+		base = 0;
+		len = 0;
+	}
+
 	p[1] = base & 0xff;
 	p[2] = (base >> 8) & 0xff;
 	p[3] = len & 0xff;
 
-	dev_dbg(&dev->dev, "  encode fixed_io %#llx-%#llx\n",
-		(unsigned long long) res->start, (unsigned long long) res->end);
+	dev_dbg(&dev->dev, "  encode fixed_io %#lx-%#lx\n", base,
+		base + len - 1);
 }
 
 static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
Index: work14/drivers/pnp/quirks.c
===================================================================
--- work14.orig/drivers/pnp/quirks.c	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/quirks.c	2008-06-17 14:45:35.000000000 -0600
@@ -248,8 +248,7 @@ static void quirk_system_pci_resources(s
 			for (j = 0;
 			     (res = pnp_get_resource(dev, IORESOURCE_MEM, j));
 			     j++) {
-				if (res->flags & IORESOURCE_UNSET ||
-				    (res->start == 0 && res->end == 0))
+				if (res->start == 0 && res->end == 0)
 					continue;
 
 				pnp_start = res->start;
Index: work14/drivers/pnp/resource.c
===================================================================
--- work14.orig/drivers/pnp/resource.c	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/resource.c	2008-06-17 14:45:35.000000000 -0600
@@ -237,7 +237,7 @@ void pnp_free_option(struct pnp_option *
 	!((*(enda) < *(startb)) || (*(endb) < *(starta)))
 
 #define cannot_compare(flags) \
-((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
+((flags) & IORESOURCE_DISABLED)
 
 int pnp_check_port(struct pnp_dev *dev, struct resource *res)
 {
@@ -505,81 +505,31 @@ int pnp_resource_type(struct resource *r
 			     IORESOURCE_IRQ | IORESOURCE_DMA);
 }
 
-struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
-					  unsigned int type, unsigned int num)
-{
-	struct pnp_resource_table *res = dev->res;
-
-	switch (type) {
-	case IORESOURCE_IO:
-		if (num >= PNP_MAX_PORT)
-			return NULL;
-		return &res->port[num];
-	case IORESOURCE_MEM:
-		if (num >= PNP_MAX_MEM)
-			return NULL;
-		return &res->mem[num];
-	case IORESOURCE_IRQ:
-		if (num >= PNP_MAX_IRQ)
-			return NULL;
-		return &res->irq[num];
-	case IORESOURCE_DMA:
-		if (num >= PNP_MAX_DMA)
-			return NULL;
-		return &res->dma[num];
-	}
-	return NULL;
-}
-
 struct resource *pnp_get_resource(struct pnp_dev *dev,
 				  unsigned int type, unsigned int num)
 {
 	struct pnp_resource *pnp_res;
+	struct resource *res;
 
-	pnp_res = pnp_get_pnp_resource(dev, type, num);
-	if (pnp_res)
-		return &pnp_res->res;
-
+	list_for_each_entry(pnp_res, &dev->resources, list) {
+		res = &pnp_res->res;
+		if (pnp_resource_type(res) == type && num-- == 0)
+			return res;
+	}
 	return NULL;
 }
 EXPORT_SYMBOL(pnp_get_resource);
 
-static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type)
+static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
 {
 	struct pnp_resource *pnp_res;
-	int i;
 
-	switch (type) {
-	case IORESOURCE_IO:
-		for (i = 0; i < PNP_MAX_PORT; i++) {
-			pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i);
-			if (pnp_res && !pnp_resource_valid(&pnp_res->res))
-				return pnp_res;
-		}
-		break;
-	case IORESOURCE_MEM:
-		for (i = 0; i < PNP_MAX_MEM; i++) {
-			pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i);
-			if (pnp_res && !pnp_resource_valid(&pnp_res->res))
-				return pnp_res;
-		}
-		break;
-	case IORESOURCE_IRQ:
-		for (i = 0; i < PNP_MAX_IRQ; i++) {
-			pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i);
-			if (pnp_res && !pnp_resource_valid(&pnp_res->res))
-				return pnp_res;
-		}
-		break;
-	case IORESOURCE_DMA:
-		for (i = 0; i < PNP_MAX_DMA; i++) {
-			pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i);
-			if (pnp_res && !pnp_resource_valid(&pnp_res->res))
-				return pnp_res;
-		}
-		break;
-	}
-	return NULL;
+	pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
+	if (!pnp_res)
+		return NULL;
+
+	list_add_tail(&pnp_res->list, &dev->resources);
+	return pnp_res;
 }
 
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
@@ -589,7 +539,7 @@ struct pnp_resource *pnp_add_irq_resourc
 	struct resource *res;
 	static unsigned char warned;
 
-	pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ);
+	pnp_res = pnp_new_resource(dev);
 	if (!pnp_res) {
 		if (!warned) {
 			dev_err(&dev->dev, "can't add resource for IRQ %d\n",
@@ -615,7 +565,7 @@ struct pnp_resource *pnp_add_dma_resourc
 	struct resource *res;
 	static unsigned char warned;
 
-	pnp_res = pnp_new_resource(dev, IORESOURCE_DMA);
+	pnp_res = pnp_new_resource(dev);
 	if (!pnp_res) {
 		if (!warned) {
 			dev_err(&dev->dev, "can't add resource for DMA %d\n",
@@ -642,7 +592,7 @@ struct pnp_resource *pnp_add_io_resource
 	struct resource *res;
 	static unsigned char warned;
 
-	pnp_res = pnp_new_resource(dev, IORESOURCE_IO);
+	pnp_res = pnp_new_resource(dev);
 	if (!pnp_res) {
 		if (!warned) {
 			dev_err(&dev->dev, "can't add resource for IO "
@@ -671,7 +621,7 @@ struct pnp_resource *pnp_add_mem_resourc
 	struct resource *res;
 	static unsigned char warned;
 
-	pnp_res = pnp_new_resource(dev, IORESOURCE_MEM);
+	pnp_res = pnp_new_resource(dev);
 	if (!pnp_res) {
 		if (!warned) {
 			dev_err(&dev->dev, "can't add resource for MEM "
Index: work14/drivers/pnp/support.c
===================================================================
--- work14.orig/drivers/pnp/support.c	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/support.c	2008-06-17 14:45:35.000000000 -0600
@@ -16,6 +16,10 @@
  */
 int pnp_is_active(struct pnp_dev *dev)
 {
+	/*
+	 * I don't think this is very reliable because pnp_disable_dev()
+	 * only clears out auto-assigned resources.
+	 */
 	if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 &&
 	    !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 &&
 	    pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1)
@@ -70,54 +74,34 @@ char *pnp_resource_type_name(struct reso
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
 {
 #ifdef DEBUG
+	struct pnp_resource *pnp_res;
 	struct resource *res;
-	int i;
 
 	dev_dbg(&dev->dev, "current resources: %s\n", desc);
+	list_for_each_entry(pnp_res, &dev->resources, list) {
+		res = &pnp_res->res;
 
-	for (i = 0; i < PNP_MAX_IRQ; i++) {
-		res = pnp_get_resource(dev, IORESOURCE_IRQ, i);
-		if (res && !(res->flags & IORESOURCE_UNSET))
-			dev_dbg(&dev->dev, "  irq %lld flags %#lx%s%s\n",
-				(unsigned long long) res->start, res->flags,
-				res->flags & IORESOURCE_DISABLED ?
-					" DISABLED" : "",
-				res->flags & IORESOURCE_AUTO ?
-					" AUTO" : "");
-	}
-	for (i = 0; i < PNP_MAX_DMA; i++) {
-		res = pnp_get_resource(dev, IORESOURCE_DMA, i);
-		if (res && !(res->flags & IORESOURCE_UNSET))
-			dev_dbg(&dev->dev, "  dma %lld flags %#lx%s%s\n",
-				(unsigned long long) res->start, res->flags,
-				res->flags & IORESOURCE_DISABLED ?
-					" DISABLED" : "",
-				res->flags & IORESOURCE_AUTO ?
-					" AUTO" : "");
-	}
-	for (i = 0; i < PNP_MAX_PORT; i++) {
-		res = pnp_get_resource(dev, IORESOURCE_IO, i);
-		if (res && !(res->flags & IORESOURCE_UNSET))
-			dev_dbg(&dev->dev, "  io  %#llx-%#llx flags %#lx"
-				"%s%s\n",
-				(unsigned long long) res->start,
-				(unsigned long long) res->end, res->flags,
-				res->flags & IORESOURCE_DISABLED ?
-					" DISABLED" : "",
-				res->flags & IORESOURCE_AUTO ?
-					" AUTO" : "");
-	}
-	for (i = 0; i < PNP_MAX_MEM; i++) {
-		res = pnp_get_resource(dev, IORESOURCE_MEM, i);
-		if (res && !(res->flags & IORESOURCE_UNSET))
-			dev_dbg(&dev->dev, "  mem %#llx-%#llx flags %#lx"
-				"%s%s\n",
-				(unsigned long long) res->start,
-				(unsigned long long) res->end, res->flags,
-				res->flags & IORESOURCE_DISABLED ?
-					" DISABLED" : "",
-				res->flags & IORESOURCE_AUTO ?
-					" AUTO" : "");
+		dev_dbg(&dev->dev, "  %-3s ", pnp_resource_type_name(res));
+
+		if (res->flags & IORESOURCE_DISABLED) {
+			printk("disabled\n");
+			continue;
+		}
+
+		switch (pnp_resource_type(res)) {
+		case IORESOURCE_IO:
+		case IORESOURCE_MEM:
+			printk("%#llx-%#llx flags %#lx",
+			       (unsigned long long) res->start,
+			       (unsigned long long) res->end, res->flags);
+			break;
+		case IORESOURCE_IRQ:
+		case IORESOURCE_DMA:
+			printk("%lld flags %#lx",
+			       (unsigned long long) res->start, res->flags);
+			break;
+		}
+		printk("\n");
 	}
 #endif
 }
Index: work14/drivers/pnp/system.c
===================================================================
--- work14.orig/drivers/pnp/system.c	2008-06-17 14:45:32.000000000 -0600
+++ work14/drivers/pnp/system.c	2008-06-17 14:45:35.000000000 -0600
@@ -60,7 +60,7 @@ static void reserve_resources_of_dev(str
 	int i;
 
 	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
-		if (res->flags & IORESOURCE_UNSET)
+		if (res->flags & IORESOURCE_DISABLED)
 			continue;
 		if (res->start == 0)
 			continue;	/* disabled */
@@ -81,7 +81,7 @@ static void reserve_resources_of_dev(str
 	}
 
 	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
-		if (res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
+		if (res->flags & IORESOURCE_DISABLED)
 			continue;
 
 		reserve_range(dev, res->start, res->end, 0);
Index: work14/include/linux/pnp.h
===================================================================
--- work14.orig/include/linux/pnp.h	2008-06-17 14:45:32.000000000 -0600
+++ work14/include/linux/pnp.h	2008-06-17 14:47:29.000000000 -0600
@@ -15,7 +15,6 @@
 
 struct pnp_protocol;
 struct pnp_dev;
-struct pnp_resource_table;
 
 /*
  * Resource Management
@@ -24,7 +23,14 @@ struct resource *pnp_get_resource(struct
 
 static inline int pnp_resource_valid(struct resource *res)
 {
-	if (res && !(res->flags & IORESOURCE_UNSET))
+	if (res)
+		return 1;
+	return 0;
+}
+
+static inline int pnp_resource_enabled(struct resource *res)
+{
+	if (res && !(res->flags & IORESOURCE_DISABLED))
 		return 1;
 	return 0;
 }
@@ -64,7 +70,7 @@ static inline unsigned long pnp_port_fla
 
 	if (pnp_resource_valid(res))
 		return res->flags;
-	return IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
+	return IORESOURCE_IO | IORESOURCE_AUTO;
 }
 
 static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar)
@@ -109,7 +115,7 @@ static inline unsigned long pnp_mem_flag
 
 	if (pnp_resource_valid(res))
 		return res->flags;
-	return IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
+	return IORESOURCE_MEM | IORESOURCE_AUTO;
 }
 
 static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar)
@@ -143,7 +149,7 @@ static inline unsigned long pnp_irq_flag
 
 	if (pnp_resource_valid(res))
 		return res->flags;
-	return IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
+	return IORESOURCE_IRQ | IORESOURCE_AUTO;
 }
 
 static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar)
@@ -167,7 +173,7 @@ static inline unsigned long pnp_dma_flag
 
 	if (pnp_resource_valid(res))
 		return res->flags;
-	return IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
+	return IORESOURCE_DMA | IORESOURCE_AUTO;
 }
 
 static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar)
@@ -296,7 +302,7 @@ struct pnp_dev {
 	int capabilities;
 	struct pnp_option *independent;
 	struct pnp_option *dependent;
-	struct pnp_resource_table *res;
+	struct list_head resources;
 
 	char name[PNP_NAME_LEN];	/* contains a human-readable name */
 	int flags;			/* used by protocols */

-- 

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

* [patch 07/28] PNPACPI: keep disabled resources when parsing current config
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (5 preceding siblings ...)
  2008-06-17 22:58 ` [patch 06/28] PNP: replace pnp_resource_table with dynamically allocated resources Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 08/28] PNP: remove ratelimit on add resource failures Bjorn Helgaas
                   ` (21 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-keep-disabled-resources-when-parsing-current-config --]
[-- Type: text/plain, Size: 3820 bytes --]

When we parse a device's _CRS data (the current resource settings),
we should keep track of everything we find, even if it's currently
disabled or invalid.

This is what we already do for ISAPNP and PNPBIOS, and it helps
keep things matched up when we subsequently re-encode resources.
For example, consider a device with (mem, irq0, irq1, io), where
irq0 is disabled.  If we drop irq0 when parsing the _CRS, we will
mistakenly put irq1 in the irq0 slot when we encode resources
for an _SRS call.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 14:47:29.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:46:52.000000000 -0600
@@ -98,8 +98,10 @@ static void pnpacpi_parse_allocated_irqr
 	int irq, flags;
 	int p, t;
 
-	if (!valid_IRQ(gsi))
+	if (!valid_IRQ(gsi)) {
+		pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
 		return;
+	}
 
 	/*
 	 * in IO-APIC mode, use overrided attribute. Two reasons:
@@ -248,24 +250,39 @@ static acpi_status pnpacpi_allocated_res
 		 * _CRS, but some firmware violates this, so parse them all.
 		 */
 		irq = &res->data.irq;
-		for (i = 0; i < irq->interrupt_count; i++) {
-			pnpacpi_parse_allocated_irqresource(dev,
-				irq->interrupts[i],
-				irq->triggering,
-				irq->polarity,
-				irq->sharable);
+		if (irq->interrupt_count == 0)
+			pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
+		else {
+			for (i = 0; i < irq->interrupt_count; i++) {
+				pnpacpi_parse_allocated_irqresource(dev,
+					irq->interrupts[i],
+					irq->triggering,
+					irq->polarity,
+				    irq->sharable);
+			}
+
+			/*
+			 * The IRQ encoder puts a single interrupt in each
+			 * descriptor, so if a _CRS descriptor has more than
+			 * one interrupt, we won't be able to re-encode it.
+			 */
+			if (pnp_can_write(dev) && irq->interrupt_count > 1) {
+				dev_warn(&dev->dev, "multiple interrupts in "
+					 "_CRS descriptor; configuration can't "
+					 "be changed\n");
+				dev->capabilities &= ~PNP_WRITE;
+			}
 		}
 		break;
 
 	case ACPI_RESOURCE_TYPE_DMA:
 		dma = &res->data.dma;
-		if (dma->channel_count > 0) {
+		if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
 			flags = dma_flags(dma->type, dma->bus_master,
 					  dma->transfer);
-			if (dma->channels[0] == (u8) -1)
-				flags |= IORESOURCE_DISABLED;
-			pnp_add_dma_resource(dev, dma->channels[0], flags);
-		}
+		else
+			flags = IORESOURCE_DISABLED;
+		pnp_add_dma_resource(dev, dma->channels[0], flags);
 		break;
 
 	case ACPI_RESOURCE_TYPE_IO:
@@ -331,12 +348,29 @@ static acpi_status pnpacpi_allocated_res
 		if (extended_irq->producer_consumer == ACPI_PRODUCER)
 			return AE_OK;
 
-		for (i = 0; i < extended_irq->interrupt_count; i++) {
-			pnpacpi_parse_allocated_irqresource(dev,
-				extended_irq->interrupts[i],
-				extended_irq->triggering,
-				extended_irq->polarity,
-				extended_irq->sharable);
+		if (extended_irq->interrupt_count == 0)
+			pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
+		else {
+			for (i = 0; i < extended_irq->interrupt_count; i++) {
+				pnpacpi_parse_allocated_irqresource(dev,
+					extended_irq->interrupts[i],
+					extended_irq->triggering,
+					extended_irq->polarity,
+					extended_irq->sharable);
+			}
+
+			/*
+			 * The IRQ encoder puts a single interrupt in each
+			 * descriptor, so if a _CRS descriptor has more than
+			 * one interrupt, we won't be able to re-encode it.
+			 */
+			if (pnp_can_write(dev) &&
+			    extended_irq->interrupt_count > 1) {
+				dev_warn(&dev->dev, "multiple interrupts in "
+					 "_CRS descriptor; configuration can't "
+					 "be changed\n");
+				dev->capabilities &= ~PNP_WRITE;
+			}
 		}
 		break;
 

-- 

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

* [patch 08/28] PNP: remove ratelimit on add resource failures
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (6 preceding siblings ...)
  2008-06-17 22:58 ` [patch 07/28] PNPACPI: keep disabled resources when parsing current config Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 09/28] PNP: dont sort by type in /sys/.../resources Bjorn Helgaas
                   ` (20 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-remove-warning-ratelimit --]
[-- Type: text/plain, Size: 2527 bytes --]

We used to have a fixed-size resource table.  If a device had
twenty resources when the table only had space for ten, we didn't
need ten warnings, so we added the ratelimit.

Now that we can dynamically allocate new resources, we should
only get failures if the allocation fails.  That should be
rare enough that we don't need to ratelimit the messages.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work10/drivers/pnp/resource.c
===================================================================
--- work10.orig/drivers/pnp/resource.c	2008-05-05 11:38:16.000000000 -0600
+++ work10/drivers/pnp/resource.c	2008-05-05 11:49:05.000000000 -0600
@@ -537,15 +537,10 @@ struct pnp_resource *pnp_add_irq_resourc
 {
 	struct pnp_resource *pnp_res;
 	struct resource *res;
-	static unsigned char warned;
 
 	pnp_res = pnp_new_resource(dev);
 	if (!pnp_res) {
-		if (!warned) {
-			dev_err(&dev->dev, "can't add resource for IRQ %d\n",
-				irq);
-			warned = 1;
-		}
+		dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
 		return NULL;
 	}
 
@@ -563,15 +558,10 @@ struct pnp_resource *pnp_add_dma_resourc
 {
 	struct pnp_resource *pnp_res;
 	struct resource *res;
-	static unsigned char warned;
 
 	pnp_res = pnp_new_resource(dev);
 	if (!pnp_res) {
-		if (!warned) {
-			dev_err(&dev->dev, "can't add resource for DMA %d\n",
-				dma);
-			warned = 1;
-		}
+		dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
 		return NULL;
 	}
 
@@ -590,16 +580,12 @@ struct pnp_resource *pnp_add_io_resource
 {
 	struct pnp_resource *pnp_res;
 	struct resource *res;
-	static unsigned char warned;
 
 	pnp_res = pnp_new_resource(dev);
 	if (!pnp_res) {
-		if (!warned) {
-			dev_err(&dev->dev, "can't add resource for IO "
-				"%#llx-%#llx\n",(unsigned long long) start,
-				(unsigned long long) end);
-			warned = 1;
-		}
+		dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
+			(unsigned long long) start,
+			(unsigned long long) end);
 		return NULL;
 	}
 
@@ -619,16 +605,12 @@ struct pnp_resource *pnp_add_mem_resourc
 {
 	struct pnp_resource *pnp_res;
 	struct resource *res;
-	static unsigned char warned;
 
 	pnp_res = pnp_new_resource(dev);
 	if (!pnp_res) {
-		if (!warned) {
-			dev_err(&dev->dev, "can't add resource for MEM "
-				"%#llx-%#llx\n",(unsigned long long) start,
-				(unsigned long long) end);
-			warned = 1;
-		}
+		dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
+			(unsigned long long) start,
+			(unsigned long long) end);
 		return NULL;
 	}
 

-- 

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

* [patch 09/28] PNP: dont sort by type in /sys/.../resources
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (7 preceding siblings ...)
  2008-06-17 22:58 ` [patch 08/28] PNP: remove ratelimit on add resource failures Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 10/28] PNP: add pnp_possible_config() -- can a device could be configured this way? Bjorn Helgaas
                   ` (19 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-unsort-sysfs-resources --]
[-- Type: text/plain, Size: 3075 bytes --]

Rather than stepping through all IO resources, then stepping through
all MMIO resources, etc., we can just iterate over the resource list
once directly.

This can change the order in /sys, e.g.,

    # cat /sys/devices/pnp0/00:07/resources     # OLD
    state = active
    io 0x3f8-0x3ff
    irq 4

    # cat /sys/devices/pnp0/00:07/resources     # NEW
    state = active
    irq 4
    io 0x3f8-0x3ff

The old code artificially sorted resources by type; the new code
just lists them in the order we read them from the ISAPNP hardware
or the BIOS.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work10/drivers/pnp/interface.c
===================================================================
--- work10.orig/drivers/pnp/interface.c	2008-05-05 11:54:26.000000000 -0600
+++ work10/drivers/pnp/interface.c	2008-05-05 11:59:53.000000000 -0600
@@ -248,8 +248,9 @@ static ssize_t pnp_show_current_resource
 					  char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	struct pnp_resource *pnp_res;
 	struct resource *res;
-	int i, ret;
+	int ret;
 	pnp_info_buffer_t *buffer;
 
 	if (!dev)
@@ -262,46 +263,33 @@ static ssize_t pnp_show_current_resource
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
 
-	pnp_printf(buffer, "state = ");
-	if (dev->active)
-		pnp_printf(buffer, "active\n");
-	else
-		pnp_printf(buffer, "disabled\n");
-
-	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
-		pnp_printf(buffer, "io");
-		if (res->flags & IORESOURCE_DISABLED)
-			pnp_printf(buffer, " disabled\n");
-		else
-			pnp_printf(buffer, " 0x%llx-0x%llx\n",
-				   (unsigned long long) res->start,
-				   (unsigned long long) res->end);
-	}
-	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
-		pnp_printf(buffer, "mem");
-		if (res->flags & IORESOURCE_DISABLED)
+	pnp_printf(buffer, "state = %s\n", dev->active ? "active" : "disabled");
+
+	list_for_each_entry(pnp_res, &dev->resources, list) {
+		res = &pnp_res->res;
+
+		pnp_printf(buffer, pnp_resource_type_name(res));
+
+		if (res->flags & IORESOURCE_DISABLED) {
 			pnp_printf(buffer, " disabled\n");
-		else
-			pnp_printf(buffer, " 0x%llx-0x%llx\n",
+			continue;
+		}
+
+		switch (pnp_resource_type(res)) {
+		case IORESOURCE_IO:
+		case IORESOURCE_MEM:
+			pnp_printf(buffer, " %#llx-%#llx\n",
 				   (unsigned long long) res->start,
 				   (unsigned long long) res->end);
-	}
-	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
-		pnp_printf(buffer, "irq");
-		if (res->flags & IORESOURCE_DISABLED)
-			pnp_printf(buffer, " disabled\n");
-		else
-			pnp_printf(buffer, " %lld\n",
-				   (unsigned long long) res->start);
-	}
-	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
-		pnp_printf(buffer, "dma");
-		if (res->flags & IORESOURCE_DISABLED)
-			pnp_printf(buffer, " disabled\n");
-		else
+			break;
+		case IORESOURCE_IRQ:
+		case IORESOURCE_DMA:
 			pnp_printf(buffer, " %lld\n",
 				   (unsigned long long) res->start);
+			break;
+		}
 	}
+
 	ret = (buffer->curr - buf);
 	kfree(buffer);
 	return ret;

-- 

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

* [patch 10/28] PNP: add pnp_possible_config() -- can a device could be configured this way?
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (8 preceding siblings ...)
  2008-06-17 22:58 ` [patch 09/28] PNP: dont sort by type in /sys/.../resources Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 11/28] PNP: whitespace/coding style fixes Bjorn Helgaas
                   ` (18 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-new-option-interface-for-serial-pnp --]
[-- Type: text/plain, Size: 5010 bytes --]

As part of a heuristic to identify modem devices, 8250_pnp.c
checks to see whether a device can be configured at any of the
legacy COM port addresses.

This patch moves the code that traverses the PNP "possible resource
options" from 8250_pnp.c to the PNP subsystem.  This encapsulation
is important because a future patch will change the implementation
of those resource options.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

---
 drivers/pnp/resource.c    |   61 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/serial/8250_pnp.c |   24 +++++-------------
 include/linux/pnp.h       |    3 ++
 3 files changed, 71 insertions(+), 17 deletions(-)

Index: work14/drivers/pnp/resource.c
===================================================================
--- work14.orig/drivers/pnp/resource.c	2008-06-17 14:40:37.000000000 -0600
+++ work14/drivers/pnp/resource.c	2008-06-17 14:40:39.000000000 -0600
@@ -624,6 +624,68 @@ struct pnp_resource *pnp_add_mem_resourc
 	return pnp_res;
 }
 
+static int pnp_possible_option(struct pnp_option *option, int type,
+			       resource_size_t start, resource_size_t size)
+{
+	struct pnp_option *tmp;
+	struct pnp_port *port;
+	struct pnp_mem *mem;
+	struct pnp_irq *irq;
+	struct pnp_dma *dma;
+
+	if (!option)
+		return 0;
+
+	for (tmp = option; tmp; tmp = tmp->next) {
+		switch (type) {
+		case IORESOURCE_IO:
+			for (port = tmp->port; port; port = port->next) {
+				if (port->min == start && port->size == size)
+					return 1;
+			}
+			break;
+		case IORESOURCE_MEM:
+			for (mem = tmp->mem; mem; mem = mem->next) {
+				if (mem->min == start && mem->size == size)
+					return 1;
+			}
+			break;
+		case IORESOURCE_IRQ:
+			for (irq = tmp->irq; irq; irq = irq->next) {
+				if (start < PNP_IRQ_NR &&
+				    test_bit(start, irq->map))
+					return 1;
+			}
+			break;
+		case IORESOURCE_DMA:
+			for (dma = tmp->dma; dma; dma = dma->next) {
+				if (dma->map & (1 << start))
+					return 1;
+			}
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Determine whether the specified resource is a possible configuration
+ * for this device.
+ */
+int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
+			resource_size_t size)
+{
+	if (pnp_possible_option(dev->independent, type, start, size))
+		return 1;
+
+	if (pnp_possible_option(dev->dependent, type, start, size))
+		return 1;
+
+	return 0;
+}
+EXPORT_SYMBOL(pnp_possible_config);
+
 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
 static int __init pnp_setup_reserve_irq(char *str)
 {
Index: work14/drivers/serial/8250_pnp.c
===================================================================
--- work14.orig/drivers/serial/8250_pnp.c	2008-06-17 14:24:21.000000000 -0600
+++ work14/drivers/serial/8250_pnp.c	2008-06-17 14:40:39.000000000 -0600
@@ -383,21 +383,14 @@ static int __devinit check_name(char *na
 	return 0;
 }
 
-static int __devinit check_resources(struct pnp_option *option)
+static int __devinit check_resources(struct pnp_dev *dev)
 {
-	struct pnp_option *tmp;
-	if (!option)
-		return 0;
+	resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
+	int i;
 
-	for (tmp = option; tmp; tmp = tmp->next) {
-		struct pnp_port *port;
-		for (port = tmp->port; port; port = port->next)
-			if ((port->size == 8) &&
-			    ((port->min == 0x2f8) ||
-			     (port->min == 0x3f8) ||
-			     (port->min == 0x2e8) ||
-			     (port->min == 0x3e8)))
-				return 1;
+	for (i = 0; i < ARRAY_SIZE(base); i++) {
+		if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
+			return 1;
 	}
 
 	return 0;
@@ -420,10 +413,7 @@ static int __devinit serial_pnp_guess_bo
 		(dev->card && check_name(dev->card->name))))
 			return -ENODEV;
 
-	if (check_resources(dev->independent))
-		return 0;
-
-	if (check_resources(dev->dependent))
+	if (check_resources(dev))
 		return 0;
 
 	return -ENODEV;
Index: work14/include/linux/pnp.h
===================================================================
--- work14.orig/include/linux/pnp.h	2008-06-17 14:40:29.000000000 -0600
+++ work14/include/linux/pnp.h	2008-06-17 14:40:39.000000000 -0600
@@ -479,6 +479,8 @@ void pnp_unregister_card_driver(struct p
 extern struct list_head pnp_cards;
 
 /* resource management */
+int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t base,
+			resource_size_t size);
 int pnp_auto_config_dev(struct pnp_dev *dev);
 int pnp_start_dev(struct pnp_dev *dev);
 int pnp_stop_dev(struct pnp_dev *dev);
@@ -506,6 +508,7 @@ static inline int pnp_register_card_driv
 static inline void pnp_unregister_card_driver(struct pnp_card_driver *drv) { }
 
 /* resource management */
+static inline int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t base, resource_size_t size) { return 0; }
 static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; }
 static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; }
 static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; }

-- 

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

* [patch 11/28] PNP: whitespace/coding style fixes
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (9 preceding siblings ...)
  2008-06-17 22:58 ` [patch 10/28] PNP: add pnp_possible_config() -- can a device could be configured this way? Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 12/28] PNP: define PNP-specific IORESOURCE_IO_* flags alongside IRQ, DMA, MEM Bjorn Helgaas
                   ` (17 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-interface-style --]
[-- Type: text/plain, Size: 1897 bytes --]

No functional change; just make a couple declarations
consistent with the rest of the file.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work10/drivers/pnp/interface.c
===================================================================
--- work10.orig/drivers/pnp/interface.c	2008-05-09 14:42:25.000000000 -0600
+++ work10/drivers/pnp/interface.c	2008-05-09 14:45:57.000000000 -0600
@@ -216,12 +216,12 @@ static ssize_t pnp_show_options(struct d
 				struct device_attribute *attr, char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	pnp_info_buffer_t *buffer;
 	struct pnp_option *independent = dev->independent;
 	struct pnp_option *dependent = dev->dependent;
 	int ret, dep = 1;
 
-	pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
-	    pnp_alloc(sizeof(pnp_info_buffer_t));
+	buffer = pnp_alloc(sizeof(pnp_info_buffer_t));
 	if (!buffer)
 		return -ENOMEM;
 
@@ -248,17 +248,18 @@ static ssize_t pnp_show_current_resource
 					  char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
+	pnp_info_buffer_t *buffer;
 	struct pnp_resource *pnp_res;
 	struct resource *res;
 	int ret;
-	pnp_info_buffer_t *buffer;
 
 	if (!dev)
 		return -EINVAL;
 
-	buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
+	buffer = pnp_alloc(sizeof(pnp_info_buffer_t));
 	if (!buffer)
 		return -ENOMEM;
+
 	buffer->len = PAGE_SIZE;
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
@@ -295,9 +296,9 @@ static ssize_t pnp_show_current_resource
 	return ret;
 }
 
-static ssize_t
-pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
-			  const char *ubuf, size_t count)
+static ssize_t pnp_set_current_resources(struct device *dmdev,
+					 struct device_attribute *attr,
+					 const char *ubuf, size_t count)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	char *buf = (void *)ubuf;

-- 

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

* [patch 12/28] PNP: define PNP-specific IORESOURCE_IO_* flags alongside IRQ, DMA, MEM
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (10 preceding siblings ...)
  2008-06-17 22:58 ` [patch 11/28] PNP: whitespace/coding style fixes Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 13/28] PNP: make resource option structures private to PNP subsystem Bjorn Helgaas
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-io-option-flags --]
[-- Type: text/plain, Size: 6059 bytes --]

PNP previously defined PNP_PORT_FLAG_16BITADDR and PNP_PORT_FLAG_FIXED
in a private header file, but put those flags in struct resource.flags
fields.  Better to make them IORESOURCE_IO_* flags like the existing
IRQ, DMA, and MEM flags.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

---
 include/linux/ioport.h         |   10 +++++++---
 include/linux/pnp.h            |    3 ---
 drivers/pnp/interface.c        |    2 +-
 drivers/pnp/isapnp/core.c      |    4 ++--
 drivers/pnp/pnpacpi/rsparser.c |   10 +++++-----
 drivers/pnp/pnpbios/rsparser.c |    4 ++--
 6 files changed, 17 insertions(+), 16 deletions(-)

Index: work14/include/linux/ioport.h
===================================================================
--- work14.orig/include/linux/ioport.h	2008-06-17 14:42:48.000000000 -0600
+++ work14/include/linux/ioport.h	2008-06-17 15:52:16.000000000 -0600
@@ -88,6 +88,10 @@ struct resource_list {
 #define IORESOURCE_MEM_SHADOWABLE	(1<<5)	/* dup: IORESOURCE_SHADOWABLE */
 #define IORESOURCE_MEM_EXPANSIONROM	(1<<6)
 
+/* PnP I/O specific bits (IORESOURCE_BITS) */
+#define IORESOURCE_IO_16BIT_ADDR	(1<<0)
+#define IORESOURCE_IO_FIXED		(1<<1)
+
 /* PCI ROM control bits (IORESOURCE_BITS) */
 #define IORESOURCE_ROM_ENABLE		(1<<0)	/* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
 #define IORESOURCE_ROM_SHADOW		(1<<1)	/* ROM is copy at C000:0 */
Index: work14/include/linux/pnp.h
===================================================================
--- work14.orig/include/linux/pnp.h	2008-06-17 15:52:14.000000000 -0600
+++ work14/include/linux/pnp.h	2008-06-17 15:52:16.000000000 -0600
@@ -182,9 +182,6 @@ static inline int pnp_dma_valid(struct p
 }
 
 
-#define PNP_PORT_FLAG_16BITADDR	(1<<0)
-#define PNP_PORT_FLAG_FIXED	(1<<1)
-
 struct pnp_port {
 	unsigned short min;	/* min base number */
 	unsigned short max;	/* max base number */
Index: work14/drivers/pnp/interface.c
===================================================================
--- work14.orig/drivers/pnp/interface.c	2008-06-17 15:52:15.000000000 -0600
+++ work14/drivers/pnp/interface.c	2008-06-17 15:52:16.000000000 -0600
@@ -57,7 +57,7 @@ static void pnp_print_port(pnp_info_buff
 		   "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
 		   space, port->min, port->max,
 		   port->align ? (port->align - 1) : 0, port->size,
-		   port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10);
+		   port->flags & IORESOURCE_IO_16BIT_ADDR ? 16 : 10);
 }
 
 static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
Index: work14/drivers/pnp/isapnp/core.c
===================================================================
--- work14.orig/drivers/pnp/isapnp/core.c	2008-06-17 14:47:29.000000000 -0600
+++ work14/drivers/pnp/isapnp/core.c	2008-06-17 15:52:16.000000000 -0600
@@ -486,7 +486,7 @@ static void __init isapnp_parse_port_res
 	port->max = (tmp[4] << 8) | tmp[3];
 	port->align = tmp[5];
 	port->size = tmp[6];
-	port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0;
+	port->flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0;
 	pnp_register_port_resource(dev, option, port);
 }
 
@@ -507,7 +507,7 @@ static void __init isapnp_parse_fixed_po
 	port->min = port->max = (tmp[1] << 8) | tmp[0];
 	port->size = tmp[2];
 	port->align = 0;
-	port->flags = PNP_PORT_FLAG_FIXED;
+	port->flags = IORESOURCE_IO_FIXED;
 	pnp_register_port_resource(dev, option, port);
 }
 
Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:46:52.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:16.000000000 -0600
@@ -180,7 +180,7 @@ static void pnpacpi_parse_allocated_iore
 	u64 end = start + len - 1;
 
 	if (io_decode == ACPI_DECODE_16)
-		flags |= PNP_PORT_FLAG_16BITADDR;
+		flags |= IORESOURCE_IO_16BIT_ADDR;
 	if (len == 0 || end >= 0x10003)
 		flags |= IORESOURCE_DISABLED;
 
@@ -485,7 +485,7 @@ static __init void pnpacpi_parse_port_op
 	port->align = io->alignment;
 	port->size = io->address_length;
 	port->flags = ACPI_DECODE_16 == io->io_decode ?
-	    PNP_PORT_FLAG_16BITADDR : 0;
+	    IORESOURCE_IO_16BIT_ADDR : 0;
 	pnp_register_port_resource(dev, option, port);
 }
 
@@ -503,7 +503,7 @@ static __init void pnpacpi_parse_fixed_p
 	port->min = port->max = io->address;
 	port->size = io->address_length;
 	port->align = 0;
-	port->flags = PNP_PORT_FLAG_FIXED;
+	port->flags = IORESOURCE_IO_FIXED;
 	pnp_register_port_resource(dev, option, port);
 }
 
@@ -609,7 +609,7 @@ static __init void pnpacpi_parse_address
 		port->min = port->max = p->minimum;
 		port->size = p->address_length;
 		port->align = 0;
-		port->flags = PNP_PORT_FLAG_FIXED;
+		port->flags = IORESOURCE_IO_FIXED;
 		pnp_register_port_resource(dev, option, port);
 	}
 }
@@ -946,7 +946,7 @@ static void pnpacpi_encode_io(struct pnp
 
 	if (pnp_resource_enabled(p)) {
 		/* Note: pnp_assign_port copies pnp_port->flags into p->flags */
-		io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
+		io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ?
 		    ACPI_DECODE_16 : ACPI_DECODE_10;
 		io->minimum = p->start;
 		io->maximum = p->end;
Index: work14/drivers/pnp/pnpbios/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpbios/rsparser.c	2008-06-17 14:47:29.000000000 -0600
+++ work14/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:16.000000000 -0600
@@ -310,7 +310,7 @@ static __init void pnpbios_parse_port_op
 	port->max = (p[5] << 8) | p[4];
 	port->align = p[6];
 	port->size = p[7];
-	port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
+	port->flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0;
 	pnp_register_port_resource(dev, option, port);
 }
 
@@ -326,7 +326,7 @@ static __init void pnpbios_parse_fixed_p
 	port->min = port->max = (p[2] << 8) | p[1];
 	port->size = p[3];
 	port->align = 0;
-	port->flags = PNP_PORT_FLAG_FIXED;
+	port->flags = IORESOURCE_IO_FIXED;
 	pnp_register_port_resource(dev, option, port);
 }
 

-- 

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

* [patch 13/28] PNP: make resource option structures private to PNP subsystem
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (11 preceding siblings ...)
  2008-06-17 22:58 ` [patch 12/28] PNP: define PNP-specific IORESOURCE_IO_* flags alongside IRQ, DMA, MEM Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 14/28] PNP: introduce pnp_irq_mask_t typedef Bjorn Helgaas
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-make-option-structures-private --]
[-- Type: text/plain, Size: 4171 bytes --]

Nothing outside the PNP subsystem should need access to a
device's resource options, so this patch moves the option
structure declarations to a private header file.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work14/drivers/pnp/base.h
===================================================================
--- work14.orig/drivers/pnp/base.h	2008-06-17 14:40:28.000000000 -0600
+++ work14/drivers/pnp/base.h	2008-06-17 14:42:28.000000000 -0600
@@ -19,6 +19,54 @@ void pnp_remove_card(struct pnp_card *ca
 int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
 void pnp_remove_card_device(struct pnp_dev *dev);
 
+struct pnp_port {
+	unsigned short min;	/* min base number */
+	unsigned short max;	/* max base number */
+	unsigned char align;	/* align boundary */
+	unsigned char size;	/* size of range */
+	unsigned char flags;	/* port flags */
+	unsigned char pad;	/* pad */
+	struct pnp_port *next;	/* next port */
+};
+
+#define PNP_IRQ_NR 256
+struct pnp_irq {
+	DECLARE_BITMAP(map, PNP_IRQ_NR);	/* bitmask for IRQ lines */
+	unsigned char flags;	/* IRQ flags */
+	unsigned char pad;	/* pad */
+	struct pnp_irq *next;	/* next IRQ */
+};
+
+struct pnp_dma {
+	unsigned char map;	/* bitmask for DMA channels */
+	unsigned char flags;	/* DMA flags */
+	struct pnp_dma *next;	/* next port */
+};
+
+struct pnp_mem {
+	unsigned int min;	/* min base number */
+	unsigned int max;	/* max base number */
+	unsigned int align;	/* align boundary */
+	unsigned int size;	/* size of range */
+	unsigned char flags;	/* memory flags */
+	unsigned char pad;	/* pad */
+	struct pnp_mem *next;	/* next memory resource */
+};
+
+#define PNP_RES_PRIORITY_PREFERRED	0
+#define PNP_RES_PRIORITY_ACCEPTABLE	1
+#define PNP_RES_PRIORITY_FUNCTIONAL	2
+#define PNP_RES_PRIORITY_INVALID	65535
+
+struct pnp_option {
+	unsigned short priority;	/* priority */
+	struct pnp_port *port;		/* first port */
+	struct pnp_irq *irq;		/* first IRQ */
+	struct pnp_dma *dma;		/* first DMA */
+	struct pnp_mem *mem;		/* first memory resource */
+	struct pnp_option *next;	/* used to chain dependent resources */
+};
+
 struct pnp_option *pnp_build_option(int priority);
 struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
 struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
Index: work14/include/linux/pnp.h
===================================================================
--- work14.orig/include/linux/pnp.h	2008-06-17 14:41:18.000000000 -0600
+++ work14/include/linux/pnp.h	2008-06-17 14:42:28.000000000 -0600
@@ -182,54 +182,6 @@ static inline int pnp_dma_valid(struct p
 }
 
 
-struct pnp_port {
-	unsigned short min;	/* min base number */
-	unsigned short max;	/* max base number */
-	unsigned char align;	/* align boundary */
-	unsigned char size;	/* size of range */
-	unsigned char flags;	/* port flags */
-	unsigned char pad;	/* pad */
-	struct pnp_port *next;	/* next port */
-};
-
-#define PNP_IRQ_NR 256
-struct pnp_irq {
-	DECLARE_BITMAP(map, PNP_IRQ_NR);	/* bitmask for IRQ lines */
-	unsigned char flags;	/* IRQ flags */
-	unsigned char pad;	/* pad */
-	struct pnp_irq *next;	/* next IRQ */
-};
-
-struct pnp_dma {
-	unsigned char map;	/* bitmask for DMA channels */
-	unsigned char flags;	/* DMA flags */
-	struct pnp_dma *next;	/* next port */
-};
-
-struct pnp_mem {
-	unsigned int min;	/* min base number */
-	unsigned int max;	/* max base number */
-	unsigned int align;	/* align boundary */
-	unsigned int size;	/* size of range */
-	unsigned char flags;	/* memory flags */
-	unsigned char pad;	/* pad */
-	struct pnp_mem *next;	/* next memory resource */
-};
-
-#define PNP_RES_PRIORITY_PREFERRED	0
-#define PNP_RES_PRIORITY_ACCEPTABLE	1
-#define PNP_RES_PRIORITY_FUNCTIONAL	2
-#define PNP_RES_PRIORITY_INVALID	65535
-
-struct pnp_option {
-	unsigned short priority;	/* priority */
-	struct pnp_port *port;		/* first port */
-	struct pnp_irq *irq;		/* first IRQ */
-	struct pnp_dma *dma;		/* first DMA */
-	struct pnp_mem *mem;		/* first memory resource */
-	struct pnp_option *next;	/* used to chain dependent resources */
-};
-
 /*
  * Device Management
  */

-- 

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

* [patch 14/28] PNP: introduce pnp_irq_mask_t typedef
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (12 preceding siblings ...)
  2008-06-17 22:58 ` [patch 13/28] PNP: make resource option structures private to PNP subsystem Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 15/28] PNP: increase I/O port & memory option address sizes Bjorn Helgaas
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-irq-bitmap-decl --]
[-- Type: text/plain, Size: 6519 bytes --]

This adds a typedef for the IRQ bitmap, which should cause
no functional change, but will make it easier to pass a
pointer to a bitmap to pnp_register_irq_resource().

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work14/drivers/pnp/base.h
===================================================================
--- work14.orig/drivers/pnp/base.h	2008-06-17 15:52:19.000000000 -0600
+++ work14/drivers/pnp/base.h	2008-06-17 15:52:20.000000000 -0600
@@ -30,8 +30,10 @@ struct pnp_port {
 };
 
 #define PNP_IRQ_NR 256
+typedef struct { DECLARE_BITMAP(bits, PNP_IRQ_NR); } pnp_irq_mask_t;
+
 struct pnp_irq {
-	DECLARE_BITMAP(map, PNP_IRQ_NR);	/* bitmask for IRQ lines */
+	pnp_irq_mask_t map;	/* bitmap for IRQ lines */
 	unsigned char flags;	/* IRQ flags */
 	unsigned char pad;	/* pad */
 	struct pnp_irq *next;	/* next IRQ */
Index: work14/drivers/pnp/resource.c
===================================================================
--- work14.orig/drivers/pnp/resource.c	2008-06-17 15:52:14.000000000 -0600
+++ work14/drivers/pnp/resource.c	2008-06-17 15:52:20.000000000 -0600
@@ -98,13 +98,13 @@ int pnp_register_irq_resource(struct pnp
 		int i;
 
 		for (i = 0; i < 16; i++)
-			if (test_bit(i, data->map))
+			if (test_bit(i, data->map.bits))
 				pcibios_penalize_isa_irq(i, 0);
 	}
 #endif
 
 #ifdef DEBUG
-	bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR);
+	bitmap_scnprintf(buf, sizeof(buf), data->map.bits, PNP_IRQ_NR);
 	dev_dbg(&dev->dev, "  irq bitmask %s flags %#x\n", buf,
 		data->flags);
 #endif
@@ -653,7 +653,7 @@ static int pnp_possible_option(struct pn
 		case IORESOURCE_IRQ:
 			for (irq = tmp->irq; irq; irq = irq->next) {
 				if (start < PNP_IRQ_NR &&
-				    test_bit(start, irq->map))
+				    test_bit(start, irq->map.bits))
 					return 1;
 			}
 			break;
Index: work14/drivers/pnp/manager.c
===================================================================
--- work14.orig/drivers/pnp/manager.c	2008-06-17 14:45:35.000000000 -0600
+++ work14/drivers/pnp/manager.c	2008-06-17 15:52:20.000000000 -0600
@@ -128,20 +128,20 @@ static int pnp_assign_irq(struct pnp_dev
 	res->start = -1;
 	res->end = -1;
 
-	if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
+	if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) {
 		res->flags |= IORESOURCE_DISABLED;
 		dev_dbg(&dev->dev, "  irq %d disabled\n", idx);
 		goto __add;
 	}
 
 	/* TBD: need check for >16 IRQ */
-	res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
+	res->start = find_next_bit(rule->map.bits, PNP_IRQ_NR, 16);
 	if (res->start < PNP_IRQ_NR) {
 		res->end = res->start;
 		goto __add;
 	}
 	for (i = 0; i < 16; i++) {
-		if (test_bit(xtab[i], rule->map)) {
+		if (test_bit(xtab[i], rule->map.bits)) {
 			res->start = res->end = xtab[i];
 			if (pnp_check_irq(dev, res))
 				goto __add;
Index: work14/drivers/pnp/interface.c
===================================================================
--- work14.orig/drivers/pnp/interface.c	2008-06-17 15:52:16.000000000 -0600
+++ work14/drivers/pnp/interface.c	2008-06-17 15:52:20.000000000 -0600
@@ -67,7 +67,7 @@ static void pnp_print_irq(pnp_info_buffe
 
 	pnp_printf(buffer, "%sirq ", space);
 	for (i = 0; i < PNP_IRQ_NR; i++)
-		if (test_bit(i, irq->map)) {
+		if (test_bit(i, irq->map.bits)) {
 			if (!first) {
 				pnp_printf(buffer, ",");
 			} else {
@@ -78,7 +78,7 @@ static void pnp_print_irq(pnp_info_buffe
 			else
 				pnp_printf(buffer, "%i", i);
 		}
-	if (bitmap_empty(irq->map, PNP_IRQ_NR))
+	if (bitmap_empty(irq->map.bits, PNP_IRQ_NR))
 		pnp_printf(buffer, "<none>");
 	if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
 		pnp_printf(buffer, " High-Edge");
Index: work14/drivers/pnp/isapnp/core.c
===================================================================
--- work14.orig/drivers/pnp/isapnp/core.c	2008-06-17 15:52:16.000000000 -0600
+++ work14/drivers/pnp/isapnp/core.c	2008-06-17 15:52:20.000000000 -0600
@@ -441,7 +441,7 @@ static void __init isapnp_parse_irq_reso
 	if (!irq)
 		return;
 	bits = (tmp[1] << 8) | tmp[0];
-	bitmap_copy(irq->map, &bits, 16);
+	bitmap_copy(irq->map.bits, &bits, 16);
 	if (size > 2)
 		irq->flags = tmp[2];
 	else
Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:16.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:20.000000000 -0600
@@ -442,7 +442,7 @@ static __init void pnpacpi_parse_irq_opt
 
 	for (i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
-			__set_bit(p->interrupts[i], irq->map);
+			__set_bit(p->interrupts[i], irq->map.bits);
 	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
 
 	pnp_register_irq_resource(dev, option, irq);
@@ -463,7 +463,7 @@ static __init void pnpacpi_parse_ext_irq
 
 	for (i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
-			__set_bit(p->interrupts[i], irq->map);
+			__set_bit(p->interrupts[i], irq->map.bits);
 	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
 
 	pnp_register_irq_resource(dev, option, irq);
Index: work14/drivers/pnp/quirks.c
===================================================================
--- work14.orig/drivers/pnp/quirks.c	2008-06-17 14:45:35.000000000 -0600
+++ work14/drivers/pnp/quirks.c	2008-06-17 15:52:20.000000000 -0600
@@ -68,7 +68,7 @@ static void quirk_cmi8330_resources(stru
 
 		for (irq = res->irq; irq; irq = irq->next) {	// Valid irqs are 5, 7, 10
 			tmp = 0x04A0;
-			bitmap_copy(irq->map, &tmp, 16);	// 0000 0100 1010 0000
+			bitmap_copy(irq->map.bits, &tmp, 16);	// 0000 0100 1010 0000
 		}
 
 		for (dma = res->dma; dma; dma = dma->next)	// Valid 8bit dma channels are 1,3
@@ -187,7 +187,7 @@ static void quirk_ad1815_mpu_resources(s
 		if (!copy)
 			break;
 
-		memcpy(copy->map, irq->map, sizeof copy->map);
+		bitmap_copy(copy->map.bits, irq->map.bits, PNP_IRQ_NR);
 		copy->flags = irq->flags;
 
 		copy->next = res->irq; /* Yes, this is NULL */
Index: work14/drivers/pnp/pnpbios/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:16.000000000 -0600
+++ work14/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:20.000000000 -0600
@@ -275,7 +275,7 @@ static __init void pnpbios_parse_irq_opt
 	if (!irq)
 		return;
 	bits = (p[2] << 8) | p[1];
-	bitmap_copy(irq->map, &bits, 16);
+	bitmap_copy(irq->map.bits, &bits, 16);
 	if (size > 2)
 		irq->flags = p[3];
 	else

-- 

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

* [patch 15/28] PNP: increase I/O port & memory option address sizes
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (13 preceding siblings ...)
  2008-06-17 22:58 ` [patch 14/28] PNP: introduce pnp_irq_mask_t typedef Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 16/28] PNP: improve resource assignment debug Bjorn Helgaas
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-option-resource-size --]
[-- Type: text/plain, Size: 4617 bytes --]

ACPI Address Space Descriptors can be up to 64 bits wide.
We should keep track of the whole thing when parsing resource
options, so this patch changes PNP port and mem option
fields from "unsigned short" and "unsigned int" to
"resource_size_t".

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

---
 drivers/pnp/base.h      |   16 ++++++++--------
 drivers/pnp/interface.c |   17 +++++++++++------
 drivers/pnp/resource.c  |   14 ++++++++++----
 3 files changed, 29 insertions(+), 18 deletions(-)

Index: work10/drivers/pnp/base.h
===================================================================
--- work10.orig/drivers/pnp/base.h	2008-05-16 16:13:34.000000000 -0600
+++ work10/drivers/pnp/base.h	2008-05-16 16:13:37.000000000 -0600
@@ -20,10 +20,10 @@ int pnp_add_card_device(struct pnp_card 
 void pnp_remove_card_device(struct pnp_dev *dev);
 
 struct pnp_port {
-	unsigned short min;	/* min base number */
-	unsigned short max;	/* max base number */
-	unsigned char align;	/* align boundary */
-	unsigned char size;	/* size of range */
+	resource_size_t min;	/* min base number */
+	resource_size_t max;	/* max base number */
+	resource_size_t align;	/* align boundary */
+	resource_size_t size;	/* size of range */
 	unsigned char flags;	/* port flags */
 	unsigned char pad;	/* pad */
 	struct pnp_port *next;	/* next port */
@@ -46,10 +46,10 @@ struct pnp_dma {
 };
 
 struct pnp_mem {
-	unsigned int min;	/* min base number */
-	unsigned int max;	/* max base number */
-	unsigned int align;	/* align boundary */
-	unsigned int size;	/* size of range */
+	resource_size_t min;	/* min base number */
+	resource_size_t max;	/* max base number */
+	resource_size_t align;	/* align boundary */
+	resource_size_t size;	/* size of range */
 	unsigned char flags;	/* memory flags */
 	unsigned char pad;	/* pad */
 	struct pnp_mem *next;	/* next memory resource */
Index: work10/drivers/pnp/interface.c
===================================================================
--- work10.orig/drivers/pnp/interface.c	2008-05-16 16:13:34.000000000 -0600
+++ work10/drivers/pnp/interface.c	2008-05-16 16:13:37.000000000 -0600
@@ -53,10 +53,12 @@ static int pnp_printf(pnp_info_buffer_t 
 static void pnp_print_port(pnp_info_buffer_t * buffer, char *space,
 			   struct pnp_port *port)
 {
-	pnp_printf(buffer,
-		   "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
-		   space, port->min, port->max,
-		   port->align ? (port->align - 1) : 0, port->size,
+	pnp_printf(buffer, "%sport %#llx-%#llx, align %#llx, size %#llx, "
+		   "%i-bit address decoding\n", space,
+		   (unsigned long long) port->min,
+		   (unsigned long long) port->max,
+		   port->align ? ((unsigned long long) port->align - 1) : 0,
+		   (unsigned long long) port->size,
 		   port->flags & IORESOURCE_IO_16BIT_ADDR ? 16 : 10);
 }
 
@@ -148,8 +150,11 @@ static void pnp_print_mem(pnp_info_buffe
 {
 	char *s;
 
-	pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
-		   space, mem->min, mem->max, mem->align, mem->size);
+	pnp_printf(buffer, "%sMemory %#llx-%#llx, align %#llx, size %#llx",
+		   space, (unsigned long long) mem->min,
+		   (unsigned long long) mem->max,
+		   (unsigned long long) mem->align,
+		   (unsigned long long) mem->size);
 	if (mem->flags & IORESOURCE_MEM_WRITEABLE)
 		pnp_printf(buffer, ", writeable");
 	if (mem->flags & IORESOURCE_MEM_CACHEABLE)
Index: work10/drivers/pnp/resource.c
===================================================================
--- work10.orig/drivers/pnp/resource.c	2008-05-16 16:13:34.000000000 -0600
+++ work10/drivers/pnp/resource.c	2008-05-16 16:13:37.000000000 -0600
@@ -143,8 +143,11 @@ int pnp_register_port_resource(struct pn
 		option->port = data;
 
 	dev_dbg(&dev->dev, "  io  "
-		"min %#x max %#x align %d size %d flags %#x\n",
-		data->min, data->max, data->align, data->size, data->flags);
+		"min %#llx max %#llx align %lld size %lld flags %#x\n",
+		(unsigned long long) data->min,
+		(unsigned long long) data->max,
+		(unsigned long long) data->align,
+		(unsigned long long) data->size, data->flags);
 	return 0;
 }
 
@@ -162,8 +165,11 @@ int pnp_register_mem_resource(struct pnp
 		option->mem = data;
 
 	dev_dbg(&dev->dev, "  mem "
-		"min %#x max %#x align %d size %d flags %#x\n",
-		data->min, data->max, data->align, data->size, data->flags);
+		"min %#llx max %#llx align %lld size %lld flags %#x\n",
+		(unsigned long long) data->min,
+		(unsigned long long) data->max,
+		(unsigned long long) data->align,
+		(unsigned long long) data->size, data->flags);
 	return 0;
 }
 

-- 

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

* [patch 16/28] PNP: improve resource assignment debug
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (14 preceding siblings ...)
  2008-06-17 22:58 ` [patch 15/28] PNP: increase I/O port & memory option address sizes Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 17/28] PNP: in debug resource dump, make empty list obvious Bjorn Helgaas
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-improve-assign-debug --]
[-- Type: text/plain, Size: 1326 bytes --]

When we fail to assign an I/O or MEM resource, include the min/max
in the debug output to help match it with the options.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work10/drivers/pnp/manager.c
===================================================================
--- work10.orig/drivers/pnp/manager.c	2008-05-13 12:01:17.000000000 -0600
+++ work10/drivers/pnp/manager.c	2008-05-13 12:50:57.000000000 -0600
@@ -47,7 +47,10 @@ static int pnp_assign_port(struct pnp_de
 		res->start += rule->align;
 		res->end = res->start + rule->size - 1;
 		if (res->start > rule->max || !rule->align) {
-			dev_dbg(&dev->dev, "  couldn't assign io %d\n", idx);
+			dev_dbg(&dev->dev, "  couldn't assign io %d "
+				"(min %#llx max %#llx)\n", idx,
+				(unsigned long long) rule->min,
+				(unsigned long long) rule->max);
 			return 0;
 		}
 	}
@@ -96,7 +99,10 @@ static int pnp_assign_mem(struct pnp_dev
 		res->start += rule->align;
 		res->end = res->start + rule->size - 1;
 		if (res->start > rule->max || !rule->align) {
-			dev_dbg(&dev->dev, "  couldn't assign mem %d\n", idx);
+			dev_dbg(&dev->dev, "  couldn't assign mem %d "
+				"(min %#llx max %#llx)\n", idx,
+				(unsigned long long) rule->min,
+				(unsigned long long) rule->max);
 			return 0;
 		}
 	}

-- 

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

* [patch 17/28] PNP: in debug resource dump, make empty list obvious
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (15 preceding siblings ...)
  2008-06-17 22:58 ` [patch 16/28] PNP: improve resource assignment debug Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 18/28] PNP: make resource assignment functions return 0 (success) or -EBUSY (failure) Bjorn Helgaas
                   ` (11 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-improve-debug-resource-dump --]
[-- Type: text/plain, Size: 1024 bytes --]

If the resource list is empty, say that explicitly.  Previously,
it was confusing because often the heading was followed by zero
resource lines, then some "add resource" lines from auto-assignment,
so the "add" lines looked like current resources.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work10/drivers/pnp/support.c
===================================================================
--- work10.orig/drivers/pnp/support.c	2008-05-16 16:01:26.000000000 -0600
+++ work10/drivers/pnp/support.c	2008-05-16 16:13:42.000000000 -0600
@@ -77,7 +77,12 @@ void dbg_pnp_show_resources(struct pnp_d
 	struct pnp_resource *pnp_res;
 	struct resource *res;
 
-	dev_dbg(&dev->dev, "current resources: %s\n", desc);
+	if (list_empty(&dev->resources)) {
+		dev_dbg(&dev->dev, "%s: no current resources\n", desc);
+		return;
+	}
+
+	dev_dbg(&dev->dev, "%s: current resources:\n", desc);
 	list_for_each_entry(pnp_res, &dev->resources, list) {
 		res = &pnp_res->res;
 

-- 

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

* [patch 18/28] PNP: make resource assignment functions return 0 (success) or -EBUSY (failure)
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (16 preceding siblings ...)
  2008-06-17 22:58 ` [patch 17/28] PNP: in debug resource dump, make empty list obvious Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 19/28] PNP: remove redundant pnp_can_configure() check Bjorn Helgaas
                   ` (10 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-change-assignment-return-values --]
[-- Type: text/plain, Size: 4614 bytes --]

This patch doesn't change any behavior; it just makes the return
values more conventional.

This changes pnp_assign_dma() from a void function to one that
returns an int, just like the other assignment functions.  For
now, at least, pnp_assign_dma() always returns 0 (success), so
it appears to never fail, just like before.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work10/drivers/pnp/manager.c
===================================================================
--- work10.orig/drivers/pnp/manager.c	2008-05-13 13:27:01.000000000 -0600
+++ work10/drivers/pnp/manager.c	2008-05-13 13:29:05.000000000 -0600
@@ -26,7 +26,7 @@ static int pnp_assign_port(struct pnp_de
 		dev_dbg(&dev->dev, "  io %d already set to %#llx-%#llx "
 			"flags %#lx\n", idx, (unsigned long long) res->start,
 			(unsigned long long) res->end, res->flags);
-		return 1;
+		return 0;
 	}
 
 	res = &local_res;
@@ -51,13 +51,13 @@ static int pnp_assign_port(struct pnp_de
 				"(min %#llx max %#llx)\n", idx,
 				(unsigned long long) rule->min,
 				(unsigned long long) rule->max);
-			return 0;
+			return -EBUSY;
 		}
 	}
 
 __add:
 	pnp_add_io_resource(dev, res->start, res->end, res->flags);
-	return 1;
+	return 0;
 }
 
 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
@@ -69,7 +69,7 @@ static int pnp_assign_mem(struct pnp_dev
 		dev_dbg(&dev->dev, "  mem %d already set to %#llx-%#llx "
 			"flags %#lx\n", idx, (unsigned long long) res->start,
 			(unsigned long long) res->end, res->flags);
-		return 1;
+		return 0;
 	}
 
 	res = &local_res;
@@ -103,13 +103,13 @@ static int pnp_assign_mem(struct pnp_dev
 				"(min %#llx max %#llx)\n", idx,
 				(unsigned long long) rule->min,
 				(unsigned long long) rule->max);
-			return 0;
+			return -EBUSY;
 		}
 	}
 
 __add:
 	pnp_add_mem_resource(dev, res->start, res->end, res->flags);
-	return 1;
+	return 0;
 }
 
 static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
@@ -126,7 +126,7 @@ static int pnp_assign_irq(struct pnp_dev
 	if (res) {
 		dev_dbg(&dev->dev, "  irq %d already set to %d flags %#lx\n",
 			idx, (int) res->start, res->flags);
-		return 1;
+		return 0;
 	}
 
 	res = &local_res;
@@ -154,14 +154,14 @@ static int pnp_assign_irq(struct pnp_dev
 		}
 	}
 	dev_dbg(&dev->dev, "  couldn't assign irq %d\n", idx);
-	return 0;
+	return -EBUSY;
 
 __add:
 	pnp_add_irq_resource(dev, res->start, res->flags);
-	return 1;
+	return 0;
 }
 
-static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
+static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
 {
 	struct resource *res, local_res;
 	int i;
@@ -175,7 +175,7 @@ static void pnp_assign_dma(struct pnp_de
 	if (res) {
 		dev_dbg(&dev->dev, "  dma %d already set to %d flags %#lx\n",
 			idx, (int) res->start, res->flags);
-		return;
+		return 0;
 	}
 
 	res = &local_res;
@@ -198,6 +198,7 @@ static void pnp_assign_dma(struct pnp_de
 
 __add:
 	pnp_add_dma_resource(dev, res->start, res->flags);
+	return 0;
 }
 
 void pnp_init_resources(struct pnp_dev *dev)
@@ -243,25 +244,26 @@ static int pnp_assign_resources(struct p
 		irq = dev->independent->irq;
 		dma = dev->independent->dma;
 		while (port) {
-			if (!pnp_assign_port(dev, port, nport))
+			if (pnp_assign_port(dev, port, nport) < 0)
 				goto fail;
 			nport++;
 			port = port->next;
 		}
 		while (mem) {
-			if (!pnp_assign_mem(dev, mem, nmem))
+			if (pnp_assign_mem(dev, mem, nmem) < 0)
 				goto fail;
 			nmem++;
 			mem = mem->next;
 		}
 		while (irq) {
-			if (!pnp_assign_irq(dev, irq, nirq))
+			if (pnp_assign_irq(dev, irq, nirq) < 0)
 				goto fail;
 			nirq++;
 			irq = irq->next;
 		}
 		while (dma) {
-			pnp_assign_dma(dev, dma, ndma);
+			if (pnp_assign_dma(dev, dma, ndma) < 0)
+				goto fail;
 			ndma++;
 			dma = dma->next;
 		}
@@ -281,25 +283,26 @@ static int pnp_assign_resources(struct p
 		irq = dep->irq;
 		dma = dep->dma;
 		while (port) {
-			if (!pnp_assign_port(dev, port, nport))
+			if (pnp_assign_port(dev, port, nport) < 0)
 				goto fail;
 			nport++;
 			port = port->next;
 		}
 		while (mem) {
-			if (!pnp_assign_mem(dev, mem, nmem))
+			if (pnp_assign_mem(dev, mem, nmem) < 0)
 				goto fail;
 			nmem++;
 			mem = mem->next;
 		}
 		while (irq) {
-			if (!pnp_assign_irq(dev, irq, nirq))
+			if (pnp_assign_irq(dev, irq, nirq) < 0)
 				goto fail;
 			nirq++;
 			irq = irq->next;
 		}
 		while (dma) {
-			pnp_assign_dma(dev, dma, ndma);
+			if (pnp_assign_dma(dev, dma, ndma) < 0)
+				goto fail;
 			ndma++;
 			dma = dma->next;
 		}

-- 

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

* [patch 19/28] PNP: remove redundant pnp_can_configure() check
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (17 preceding siblings ...)
  2008-06-17 22:58 ` [patch 18/28] PNP: make resource assignment functions return 0 (success) or -EBUSY (failure) Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 20/28] PNP: centralize resource option allocations Bjorn Helgaas
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-remove-assign-configurability-check --]
[-- Type: text/plain, Size: 788 bytes --]

pnp_assign_resources() is static and the only caller checks
pnp_can_configure() before calling it, so no need to do it
again.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work10/drivers/pnp/manager.c
===================================================================
--- work10.orig/drivers/pnp/manager.c	2008-05-13 13:29:57.000000000 -0600
+++ work10/drivers/pnp/manager.c	2008-05-13 13:30:21.000000000 -0600
@@ -231,9 +231,6 @@ static int pnp_assign_resources(struct p
 	struct pnp_dma *dma;
 	int nport = 0, nmem = 0, nirq = 0, ndma = 0;
 
-	if (!pnp_can_configure(dev))
-		return -ENODEV;
-
 	dbg_pnp_show_resources(dev, "before pnp_assign_resources");
 	mutex_lock(&pnp_res_mutex);
 	pnp_clean_resource_table(dev);

-- 

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

* [patch 20/28] PNP: centralize resource option allocations
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (18 preceding siblings ...)
  2008-06-17 22:58 ` [patch 19/28] PNP: remove redundant pnp_can_configure() check Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 21/28] PNPACPI: ignore _PRS interrupt numbers larger than PNP_IRQ_NR Bjorn Helgaas
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-centralize-option-allocs --]
[-- Type: text/plain, Size: 23086 bytes --]

This patch moves all the option allocations (pnp_mem, pnp_port, etc)
into the pnp_register_{mem,port,irq,dma}_resource() functions.  This
will make it easier to rework the option data structures.

The non-trivial part of this patch is the IRQ handling.  The backends
have to allocate a local pnp_irq_mask_t bitmap, populate it, and pass
a pointer to pnp_register_irq_resource().

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

---
 drivers/pnp/base.h             |   12 ++-
 drivers/pnp/isapnp/core.c      |  115 +++++++++++++------------------
 drivers/pnp/pnpacpi/rsparser.c |  149 +++++++++++++----------------------------
 drivers/pnp/pnpbios/rsparser.c |  112 ++++++++++++------------------
 drivers/pnp/resource.c         |   58 +++++++++++++--
 5 files changed, 200 insertions(+), 246 deletions(-)

Index: work14/drivers/pnp/base.h
===================================================================
--- work14.orig/drivers/pnp/base.h	2008-06-17 15:52:22.000000000 -0600
+++ work14/drivers/pnp/base.h	2008-06-17 15:52:27.000000000 -0600
@@ -74,13 +74,17 @@ struct pnp_option *pnp_register_independ
 struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
 						 int priority);
 int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
-			      struct pnp_irq *data);
+			      pnp_irq_mask_t *map, unsigned char flags);
 int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
-			      struct pnp_dma *data);
+			      unsigned char map, unsigned char flags);
 int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
-			       struct pnp_port *data);
+			       resource_size_t min, resource_size_t max,
+			       resource_size_t align, resource_size_t size,
+			       unsigned char flags);
 int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
-			      struct pnp_mem *data);
+			      resource_size_t min, resource_size_t max,
+			      resource_size_t align, resource_size_t size,
+			      unsigned char flags);
 void pnp_init_resources(struct pnp_dev *dev);
 
 void pnp_fixup_device(struct pnp_dev *dev);
Index: work14/drivers/pnp/isapnp/core.c
===================================================================
--- work14.orig/drivers/pnp/isapnp/core.c	2008-06-17 15:52:20.000000000 -0600
+++ work14/drivers/pnp/isapnp/core.c	2008-06-17 15:52:27.000000000 -0600
@@ -433,20 +433,20 @@ static void __init isapnp_parse_irq_reso
 					     int size)
 {
 	unsigned char tmp[3];
-	struct pnp_irq *irq;
 	unsigned long bits;
+	pnp_irq_mask_t map;
+	unsigned char flags = IORESOURCE_IRQ_HIGHEDGE;
 
 	isapnp_peek(tmp, size);
-	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
-	if (!irq)
-		return;
 	bits = (tmp[1] << 8) | tmp[0];
-	bitmap_copy(irq->map.bits, &bits, 16);
+
+	bitmap_zero(map.bits, PNP_IRQ_NR);
+	bitmap_copy(map.bits, &bits, 16);
+
 	if (size > 2)
-		irq->flags = tmp[2];
-	else
-		irq->flags = IORESOURCE_IRQ_HIGHEDGE;
-	pnp_register_irq_resource(dev, option, irq);
+		flags = tmp[2];
+
+	pnp_register_irq_resource(dev, option, &map, flags);
 }
 
 /*
@@ -457,15 +457,9 @@ static void __init isapnp_parse_dma_reso
 					     int size)
 {
 	unsigned char tmp[2];
-	struct pnp_dma *dma;
 
 	isapnp_peek(tmp, size);
-	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
-	if (!dma)
-		return;
-	dma->map = tmp[0];
-	dma->flags = tmp[1];
-	pnp_register_dma_resource(dev, option, dma);
+	pnp_register_dma_resource(dev, option, tmp[0], tmp[1]);
 }
 
 /*
@@ -476,18 +470,16 @@ static void __init isapnp_parse_port_res
 					      int size)
 {
 	unsigned char tmp[7];
-	struct pnp_port *port;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
 	isapnp_peek(tmp, size);
-	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-	if (!port)
-		return;
-	port->min = (tmp[2] << 8) | tmp[1];
-	port->max = (tmp[4] << 8) | tmp[3];
-	port->align = tmp[5];
-	port->size = tmp[6];
-	port->flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0;
-	pnp_register_port_resource(dev, option, port);
+	min = (tmp[2] << 8) | tmp[1];
+	max = (tmp[4] << 8) | tmp[3];
+	align = tmp[5];
+	len = tmp[6];
+	flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0;
+	pnp_register_port_resource(dev, option, min, max, align, len, flags);
 }
 
 /*
@@ -498,17 +490,13 @@ static void __init isapnp_parse_fixed_po
 						    int size)
 {
 	unsigned char tmp[3];
-	struct pnp_port *port;
+	resource_size_t base, len;
 
 	isapnp_peek(tmp, size);
-	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-	if (!port)
-		return;
-	port->min = port->max = (tmp[1] << 8) | tmp[0];
-	port->size = tmp[2];
-	port->align = 0;
-	port->flags = IORESOURCE_IO_FIXED;
-	pnp_register_port_resource(dev, option, port);
+	base = (tmp[1] << 8) | tmp[0];
+	len = tmp[2];
+	pnp_register_port_resource(dev, option, base, base, 0, len,
+				   IORESOURCE_IO_FIXED);
 }
 
 /*
@@ -519,18 +507,16 @@ static void __init isapnp_parse_mem_reso
 					     int size)
 {
 	unsigned char tmp[9];
-	struct pnp_mem *mem;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
 	isapnp_peek(tmp, size);
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
-	mem->max = ((tmp[4] << 8) | tmp[3]) << 8;
-	mem->align = (tmp[6] << 8) | tmp[5];
-	mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
-	mem->flags = tmp[0];
-	pnp_register_mem_resource(dev, option, mem);
+	min = ((tmp[2] << 8) | tmp[1]) << 8;
+	max = ((tmp[4] << 8) | tmp[3]) << 8;
+	align = (tmp[6] << 8) | tmp[5];
+	len = ((tmp[8] << 8) | tmp[7]) << 8;
+	flags = tmp[0];
+	pnp_register_mem_resource(dev, option, min, max, align, len, flags);
 }
 
 /*
@@ -541,20 +527,16 @@ static void __init isapnp_parse_mem32_re
 					       int size)
 {
 	unsigned char tmp[17];
-	struct pnp_mem *mem;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
 	isapnp_peek(tmp, size);
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
-	mem->max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
-	mem->align =
-	    (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
-	mem->size =
-	    (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
-	mem->flags = tmp[0];
-	pnp_register_mem_resource(dev, option, mem);
+	min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
+	max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
+	align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
+	len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
+	flags = tmp[0];
+	pnp_register_mem_resource(dev, option, min, max, align, len, flags);
 }
 
 /*
@@ -565,18 +547,14 @@ static void __init isapnp_parse_fixed_me
 						     int size)
 {
 	unsigned char tmp[9];
-	struct pnp_mem *mem;
+	resource_size_t base, len;
+	unsigned char flags;
 
 	isapnp_peek(tmp, size);
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = mem->max =
-	    (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
-	mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
-	mem->align = 0;
-	mem->flags = tmp[0];
-	pnp_register_mem_resource(dev, option, mem);
+	base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
+	len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
+	flags = tmp[0];
+	pnp_register_mem_resource(dev, option, base, base, 0, len, flags);
 }
 
 /*
Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:20.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:27.000000000 -0600
@@ -411,20 +411,16 @@ static __init void pnpacpi_parse_dma_opt
 					    struct acpi_resource_dma *p)
 {
 	int i;
-	struct pnp_dma *dma;
+	unsigned char map = 0, flags;
 
 	if (p->channel_count == 0)
 		return;
-	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
-	if (!dma)
-		return;
 
 	for (i = 0; i < p->channel_count; i++)
-		dma->map |= 1 << p->channels[i];
-
-	dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
+		map |= 1 << p->channels[i];
 
-	pnp_register_dma_resource(dev, option, dma);
+	flags = dma_flags(p->type, p->bus_master, p->transfer);
+	pnp_register_dma_resource(dev, option, map, flags);
 }
 
 static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
@@ -432,20 +428,19 @@ static __init void pnpacpi_parse_irq_opt
 					    struct acpi_resource_irq *p)
 {
 	int i;
-	struct pnp_irq *irq;
+	pnp_irq_mask_t map;
+	unsigned char flags;
 
 	if (p->interrupt_count == 0)
 		return;
-	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
-	if (!irq)
-		return;
 
+	bitmap_zero(map.bits, PNP_IRQ_NR);
 	for (i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
-			__set_bit(p->interrupts[i], irq->map.bits);
-	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
+			__set_bit(p->interrupts[i], map.bits);
 
-	pnp_register_irq_resource(dev, option, irq);
+	flags = irq_flags(p->triggering, p->polarity, p->sharable);
+	pnp_register_irq_resource(dev, option, &map, flags);
 }
 
 static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
@@ -453,123 +448,90 @@ static __init void pnpacpi_parse_ext_irq
 					struct acpi_resource_extended_irq *p)
 {
 	int i;
-	struct pnp_irq *irq;
+	pnp_irq_mask_t map;
+	unsigned char flags;
 
 	if (p->interrupt_count == 0)
 		return;
-	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
-	if (!irq)
-		return;
 
+	bitmap_zero(map.bits, PNP_IRQ_NR);
 	for (i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
-			__set_bit(p->interrupts[i], irq->map.bits);
-	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
+			__set_bit(p->interrupts[i], map.bits);
 
-	pnp_register_irq_resource(dev, option, irq);
+	flags = irq_flags(p->triggering, p->polarity, p->sharable);
+	pnp_register_irq_resource(dev, option, &map, flags);
 }
 
 static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
 					     struct pnp_option *option,
 					     struct acpi_resource_io *io)
 {
-	struct pnp_port *port;
+	unsigned char flags = 0;
 
 	if (io->address_length == 0)
 		return;
-	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-	if (!port)
-		return;
-	port->min = io->minimum;
-	port->max = io->maximum;
-	port->align = io->alignment;
-	port->size = io->address_length;
-	port->flags = ACPI_DECODE_16 == io->io_decode ?
-	    IORESOURCE_IO_16BIT_ADDR : 0;
-	pnp_register_port_resource(dev, option, port);
+
+	if (io->io_decode == ACPI_DECODE_16)
+		flags = IORESOURCE_IO_16BIT_ADDR;
+	pnp_register_port_resource(dev, option, io->minimum, io->maximum,
+				   io->alignment, io->address_length, flags);
 }
 
 static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
 						   struct pnp_option *option,
 					struct acpi_resource_fixed_io *io)
 {
-	struct pnp_port *port;
-
 	if (io->address_length == 0)
 		return;
-	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-	if (!port)
-		return;
-	port->min = port->max = io->address;
-	port->size = io->address_length;
-	port->align = 0;
-	port->flags = IORESOURCE_IO_FIXED;
-	pnp_register_port_resource(dev, option, port);
+
+	pnp_register_port_resource(dev, option, io->address, io->address, 0,
+				   io->address_length, IORESOURCE_IO_FIXED);
 }
 
 static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
 					      struct pnp_option *option,
 					      struct acpi_resource_memory24 *p)
 {
-	struct pnp_mem *mem;
+	unsigned char flags = 0;
 
 	if (p->address_length == 0)
 		return;
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = p->minimum;
-	mem->max = p->maximum;
-	mem->align = p->alignment;
-	mem->size = p->address_length;
 
-	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
-	    IORESOURCE_MEM_WRITEABLE : 0;
-
-	pnp_register_mem_resource(dev, option, mem);
+	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
+		flags = IORESOURCE_MEM_WRITEABLE;
+	pnp_register_mem_resource(dev, option, p->minimum, p->maximum,
+				  p->alignment, p->address_length, flags);
 }
 
 static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
 					      struct pnp_option *option,
 					      struct acpi_resource_memory32 *p)
 {
-	struct pnp_mem *mem;
+	unsigned char flags = 0;
 
 	if (p->address_length == 0)
 		return;
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = p->minimum;
-	mem->max = p->maximum;
-	mem->align = p->alignment;
-	mem->size = p->address_length;
 
-	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
-	    IORESOURCE_MEM_WRITEABLE : 0;
-
-	pnp_register_mem_resource(dev, option, mem);
+	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
+		flags = IORESOURCE_MEM_WRITEABLE;
+	pnp_register_mem_resource(dev, option, p->minimum, p->maximum,
+				  p->alignment, p->address_length, flags);
 }
 
 static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
 						    struct pnp_option *option,
 					struct acpi_resource_fixed_memory32 *p)
 {
-	struct pnp_mem *mem;
+	unsigned char flags = 0;
 
 	if (p->address_length == 0)
 		return;
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = mem->max = p->address;
-	mem->size = p->address_length;
-	mem->align = 0;
 
-	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
-	    IORESOURCE_MEM_WRITEABLE : 0;
-
-	pnp_register_mem_resource(dev, option, mem);
+	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
+		flags = IORESOURCE_MEM_WRITEABLE;
+	pnp_register_mem_resource(dev, option, p->address, p->address,
+				  0, p->address_length, flags);
 }
 
 static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
@@ -578,8 +540,7 @@ static __init void pnpacpi_parse_address
 {
 	struct acpi_resource_address64 addr, *p = &addr;
 	acpi_status status;
-	struct pnp_mem *mem;
-	struct pnp_port *port;
+	unsigned char flags = 0;
 
 	status = acpi_resource_to_address64(r, p);
 	if (!ACPI_SUCCESS(status)) {
@@ -592,26 +553,14 @@ static __init void pnpacpi_parse_address
 		return;
 
 	if (p->resource_type == ACPI_MEMORY_RANGE) {
-		mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-		if (!mem)
-			return;
-		mem->min = mem->max = p->minimum;
-		mem->size = p->address_length;
-		mem->align = 0;
-		mem->flags = (p->info.mem.write_protect ==
-			      ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
-		    : 0;
-		pnp_register_mem_resource(dev, option, mem);
-	} else if (p->resource_type == ACPI_IO_RANGE) {
-		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-		if (!port)
-			return;
-		port->min = port->max = p->minimum;
-		port->size = p->address_length;
-		port->align = 0;
-		port->flags = IORESOURCE_IO_FIXED;
-		pnp_register_port_resource(dev, option, port);
-	}
+		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
+			flags = IORESOURCE_MEM_WRITEABLE;
+		pnp_register_mem_resource(dev, option, p->minimum, p->minimum,
+					  0, p->address_length, flags);
+	} else if (p->resource_type == ACPI_IO_RANGE)
+		pnp_register_port_resource(dev, option, p->minimum, p->minimum,
+					   0, p->address_length,
+					   IORESOURCE_IO_FIXED);
 }
 
 struct acpipnp_parse_option_s {
Index: work14/drivers/pnp/pnpbios/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:20.000000000 -0600
+++ work14/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:27.000000000 -0600
@@ -218,116 +218,96 @@ static __init void pnpbios_parse_mem_opt
 					    unsigned char *p, int size,
 					    struct pnp_option *option)
 {
-	struct pnp_mem *mem;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = ((p[5] << 8) | p[4]) << 8;
-	mem->max = ((p[7] << 8) | p[6]) << 8;
-	mem->align = (p[9] << 8) | p[8];
-	mem->size = ((p[11] << 8) | p[10]) << 8;
-	mem->flags = p[3];
-	pnp_register_mem_resource(dev, option, mem);
+	min = ((p[5] << 8) | p[4]) << 8;
+	max = ((p[7] << 8) | p[6]) << 8;
+	align = (p[9] << 8) | p[8];
+	len = ((p[11] << 8) | p[10]) << 8;
+	flags = p[3];
+	pnp_register_mem_resource(dev, option, min, max, align, len, flags);
 }
 
 static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
 					      unsigned char *p, int size,
 					      struct pnp_option *option)
 {
-	struct pnp_mem *mem;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
-	mem->max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
-	mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
-	mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
-	mem->flags = p[3];
-	pnp_register_mem_resource(dev, option, mem);
+	min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
+	max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
+	align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
+	len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
+	flags = p[3];
+	pnp_register_mem_resource(dev, option, min, max, align, len, flags);
 }
 
 static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
 						    unsigned char *p, int size,
 						    struct pnp_option *option)
 {
-	struct pnp_mem *mem;
+	resource_size_t base, len;
+	unsigned char flags;
 
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
-		return;
-	mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
-	mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
-	mem->align = 0;
-	mem->flags = p[3];
-	pnp_register_mem_resource(dev, option, mem);
+	base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
+	len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
+	flags = p[3];
+	pnp_register_mem_resource(dev, option, base, base, 0, len, flags);
 }
 
 static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
 					    unsigned char *p, int size,
 					    struct pnp_option *option)
 {
-	struct pnp_irq *irq;
 	unsigned long bits;
+	pnp_irq_mask_t map;
+	unsigned char flags = IORESOURCE_IRQ_HIGHEDGE;
 
-	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
-	if (!irq)
-		return;
 	bits = (p[2] << 8) | p[1];
-	bitmap_copy(irq->map.bits, &bits, 16);
+
+	bitmap_zero(map.bits, PNP_IRQ_NR);
+	bitmap_copy(map.bits, &bits, 16);
+
 	if (size > 2)
-		irq->flags = p[3];
-	else
-		irq->flags = IORESOURCE_IRQ_HIGHEDGE;
-	pnp_register_irq_resource(dev, option, irq);
+		flags = p[3];
+
+	pnp_register_irq_resource(dev, option, &map, flags);
 }
 
 static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
 					    unsigned char *p, int size,
 					    struct pnp_option *option)
 {
-	struct pnp_dma *dma;
-
-	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
-	if (!dma)
-		return;
-	dma->map = p[1];
-	dma->flags = p[2];
-	pnp_register_dma_resource(dev, option, dma);
+	pnp_register_dma_resource(dev, option, p[1], p[2]);
 }
 
 static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
 					     unsigned char *p, int size,
 					     struct pnp_option *option)
 {
-	struct pnp_port *port;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
-	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-	if (!port)
-		return;
-	port->min = (p[3] << 8) | p[2];
-	port->max = (p[5] << 8) | p[4];
-	port->align = p[6];
-	port->size = p[7];
-	port->flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0;
-	pnp_register_port_resource(dev, option, port);
+	min = (p[3] << 8) | p[2];
+	max = (p[5] << 8) | p[4];
+	align = p[6];
+	len = p[7];
+	flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0;
+	pnp_register_port_resource(dev, option, min, max, align, len, flags);
 }
 
 static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
 						   unsigned char *p, int size,
 						   struct pnp_option *option)
 {
-	struct pnp_port *port;
+	resource_size_t base, len;
 
-	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-	if (!port)
-		return;
-	port->min = port->max = (p[2] << 8) | p[1];
-	port->size = p[3];
-	port->align = 0;
-	port->flags = IORESOURCE_IO_FIXED;
-	pnp_register_port_resource(dev, option, port);
+	base = (p[2] << 8) | p[1];
+	len = p[3];
+	pnp_register_port_resource(dev, option, base, base, 0, len,
+				   IORESOURCE_IO_FIXED);
 }
 
 static __init unsigned char *
Index: work14/drivers/pnp/resource.c
===================================================================
--- work14.orig/drivers/pnp/resource.c	2008-06-17 15:52:22.000000000 -0600
+++ work14/drivers/pnp/resource.c	2008-06-17 15:52:27.000000000 -0600
@@ -78,13 +78,20 @@ struct pnp_option *pnp_register_dependen
 }
 
 int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
-			      struct pnp_irq *data)
+			      pnp_irq_mask_t *map, unsigned char flags)
 {
-	struct pnp_irq *ptr;
+	struct pnp_irq *data, *ptr;
 #ifdef DEBUG
 	char buf[PNP_IRQ_NR];   /* hex-encoded, so this is overkill but safe */
 #endif
 
+	data = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->map = *map;
+	data->flags = flags;
+
 	ptr = option->irq;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
@@ -112,9 +119,16 @@ int pnp_register_irq_resource(struct pnp
 }
 
 int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
-			      struct pnp_dma *data)
+			      unsigned char map, unsigned char flags)
 {
-	struct pnp_dma *ptr;
+	struct pnp_dma *data, *ptr;
+
+	data = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->map = map;
+	data->flags = flags;
 
 	ptr = option->dma;
 	while (ptr && ptr->next)
@@ -130,9 +144,21 @@ int pnp_register_dma_resource(struct pnp
 }
 
 int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
-			       struct pnp_port *data)
-{
-	struct pnp_port *ptr;
+			       resource_size_t min, resource_size_t max,
+			       resource_size_t align, resource_size_t size,
+			       unsigned char flags)
+{
+	struct pnp_port *data, *ptr;
+
+	data = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->min = min;
+	data->max = max;
+	data->align = align;
+	data->size = size;
+	data->flags = flags;
 
 	ptr = option->port;
 	while (ptr && ptr->next)
@@ -152,9 +178,21 @@ int pnp_register_port_resource(struct pn
 }
 
 int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
-			      struct pnp_mem *data)
-{
-	struct pnp_mem *ptr;
+			      resource_size_t min, resource_size_t max,
+			      resource_size_t align, resource_size_t size,
+			      unsigned char flags)
+{
+	struct pnp_mem *data, *ptr;
+
+	data = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->min = min;
+	data->max = max;
+	data->align = align;
+	data->size = size;
+	data->flags = flags;
 
 	ptr = option->mem;
 	while (ptr && ptr->next)

-- 

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

* [patch 21/28] PNPACPI: ignore _PRS interrupt numbers larger than PNP_IRQ_NR
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (19 preceding siblings ...)
  2008-06-17 22:58 ` [patch 20/28] PNP: centralize resource option allocations Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 22/28] PNP: rename pnp_register_*_resource() local variables Bjorn Helgaas
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnpacpi-extended-irq-option --]
[-- Type: text/plain, Size: 1556 bytes --]

ACPI Extended Interrupt Descriptors can encode 32-bit interrupt
numbers, so an interrupt number may exceed the size of the bitmap
we use to track possible IRQ settings.

To avoid corrupting memory, complain and ignore too-large interrupt
numbers.

There's similar code in pnpacpi_parse_irq_option(), but I didn't
change that because the small IRQ descriptor can only encode
IRQs 0-15, which do not exceed bitmap size.

In the future, we could handle IRQ numbers greater than PNP_IRQ_NR
by replacing the bitmap with a table or list.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:27.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:29.000000000 -0600
@@ -435,9 +435,16 @@ static __init void pnpacpi_parse_irq_opt
 		return;
 
 	bitmap_zero(map.bits, PNP_IRQ_NR);
-	for (i = 0; i < p->interrupt_count; i++)
-		if (p->interrupts[i])
-			__set_bit(p->interrupts[i], map.bits);
+	for (i = 0; i < p->interrupt_count; i++) {
+		if (p->interrupts[i]) {
+			if (p->interrupts[i] < PNP_IRQ_NR)
+				__set_bit(p->interrupts[i], map.bits);
+			else
+				dev_err(&dev->dev, "ignoring IRQ %d option "
+					"(too large for %d entry bitmap)\n",
+					p->interrupts[i], PNP_IRQ_NR);
+		}
+	}
 
 	flags = irq_flags(p->triggering, p->polarity, p->sharable);
 	pnp_register_irq_resource(dev, option, &map, flags);

-- 

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

* [patch 22/28] PNP: rename pnp_register_*_resource() local variables
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (20 preceding siblings ...)
  2008-06-17 22:58 ` [patch 21/28] PNPACPI: ignore _PRS interrupt numbers larger than PNP_IRQ_NR Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 23/28] PNP: support optional IRQ resources Bjorn Helgaas
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-register-renames --]
[-- Type: text/plain, Size: 4832 bytes --]

No functional change; just rename "data" to something more
descriptive.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work10/drivers/pnp/resource.c
===================================================================
--- work10.orig/drivers/pnp/resource.c	2008-05-20 13:23:06.000000000 -0600
+++ work10/drivers/pnp/resource.c	2008-05-20 13:24:27.000000000 -0600
@@ -80,40 +80,40 @@ struct pnp_option *pnp_register_dependen
 int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
 			      pnp_irq_mask_t *map, unsigned char flags)
 {
-	struct pnp_irq *data, *ptr;
+	struct pnp_irq *irq, *ptr;
 #ifdef DEBUG
 	char buf[PNP_IRQ_NR];   /* hex-encoded, so this is overkill but safe */
 #endif
 
-	data = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
-	if (!data)
+	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+	if (!irq)
 		return -ENOMEM;
 
-	data->map = *map;
-	data->flags = flags;
+	irq->map = *map;
+	irq->flags = flags;
 
 	ptr = option->irq;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
 	if (ptr)
-		ptr->next = data;
+		ptr->next = irq;
 	else
-		option->irq = data;
+		option->irq = irq;
 
 #ifdef CONFIG_PCI
 	{
 		int i;
 
 		for (i = 0; i < 16; i++)
-			if (test_bit(i, data->map.bits))
+			if (test_bit(i, irq->map.bits))
 				pcibios_penalize_isa_irq(i, 0);
 	}
 #endif
 
 #ifdef DEBUG
-	bitmap_scnprintf(buf, sizeof(buf), data->map.bits, PNP_IRQ_NR);
+	bitmap_scnprintf(buf, sizeof(buf), irq->map.bits, PNP_IRQ_NR);
 	dev_dbg(&dev->dev, "  irq bitmask %s flags %#x\n", buf,
-		data->flags);
+		irq->flags);
 #endif
 	return 0;
 }
@@ -121,25 +121,25 @@ int pnp_register_irq_resource(struct pnp
 int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
 			      unsigned char map, unsigned char flags)
 {
-	struct pnp_dma *data, *ptr;
+	struct pnp_dma *dma, *ptr;
 
-	data = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
-	if (!data)
+	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+	if (!dma)
 		return -ENOMEM;
 
-	data->map = map;
-	data->flags = flags;
+	dma->map = map;
+	dma->flags = flags;
 
 	ptr = option->dma;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
 	if (ptr)
-		ptr->next = data;
+		ptr->next = dma;
 	else
-		option->dma = data;
+		option->dma = dma;
 
-	dev_dbg(&dev->dev, "  dma bitmask %#x flags %#x\n", data->map,
-		data->flags);
+	dev_dbg(&dev->dev, "  dma bitmask %#x flags %#x\n", dma->map,
+		dma->flags);
 	return 0;
 }
 
@@ -148,32 +148,32 @@ int pnp_register_port_resource(struct pn
 			       resource_size_t align, resource_size_t size,
 			       unsigned char flags)
 {
-	struct pnp_port *data, *ptr;
+	struct pnp_port *port, *ptr;
 
-	data = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-	if (!data)
+	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
+	if (!port)
 		return -ENOMEM;
 
-	data->min = min;
-	data->max = max;
-	data->align = align;
-	data->size = size;
-	data->flags = flags;
+	port->min = min;
+	port->max = max;
+	port->align = align;
+	port->size = size;
+	port->flags = flags;
 
 	ptr = option->port;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
 	if (ptr)
-		ptr->next = data;
+		ptr->next = port;
 	else
-		option->port = data;
+		option->port = port;
 
 	dev_dbg(&dev->dev, "  io  "
 		"min %#llx max %#llx align %lld size %lld flags %#x\n",
-		(unsigned long long) data->min,
-		(unsigned long long) data->max,
-		(unsigned long long) data->align,
-		(unsigned long long) data->size, data->flags);
+		(unsigned long long) port->min,
+		(unsigned long long) port->max,
+		(unsigned long long) port->align,
+		(unsigned long long) port->size, port->flags);
 	return 0;
 }
 
@@ -182,32 +182,32 @@ int pnp_register_mem_resource(struct pnp
 			      resource_size_t align, resource_size_t size,
 			      unsigned char flags)
 {
-	struct pnp_mem *data, *ptr;
+	struct pnp_mem *mem, *ptr;
 
-	data = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!data)
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+	if (!mem)
 		return -ENOMEM;
 
-	data->min = min;
-	data->max = max;
-	data->align = align;
-	data->size = size;
-	data->flags = flags;
+	mem->min = min;
+	mem->max = max;
+	mem->align = align;
+	mem->size = size;
+	mem->flags = flags;
 
 	ptr = option->mem;
 	while (ptr && ptr->next)
 		ptr = ptr->next;
 	if (ptr)
-		ptr->next = data;
+		ptr->next = mem;
 	else
-		option->mem = data;
+		option->mem = mem;
 
 	dev_dbg(&dev->dev, "  mem "
 		"min %#llx max %#llx align %lld size %lld flags %#x\n",
-		(unsigned long long) data->min,
-		(unsigned long long) data->max,
-		(unsigned long long) data->align,
-		(unsigned long long) data->size, data->flags);
+		(unsigned long long) mem->min,
+		(unsigned long long) mem->max,
+		(unsigned long long) mem->align,
+		(unsigned long long) mem->size, mem->flags);
 	return 0;
 }
 

-- 

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

* [patch 23/28] PNP: support optional IRQ resources
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (21 preceding siblings ...)
  2008-06-17 22:58 ` [patch 22/28] PNP: rename pnp_register_*_resource() local variables Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 24/28] PNP: remove extra 0x100 bit from option priority Bjorn Helgaas
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-optional-irqs --]
[-- Type: text/plain, Size: 5873 bytes --]

This patch adds an IORESOURCE_IRQ_OPTIONAL flag for use when
assigning resources to a device.  If the flag is set and we are
unable to assign an IRQ to the device, we can leave the IRQ
disabled but allow the overall resource allocation to succeed.

Some devices request an IRQ, but can run without an IRQ
(possibly with degraded performance).  This flag lets us run
the device without the IRQ instead of just leaving the
device disabled.

This is a reimplementation of this previous change by Rene
Herman <rene.herman@gmail.com>:
    http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b73a223661ed137c5d3d2635f954382e94f5a43

I reimplemented this for two reasons:
    - to prepare for converting all resource options into a single linked
      list, as opposed to the per-resource-type lists we have now, and
    - to preserve the order and number of resource options.

In PNPBIOS and ACPI, we configure a device by giving firmware a
list of resource assignments.  It is important that this list
has exactly the same number of resources, in the same order,
as the "template" list we got from the firmware in the first
place.

The problem of a sound card MPU401 being left disabled for want of
an IRQ was reported by Uwe Bugla <uwe.bugla@gmx.de>.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work10/include/linux/ioport.h
===================================================================
--- work10.orig/include/linux/ioport.h	2008-06-17 12:42:07.000000000 -0600
+++ work10/include/linux/ioport.h	2008-06-17 12:42:07.000000000 -0600
@@ -59,6 +59,7 @@ struct resource_list {
 #define IORESOURCE_IRQ_HIGHLEVEL	(1<<2)
 #define IORESOURCE_IRQ_LOWLEVEL		(1<<3)
 #define IORESOURCE_IRQ_SHAREABLE	(1<<4)
+#define IORESOURCE_IRQ_OPTIONAL		(1<<5)
 
 /* PnP DMA specific bits (IORESOURCE_BITS) */
 #define IORESOURCE_DMA_TYPE_MASK	(3<<0)
Index: work10/drivers/pnp/manager.c
===================================================================
--- work10.orig/drivers/pnp/manager.c	2008-06-17 12:42:07.000000000 -0600
+++ work10/drivers/pnp/manager.c	2008-06-17 12:43:03.000000000 -0600
@@ -153,6 +153,15 @@ static int pnp_assign_irq(struct pnp_dev
 				goto __add;
 		}
 	}
+
+	if (rule->flags & IORESOURCE_IRQ_OPTIONAL) {
+		res->start = -1;
+		res->end = -1;
+		res->flags |= IORESOURCE_DISABLED;
+		dev_dbg(&dev->dev, "  irq %d disabled (optional)\n", idx);
+		goto __add;
+	}
+
 	dev_dbg(&dev->dev, "  couldn't assign irq %d\n", idx);
 	return -EBUSY;
 
Index: work10/drivers/pnp/quirks.c
===================================================================
--- work10.orig/drivers/pnp/quirks.c	2008-06-17 12:42:07.000000000 -0600
+++ work10/drivers/pnp/quirks.c	2008-06-17 12:44:48.000000000 -0600
@@ -118,34 +118,46 @@ static struct pnp_option *quirk_isapnp_m
 	struct pnp_option *res;
 
 	/*
-	 * Build a functional IRQ-less variant of each MPU option.
+	 * Build a functional IRQ-optional variant of each MPU option.
 	 */
 
 	for (res = dev->dependent; res; res = res->next) {
 		struct pnp_option *curr;
 		struct pnp_port *port;
-		struct pnp_port *copy;
+		struct pnp_port *copy_port;
+		struct pnp_irq *irq;
+		struct pnp_irq *copy_irq;
 
 		port = res->port;
-		if (!port || !res->irq)
+		irq = res->irq;
+		if (!port || !irq)
 			continue;
 
-		copy = pnp_alloc(sizeof *copy);
-		if (!copy)
+		copy_port = pnp_alloc(sizeof *copy_port);
+		if (!copy_port)
 			break;
 
-		copy->min = port->min;
-		copy->max = port->max;
-		copy->align = port->align;
-		copy->size = port->size;
-		copy->flags = port->flags;
+		copy_irq = pnp_alloc(sizeof *copy_irq);
+		if (!copy_irq) {
+			kfree(copy_port);
+			break;
+		}
+
+		*copy_port = *port;
+		copy_port->next = NULL;
+
+		*copy_irq = *irq;
+		copy_irq->flags |= IORESOURCE_IRQ_OPTIONAL;
+		copy_irq->next = NULL;
 
 		curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL);
 		if (!curr) {
-			kfree(copy);
+			kfree(copy_port);
+			kfree(copy_irq);
 			break;
 		}
-		curr->port = copy;
+		curr->port = copy_port;
+		curr->irq = copy_irq;
 
 		if (prev)
 			prev->next = curr;
@@ -154,7 +166,7 @@ static struct pnp_option *quirk_isapnp_m
 		prev = curr;
 	}
 	if (head)
-		dev_info(&dev->dev, "adding IRQ-less MPU options\n");
+		dev_info(&dev->dev, "adding IRQ-optional MPU options\n");
 
 	return head;
 }
@@ -164,10 +176,6 @@ static void quirk_ad1815_mpu_resources(s
 	struct pnp_option *res;
 	struct pnp_irq *irq;
 
-	/*
-	 * Distribute the independent IRQ over the dependent options
-	 */
-
 	res = dev->independent;
 	if (!res)
 		return;
@@ -176,33 +184,8 @@ static void quirk_ad1815_mpu_resources(s
 	if (!irq || irq->next)
 		return;
 
-	res = dev->dependent;
-	if (!res)
-		return;
-
-	while (1) {
-		struct pnp_irq *copy;
-
-		copy = pnp_alloc(sizeof *copy);
-		if (!copy)
-			break;
-
-		bitmap_copy(copy->map.bits, irq->map.bits, PNP_IRQ_NR);
-		copy->flags = irq->flags;
-
-		copy->next = res->irq; /* Yes, this is NULL */
-		res->irq = copy;
-
-		if (!res->next)
-			break;
-		res = res->next;
-	}
-	kfree(irq);
-
-	res->next = quirk_isapnp_mpu_options(dev);
-
-	res = dev->independent;
-	res->irq = NULL;
+	irq->flags |= IORESOURCE_IRQ_OPTIONAL;
+	dev_info(&dev->dev, "made independent IRQ optional\n");
 }
 
 static void quirk_isapnp_mpu_resources(struct pnp_dev *dev)
Index: work10/drivers/pnp/interface.c
===================================================================
--- work10.orig/drivers/pnp/interface.c	2008-06-17 12:42:07.000000000 -0600
+++ work10/drivers/pnp/interface.c	2008-06-17 12:43:03.000000000 -0600
@@ -90,6 +90,8 @@ static void pnp_print_irq(pnp_info_buffe
 		pnp_printf(buffer, " High-Level");
 	if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
 		pnp_printf(buffer, " Low-Level");
+	if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
+		pnp_printf(buffer, " (optional)");
 	pnp_printf(buffer, "\n");
 }
 

-- 

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

* [patch 24/28] PNP: remove extra 0x100 bit from option priority
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (22 preceding siblings ...)
  2008-06-17 22:58 ` [patch 23/28] PNP: support optional IRQ resources Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 25/28] ISAPNP: handle independent options following dependent ones Bjorn Helgaas
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-remove-extra-priority-bits --]
[-- Type: text/plain, Size: 3277 bytes --]

When building resource options, ISAPNP and PNPBIOS set the priority
to something like "0x100 | PNP_RES_PRIORITY_ACCEPTABLE", but we 
immediately mask off the 0x100 again in pnp_build_option(), so that
bit looks superfluous.

Thanks to Rene Herman <rene.herman@gmail.com> for pointing this out.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work14/drivers/pnp/isapnp/core.c
===================================================================
--- work14.orig/drivers/pnp/isapnp/core.c	2008-06-17 15:52:27.000000000 -0600
+++ work14/drivers/pnp/isapnp/core.c	2008-06-17 15:52:33.000000000 -0600
@@ -582,7 +582,7 @@ isapnp_parse_name(char *name, unsigned i
 static int __init isapnp_create_device(struct pnp_card *card,
 				       unsigned short size)
 {
-	int number = 0, skip = 0, priority = 0, compat = 0;
+	int number = 0, skip = 0, priority, compat = 0;
 	unsigned char type, tmp[17];
 	struct pnp_option *option;
 	struct pnp_dev *dev;
@@ -621,7 +621,6 @@ static int __init isapnp_create_device(s
 			} else {
 				skip = 1;
 			}
-			priority = 0;
 			compat = 0;
 			break;
 		case _STAG_COMPATDEVID:
@@ -650,10 +649,10 @@ static int __init isapnp_create_device(s
 		case _STAG_STARTDEP:
 			if (size > 1)
 				goto __skip;
-			priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
+			priority = PNP_RES_PRIORITY_ACCEPTABLE;
 			if (size > 0) {
 				isapnp_peek(tmp, size);
-				priority = 0x100 | tmp[0];
+				priority = tmp[0];
 				size = 0;
 			}
 			option = pnp_register_dependent_option(dev, priority);
@@ -663,7 +662,6 @@ static int __init isapnp_create_device(s
 		case _STAG_ENDDEP:
 			if (size != 0)
 				goto __skip;
-			priority = 0;
 			dev_dbg(&dev->dev, "end dependent options\n");
 			break;
 		case _STAG_IOPORT:
Index: work14/drivers/pnp/pnpbios/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:27.000000000 -0600
+++ work14/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:33.000000000 -0600
@@ -315,7 +315,7 @@ pnpbios_parse_resource_option_data(unsig
 					struct pnp_dev *dev)
 {
 	unsigned int len, tag;
-	int priority = 0;
+	int priority;
 	struct pnp_option *option, *option_independent;
 
 	if (!p)
@@ -389,9 +389,9 @@ pnpbios_parse_resource_option_data(unsig
 		case SMALL_TAG_STARTDEP:
 			if (len > 1)
 				goto len_err;
-			priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
+			priority = PNP_RES_PRIORITY_ACCEPTABLE;
 			if (len > 0)
-				priority = 0x100 | p[1];
+				priority = p[1];
 			option = pnp_register_dependent_option(dev, priority);
 			if (!option)
 				return NULL;
Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:29.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:33.000000000 -0600
@@ -579,7 +579,7 @@ struct acpipnp_parse_option_s {
 static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 						  void *data)
 {
-	int priority = 0;
+	int priority;
 	struct acpipnp_parse_option_s *parse_data = data;
 	struct pnp_dev *dev = parse_data->dev;
 	struct pnp_option *option = parse_data->option;

-- 

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

* [patch 25/28] ISAPNP: handle independent options following dependent ones
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (23 preceding siblings ...)
  2008-06-17 22:58 ` [patch 24/28] PNP: remove extra 0x100 bit from option priority Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 26/28] PNP: convert resource options to single linked list Bjorn Helgaas
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: isapnp-enddep-bugfix --]
[-- Type: text/plain, Size: 1875 bytes --]

The ISAPNP spec recommends that independent options precede
dependent ones, but this is not actually required.  The current
ISAPNP code incorrectly puts such trailing independent options
at the end of the last dependent option list.

This patch fixes that bug by resetting the current option list
to the independent list when we see an "End Dependent Functions"
tag.  PNPBIOS and PNPACPI handle this the same way.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

Index: work10/drivers/pnp/isapnp/core.c
===================================================================
--- work10.orig/drivers/pnp/isapnp/core.c	2008-06-03 15:45:02.000000000 -0600
+++ work10/drivers/pnp/isapnp/core.c	2008-06-03 15:49:38.000000000 -0600
@@ -584,14 +584,14 @@ static int __init isapnp_create_device(s
 {
 	int number = 0, skip = 0, priority, compat = 0;
 	unsigned char type, tmp[17];
-	struct pnp_option *option;
+	struct pnp_option *option, *option_independent;
 	struct pnp_dev *dev;
 	u32 eisa_id;
 	char id[8];
 
 	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 		return 1;
-	option = pnp_register_independent_option(dev);
+	option_independent = option = pnp_register_independent_option(dev);
 	if (!option) {
 		kfree(dev);
 		return 1;
@@ -613,6 +613,7 @@ static int __init isapnp_create_device(s
 				size = 0;
 				skip = 0;
 				option = pnp_register_independent_option(dev);
+				option_independent = option;
 				if (!option) {
 					kfree(dev);
 					return 1;
@@ -662,6 +663,10 @@ static int __init isapnp_create_device(s
 		case _STAG_ENDDEP:
 			if (size != 0)
 				goto __skip;
+			if (option_independent == option)
+				dev_warn(&dev->dev, "missing "
+					 "_STAG_STARTDEP tag\n");
+			option = option_independent;
 			dev_dbg(&dev->dev, "end dependent options\n");
 			break;
 		case _STAG_IOPORT:

-- 

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

* [patch 26/28] PNP: convert resource options to single linked list
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (24 preceding siblings ...)
  2008-06-17 22:58 ` [patch 25/28] ISAPNP: handle independent options following dependent ones Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-17 22:58 ` [patch 27/28] PNP: avoid legacy IDE IRQs Bjorn Helgaas
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, Rene Herman, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-option-list --]
[-- Type: text/plain, Size: 63407 bytes --]

ISAPNP, PNPBIOS, and ACPI describe the "possible resource settings" of
a device, i.e., the possibilities an OS bus driver has when it assigns
I/O port, MMIO, and other resources to the device.

PNP used to maintain this "possible resource setting" information in
one independent option structure and a list of dependent option
structures for each device.  Each of these option structures had lists
of I/O, memory, IRQ, and DMA resources, for example:

  dev
    independent options
      ind-io0  -> ind-io1  ...
      ind-mem0 -> ind-mem1 ...
      ...
    dependent option set 0
      dep0-io0  -> dep0-io1  ...
      dep0-mem0 -> dep0-mem1 ...
      ...
    dependent option set 1
      dep1-io0  -> dep1-io1  ...
      dep1-mem0 -> dep1-mem1 ...
      ...
    ...

This data structure was designed for ISAPNP, where the OS configures
device resource settings by writing directly to configuration
registers.  The OS can write the registers in arbitrary order much
like it writes PCI BARs.

However, for PNPBIOS and ACPI devices, the OS uses firmware interfaces
that perform device configuration, and it is important to pass the
desired settings to those interfaces in the correct order.  The OS
learns the correct order by using firmware interfaces that return the
"current resource settings" and "possible resource settings," but the
option structures above doesn't store the ordering information.

This patch replaces the independent and dependent lists with a single
list of options.  For example, a device might have possible resource
settings like this:

  dev
    options
      ind-io0 -> dep0-io0 -> dep1->io0 -> ind-io1 ...

All the possible settings are in the same list, in the order they
come from the firmware "possible resource settings" list.  Each entry
is tagged with an independent/dependent flag.  Dependent entries also
have a "set number" and an optional priority value.  All dependent
entries must be assigned from the same set.  For example, the OS can
use all the entries from dependent set 0, or all the entries from
dependent set 1, but it cannot mix entries from set 0 with entries
from set 1.

Prior to this patch PNP didn't keep track of the order of this list,
and it assigned all independent options first, then all dependent
ones.  Using the example above, that resulted in a "desired
configuration" list like this:

  ind->io0 -> ind->io1 -> depN-io0 ...

instead of the list the firmware expects, which looks like this:

  ind->io0 -> depN-io0 -> ind-io1 ...

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Rene Herman <rene.herman@gmail.com>

---
 drivers/pnp/base.h             |   89 +++++++++---
 drivers/pnp/core.c             |    4 
 drivers/pnp/interface.c        |   75 ++++------
 drivers/pnp/isapnp/core.c      |   68 ++++-----
 drivers/pnp/manager.c          |  137 +++++--------------
 drivers/pnp/pnpacpi/rsparser.c |   93 +++++--------
 drivers/pnp/pnpbios/rsparser.c |   64 ++++-----
 drivers/pnp/quirks.c           |  288 ++++++++++++++++++++++-------------------
 drivers/pnp/resource.c         |  205 +++++------------------------
 drivers/pnp/support.c          |   79 +++++++++++
 include/linux/pnp.h            |    6 
 11 files changed, 524 insertions(+), 584 deletions(-)

Index: work14/drivers/pnp/base.h
===================================================================
--- work14.orig/drivers/pnp/base.h	2008-06-17 15:52:27.000000000 -0600
+++ work14/drivers/pnp/base.h	2008-06-17 15:52:36.000000000 -0600
@@ -1,3 +1,8 @@
+/*
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
+ */
+
 extern spinlock_t pnp_lock;
 void *pnp_alloc(long size);
 
@@ -25,8 +30,6 @@ struct pnp_port {
 	resource_size_t align;	/* align boundary */
 	resource_size_t size;	/* size of range */
 	unsigned char flags;	/* port flags */
-	unsigned char pad;	/* pad */
-	struct pnp_port *next;	/* next port */
 };
 
 #define PNP_IRQ_NR 256
@@ -35,14 +38,11 @@ typedef struct { DECLARE_BITMAP(bits, PN
 struct pnp_irq {
 	pnp_irq_mask_t map;	/* bitmap for IRQ lines */
 	unsigned char flags;	/* IRQ flags */
-	unsigned char pad;	/* pad */
-	struct pnp_irq *next;	/* next IRQ */
 };
 
 struct pnp_dma {
 	unsigned char map;	/* bitmask for DMA channels */
 	unsigned char flags;	/* DMA flags */
-	struct pnp_dma *next;	/* next port */
 };
 
 struct pnp_mem {
@@ -51,44 +51,91 @@ struct pnp_mem {
 	resource_size_t align;	/* align boundary */
 	resource_size_t size;	/* size of range */
 	unsigned char flags;	/* memory flags */
-	unsigned char pad;	/* pad */
-	struct pnp_mem *next;	/* next memory resource */
 };
 
+#define PNP_OPTION_DEPENDENT		0x80000000
+#define PNP_OPTION_SET_MASK		0xffff
+#define PNP_OPTION_SET_SHIFT		12
+#define PNP_OPTION_PRIORITY_MASK	0xfff
+#define PNP_OPTION_PRIORITY_SHIFT	0
+
 #define PNP_RES_PRIORITY_PREFERRED	0
 #define PNP_RES_PRIORITY_ACCEPTABLE	1
 #define PNP_RES_PRIORITY_FUNCTIONAL	2
-#define PNP_RES_PRIORITY_INVALID	65535
+#define PNP_RES_PRIORITY_INVALID	PNP_OPTION_PRIORITY_MASK
 
 struct pnp_option {
-	unsigned short priority;	/* priority */
-	struct pnp_port *port;		/* first port */
-	struct pnp_irq *irq;		/* first IRQ */
-	struct pnp_dma *dma;		/* first DMA */
-	struct pnp_mem *mem;		/* first memory resource */
-	struct pnp_option *next;	/* used to chain dependent resources */
+	struct list_head list;
+	unsigned int flags;	/* independent/dependent, set, priority */
+
+	unsigned long type;	/* IORESOURCE_{IO,MEM,IRQ,DMA} */
+	union {
+		struct pnp_port port;
+		struct pnp_irq irq;
+		struct pnp_dma dma;
+		struct pnp_mem mem;
+	} u;
 };
 
-struct pnp_option *pnp_build_option(int priority);
-struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
-struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
-						 int priority);
-int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
+int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
 			      pnp_irq_mask_t *map, unsigned char flags);
-int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
+int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
 			      unsigned char map, unsigned char flags);
-int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
+int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
 			       resource_size_t min, resource_size_t max,
 			       resource_size_t align, resource_size_t size,
 			       unsigned char flags);
-int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
+int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
 			      resource_size_t min, resource_size_t max,
 			      resource_size_t align, resource_size_t size,
 			      unsigned char flags);
+
+static inline int pnp_option_is_dependent(struct pnp_option *option)
+{
+	return option->flags & PNP_OPTION_DEPENDENT ? 1 : 0;
+}
+
+static inline unsigned int pnp_option_set(struct pnp_option *option)
+{
+	return (option->flags >> PNP_OPTION_SET_SHIFT) & PNP_OPTION_SET_MASK;
+}
+
+static inline unsigned int pnp_option_priority(struct pnp_option *option)
+{
+	return (option->flags >> PNP_OPTION_PRIORITY_SHIFT) &
+	    PNP_OPTION_PRIORITY_MASK;
+}
+
+static inline unsigned int pnp_new_dependent_set(struct pnp_dev *dev,
+						 int priority)
+{
+	unsigned int flags;
+
+	if (priority > PNP_RES_PRIORITY_FUNCTIONAL) {
+		dev_warn(&dev->dev, "invalid dependent option priority %d "
+			 "clipped to %d", priority,
+			 PNP_RES_PRIORITY_INVALID);
+		priority = PNP_RES_PRIORITY_INVALID;
+	}
+
+	flags = PNP_OPTION_DEPENDENT |
+	    ((dev->num_dependent_sets & PNP_OPTION_SET_MASK) <<
+		PNP_OPTION_SET_SHIFT) |
+	    ((priority & PNP_OPTION_PRIORITY_MASK) <<
+		PNP_OPTION_PRIORITY_SHIFT);
+
+	dev->num_dependent_sets++;
+
+	return flags;
+}
+
+char *pnp_option_priority_name(struct pnp_option *option);
+void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option);
+
 void pnp_init_resources(struct pnp_dev *dev);
 
 void pnp_fixup_device(struct pnp_dev *dev);
-void pnp_free_option(struct pnp_option *option);
+void pnp_free_options(struct pnp_dev *dev);
 int __pnp_add_device(struct pnp_dev *dev);
 void __pnp_remove_device(struct pnp_dev *dev);
 
Index: work14/drivers/pnp/core.c
===================================================================
--- work14.orig/drivers/pnp/core.c	2008-06-17 14:45:35.000000000 -0600
+++ work14/drivers/pnp/core.c	2008-06-17 15:52:36.000000000 -0600
@@ -118,10 +118,9 @@ static void pnp_release_device(struct de
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 
-	pnp_free_option(dev->independent);
-	pnp_free_option(dev->dependent);
 	pnp_free_ids(dev);
 	pnp_free_resources(dev);
+	pnp_free_options(dev);
 	kfree(dev);
 }
 
@@ -135,6 +134,7 @@ struct pnp_dev *pnp_alloc_dev(struct pnp
 		return NULL;
 
 	INIT_LIST_HEAD(&dev->resources);
+	INIT_LIST_HEAD(&dev->options);
 	dev->protocol = protocol;
 	dev->number = id;
 	dev->dma_mask = DMA_24BIT_MASK;
Index: work14/drivers/pnp/interface.c
===================================================================
--- work14.orig/drivers/pnp/interface.c	2008-06-17 15:52:32.000000000 -0600
+++ work14/drivers/pnp/interface.c	2008-06-17 15:52:36.000000000 -0600
@@ -3,6 +3,8 @@
  *
  * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
  * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  */
 
 #include <linux/pnp.h>
@@ -184,39 +186,22 @@ static void pnp_print_mem(pnp_info_buffe
 }
 
 static void pnp_print_option(pnp_info_buffer_t * buffer, char *space,
-			     struct pnp_option *option, int dep)
+			     struct pnp_option *option)
 {
-	char *s;
-	struct pnp_port *port;
-	struct pnp_irq *irq;
-	struct pnp_dma *dma;
-	struct pnp_mem *mem;
-
-	if (dep) {
-		switch (option->priority) {
-		case PNP_RES_PRIORITY_PREFERRED:
-			s = "preferred";
-			break;
-		case PNP_RES_PRIORITY_ACCEPTABLE:
-			s = "acceptable";
-			break;
-		case PNP_RES_PRIORITY_FUNCTIONAL:
-			s = "functional";
-			break;
-		default:
-			s = "invalid";
-		}
-		pnp_printf(buffer, "Dependent: %02i - Priority %s\n", dep, s);
+	switch (option->type) {
+	case IORESOURCE_IO:
+		pnp_print_port(buffer, space, &option->u.port);
+		break;
+	case IORESOURCE_MEM:
+		pnp_print_mem(buffer, space, &option->u.mem);
+		break;
+	case IORESOURCE_IRQ:
+		pnp_print_irq(buffer, space, &option->u.irq);
+		break;
+	case IORESOURCE_DMA:
+		pnp_print_dma(buffer, space, &option->u.dma);
+		break;
 	}
-
-	for (port = option->port; port; port = port->next)
-		pnp_print_port(buffer, space, port);
-	for (irq = option->irq; irq; irq = irq->next)
-		pnp_print_irq(buffer, space, irq);
-	for (dma = option->dma; dma; dma = dma->next)
-		pnp_print_dma(buffer, space, dma);
-	for (mem = option->mem; mem; mem = mem->next)
-		pnp_print_mem(buffer, space, mem);
 }
 
 static ssize_t pnp_show_options(struct device *dmdev,
@@ -224,9 +209,9 @@ static ssize_t pnp_show_options(struct d
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	pnp_info_buffer_t *buffer;
-	struct pnp_option *independent = dev->independent;
-	struct pnp_option *dependent = dev->dependent;
-	int ret, dep = 1;
+	struct pnp_option *option;
+	int ret, dep = 0, set = 0;
+	char *indent;
 
 	buffer = pnp_alloc(sizeof(pnp_info_buffer_t));
 	if (!buffer)
@@ -235,14 +220,24 @@ static ssize_t pnp_show_options(struct d
 	buffer->len = PAGE_SIZE;
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
-	if (independent)
-		pnp_print_option(buffer, "", independent, 0);
 
-	while (dependent) {
-		pnp_print_option(buffer, "   ", dependent, dep);
-		dependent = dependent->next;
-		dep++;
+	list_for_each_entry(option, &dev->options, list) {
+		if (pnp_option_is_dependent(option)) {
+			indent = "  ";
+			if (!dep || pnp_option_set(option) != set) {
+				set = pnp_option_set(option);
+				dep = 1;
+				pnp_printf(buffer, "Dependent: %02i - "
+					   "Priority %s\n", set,
+					   pnp_option_priority_name(option));
+			}
+		} else {
+			dep = 0;
+			indent = "";
+		}
+		pnp_print_option(buffer, indent, option);
 	}
+
 	ret = (buffer->curr - buf);
 	kfree(buffer);
 	return ret;
Index: work14/drivers/pnp/isapnp/core.c
===================================================================
--- work14.orig/drivers/pnp/isapnp/core.c	2008-06-17 15:52:35.000000000 -0600
+++ work14/drivers/pnp/isapnp/core.c	2008-06-17 15:52:36.000000000 -0600
@@ -429,7 +429,7 @@ static struct pnp_dev *__init isapnp_par
  *  Add IRQ resource to resources list.
  */
 static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
-					     struct pnp_option *option,
+					     unsigned int option_flags,
 					     int size)
 {
 	unsigned char tmp[3];
@@ -446,27 +446,27 @@ static void __init isapnp_parse_irq_reso
 	if (size > 2)
 		flags = tmp[2];
 
-	pnp_register_irq_resource(dev, option, &map, flags);
+	pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
 /*
  *  Add DMA resource to resources list.
  */
 static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
-					     struct pnp_option *option,
+					     unsigned int option_flags,
 					     int size)
 {
 	unsigned char tmp[2];
 
 	isapnp_peek(tmp, size);
-	pnp_register_dma_resource(dev, option, tmp[0], tmp[1]);
+	pnp_register_dma_resource(dev, option_flags, tmp[0], tmp[1]);
 }
 
 /*
  *  Add port resource to resources list.
  */
 static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
-					      struct pnp_option *option,
+					      unsigned int option_flags,
 					      int size)
 {
 	unsigned char tmp[7];
@@ -479,14 +479,15 @@ static void __init isapnp_parse_port_res
 	align = tmp[5];
 	len = tmp[6];
 	flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0;
-	pnp_register_port_resource(dev, option, min, max, align, len, flags);
+	pnp_register_port_resource(dev, option_flags,
+				   min, max, align, len, flags);
 }
 
 /*
  *  Add fixed port resource to resources list.
  */
 static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
-						    struct pnp_option *option,
+						    unsigned int option_flags,
 						    int size)
 {
 	unsigned char tmp[3];
@@ -495,7 +496,7 @@ static void __init isapnp_parse_fixed_po
 	isapnp_peek(tmp, size);
 	base = (tmp[1] << 8) | tmp[0];
 	len = tmp[2];
-	pnp_register_port_resource(dev, option, base, base, 0, len,
+	pnp_register_port_resource(dev, option_flags, base, base, 0, len,
 				   IORESOURCE_IO_FIXED);
 }
 
@@ -503,7 +504,7 @@ static void __init isapnp_parse_fixed_po
  *  Add memory resource to resources list.
  */
 static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
-					     struct pnp_option *option,
+					     unsigned int option_flags,
 					     int size)
 {
 	unsigned char tmp[9];
@@ -516,14 +517,15 @@ static void __init isapnp_parse_mem_reso
 	align = (tmp[6] << 8) | tmp[5];
 	len = ((tmp[8] << 8) | tmp[7]) << 8;
 	flags = tmp[0];
-	pnp_register_mem_resource(dev, option, min, max, align, len, flags);
+	pnp_register_mem_resource(dev, option_flags,
+				  min, max, align, len, flags);
 }
 
 /*
  *  Add 32-bit memory resource to resources list.
  */
 static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
-					       struct pnp_option *option,
+					       unsigned int option_flags,
 					       int size)
 {
 	unsigned char tmp[17];
@@ -536,14 +538,15 @@ static void __init isapnp_parse_mem32_re
 	align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
 	len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
 	flags = tmp[0];
-	pnp_register_mem_resource(dev, option, min, max, align, len, flags);
+	pnp_register_mem_resource(dev, option_flags,
+				  min, max, align, len, flags);
 }
 
 /*
  *  Add 32-bit fixed memory resource to resources list.
  */
 static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
-						     struct pnp_option *option,
+						     unsigned int option_flags,
 						     int size)
 {
 	unsigned char tmp[9];
@@ -554,7 +557,7 @@ static void __init isapnp_parse_fixed_me
 	base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
 	len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
 	flags = tmp[0];
-	pnp_register_mem_resource(dev, option, base, base, 0, len, flags);
+	pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags);
 }
 
 /*
@@ -584,18 +587,14 @@ static int __init isapnp_create_device(s
 {
 	int number = 0, skip = 0, priority, compat = 0;
 	unsigned char type, tmp[17];
-	struct pnp_option *option, *option_independent;
+	unsigned int option_flags;
 	struct pnp_dev *dev;
 	u32 eisa_id;
 	char id[8];
 
 	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 		return 1;
-	option_independent = option = pnp_register_independent_option(dev);
-	if (!option) {
-		kfree(dev);
-		return 1;
-	}
+	option_flags = 0;
 	pnp_add_card_device(card, dev);
 
 	while (1) {
@@ -612,12 +611,7 @@ static int __init isapnp_create_device(s
 					return 1;
 				size = 0;
 				skip = 0;
-				option = pnp_register_independent_option(dev);
-				option_independent = option;
-				if (!option) {
-					kfree(dev);
-					return 1;
-				}
+				option_flags = 0;
 				pnp_add_card_device(card, dev);
 			} else {
 				skip = 1;
@@ -638,13 +632,13 @@ static int __init isapnp_create_device(s
 		case _STAG_IRQ:
 			if (size < 2 || size > 3)
 				goto __skip;
-			isapnp_parse_irq_resource(dev, option, size);
+			isapnp_parse_irq_resource(dev, option_flags, size);
 			size = 0;
 			break;
 		case _STAG_DMA:
 			if (size != 2)
 				goto __skip;
-			isapnp_parse_dma_resource(dev, option, size);
+			isapnp_parse_dma_resource(dev, option_flags, size);
 			size = 0;
 			break;
 		case _STAG_STARTDEP:
@@ -656,29 +650,24 @@ static int __init isapnp_create_device(s
 				priority = tmp[0];
 				size = 0;
 			}
-			option = pnp_register_dependent_option(dev, priority);
-			if (!option)
-				return 1;
+			option_flags = pnp_new_dependent_set(dev, priority);
 			break;
 		case _STAG_ENDDEP:
 			if (size != 0)
 				goto __skip;
-			if (option_independent == option)
-				dev_warn(&dev->dev, "missing "
-					 "_STAG_STARTDEP tag\n");
-			option = option_independent;
-			dev_dbg(&dev->dev, "end dependent options\n");
+			option_flags = 0;
 			break;
 		case _STAG_IOPORT:
 			if (size != 7)
 				goto __skip;
-			isapnp_parse_port_resource(dev, option, size);
+			isapnp_parse_port_resource(dev, option_flags, size);
 			size = 0;
 			break;
 		case _STAG_FIXEDIO:
 			if (size != 3)
 				goto __skip;
-			isapnp_parse_fixed_port_resource(dev, option, size);
+			isapnp_parse_fixed_port_resource(dev, option_flags,
+							 size);
 			size = 0;
 			break;
 		case _STAG_VENDOR:
@@ -686,7 +675,7 @@ static int __init isapnp_create_device(s
 		case _LTAG_MEMRANGE:
 			if (size != 9)
 				goto __skip;
-			isapnp_parse_mem_resource(dev, option, size);
+			isapnp_parse_mem_resource(dev, option_flags, size);
 			size = 0;
 			break;
 		case _LTAG_ANSISTR:
@@ -701,13 +690,14 @@ static int __init isapnp_create_device(s
 		case _LTAG_MEM32RANGE:
 			if (size != 17)
 				goto __skip;
-			isapnp_parse_mem32_resource(dev, option, size);
+			isapnp_parse_mem32_resource(dev, option_flags, size);
 			size = 0;
 			break;
 		case _LTAG_FIXEDMEM32RANGE:
 			if (size != 9)
 				goto __skip;
-			isapnp_parse_fixed_mem32_resource(dev, option, size);
+			isapnp_parse_fixed_mem32_resource(dev, option_flags,
+							  size);
 			size = 0;
 			break;
 		case _STAG_END:
Index: work14/drivers/pnp/manager.c
===================================================================
--- work14.orig/drivers/pnp/manager.c	2008-06-17 15:52:32.000000000 -0600
+++ work14/drivers/pnp/manager.c	2008-06-17 15:52:36.000000000 -0600
@@ -3,6 +3,8 @@
  *
  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  */
 
 #include <linux/errno.h>
@@ -228,102 +230,51 @@ static void pnp_clean_resource_table(str
 /**
  * pnp_assign_resources - assigns resources to the device based on the specified dependent number
  * @dev: pointer to the desired device
- * @depnum: the dependent function number
- *
- * Only set depnum to 0 if the device does not have dependent options.
+ * @set: the dependent function number
  */
-static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
+static int pnp_assign_resources(struct pnp_dev *dev, int set)
 {
-	struct pnp_port *port;
-	struct pnp_mem *mem;
-	struct pnp_irq *irq;
-	struct pnp_dma *dma;
+	struct pnp_option *option;
 	int nport = 0, nmem = 0, nirq = 0, ndma = 0;
+	int ret = 0;
 
-	dbg_pnp_show_resources(dev, "before pnp_assign_resources");
+	dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
 	mutex_lock(&pnp_res_mutex);
 	pnp_clean_resource_table(dev);
-	if (dev->independent) {
-		dev_dbg(&dev->dev, "assigning independent options\n");
-		port = dev->independent->port;
-		mem = dev->independent->mem;
-		irq = dev->independent->irq;
-		dma = dev->independent->dma;
-		while (port) {
-			if (pnp_assign_port(dev, port, nport) < 0)
-				goto fail;
-			nport++;
-			port = port->next;
-		}
-		while (mem) {
-			if (pnp_assign_mem(dev, mem, nmem) < 0)
-				goto fail;
-			nmem++;
-			mem = mem->next;
-		}
-		while (irq) {
-			if (pnp_assign_irq(dev, irq, nirq) < 0)
-				goto fail;
-			nirq++;
-			irq = irq->next;
-		}
-		while (dma) {
-			if (pnp_assign_dma(dev, dma, ndma) < 0)
-				goto fail;
-			ndma++;
-			dma = dma->next;
-		}
-	}
 
-	if (depnum) {
-		struct pnp_option *dep;
-		int i;
-
-		dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum);
-		for (i = 1, dep = dev->dependent; i < depnum;
-		     i++, dep = dep->next)
-			if (!dep)
-				goto fail;
-		port = dep->port;
-		mem = dep->mem;
-		irq = dep->irq;
-		dma = dep->dma;
-		while (port) {
-			if (pnp_assign_port(dev, port, nport) < 0)
-				goto fail;
-			nport++;
-			port = port->next;
-		}
-		while (mem) {
-			if (pnp_assign_mem(dev, mem, nmem) < 0)
-				goto fail;
-			nmem++;
-			mem = mem->next;
-		}
-		while (irq) {
-			if (pnp_assign_irq(dev, irq, nirq) < 0)
-				goto fail;
-			nirq++;
-			irq = irq->next;
-		}
-		while (dma) {
-			if (pnp_assign_dma(dev, dma, ndma) < 0)
-				goto fail;
-			ndma++;
-			dma = dma->next;
+	list_for_each_entry(option, &dev->options, list) {
+		if (pnp_option_is_dependent(option) &&
+		    pnp_option_set(option) != set)
+				continue;
+
+		switch (option->type) {
+		case IORESOURCE_IO:
+			ret = pnp_assign_port(dev, &option->u.port, nport++);
+			break;
+		case IORESOURCE_MEM:
+			ret = pnp_assign_mem(dev, &option->u.mem, nmem++);
+			break;
+		case IORESOURCE_IRQ:
+			ret = pnp_assign_irq(dev, &option->u.irq, nirq++);
+			break;
+		case IORESOURCE_DMA:
+			ret = pnp_assign_dma(dev, &option->u.dma, ndma++);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
 		}
-	} else if (dev->dependent)
-		goto fail;
-
-	mutex_unlock(&pnp_res_mutex);
-	dbg_pnp_show_resources(dev, "after pnp_assign_resources");
-	return 1;
+		if (ret < 0)
+			break;
+	}
 
-fail:
-	pnp_clean_resource_table(dev);
 	mutex_unlock(&pnp_res_mutex);
-	dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)");
-	return 0;
+	if (ret < 0) {
+		dev_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret);
+		pnp_clean_resource_table(dev);
+	} else
+		dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded");
+	return ret;
 }
 
 /**
@@ -332,29 +283,25 @@ fail:
  */
 int pnp_auto_config_dev(struct pnp_dev *dev)
 {
-	struct pnp_option *dep;
-	int i = 1;
+	int i, ret;
 
 	if (!pnp_can_configure(dev)) {
 		dev_dbg(&dev->dev, "configuration not supported\n");
 		return -ENODEV;
 	}
 
-	if (!dev->dependent) {
-		if (pnp_assign_resources(dev, 0))
+	ret = pnp_assign_resources(dev, 0);
+	if (ret == 0)
+		return 0;
+
+	for (i = 1; i < dev->num_dependent_sets; i++) {
+		ret = pnp_assign_resources(dev, i);
+		if (ret == 0)
 			return 0;
-	} else {
-		dep = dev->dependent;
-		do {
-			if (pnp_assign_resources(dev, i))
-				return 0;
-			dep = dep->next;
-			i++;
-		} while (dep);
 	}
 
 	dev_err(&dev->dev, "unable to assign resources\n");
-	return -EBUSY;
+	return ret;
 }
 
 /**
Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:33.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:36.000000000 -0600
@@ -407,7 +407,7 @@ int pnpacpi_parse_allocated_resource(str
 }
 
 static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
-					    struct pnp_option *option,
+					    unsigned int option_flags,
 					    struct acpi_resource_dma *p)
 {
 	int i;
@@ -420,11 +420,11 @@ static __init void pnpacpi_parse_dma_opt
 		map |= 1 << p->channels[i];
 
 	flags = dma_flags(p->type, p->bus_master, p->transfer);
-	pnp_register_dma_resource(dev, option, map, flags);
+	pnp_register_dma_resource(dev, option_flags, map, flags);
 }
 
 static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
-					    struct pnp_option *option,
+					    unsigned int option_flags,
 					    struct acpi_resource_irq *p)
 {
 	int i;
@@ -447,11 +447,11 @@ static __init void pnpacpi_parse_irq_opt
 	}
 
 	flags = irq_flags(p->triggering, p->polarity, p->sharable);
-	pnp_register_irq_resource(dev, option, &map, flags);
+	pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
 static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
-						struct pnp_option *option,
+					unsigned int option_flags,
 					struct acpi_resource_extended_irq *p)
 {
 	int i;
@@ -467,11 +467,11 @@ static __init void pnpacpi_parse_ext_irq
 			__set_bit(p->interrupts[i], map.bits);
 
 	flags = irq_flags(p->triggering, p->polarity, p->sharable);
-	pnp_register_irq_resource(dev, option, &map, flags);
+	pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
 static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
-					     struct pnp_option *option,
+					     unsigned int option_flags,
 					     struct acpi_resource_io *io)
 {
 	unsigned char flags = 0;
@@ -481,23 +481,23 @@ static __init void pnpacpi_parse_port_op
 
 	if (io->io_decode == ACPI_DECODE_16)
 		flags = IORESOURCE_IO_16BIT_ADDR;
-	pnp_register_port_resource(dev, option, io->minimum, io->maximum,
+	pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
 				   io->alignment, io->address_length, flags);
 }
 
 static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
-						   struct pnp_option *option,
+					unsigned int option_flags,
 					struct acpi_resource_fixed_io *io)
 {
 	if (io->address_length == 0)
 		return;
 
-	pnp_register_port_resource(dev, option, io->address, io->address, 0,
-				   io->address_length, IORESOURCE_IO_FIXED);
+	pnp_register_port_resource(dev, option_flags, io->address, io->address,
+				   0, io->address_length, IORESOURCE_IO_FIXED);
 }
 
 static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
-					      struct pnp_option *option,
+					      unsigned int option_flags,
 					      struct acpi_resource_memory24 *p)
 {
 	unsigned char flags = 0;
@@ -507,12 +507,12 @@ static __init void pnpacpi_parse_mem24_o
 
 	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
 		flags = IORESOURCE_MEM_WRITEABLE;
-	pnp_register_mem_resource(dev, option, p->minimum, p->maximum,
+	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
 				  p->alignment, p->address_length, flags);
 }
 
 static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
-					      struct pnp_option *option,
+					      unsigned int option_flags,
 					      struct acpi_resource_memory32 *p)
 {
 	unsigned char flags = 0;
@@ -522,12 +522,12 @@ static __init void pnpacpi_parse_mem32_o
 
 	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
 		flags = IORESOURCE_MEM_WRITEABLE;
-	pnp_register_mem_resource(dev, option, p->minimum, p->maximum,
+	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
 				  p->alignment, p->address_length, flags);
 }
 
 static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
-						    struct pnp_option *option,
+					unsigned int option_flags,
 					struct acpi_resource_fixed_memory32 *p)
 {
 	unsigned char flags = 0;
@@ -537,12 +537,12 @@ static __init void pnpacpi_parse_fixed_m
 
 	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
 		flags = IORESOURCE_MEM_WRITEABLE;
-	pnp_register_mem_resource(dev, option, p->address, p->address,
+	pnp_register_mem_resource(dev, option_flags, p->address, p->address,
 				  0, p->address_length, flags);
 }
 
 static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
-						struct pnp_option *option,
+						unsigned int option_flags,
 						struct acpi_resource *r)
 {
 	struct acpi_resource_address64 addr, *p = &addr;
@@ -562,18 +562,18 @@ static __init void pnpacpi_parse_address
 	if (p->resource_type == ACPI_MEMORY_RANGE) {
 		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
 			flags = IORESOURCE_MEM_WRITEABLE;
-		pnp_register_mem_resource(dev, option, p->minimum, p->minimum,
-					  0, p->address_length, flags);
+		pnp_register_mem_resource(dev, option_flags, p->minimum,
+					  p->minimum, 0, p->address_length,
+					  flags);
 	} else if (p->resource_type == ACPI_IO_RANGE)
-		pnp_register_port_resource(dev, option, p->minimum, p->minimum,
-					   0, p->address_length,
+		pnp_register_port_resource(dev, option_flags, p->minimum,
+					   p->minimum, 0, p->address_length,
 					   IORESOURCE_IO_FIXED);
 }
 
 struct acpipnp_parse_option_s {
-	struct pnp_option *option;
-	struct pnp_option *option_independent;
 	struct pnp_dev *dev;
+	unsigned int option_flags;
 };
 
 static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
@@ -582,15 +582,15 @@ static __init acpi_status pnpacpi_option
 	int priority;
 	struct acpipnp_parse_option_s *parse_data = data;
 	struct pnp_dev *dev = parse_data->dev;
-	struct pnp_option *option = parse_data->option;
+	unsigned int option_flags = parse_data->option_flags;
 
 	switch (res->type) {
 	case ACPI_RESOURCE_TYPE_IRQ:
-		pnpacpi_parse_irq_option(dev, option, &res->data.irq);
+		pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);
 		break;
 
 	case ACPI_RESOURCE_TYPE_DMA:
-		pnpacpi_parse_dma_option(dev, option, &res->data.dma);
+		pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);
 		break;
 
 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -610,31 +610,19 @@ static __init acpi_status pnpacpi_option
 			priority = PNP_RES_PRIORITY_INVALID;
 			break;
 		}
-		/* TBD: Consider performance/robustness bits */
-		option = pnp_register_dependent_option(dev, priority);
-		if (!option)
-			return AE_ERROR;
-		parse_data->option = option;
+		parse_data->option_flags = pnp_new_dependent_set(dev, priority);
 		break;
 
 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
-		/*only one EndDependentFn is allowed */
-		if (!parse_data->option_independent) {
-			dev_warn(&dev->dev, "more than one EndDependentFn "
-				 "in _PRS\n");
-			return AE_ERROR;
-		}
-		parse_data->option = parse_data->option_independent;
-		parse_data->option_independent = NULL;
-		dev_dbg(&dev->dev, "end dependent options\n");
+		parse_data->option_flags = 0;
 		break;
 
 	case ACPI_RESOURCE_TYPE_IO:
-		pnpacpi_parse_port_option(dev, option, &res->data.io);
+		pnpacpi_parse_port_option(dev, option_flags, &res->data.io);
 		break;
 
 	case ACPI_RESOURCE_TYPE_FIXED_IO:
-		pnpacpi_parse_fixed_port_option(dev, option,
+		pnpacpi_parse_fixed_port_option(dev, option_flags,
 					        &res->data.fixed_io);
 		break;
 
@@ -643,29 +631,31 @@ static __init acpi_status pnpacpi_option
 		break;
 
 	case ACPI_RESOURCE_TYPE_MEMORY24:
-		pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
+		pnpacpi_parse_mem24_option(dev, option_flags,
+					   &res->data.memory24);
 		break;
 
 	case ACPI_RESOURCE_TYPE_MEMORY32:
-		pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
+		pnpacpi_parse_mem32_option(dev, option_flags,
+					   &res->data.memory32);
 		break;
 
 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		pnpacpi_parse_fixed_mem32_option(dev, option,
+		pnpacpi_parse_fixed_mem32_option(dev, option_flags,
 						 &res->data.fixed_memory32);
 		break;
 
 	case ACPI_RESOURCE_TYPE_ADDRESS16:
 	case ACPI_RESOURCE_TYPE_ADDRESS32:
 	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		pnpacpi_parse_address_option(dev, option, res);
+		pnpacpi_parse_address_option(dev, option_flags, res);
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
-		pnpacpi_parse_ext_irq_option(dev, option,
+		pnpacpi_parse_ext_irq_option(dev, option_flags,
 					     &res->data.extended_irq);
 		break;
 
@@ -689,12 +679,9 @@ int __init pnpacpi_parse_resource_option
 
 	dev_dbg(&dev->dev, "parse resource options\n");
 
-	parse_data.option = pnp_register_independent_option(dev);
-	if (!parse_data.option)
-		return -ENOMEM;
-
-	parse_data.option_independent = parse_data.option;
 	parse_data.dev = dev;
+	parse_data.option_flags = 0;
+
 	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
 				     pnpacpi_option_resource, &parse_data);
 
Index: work14/drivers/pnp/pnpbios/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:33.000000000 -0600
+++ work14/drivers/pnp/pnpbios/rsparser.c	2008-06-17 15:52:36.000000000 -0600
@@ -216,7 +216,7 @@ len_err:
 
 static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
 					    unsigned char *p, int size,
-					    struct pnp_option *option)
+					    unsigned int option_flags)
 {
 	resource_size_t min, max, align, len;
 	unsigned char flags;
@@ -226,12 +226,13 @@ static __init void pnpbios_parse_mem_opt
 	align = (p[9] << 8) | p[8];
 	len = ((p[11] << 8) | p[10]) << 8;
 	flags = p[3];
-	pnp_register_mem_resource(dev, option, min, max, align, len, flags);
+	pnp_register_mem_resource(dev, option_flags, min, max, align, len,
+				  flags);
 }
 
 static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
 					      unsigned char *p, int size,
-					      struct pnp_option *option)
+					      unsigned int option_flags)
 {
 	resource_size_t min, max, align, len;
 	unsigned char flags;
@@ -241,12 +242,13 @@ static __init void pnpbios_parse_mem32_o
 	align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
 	len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
 	flags = p[3];
-	pnp_register_mem_resource(dev, option, min, max, align, len, flags);
+	pnp_register_mem_resource(dev, option_flags, min, max, align, len,
+				  flags);
 }
 
 static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
 						    unsigned char *p, int size,
-						    struct pnp_option *option)
+						    unsigned int option_flags)
 {
 	resource_size_t base, len;
 	unsigned char flags;
@@ -254,12 +256,12 @@ static __init void pnpbios_parse_fixed_m
 	base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
 	len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
 	flags = p[3];
-	pnp_register_mem_resource(dev, option, base, base, 0, len, flags);
+	pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags);
 }
 
 static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
 					    unsigned char *p, int size,
-					    struct pnp_option *option)
+					    unsigned int option_flags)
 {
 	unsigned long bits;
 	pnp_irq_mask_t map;
@@ -273,19 +275,19 @@ static __init void pnpbios_parse_irq_opt
 	if (size > 2)
 		flags = p[3];
 
-	pnp_register_irq_resource(dev, option, &map, flags);
+	pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
 static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
 					    unsigned char *p, int size,
-					    struct pnp_option *option)
+					    unsigned int option_flags)
 {
-	pnp_register_dma_resource(dev, option, p[1], p[2]);
+	pnp_register_dma_resource(dev, option_flags, p[1], p[2]);
 }
 
 static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
 					     unsigned char *p, int size,
-					     struct pnp_option *option)
+					     unsigned int option_flags)
 {
 	resource_size_t min, max, align, len;
 	unsigned char flags;
@@ -295,38 +297,35 @@ static __init void pnpbios_parse_port_op
 	align = p[6];
 	len = p[7];
 	flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0;
-	pnp_register_port_resource(dev, option, min, max, align, len, flags);
+	pnp_register_port_resource(dev, option_flags, min, max, align, len,
+				   flags);
 }
 
 static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
 						   unsigned char *p, int size,
-						   struct pnp_option *option)
+						   unsigned int option_flags)
 {
 	resource_size_t base, len;
 
 	base = (p[2] << 8) | p[1];
 	len = p[3];
-	pnp_register_port_resource(dev, option, base, base, 0, len,
+	pnp_register_port_resource(dev, option_flags, base, base, 0, len,
 				   IORESOURCE_IO_FIXED);
 }
 
 static __init unsigned char *
 pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
-					struct pnp_dev *dev)
+				   struct pnp_dev *dev)
 {
 	unsigned int len, tag;
 	int priority;
-	struct pnp_option *option, *option_independent;
+	unsigned int option_flags;
 
 	if (!p)
 		return NULL;
 
 	dev_dbg(&dev->dev, "parse resource options\n");
-
-	option_independent = option = pnp_register_independent_option(dev);
-	if (!option)
-		return NULL;
-
+	option_flags = 0;
 	while ((char *)p < (char *)end) {
 
 		/* determine the type of tag */
@@ -343,37 +342,38 @@ pnpbios_parse_resource_option_data(unsig
 		case LARGE_TAG_MEM:
 			if (len != 9)
 				goto len_err;
-			pnpbios_parse_mem_option(dev, p, len, option);
+			pnpbios_parse_mem_option(dev, p, len, option_flags);
 			break;
 
 		case LARGE_TAG_MEM32:
 			if (len != 17)
 				goto len_err;
-			pnpbios_parse_mem32_option(dev, p, len, option);
+			pnpbios_parse_mem32_option(dev, p, len, option_flags);
 			break;
 
 		case LARGE_TAG_FIXEDMEM32:
 			if (len != 9)
 				goto len_err;
-			pnpbios_parse_fixed_mem32_option(dev, p, len, option);
+			pnpbios_parse_fixed_mem32_option(dev, p, len,
+							 option_flags);
 			break;
 
 		case SMALL_TAG_IRQ:
 			if (len < 2 || len > 3)
 				goto len_err;
-			pnpbios_parse_irq_option(dev, p, len, option);
+			pnpbios_parse_irq_option(dev, p, len, option_flags);
 			break;
 
 		case SMALL_TAG_DMA:
 			if (len != 2)
 				goto len_err;
-			pnpbios_parse_dma_option(dev, p, len, option);
+			pnpbios_parse_dma_option(dev, p, len, option_flags);
 			break;
 
 		case SMALL_TAG_PORT:
 			if (len != 7)
 				goto len_err;
-			pnpbios_parse_port_option(dev, p, len, option);
+			pnpbios_parse_port_option(dev, p, len, option_flags);
 			break;
 
 		case SMALL_TAG_VENDOR:
@@ -383,7 +383,8 @@ pnpbios_parse_resource_option_data(unsig
 		case SMALL_TAG_FIXEDPORT:
 			if (len != 3)
 				goto len_err;
-			pnpbios_parse_fixed_port_option(dev, p, len, option);
+			pnpbios_parse_fixed_port_option(dev, p, len,
+							option_flags);
 			break;
 
 		case SMALL_TAG_STARTDEP:
@@ -392,19 +393,13 @@ pnpbios_parse_resource_option_data(unsig
 			priority = PNP_RES_PRIORITY_ACCEPTABLE;
 			if (len > 0)
 				priority = p[1];
-			option = pnp_register_dependent_option(dev, priority);
-			if (!option)
-				return NULL;
+			option_flags = pnp_new_dependent_set(dev, priority);
 			break;
 
 		case SMALL_TAG_ENDDEP:
 			if (len != 0)
 				goto len_err;
-			if (option_independent == option)
-				dev_warn(&dev->dev, "missing "
-					 "SMALL_TAG_STARTDEP tag\n");
-			option = option_independent;
-			dev_dbg(&dev->dev, "end dependent options\n");
+			option_flags = 0;
 			break;
 
 		case SMALL_TAG_END:
Index: work14/drivers/pnp/quirks.c
===================================================================
--- work14.orig/drivers/pnp/quirks.c	2008-06-17 15:52:32.000000000 -0600
+++ work14/drivers/pnp/quirks.c	2008-06-17 15:52:36.000000000 -0600
@@ -5,6 +5,8 @@
  *  when building up the resource structure for the first time.
  *
  *  Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
+ *  Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
  *  Heavily based on PCI quirks handling which is
  *
@@ -20,186 +22,207 @@
 #include <linux/kallsyms.h>
 #include "base.h"
 
+static void quirk_awe32_add_ports(struct pnp_dev *dev,
+				  struct pnp_option *option,
+				  unsigned int offset)
+{
+	struct pnp_option *new_option;
+
+	new_option = kmalloc(sizeof(struct pnp_option), GFP_KERNEL);
+	if (!new_option) {
+		dev_err(&dev->dev, "couldn't add ioport region to option set "
+			"%d\n", pnp_option_set(option));
+		return;
+	}
+
+	*new_option = *option;
+	new_option->u.port.min += offset;
+	new_option->u.port.max += offset;
+	list_add(&new_option->list, &option->list);
+
+	dev_info(&dev->dev, "added ioport region %#llx-%#llx to set %d\n",
+		(unsigned long long) new_option->u.port.min,
+		(unsigned long long) new_option->u.port.max,
+		pnp_option_set(option));
+}
+
 static void quirk_awe32_resources(struct pnp_dev *dev)
 {
-	struct pnp_port *port, *port2, *port3;
-	struct pnp_option *res = dev->dependent;
+	struct pnp_option *option;
+	unsigned int set = ~0;
 
 	/*
-	 * Unfortunately the isapnp_add_port_resource is too tightly bound
-	 * into the PnP discovery sequence, and cannot be used. Link in the
-	 * two extra ports (at offset 0x400 and 0x800 from the one given) by
-	 * hand.
+	 * Add two extra ioport regions (at offset 0x400 and 0x800 from the
+	 * one given) to every dependent option set.
 	 */
-	for (; res; res = res->next) {
-		port2 = pnp_alloc(sizeof(struct pnp_port));
-		if (!port2)
-			return;
-		port3 = pnp_alloc(sizeof(struct pnp_port));
-		if (!port3) {
-			kfree(port2);
-			return;
+	list_for_each_entry(option, &dev->options, list) {
+		if (pnp_option_is_dependent(option) &&
+		    pnp_option_set(option) != set) {
+			set = pnp_option_set(option);
+			quirk_awe32_add_ports(dev, option, 0x800);
+			quirk_awe32_add_ports(dev, option, 0x400);
 		}
-		port = res->port;
-		memcpy(port2, port, sizeof(struct pnp_port));
-		memcpy(port3, port, sizeof(struct pnp_port));
-		port->next = port2;
-		port2->next = port3;
-		port2->min += 0x400;
-		port2->max += 0x400;
-		port3->min += 0x800;
-		port3->max += 0x800;
-		dev_info(&dev->dev,
-			"AWE32 quirk - added ioports 0x%lx and 0x%lx\n",
-			(unsigned long)port2->min,
-			(unsigned long)port3->min);
 	}
 }
 
 static void quirk_cmi8330_resources(struct pnp_dev *dev)
 {
-	struct pnp_option *res = dev->dependent;
-	unsigned long tmp;
-
-	for (; res; res = res->next) {
-
-		struct pnp_irq *irq;
-		struct pnp_dma *dma;
+	struct pnp_option *option;
+	struct pnp_irq *irq;
+	struct pnp_dma *dma;
 
-		for (irq = res->irq; irq; irq = irq->next) {	// Valid irqs are 5, 7, 10
-			tmp = 0x04A0;
-			bitmap_copy(irq->map.bits, &tmp, 16);	// 0000 0100 1010 0000
-		}
+	list_for_each_entry(option, &dev->options, list) {
+		if (!pnp_option_is_dependent(option))
+			continue;
 
-		for (dma = res->dma; dma; dma = dma->next)	// Valid 8bit dma channels are 1,3
+		if (option->type == IORESOURCE_IRQ) {
+			irq = &option->u.irq;
+			bitmap_zero(irq->map.bits, PNP_IRQ_NR);
+			__set_bit(5, irq->map.bits);
+			__set_bit(7, irq->map.bits);
+			__set_bit(10, irq->map.bits);
+			dev_info(&dev->dev, "set possible IRQs in "
+				 "option set %d to 5, 7, 10\n",
+				 pnp_option_set(option));
+		} else if (option->type == IORESOURCE_DMA) {
+			dma = &option->u.dma;
 			if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) ==
-			    IORESOURCE_DMA_8BIT)
-				dma->map = 0x000A;
+						IORESOURCE_DMA_8BIT &&
+			    dma->map != 0x0A) {
+				dev_info(&dev->dev, "changing possible "
+					 "DMA channel mask in option set %d "
+					 "from %#02x to 0x0A (1, 3)\n",
+					 pnp_option_set(option), dma->map);
+				dma->map = 0x0A;
+			}
+		}
 	}
-	dev_info(&dev->dev, "CMI8330 quirk - forced possible IRQs to 5, 7, 10 "
-		"and DMA channels to 1, 3\n");
 }
 
 static void quirk_sb16audio_resources(struct pnp_dev *dev)
 {
+	struct pnp_option *option;
+	unsigned int prev_option_flags = ~0, n = 0;
 	struct pnp_port *port;
-	struct pnp_option *res = dev->dependent;
-	int changed = 0;
 
 	/*
-	 * The default range on the mpu port for these devices is 0x388-0x388.
+	 * The default range on the OPL port for these devices is 0x388-0x388.
 	 * Here we increase that range so that two such cards can be
 	 * auto-configured.
 	 */
+	list_for_each_entry(option, &dev->options, list) {
+		if (prev_option_flags != option->flags) {
+			prev_option_flags = option->flags;
+			n = 0;
+		}
 
-	for (; res; res = res->next) {
-		port = res->port;
-		if (!port)
-			continue;
-		port = port->next;
-		if (!port)
-			continue;
-		port = port->next;
-		if (!port)
-			continue;
-		if (port->min != port->max)
-			continue;
-		port->max += 0x70;
-		changed = 1;
+		if (pnp_option_is_dependent(option) &&
+		    option->type == IORESOURCE_IO) {
+			n++;
+			port = &option->u.port;
+			if (n == 3 && port->min == port->max) {
+				port->max += 0x70;
+				dev_info(&dev->dev, "increased option port "
+					 "range from %#llx-%#llx to "
+					 "%#llx-%#llx\n",
+					 (unsigned long long) port->min,
+					 (unsigned long long) port->min,
+					 (unsigned long long) port->min,
+					 (unsigned long long) port->max);
+			}
+		}
 	}
-	if (changed)
-		dev_info(&dev->dev, "SB audio device quirk - increased port range\n");
 }
 
-static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev)
+static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev,
+						  unsigned int set)
 {
-	struct pnp_option *head = NULL;
-	struct pnp_option *prev = NULL;
-	struct pnp_option *res;
-
-	/*
-	 * Build a functional IRQ-optional variant of each MPU option.
-	 */
-
-	for (res = dev->dependent; res; res = res->next) {
-		struct pnp_option *curr;
-		struct pnp_port *port;
-		struct pnp_port *copy_port;
-		struct pnp_irq *irq;
-		struct pnp_irq *copy_irq;
-
-		port = res->port;
-		irq = res->irq;
-		if (!port || !irq)
-			continue;
+	struct pnp_option *tail = NULL, *first_new_option = NULL;
+	struct pnp_option *option, *new_option;
+	unsigned int flags;
+
+	list_for_each_entry(option, &dev->options, list) {
+		if (pnp_option_is_dependent(option))
+			tail = option;
+	}
+	if (!tail) {
+		dev_err(&dev->dev, "no dependent option sets\n");
+		return NULL;
+	}
 
-		copy_port = pnp_alloc(sizeof *copy_port);
-		if (!copy_port)
-			break;
-
-		copy_irq = pnp_alloc(sizeof *copy_irq);
-		if (!copy_irq) {
-			kfree(copy_port);
-			break;
-		}
+	flags = pnp_new_dependent_set(dev, PNP_RES_PRIORITY_FUNCTIONAL);
+	list_for_each_entry(option, &dev->options, list) {
+		if (pnp_option_is_dependent(option) &&
+		    pnp_option_set(option) == set) {
+			new_option = kmalloc(sizeof(struct pnp_option),
+					     GFP_KERNEL);
+			if (!new_option) {
+				dev_err(&dev->dev, "couldn't clone dependent "
+					"set %d\n", set);
+				return NULL;
+			}
 
-		*copy_port = *port;
-		copy_port->next = NULL;
+			*new_option = *option;
+			new_option->flags = flags;
+			if (!first_new_option)
+				first_new_option = new_option;
 
-		*copy_irq = *irq;
-		copy_irq->flags |= IORESOURCE_IRQ_OPTIONAL;
-		copy_irq->next = NULL;
-
-		curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL);
-		if (!curr) {
-			kfree(copy_port);
-			kfree(copy_irq);
-			break;
+			list_add(&new_option->list, &tail->list);
+			tail = new_option;
 		}
-		curr->port = copy_port;
-		curr->irq = copy_irq;
-
-		if (prev)
-			prev->next = curr;
-		else
-			head = curr;
-		prev = curr;
 	}
-	if (head)
-		dev_info(&dev->dev, "adding IRQ-optional MPU options\n");
 
-	return head;
+	return first_new_option;
 }
 
-static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
+
+static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev)
 {
-	struct pnp_option *res;
+	struct pnp_option *new_option;
+	unsigned int num_sets, i, set;
 	struct pnp_irq *irq;
 
-	res = dev->independent;
-	if (!res)
-		return;
+	num_sets = dev->num_dependent_sets;
+	for (i = 0; i < num_sets; i++) {
+		new_option = pnp_clone_dependent_set(dev, i);
+		if (!new_option)
+			return;
 
-	irq = res->irq;
-	if (!irq || irq->next)
-		return;
+		set = pnp_option_set(new_option);
+		while (new_option && pnp_option_set(new_option) == set) {
+			if (new_option->type == IORESOURCE_IRQ) {
+				irq = &new_option->u.irq;
+				irq->flags |= IORESOURCE_IRQ_OPTIONAL;
+			}
+			dbg_pnp_show_option(dev, new_option);
+			new_option = list_entry(new_option->list.next,
+						struct pnp_option, list);
+		}
 
-	irq->flags |= IORESOURCE_IRQ_OPTIONAL;
-	dev_info(&dev->dev, "made independent IRQ optional\n");
+		dev_info(&dev->dev, "added dependent option set %d (same as "
+			 "set %d except IRQ optional)\n", set, i);
+	}
 }
 
-static void quirk_isapnp_mpu_resources(struct pnp_dev *dev)
+static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
 {
-	struct pnp_option *res;
+	struct pnp_option *option;
+	struct pnp_irq *irq = NULL;
+	unsigned int independent_irqs = 0;
+
+	list_for_each_entry(option, &dev->options, list) {
+		if (option->type == IORESOURCE_IRQ &&
+		    !pnp_option_is_dependent(option)) {
+			independent_irqs++;
+			irq = &option->u.irq;
+		}
+	}
 
-	res = dev->dependent;
-	if (!res)
+	if (independent_irqs != 1)
 		return;
 
-	while (res->next)
-		res = res->next;
-
-	res->next = quirk_isapnp_mpu_options(dev);
+	irq->flags |= IORESOURCE_IRQ_OPTIONAL;
+	dev_info(&dev->dev, "made independent IRQ optional\n");
 }
 
 #include <linux/pci.h>
@@ -294,10 +317,10 @@ static struct pnp_fixup pnp_fixups[] = {
 	{"CTL0043", quirk_sb16audio_resources},
 	{"CTL0044", quirk_sb16audio_resources},
 	{"CTL0045", quirk_sb16audio_resources},
-	/* Add IRQ-less MPU options */
+	/* Add IRQ-optional MPU options */
 	{"ADS7151", quirk_ad1815_mpu_resources},
-	{"ADS7181", quirk_isapnp_mpu_resources},
-	{"AZT0002", quirk_isapnp_mpu_resources},
+	{"ADS7181", quirk_add_irq_optional_dependent_sets},
+	{"AZT0002", quirk_add_irq_optional_dependent_sets},
 	/* PnP resources that might overlap PCI BARs */
 	{"PNP0c01", quirk_system_pci_resources},
 	{"PNP0c02", quirk_system_pci_resources},
Index: work14/drivers/pnp/resource.c
===================================================================
--- work14.orig/drivers/pnp/resource.c	2008-06-17 15:52:31.000000000 -0600
+++ work14/drivers/pnp/resource.c	2008-06-17 15:52:36.000000000 -0600
@@ -3,6 +3,8 @@
  *
  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  */
 
 #include <linux/module.h>
@@ -28,78 +30,36 @@ static int pnp_reserve_mem[16] = {[0 ...
  * option registration
  */
 
-struct pnp_option *pnp_build_option(int priority)
+struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type,
+				    unsigned int option_flags)
 {
-	struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option));
+	struct pnp_option *option;
 
+	option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL);
 	if (!option)
 		return NULL;
 
-	option->priority = priority & 0xff;
-	/* make sure the priority is valid */
-	if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL)
-		option->priority = PNP_RES_PRIORITY_INVALID;
+	option->flags = option_flags;
+	option->type = type;
 
+	list_add_tail(&option->list, &dev->options);
 	return option;
 }
 
-struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
-{
-	struct pnp_option *option;
-
-	option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED);
-
-	/* this should never happen but if it does we'll try to continue */
-	if (dev->independent)
-		dev_err(&dev->dev, "independent resource already registered\n");
-	dev->independent = option;
-
-	dev_dbg(&dev->dev, "new independent option\n");
-	return option;
-}
-
-struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
-						 int priority)
-{
-	struct pnp_option *option;
-
-	option = pnp_build_option(priority);
-
-	if (dev->dependent) {
-		struct pnp_option *parent = dev->dependent;
-		while (parent->next)
-			parent = parent->next;
-		parent->next = option;
-	} else
-		dev->dependent = option;
-
-	dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority);
-	return option;
-}
-
-int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
+int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
 			      pnp_irq_mask_t *map, unsigned char flags)
 {
-	struct pnp_irq *irq, *ptr;
-#ifdef DEBUG
-	char buf[PNP_IRQ_NR];   /* hex-encoded, so this is overkill but safe */
-#endif
+	struct pnp_option *option;
+	struct pnp_irq *irq;
 
-	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
-	if (!irq)
+	option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
+	if (!option)
 		return -ENOMEM;
 
+	irq = &option->u.irq;
 	irq->map = *map;
 	irq->flags = flags;
 
-	ptr = option->irq;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = irq;
-	else
-		option->irq = irq;
-
 #ifdef CONFIG_PCI
 	{
 		int i;
@@ -110,163 +70,81 @@ int pnp_register_irq_resource(struct pnp
 	}
 #endif
 
-#ifdef DEBUG
-	bitmap_scnprintf(buf, sizeof(buf), irq->map.bits, PNP_IRQ_NR);
-	dev_dbg(&dev->dev, "  irq bitmask %s flags %#x\n", buf,
-		irq->flags);
-#endif
+	dbg_pnp_show_option(dev, option);
 	return 0;
 }
 
-int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
+int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
 			      unsigned char map, unsigned char flags)
 {
-	struct pnp_dma *dma, *ptr;
+	struct pnp_option *option;
+	struct pnp_dma *dma;
 
-	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
-	if (!dma)
+	option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
+	if (!option)
 		return -ENOMEM;
 
+	dma = &option->u.dma;
 	dma->map = map;
 	dma->flags = flags;
 
-	ptr = option->dma;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = dma;
-	else
-		option->dma = dma;
-
-	dev_dbg(&dev->dev, "  dma bitmask %#x flags %#x\n", dma->map,
-		dma->flags);
+	dbg_pnp_show_option(dev, option);
 	return 0;
 }
 
-int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
+int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
 			       resource_size_t min, resource_size_t max,
 			       resource_size_t align, resource_size_t size,
 			       unsigned char flags)
 {
-	struct pnp_port *port, *ptr;
+	struct pnp_option *option;
+	struct pnp_port *port;
 
-	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
-	if (!port)
+	option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
+	if (!option)
 		return -ENOMEM;
 
+	port = &option->u.port;
 	port->min = min;
 	port->max = max;
 	port->align = align;
 	port->size = size;
 	port->flags = flags;
 
-	ptr = option->port;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = port;
-	else
-		option->port = port;
-
-	dev_dbg(&dev->dev, "  io  "
-		"min %#llx max %#llx align %lld size %lld flags %#x\n",
-		(unsigned long long) port->min,
-		(unsigned long long) port->max,
-		(unsigned long long) port->align,
-		(unsigned long long) port->size, port->flags);
+	dbg_pnp_show_option(dev, option);
 	return 0;
 }
 
-int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
+int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
 			      resource_size_t min, resource_size_t max,
 			      resource_size_t align, resource_size_t size,
 			      unsigned char flags)
 {
-	struct pnp_mem *mem, *ptr;
+	struct pnp_option *option;
+	struct pnp_mem *mem;
 
-	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
-	if (!mem)
+	option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
+	if (!option)
 		return -ENOMEM;
 
+	mem = &option->u.mem;
 	mem->min = min;
 	mem->max = max;
 	mem->align = align;
 	mem->size = size;
 	mem->flags = flags;
 
-	ptr = option->mem;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = mem;
-	else
-		option->mem = mem;
-
-	dev_dbg(&dev->dev, "  mem "
-		"min %#llx max %#llx align %lld size %lld flags %#x\n",
-		(unsigned long long) mem->min,
-		(unsigned long long) mem->max,
-		(unsigned long long) mem->align,
-		(unsigned long long) mem->size, mem->flags);
+	dbg_pnp_show_option(dev, option);
 	return 0;
 }
 
-static void pnp_free_port(struct pnp_port *port)
-{
-	struct pnp_port *next;
-
-	while (port) {
-		next = port->next;
-		kfree(port);
-		port = next;
-	}
-}
-
-static void pnp_free_irq(struct pnp_irq *irq)
+void pnp_free_options(struct pnp_dev *dev)
 {
-	struct pnp_irq *next;
-
-	while (irq) {
-		next = irq->next;
-		kfree(irq);
-		irq = next;
-	}
-}
+	struct pnp_option *option, *tmp;
 
-static void pnp_free_dma(struct pnp_dma *dma)
-{
-	struct pnp_dma *next;
-
-	while (dma) {
-		next = dma->next;
-		kfree(dma);
-		dma = next;
-	}
-}
-
-static void pnp_free_mem(struct pnp_mem *mem)
-{
-	struct pnp_mem *next;
-
-	while (mem) {
-		next = mem->next;
-		kfree(mem);
-		mem = next;
-	}
-}
-
-void pnp_free_option(struct pnp_option *option)
-{
-	struct pnp_option *next;
-
-	while (option) {
-		next = option->next;
-		pnp_free_port(option->port);
-		pnp_free_irq(option->irq);
-		pnp_free_dma(option->dma);
-		pnp_free_mem(option->mem);
+	list_for_each_entry_safe(option, tmp, &dev->options, list) {
+		list_del(&option->list);
 		kfree(option);
-		option = next;
 	}
 }
 
@@ -668,66 +546,50 @@ struct pnp_resource *pnp_add_mem_resourc
 	return pnp_res;
 }
 
-static int pnp_possible_option(struct pnp_option *option, int type,
-			       resource_size_t start, resource_size_t size)
+/*
+ * Determine whether the specified resource is a possible configuration
+ * for this device.
+ */
+int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
+			resource_size_t size)
 {
-	struct pnp_option *tmp;
+	struct pnp_option *option;
 	struct pnp_port *port;
 	struct pnp_mem *mem;
 	struct pnp_irq *irq;
 	struct pnp_dma *dma;
 
-	if (!option)
-		return 0;
+	list_for_each_entry(option, &dev->options, list) {
+		if (option->type != type)
+			continue;
 
-	for (tmp = option; tmp; tmp = tmp->next) {
-		switch (type) {
+		switch (option->type) {
 		case IORESOURCE_IO:
-			for (port = tmp->port; port; port = port->next) {
-				if (port->min == start && port->size == size)
-					return 1;
-			}
+			port = &option->u.port;
+			if (port->min == start && port->size == size)
+				return 1;
 			break;
 		case IORESOURCE_MEM:
-			for (mem = tmp->mem; mem; mem = mem->next) {
-				if (mem->min == start && mem->size == size)
-					return 1;
-			}
+			mem = &option->u.mem;
+			if (mem->min == start && mem->size == size)
+				return 1;
 			break;
 		case IORESOURCE_IRQ:
-			for (irq = tmp->irq; irq; irq = irq->next) {
-				if (start < PNP_IRQ_NR &&
-				    test_bit(start, irq->map.bits))
-					return 1;
-			}
+			irq = &option->u.irq;
+			if (start < PNP_IRQ_NR &&
+			    test_bit(start, irq->map.bits))
+				return 1;
 			break;
 		case IORESOURCE_DMA:
-			for (dma = tmp->dma; dma; dma = dma->next) {
-				if (dma->map & (1 << start))
-					return 1;
-			}
+			dma = &option->u.dma;
+			if (dma->map & (1 << start))
+				return 1;
 			break;
 		}
 	}
 
 	return 0;
 }
-
-/*
- * Determine whether the specified resource is a possible configuration
- * for this device.
- */
-int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
-			resource_size_t size)
-{
-	if (pnp_possible_option(dev->independent, type, start, size))
-		return 1;
-
-	if (pnp_possible_option(dev->dependent, type, start, size))
-		return 1;
-
-	return 0;
-}
 EXPORT_SYMBOL(pnp_possible_config);
 
 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
Index: work14/drivers/pnp/support.c
===================================================================
--- work14.orig/drivers/pnp/support.c	2008-06-17 15:52:24.000000000 -0600
+++ work14/drivers/pnp/support.c	2008-06-17 15:52:36.000000000 -0600
@@ -2,6 +2,8 @@
  * support.c - standard functions for the use of pnp protocol drivers
  *
  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  */
 
 #include <linux/module.h>
@@ -110,3 +112,80 @@ void dbg_pnp_show_resources(struct pnp_d
 	}
 #endif
 }
+
+char *pnp_option_priority_name(struct pnp_option *option)
+{
+	switch (pnp_option_priority(option)) {
+	case PNP_RES_PRIORITY_PREFERRED:
+		return "preferred";
+	case PNP_RES_PRIORITY_ACCEPTABLE:
+		return "acceptable";
+	case PNP_RES_PRIORITY_FUNCTIONAL:
+		return "functional";
+	}
+	return "invalid";
+}
+
+void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
+{
+#ifdef DEBUG
+	struct pnp_port *port;
+	struct pnp_mem *mem;
+	struct pnp_irq *irq;
+	struct pnp_dma *dma;
+	int i;
+
+	if (pnp_option_is_dependent(option))
+		dev_dbg(&dev->dev, "  dependent set %d (%s) ",
+			pnp_option_set(option),
+			pnp_option_priority_name(option));
+	else
+		dev_dbg(&dev->dev, "  independent ");
+
+	switch (option->type) {
+	case IORESOURCE_IO:
+		port = &option->u.port;
+		printk("io  min %#llx max %#llx align %lld size %lld flags %#x",
+			(unsigned long long) port->min,
+			(unsigned long long) port->max,
+			(unsigned long long) port->align,
+			(unsigned long long) port->size, port->flags);
+		break;
+	case IORESOURCE_MEM:
+		mem = &option->u.mem;
+		printk("mem min %#llx max %#llx align %lld size %lld flags %#x",
+		       (unsigned long long) mem->min,
+		       (unsigned long long) mem->max,
+		       (unsigned long long) mem->align,
+		       (unsigned long long) mem->size, mem->flags);
+		break;
+	case IORESOURCE_IRQ:
+		irq = &option->u.irq;
+		printk("irq");
+		if (bitmap_empty(irq->map.bits, PNP_IRQ_NR))
+			printk(" <none>");
+		else {
+			for (i = 0; i < PNP_IRQ_NR; i++)
+				if (test_bit(i, irq->map.bits))
+					printk(" %d", i);
+		}
+		printk(" flags %#x", irq->flags);
+		if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
+			printk(" (optional)");
+		break;
+	case IORESOURCE_DMA:
+		dma = &option->u.dma;
+		printk("dma");
+		if (!dma->map)
+			printk(" <none>");
+		else {
+			for (i = 0; i < 8; i++)
+				if (dma->map & (1 << i))
+					printk(" %d", i);
+		}
+		printk(" (bitmask %#x) flags %#x", dma->map, dma->flags);
+		break;
+	}
+	printk("\n");
+#endif
+}
Index: work14/include/linux/pnp.h
===================================================================
--- work14.orig/include/linux/pnp.h	2008-06-17 15:52:19.000000000 -0600
+++ work14/include/linux/pnp.h	2008-06-17 15:52:36.000000000 -0600
@@ -1,6 +1,8 @@
 /*
  * Linux Plug and Play Support
  * Copyright by Adam Belay <ambx1@neo.rr.com>
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  */
 
 #ifndef _LINUX_PNP_H
@@ -249,9 +251,9 @@ struct pnp_dev {
 
 	int active;
 	int capabilities;
-	struct pnp_option *independent;
-	struct pnp_option *dependent;
+	unsigned int num_dependent_sets;
 	struct list_head resources;
+	struct list_head options;
 
 	char name[PNP_NAME_LEN];	/* contains a human-readable name */
 	int flags;			/* used by protocols */

-- 

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

* [patch 27/28] PNP: avoid legacy IDE IRQs
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (25 preceding siblings ...)
  2008-06-17 22:58 ` [patch 26/28] PNP: convert resource options to single linked list Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-18 21:34   ` Bartlomiej Zolnierkiewicz
  2008-06-17 22:58 ` [patch 28/28] PNPACPI: add support for HP vendor-specific CCSR descriptors Bjorn Helgaas
  2008-06-18  0:00 ` [patch 00/28] PNP: convert fixed tables to lists, v3 Len Brown
  28 siblings, 1 reply; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnp-legacy-ide-irq --]
[-- Type: text/plain, Size: 2569 bytes --]

If an IDE controller is in compatibility mode, it expects to use
IRQs 14 and 15, so PNP should avoid them.

This patch should resolve this problem report:
  parallel driver grabs IRQ14 preventing legacy SFF ATA controller from working
  https://bugzilla.novell.com/show_bug.cgi?id=375836

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work14/drivers/pnp/resource.c
===================================================================
--- work14.orig/drivers/pnp/resource.c	2008-06-17 15:52:36.000000000 -0600
+++ work14/drivers/pnp/resource.c	2008-06-17 16:14:18.000000000 -0600
@@ -17,6 +17,7 @@
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/libata.h>
 
 #include <linux/pnp.h>
 #include "base.h"
@@ -286,6 +287,61 @@ static irqreturn_t pnp_test_handler(int 
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_PCI
+static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
+			    unsigned int irq)
+{
+	u32 class;
+	u8 progif;
+
+	if (pci->irq == irq) {
+		dev_dbg(&pnp->dev, "device %s using irq %d\n",
+			pci_name(pci), irq);
+		return 1;
+	}
+
+	/*
+	 * See pci_setup_device() and ata_pci_sff_activate_host() for
+	 * similar IDE legacy detection.
+	 */
+	pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
+	class >>= 8;		/* discard revision ID */
+	progif = class & 0xff;
+	class >>= 8;
+
+	if (class == PCI_CLASS_STORAGE_IDE) {
+		/*
+		 * Unless both channels are native-PCI mode only,
+		 * treat the compatibility IRQs as busy.
+		 */
+		if ((progif & 0x5) != 0x5)
+			if (ATA_PRIMARY_IRQ(pci) == irq ||
+			    ATA_SECONDARY_IRQ(pci) == irq) {
+				dev_dbg(&pnp->dev, "legacy IDE device %s "
+					"using irq %d\n", pci_name(pci), irq);
+				return 1;
+			}
+	}
+
+	return 0;
+}
+#endif
+
+static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
+{
+#ifdef CONFIG_PCI
+	struct pci_dev *pci = NULL;
+
+	for_each_pci_dev(pci) {
+		if (pci_dev_uses_irq(pnp, pci, irq)) {
+			pci_dev_put(pci);
+			return 1;
+		}
+	}
+#endif
+	return 0;
+}
+
 int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
 {
 	int i;
@@ -317,18 +373,9 @@ int pnp_check_irq(struct pnp_dev *dev, s
 		}
 	}
 
-#ifdef CONFIG_PCI
 	/* check if the resource is being used by a pci device */
-	{
-		struct pci_dev *pci = NULL;
-		for_each_pci_dev(pci) {
-			if (pci->irq == *irq) {
-				pci_dev_put(pci);
-				return 0;
-			}
-		}
-	}
-#endif
+	if (pci_uses_irq(dev, *irq))
+		return 0;
 
 	/* check if the resource is already in use, skip if the
 	 * device is active because it itself may be in use */

-- 

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

* [patch 28/28] PNPACPI: add support for HP vendor-specific CCSR descriptors
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (26 preceding siblings ...)
  2008-06-17 22:58 ` [patch 27/28] PNP: avoid legacy IDE IRQs Bjorn Helgaas
@ 2008-06-17 22:58 ` Bjorn Helgaas
  2008-06-18  0:00 ` [patch 00/28] PNP: convert fixed tables to lists, v3 Len Brown
  28 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-17 22:58 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

[-- Attachment #1: pnpacpi-hp-vendor-descriptor --]
[-- Type: text/plain, Size: 3744 bytes --]

The HP CCSR descriptor describes MMIO address space that should appear
as a MEM resource.  This patch adds support for parsing these descriptors
in the _CRS data.

The visible effect of this is that these MEM resources will appear
in /sys/devices/pnp0/.../resources, which means that "lspnp -v" will
report it, user applications can use this to locate device CSR space,
and kernel drivers can use the normal PNP resource accessors to
locate them.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work14/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work14.orig/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 15:52:36.000000000 -0600
+++ work14/drivers/pnp/pnpacpi/rsparser.c	2008-06-17 16:37:40.000000000 -0600
@@ -3,6 +3,8 @@
  *
  * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
  * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -187,6 +189,61 @@ static void pnpacpi_parse_allocated_iore
 	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
+ * marked as "consumer-only," but old versions of Windows and Linux ignore
+ * the producer/consumer flag, so HP invented a vendor-defined resource to
+ * describe the location and size of CSR space.
+ */
+static struct acpi_vendor_uuid hp_ccsr_uuid = {
+	.subtype = 2,
+	.data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
+	    0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
+};
+
+static int vendor_resource_matches(struct pnp_dev *dev,
+				   struct acpi_resource_vendor_typed *vendor,
+				   struct acpi_vendor_uuid *match,
+				   int expected_len)
+{
+	int uuid_len = sizeof(vendor->uuid);
+	u8 uuid_subtype = vendor->uuid_subtype;
+	u8 *uuid = vendor->uuid;
+	int actual_len;
+
+	/* byte_length includes uuid_subtype and uuid */
+	actual_len = vendor->byte_length - uuid_len - 1;
+
+	if (uuid_subtype == match->subtype &&
+	    uuid_len == sizeof(match->data) &&
+	    memcmp(uuid, match->data, uuid_len) == 0) {
+		if (expected_len && expected_len != actual_len) {
+			dev_err(&dev->dev, "wrong vendor descriptor size; "
+				"expected %d, found %d bytes\n",
+				expected_len, actual_len);
+			return 0;
+		}
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
+				    struct acpi_resource_vendor_typed *vendor)
+{
+	if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
+		u64 start, length;
+
+		memcpy(&start, vendor->byte_data, sizeof(start));
+		memcpy(&length, vendor->byte_data + 8, sizeof(length));
+
+		pnp_add_mem_resource(dev, start, start + length - 1, 0);
+	}
+}
+
 static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
 						u64 start, u64 len,
 						int write_protect)
@@ -237,6 +294,7 @@ static acpi_status pnpacpi_allocated_res
 	struct acpi_resource_dma *dma;
 	struct acpi_resource_io *io;
 	struct acpi_resource_fixed_io *fixed_io;
+	struct acpi_resource_vendor_typed *vendor_typed;
 	struct acpi_resource_memory24 *memory24;
 	struct acpi_resource_memory32 *memory32;
 	struct acpi_resource_fixed_memory32 *fixed_memory32;
@@ -306,6 +364,8 @@ static acpi_status pnpacpi_allocated_res
 		break;
 
 	case ACPI_RESOURCE_TYPE_VENDOR:
+		vendor_typed = &res->data.vendor_typed;
+		pnpacpi_parse_allocated_vendor(dev, vendor_typed);
 		break;
 
 	case ACPI_RESOURCE_TYPE_END_TAG:

-- 

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

* Re: [patch 00/28] PNP: convert fixed tables to lists, v3
  2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
                   ` (27 preceding siblings ...)
  2008-06-17 22:58 ` [patch 28/28] PNPACPI: add support for HP vendor-specific CCSR descriptors Bjorn Helgaas
@ 2008-06-18  0:00 ` Len Brown
  28 siblings, 0 replies; 32+ messages in thread
From: Len Brown @ 2008-06-18  0:00 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby

thanks for the update, bjorn.

it applied cleanly to top of linus' tree,
built cleanly and booted cleanly -- no unexplained dmesg diffs.

there are a couple of checkpatch.pl warnings -- i'll look
at those after the celtics.

cheers,
-len


On Tue, 17 Jun 2008, Bjorn Helgaas wrote:

> This patch series contains all my PNP patches that are not yet in Linus'
> tree, including both the "convert resource table to dynamic list" series
> and the "convert resource options to unified dynamic list" series.
> 
> This series should replace all the PNP patches in -mm from
>     pnp-add-detail-to-debug-resource-dump.patch
>     ...
>     not-for-merging-pnp-changes-suspend-oops.patch
> except for isa-set-24-bit-dma_mask-for-isa-devices.patch, which got
> stuck in the middle but isn't really PNP-related.
> 
> I'll be on vacation for the rest of the week, so I won't be able to
> respond to any issues until Monday.
> 
> Here are the significant changes since the last posting:
> 
>     - When replacing pnp_resource_table, the PNPACPI resource encoders
>       have to explicitly handle disabled resources; previously any
>       unused slots in the table were implicitly disabled.  This should
>       fix Jiri Slaby's oops on suspend/resume (though he hasn't tested
>       this version).
>       
>       This change is in the patch titled "PNP: replace pnp_resource_table
>       with dynamically allocated resources".
>       
>     - Added a new patch to keep disabled IRQ and DMA resources when parsing
>       current config.  This fixes a bug in the current (2.6.25) PNPACPI
>       code: consider a device with (mem, irq0, irq1, io), where irq0 is
>       disabled.  If we drop irq0 when parsing the _CRS, we will mistakenly
>       put irq1 in the irq0 slot when we encode resources for an _SRS call.
> 
>     - Added a new patch to avoid interrupts used by an IDE controller in
>       compatibility mode.  https://bugzilla.novell.com/show_bug.cgi?id=375836
> 
>     - Added a new PNPACPI patch to support HP vendor-specific descriptors.
>       This has long been supported by arch/ia64/kernel/acpi-ext.c, which
>       provides an hp_acpi_csr_space() interface, but I think it's better
>       and more generic to support it in PNPACPI.
> 
> Changes since v2 of "convert resource options to unified dynamic list":
> 
>     - fixed bisection problem in quirk_ad1815_mpu_resources()
>     - fixed checkpatch warning in pnp_show_options()
>       (pnp-convert-resource-options-to-single-linked-list-checkpatch-fixes.patch)
>     - replaced pnp_independent_option() with literal 0
>     - fixed coding style in pnp/manager.c
>     - added EXPORT_SYMBOL(pnp_possible_config)
>       (pnp-add-pnp_possible_config-can-a-device-could-be-configured-this-way-fix.patch)
> 
> Bjorn
> -- 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [patch 27/28] PNP: avoid legacy IDE IRQs
  2008-06-17 22:58 ` [patch 27/28] PNP: avoid legacy IDE IRQs Bjorn Helgaas
@ 2008-06-18 21:34   ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 32+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-06-18 21:34 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Len Brown, linux-acpi, linux-kernel, Adam Belay, Adam M Belay,
	Li Shaohua, Matthieu Castet, Thomas Renninger, Rene Herman,
	Jaroslav Kysela, Andrew Morton, Takashi Iwai, Jiri Slaby,
	Jeff Garzik


Hi,

On Wednesday 18 June 2008, Bjorn Helgaas wrote:
> If an IDE controller is in compatibility mode, it expects to use
> IRQs 14 and 15, so PNP should avoid them.
> 
> This patch should resolve this problem report:
>   parallel driver grabs IRQ14 preventing legacy SFF ATA controller from working
>   https://bugzilla.novell.com/show_bug.cgi?id=375836
> 
> Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
> 
> Index: work14/drivers/pnp/resource.c
> ===================================================================
> --- work14.orig/drivers/pnp/resource.c	2008-06-17 15:52:36.000000000 -0600
> +++ work14/drivers/pnp/resource.c	2008-06-17 16:14:18.000000000 -0600
> @@ -17,6 +17,7 @@
>  #include <linux/pci.h>
>  #include <linux/ioport.h>
>  #include <linux/init.h>
> +#include <linux/libata.h>

this include is for libata only AFAIK

[ I added Jeff to cc: ]

>  #include <linux/pnp.h>
>  #include "base.h"
> @@ -286,6 +287,61 @@ static irqreturn_t pnp_test_handler(int 
>  	return IRQ_HANDLED;
>  }
>  
> +#ifdef CONFIG_PCI
> +static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
> +			    unsigned int irq)
> +{
> +	u32 class;
> +	u8 progif;
> +
> +	if (pci->irq == irq) {
> +		dev_dbg(&pnp->dev, "device %s using irq %d\n",
> +			pci_name(pci), irq);
> +		return 1;
> +	}
> +
> +	/*
> +	 * See pci_setup_device() and ata_pci_sff_activate_host() for
> +	 * similar IDE legacy detection.
> +	 */
> +	pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
> +	class >>= 8;		/* discard revision ID */
> +	progif = class & 0xff;
> +	class >>= 8;
> +
> +	if (class == PCI_CLASS_STORAGE_IDE) {
> +		/*
> +		 * Unless both channels are native-PCI mode only,
> +		 * treat the compatibility IRQs as busy.
> +		 */
> +		if ((progif & 0x5) != 0x5)
> +			if (ATA_PRIMARY_IRQ(pci) == irq ||
> +			    ATA_SECONDARY_IRQ(pci) == irq) {

ATA_*_IRQ are libata specific (+ it looks like they should be removed),
please use pci_get_legacy_ide_irq(dev, channel) instead.

Thanks,
Bart

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

* [patch 27/28] PNP: avoid legacy IDE IRQs
  2008-06-27 22:56 [patch 00/28] PNP: convert fixed tables to lists, v4 Bjorn Helgaas
@ 2008-06-27 22:57 ` Bjorn Helgaas
  0 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2008-06-27 22:57 UTC (permalink / raw)
  To: Len Brown, Andi Kleen
  Cc: linux-acpi, linux-kernel, Adam Belay, Adam M Belay, Li Shaohua,
	Matthieu Castet, Thomas Renninger, Rene Herman, Jaroslav Kysela,
	Andrew Morton, Takashi Iwai, Jiri Slaby, David Howells,
	Bartlomiej Zolnierkiewicz

[-- Attachment #1: pnp-legacy-ide-irq --]
[-- Type: text/plain, Size: 2421 bytes --]

If an IDE controller is in compatibility mode, it expects to use
IRQs 14 and 15, so PNP should avoid them.

This patch should resolve this problem report:
  parallel driver grabs IRQ14 preventing legacy SFF ATA controller from working
  https://bugzilla.novell.com/show_bug.cgi?id=375836

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work14/drivers/pnp/resource.c
===================================================================
--- work14.orig/drivers/pnp/resource.c	2008-06-17 16:40:04.000000000 -0600
+++ work14/drivers/pnp/resource.c	2008-06-24 15:39:08.000000000 -0600
@@ -286,6 +286,61 @@ static irqreturn_t pnp_test_handler(int 
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_PCI
+static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
+			    unsigned int irq)
+{
+	u32 class;
+	u8 progif;
+
+	if (pci->irq == irq) {
+		dev_dbg(&pnp->dev, "device %s using irq %d\n",
+			pci_name(pci), irq);
+		return 1;
+	}
+
+	/*
+	 * See pci_setup_device() and ata_pci_sff_activate_host() for
+	 * similar IDE legacy detection.
+	 */
+	pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
+	class >>= 8;		/* discard revision ID */
+	progif = class & 0xff;
+	class >>= 8;
+
+	if (class == PCI_CLASS_STORAGE_IDE) {
+		/*
+		 * Unless both channels are native-PCI mode only,
+		 * treat the compatibility IRQs as busy.
+		 */
+		if ((progif & 0x5) != 0x5)
+			if (pci_get_legacy_ide_irq(pci, 0) == irq ||
+			    pci_get_legacy_ide_irq(pci, 1) == irq) {
+				dev_dbg(&pnp->dev, "legacy IDE device %s "
+					"using irq %d\n", pci_name(pci), irq);
+				return 1;
+			}
+	}
+
+	return 0;
+}
+#endif
+
+static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
+{
+#ifdef CONFIG_PCI
+	struct pci_dev *pci = NULL;
+
+	for_each_pci_dev(pci) {
+		if (pci_dev_uses_irq(pnp, pci, irq)) {
+			pci_dev_put(pci);
+			return 1;
+		}
+	}
+#endif
+	return 0;
+}
+
 int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
 {
 	int i;
@@ -317,18 +372,9 @@ int pnp_check_irq(struct pnp_dev *dev, s
 		}
 	}
 
-#ifdef CONFIG_PCI
 	/* check if the resource is being used by a pci device */
-	{
-		struct pci_dev *pci = NULL;
-		for_each_pci_dev(pci) {
-			if (pci->irq == *irq) {
-				pci_dev_put(pci);
-				return 0;
-			}
-		}
-	}
-#endif
+	if (pci_uses_irq(dev, *irq))
+		return 0;
 
 	/* check if the resource is already in use, skip if the
 	 * device is active because it itself may be in use */

-- 

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

end of thread, other threads:[~2008-06-27 23:12 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-17 22:58 [patch 00/28] PNP: convert fixed tables to lists, v3 Bjorn Helgaas
2008-06-17 22:58 ` [patch 01/28] PNP: add detail to debug resource dump Bjorn Helgaas
2008-06-17 22:58 ` [patch 02/28] PNP: remove pnp_resource.index Bjorn Helgaas
2008-06-17 22:58 ` [patch 03/28] PNP: add pnp_resource_type() internal interface Bjorn Helgaas
2008-06-17 22:58 ` [patch 04/28] PNP: add pnp_resource_type_name() helper function Bjorn Helgaas
2008-06-17 22:58 ` [patch 05/28] PNP: make pnp_{port,mem,etc}_start(), et al work for invalid resources Bjorn Helgaas
2008-06-17 22:58 ` [patch 06/28] PNP: replace pnp_resource_table with dynamically allocated resources Bjorn Helgaas
2008-06-17 22:58 ` [patch 07/28] PNPACPI: keep disabled resources when parsing current config Bjorn Helgaas
2008-06-17 22:58 ` [patch 08/28] PNP: remove ratelimit on add resource failures Bjorn Helgaas
2008-06-17 22:58 ` [patch 09/28] PNP: dont sort by type in /sys/.../resources Bjorn Helgaas
2008-06-17 22:58 ` [patch 10/28] PNP: add pnp_possible_config() -- can a device could be configured this way? Bjorn Helgaas
2008-06-17 22:58 ` [patch 11/28] PNP: whitespace/coding style fixes Bjorn Helgaas
2008-06-17 22:58 ` [patch 12/28] PNP: define PNP-specific IORESOURCE_IO_* flags alongside IRQ, DMA, MEM Bjorn Helgaas
2008-06-17 22:58 ` [patch 13/28] PNP: make resource option structures private to PNP subsystem Bjorn Helgaas
2008-06-17 22:58 ` [patch 14/28] PNP: introduce pnp_irq_mask_t typedef Bjorn Helgaas
2008-06-17 22:58 ` [patch 15/28] PNP: increase I/O port & memory option address sizes Bjorn Helgaas
2008-06-17 22:58 ` [patch 16/28] PNP: improve resource assignment debug Bjorn Helgaas
2008-06-17 22:58 ` [patch 17/28] PNP: in debug resource dump, make empty list obvious Bjorn Helgaas
2008-06-17 22:58 ` [patch 18/28] PNP: make resource assignment functions return 0 (success) or -EBUSY (failure) Bjorn Helgaas
2008-06-17 22:58 ` [patch 19/28] PNP: remove redundant pnp_can_configure() check Bjorn Helgaas
2008-06-17 22:58 ` [patch 20/28] PNP: centralize resource option allocations Bjorn Helgaas
2008-06-17 22:58 ` [patch 21/28] PNPACPI: ignore _PRS interrupt numbers larger than PNP_IRQ_NR Bjorn Helgaas
2008-06-17 22:58 ` [patch 22/28] PNP: rename pnp_register_*_resource() local variables Bjorn Helgaas
2008-06-17 22:58 ` [patch 23/28] PNP: support optional IRQ resources Bjorn Helgaas
2008-06-17 22:58 ` [patch 24/28] PNP: remove extra 0x100 bit from option priority Bjorn Helgaas
2008-06-17 22:58 ` [patch 25/28] ISAPNP: handle independent options following dependent ones Bjorn Helgaas
2008-06-17 22:58 ` [patch 26/28] PNP: convert resource options to single linked list Bjorn Helgaas
2008-06-17 22:58 ` [patch 27/28] PNP: avoid legacy IDE IRQs Bjorn Helgaas
2008-06-18 21:34   ` Bartlomiej Zolnierkiewicz
2008-06-17 22:58 ` [patch 28/28] PNPACPI: add support for HP vendor-specific CCSR descriptors Bjorn Helgaas
2008-06-18  0:00 ` [patch 00/28] PNP: convert fixed tables to lists, v3 Len Brown
  -- strict thread matches above, loose matches on Subject: below --
2008-06-27 22:56 [patch 00/28] PNP: convert fixed tables to lists, v4 Bjorn Helgaas
2008-06-27 22:57 ` [patch 27/28] PNP: avoid legacy IDE IRQs Bjorn Helgaas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox