aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/interface.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2008-06-27 18:57:17 -0400
committerAndi Kleen <andi@basil.nowhere.org>2008-07-16 17:27:07 -0400
commit1f32ca31e7409d37c1b25e5f81840fb184380cdf (patch)
treee587c85b46b04dbbb5987e2a4986ab174f3bd6fa /drivers/pnp/interface.c
parentbbe413b4fc7f791248c7ee00ce7b3778491a3700 (diff)
PNP: convert resource options to single linked list
ISAPNP, PNPBIOS, and ACPI describe the "possible resource settings" of a device, i.e., the possibilities an OS bus driver has when it assigns I/O port, MMIO, and other resources to the device. PNP used to maintain this "possible resource setting" information in one independent option structure and a list of dependent option structures for each device. Each of these option structures had lists of I/O, memory, IRQ, and DMA resources, for example: dev independent options ind-io0 -> ind-io1 ... ind-mem0 -> ind-mem1 ... ... dependent option set 0 dep0-io0 -> dep0-io1 ... dep0-mem0 -> dep0-mem1 ... ... dependent option set 1 dep1-io0 -> dep1-io1 ... dep1-mem0 -> dep1-mem1 ... ... ... This data structure was designed for ISAPNP, where the OS configures device resource settings by writing directly to configuration registers. The OS can write the registers in arbitrary order much like it writes PCI BARs. However, for PNPBIOS and ACPI devices, the OS uses firmware interfaces that perform device configuration, and it is important to pass the desired settings to those interfaces in the correct order. The OS learns the correct order by using firmware interfaces that return the "current resource settings" and "possible resource settings," but the option structures above doesn't store the ordering information. This patch replaces the independent and dependent lists with a single list of options. For example, a device might have possible resource settings like this: dev options ind-io0 -> dep0-io0 -> dep1->io0 -> ind-io1 ... All the possible settings are in the same list, in the order they come from the firmware "possible resource settings" list. Each entry is tagged with an independent/dependent flag. Dependent entries also have a "set number" and an optional priority value. All dependent entries must be assigned from the same set. For example, the OS can use all the entries from dependent set 0, or all the entries from dependent set 1, but it cannot mix entries from set 0 with entries from set 1. Prior to this patch PNP didn't keep track of the order of this list, and it assigned all independent options first, then all dependent ones. Using the example above, that resulted in a "desired configuration" list like this: ind->io0 -> ind->io1 -> depN-io0 ... instead of the list the firmware expects, which looks like this: ind->io0 -> depN-io0 -> ind-io1 ... Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Rene Herman <rene.herman@gmail.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pnp/interface.c')
-rw-r--r--drivers/pnp/interface.c75
1 files changed, 35 insertions, 40 deletions
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 7a9fb5544b80..a876ecf7028c 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz> 4 * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
5 * Copyright 2002 Adam Belay <ambx1@neo.rr.com> 5 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
6 */ 8 */
7 9
8#include <linux/pnp.h> 10#include <linux/pnp.h>
@@ -184,39 +186,22 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space,
184} 186}
185 187
186static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, 188static void pnp_print_option(pnp_info_buffer_t * buffer, char *space,
187 struct pnp_option *option, int dep) 189 struct pnp_option *option)
188{ 190{
189 char *s; 191 switch (option->type) {
190 struct pnp_port *port; 192 case IORESOURCE_IO:
191 struct pnp_irq *irq; 193 pnp_print_port(buffer, space, &option->u.port);
192 struct pnp_dma *dma; 194 break;
193 struct pnp_mem *mem; 195 case IORESOURCE_MEM:
194 196 pnp_print_mem(buffer, space, &option->u.mem);
195 if (dep) { 197 break;
196 switch (option->priority) { 198 case IORESOURCE_IRQ:
197 case PNP_RES_PRIORITY_PREFERRED: 199 pnp_print_irq(buffer, space, &option->u.irq);
198 s = "preferred"; 200 break;
199 break; 201 case IORESOURCE_DMA:
200 case PNP_RES_PRIORITY_ACCEPTABLE: 202 pnp_print_dma(buffer, space, &option->u.dma);
201 s = "acceptable"; 203 break;
202 break;
203 case PNP_RES_PRIORITY_FUNCTIONAL:
204 s = "functional";
205 break;
206 default:
207 s = "invalid";
208 }
209 pnp_printf(buffer, "Dependent: %02i - Priority %s\n", dep, s);
210 } 204 }
211
212 for (port = option->port; port; port = port->next)
213 pnp_print_port(buffer, space, port);
214 for (irq = option->irq; irq; irq = irq->next)
215 pnp_print_irq(buffer, space, irq);
216 for (dma = option->dma; dma; dma = dma->next)
217 pnp_print_dma(buffer, space, dma);
218 for (mem = option->mem; mem; mem = mem->next)
219 pnp_print_mem(buffer, space, mem);
220} 205}
221 206
222static ssize_t pnp_show_options(struct device *dmdev, 207static ssize_t pnp_show_options(struct device *dmdev,
@@ -224,9 +209,9 @@ static ssize_t pnp_show_options(struct device *dmdev,
224{ 209{
225 struct pnp_dev *dev = to_pnp_dev(dmdev); 210 struct pnp_dev *dev = to_pnp_dev(dmdev);
226 pnp_info_buffer_t *buffer; 211 pnp_info_buffer_t *buffer;
227 struct pnp_option *independent = dev->independent; 212 struct pnp_option *option;
228 struct pnp_option *dependent = dev->dependent; 213 int ret, dep = 0, set = 0;
229 int ret, dep = 1; 214 char *indent;
230 215
231 buffer = pnp_alloc(sizeof(pnp_info_buffer_t)); 216 buffer = pnp_alloc(sizeof(pnp_info_buffer_t));
232 if (!buffer) 217 if (!buffer)
@@ -235,14 +220,24 @@ static ssize_t pnp_show_options(struct device *dmdev,
235 buffer->len = PAGE_SIZE; 220 buffer->len = PAGE_SIZE;
236 buffer->buffer = buf; 221 buffer->buffer = buf;
237 buffer->curr = buffer->buffer; 222 buffer->curr = buffer->buffer;
238 if (independent)
239 pnp_print_option(buffer, "", independent, 0);
240 223
241 while (dependent) { 224 list_for_each_entry(option, &dev->options, list) {
242 pnp_print_option(buffer, " ", dependent, dep); 225 if (pnp_option_is_dependent(option)) {
243 dependent = dependent->next; 226 indent = " ";
244 dep++; 227 if (!dep || pnp_option_set(option) != set) {
228 set = pnp_option_set(option);
229 dep = 1;
230 pnp_printf(buffer, "Dependent: %02i - "
231 "Priority %s\n", set,
232 pnp_option_priority_name(option));
233 }
234 } else {
235 dep = 0;
236 indent = "";
237 }
238 pnp_print_option(buffer, indent, option);
245 } 239 }
240
246 ret = (buffer->curr - buf); 241 ret = (buffer->curr - buf);
247 kfree(buffer); 242 kfree(buffer);
248 return ret; 243 return ret;