diff options
Diffstat (limited to 'drivers/pnp/pnpacpi')
-rw-r--r-- | drivers/pnp/pnpacpi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pnp/pnpacpi/rsparser.c | 75 |
2 files changed, 44 insertions, 33 deletions
diff --git a/drivers/pnp/pnpacpi/Kconfig b/drivers/pnp/pnpacpi/Kconfig index 0782cdc5009f..b1854171b963 100644 --- a/drivers/pnp/pnpacpi/Kconfig +++ b/drivers/pnp/pnpacpi/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | config PNPACPI | 4 | config PNPACPI |
5 | bool "Plug and Play ACPI support (EXPERIMENTAL)" | 5 | bool "Plug and Play ACPI support (EXPERIMENTAL)" |
6 | depends on PNP && ACPI_BUS && EXPERIMENTAL | 6 | depends on PNP && ACPI && EXPERIMENTAL |
7 | default y | 7 | default y |
8 | ---help--- | 8 | ---help--- |
9 | Linux uses the PNPACPI to autodetect built-in | 9 | Linux uses the PNPACPI to autodetect built-in |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 675b76a42403..416d30debe6c 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -73,25 +73,35 @@ static void decode_irq_flags(int flag, int *edge_level, int *active_high_low) | |||
73 | } | 73 | } |
74 | 74 | ||
75 | static void | 75 | static void |
76 | pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, int irq) | 76 | pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi, |
77 | int edge_level, int active_high_low) | ||
77 | { | 78 | { |
78 | int i = 0; | 79 | int i = 0; |
80 | int irq; | ||
81 | |||
82 | if (!valid_IRQ(gsi)) | ||
83 | return; | ||
84 | |||
79 | while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && | 85 | while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && |
80 | i < PNP_MAX_IRQ) | 86 | i < PNP_MAX_IRQ) |
81 | i++; | 87 | i++; |
82 | if (i < PNP_MAX_IRQ) { | 88 | if (i >= PNP_MAX_IRQ) |
83 | res->irq_resource[i].flags = IORESOURCE_IRQ; //Also clears _UNSET flag | 89 | return; |
84 | if (irq == -1) { | 90 | |
85 | res->irq_resource[i].flags |= IORESOURCE_DISABLED; | 91 | res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag |
86 | return; | 92 | irq = acpi_register_gsi(gsi, edge_level, active_high_low); |
87 | } | 93 | if (irq < 0) { |
88 | res->irq_resource[i].start =(unsigned long) irq; | 94 | res->irq_resource[i].flags |= IORESOURCE_DISABLED; |
89 | res->irq_resource[i].end = (unsigned long) irq; | 95 | return; |
90 | } | 96 | } |
97 | |||
98 | res->irq_resource[i].start = irq; | ||
99 | res->irq_resource[i].end = irq; | ||
100 | pcibios_penalize_isa_irq(irq, 1); | ||
91 | } | 101 | } |
92 | 102 | ||
93 | static void | 103 | static void |
94 | pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma) | 104 | pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma) |
95 | { | 105 | { |
96 | int i = 0; | 106 | int i = 0; |
97 | while (i < PNP_MAX_DMA && | 107 | while (i < PNP_MAX_DMA && |
@@ -103,14 +113,14 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma) | |||
103 | res->dma_resource[i].flags |= IORESOURCE_DISABLED; | 113 | res->dma_resource[i].flags |= IORESOURCE_DISABLED; |
104 | return; | 114 | return; |
105 | } | 115 | } |
106 | res->dma_resource[i].start =(unsigned long) dma; | 116 | res->dma_resource[i].start = dma; |
107 | res->dma_resource[i].end = (unsigned long) dma; | 117 | res->dma_resource[i].end = dma; |
108 | } | 118 | } |
109 | } | 119 | } |
110 | 120 | ||
111 | static void | 121 | static void |
112 | pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, | 122 | pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, |
113 | int io, int len) | 123 | u32 io, u32 len) |
114 | { | 124 | { |
115 | int i = 0; | 125 | int i = 0; |
116 | while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && | 126 | while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && |
@@ -122,14 +132,14 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, | |||
122 | res->port_resource[i].flags |= IORESOURCE_DISABLED; | 132 | res->port_resource[i].flags |= IORESOURCE_DISABLED; |
123 | return; | 133 | return; |
124 | } | 134 | } |
125 | res->port_resource[i].start = (unsigned long) io; | 135 | res->port_resource[i].start = io; |
126 | res->port_resource[i].end = (unsigned long)(io + len - 1); | 136 | res->port_resource[i].end = io + len - 1; |
127 | } | 137 | } |
128 | } | 138 | } |
129 | 139 | ||
130 | static void | 140 | static void |
131 | pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res, | 141 | pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res, |
132 | int mem, int len) | 142 | u64 mem, u64 len) |
133 | { | 143 | { |
134 | int i = 0; | 144 | int i = 0; |
135 | while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && | 145 | while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && |
@@ -141,8 +151,8 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res, | |||
141 | res->mem_resource[i].flags |= IORESOURCE_DISABLED; | 151 | res->mem_resource[i].flags |= IORESOURCE_DISABLED; |
142 | return; | 152 | return; |
143 | } | 153 | } |
144 | res->mem_resource[i].start = (unsigned long) mem; | 154 | res->mem_resource[i].start = mem; |
145 | res->mem_resource[i].end = (unsigned long)(mem + len - 1); | 155 | res->mem_resource[i].end = mem + len - 1; |
146 | } | 156 | } |
147 | } | 157 | } |
148 | 158 | ||
@@ -151,27 +161,28 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
151 | void *data) | 161 | void *data) |
152 | { | 162 | { |
153 | struct pnp_resource_table * res_table = (struct pnp_resource_table *)data; | 163 | struct pnp_resource_table * res_table = (struct pnp_resource_table *)data; |
164 | int i; | ||
154 | 165 | ||
155 | switch (res->id) { | 166 | switch (res->id) { |
156 | case ACPI_RSTYPE_IRQ: | 167 | case ACPI_RSTYPE_IRQ: |
157 | if ((res->data.irq.number_of_interrupts > 0) && | 168 | /* |
158 | valid_IRQ(res->data.irq.interrupts[0])) { | 169 | * Per spec, only one interrupt per descriptor is allowed in |
159 | pnpacpi_parse_allocated_irqresource(res_table, | 170 | * _CRS, but some firmware violates this, so parse them all. |
160 | acpi_register_gsi(res->data.irq.interrupts[0], | 171 | */ |
161 | res->data.irq.edge_level, | 172 | for (i = 0; i < res->data.irq.number_of_interrupts; i++) { |
162 | res->data.irq.active_high_low)); | 173 | pnpacpi_parse_allocated_irqresource(res_table, |
163 | pcibios_penalize_isa_irq(res->data.irq.interrupts[0], 1); | 174 | res->data.irq.interrupts[i], |
175 | res->data.irq.edge_level, | ||
176 | res->data.irq.active_high_low); | ||
164 | } | 177 | } |
165 | break; | 178 | break; |
166 | 179 | ||
167 | case ACPI_RSTYPE_EXT_IRQ: | 180 | case ACPI_RSTYPE_EXT_IRQ: |
168 | if ((res->data.extended_irq.number_of_interrupts > 0) && | 181 | for (i = 0; i < res->data.extended_irq.number_of_interrupts; i++) { |
169 | valid_IRQ(res->data.extended_irq.interrupts[0])) { | 182 | pnpacpi_parse_allocated_irqresource(res_table, |
170 | pnpacpi_parse_allocated_irqresource(res_table, | 183 | res->data.extended_irq.interrupts[i], |
171 | acpi_register_gsi(res->data.extended_irq.interrupts[0], | 184 | res->data.extended_irq.edge_level, |
172 | res->data.extended_irq.edge_level, | 185 | res->data.extended_irq.active_high_low); |
173 | res->data.extended_irq.active_high_low)); | ||
174 | pcibios_penalize_isa_irq(res->data.extended_irq.interrupts[0], 1); | ||
175 | } | 186 | } |
176 | break; | 187 | break; |
177 | case ACPI_RSTYPE_DMA: | 188 | case ACPI_RSTYPE_DMA: |