diff mbox

PNPACPI: Register disabled resources

Message ID 4E04FB69.3000206@gmx.net (mailing list archive)
State New, archived
Headers show

Commit Message

Witold Szczeponik June 24, 2011, 9:02 p.m. UTC
When parsing PnP resources, it may happen that some of these
are disabled.  The current solution is to skip these resources
completely - with the unfortunate side effect that they are not
registered despite the fact that they exist, after all.  The
downside of his is that these resources cannot be manipulated
programatically.  The kernel's APM implementation does not suffer
from this problem.

This patch fixes a problem with (at least) some vintage IBM
ThinkPad 600E (and most likely also on the 600, 600X, and 770X
which have a very similar layout) where some of its PnP devices
support options where either an IRQ or DMA is disabled.  The
manipulation of these resources is important because the 600E
has very special requirements.

The patch applies the idea to register disabled resources to
all types of resources, not just to IRQs and DMAs.

No regressions were observed on hardware that does not require
this patch.

The patch is applied against 2.6.39.


Signed-off-by: Witold Szczeponik <Witold.Szczeponik@gmx.net>


--
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

Comments

Henrique de Moraes Holschuh June 25, 2011, 2:54 a.m. UTC | #1
On Fri, 24 Jun 2011, Witold Szczeponik wrote:
> When parsing PnP resources, it may happen that some of these
> are disabled.  The current solution is to skip these resources
> completely - with the unfortunate side effect that they are not
> registered despite the fact that they exist, after all.  The
> downside of his is that these resources cannot be manipulated
> programatically.  The kernel's APM implementation does not suffer
> from this problem.
> 
> This patch fixes a problem with (at least) some vintage IBM
> ThinkPad 600E (and most likely also on the 600, 600X, and 770X
> which have a very similar layout) where some of its PnP devices
> support options where either an IRQ or DMA is disabled.  The
> manipulation of these resources is important because the 600E
> has very special requirements.
> 
> The patch applies the idea to register disabled resources to
> all types of resources, not just to IRQs and DMAs.

Maybe you could post to the linux-thinkpad ML a follow up, mentioning this
patch and how these thinkpad users should use it plus whatever userspace to
improve the suport for their boxes?
Witold Szczeponik July 3, 2011, 10:50 a.m. UTC | #2
Am 25.06.2011 04:54, schrieb Henrique de Moraes Holschuh:

>
> Maybe you could post to the linux-thinkpad ML a follow up, mentioning this
> patch and how these thinkpad users should use it plus whatever userspace to
> improve the suport for their boxes?
>

Hi Henrique,

I will send out a more detailed patch description shortly.  Since a 
subtle typo sneaked into the original patch, resending the entire patch 
makes sense (to me).  I will also include the linux-thinkpad ML.

--- Witold
--
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
diff mbox

Patch

Index: linux/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- linux.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux/drivers/pnp/pnpacpi/rsparser.c
@@ -509,15 +509,15 @@  static __init void pnpacpi_parse_dma_opt
  					    struct acpi_resource_dma *p)
  {
  	int i;
-	unsigned char map = 0, flags;
+	unsigned char map = 0, flags = 0;

  	if (p->channel_count == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	for (i = 0; i < p->channel_count; i++)
  		map |= 1 << p->channels[i];

-	flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
+	flags |= dma_flags(dev, p->type, p->bus_master, p->transfer);
  	pnp_register_dma_resource(dev, option_flags, map, flags);
  }

@@ -527,17 +527,17 @@  static __init void pnpacpi_parse_irq_opt
  {
  	int i;
  	pnp_irq_mask_t map;
-	unsigned char flags;
+	unsigned char flags = 0;

  	if (p->interrupt_count == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	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);

-	flags = irq_flags(p->triggering, p->polarity, p->sharable);
+	flags |= irq_flags(p->triggering, p->polarity, p->sharable);
  	pnp_register_irq_resource(dev, option_flags, &map, flags);
  }

@@ -547,10 +547,10 @@  static __init void pnpacpi_parse_ext_irq
  {
  	int i;
  	pnp_irq_mask_t map;
-	unsigned char flags;
+	unsigned char flags = 0;

  	if (p->interrupt_count == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	bitmap_zero(map.bits, PNP_IRQ_NR);
  	for (i = 0; i < p->interrupt_count; i++) {
@@ -564,7 +564,7 @@  static __init void pnpacpi_parse_ext_irq
  		}
  	}

-	flags = irq_flags(p->triggering, p->polarity, p->sharable);
+	flags |= irq_flags(p->triggering, p->polarity, p->sharable);
  	pnp_register_irq_resource(dev, option_flags, &map, flags);
  }

@@ -575,10 +575,10 @@  static __init void pnpacpi_parse_port_op
  	unsigned char flags = 0;

  	if (io->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	if (io->io_decode == ACPI_DECODE_16)
-		flags = IORESOURCE_IO_16BIT_ADDR;
+		flags |= IORESOURCE_IO_16BIT_ADDR;
  	pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
  				   io->alignment, io->address_length, flags);
  }
@@ -587,11 +587,13 @@  static __init void pnpacpi_parse_fixed_p
  					unsigned int option_flags,
  					struct acpi_resource_fixed_io *io)
  {
+	unsigned char flags = 0;
+
  	if (io->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	pnp_register_port_resource(dev, option_flags, io->address, io->address,
-				   0, io->address_length, IORESOURCE_IO_FIXED);
+				   0, io->address_length, flags | IORESOURCE_IO_FIXED);
  }

  static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
@@ -601,10 +603,10 @@  static __init void pnpacpi_parse_mem24_o
  	unsigned char flags = 0;

  	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-		flags = IORESOURCE_MEM_WRITEABLE;
+		flags |= IORESOURCE_MEM_WRITEABLE;
  	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
  				  p->alignment, p->address_length, flags);
  }
@@ -616,10 +618,10 @@  static __init void pnpacpi_parse_mem32_o
  	unsigned char flags = 0;

  	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-		flags = IORESOURCE_MEM_WRITEABLE;
+		flags |= IORESOURCE_MEM_WRITEABLE;
  	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
  				  p->alignment, p->address_length, flags);
  }
@@ -631,10 +633,10 @@  static __init void pnpacpi_parse_fixed_m
  	unsigned char flags = 0;

  	if (p->address_length == 0)
-		return;
+		iflags |= IORESOURCE_DISABLED;

  	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-		flags = IORESOURCE_MEM_WRITEABLE;
+		flags |= IORESOURCE_MEM_WRITEABLE;
  	pnp_register_mem_resource(dev, option_flags, p->address, p->address,
  				  0, p->address_length, flags);
  }
@@ -655,18 +657,18 @@  static __init void pnpacpi_parse_address
  	}

  	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	if (p->resource_type == ACPI_MEMORY_RANGE) {
  		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
-			flags = IORESOURCE_MEM_WRITEABLE;
+			flags |= IORESOURCE_MEM_WRITEABLE;
  		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_flags, p->minimum,
  					   p->minimum, 0, p->address_length,
-					   IORESOURCE_IO_FIXED);
+					   flags | IORESOURCE_IO_FIXED);
  }

  static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
@@ -677,18 +679,18 @@  static __init void pnpacpi_parse_ext_add
  	unsigned char flags = 0;

  	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;

  	if (p->resource_type == ACPI_MEMORY_RANGE) {
  		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
-			flags = IORESOURCE_MEM_WRITEABLE;
+			flags |= IORESOURCE_MEM_WRITEABLE;
  		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_flags, p->minimum,
  					   p->minimum, 0, p->address_length,
-					   IORESOURCE_IO_FIXED);
+					   flags | IORESOURCE_IO_FIXED);
  }

  struct acpipnp_parse_option_s {