diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2008-06-09 19:52:04 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-06-11 19:13:46 -0400 |
commit | e9fe9e188118a0a34c6200d9b10ea6247f53592d (patch) | |
tree | 151fb9549cefbcf7a8f7e1d591c99381d2c9802c | |
parent | 0638bc8dc037d844efe1d4abf44488c037705905 (diff) |
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>
-rw-r--r-- | drivers/pnp/pnpacpi/rsparser.c | 16 | ||||
-rw-r--r-- | include/linux/ioport.h | 6 |
2 files changed, 15 insertions, 7 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 0201c8adfda7..ab09fe6fe1e4 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -56,9 +56,11 @@ static int irq_flags(int triggering, int polarity, int shareable) | |||
56 | return flags; | 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 | case IORESOURCE_IRQ_LOWLEVEL: | 64 | case IORESOURCE_IRQ_LOWLEVEL: |
63 | *triggering = ACPI_LEVEL_SENSITIVE; | 65 | *triggering = ACPI_LEVEL_SENSITIVE; |
64 | *polarity = ACPI_ACTIVE_LOW; | 66 | *polarity = ACPI_ACTIVE_LOW; |
@@ -75,6 +77,12 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) | |||
75 | *triggering = ACPI_EDGE_SENSITIVE; | 77 | *triggering = ACPI_EDGE_SENSITIVE; |
76 | *polarity = ACPI_ACTIVE_HIGH; | 78 | *polarity = ACPI_ACTIVE_HIGH; |
77 | break; | 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 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev, | |||
790 | struct acpi_resource_irq *irq = &resource->data.irq; | 798 | struct acpi_resource_irq *irq = &resource->data.irq; |
791 | int triggering, polarity; | 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 | irq->triggering = triggering; | 802 | irq->triggering = triggering; |
795 | irq->polarity = polarity; | 803 | irq->polarity = polarity; |
796 | if (triggering == ACPI_EDGE_SENSITIVE) | 804 | if (triggering == ACPI_EDGE_SENSITIVE) |
@@ -813,7 +821,7 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, | |||
813 | struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; | 821 | struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; |
814 | int triggering, polarity; | 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 | extended_irq->producer_consumer = ACPI_CONSUMER; | 825 | extended_irq->producer_consumer = ACPI_CONSUMER; |
818 | extended_irq->triggering = triggering; | 826 | extended_irq->triggering = triggering; |
819 | extended_irq->polarity = polarity; | 827 | extended_irq->polarity = polarity; |
diff --git a/include/linux/ioport.h b/include/linux/ioport.h index d5d40a9f7929..c6801bffe76d 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h | |||
@@ -53,14 +53,14 @@ struct resource_list { | |||
53 | #define IORESOURCE_AUTO 0x40000000 | 53 | #define IORESOURCE_AUTO 0x40000000 |
54 | #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ | 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 | #define IORESOURCE_IRQ_HIGHEDGE (1<<0) | 57 | #define IORESOURCE_IRQ_HIGHEDGE (1<<0) |
58 | #define IORESOURCE_IRQ_LOWEDGE (1<<1) | 58 | #define IORESOURCE_IRQ_LOWEDGE (1<<1) |
59 | #define IORESOURCE_IRQ_HIGHLEVEL (1<<2) | 59 | #define IORESOURCE_IRQ_HIGHLEVEL (1<<2) |
60 | #define IORESOURCE_IRQ_LOWLEVEL (1<<3) | 60 | #define IORESOURCE_IRQ_LOWLEVEL (1<<3) |
61 | #define IORESOURCE_IRQ_SHAREABLE (1<<4) | 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 | #define IORESOURCE_DMA_TYPE_MASK (3<<0) | 64 | #define IORESOURCE_DMA_TYPE_MASK (3<<0) |
65 | #define IORESOURCE_DMA_8BIT (0<<0) | 65 | #define IORESOURCE_DMA_8BIT (0<<0) |
66 | #define IORESOURCE_DMA_8AND16BIT (1<<0) | 66 | #define IORESOURCE_DMA_8AND16BIT (1<<0) |
@@ -76,7 +76,7 @@ struct resource_list { | |||
76 | #define IORESOURCE_DMA_TYPEB (2<<6) | 76 | #define IORESOURCE_DMA_TYPEB (2<<6) |
77 | #define IORESOURCE_DMA_TYPEF (3<<6) | 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 | #define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */ | 80 | #define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */ |
81 | #define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */ | 81 | #define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */ |
82 | #define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */ | 82 | #define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */ |