public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations
@ 2007-07-16 14:21 Thomas Renninger
  2007-07-16 16:48 ` Jean Delvare
  2007-07-17 15:49 ` Bjorn Helgaas
  0 siblings, 2 replies; 6+ messages in thread
From: Thomas Renninger @ 2007-07-16 14:21 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-acpi, Bjorn Helgaas, Alexey Starikovskiy, Jean Delvare,
	Bernhard Walle

PNP0C02 devices normally have a lot more IO port declarations than
currently defined in PNP_MAX_PORT

For checking, have a look at your disassembled DSDT, and look out for
the _CRS function (and/or a ResourceTemplate often called CRS).

Here an  example:
IO (Decode16,0x0010,             // Range Minimum
             0x0010,             // Range Maximum
             0x00,               // Alignment
             0x10,               // Length
)
IO (Decode16,
             0x0022,             // Range Minimum
             0x0022,             // Range Maximum
             0x00,               // Alignment
             0x1E,               // Length
)
...
IO (Decode16,
             0x0000,             // Range Minimum
             0x0000,             // Range Maximum
             0x00,               // Alignment
             0x00,               // Length
_Y06)
IO (Decode16,
             0x0000,             // Range Minimum
             0x0000,             // Range Maximum
             0x00,               // Alignment
             0x00,               // Length
_Y07)

The latter zeroed (_Y07) declarations are filled with dynamic values in
_CRS and also need an PNP IO port reserved.

On this machine (x86_64 workstation) more then 20 IO resource
declarations exist for one PNP0C02 device.
It could be that the suggested 32 is still not big enough.

Most of the ports are below 0x100, which get ignored by the pnp layer
anyways (cmp. with drivers/pnp/system.c:reserve_resources_of_dev() ).
These could already be ignore in
drivers/pnp/pnpacpi/rsparser.c:pnpacpi_parse_allocated_ioresource()
not filling up PNP_MAX_PORTs, but this is not that nice and probably
will get reverted at some later point when standard PC hardware (below
0x100, pics, kbd, timer, dma, ...) also gets requested by ACPI
sublayers.


I also wonder whether other limits like:
 #define PNP_MAX_MEM        4
 #define PNP_MAX_IRQ        2
 #define PNP_MAX_DMA        2
could get exceeded with pnpacpi?

I don't know what the theoretical max for ports on one device is, but
IMO the static array should get something dynamically allocated?

Something like:

+++ linux-2.6.22.1/include/linux/pnp.h
@@ -14,7 +14,7 @@
-#define PNP_MAX_PORT           8
+#define PNP_MAX_PORT           256

 struct pnp_resource_table {
-       struct resource port_resource[PNP_MAX_PORT];
+       struct resource *port_resource[PNP_MAX_PORT];
        struct resource mem_resource[PNP_MAX_MEM];

or
-       struct resource port_resource[PNP_MAX_PORT];
+       struct resource **port_resource;

and then k(z)alloc the resource structs...

BTW: This was the reason why:
  50e0-50ef : amd756_smbus
got not reserved on the patch:
"Identify native drivers and ACPI subsystem accessing the same
resources"
I sent some days ago. In 2.6.18 it seems this got handled (correctly) by
/drivers/acpi/motherboard which got replaced with pnpacpi system driver.

This would be the less intrusive short term fix:

------------------

Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations

Also print a message if PNP_DEBUG is set if we run out of PNP_MAX_PORTS.

Signed-off-by: Thomas Renninger <trenn@suse.de>

---
 drivers/pnp/pnpacpi/rsparser.c |    3 ++-
 include/linux/pnp.h            |    2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

Index: linux-2.6.22.1/include/linux/pnp.h
===================================================================
--- linux-2.6.22.1.orig/include/linux/pnp.h
+++ linux-2.6.22.1/include/linux/pnp.h
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/mod_devicetable.h>
 
-#define PNP_MAX_PORT		8
+#define PNP_MAX_PORT		32
 #define PNP_MAX_MEM		4
 #define PNP_MAX_IRQ		2
 #define PNP_MAX_DMA		2
Index: linux-2.6.22.1/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux-2.6.22.1/drivers/pnp/pnpacpi/rsparser.c
@@ -185,7 +185,8 @@ pnpacpi_parse_allocated_ioresource(struc
 		}
 		res->port_resource[i].start = io;
 		res->port_resource[i].end = io + len - 1;
-	}
+	} else
+		pnp_dbg("Run out of pnp ports - MAX_PNP_PORT must be increased");
 }
 
 static void




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

* Re: [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations
  2007-07-16 14:21 [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations Thomas Renninger
@ 2007-07-16 16:48 ` Jean Delvare
  2007-07-17 15:49 ` Bjorn Helgaas
  1 sibling, 0 replies; 6+ messages in thread
From: Jean Delvare @ 2007-07-16 16:48 UTC (permalink / raw)
  To: Thomas Renninger
  Cc: linux-kernel, linux-acpi, Bjorn Helgaas, Alexey Starikovskiy,
	Bernhard Walle

Hi Thomas,

On Mon, 16 Jul 2007 16:21:07 +0200, Thomas Renninger wrote:
> PNP0C02 devices normally have a lot more IO port declarations than
> currently defined in PNP_MAX_PORT
> 
> For checking, have a look at your disassembled DSDT, and look out for
> the _CRS function (and/or a ResourceTemplate often called CRS).
> 
> Here an  example:
> IO (Decode16,0x0010,             // Range Minimum
>              0x0010,             // Range Maximum
>              0x00,               // Alignment
>              0x10,               // Length
> )
> IO (Decode16,
>              0x0022,             // Range Minimum
>              0x0022,             // Range Maximum
>              0x00,               // Alignment
>              0x1E,               // Length
> )
> ...
> IO (Decode16,
>              0x0000,             // Range Minimum
>              0x0000,             // Range Maximum
>              0x00,               // Alignment
>              0x00,               // Length
> _Y06)
> IO (Decode16,
>              0x0000,             // Range Minimum
>              0x0000,             // Range Maximum
>              0x00,               // Alignment
>              0x00,               // Length
> _Y07)
> 
> The latter zeroed (_Y07) declarations are filled with dynamic values in
> _CRS and also need an PNP IO port reserved.
> 
> On this machine (x86_64 workstation) more then 20 IO resource
> declarations exist for one PNP0C02 device.
> It could be that the suggested 32 is still not big enough.

I just tested on my own workstation, and 8 wasn't enough for me either:
there are 12 resources listed for the PNP0C02 device on my workstation.

After applying your patch, I get the following differences in /proc/ioports:

--- ioports.before      2007-07-16 18:29:30.000000000 +0200
+++ ioports.after       2007-07-16 18:39:05.000000000 +0200
@@ -13,7 +13,8 @@
 01f0-01f7 : 0000:00:0f.0
   01f0-01f7 : ide0
 0290-0297 : f71805f
-  0295-0296 : f71805f
+  0290-0297 : pnp 00:03
+    0295-0296 : f71805f
 0376-0376 : 0000:00:0f.0
   0376-0376 : ide1
 0378-037a : parport0
@@ -21,6 +22,8 @@
 03f6-03f6 : 0000:00:0f.0
   03f6-03f6 : ide0
 03f8-03ff : serial
+04d0-04d1 : pnp 00:03
+0800-0805 : pnp 00:03
 0cf8-0cff : PCI conf1
 4000-407f : pnp 00:02
   4000-4003 : ACPI PM1a_EVT_BLK

> (...)
> ------------------
> 
> Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations
> 
> Also print a message if PNP_DEBUG is set if we run out of PNP_MAX_PORTS.
> 
> Signed-off-by: Thomas Renninger <trenn@suse.de>
> 
> ---
>  drivers/pnp/pnpacpi/rsparser.c |    3 ++-
>  include/linux/pnp.h            |    2 +-
>  2 files changed, 3 insertions(+), 2 deletions(-)
> 
> Index: linux-2.6.22.1/include/linux/pnp.h
> ===================================================================
> --- linux-2.6.22.1.orig/include/linux/pnp.h
> +++ linux-2.6.22.1/include/linux/pnp.h
> @@ -14,7 +14,7 @@
>  #include <linux/errno.h>
>  #include <linux/mod_devicetable.h>
>  
> -#define PNP_MAX_PORT		8
> +#define PNP_MAX_PORT		32
>  #define PNP_MAX_MEM		4
>  #define PNP_MAX_IRQ		2
>  #define PNP_MAX_DMA		2
> Index: linux-2.6.22.1/drivers/pnp/pnpacpi/rsparser.c
> ===================================================================
> --- linux-2.6.22.1.orig/drivers/pnp/pnpacpi/rsparser.c
> +++ linux-2.6.22.1/drivers/pnp/pnpacpi/rsparser.c
> @@ -185,7 +185,8 @@ pnpacpi_parse_allocated_ioresource(struc
>  		}
>  		res->port_resource[i].start = io;
>  		res->port_resource[i].end = io + len - 1;
> -	}
> +	} else
> +		pnp_dbg("Run out of pnp ports - MAX_PNP_PORT must be increased");

PNP_MAX_PORT, not MAX_PNP_PORT.

>  }
>  
>  static void

I like this patch and I'd like to see it upstream soon. I think it can
even be improved:

* If we run out of pnp ports, we should print an error message rather
than a debug message. If it takes CONFIG_PNP_DEBUG=y to get reports
that the max is too low, we won't have many reports.

* Can we have similar messages for PNP_MAX_MEM, PNP_MAX_IRQ and
PNP_MAX_DMA? I think that we really want to know when we hit limits for
these too.

Thanks,
-- 
Jean Delvare

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

* Re: [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations
  2007-07-16 14:21 [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations Thomas Renninger
  2007-07-16 16:48 ` Jean Delvare
@ 2007-07-17 15:49 ` Bjorn Helgaas
  2007-07-18  8:21   ` Thomas Renninger
  1 sibling, 1 reply; 6+ messages in thread
From: Bjorn Helgaas @ 2007-07-17 15:49 UTC (permalink / raw)
  To: trenn
  Cc: linux-kernel, linux-acpi, Alexey Starikovskiy, Jean Delvare,
	Bernhard Walle

On Monday 16 July 2007 08:21:07 am Thomas Renninger wrote:
> PNP0C02 devices normally have a lot more IO port declarations than
> currently defined in PNP_MAX_PORT

Yes.

> I also wonder whether other limits like:
>  #define PNP_MAX_MEM        4
>  #define PNP_MAX_IRQ        2
>  #define PNP_MAX_DMA        2
> could get exceeded with pnpacpi?

Definitely.  I think the current limits come from the PNP ISA spec
(sec 4.6).  I don't see similar limits in the PNPBIOS or ACPI specs,
so ideally I think they should be dynamically allocated as you suggest.

HPET devices often use more than two IRQs, so I worked up the following
patch a while ago.  I didn't post it because Adam had plans for a better
fix.  But I suspect he's otherwise occupied now :-)

It doesn't change PNP_MAX_PORT, so that would have to be updated.




PNP: increase number of resources devices can use

PNPACPI and PNPBIOS devices can use more than 2 IRQs, so bump PNP_MAX_IRQ
from 2 to 4.  For example, HPET devices can have up to 32 timers, each with
an IRQ.  (Current HPETs typically have 3 timers.)

Add ISAPNP_MAX_PORT, ISAPNP_MAX_MEM, ISAPNP_MAX_IRQ, and ISAPNP_MAX_DMA
because ISAPNP does limit the number of resources a device can use.

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

Index: work-mm1/drivers/pnp/isapnp/core.c
===================================================================
--- work-mm1.orig/drivers/pnp/isapnp/core.c	2005-08-09 10:07:45.000000000 -0600
+++ work-mm1/drivers/pnp/isapnp/core.c	2005-08-09 14:03:03.000000000 -0600
@@ -950,28 +950,28 @@
 
 	dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
 	if (dev->active) {
-		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
+		for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
 			ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
 			if (!ret)
 				continue;
 			res->port_resource[tmp].start = ret;
 			res->port_resource[tmp].flags = IORESOURCE_IO;
 		}
-		for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
+		for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
 			ret = isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8;
 			if (!ret)
 				continue;
 			res->mem_resource[tmp].start = ret;
 			res->mem_resource[tmp].flags = IORESOURCE_MEM;
 		}
-		for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
+		for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
 			ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8);
 			if (!ret)
 				continue;
 			res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret;
 			res->irq_resource[tmp].flags = IORESOURCE_IRQ;
 		}
-		for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
+		for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
 			ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
 			if (ret == 4)
 				continue;
@@ -998,17 +998,17 @@
 
 	isapnp_cfg_begin(dev->card->number, dev->number);
 	dev->active = 1;
-	for (tmp = 0; tmp < PNP_MAX_PORT && (res->port_resource[tmp].flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; tmp++)
+	for (tmp = 0; tmp < ISAPNP_MAX_PORT && (res->port_resource[tmp].flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; tmp++)
 		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), res->port_resource[tmp].start);
-	for (tmp = 0; tmp < PNP_MAX_IRQ && (res->irq_resource[tmp].flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; tmp++) {
+	for (tmp = 0; tmp < ISAPNP_MAX_IRQ && (res->irq_resource[tmp].flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; tmp++) {
 		int irq = res->irq_resource[tmp].start;
 		if (irq == 2)
 			irq = 9;
 		isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);
 	}
-	for (tmp = 0; tmp < PNP_MAX_DMA && (res->dma_resource[tmp].flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; tmp++)
+	for (tmp = 0; tmp < ISAPNP_MAX_DMA && (res->dma_resource[tmp].flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; tmp++)
 		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, res->dma_resource[tmp].start);
-	for (tmp = 0; tmp < PNP_MAX_MEM && (res->mem_resource[tmp].flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; tmp++)
+	for (tmp = 0; tmp < ISAPNP_MAX_MEM && (res->mem_resource[tmp].flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; tmp++)
 		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<3), (res->mem_resource[tmp].start >> 8) & 0xffff);
 	/* FIXME: We aren't handling 32bit mems properly here */
 	isapnp_activate(dev->number);
Index: work-mm1/include/linux/isapnp.h
===================================================================
--- work-mm1.orig/include/linux/isapnp.h	2005-06-17 13:48:29.000000000 -0600
+++ work-mm1/include/linux/isapnp.h	2005-08-09 14:35:31.000000000 -0600
@@ -24,6 +24,7 @@
 
 #include <linux/config.h>
 #include <linux/errno.h>
+#include <linux/kernel.h>
 #include <linux/pnp.h>
 
 /*
@@ -36,6 +37,11 @@
 #define ISAPNP_CFG_IRQ			0x70	/* 2 * word */
 #define ISAPNP_CFG_DMA			0x74	/* 2 * byte */
 
+#define ISAPNP_MAX_PORT			min(8, PNP_MAX_PORT)
+#define ISAPNP_MAX_MEM			min(4, PNP_MAX_MEM)
+#define ISAPNP_MAX_IRQ			min(2, PNP_MAX_IRQ)
+#define ISAPNP_MAX_DMA			min(2, PNP_MAX_DMA)
+
 /*
  *
  */
Index: work-mm1/include/linux/pnp.h
===================================================================
--- work-mm1.orig/include/linux/pnp.h	2005-08-09 10:07:46.000000000 -0600
+++ work-mm1/include/linux/pnp.h	2005-08-09 14:01:08.000000000 -0600
@@ -16,7 +16,7 @@
 
 #define PNP_MAX_PORT		8
 #define PNP_MAX_MEM		4
-#define PNP_MAX_IRQ		2
+#define PNP_MAX_IRQ		4
 #define PNP_MAX_DMA		2
 #define PNP_NAME_LEN		50
 
Index: work-mm1/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- work-mm1.orig/drivers/pnp/pnpacpi/rsparser.c	2005-08-09 10:07:45.000000000 -0600
+++ work-mm1/drivers/pnp/pnpacpi/rsparser.c	2005-08-09 14:29:59.000000000 -0600
@@ -72,6 +72,10 @@
 	}
 }
 
+/*
+ * ACPI doesn't limit the number of resources a device can use, so
+ * we can use the generic PNP limits (PNP_MAX_IRQ, etc).
+ */
 static void
 pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
 	int edge_level, int active_high_low)
Index: work-mm1/drivers/pnp/pnpbios/rsparser.c
===================================================================
--- work-mm1.orig/drivers/pnp/pnpbios/rsparser.c	2005-08-09 10:07:45.000000000 -0600
+++ work-mm1/drivers/pnp/pnpbios/rsparser.c	2005-08-09 14:29:37.000000000 -0600
@@ -51,6 +51,10 @@
  * Allocated Resources
  */
 
+/*
+ * PNPBIOS doesn't limit the number of resources a device can use, so
+ * we can use the generic PNP limits (PNP_MAX_IRQ, etc).
+ */
 static void
 pnpbios_parse_allocated_irqresource(struct pnp_resource_table * res, int irq)
 {

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

* Re: [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations
  2007-07-17 15:49 ` Bjorn Helgaas
@ 2007-07-18  8:21   ` Thomas Renninger
  2007-07-18 21:33     ` Bjorn Helgaas
  0 siblings, 1 reply; 6+ messages in thread
From: Thomas Renninger @ 2007-07-18  8:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-kernel, linux-acpi, Alexey Starikovskiy, Jean Delvare,
	Bernhard Walle

On Tue, 2007-07-17 at 09:49 -0600, Bjorn Helgaas wrote:
> On Monday 16 July 2007 08:21:07 am Thomas Renninger wrote:
> > PNP0C02 devices normally have a lot more IO port declarations than
> > currently defined in PNP_MAX_PORT
> 
> Yes.
> 
> > I also wonder whether other limits like:
> >  #define PNP_MAX_MEM        4
> >  #define PNP_MAX_IRQ        2
> >  #define PNP_MAX_DMA        2
> > could get exceeded with pnpacpi?
> 
> Definitely.  I think the current limits come from the PNP ISA spec
> (sec 4.6).  I don't see similar limits in the PNPBIOS or ACPI specs,
> so ideally I think they should be dynamically allocated as you suggest.
> 
I wanted to implement the dynamic approach and used a dynamically
allocated array, filled up from beginning. While this is close to the
current implementation I thought this is the easiest sufficient way...
(I also only did this for io ports where most mem is wasted).
Now I am thinking about hotplug (e.g. if a SSDT with resources gets
hot-added, removed)... If a device can vanish, the array must get
reordered, not a really well fitting structure, a list (a pnp specific
set up, or from include/linux/list.h?) should be better?

I only have a half baken (even not compiling, I already saw several bugs
myself in this one while flying over...) patch. It shows what I wanted
to do.  The important part is in include/linux/pnp.h. After sleeping
over it, I fear I am doing this work for nothing...

As this is touching nearly every file in drivers/pnp I'd like to have
some advice/discussion, before I start (over and over) again...

If someone screams who knows that part well and wanted to add this
anyway..., I am busy enough :) (,but I can do it if not...)

Thanks,

   Thomas

---
 drivers/pnp/interface.c        |   16 ++++++++++------
 drivers/pnp/isapnp/core.c      |    9 +++++----
 drivers/pnp/manager.c          |   13 ++++++++-----
 drivers/pnp/pnpacpi/rsparser.c |   17 +++++++++--------
 drivers/pnp/pnpbios/rsparser.c |   14 ++++++++------
 drivers/pnp/resource.c         |   16 ++++++++--------
 drivers/pnp/system.c           |    2 +-
 include/linux/pnp.h            |   12 +++++++-----
 8 files changed, 56 insertions(+), 43 deletions(-)

Index: linux-2.6.22.1/drivers/pnp/interface.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/interface.c
+++ linux-2.6.22.1/drivers/pnp/interface.c
@@ -258,7 +258,7 @@ static ssize_t pnp_show_current_resource
 	else
 		pnp_printf(buffer,"disabled\n");
 
-	for (i = 0; i < PNP_MAX_PORT; i++) {
+	for (i = 0; pnp_port_res_pointer(dev, i); i++) {
 		if (pnp_port_valid(dev, i)) {
 			pnp_printf(buffer,"io");
 			if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
@@ -370,19 +370,23 @@ pnp_set_current_resources(struct device 
 				buf += 2;
 				while (isspace(*buf))
 					++buf;
-				dev->res.port_resource[nport].start = simple_strtoul(buf,&buf,0);
+				pnp_port_start(dev,nport) =
+					simple_strtoul(buf,&buf,0);
 				while (isspace(*buf))
 					++buf;
 				if(*buf == '-') {
 					buf += 1;
 					while (isspace(*buf))
 						++buf;
-					dev->res.port_resource[nport].end = simple_strtoul(buf,&buf,0);
+					pnp_port_end(dev,nport) =
+						simple_strtoul(buf,&buf,0);
 				} else
-					dev->res.port_resource[nport].end = dev->res.port_resource[nport].start;
-				dev->res.port_resource[nport].flags = IORESOURCE_IO;
+					pnp_port_end(dev,nport) =
+						pnp_port_start(dev,nport);
+				pnp_port_flags(dev,nport) = IORESOURCE_IO;
 				nport++;
-				if (nport >= PNP_MAX_PORT)
+				if (!pnp_port_res_pointer(dev,nport) ||
+				    nport >= PNP_MAX_PORT)
 					break;
 				continue;
 			}
Index: linux-2.6.22.1/drivers/pnp/manager.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/manager.c
+++ linux-2.6.22.1/drivers/pnp/manager.c
@@ -26,18 +26,21 @@ static int pnp_assign_port(struct pnp_de
 		return -EINVAL;
 
 	if (idx >= PNP_MAX_PORT) {
-		pnp_err("More than 4 ports is incompatible with pnp specifications.");
+		pnp_err("Run out of pnp ports\n");
 		/* pretend we were successful so at least the manager won't try again */
 		return 1;
 	}
 
 	/* check if this resource has been manually set, if so skip */
-	if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
+	if (pnp_port_res_pointer(dev, idx) && !(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
 		return 1;
 
-	start = &dev->res.port_resource[idx].start;
-	end = &dev->res.port_resource[idx].end;
-	flags = &dev->res.port_resource[idx].flags;
+	if (!pnp_port_res_pointer(dev, idx))
+		pnp_port_res_pointer(dev, idx) = kzalloc(sizeof(struct resource), GFP_KERNEL);
+
+	start = &pnp_port_res_pointer(dev, idx)->start;
+	end =   &pnp_port_res_pointer(dev, idx)->end;
+	flags = &pnp_port_res_pointer(dev, idx)->flags;
 
 	/* set the initial values */
 	*flags |= rule->flags | IORESOURCE_IO;
Index: linux-2.6.22.1/drivers/pnp/resource.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/resource.c
+++ linux-2.6.22.1/drivers/pnp/resource.c
@@ -241,11 +241,11 @@ int pnp_check_port(struct pnp_dev * dev,
 	int tmp;
 	struct pnp_dev *tdev;
 	resource_size_t *port, *end, *tport, *tend;
-	port = &dev->res.port_resource[idx].start;
-	end = &dev->res.port_resource[idx].end;
+	port = &(pnp_port_start(dev,idx));
+	end = &(pnp_port_end(dev,idx));
 
 	/* if the resource doesn't exist, don't complain about it */
-	if (cannot_compare(dev->res.port_resource[idx].flags))
+	if (cannot_compare(pnp_port_flags(dev,idx)))
 		return 1;
 
 	/* check if the resource is already in use, skip if the
@@ -264,10 +264,10 @@ int pnp_check_port(struct pnp_dev * dev,
 	}
 
 	/* check for internal conflicts */
-	for (tmp = 0; tmp < PNP_MAX_PORT && tmp != idx; tmp++) {
-		if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) {
-			tport = &dev->res.port_resource[tmp].start;
-			tend = &dev->res.port_resource[tmp].end;
+	for (tmp = 0; pnp_port_res_pointer(dev, tmp) && tmp != idx; tmp++) {
+		if (pnp_port_flags(dev,tmp) & IORESOURCE_IO) {
+			tport = &(pnp_port_start(dev,tmp));
+			tend = &(pnp_port_end(dev,tmp));
 			if (ranged_conflict(port,end,tport,tend))
 				return 0;
 		}
@@ -277,7 +277,7 @@ int pnp_check_port(struct pnp_dev * dev,
 	pnp_for_each_dev(tdev) {
 		if (tdev == dev)
 			continue;
-		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
+		for (tmp = 0;  pnp_port_res_pointer(dev, tmp); tmp++) {
 			if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
 				if (cannot_compare(tdev->res.port_resource[tmp].flags))
 					continue;
Index: linux-2.6.22.1/drivers/pnp/system.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/system.c
+++ linux-2.6.22.1/drivers/pnp/system.c
@@ -55,7 +55,7 @@ static void reserve_resources_of_dev(con
 {
 	int i;
 
-	for (i = 0; i < PNP_MAX_PORT; i++) {
+	for (i = 0; pnp_port_res_pointer(dev, i); i++) {
 		if (!pnp_port_valid(dev, i))
 			continue;
 		if (pnp_port_start(dev, i) == 0)
Index: linux-2.6.22.1/include/linux/pnp.h
===================================================================
--- linux-2.6.22.1.orig/include/linux/pnp.h
+++ linux-2.6.22.1/include/linux/pnp.h
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/mod_devicetable.h>
 
-#define PNP_MAX_PORT		8
+#define PNP_MAX_PORT		256
 #define PNP_MAX_MEM		4
 #define PNP_MAX_IRQ		2
 #define PNP_MAX_DMA		2
@@ -29,9 +29,11 @@ struct pnp_dev;
  */
 
 /* Use these instead of directly reading pnp_dev to get resource information */
-#define pnp_port_start(dev,bar)   ((dev)->res.port_resource[(bar)].start)
-#define pnp_port_end(dev,bar)     ((dev)->res.port_resource[(bar)].end)
-#define pnp_port_flags(dev,bar)   ((dev)->res.port_resource[(bar)].flags)
+#define pnp_port_res_pointer(dev,bar)   (bar >= PNP_MAX_PORT ? NULL : \
+					 (dev)->res.port_resource[(bar)])
+#define pnp_port_start(dev,bar)   ((dev)->res.port_resource[(bar)]->start)
+#define pnp_port_end(dev,bar)     ((dev)->res.port_resource[(bar)]->end)
+#define pnp_port_flags(dev,bar)   ((dev)->res.port_resource[(bar)]->flags)
 #define pnp_port_valid(dev,bar) \
 	((pnp_port_flags((dev),(bar)) & (IORESOURCE_IO | IORESOURCE_UNSET)) \
 		== IORESOURCE_IO)
@@ -121,7 +123,7 @@ struct pnp_option {
 };
 
 struct pnp_resource_table {
-	struct resource port_resource[PNP_MAX_PORT];
+	struct resource *port_resource[PNP_MAX_PORT];
 	struct resource mem_resource[PNP_MAX_MEM];
 	struct resource dma_resource[PNP_MAX_DMA];
 	struct resource irq_resource[PNP_MAX_IRQ];
Index: linux-2.6.22.1/drivers/pnp/isapnp/core.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/isapnp/core.c
+++ linux-2.6.22.1/drivers/pnp/isapnp/core.c
@@ -954,12 +954,13 @@ static int isapnp_read_resources(struct 
 
 	dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
 	if (dev->active) {
-		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
+		for (tmp = 0; res->port_resource[tmp] && tmp < PNP_MAX_PORT;
+		     tmp++) {
 			ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
 			if (!ret)
 				continue;
-			res->port_resource[tmp].start = ret;
-			res->port_resource[tmp].flags = IORESOURCE_IO;
+			res->port_resource[tmp]->start = ret;
+			res->port_resource[tmp]->flags = IORESOURCE_IO;
 		}
 		for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
 			ret = isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8;
@@ -1002,7 +1003,7 @@ static int isapnp_set_resources(struct p
 
 	isapnp_cfg_begin(dev->card->number, dev->number);
 	dev->active = 1;
-	for (tmp = 0; tmp < PNP_MAX_PORT && (res->port_resource[tmp].flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; tmp++)
+	for (tmp = 0; res->port_resource[tmp] && tmp < PNP_MAX_PORT && (res->port_resource[tmp].flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; tmp++)
 		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), res->port_resource[tmp].start);
 	for (tmp = 0; tmp < PNP_MAX_IRQ && (res->irq_resource[tmp].flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; tmp++) {
 		int irq = res->irq_resource[tmp].start;
Index: linux-2.6.22.1/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux-2.6.22.1/drivers/pnp/pnpacpi/rsparser.c
@@ -172,19 +172,20 @@ pnpacpi_parse_allocated_ioresource(struc
 	u64 io, u64 len, int io_decode)
 {
 	int i = 0;
-	while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
-			i < PNP_MAX_PORT)
+	while (res->port_resource[i] &&
+	       !(res->port_resource[i]->flags & IORESOURCE_UNSET) &&
+	       i < PNP_MAX_PORT)
 		i++;
-	if (i < PNP_MAX_PORT) {
-		res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
+	if (res->port_resource[i] && i < PNP_MAX_PORT) {
+		res->port_resource[i]->flags = IORESOURCE_IO;  // Also clears _UNSET flag
 		if (io_decode == ACPI_DECODE_16)
-			res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
+			res->port_resource[i]->flags |= PNP_PORT_FLAG_16BITADDR;
 		if (len <= 0 || (io + len -1) >= 0x10003) {
-			res->port_resource[i].flags |= IORESOURCE_DISABLED;
+			res->port_resource[i]->flags |= IORESOURCE_DISABLED;
 			return;
 		}
-		res->port_resource[i].start = io;
-		res->port_resource[i].end = io + len - 1;
+		res->port_resource[i]->start = io;
+		res->port_resource[i]->end = io + len - 1;
 	}
 }
 
Index: linux-2.6.22.1/drivers/pnp/pnpbios/rsparser.c
===================================================================
--- linux-2.6.22.1.orig/drivers/pnp/pnpbios/rsparser.c
+++ linux-2.6.22.1/drivers/pnp/pnpbios/rsparser.c
@@ -91,15 +91,17 @@ static void
 pnpbios_parse_allocated_ioresource(struct pnp_resource_table * res, int io, int len)
 {
 	int i = 0;
-	while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_PORT) i++;
-	if (i < PNP_MAX_PORT) {
-		res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
+	while (res->port_resource[i] &&
+	       !(res->port_resource[i]->flags & IORESOURCE_UNSET) &&
+	       i < PNP_MAX_PORT) i++;
+	if (res->port_resource[i] && i < PNP_MAX_PORT) {
+		res->port_resource[i]->flags = IORESOURCE_IO;  // Also clears _UNSET flag
 		if (len <= 0 || (io + len -1) >= 0x10003) {
-			res->port_resource[i].flags |= IORESOURCE_DISABLED;
+			res->port_resource[i]->flags |= IORESOURCE_DISABLED;
 			return;
 		}
-		res->port_resource[i].start = (unsigned long) io;
-		res->port_resource[i].end = (unsigned long)(io + len - 1);
+		res->port_resource[i]->start = (unsigned long) io;
+		res->port_resource[i]->end = (unsigned long)(io + len - 1);
 	}
 }
 



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

* Re: [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations
  2007-07-18  8:21   ` Thomas Renninger
@ 2007-07-18 21:33     ` Bjorn Helgaas
  2007-07-19  9:23       ` Thomas Renninger
  0 siblings, 1 reply; 6+ messages in thread
From: Bjorn Helgaas @ 2007-07-18 21:33 UTC (permalink / raw)
  To: trenn
  Cc: linux-kernel, linux-acpi, Alexey Starikovskiy, Jean Delvare,
	Bernhard Walle

On Wednesday 18 July 2007 02:21:14 am Thomas Renninger wrote:
> On Tue, 2007-07-17 at 09:49 -0600, Bjorn Helgaas wrote:
> > On Monday 16 July 2007 08:21:07 am Thomas Renninger wrote:
> > > PNP0C02 devices normally have a lot more IO port declarations than
> > > currently defined in PNP_MAX_PORT
> > 
> > Yes.
> > 
> > > I also wonder whether other limits like:
> > >  #define PNP_MAX_MEM        4
> > >  #define PNP_MAX_IRQ        2
> > >  #define PNP_MAX_DMA        2
> > > could get exceeded with pnpacpi?
> > 
> > Definitely.  I think the current limits come from the PNP ISA spec
> > (sec 4.6).  I don't see similar limits in the PNPBIOS or ACPI specs,
> > so ideally I think they should be dynamically allocated as you suggest.
> > 
> I wanted to implement the dynamic approach and used a dynamically
> allocated array, filled up from beginning. While this is close to the
> current implementation I thought this is the easiest sufficient way...
> (I also only did this for io ports where most mem is wasted).
> Now I am thinking about hotplug (e.g. if a SSDT with resources gets
> hot-added, removed)... If a device can vanish, the array must get
> reordered, not a really well fitting structure, a list (a pnp specific
> set up, or from include/linux/list.h?) should be better?

I don't understand the array reordering problem.  Either a device exists
or it doesn't.  Loading or unloading an SSDT should not change the number
of resources for devices (except that it might add or remove an entire
device).

I think for now, it would be sufficient to increase PNP_MAX_IRQ to 8
and PNP_MAX_PORT to 32 and be done with it.  I don't think it's worth
getting more complicated unless we dynamically allocate everything.

Bjorn

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

* Re: [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations
  2007-07-18 21:33     ` Bjorn Helgaas
@ 2007-07-19  9:23       ` Thomas Renninger
  0 siblings, 0 replies; 6+ messages in thread
From: Thomas Renninger @ 2007-07-19  9:23 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-kernel, linux-acpi, Alexey Starikovskiy, Jean Delvare,
	Bernhard Walle

On Wed, 2007-07-18 at 15:33 -0600, Bjorn Helgaas wrote:
> On Wednesday 18 July 2007 02:21:14 am Thomas Renninger wrote:
> > On Tue, 2007-07-17 at 09:49 -0600, Bjorn Helgaas wrote:
> > > On Monday 16 July 2007 08:21:07 am Thomas Renninger wrote:
> > > > PNP0C02 devices normally have a lot more IO port declarations than
> > > > currently defined in PNP_MAX_PORT
> > > 
> > > Yes.
> > > 
> > > > I also wonder whether other limits like:
> > > >  #define PNP_MAX_MEM        4
> > > >  #define PNP_MAX_IRQ        2
> > > >  #define PNP_MAX_DMA        2
> > > > could get exceeded with pnpacpi?
> > > 
> > > Definitely.  I think the current limits come from the PNP ISA spec
> > > (sec 4.6).  I don't see similar limits in the PNPBIOS or ACPI specs,
> > > so ideally I think they should be dynamically allocated as you suggest.
> > > 
> > I wanted to implement the dynamic approach and used a dynamically
> > allocated array, filled up from beginning. While this is close to the
> > current implementation I thought this is the easiest sufficient way...
> > (I also only did this for io ports where most mem is wasted).
> > Now I am thinking about hotplug (e.g. if a SSDT with resources gets
> > hot-added, removed)... If a device can vanish, the array must get
> > reordered, not a really well fitting structure, a list (a pnp specific
> > set up, or from include/linux/list.h?) should be better?
> 
> I don't understand the array reordering problem.  Either a device exists
> or it doesn't.  Loading or unloading an SSDT should not change the number
> of resources for devices (except that it might add or remove an entire
> device).
Yes, you are right. I feared there could be cases were single resources
should be able to be removed.
> 
> I think for now, it would be sufficient to increase PNP_MAX_IRQ to 8
> and PNP_MAX_PORT to 32 and be done with it.  I don't think it's worth
> getting more complicated unless we dynamically allocate everything.
Ok.

Thanks,

   Thomas

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

end of thread, other threads:[~2007-07-19  9:23 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-16 14:21 [PATCH] - Increase PNP_MAX_PORT. ACPI devices can have a lot IO resource declarations Thomas Renninger
2007-07-16 16:48 ` Jean Delvare
2007-07-17 15:49 ` Bjorn Helgaas
2007-07-18  8:21   ` Thomas Renninger
2007-07-18 21:33     ` Bjorn Helgaas
2007-07-19  9:23       ` Thomas Renninger

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