Commit e9fe9e188118a0a34c6200d9b10ea6247f53592d

Authored by Bjorn Helgaas
Committed by Len Brown
1 parent 0638bc8dc0

pnpacpi: fix IRQ flag decoding

When decoding IRQ trigger mode and polarity, it is not enough to mask by
IORESOURCE_BITS because there are now additional bits defined.  For
example, if IORESOURCE_IRQ_SHAREABLE was set, we failed to set *triggering
and *polarity at all.

I can't point to a failure that this patch fixes, but
bugs in this area have caused problems when resuming after
suspend, for example:

    http://bugzilla.kernel.org/show_bug.cgi?id=6316
    http://bugzilla.kernel.org/show_bug.cgi?id=9487
    https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.22/+bug/152187

This is based on a patch by Tom Jaeger:
    http://bugzilla.kernel.org/show_bug.cgi?id=9487#c32

[rene.herman@keyaccess.nl: fix comment]
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Len Brown <len.brown@intel.com>

Showing 2 changed files with 15 additions and 7 deletions Side-by-side Diff

drivers/pnp/pnpacpi/rsparser.c
... ... @@ -56,9 +56,11 @@
56 56 return flags;
57 57 }
58 58  
59   -static void decode_irq_flags(int flag, int *triggering, int *polarity)
  59 +static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
  60 + int *polarity)
60 61 {
61   - switch (flag) {
  62 + switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
  63 + IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE)) {
62 64 case IORESOURCE_IRQ_LOWLEVEL:
63 65 *triggering = ACPI_LEVEL_SENSITIVE;
64 66 *polarity = ACPI_ACTIVE_LOW;
... ... @@ -75,6 +77,12 @@
75 77 *triggering = ACPI_EDGE_SENSITIVE;
76 78 *polarity = ACPI_ACTIVE_HIGH;
77 79 break;
  80 + default:
  81 + dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",
  82 + flags);
  83 + *triggering = ACPI_EDGE_SENSITIVE;
  84 + *polarity = ACPI_ACTIVE_HIGH;
  85 + break;
78 86 }
79 87 }
80 88  
... ... @@ -790,7 +798,7 @@
790 798 struct acpi_resource_irq *irq = &resource->data.irq;
791 799 int triggering, polarity;
792 800  
793   - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
  801 + decode_irq_flags(dev, p->flags, &triggering, &polarity);
794 802 irq->triggering = triggering;
795 803 irq->polarity = polarity;
796 804 if (triggering == ACPI_EDGE_SENSITIVE)
... ... @@ -813,7 +821,7 @@
813 821 struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
814 822 int triggering, polarity;
815 823  
816   - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
  824 + decode_irq_flags(dev, p->flags, &triggering, &polarity);
817 825 extended_irq->producer_consumer = ACPI_CONSUMER;
818 826 extended_irq->triggering = triggering;
819 827 extended_irq->polarity = polarity;
include/linux/ioport.h
... ... @@ -53,14 +53,14 @@
53 53 #define IORESOURCE_AUTO 0x40000000
54 54 #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
55 55  
56   -/* ISA PnP IRQ specific bits (IORESOURCE_BITS) */
  56 +/* PnP IRQ specific bits (IORESOURCE_BITS) */
57 57 #define IORESOURCE_IRQ_HIGHEDGE (1<<0)
58 58 #define IORESOURCE_IRQ_LOWEDGE (1<<1)
59 59 #define IORESOURCE_IRQ_HIGHLEVEL (1<<2)
60 60 #define IORESOURCE_IRQ_LOWLEVEL (1<<3)
61 61 #define IORESOURCE_IRQ_SHAREABLE (1<<4)
62 62  
63   -/* ISA PnP DMA specific bits (IORESOURCE_BITS) */
  63 +/* PnP DMA specific bits (IORESOURCE_BITS) */
64 64 #define IORESOURCE_DMA_TYPE_MASK (3<<0)
65 65 #define IORESOURCE_DMA_8BIT (0<<0)
66 66 #define IORESOURCE_DMA_8AND16BIT (1<<0)
... ... @@ -76,7 +76,7 @@
76 76 #define IORESOURCE_DMA_TYPEB (2<<6)
77 77 #define IORESOURCE_DMA_TYPEF (3<<6)
78 78  
79   -/* ISA PnP memory I/O specific bits (IORESOURCE_BITS) */
  79 +/* PnP memory I/O specific bits (IORESOURCE_BITS) */
80 80 #define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */
81 81 #define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */
82 82 #define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */