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>
This commit is contained in:
Родитель
0638bc8dc0
Коммит
e9fe9e1881
|
@ -56,9 +56,11 @@ static int irq_flags(int triggering, int polarity, int shareable)
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_irq_flags(int flag, int *triggering, int *polarity)
|
static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
|
||||||
|
int *polarity)
|
||||||
{
|
{
|
||||||
switch (flag) {
|
switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
|
||||||
|
IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE)) {
|
||||||
case IORESOURCE_IRQ_LOWLEVEL:
|
case IORESOURCE_IRQ_LOWLEVEL:
|
||||||
*triggering = ACPI_LEVEL_SENSITIVE;
|
*triggering = ACPI_LEVEL_SENSITIVE;
|
||||||
*polarity = ACPI_ACTIVE_LOW;
|
*polarity = ACPI_ACTIVE_LOW;
|
||||||
|
@ -75,6 +77,12 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity)
|
||||||
*triggering = ACPI_EDGE_SENSITIVE;
|
*triggering = ACPI_EDGE_SENSITIVE;
|
||||||
*polarity = ACPI_ACTIVE_HIGH;
|
*polarity = ACPI_ACTIVE_HIGH;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",
|
||||||
|
flags);
|
||||||
|
*triggering = ACPI_EDGE_SENSITIVE;
|
||||||
|
*polarity = ACPI_ACTIVE_HIGH;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,7 +798,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
|
||||||
struct acpi_resource_irq *irq = &resource->data.irq;
|
struct acpi_resource_irq *irq = &resource->data.irq;
|
||||||
int triggering, polarity;
|
int triggering, polarity;
|
||||||
|
|
||||||
decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
|
decode_irq_flags(dev, p->flags, &triggering, &polarity);
|
||||||
irq->triggering = triggering;
|
irq->triggering = triggering;
|
||||||
irq->polarity = polarity;
|
irq->polarity = polarity;
|
||||||
if (triggering == ACPI_EDGE_SENSITIVE)
|
if (triggering == ACPI_EDGE_SENSITIVE)
|
||||||
|
@ -813,7 +821,7 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
|
||||||
struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
|
struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
|
||||||
int triggering, polarity;
|
int triggering, polarity;
|
||||||
|
|
||||||
decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
|
decode_irq_flags(dev, p->flags, &triggering, &polarity);
|
||||||
extended_irq->producer_consumer = ACPI_CONSUMER;
|
extended_irq->producer_consumer = ACPI_CONSUMER;
|
||||||
extended_irq->triggering = triggering;
|
extended_irq->triggering = triggering;
|
||||||
extended_irq->polarity = polarity;
|
extended_irq->polarity = polarity;
|
||||||
|
|
|
@ -53,14 +53,14 @@ struct resource_list {
|
||||||
#define IORESOURCE_AUTO 0x40000000
|
#define IORESOURCE_AUTO 0x40000000
|
||||||
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
|
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
|
||||||
|
|
||||||
/* ISA PnP IRQ specific bits (IORESOURCE_BITS) */
|
/* PnP IRQ specific bits (IORESOURCE_BITS) */
|
||||||
#define IORESOURCE_IRQ_HIGHEDGE (1<<0)
|
#define IORESOURCE_IRQ_HIGHEDGE (1<<0)
|
||||||
#define IORESOURCE_IRQ_LOWEDGE (1<<1)
|
#define IORESOURCE_IRQ_LOWEDGE (1<<1)
|
||||||
#define IORESOURCE_IRQ_HIGHLEVEL (1<<2)
|
#define IORESOURCE_IRQ_HIGHLEVEL (1<<2)
|
||||||
#define IORESOURCE_IRQ_LOWLEVEL (1<<3)
|
#define IORESOURCE_IRQ_LOWLEVEL (1<<3)
|
||||||
#define IORESOURCE_IRQ_SHAREABLE (1<<4)
|
#define IORESOURCE_IRQ_SHAREABLE (1<<4)
|
||||||
|
|
||||||
/* ISA PnP DMA specific bits (IORESOURCE_BITS) */
|
/* PnP DMA specific bits (IORESOURCE_BITS) */
|
||||||
#define IORESOURCE_DMA_TYPE_MASK (3<<0)
|
#define IORESOURCE_DMA_TYPE_MASK (3<<0)
|
||||||
#define IORESOURCE_DMA_8BIT (0<<0)
|
#define IORESOURCE_DMA_8BIT (0<<0)
|
||||||
#define IORESOURCE_DMA_8AND16BIT (1<<0)
|
#define IORESOURCE_DMA_8AND16BIT (1<<0)
|
||||||
|
@ -76,7 +76,7 @@ struct resource_list {
|
||||||
#define IORESOURCE_DMA_TYPEB (2<<6)
|
#define IORESOURCE_DMA_TYPEB (2<<6)
|
||||||
#define IORESOURCE_DMA_TYPEF (3<<6)
|
#define IORESOURCE_DMA_TYPEF (3<<6)
|
||||||
|
|
||||||
/* ISA PnP memory I/O specific bits (IORESOURCE_BITS) */
|
/* PnP memory I/O specific bits (IORESOURCE_BITS) */
|
||||||
#define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */
|
#define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */
|
||||||
#define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */
|
#define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */
|
||||||
#define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */
|
#define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче