diff options
Diffstat (limited to 'drivers/pnp')
-rw-r--r-- | drivers/pnp/base.h | 148 | ||||
-rw-r--r-- | drivers/pnp/core.c | 29 | ||||
-rw-r--r-- | drivers/pnp/interface.c | 207 | ||||
-rw-r--r-- | drivers/pnp/isapnp/core.c | 253 | ||||
-rw-r--r-- | drivers/pnp/manager.c | 414 | ||||
-rw-r--r-- | drivers/pnp/pnpacpi/core.c | 4 | ||||
-rw-r--r-- | drivers/pnp/pnpacpi/rsparser.c | 492 | ||||
-rw-r--r-- | drivers/pnp/pnpbios/rsparser.c | 274 | ||||
-rw-r--r-- | drivers/pnp/quirks.c | 307 | ||||
-rw-r--r-- | drivers/pnp/resource.c | 454 | ||||
-rw-r--r-- | drivers/pnp/support.c | 171 | ||||
-rw-r--r-- | drivers/pnp/system.c | 4 |
12 files changed, 1396 insertions, 1361 deletions
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 886dac823ed6..e3fa9a2d9a3d 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. | ||
3 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | ||
4 | */ | ||
5 | |||
1 | extern spinlock_t pnp_lock; | 6 | extern spinlock_t pnp_lock; |
2 | void *pnp_alloc(long size); | 7 | void *pnp_alloc(long size); |
3 | 8 | ||
@@ -19,22 +24,118 @@ void pnp_remove_card(struct pnp_card *card); | |||
19 | int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); | 24 | int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); |
20 | void pnp_remove_card_device(struct pnp_dev *dev); | 25 | void pnp_remove_card_device(struct pnp_dev *dev); |
21 | 26 | ||
22 | struct pnp_option *pnp_build_option(int priority); | 27 | struct pnp_port { |
23 | struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev); | 28 | resource_size_t min; /* min base number */ |
24 | struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, | 29 | resource_size_t max; /* max base number */ |
25 | int priority); | 30 | resource_size_t align; /* align boundary */ |
26 | int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, | 31 | resource_size_t size; /* size of range */ |
27 | struct pnp_irq *data); | 32 | unsigned char flags; /* port flags */ |
28 | int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, | 33 | }; |
29 | struct pnp_dma *data); | 34 | |
30 | int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, | 35 | #define PNP_IRQ_NR 256 |
31 | struct pnp_port *data); | 36 | typedef struct { DECLARE_BITMAP(bits, PNP_IRQ_NR); } pnp_irq_mask_t; |
32 | int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, | 37 | |
33 | struct pnp_mem *data); | 38 | struct pnp_irq { |
39 | pnp_irq_mask_t map; /* bitmap for IRQ lines */ | ||
40 | unsigned char flags; /* IRQ flags */ | ||
41 | }; | ||
42 | |||
43 | struct pnp_dma { | ||
44 | unsigned char map; /* bitmask for DMA channels */ | ||
45 | unsigned char flags; /* DMA flags */ | ||
46 | }; | ||
47 | |||
48 | struct pnp_mem { | ||
49 | resource_size_t min; /* min base number */ | ||
50 | resource_size_t max; /* max base number */ | ||
51 | resource_size_t align; /* align boundary */ | ||
52 | resource_size_t size; /* size of range */ | ||
53 | unsigned char flags; /* memory flags */ | ||
54 | }; | ||
55 | |||
56 | #define PNP_OPTION_DEPENDENT 0x80000000 | ||
57 | #define PNP_OPTION_SET_MASK 0xffff | ||
58 | #define PNP_OPTION_SET_SHIFT 12 | ||
59 | #define PNP_OPTION_PRIORITY_MASK 0xfff | ||
60 | #define PNP_OPTION_PRIORITY_SHIFT 0 | ||
61 | |||
62 | #define PNP_RES_PRIORITY_PREFERRED 0 | ||
63 | #define PNP_RES_PRIORITY_ACCEPTABLE 1 | ||
64 | #define PNP_RES_PRIORITY_FUNCTIONAL 2 | ||
65 | #define PNP_RES_PRIORITY_INVALID PNP_OPTION_PRIORITY_MASK | ||
66 | |||
67 | struct pnp_option { | ||
68 | struct list_head list; | ||
69 | unsigned int flags; /* independent/dependent, set, priority */ | ||
70 | |||
71 | unsigned long type; /* IORESOURCE_{IO,MEM,IRQ,DMA} */ | ||
72 | union { | ||
73 | struct pnp_port port; | ||
74 | struct pnp_irq irq; | ||
75 | struct pnp_dma dma; | ||
76 | struct pnp_mem mem; | ||
77 | } u; | ||
78 | }; | ||
79 | |||
80 | int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags, | ||
81 | pnp_irq_mask_t *map, unsigned char flags); | ||
82 | int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags, | ||
83 | unsigned char map, unsigned char flags); | ||
84 | int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags, | ||
85 | resource_size_t min, resource_size_t max, | ||
86 | resource_size_t align, resource_size_t size, | ||
87 | unsigned char flags); | ||
88 | int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags, | ||
89 | resource_size_t min, resource_size_t max, | ||
90 | resource_size_t align, resource_size_t size, | ||
91 | unsigned char flags); | ||
92 | |||
93 | static inline int pnp_option_is_dependent(struct pnp_option *option) | ||
94 | { | ||
95 | return option->flags & PNP_OPTION_DEPENDENT ? 1 : 0; | ||
96 | } | ||
97 | |||
98 | static inline unsigned int pnp_option_set(struct pnp_option *option) | ||
99 | { | ||
100 | return (option->flags >> PNP_OPTION_SET_SHIFT) & PNP_OPTION_SET_MASK; | ||
101 | } | ||
102 | |||
103 | static inline unsigned int pnp_option_priority(struct pnp_option *option) | ||
104 | { | ||
105 | return (option->flags >> PNP_OPTION_PRIORITY_SHIFT) & | ||
106 | PNP_OPTION_PRIORITY_MASK; | ||
107 | } | ||
108 | |||
109 | static inline unsigned int pnp_new_dependent_set(struct pnp_dev *dev, | ||
110 | int priority) | ||
111 | { | ||
112 | unsigned int flags; | ||
113 | |||
114 | if (priority > PNP_RES_PRIORITY_FUNCTIONAL) { | ||
115 | dev_warn(&dev->dev, "invalid dependent option priority %d " | ||
116 | "clipped to %d", priority, | ||
117 | PNP_RES_PRIORITY_INVALID); | ||
118 | priority = PNP_RES_PRIORITY_INVALID; | ||
119 | } | ||
120 | |||
121 | flags = PNP_OPTION_DEPENDENT | | ||
122 | ((dev->num_dependent_sets & PNP_OPTION_SET_MASK) << | ||
123 | PNP_OPTION_SET_SHIFT) | | ||
124 | ((priority & PNP_OPTION_PRIORITY_MASK) << | ||
125 | PNP_OPTION_PRIORITY_SHIFT); | ||
126 | |||
127 | dev->num_dependent_sets++; | ||
128 | |||
129 | return flags; | ||
130 | } | ||
131 | |||
132 | char *pnp_option_priority_name(struct pnp_option *option); | ||
133 | void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option); | ||
134 | |||
34 | void pnp_init_resources(struct pnp_dev *dev); | 135 | void pnp_init_resources(struct pnp_dev *dev); |
35 | 136 | ||
36 | void pnp_fixup_device(struct pnp_dev *dev); | 137 | void pnp_fixup_device(struct pnp_dev *dev); |
37 | void pnp_free_option(struct pnp_option *option); | 138 | void pnp_free_options(struct pnp_dev *dev); |
38 | int __pnp_add_device(struct pnp_dev *dev); | 139 | int __pnp_add_device(struct pnp_dev *dev); |
39 | void __pnp_remove_device(struct pnp_dev *dev); | 140 | void __pnp_remove_device(struct pnp_dev *dev); |
40 | 141 | ||
@@ -43,29 +144,18 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res); | |||
43 | int pnp_check_irq(struct pnp_dev *dev, struct resource *res); | 144 | int pnp_check_irq(struct pnp_dev *dev, struct resource *res); |
44 | int pnp_check_dma(struct pnp_dev *dev, struct resource *res); | 145 | int pnp_check_dma(struct pnp_dev *dev, struct resource *res); |
45 | 146 | ||
147 | char *pnp_resource_type_name(struct resource *res); | ||
46 | void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); | 148 | void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); |
47 | 149 | ||
48 | void pnp_init_resource(struct resource *res); | 150 | void pnp_free_resources(struct pnp_dev *dev); |
49 | 151 | int pnp_resource_type(struct resource *res); | |
50 | struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, | ||
51 | unsigned int type, unsigned int num); | ||
52 | |||
53 | #define PNP_MAX_PORT 40 | ||
54 | #define PNP_MAX_MEM 24 | ||
55 | #define PNP_MAX_IRQ 2 | ||
56 | #define PNP_MAX_DMA 2 | ||
57 | 152 | ||
58 | struct pnp_resource { | 153 | struct pnp_resource { |
154 | struct list_head list; | ||
59 | struct resource res; | 155 | struct resource res; |
60 | unsigned int index; /* ISAPNP config register index */ | ||
61 | }; | 156 | }; |
62 | 157 | ||
63 | struct pnp_resource_table { | 158 | void pnp_free_resource(struct pnp_resource *pnp_res); |
64 | struct pnp_resource port[PNP_MAX_PORT]; | ||
65 | struct pnp_resource mem[PNP_MAX_MEM]; | ||
66 | struct pnp_resource dma[PNP_MAX_DMA]; | ||
67 | struct pnp_resource irq[PNP_MAX_IRQ]; | ||
68 | }; | ||
69 | 159 | ||
70 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, | 160 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, |
71 | int flags); | 161 | int flags); |
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index 20771b7d4482..a411582bcd72 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c | |||
@@ -99,14 +99,28 @@ static void pnp_free_ids(struct pnp_dev *dev) | |||
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | void pnp_free_resource(struct pnp_resource *pnp_res) | ||
103 | { | ||
104 | list_del(&pnp_res->list); | ||
105 | kfree(pnp_res); | ||
106 | } | ||
107 | |||
108 | void pnp_free_resources(struct pnp_dev *dev) | ||
109 | { | ||
110 | struct pnp_resource *pnp_res, *tmp; | ||
111 | |||
112 | list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) { | ||
113 | pnp_free_resource(pnp_res); | ||
114 | } | ||
115 | } | ||
116 | |||
102 | static void pnp_release_device(struct device *dmdev) | 117 | static void pnp_release_device(struct device *dmdev) |
103 | { | 118 | { |
104 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 119 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
105 | 120 | ||
106 | pnp_free_option(dev->independent); | ||
107 | pnp_free_option(dev->dependent); | ||
108 | pnp_free_ids(dev); | 121 | pnp_free_ids(dev); |
109 | kfree(dev->res); | 122 | pnp_free_resources(dev); |
123 | pnp_free_options(dev); | ||
110 | kfree(dev); | 124 | kfree(dev); |
111 | } | 125 | } |
112 | 126 | ||
@@ -119,12 +133,8 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid | |||
119 | if (!dev) | 133 | if (!dev) |
120 | return NULL; | 134 | return NULL; |
121 | 135 | ||
122 | dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); | 136 | INIT_LIST_HEAD(&dev->resources); |
123 | if (!dev->res) { | 137 | INIT_LIST_HEAD(&dev->options); |
124 | kfree(dev); | ||
125 | return NULL; | ||
126 | } | ||
127 | |||
128 | dev->protocol = protocol; | 138 | dev->protocol = protocol; |
129 | dev->number = id; | 139 | dev->number = id; |
130 | dev->dma_mask = DMA_24BIT_MASK; | 140 | dev->dma_mask = DMA_24BIT_MASK; |
@@ -140,7 +150,6 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid | |||
140 | 150 | ||
141 | dev_id = pnp_add_id(dev, pnpid); | 151 | dev_id = pnp_add_id(dev, pnpid); |
142 | if (!dev_id) { | 152 | if (!dev_id) { |
143 | kfree(dev->res); | ||
144 | kfree(dev); | 153 | kfree(dev); |
145 | return NULL; | 154 | return NULL; |
146 | } | 155 | } |
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 5695a79f3a52..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> |
@@ -53,11 +55,13 @@ static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt, ...) | |||
53 | static void pnp_print_port(pnp_info_buffer_t * buffer, char *space, | 55 | static void pnp_print_port(pnp_info_buffer_t * buffer, char *space, |
54 | struct pnp_port *port) | 56 | struct pnp_port *port) |
55 | { | 57 | { |
56 | pnp_printf(buffer, | 58 | pnp_printf(buffer, "%sport %#llx-%#llx, align %#llx, size %#llx, " |
57 | "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n", | 59 | "%i-bit address decoding\n", space, |
58 | space, port->min, port->max, | 60 | (unsigned long long) port->min, |
59 | port->align ? (port->align - 1) : 0, port->size, | 61 | (unsigned long long) port->max, |
60 | port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10); | 62 | port->align ? ((unsigned long long) port->align - 1) : 0, |
63 | (unsigned long long) port->size, | ||
64 | port->flags & IORESOURCE_IO_16BIT_ADDR ? 16 : 10); | ||
61 | } | 65 | } |
62 | 66 | ||
63 | static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, | 67 | static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, |
@@ -67,7 +71,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, | |||
67 | 71 | ||
68 | pnp_printf(buffer, "%sirq ", space); | 72 | pnp_printf(buffer, "%sirq ", space); |
69 | for (i = 0; i < PNP_IRQ_NR; i++) | 73 | for (i = 0; i < PNP_IRQ_NR; i++) |
70 | if (test_bit(i, irq->map)) { | 74 | if (test_bit(i, irq->map.bits)) { |
71 | if (!first) { | 75 | if (!first) { |
72 | pnp_printf(buffer, ","); | 76 | pnp_printf(buffer, ","); |
73 | } else { | 77 | } else { |
@@ -78,7 +82,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, | |||
78 | else | 82 | else |
79 | pnp_printf(buffer, "%i", i); | 83 | pnp_printf(buffer, "%i", i); |
80 | } | 84 | } |
81 | if (bitmap_empty(irq->map, PNP_IRQ_NR)) | 85 | if (bitmap_empty(irq->map.bits, PNP_IRQ_NR)) |
82 | pnp_printf(buffer, "<none>"); | 86 | pnp_printf(buffer, "<none>"); |
83 | if (irq->flags & IORESOURCE_IRQ_HIGHEDGE) | 87 | if (irq->flags & IORESOURCE_IRQ_HIGHEDGE) |
84 | pnp_printf(buffer, " High-Edge"); | 88 | pnp_printf(buffer, " High-Edge"); |
@@ -88,6 +92,8 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, | |||
88 | pnp_printf(buffer, " High-Level"); | 92 | pnp_printf(buffer, " High-Level"); |
89 | if (irq->flags & IORESOURCE_IRQ_LOWLEVEL) | 93 | if (irq->flags & IORESOURCE_IRQ_LOWLEVEL) |
90 | pnp_printf(buffer, " Low-Level"); | 94 | pnp_printf(buffer, " Low-Level"); |
95 | if (irq->flags & IORESOURCE_IRQ_OPTIONAL) | ||
96 | pnp_printf(buffer, " (optional)"); | ||
91 | pnp_printf(buffer, "\n"); | 97 | pnp_printf(buffer, "\n"); |
92 | } | 98 | } |
93 | 99 | ||
@@ -148,8 +154,11 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space, | |||
148 | { | 154 | { |
149 | char *s; | 155 | char *s; |
150 | 156 | ||
151 | pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x", | 157 | pnp_printf(buffer, "%sMemory %#llx-%#llx, align %#llx, size %#llx", |
152 | space, mem->min, mem->max, mem->align, mem->size); | 158 | space, (unsigned long long) mem->min, |
159 | (unsigned long long) mem->max, | ||
160 | (unsigned long long) mem->align, | ||
161 | (unsigned long long) mem->size); | ||
153 | if (mem->flags & IORESOURCE_MEM_WRITEABLE) | 162 | if (mem->flags & IORESOURCE_MEM_WRITEABLE) |
154 | pnp_printf(buffer, ", writeable"); | 163 | pnp_printf(buffer, ", writeable"); |
155 | if (mem->flags & IORESOURCE_MEM_CACHEABLE) | 164 | if (mem->flags & IORESOURCE_MEM_CACHEABLE) |
@@ -177,65 +186,58 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space, | |||
177 | } | 186 | } |
178 | 187 | ||
179 | static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, | 188 | static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, |
180 | struct pnp_option *option, int dep) | 189 | struct pnp_option *option) |
181 | { | 190 | { |
182 | char *s; | 191 | switch (option->type) { |
183 | struct pnp_port *port; | 192 | case IORESOURCE_IO: |
184 | struct pnp_irq *irq; | 193 | pnp_print_port(buffer, space, &option->u.port); |
185 | struct pnp_dma *dma; | 194 | break; |
186 | struct pnp_mem *mem; | 195 | case IORESOURCE_MEM: |
187 | 196 | pnp_print_mem(buffer, space, &option->u.mem); | |
188 | if (dep) { | 197 | break; |
189 | switch (option->priority) { | 198 | case IORESOURCE_IRQ: |
190 | case PNP_RES_PRIORITY_PREFERRED: | 199 | pnp_print_irq(buffer, space, &option->u.irq); |
191 | s = "preferred"; | 200 | break; |
192 | break; | 201 | case IORESOURCE_DMA: |
193 | case PNP_RES_PRIORITY_ACCEPTABLE: | 202 | pnp_print_dma(buffer, space, &option->u.dma); |
194 | s = "acceptable"; | 203 | break; |
195 | break; | ||
196 | case PNP_RES_PRIORITY_FUNCTIONAL: | ||
197 | s = "functional"; | ||
198 | break; | ||
199 | default: | ||
200 | s = "invalid"; | ||
201 | } | ||
202 | pnp_printf(buffer, "Dependent: %02i - Priority %s\n", dep, s); | ||
203 | } | 204 | } |
204 | |||
205 | for (port = option->port; port; port = port->next) | ||
206 | pnp_print_port(buffer, space, port); | ||
207 | for (irq = option->irq; irq; irq = irq->next) | ||
208 | pnp_print_irq(buffer, space, irq); | ||
209 | for (dma = option->dma; dma; dma = dma->next) | ||
210 | pnp_print_dma(buffer, space, dma); | ||
211 | for (mem = option->mem; mem; mem = mem->next) | ||
212 | pnp_print_mem(buffer, space, mem); | ||
213 | } | 205 | } |
214 | 206 | ||
215 | static ssize_t pnp_show_options(struct device *dmdev, | 207 | static ssize_t pnp_show_options(struct device *dmdev, |
216 | struct device_attribute *attr, char *buf) | 208 | struct device_attribute *attr, char *buf) |
217 | { | 209 | { |
218 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 210 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
219 | struct pnp_option *independent = dev->independent; | 211 | pnp_info_buffer_t *buffer; |
220 | struct pnp_option *dependent = dev->dependent; | 212 | struct pnp_option *option; |
221 | int ret, dep = 1; | 213 | int ret, dep = 0, set = 0; |
214 | char *indent; | ||
222 | 215 | ||
223 | pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) | 216 | buffer = pnp_alloc(sizeof(pnp_info_buffer_t)); |
224 | pnp_alloc(sizeof(pnp_info_buffer_t)); | ||
225 | if (!buffer) | 217 | if (!buffer) |
226 | return -ENOMEM; | 218 | return -ENOMEM; |
227 | 219 | ||
228 | buffer->len = PAGE_SIZE; | 220 | buffer->len = PAGE_SIZE; |
229 | buffer->buffer = buf; | 221 | buffer->buffer = buf; |
230 | buffer->curr = buffer->buffer; | 222 | buffer->curr = buffer->buffer; |
231 | if (independent) | ||
232 | pnp_print_option(buffer, "", independent, 0); | ||
233 | 223 | ||
234 | while (dependent) { | 224 | list_for_each_entry(option, &dev->options, list) { |
235 | pnp_print_option(buffer, " ", dependent, dep); | 225 | if (pnp_option_is_dependent(option)) { |
236 | dependent = dependent->next; | 226 | indent = " "; |
237 | 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); | ||
238 | } | 239 | } |
240 | |||
239 | ret = (buffer->curr - buf); | 241 | ret = (buffer->curr - buf); |
240 | kfree(buffer); | 242 | kfree(buffer); |
241 | return ret; | 243 | return ret; |
@@ -248,79 +250,59 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, | |||
248 | char *buf) | 250 | char *buf) |
249 | { | 251 | { |
250 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 252 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
251 | struct resource *res; | ||
252 | int i, ret; | ||
253 | pnp_info_buffer_t *buffer; | 253 | pnp_info_buffer_t *buffer; |
254 | struct pnp_resource *pnp_res; | ||
255 | struct resource *res; | ||
256 | int ret; | ||
254 | 257 | ||
255 | if (!dev) | 258 | if (!dev) |
256 | return -EINVAL; | 259 | return -EINVAL; |
257 | 260 | ||
258 | buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t)); | 261 | buffer = pnp_alloc(sizeof(pnp_info_buffer_t)); |
259 | if (!buffer) | 262 | if (!buffer) |
260 | return -ENOMEM; | 263 | return -ENOMEM; |
264 | |||
261 | buffer->len = PAGE_SIZE; | 265 | buffer->len = PAGE_SIZE; |
262 | buffer->buffer = buf; | 266 | buffer->buffer = buf; |
263 | buffer->curr = buffer->buffer; | 267 | buffer->curr = buffer->buffer; |
264 | 268 | ||
265 | pnp_printf(buffer, "state = "); | 269 | pnp_printf(buffer, "state = %s\n", dev->active ? "active" : "disabled"); |
266 | if (dev->active) | 270 | |
267 | pnp_printf(buffer, "active\n"); | 271 | list_for_each_entry(pnp_res, &dev->resources, list) { |
268 | else | 272 | res = &pnp_res->res; |
269 | pnp_printf(buffer, "disabled\n"); | 273 | |
270 | 274 | pnp_printf(buffer, pnp_resource_type_name(res)); | |
271 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { | 275 | |
272 | if (pnp_resource_valid(res)) { | 276 | if (res->flags & IORESOURCE_DISABLED) { |
273 | pnp_printf(buffer, "io"); | 277 | pnp_printf(buffer, " disabled\n"); |
274 | if (res->flags & IORESOURCE_DISABLED) | 278 | continue; |
275 | pnp_printf(buffer, " disabled\n"); | ||
276 | else | ||
277 | pnp_printf(buffer, " 0x%llx-0x%llx\n", | ||
278 | (unsigned long long) res->start, | ||
279 | (unsigned long long) res->end); | ||
280 | } | ||
281 | } | ||
282 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { | ||
283 | if (pnp_resource_valid(res)) { | ||
284 | pnp_printf(buffer, "mem"); | ||
285 | if (res->flags & IORESOURCE_DISABLED) | ||
286 | pnp_printf(buffer, " disabled\n"); | ||
287 | else | ||
288 | pnp_printf(buffer, " 0x%llx-0x%llx\n", | ||
289 | (unsigned long long) res->start, | ||
290 | (unsigned long long) res->end); | ||
291 | } | ||
292 | } | ||
293 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { | ||
294 | if (pnp_resource_valid(res)) { | ||
295 | pnp_printf(buffer, "irq"); | ||
296 | if (res->flags & IORESOURCE_DISABLED) | ||
297 | pnp_printf(buffer, " disabled\n"); | ||
298 | else | ||
299 | pnp_printf(buffer, " %lld\n", | ||
300 | (unsigned long long) res->start); | ||
301 | } | 279 | } |
302 | } | 280 | |
303 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { | 281 | switch (pnp_resource_type(res)) { |
304 | if (pnp_resource_valid(res)) { | 282 | case IORESOURCE_IO: |
305 | pnp_printf(buffer, "dma"); | 283 | case IORESOURCE_MEM: |
306 | if (res->flags & IORESOURCE_DISABLED) | 284 | pnp_printf(buffer, " %#llx-%#llx\n", |
307 | pnp_printf(buffer, " disabled\n"); | 285 | (unsigned long long) res->start, |
308 | else | 286 | (unsigned long long) res->end); |
309 | pnp_printf(buffer, " %lld\n", | 287 | break; |
310 | (unsigned long long) res->start); | 288 | case IORESOURCE_IRQ: |
289 | case IORESOURCE_DMA: | ||
290 | pnp_printf(buffer, " %lld\n", | ||
291 | (unsigned long long) res->start); | ||
292 | break; | ||
311 | } | 293 | } |
312 | } | 294 | } |
295 | |||
313 | ret = (buffer->curr - buf); | 296 | ret = (buffer->curr - buf); |
314 | kfree(buffer); | 297 | kfree(buffer); |
315 | return ret; | 298 | return ret; |
316 | } | 299 | } |
317 | 300 | ||
318 | static ssize_t | 301 | static ssize_t pnp_set_current_resources(struct device *dmdev, |
319 | pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | 302 | struct device_attribute *attr, |
320 | const char *ubuf, size_t count) | 303 | const char *ubuf, size_t count) |
321 | { | 304 | { |
322 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 305 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
323 | struct pnp_resource *pnp_res; | ||
324 | char *buf = (void *)ubuf; | 306 | char *buf = (void *)ubuf; |
325 | int retval = 0; | 307 | int retval = 0; |
326 | resource_size_t start, end; | 308 | resource_size_t start, end; |
@@ -368,7 +350,6 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
368 | goto done; | 350 | goto done; |
369 | } | 351 | } |
370 | if (!strnicmp(buf, "set", 3)) { | 352 | if (!strnicmp(buf, "set", 3)) { |
371 | int nport = 0, nmem = 0, nirq = 0, ndma = 0; | ||
372 | if (dev->active) | 353 | if (dev->active) |
373 | goto done; | 354 | goto done; |
374 | buf += 3; | 355 | buf += 3; |
@@ -391,10 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
391 | end = simple_strtoul(buf, &buf, 0); | 372 | end = simple_strtoul(buf, &buf, 0); |
392 | } else | 373 | } else |
393 | end = start; | 374 | end = start; |
394 | pnp_res = pnp_add_io_resource(dev, start, end, | 375 | pnp_add_io_resource(dev, start, end, 0); |
395 | 0); | ||
396 | if (pnp_res) | ||
397 | pnp_res->index = nport++; | ||
398 | continue; | 376 | continue; |
399 | } | 377 | } |
400 | if (!strnicmp(buf, "mem", 3)) { | 378 | if (!strnicmp(buf, "mem", 3)) { |
@@ -411,10 +389,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
411 | end = simple_strtoul(buf, &buf, 0); | 389 | end = simple_strtoul(buf, &buf, 0); |
412 | } else | 390 | } else |
413 | end = start; | 391 | end = start; |
414 | pnp_res = pnp_add_mem_resource(dev, start, end, | 392 | pnp_add_mem_resource(dev, start, end, 0); |
415 | 0); | ||
416 | if (pnp_res) | ||
417 | pnp_res->index = nmem++; | ||
418 | continue; | 393 | continue; |
419 | } | 394 | } |
420 | if (!strnicmp(buf, "irq", 3)) { | 395 | if (!strnicmp(buf, "irq", 3)) { |
@@ -422,9 +397,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
422 | while (isspace(*buf)) | 397 | while (isspace(*buf)) |
423 | ++buf; | 398 | ++buf; |
424 | start = simple_strtoul(buf, &buf, 0); | 399 | start = simple_strtoul(buf, &buf, 0); |
425 | pnp_res = pnp_add_irq_resource(dev, start, 0); | 400 | pnp_add_irq_resource(dev, start, 0); |
426 | if (pnp_res) | ||
427 | pnp_res->index = nirq++; | ||
428 | continue; | 401 | continue; |
429 | } | 402 | } |
430 | if (!strnicmp(buf, "dma", 3)) { | 403 | if (!strnicmp(buf, "dma", 3)) { |
@@ -432,9 +405,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
432 | while (isspace(*buf)) | 405 | while (isspace(*buf)) |
433 | ++buf; | 406 | ++buf; |
434 | start = simple_strtoul(buf, &buf, 0); | 407 | start = simple_strtoul(buf, &buf, 0); |
435 | pnp_res = pnp_add_dma_resource(dev, start, 0); | 408 | pnp_add_dma_resource(dev, start, 0); |
436 | if (pnp_res) | ||
437 | pnp_res->index = ndma++; | ||
438 | continue; | 409 | continue; |
439 | } | 410 | } |
440 | break; | 411 | break; |
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index f1bccdbdeb08..101a835e8759 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c | |||
@@ -429,154 +429,135 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, | |||
429 | * Add IRQ resource to resources list. | 429 | * Add IRQ resource to resources list. |
430 | */ | 430 | */ |
431 | static void __init isapnp_parse_irq_resource(struct pnp_dev *dev, | 431 | static void __init isapnp_parse_irq_resource(struct pnp_dev *dev, |
432 | struct pnp_option *option, | 432 | unsigned int option_flags, |
433 | int size) | 433 | int size) |
434 | { | 434 | { |
435 | unsigned char tmp[3]; | 435 | unsigned char tmp[3]; |
436 | struct pnp_irq *irq; | ||
437 | unsigned long bits; | 436 | unsigned long bits; |
437 | pnp_irq_mask_t map; | ||
438 | unsigned char flags = IORESOURCE_IRQ_HIGHEDGE; | ||
438 | 439 | ||
439 | isapnp_peek(tmp, size); | 440 | isapnp_peek(tmp, size); |
440 | irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); | ||
441 | if (!irq) | ||
442 | return; | ||
443 | bits = (tmp[1] << 8) | tmp[0]; | 441 | bits = (tmp[1] << 8) | tmp[0]; |
444 | bitmap_copy(irq->map, &bits, 16); | 442 | |
443 | bitmap_zero(map.bits, PNP_IRQ_NR); | ||
444 | bitmap_copy(map.bits, &bits, 16); | ||
445 | |||
445 | if (size > 2) | 446 | if (size > 2) |
446 | irq->flags = tmp[2]; | 447 | flags = tmp[2]; |
447 | else | 448 | |
448 | irq->flags = IORESOURCE_IRQ_HIGHEDGE; | 449 | pnp_register_irq_resource(dev, option_flags, &map, flags); |
449 | pnp_register_irq_resource(dev, option, irq); | ||
450 | } | 450 | } |
451 | 451 | ||
452 | /* | 452 | /* |
453 | * Add DMA resource to resources list. | 453 | * Add DMA resource to resources list. |
454 | */ | 454 | */ |
455 | static void __init isapnp_parse_dma_resource(struct pnp_dev *dev, | 455 | static void __init isapnp_parse_dma_resource(struct pnp_dev *dev, |
456 | struct pnp_option *option, | 456 | unsigned int option_flags, |
457 | int size) | 457 | int size) |
458 | { | 458 | { |
459 | unsigned char tmp[2]; | 459 | unsigned char tmp[2]; |
460 | struct pnp_dma *dma; | ||
461 | 460 | ||
462 | isapnp_peek(tmp, size); | 461 | isapnp_peek(tmp, size); |
463 | dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); | 462 | pnp_register_dma_resource(dev, option_flags, tmp[0], tmp[1]); |
464 | if (!dma) | ||
465 | return; | ||
466 | dma->map = tmp[0]; | ||
467 | dma->flags = tmp[1]; | ||
468 | pnp_register_dma_resource(dev, option, dma); | ||
469 | } | 463 | } |
470 | 464 | ||
471 | /* | 465 | /* |
472 | * Add port resource to resources list. | 466 | * Add port resource to resources list. |
473 | */ | 467 | */ |
474 | static void __init isapnp_parse_port_resource(struct pnp_dev *dev, | 468 | static void __init isapnp_parse_port_resource(struct pnp_dev *dev, |
475 | struct pnp_option *option, | 469 | unsigned int option_flags, |
476 | int size) | 470 | int size) |
477 | { | 471 | { |
478 | unsigned char tmp[7]; | 472 | unsigned char tmp[7]; |
479 | struct pnp_port *port; | 473 | resource_size_t min, max, align, len; |
474 | unsigned char flags; | ||
480 | 475 | ||
481 | isapnp_peek(tmp, size); | 476 | isapnp_peek(tmp, size); |
482 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); | 477 | min = (tmp[2] << 8) | tmp[1]; |
483 | if (!port) | 478 | max = (tmp[4] << 8) | tmp[3]; |
484 | return; | 479 | align = tmp[5]; |
485 | port->min = (tmp[2] << 8) | tmp[1]; | 480 | len = tmp[6]; |
486 | port->max = (tmp[4] << 8) | tmp[3]; | 481 | flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0; |
487 | port->align = tmp[5]; | 482 | pnp_register_port_resource(dev, option_flags, |
488 | port->size = tmp[6]; | 483 | min, max, align, len, flags); |
489 | port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0; | ||
490 | pnp_register_port_resource(dev, option, port); | ||
491 | } | 484 | } |
492 | 485 | ||
493 | /* | 486 | /* |
494 | * Add fixed port resource to resources list. | 487 | * Add fixed port resource to resources list. |
495 | */ | 488 | */ |
496 | static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev, | 489 | static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev, |
497 | struct pnp_option *option, | 490 | unsigned int option_flags, |
498 | int size) | 491 | int size) |
499 | { | 492 | { |
500 | unsigned char tmp[3]; | 493 | unsigned char tmp[3]; |
501 | struct pnp_port *port; | 494 | resource_size_t base, len; |
502 | 495 | ||
503 | isapnp_peek(tmp, size); | 496 | isapnp_peek(tmp, size); |
504 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); | 497 | base = (tmp[1] << 8) | tmp[0]; |
505 | if (!port) | 498 | len = tmp[2]; |
506 | return; | 499 | pnp_register_port_resource(dev, option_flags, base, base, 0, len, |
507 | port->min = port->max = (tmp[1] << 8) | tmp[0]; | 500 | IORESOURCE_IO_FIXED); |
508 | port->size = tmp[2]; | ||
509 | port->align = 0; | ||
510 | port->flags = PNP_PORT_FLAG_FIXED; | ||
511 | pnp_register_port_resource(dev, option, port); | ||
512 | } | 501 | } |
513 | 502 | ||
514 | /* | 503 | /* |
515 | * Add memory resource to resources list. | 504 | * Add memory resource to resources list. |
516 | */ | 505 | */ |
517 | static void __init isapnp_parse_mem_resource(struct pnp_dev *dev, | 506 | static void __init isapnp_parse_mem_resource(struct pnp_dev *dev, |
518 | struct pnp_option *option, | 507 | unsigned int option_flags, |
519 | int size) | 508 | int size) |
520 | { | 509 | { |
521 | unsigned char tmp[9]; | 510 | unsigned char tmp[9]; |
522 | struct pnp_mem *mem; | 511 | resource_size_t min, max, align, len; |
512 | unsigned char flags; | ||
523 | 513 | ||
524 | isapnp_peek(tmp, size); | 514 | isapnp_peek(tmp, size); |
525 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 515 | min = ((tmp[2] << 8) | tmp[1]) << 8; |
526 | if (!mem) | 516 | max = ((tmp[4] << 8) | tmp[3]) << 8; |
527 | return; | 517 | align = (tmp[6] << 8) | tmp[5]; |
528 | mem->min = ((tmp[2] << 8) | tmp[1]) << 8; | 518 | len = ((tmp[8] << 8) | tmp[7]) << 8; |
529 | mem->max = ((tmp[4] << 8) | tmp[3]) << 8; | 519 | flags = tmp[0]; |
530 | mem->align = (tmp[6] << 8) | tmp[5]; | 520 | pnp_register_mem_resource(dev, option_flags, |
531 | mem->size = ((tmp[8] << 8) | tmp[7]) << 8; | 521 | min, max, align, len, flags); |
532 | mem->flags = tmp[0]; | ||
533 | pnp_register_mem_resource(dev, option, mem); | ||
534 | } | 522 | } |
535 | 523 | ||
536 | /* | 524 | /* |
537 | * Add 32-bit memory resource to resources list. | 525 | * Add 32-bit memory resource to resources list. |
538 | */ | 526 | */ |
539 | static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev, | 527 | static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev, |
540 | struct pnp_option *option, | 528 | unsigned int option_flags, |
541 | int size) | 529 | int size) |
542 | { | 530 | { |
543 | unsigned char tmp[17]; | 531 | unsigned char tmp[17]; |
544 | struct pnp_mem *mem; | 532 | resource_size_t min, max, align, len; |
533 | unsigned char flags; | ||
545 | 534 | ||
546 | isapnp_peek(tmp, size); | 535 | isapnp_peek(tmp, size); |
547 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 536 | min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; |
548 | if (!mem) | 537 | max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; |
549 | return; | 538 | align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; |
550 | mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; | 539 | len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; |
551 | mem->max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; | 540 | flags = tmp[0]; |
552 | mem->align = | 541 | pnp_register_mem_resource(dev, option_flags, |
553 | (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; | 542 | min, max, align, len, flags); |
554 | mem->size = | ||
555 | (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; | ||
556 | mem->flags = tmp[0]; | ||
557 | pnp_register_mem_resource(dev, option, mem); | ||
558 | } | 543 | } |
559 | 544 | ||
560 | /* | 545 | /* |
561 | * Add 32-bit fixed memory resource to resources list. | 546 | * Add 32-bit fixed memory resource to resources list. |
562 | */ | 547 | */ |
563 | static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev, | 548 | static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev, |
564 | struct pnp_option *option, | 549 | unsigned int option_flags, |
565 | int size) | 550 | int size) |
566 | { | 551 | { |
567 | unsigned char tmp[9]; | 552 | unsigned char tmp[9]; |
568 | struct pnp_mem *mem; | 553 | resource_size_t base, len; |
554 | unsigned char flags; | ||
569 | 555 | ||
570 | isapnp_peek(tmp, size); | 556 | isapnp_peek(tmp, size); |
571 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 557 | base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; |
572 | if (!mem) | 558 | len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; |
573 | return; | 559 | flags = tmp[0]; |
574 | mem->min = mem->max = | 560 | pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags); |
575 | (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; | ||
576 | mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; | ||
577 | mem->align = 0; | ||
578 | mem->flags = tmp[0]; | ||
579 | pnp_register_mem_resource(dev, option, mem); | ||
580 | } | 561 | } |
581 | 562 | ||
582 | /* | 563 | /* |
@@ -604,20 +585,16 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) | |||
604 | static int __init isapnp_create_device(struct pnp_card *card, | 585 | static int __init isapnp_create_device(struct pnp_card *card, |
605 | unsigned short size) | 586 | unsigned short size) |
606 | { | 587 | { |
607 | int number = 0, skip = 0, priority = 0, compat = 0; | 588 | int number = 0, skip = 0, priority, compat = 0; |
608 | unsigned char type, tmp[17]; | 589 | unsigned char type, tmp[17]; |
609 | struct pnp_option *option; | 590 | unsigned int option_flags; |
610 | struct pnp_dev *dev; | 591 | struct pnp_dev *dev; |
611 | u32 eisa_id; | 592 | u32 eisa_id; |
612 | char id[8]; | 593 | char id[8]; |
613 | 594 | ||
614 | if ((dev = isapnp_parse_device(card, size, number++)) == NULL) | 595 | if ((dev = isapnp_parse_device(card, size, number++)) == NULL) |
615 | return 1; | 596 | return 1; |
616 | option = pnp_register_independent_option(dev); | 597 | option_flags = 0; |
617 | if (!option) { | ||
618 | kfree(dev); | ||
619 | return 1; | ||
620 | } | ||
621 | pnp_add_card_device(card, dev); | 598 | pnp_add_card_device(card, dev); |
622 | 599 | ||
623 | while (1) { | 600 | while (1) { |
@@ -634,16 +611,11 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
634 | return 1; | 611 | return 1; |
635 | size = 0; | 612 | size = 0; |
636 | skip = 0; | 613 | skip = 0; |
637 | option = pnp_register_independent_option(dev); | 614 | option_flags = 0; |
638 | if (!option) { | ||
639 | kfree(dev); | ||
640 | return 1; | ||
641 | } | ||
642 | pnp_add_card_device(card, dev); | 615 | pnp_add_card_device(card, dev); |
643 | } else { | 616 | } else { |
644 | skip = 1; | 617 | skip = 1; |
645 | } | 618 | } |
646 | priority = 0; | ||
647 | compat = 0; | 619 | compat = 0; |
648 | break; | 620 | break; |
649 | case _STAG_COMPATDEVID: | 621 | case _STAG_COMPATDEVID: |
@@ -660,44 +632,42 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
660 | case _STAG_IRQ: | 632 | case _STAG_IRQ: |
661 | if (size < 2 || size > 3) | 633 | if (size < 2 || size > 3) |
662 | goto __skip; | 634 | goto __skip; |
663 | isapnp_parse_irq_resource(dev, option, size); | 635 | isapnp_parse_irq_resource(dev, option_flags, size); |
664 | size = 0; | 636 | size = 0; |
665 | break; | 637 | break; |
666 | case _STAG_DMA: | 638 | case _STAG_DMA: |
667 | if (size != 2) | 639 | if (size != 2) |
668 | goto __skip; | 640 | goto __skip; |
669 | isapnp_parse_dma_resource(dev, option, size); | 641 | isapnp_parse_dma_resource(dev, option_flags, size); |
670 | size = 0; | 642 | size = 0; |
671 | break; | 643 | break; |
672 | case _STAG_STARTDEP: | 644 | case _STAG_STARTDEP: |
673 | if (size > 1) | 645 | if (size > 1) |
674 | goto __skip; | 646 | goto __skip; |
675 | priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; | 647 | priority = PNP_RES_PRIORITY_ACCEPTABLE; |
676 | if (size > 0) { | 648 | if (size > 0) { |
677 | isapnp_peek(tmp, size); | 649 | isapnp_peek(tmp, size); |
678 | priority = 0x100 | tmp[0]; | 650 | priority = tmp[0]; |
679 | size = 0; | 651 | size = 0; |
680 | } | 652 | } |
681 | option = pnp_register_dependent_option(dev, priority); | 653 | option_flags = pnp_new_dependent_set(dev, priority); |
682 | if (!option) | ||
683 | return 1; | ||
684 | break; | 654 | break; |
685 | case _STAG_ENDDEP: | 655 | case _STAG_ENDDEP: |
686 | if (size != 0) | 656 | if (size != 0) |
687 | goto __skip; | 657 | goto __skip; |
688 | priority = 0; | 658 | option_flags = 0; |
689 | dev_dbg(&dev->dev, "end dependent options\n"); | ||
690 | break; | 659 | break; |
691 | case _STAG_IOPORT: | 660 | case _STAG_IOPORT: |
692 | if (size != 7) | 661 | if (size != 7) |
693 | goto __skip; | 662 | goto __skip; |
694 | isapnp_parse_port_resource(dev, option, size); | 663 | isapnp_parse_port_resource(dev, option_flags, size); |
695 | size = 0; | 664 | size = 0; |
696 | break; | 665 | break; |
697 | case _STAG_FIXEDIO: | 666 | case _STAG_FIXEDIO: |
698 | if (size != 3) | 667 | if (size != 3) |
699 | goto __skip; | 668 | goto __skip; |
700 | isapnp_parse_fixed_port_resource(dev, option, size); | 669 | isapnp_parse_fixed_port_resource(dev, option_flags, |
670 | size); | ||
701 | size = 0; | 671 | size = 0; |
702 | break; | 672 | break; |
703 | case _STAG_VENDOR: | 673 | case _STAG_VENDOR: |
@@ -705,7 +675,7 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
705 | case _LTAG_MEMRANGE: | 675 | case _LTAG_MEMRANGE: |
706 | if (size != 9) | 676 | if (size != 9) |
707 | goto __skip; | 677 | goto __skip; |
708 | isapnp_parse_mem_resource(dev, option, size); | 678 | isapnp_parse_mem_resource(dev, option_flags, size); |
709 | size = 0; | 679 | size = 0; |
710 | break; | 680 | break; |
711 | case _LTAG_ANSISTR: | 681 | case _LTAG_ANSISTR: |
@@ -720,13 +690,14 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
720 | case _LTAG_MEM32RANGE: | 690 | case _LTAG_MEM32RANGE: |
721 | if (size != 17) | 691 | if (size != 17) |
722 | goto __skip; | 692 | goto __skip; |
723 | isapnp_parse_mem32_resource(dev, option, size); | 693 | isapnp_parse_mem32_resource(dev, option_flags, size); |
724 | size = 0; | 694 | size = 0; |
725 | break; | 695 | break; |
726 | case _LTAG_FIXEDMEM32RANGE: | 696 | case _LTAG_FIXEDMEM32RANGE: |
727 | if (size != 9) | 697 | if (size != 9) |
728 | goto __skip; | 698 | goto __skip; |
729 | isapnp_parse_fixed_mem32_resource(dev, option, size); | 699 | isapnp_parse_fixed_mem32_resource(dev, option_flags, |
700 | size); | ||
730 | size = 0; | 701 | size = 0; |
731 | break; | 702 | break; |
732 | case _STAG_END: | 703 | case _STAG_END: |
@@ -928,7 +899,6 @@ EXPORT_SYMBOL(isapnp_write_byte); | |||
928 | 899 | ||
929 | static int isapnp_get_resources(struct pnp_dev *dev) | 900 | static int isapnp_get_resources(struct pnp_dev *dev) |
930 | { | 901 | { |
931 | struct pnp_resource *pnp_res; | ||
932 | int i, ret; | 902 | int i, ret; |
933 | 903 | ||
934 | dev_dbg(&dev->dev, "get resources\n"); | 904 | dev_dbg(&dev->dev, "get resources\n"); |
@@ -940,35 +910,23 @@ static int isapnp_get_resources(struct pnp_dev *dev) | |||
940 | 910 | ||
941 | for (i = 0; i < ISAPNP_MAX_PORT; i++) { | 911 | for (i = 0; i < ISAPNP_MAX_PORT; i++) { |
942 | ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)); | 912 | ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)); |
943 | if (ret) { | 913 | pnp_add_io_resource(dev, ret, ret, |
944 | pnp_res = pnp_add_io_resource(dev, ret, ret, 0); | 914 | ret == 0 ? IORESOURCE_DISABLED : 0); |
945 | if (pnp_res) | ||
946 | pnp_res->index = i; | ||
947 | } | ||
948 | } | 915 | } |
949 | for (i = 0; i < ISAPNP_MAX_MEM; i++) { | 916 | for (i = 0; i < ISAPNP_MAX_MEM; i++) { |
950 | ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8; | 917 | ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8; |
951 | if (ret) { | 918 | pnp_add_mem_resource(dev, ret, ret, |
952 | pnp_res = pnp_add_mem_resource(dev, ret, ret, 0); | 919 | ret == 0 ? IORESOURCE_DISABLED : 0); |
953 | if (pnp_res) | ||
954 | pnp_res->index = i; | ||
955 | } | ||
956 | } | 920 | } |
957 | for (i = 0; i < ISAPNP_MAX_IRQ; i++) { | 921 | for (i = 0; i < ISAPNP_MAX_IRQ; i++) { |
958 | ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8; | 922 | ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8; |
959 | if (ret) { | 923 | pnp_add_irq_resource(dev, ret, |
960 | pnp_res = pnp_add_irq_resource(dev, ret, 0); | 924 | ret == 0 ? IORESOURCE_DISABLED : 0); |
961 | if (pnp_res) | ||
962 | pnp_res->index = i; | ||
963 | } | ||
964 | } | 925 | } |
965 | for (i = 0; i < ISAPNP_MAX_DMA; i++) { | 926 | for (i = 0; i < ISAPNP_MAX_DMA; i++) { |
966 | ret = isapnp_read_byte(ISAPNP_CFG_DMA + i); | 927 | ret = isapnp_read_byte(ISAPNP_CFG_DMA + i); |
967 | if (ret != 4) { | 928 | pnp_add_dma_resource(dev, ret, |
968 | pnp_res = pnp_add_dma_resource(dev, ret, 0); | 929 | ret == 4 ? IORESOURCE_DISABLED : 0); |
969 | if (pnp_res) | ||
970 | pnp_res->index = i; | ||
971 | } | ||
972 | } | 930 | } |
973 | 931 | ||
974 | __end: | 932 | __end: |
@@ -978,62 +936,45 @@ __end: | |||
978 | 936 | ||
979 | static int isapnp_set_resources(struct pnp_dev *dev) | 937 | static int isapnp_set_resources(struct pnp_dev *dev) |
980 | { | 938 | { |
981 | struct pnp_resource *pnp_res; | ||
982 | struct resource *res; | 939 | struct resource *res; |
983 | int tmp, index; | 940 | int tmp; |
984 | 941 | ||
985 | dev_dbg(&dev->dev, "set resources\n"); | 942 | dev_dbg(&dev->dev, "set resources\n"); |
986 | isapnp_cfg_begin(dev->card->number, dev->number); | 943 | isapnp_cfg_begin(dev->card->number, dev->number); |
987 | dev->active = 1; | 944 | dev->active = 1; |
988 | for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { | 945 | for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { |
989 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp); | 946 | res = pnp_get_resource(dev, IORESOURCE_IO, tmp); |
990 | if (!pnp_res) | 947 | if (pnp_resource_enabled(res)) { |
991 | continue; | ||
992 | res = &pnp_res->res; | ||
993 | if (pnp_resource_valid(res)) { | ||
994 | index = pnp_res->index; | ||
995 | dev_dbg(&dev->dev, " set io %d to %#llx\n", | 948 | dev_dbg(&dev->dev, " set io %d to %#llx\n", |
996 | index, (unsigned long long) res->start); | 949 | tmp, (unsigned long long) res->start); |
997 | isapnp_write_word(ISAPNP_CFG_PORT + (index << 1), | 950 | isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), |
998 | res->start); | 951 | res->start); |
999 | } | 952 | } |
1000 | } | 953 | } |
1001 | for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { | 954 | for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { |
1002 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp); | 955 | res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); |
1003 | if (!pnp_res) | 956 | if (pnp_resource_enabled(res)) { |
1004 | continue; | ||
1005 | res = &pnp_res->res; | ||
1006 | if (pnp_resource_valid(res)) { | ||
1007 | int irq = res->start; | 957 | int irq = res->start; |
1008 | if (irq == 2) | 958 | if (irq == 2) |
1009 | irq = 9; | 959 | irq = 9; |
1010 | index = pnp_res->index; | 960 | dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); |
1011 | dev_dbg(&dev->dev, " set irq %d to %d\n", index, irq); | 961 | isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); |
1012 | isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq); | ||
1013 | } | 962 | } |
1014 | } | 963 | } |
1015 | for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { | 964 | for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { |
1016 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp); | 965 | res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); |
1017 | if (!pnp_res) | 966 | if (pnp_resource_enabled(res)) { |
1018 | continue; | ||
1019 | res = &pnp_res->res; | ||
1020 | if (pnp_resource_valid(res)) { | ||
1021 | index = pnp_res->index; | ||
1022 | dev_dbg(&dev->dev, " set dma %d to %lld\n", | 967 | dev_dbg(&dev->dev, " set dma %d to %lld\n", |
1023 | index, (unsigned long long) res->start); | 968 | tmp, (unsigned long long) res->start); |
1024 | isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start); | 969 | isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start); |
1025 | } | 970 | } |
1026 | } | 971 | } |
1027 | for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { | 972 | for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { |
1028 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp); | 973 | res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); |
1029 | if (!pnp_res) | 974 | if (pnp_resource_enabled(res)) { |
1030 | continue; | ||
1031 | res = &pnp_res->res; | ||
1032 | if (pnp_resource_valid(res)) { | ||
1033 | index = pnp_res->index; | ||
1034 | dev_dbg(&dev->dev, " set mem %d to %#llx\n", | 975 | dev_dbg(&dev->dev, " set mem %d to %#llx\n", |
1035 | index, (unsigned long long) res->start); | 976 | tmp, (unsigned long long) res->start); |
1036 | isapnp_write_word(ISAPNP_CFG_MEM + (index << 3), | 977 | isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), |
1037 | (res->start >> 8) & 0xffff); | 978 | (res->start >> 8) & 0xffff); |
1038 | } | 979 | } |
1039 | } | 980 | } |
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index bea0914ff947..b526eaad3f6c 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz> | 4 | * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz> |
5 | * Copyright 2003 Adam Belay <ambx1@neo.rr.com> | 5 | * Copyright 2003 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/errno.h> | 10 | #include <linux/errno.h> |
@@ -19,82 +21,64 @@ DEFINE_MUTEX(pnp_res_mutex); | |||
19 | 21 | ||
20 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) | 22 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) |
21 | { | 23 | { |
22 | struct pnp_resource *pnp_res; | 24 | struct resource *res, local_res; |
23 | struct resource *res; | ||
24 | |||
25 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx); | ||
26 | if (!pnp_res) { | ||
27 | dev_err(&dev->dev, "too many I/O port resources\n"); | ||
28 | /* pretend we were successful so at least the manager won't try again */ | ||
29 | return 1; | ||
30 | } | ||
31 | |||
32 | res = &pnp_res->res; | ||
33 | 25 | ||
34 | /* check if this resource has been manually set, if so skip */ | 26 | res = pnp_get_resource(dev, IORESOURCE_IO, idx); |
35 | if (!(res->flags & IORESOURCE_AUTO)) { | 27 | if (res) { |
36 | dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " | 28 | dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " |
37 | "flags %#lx\n", idx, (unsigned long long) res->start, | 29 | "flags %#lx\n", idx, (unsigned long long) res->start, |
38 | (unsigned long long) res->end, res->flags); | 30 | (unsigned long long) res->end, res->flags); |
39 | return 1; | 31 | return 0; |
40 | } | 32 | } |
41 | 33 | ||
42 | /* set the initial values */ | 34 | res = &local_res; |
43 | pnp_res->index = idx; | 35 | res->flags = rule->flags | IORESOURCE_AUTO; |
44 | res->flags |= rule->flags | IORESOURCE_IO; | 36 | res->start = 0; |
45 | res->flags &= ~IORESOURCE_UNSET; | 37 | res->end = 0; |
46 | 38 | ||
47 | if (!rule->size) { | 39 | if (!rule->size) { |
48 | res->flags |= IORESOURCE_DISABLED; | 40 | res->flags |= IORESOURCE_DISABLED; |
49 | dev_dbg(&dev->dev, " io %d disabled\n", idx); | 41 | dev_dbg(&dev->dev, " io %d disabled\n", idx); |
50 | return 1; /* skip disabled resource requests */ | 42 | goto __add; |
51 | } | 43 | } |
52 | 44 | ||
53 | res->start = rule->min; | 45 | res->start = rule->min; |
54 | res->end = res->start + rule->size - 1; | 46 | res->end = res->start + rule->size - 1; |
55 | 47 | ||
56 | /* run through until pnp_check_port is happy */ | ||
57 | while (!pnp_check_port(dev, res)) { | 48 | while (!pnp_check_port(dev, res)) { |
58 | res->start += rule->align; | 49 | res->start += rule->align; |
59 | res->end = res->start + rule->size - 1; | 50 | res->end = res->start + rule->size - 1; |
60 | if (res->start > rule->max || !rule->align) { | 51 | if (res->start > rule->max || !rule->align) { |
61 | dev_dbg(&dev->dev, " couldn't assign io %d\n", idx); | 52 | dev_dbg(&dev->dev, " couldn't assign io %d " |
62 | return 0; | 53 | "(min %#llx max %#llx)\n", idx, |
54 | (unsigned long long) rule->min, | ||
55 | (unsigned long long) rule->max); | ||
56 | return -EBUSY; | ||
63 | } | 57 | } |
64 | } | 58 | } |
65 | dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, | 59 | |
66 | (unsigned long long) res->start, (unsigned long long) res->end); | 60 | __add: |
67 | return 1; | 61 | pnp_add_io_resource(dev, res->start, res->end, res->flags); |
62 | return 0; | ||
68 | } | 63 | } |
69 | 64 | ||
70 | static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) | 65 | static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) |
71 | { | 66 | { |
72 | struct pnp_resource *pnp_res; | 67 | struct resource *res, local_res; |
73 | struct resource *res; | ||
74 | |||
75 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx); | ||
76 | if (!pnp_res) { | ||
77 | dev_err(&dev->dev, "too many memory resources\n"); | ||
78 | /* pretend we were successful so at least the manager won't try again */ | ||
79 | return 1; | ||
80 | } | ||
81 | 68 | ||
82 | res = &pnp_res->res; | 69 | res = pnp_get_resource(dev, IORESOURCE_MEM, idx); |
83 | 70 | if (res) { | |
84 | /* check if this resource has been manually set, if so skip */ | ||
85 | if (!(res->flags & IORESOURCE_AUTO)) { | ||
86 | dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " | 71 | dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " |
87 | "flags %#lx\n", idx, (unsigned long long) res->start, | 72 | "flags %#lx\n", idx, (unsigned long long) res->start, |
88 | (unsigned long long) res->end, res->flags); | 73 | (unsigned long long) res->end, res->flags); |
89 | return 1; | 74 | return 0; |
90 | } | 75 | } |
91 | 76 | ||
92 | /* set the initial values */ | 77 | res = &local_res; |
93 | pnp_res->index = idx; | 78 | res->flags = rule->flags | IORESOURCE_AUTO; |
94 | res->flags |= rule->flags | IORESOURCE_MEM; | 79 | res->start = 0; |
95 | res->flags &= ~IORESOURCE_UNSET; | 80 | res->end = 0; |
96 | 81 | ||
97 | /* convert pnp flags to standard Linux flags */ | ||
98 | if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) | 82 | if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) |
99 | res->flags |= IORESOURCE_READONLY; | 83 | res->flags |= IORESOURCE_READONLY; |
100 | if (rule->flags & IORESOURCE_MEM_CACHEABLE) | 84 | if (rule->flags & IORESOURCE_MEM_CACHEABLE) |
@@ -107,30 +91,32 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) | |||
107 | if (!rule->size) { | 91 | if (!rule->size) { |
108 | res->flags |= IORESOURCE_DISABLED; | 92 | res->flags |= IORESOURCE_DISABLED; |
109 | dev_dbg(&dev->dev, " mem %d disabled\n", idx); | 93 | dev_dbg(&dev->dev, " mem %d disabled\n", idx); |
110 | return 1; /* skip disabled resource requests */ | 94 | goto __add; |
111 | } | 95 | } |
112 | 96 | ||
113 | res->start = rule->min; | 97 | res->start = rule->min; |
114 | res->end = res->start + rule->size - 1; | 98 | res->end = res->start + rule->size - 1; |
115 | 99 | ||
116 | /* run through until pnp_check_mem is happy */ | ||
117 | while (!pnp_check_mem(dev, res)) { | 100 | while (!pnp_check_mem(dev, res)) { |
118 | res->start += rule->align; | 101 | res->start += rule->align; |
119 | res->end = res->start + rule->size - 1; | 102 | res->end = res->start + rule->size - 1; |
120 | if (res->start > rule->max || !rule->align) { | 103 | if (res->start > rule->max || !rule->align) { |
121 | dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx); | 104 | dev_dbg(&dev->dev, " couldn't assign mem %d " |
122 | return 0; | 105 | "(min %#llx max %#llx)\n", idx, |
106 | (unsigned long long) rule->min, | ||
107 | (unsigned long long) rule->max); | ||
108 | return -EBUSY; | ||
123 | } | 109 | } |
124 | } | 110 | } |
125 | dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, | 111 | |
126 | (unsigned long long) res->start, (unsigned long long) res->end); | 112 | __add: |
127 | return 1; | 113 | pnp_add_mem_resource(dev, res->start, res->end, res->flags); |
114 | return 0; | ||
128 | } | 115 | } |
129 | 116 | ||
130 | static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) | 117 | static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) |
131 | { | 118 | { |
132 | struct pnp_resource *pnp_res; | 119 | struct resource *res, local_res; |
133 | struct resource *res; | ||
134 | int i; | 120 | int i; |
135 | 121 | ||
136 | /* IRQ priority: this table is good for i386 */ | 122 | /* IRQ priority: this table is good for i386 */ |
@@ -138,59 +124,57 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) | |||
138 | 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 | 124 | 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 |
139 | }; | 125 | }; |
140 | 126 | ||
141 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx); | 127 | res = pnp_get_resource(dev, IORESOURCE_IRQ, idx); |
142 | if (!pnp_res) { | 128 | if (res) { |
143 | dev_err(&dev->dev, "too many IRQ resources\n"); | ||
144 | /* pretend we were successful so at least the manager won't try again */ | ||
145 | return 1; | ||
146 | } | ||
147 | |||
148 | res = &pnp_res->res; | ||
149 | |||
150 | /* check if this resource has been manually set, if so skip */ | ||
151 | if (!(res->flags & IORESOURCE_AUTO)) { | ||
152 | dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", | 129 | dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", |
153 | idx, (int) res->start, res->flags); | 130 | idx, (int) res->start, res->flags); |
154 | return 1; | 131 | return 0; |
155 | } | 132 | } |
156 | 133 | ||
157 | /* set the initial values */ | 134 | res = &local_res; |
158 | pnp_res->index = idx; | 135 | res->flags = rule->flags | IORESOURCE_AUTO; |
159 | res->flags |= rule->flags | IORESOURCE_IRQ; | 136 | res->start = -1; |
160 | res->flags &= ~IORESOURCE_UNSET; | 137 | res->end = -1; |
161 | 138 | ||
162 | if (bitmap_empty(rule->map, PNP_IRQ_NR)) { | 139 | if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) { |
163 | res->flags |= IORESOURCE_DISABLED; | 140 | res->flags |= IORESOURCE_DISABLED; |
164 | dev_dbg(&dev->dev, " irq %d disabled\n", idx); | 141 | dev_dbg(&dev->dev, " irq %d disabled\n", idx); |
165 | return 1; /* skip disabled resource requests */ | 142 | goto __add; |
166 | } | 143 | } |
167 | 144 | ||
168 | /* TBD: need check for >16 IRQ */ | 145 | /* TBD: need check for >16 IRQ */ |
169 | res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16); | 146 | res->start = find_next_bit(rule->map.bits, PNP_IRQ_NR, 16); |
170 | if (res->start < PNP_IRQ_NR) { | 147 | if (res->start < PNP_IRQ_NR) { |
171 | res->end = res->start; | 148 | res->end = res->start; |
172 | dev_dbg(&dev->dev, " assign irq %d %d\n", idx, | 149 | goto __add; |
173 | (int) res->start); | ||
174 | return 1; | ||
175 | } | 150 | } |
176 | for (i = 0; i < 16; i++) { | 151 | for (i = 0; i < 16; i++) { |
177 | if (test_bit(xtab[i], rule->map)) { | 152 | if (test_bit(xtab[i], rule->map.bits)) { |
178 | res->start = res->end = xtab[i]; | 153 | res->start = res->end = xtab[i]; |
179 | if (pnp_check_irq(dev, res)) { | 154 | if (pnp_check_irq(dev, res)) |
180 | dev_dbg(&dev->dev, " assign irq %d %d\n", idx, | 155 | goto __add; |
181 | (int) res->start); | ||
182 | return 1; | ||
183 | } | ||
184 | } | 156 | } |
185 | } | 157 | } |
158 | |||
159 | if (rule->flags & IORESOURCE_IRQ_OPTIONAL) { | ||
160 | res->start = -1; | ||
161 | res->end = -1; | ||
162 | res->flags |= IORESOURCE_DISABLED; | ||
163 | dev_dbg(&dev->dev, " irq %d disabled (optional)\n", idx); | ||
164 | goto __add; | ||
165 | } | ||
166 | |||
186 | dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); | 167 | dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); |
168 | return -EBUSY; | ||
169 | |||
170 | __add: | ||
171 | pnp_add_irq_resource(dev, res->start, res->flags); | ||
187 | return 0; | 172 | return 0; |
188 | } | 173 | } |
189 | 174 | ||
190 | static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) | 175 | static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) |
191 | { | 176 | { |
192 | struct pnp_resource *pnp_res; | 177 | struct resource *res, local_res; |
193 | struct resource *res; | ||
194 | int i; | 178 | int i; |
195 | 179 | ||
196 | /* DMA priority: this table is good for i386 */ | 180 | /* DMA priority: this table is good for i386 */ |
@@ -198,231 +182,99 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) | |||
198 | 1, 3, 5, 6, 7, 0, 2, 4 | 182 | 1, 3, 5, 6, 7, 0, 2, 4 |
199 | }; | 183 | }; |
200 | 184 | ||
201 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx); | 185 | res = pnp_get_resource(dev, IORESOURCE_DMA, idx); |
202 | if (!pnp_res) { | 186 | if (res) { |
203 | dev_err(&dev->dev, "too many DMA resources\n"); | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | res = &pnp_res->res; | ||
208 | |||
209 | /* check if this resource has been manually set, if so skip */ | ||
210 | if (!(res->flags & IORESOURCE_AUTO)) { | ||
211 | dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", | 187 | dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", |
212 | idx, (int) res->start, res->flags); | 188 | idx, (int) res->start, res->flags); |
213 | return; | 189 | return 0; |
214 | } | 190 | } |
215 | 191 | ||
216 | /* set the initial values */ | 192 | res = &local_res; |
217 | pnp_res->index = idx; | 193 | res->flags = rule->flags | IORESOURCE_AUTO; |
218 | res->flags |= rule->flags | IORESOURCE_DMA; | 194 | res->start = -1; |
219 | res->flags &= ~IORESOURCE_UNSET; | 195 | res->end = -1; |
220 | 196 | ||
221 | for (i = 0; i < 8; i++) { | 197 | for (i = 0; i < 8; i++) { |
222 | if (rule->map & (1 << xtab[i])) { | 198 | if (rule->map & (1 << xtab[i])) { |
223 | res->start = res->end = xtab[i]; | 199 | res->start = res->end = xtab[i]; |
224 | if (pnp_check_dma(dev, res)) { | 200 | if (pnp_check_dma(dev, res)) |
225 | dev_dbg(&dev->dev, " assign dma %d %d\n", idx, | 201 | goto __add; |
226 | (int) res->start); | ||
227 | return; | ||
228 | } | ||
229 | } | 202 | } |
230 | } | 203 | } |
231 | #ifdef MAX_DMA_CHANNELS | 204 | #ifdef MAX_DMA_CHANNELS |
232 | res->start = res->end = MAX_DMA_CHANNELS; | 205 | res->start = res->end = MAX_DMA_CHANNELS; |
233 | #endif | 206 | #endif |
234 | res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; | 207 | res->flags |= IORESOURCE_DISABLED; |
235 | dev_dbg(&dev->dev, " disable dma %d\n", idx); | 208 | dev_dbg(&dev->dev, " disable dma %d\n", idx); |
236 | } | ||
237 | |||
238 | void pnp_init_resource(struct resource *res) | ||
239 | { | ||
240 | unsigned long type; | ||
241 | |||
242 | type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM | | ||
243 | IORESOURCE_IRQ | IORESOURCE_DMA); | ||
244 | 209 | ||
245 | res->name = NULL; | 210 | __add: |
246 | res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET; | 211 | pnp_add_dma_resource(dev, res->start, res->flags); |
247 | if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) { | 212 | return 0; |
248 | res->start = -1; | ||
249 | res->end = -1; | ||
250 | } else { | ||
251 | res->start = 0; | ||
252 | res->end = 0; | ||
253 | } | ||
254 | } | 213 | } |
255 | 214 | ||
256 | /** | ||
257 | * pnp_init_resources - Resets a resource table to default values. | ||
258 | * @table: pointer to the desired resource table | ||
259 | */ | ||
260 | void pnp_init_resources(struct pnp_dev *dev) | 215 | void pnp_init_resources(struct pnp_dev *dev) |
261 | { | 216 | { |
262 | struct resource *res; | 217 | pnp_free_resources(dev); |
263 | int idx; | ||
264 | |||
265 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { | ||
266 | res = &dev->res->irq[idx].res; | ||
267 | res->flags = IORESOURCE_IRQ; | ||
268 | pnp_init_resource(res); | ||
269 | } | ||
270 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { | ||
271 | res = &dev->res->dma[idx].res; | ||
272 | res->flags = IORESOURCE_DMA; | ||
273 | pnp_init_resource(res); | ||
274 | } | ||
275 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { | ||
276 | res = &dev->res->port[idx].res; | ||
277 | res->flags = IORESOURCE_IO; | ||
278 | pnp_init_resource(res); | ||
279 | } | ||
280 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { | ||
281 | res = &dev->res->mem[idx].res; | ||
282 | res->flags = IORESOURCE_MEM; | ||
283 | pnp_init_resource(res); | ||
284 | } | ||
285 | } | 218 | } |
286 | 219 | ||
287 | /** | ||
288 | * pnp_clean_resources - clears resources that were not manually set | ||
289 | * @res: the resources to clean | ||
290 | */ | ||
291 | static void pnp_clean_resource_table(struct pnp_dev *dev) | 220 | static void pnp_clean_resource_table(struct pnp_dev *dev) |
292 | { | 221 | { |
293 | struct resource *res; | 222 | struct pnp_resource *pnp_res, *tmp; |
294 | int idx; | 223 | |
295 | 224 | list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) { | |
296 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { | 225 | if (pnp_res->res.flags & IORESOURCE_AUTO) |
297 | res = &dev->res->irq[idx].res; | 226 | pnp_free_resource(pnp_res); |
298 | if (res->flags & IORESOURCE_AUTO) { | ||
299 | res->flags = IORESOURCE_IRQ; | ||
300 | pnp_init_resource(res); | ||
301 | } | ||
302 | } | ||
303 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { | ||
304 | res = &dev->res->dma[idx].res; | ||
305 | if (res->flags & IORESOURCE_AUTO) { | ||
306 | res->flags = IORESOURCE_DMA; | ||
307 | pnp_init_resource(res); | ||
308 | } | ||
309 | } | ||
310 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { | ||
311 | res = &dev->res->port[idx].res; | ||
312 | if (res->flags & IORESOURCE_AUTO) { | ||
313 | res->flags = IORESOURCE_IO; | ||
314 | pnp_init_resource(res); | ||
315 | } | ||
316 | } | ||
317 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { | ||
318 | res = &dev->res->mem[idx].res; | ||
319 | if (res->flags & IORESOURCE_AUTO) { | ||
320 | res->flags = IORESOURCE_MEM; | ||
321 | pnp_init_resource(res); | ||
322 | } | ||
323 | } | 227 | } |
324 | } | 228 | } |
325 | 229 | ||
326 | /** | 230 | /** |
327 | * pnp_assign_resources - assigns resources to the device based on the specified dependent number | 231 | * pnp_assign_resources - assigns resources to the device based on the specified dependent number |
328 | * @dev: pointer to the desired device | 232 | * @dev: pointer to the desired device |
329 | * @depnum: the dependent function number | 233 | * @set: the dependent function number |
330 | * | ||
331 | * Only set depnum to 0 if the device does not have dependent options. | ||
332 | */ | 234 | */ |
333 | static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | 235 | static int pnp_assign_resources(struct pnp_dev *dev, int set) |
334 | { | 236 | { |
335 | struct pnp_port *port; | 237 | struct pnp_option *option; |
336 | struct pnp_mem *mem; | ||
337 | struct pnp_irq *irq; | ||
338 | struct pnp_dma *dma; | ||
339 | int nport = 0, nmem = 0, nirq = 0, ndma = 0; | 238 | int nport = 0, nmem = 0, nirq = 0, ndma = 0; |
239 | int ret = 0; | ||
340 | 240 | ||
341 | if (!pnp_can_configure(dev)) | 241 | dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set); |
342 | return -ENODEV; | ||
343 | |||
344 | dbg_pnp_show_resources(dev, "before pnp_assign_resources"); | ||
345 | mutex_lock(&pnp_res_mutex); | 242 | mutex_lock(&pnp_res_mutex); |
346 | pnp_clean_resource_table(dev); | 243 | pnp_clean_resource_table(dev); |
347 | if (dev->independent) { | ||
348 | dev_dbg(&dev->dev, "assigning independent options\n"); | ||
349 | port = dev->independent->port; | ||
350 | mem = dev->independent->mem; | ||
351 | irq = dev->independent->irq; | ||
352 | dma = dev->independent->dma; | ||
353 | while (port) { | ||
354 | if (!pnp_assign_port(dev, port, nport)) | ||
355 | goto fail; | ||
356 | nport++; | ||
357 | port = port->next; | ||
358 | } | ||
359 | while (mem) { | ||
360 | if (!pnp_assign_mem(dev, mem, nmem)) | ||
361 | goto fail; | ||
362 | nmem++; | ||
363 | mem = mem->next; | ||
364 | } | ||
365 | while (irq) { | ||
366 | if (!pnp_assign_irq(dev, irq, nirq)) | ||
367 | goto fail; | ||
368 | nirq++; | ||
369 | irq = irq->next; | ||
370 | } | ||
371 | while (dma) { | ||
372 | pnp_assign_dma(dev, dma, ndma); | ||
373 | ndma++; | ||
374 | dma = dma->next; | ||
375 | } | ||
376 | } | ||
377 | 244 | ||
378 | if (depnum) { | 245 | list_for_each_entry(option, &dev->options, list) { |
379 | struct pnp_option *dep; | 246 | if (pnp_option_is_dependent(option) && |
380 | int i; | 247 | pnp_option_set(option) != set) |
381 | 248 | continue; | |
382 | dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); | 249 | |
383 | for (i = 1, dep = dev->dependent; i < depnum; | 250 | switch (option->type) { |
384 | i++, dep = dep->next) | 251 | case IORESOURCE_IO: |
385 | if (!dep) | 252 | ret = pnp_assign_port(dev, &option->u.port, nport++); |
386 | goto fail; | 253 | break; |
387 | port = dep->port; | 254 | case IORESOURCE_MEM: |
388 | mem = dep->mem; | 255 | ret = pnp_assign_mem(dev, &option->u.mem, nmem++); |
389 | irq = dep->irq; | 256 | break; |
390 | dma = dep->dma; | 257 | case IORESOURCE_IRQ: |
391 | while (port) { | 258 | ret = pnp_assign_irq(dev, &option->u.irq, nirq++); |
392 | if (!pnp_assign_port(dev, port, nport)) | 259 | break; |
393 | goto fail; | 260 | case IORESOURCE_DMA: |
394 | nport++; | 261 | ret = pnp_assign_dma(dev, &option->u.dma, ndma++); |
395 | port = port->next; | 262 | break; |
396 | } | 263 | default: |
397 | while (mem) { | 264 | ret = -EINVAL; |
398 | if (!pnp_assign_mem(dev, mem, nmem)) | 265 | break; |
399 | goto fail; | ||
400 | nmem++; | ||
401 | mem = mem->next; | ||
402 | } | ||
403 | while (irq) { | ||
404 | if (!pnp_assign_irq(dev, irq, nirq)) | ||
405 | goto fail; | ||
406 | nirq++; | ||
407 | irq = irq->next; | ||
408 | } | 266 | } |
409 | while (dma) { | 267 | if (ret < 0) |
410 | pnp_assign_dma(dev, dma, ndma); | 268 | break; |
411 | ndma++; | 269 | } |
412 | dma = dma->next; | ||
413 | } | ||
414 | } else if (dev->dependent) | ||
415 | goto fail; | ||
416 | |||
417 | mutex_unlock(&pnp_res_mutex); | ||
418 | dbg_pnp_show_resources(dev, "after pnp_assign_resources"); | ||
419 | return 1; | ||
420 | 270 | ||
421 | fail: | ||
422 | pnp_clean_resource_table(dev); | ||
423 | mutex_unlock(&pnp_res_mutex); | 271 | mutex_unlock(&pnp_res_mutex); |
424 | dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); | 272 | if (ret < 0) { |
425 | return 0; | 273 | dev_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret); |
274 | pnp_clean_resource_table(dev); | ||
275 | } else | ||
276 | dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded"); | ||
277 | return ret; | ||
426 | } | 278 | } |
427 | 279 | ||
428 | /** | 280 | /** |
@@ -431,29 +283,25 @@ fail: | |||
431 | */ | 283 | */ |
432 | int pnp_auto_config_dev(struct pnp_dev *dev) | 284 | int pnp_auto_config_dev(struct pnp_dev *dev) |
433 | { | 285 | { |
434 | struct pnp_option *dep; | 286 | int i, ret; |
435 | int i = 1; | ||
436 | 287 | ||
437 | if (!pnp_can_configure(dev)) { | 288 | if (!pnp_can_configure(dev)) { |
438 | dev_dbg(&dev->dev, "configuration not supported\n"); | 289 | dev_dbg(&dev->dev, "configuration not supported\n"); |
439 | return -ENODEV; | 290 | return -ENODEV; |
440 | } | 291 | } |
441 | 292 | ||
442 | if (!dev->dependent) { | 293 | ret = pnp_assign_resources(dev, 0); |
443 | if (pnp_assign_resources(dev, 0)) | 294 | if (ret == 0) |
295 | return 0; | ||
296 | |||
297 | for (i = 1; i < dev->num_dependent_sets; i++) { | ||
298 | ret = pnp_assign_resources(dev, i); | ||
299 | if (ret == 0) | ||
444 | return 0; | 300 | return 0; |
445 | } else { | ||
446 | dep = dev->dependent; | ||
447 | do { | ||
448 | if (pnp_assign_resources(dev, i)) | ||
449 | return 0; | ||
450 | dep = dep->next; | ||
451 | i++; | ||
452 | } while (dep); | ||
453 | } | 301 | } |
454 | 302 | ||
455 | dev_err(&dev->dev, "unable to assign resources\n"); | 303 | dev_err(&dev->dev, "unable to assign resources\n"); |
456 | return -EBUSY; | 304 | return ret; |
457 | } | 305 | } |
458 | 306 | ||
459 | /** | 307 | /** |
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 50902773beaf..c1b9ea34977b 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
@@ -117,9 +117,7 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) | |||
117 | { | 117 | { |
118 | int power_state; | 118 | int power_state; |
119 | 119 | ||
120 | power_state = acpi_pm_device_sleep_state(&dev->dev, | 120 | power_state = acpi_pm_device_sleep_state(&dev->dev, NULL); |
121 | device_may_wakeup(&dev->dev), | ||
122 | NULL); | ||
123 | if (power_state < 0) | 121 | if (power_state < 0) |
124 | power_state = (state.event == PM_EVENT_ON) ? | 122 | power_state = (state.event == PM_EVENT_ON) ? |
125 | ACPI_STATE_D0 : ACPI_STATE_D3; | 123 | ACPI_STATE_D0 : ACPI_STATE_D3; |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 46c791adb894..d7e9f2152df0 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr> | 4 | * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr> |
5 | * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com> | 5 | * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com> |
6 | * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. | ||
7 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | ||
6 | * | 8 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
@@ -98,8 +100,10 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, | |||
98 | int irq, flags; | 100 | int irq, flags; |
99 | int p, t; | 101 | int p, t; |
100 | 102 | ||
101 | if (!valid_IRQ(gsi)) | 103 | if (!valid_IRQ(gsi)) { |
104 | pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED); | ||
102 | return; | 105 | return; |
106 | } | ||
103 | 107 | ||
104 | /* | 108 | /* |
105 | * in IO-APIC mode, use overrided attribute. Two reasons: | 109 | * in IO-APIC mode, use overrided attribute. Two reasons: |
@@ -178,13 +182,68 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, | |||
178 | u64 end = start + len - 1; | 182 | u64 end = start + len - 1; |
179 | 183 | ||
180 | if (io_decode == ACPI_DECODE_16) | 184 | if (io_decode == ACPI_DECODE_16) |
181 | flags |= PNP_PORT_FLAG_16BITADDR; | 185 | flags |= IORESOURCE_IO_16BIT_ADDR; |
182 | if (len == 0 || end >= 0x10003) | 186 | if (len == 0 || end >= 0x10003) |
183 | flags |= IORESOURCE_DISABLED; | 187 | flags |= IORESOURCE_DISABLED; |
184 | 188 | ||
185 | pnp_add_io_resource(dev, start, end, flags); | 189 | pnp_add_io_resource(dev, start, end, flags); |
186 | } | 190 | } |
187 | 191 | ||
192 | /* | ||
193 | * Device CSRs that do not appear in PCI config space should be described | ||
194 | * via ACPI. This would normally be done with Address Space Descriptors | ||
195 | * marked as "consumer-only," but old versions of Windows and Linux ignore | ||
196 | * the producer/consumer flag, so HP invented a vendor-defined resource to | ||
197 | * describe the location and size of CSR space. | ||
198 | */ | ||
199 | static struct acpi_vendor_uuid hp_ccsr_uuid = { | ||
200 | .subtype = 2, | ||
201 | .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a, | ||
202 | 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad }, | ||
203 | }; | ||
204 | |||
205 | static int vendor_resource_matches(struct pnp_dev *dev, | ||
206 | struct acpi_resource_vendor_typed *vendor, | ||
207 | struct acpi_vendor_uuid *match, | ||
208 | int expected_len) | ||
209 | { | ||
210 | int uuid_len = sizeof(vendor->uuid); | ||
211 | u8 uuid_subtype = vendor->uuid_subtype; | ||
212 | u8 *uuid = vendor->uuid; | ||
213 | int actual_len; | ||
214 | |||
215 | /* byte_length includes uuid_subtype and uuid */ | ||
216 | actual_len = vendor->byte_length - uuid_len - 1; | ||
217 | |||
218 | if (uuid_subtype == match->subtype && | ||
219 | uuid_len == sizeof(match->data) && | ||
220 | memcmp(uuid, match->data, uuid_len) == 0) { | ||
221 | if (expected_len && expected_len != actual_len) { | ||
222 | dev_err(&dev->dev, "wrong vendor descriptor size; " | ||
223 | "expected %d, found %d bytes\n", | ||
224 | expected_len, actual_len); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | return 1; | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev, | ||
235 | struct acpi_resource_vendor_typed *vendor) | ||
236 | { | ||
237 | if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) { | ||
238 | u64 start, length; | ||
239 | |||
240 | memcpy(&start, vendor->byte_data, sizeof(start)); | ||
241 | memcpy(&length, vendor->byte_data + 8, sizeof(length)); | ||
242 | |||
243 | pnp_add_mem_resource(dev, start, start + length - 1, 0); | ||
244 | } | ||
245 | } | ||
246 | |||
188 | static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, | 247 | static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, |
189 | u64 start, u64 len, | 248 | u64 start, u64 len, |
190 | int write_protect) | 249 | int write_protect) |
@@ -235,6 +294,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
235 | struct acpi_resource_dma *dma; | 294 | struct acpi_resource_dma *dma; |
236 | struct acpi_resource_io *io; | 295 | struct acpi_resource_io *io; |
237 | struct acpi_resource_fixed_io *fixed_io; | 296 | struct acpi_resource_fixed_io *fixed_io; |
297 | struct acpi_resource_vendor_typed *vendor_typed; | ||
238 | struct acpi_resource_memory24 *memory24; | 298 | struct acpi_resource_memory24 *memory24; |
239 | struct acpi_resource_memory32 *memory32; | 299 | struct acpi_resource_memory32 *memory32; |
240 | struct acpi_resource_fixed_memory32 *fixed_memory32; | 300 | struct acpi_resource_fixed_memory32 *fixed_memory32; |
@@ -248,24 +308,39 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
248 | * _CRS, but some firmware violates this, so parse them all. | 308 | * _CRS, but some firmware violates this, so parse them all. |
249 | */ | 309 | */ |
250 | irq = &res->data.irq; | 310 | irq = &res->data.irq; |
251 | for (i = 0; i < irq->interrupt_count; i++) { | 311 | if (irq->interrupt_count == 0) |
252 | pnpacpi_parse_allocated_irqresource(dev, | 312 | pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); |
253 | irq->interrupts[i], | 313 | else { |
254 | irq->triggering, | 314 | for (i = 0; i < irq->interrupt_count; i++) { |
255 | irq->polarity, | 315 | pnpacpi_parse_allocated_irqresource(dev, |
256 | irq->sharable); | 316 | irq->interrupts[i], |
317 | irq->triggering, | ||
318 | irq->polarity, | ||
319 | irq->sharable); | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * The IRQ encoder puts a single interrupt in each | ||
324 | * descriptor, so if a _CRS descriptor has more than | ||
325 | * one interrupt, we won't be able to re-encode it. | ||
326 | */ | ||
327 | if (pnp_can_write(dev) && irq->interrupt_count > 1) { | ||
328 | dev_warn(&dev->dev, "multiple interrupts in " | ||
329 | "_CRS descriptor; configuration can't " | ||
330 | "be changed\n"); | ||
331 | dev->capabilities &= ~PNP_WRITE; | ||
332 | } | ||
257 | } | 333 | } |
258 | break; | 334 | break; |
259 | 335 | ||
260 | case ACPI_RESOURCE_TYPE_DMA: | 336 | case ACPI_RESOURCE_TYPE_DMA: |
261 | dma = &res->data.dma; | 337 | dma = &res->data.dma; |
262 | if (dma->channel_count > 0) { | 338 | if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) |
263 | flags = dma_flags(dma->type, dma->bus_master, | 339 | flags = dma_flags(dma->type, dma->bus_master, |
264 | dma->transfer); | 340 | dma->transfer); |
265 | if (dma->channels[0] == (u8) -1) | 341 | else |
266 | flags |= IORESOURCE_DISABLED; | 342 | flags = IORESOURCE_DISABLED; |
267 | pnp_add_dma_resource(dev, dma->channels[0], flags); | 343 | pnp_add_dma_resource(dev, dma->channels[0], flags); |
268 | } | ||
269 | break; | 344 | break; |
270 | 345 | ||
271 | case ACPI_RESOURCE_TYPE_IO: | 346 | case ACPI_RESOURCE_TYPE_IO: |
@@ -289,6 +364,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
289 | break; | 364 | break; |
290 | 365 | ||
291 | case ACPI_RESOURCE_TYPE_VENDOR: | 366 | case ACPI_RESOURCE_TYPE_VENDOR: |
367 | vendor_typed = &res->data.vendor_typed; | ||
368 | pnpacpi_parse_allocated_vendor(dev, vendor_typed); | ||
292 | break; | 369 | break; |
293 | 370 | ||
294 | case ACPI_RESOURCE_TYPE_END_TAG: | 371 | case ACPI_RESOURCE_TYPE_END_TAG: |
@@ -331,12 +408,29 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
331 | if (extended_irq->producer_consumer == ACPI_PRODUCER) | 408 | if (extended_irq->producer_consumer == ACPI_PRODUCER) |
332 | return AE_OK; | 409 | return AE_OK; |
333 | 410 | ||
334 | for (i = 0; i < extended_irq->interrupt_count; i++) { | 411 | if (extended_irq->interrupt_count == 0) |
335 | pnpacpi_parse_allocated_irqresource(dev, | 412 | pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); |
336 | extended_irq->interrupts[i], | 413 | else { |
337 | extended_irq->triggering, | 414 | for (i = 0; i < extended_irq->interrupt_count; i++) { |
338 | extended_irq->polarity, | 415 | pnpacpi_parse_allocated_irqresource(dev, |
339 | extended_irq->sharable); | 416 | extended_irq->interrupts[i], |
417 | extended_irq->triggering, | ||
418 | extended_irq->polarity, | ||
419 | extended_irq->sharable); | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * The IRQ encoder puts a single interrupt in each | ||
424 | * descriptor, so if a _CRS descriptor has more than | ||
425 | * one interrupt, we won't be able to re-encode it. | ||
426 | */ | ||
427 | if (pnp_can_write(dev) && | ||
428 | extended_irq->interrupt_count > 1) { | ||
429 | dev_warn(&dev->dev, "multiple interrupts in " | ||
430 | "_CRS descriptor; configuration can't " | ||
431 | "be changed\n"); | ||
432 | dev->capabilities &= ~PNP_WRITE; | ||
433 | } | ||
340 | } | 434 | } |
341 | break; | 435 | break; |
342 | 436 | ||
@@ -373,179 +467,147 @@ int pnpacpi_parse_allocated_resource(struct pnp_dev *dev) | |||
373 | } | 467 | } |
374 | 468 | ||
375 | static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, | 469 | static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, |
376 | struct pnp_option *option, | 470 | unsigned int option_flags, |
377 | struct acpi_resource_dma *p) | 471 | struct acpi_resource_dma *p) |
378 | { | 472 | { |
379 | int i; | 473 | int i; |
380 | struct pnp_dma *dma; | 474 | unsigned char map = 0, flags; |
381 | 475 | ||
382 | if (p->channel_count == 0) | 476 | if (p->channel_count == 0) |
383 | return; | 477 | return; |
384 | dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); | ||
385 | if (!dma) | ||
386 | return; | ||
387 | 478 | ||
388 | for (i = 0; i < p->channel_count; i++) | 479 | for (i = 0; i < p->channel_count; i++) |
389 | dma->map |= 1 << p->channels[i]; | 480 | map |= 1 << p->channels[i]; |
390 | |||
391 | dma->flags = dma_flags(p->type, p->bus_master, p->transfer); | ||
392 | 481 | ||
393 | pnp_register_dma_resource(dev, option, dma); | 482 | flags = dma_flags(p->type, p->bus_master, p->transfer); |
483 | pnp_register_dma_resource(dev, option_flags, map, flags); | ||
394 | } | 484 | } |
395 | 485 | ||
396 | static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, | 486 | static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, |
397 | struct pnp_option *option, | 487 | unsigned int option_flags, |
398 | struct acpi_resource_irq *p) | 488 | struct acpi_resource_irq *p) |
399 | { | 489 | { |
400 | int i; | 490 | int i; |
401 | struct pnp_irq *irq; | 491 | pnp_irq_mask_t map; |
492 | unsigned char flags; | ||
402 | 493 | ||
403 | if (p->interrupt_count == 0) | 494 | if (p->interrupt_count == 0) |
404 | return; | 495 | return; |
405 | irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); | ||
406 | if (!irq) | ||
407 | return; | ||
408 | 496 | ||
497 | bitmap_zero(map.bits, PNP_IRQ_NR); | ||
409 | for (i = 0; i < p->interrupt_count; i++) | 498 | for (i = 0; i < p->interrupt_count; i++) |
410 | if (p->interrupts[i]) | 499 | if (p->interrupts[i]) |
411 | __set_bit(p->interrupts[i], irq->map); | 500 | __set_bit(p->interrupts[i], map.bits); |
412 | irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); | ||
413 | 501 | ||
414 | pnp_register_irq_resource(dev, option, irq); | 502 | flags = irq_flags(p->triggering, p->polarity, p->sharable); |
503 | pnp_register_irq_resource(dev, option_flags, &map, flags); | ||
415 | } | 504 | } |
416 | 505 | ||
417 | static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, | 506 | static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, |
418 | struct pnp_option *option, | 507 | unsigned int option_flags, |
419 | struct acpi_resource_extended_irq *p) | 508 | struct acpi_resource_extended_irq *p) |
420 | { | 509 | { |
421 | int i; | 510 | int i; |
422 | struct pnp_irq *irq; | 511 | pnp_irq_mask_t map; |
512 | unsigned char flags; | ||
423 | 513 | ||
424 | if (p->interrupt_count == 0) | 514 | if (p->interrupt_count == 0) |
425 | return; | 515 | return; |
426 | irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); | ||
427 | if (!irq) | ||
428 | return; | ||
429 | 516 | ||
430 | for (i = 0; i < p->interrupt_count; i++) | 517 | bitmap_zero(map.bits, PNP_IRQ_NR); |
431 | if (p->interrupts[i]) | 518 | for (i = 0; i < p->interrupt_count; i++) { |
432 | __set_bit(p->interrupts[i], irq->map); | 519 | if (p->interrupts[i]) { |
433 | irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); | 520 | if (p->interrupts[i] < PNP_IRQ_NR) |
521 | __set_bit(p->interrupts[i], map.bits); | ||
522 | else | ||
523 | dev_err(&dev->dev, "ignoring IRQ %d option " | ||
524 | "(too large for %d entry bitmap)\n", | ||
525 | p->interrupts[i], PNP_IRQ_NR); | ||
526 | } | ||
527 | } | ||
434 | 528 | ||
435 | pnp_register_irq_resource(dev, option, irq); | 529 | flags = irq_flags(p->triggering, p->polarity, p->sharable); |
530 | pnp_register_irq_resource(dev, option_flags, &map, flags); | ||
436 | } | 531 | } |
437 | 532 | ||
438 | static __init void pnpacpi_parse_port_option(struct pnp_dev *dev, | 533 | static __init void pnpacpi_parse_port_option(struct pnp_dev *dev, |
439 | struct pnp_option *option, | 534 | unsigned int option_flags, |
440 | struct acpi_resource_io *io) | 535 | struct acpi_resource_io *io) |
441 | { | 536 | { |
442 | struct pnp_port *port; | 537 | unsigned char flags = 0; |
443 | 538 | ||
444 | if (io->address_length == 0) | 539 | if (io->address_length == 0) |
445 | return; | 540 | return; |
446 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); | 541 | |
447 | if (!port) | 542 | if (io->io_decode == ACPI_DECODE_16) |
448 | return; | 543 | flags = IORESOURCE_IO_16BIT_ADDR; |
449 | port->min = io->minimum; | 544 | pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum, |
450 | port->max = io->maximum; | 545 | io->alignment, io->address_length, flags); |
451 | port->align = io->alignment; | ||
452 | port->size = io->address_length; | ||
453 | port->flags = ACPI_DECODE_16 == io->io_decode ? | ||
454 | PNP_PORT_FLAG_16BITADDR : 0; | ||
455 | pnp_register_port_resource(dev, option, port); | ||
456 | } | 546 | } |
457 | 547 | ||
458 | static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev, | 548 | static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev, |
459 | struct pnp_option *option, | 549 | unsigned int option_flags, |
460 | struct acpi_resource_fixed_io *io) | 550 | struct acpi_resource_fixed_io *io) |
461 | { | 551 | { |
462 | struct pnp_port *port; | ||
463 | |||
464 | if (io->address_length == 0) | 552 | if (io->address_length == 0) |
465 | return; | 553 | return; |
466 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); | 554 | |
467 | if (!port) | 555 | pnp_register_port_resource(dev, option_flags, io->address, io->address, |
468 | return; | 556 | 0, io->address_length, IORESOURCE_IO_FIXED); |
469 | port->min = port->max = io->address; | ||
470 | port->size = io->address_length; | ||
471 | port->align = 0; | ||
472 | port->flags = PNP_PORT_FLAG_FIXED; | ||
473 | pnp_register_port_resource(dev, option, port); | ||
474 | } | 557 | } |
475 | 558 | ||
476 | static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, | 559 | static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, |
477 | struct pnp_option *option, | 560 | unsigned int option_flags, |
478 | struct acpi_resource_memory24 *p) | 561 | struct acpi_resource_memory24 *p) |
479 | { | 562 | { |
480 | struct pnp_mem *mem; | 563 | unsigned char flags = 0; |
481 | 564 | ||
482 | if (p->address_length == 0) | 565 | if (p->address_length == 0) |
483 | return; | 566 | return; |
484 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | ||
485 | if (!mem) | ||
486 | return; | ||
487 | mem->min = p->minimum; | ||
488 | mem->max = p->maximum; | ||
489 | mem->align = p->alignment; | ||
490 | mem->size = p->address_length; | ||
491 | |||
492 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? | ||
493 | IORESOURCE_MEM_WRITEABLE : 0; | ||
494 | 567 | ||
495 | pnp_register_mem_resource(dev, option, mem); | 568 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) |
569 | flags = IORESOURCE_MEM_WRITEABLE; | ||
570 | pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum, | ||
571 | p->alignment, p->address_length, flags); | ||
496 | } | 572 | } |
497 | 573 | ||
498 | static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev, | 574 | static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev, |
499 | struct pnp_option *option, | 575 | unsigned int option_flags, |
500 | struct acpi_resource_memory32 *p) | 576 | struct acpi_resource_memory32 *p) |
501 | { | 577 | { |
502 | struct pnp_mem *mem; | 578 | unsigned char flags = 0; |
503 | 579 | ||
504 | if (p->address_length == 0) | 580 | if (p->address_length == 0) |
505 | return; | 581 | return; |
506 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | ||
507 | if (!mem) | ||
508 | return; | ||
509 | mem->min = p->minimum; | ||
510 | mem->max = p->maximum; | ||
511 | mem->align = p->alignment; | ||
512 | mem->size = p->address_length; | ||
513 | |||
514 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? | ||
515 | IORESOURCE_MEM_WRITEABLE : 0; | ||
516 | 582 | ||
517 | pnp_register_mem_resource(dev, option, mem); | 583 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) |
584 | flags = IORESOURCE_MEM_WRITEABLE; | ||
585 | pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum, | ||
586 | p->alignment, p->address_length, flags); | ||
518 | } | 587 | } |
519 | 588 | ||
520 | static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev, | 589 | static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev, |
521 | struct pnp_option *option, | 590 | unsigned int option_flags, |
522 | struct acpi_resource_fixed_memory32 *p) | 591 | struct acpi_resource_fixed_memory32 *p) |
523 | { | 592 | { |
524 | struct pnp_mem *mem; | 593 | unsigned char flags = 0; |
525 | 594 | ||
526 | if (p->address_length == 0) | 595 | if (p->address_length == 0) |
527 | return; | 596 | return; |
528 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | ||
529 | if (!mem) | ||
530 | return; | ||
531 | mem->min = mem->max = p->address; | ||
532 | mem->size = p->address_length; | ||
533 | mem->align = 0; | ||
534 | |||
535 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? | ||
536 | IORESOURCE_MEM_WRITEABLE : 0; | ||
537 | 597 | ||
538 | pnp_register_mem_resource(dev, option, mem); | 598 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) |
599 | flags = IORESOURCE_MEM_WRITEABLE; | ||
600 | pnp_register_mem_resource(dev, option_flags, p->address, p->address, | ||
601 | 0, p->address_length, flags); | ||
539 | } | 602 | } |
540 | 603 | ||
541 | static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, | 604 | static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, |
542 | struct pnp_option *option, | 605 | unsigned int option_flags, |
543 | struct acpi_resource *r) | 606 | struct acpi_resource *r) |
544 | { | 607 | { |
545 | struct acpi_resource_address64 addr, *p = &addr; | 608 | struct acpi_resource_address64 addr, *p = &addr; |
546 | acpi_status status; | 609 | acpi_status status; |
547 | struct pnp_mem *mem; | 610 | unsigned char flags = 0; |
548 | struct pnp_port *port; | ||
549 | 611 | ||
550 | status = acpi_resource_to_address64(r, p); | 612 | status = acpi_resource_to_address64(r, p); |
551 | if (!ACPI_SUCCESS(status)) { | 613 | if (!ACPI_SUCCESS(status)) { |
@@ -558,49 +620,37 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, | |||
558 | return; | 620 | return; |
559 | 621 | ||
560 | if (p->resource_type == ACPI_MEMORY_RANGE) { | 622 | if (p->resource_type == ACPI_MEMORY_RANGE) { |
561 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 623 | if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) |
562 | if (!mem) | 624 | flags = IORESOURCE_MEM_WRITEABLE; |
563 | return; | 625 | pnp_register_mem_resource(dev, option_flags, p->minimum, |
564 | mem->min = mem->max = p->minimum; | 626 | p->minimum, 0, p->address_length, |
565 | mem->size = p->address_length; | 627 | flags); |
566 | mem->align = 0; | 628 | } else if (p->resource_type == ACPI_IO_RANGE) |
567 | mem->flags = (p->info.mem.write_protect == | 629 | pnp_register_port_resource(dev, option_flags, p->minimum, |
568 | ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE | 630 | p->minimum, 0, p->address_length, |
569 | : 0; | 631 | IORESOURCE_IO_FIXED); |
570 | pnp_register_mem_resource(dev, option, mem); | ||
571 | } else if (p->resource_type == ACPI_IO_RANGE) { | ||
572 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); | ||
573 | if (!port) | ||
574 | return; | ||
575 | port->min = port->max = p->minimum; | ||
576 | port->size = p->address_length; | ||
577 | port->align = 0; | ||
578 | port->flags = PNP_PORT_FLAG_FIXED; | ||
579 | pnp_register_port_resource(dev, option, port); | ||
580 | } | ||
581 | } | 632 | } |
582 | 633 | ||
583 | struct acpipnp_parse_option_s { | 634 | struct acpipnp_parse_option_s { |
584 | struct pnp_option *option; | ||
585 | struct pnp_option *option_independent; | ||
586 | struct pnp_dev *dev; | 635 | struct pnp_dev *dev; |
636 | unsigned int option_flags; | ||
587 | }; | 637 | }; |
588 | 638 | ||
589 | static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | 639 | static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, |
590 | void *data) | 640 | void *data) |
591 | { | 641 | { |
592 | int priority = 0; | 642 | int priority; |
593 | struct acpipnp_parse_option_s *parse_data = data; | 643 | struct acpipnp_parse_option_s *parse_data = data; |
594 | struct pnp_dev *dev = parse_data->dev; | 644 | struct pnp_dev *dev = parse_data->dev; |
595 | struct pnp_option *option = parse_data->option; | 645 | unsigned int option_flags = parse_data->option_flags; |
596 | 646 | ||
597 | switch (res->type) { | 647 | switch (res->type) { |
598 | case ACPI_RESOURCE_TYPE_IRQ: | 648 | case ACPI_RESOURCE_TYPE_IRQ: |
599 | pnpacpi_parse_irq_option(dev, option, &res->data.irq); | 649 | pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq); |
600 | break; | 650 | break; |
601 | 651 | ||
602 | case ACPI_RESOURCE_TYPE_DMA: | 652 | case ACPI_RESOURCE_TYPE_DMA: |
603 | pnpacpi_parse_dma_option(dev, option, &res->data.dma); | 653 | pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma); |
604 | break; | 654 | break; |
605 | 655 | ||
606 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | 656 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: |
@@ -620,31 +670,19 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
620 | priority = PNP_RES_PRIORITY_INVALID; | 670 | priority = PNP_RES_PRIORITY_INVALID; |
621 | break; | 671 | break; |
622 | } | 672 | } |
623 | /* TBD: Consider performance/robustness bits */ | 673 | parse_data->option_flags = pnp_new_dependent_set(dev, priority); |
624 | option = pnp_register_dependent_option(dev, priority); | ||
625 | if (!option) | ||
626 | return AE_ERROR; | ||
627 | parse_data->option = option; | ||
628 | break; | 674 | break; |
629 | 675 | ||
630 | case ACPI_RESOURCE_TYPE_END_DEPENDENT: | 676 | case ACPI_RESOURCE_TYPE_END_DEPENDENT: |
631 | /*only one EndDependentFn is allowed */ | 677 | parse_data->option_flags = 0; |
632 | if (!parse_data->option_independent) { | ||
633 | dev_warn(&dev->dev, "more than one EndDependentFn " | ||
634 | "in _PRS\n"); | ||
635 | return AE_ERROR; | ||
636 | } | ||
637 | parse_data->option = parse_data->option_independent; | ||
638 | parse_data->option_independent = NULL; | ||
639 | dev_dbg(&dev->dev, "end dependent options\n"); | ||
640 | break; | 678 | break; |
641 | 679 | ||
642 | case ACPI_RESOURCE_TYPE_IO: | 680 | case ACPI_RESOURCE_TYPE_IO: |
643 | pnpacpi_parse_port_option(dev, option, &res->data.io); | 681 | pnpacpi_parse_port_option(dev, option_flags, &res->data.io); |
644 | break; | 682 | break; |
645 | 683 | ||
646 | case ACPI_RESOURCE_TYPE_FIXED_IO: | 684 | case ACPI_RESOURCE_TYPE_FIXED_IO: |
647 | pnpacpi_parse_fixed_port_option(dev, option, | 685 | pnpacpi_parse_fixed_port_option(dev, option_flags, |
648 | &res->data.fixed_io); | 686 | &res->data.fixed_io); |
649 | break; | 687 | break; |
650 | 688 | ||
@@ -653,29 +691,31 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
653 | break; | 691 | break; |
654 | 692 | ||
655 | case ACPI_RESOURCE_TYPE_MEMORY24: | 693 | case ACPI_RESOURCE_TYPE_MEMORY24: |
656 | pnpacpi_parse_mem24_option(dev, option, &res->data.memory24); | 694 | pnpacpi_parse_mem24_option(dev, option_flags, |
695 | &res->data.memory24); | ||
657 | break; | 696 | break; |
658 | 697 | ||
659 | case ACPI_RESOURCE_TYPE_MEMORY32: | 698 | case ACPI_RESOURCE_TYPE_MEMORY32: |
660 | pnpacpi_parse_mem32_option(dev, option, &res->data.memory32); | 699 | pnpacpi_parse_mem32_option(dev, option_flags, |
700 | &res->data.memory32); | ||
661 | break; | 701 | break; |
662 | 702 | ||
663 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | 703 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
664 | pnpacpi_parse_fixed_mem32_option(dev, option, | 704 | pnpacpi_parse_fixed_mem32_option(dev, option_flags, |
665 | &res->data.fixed_memory32); | 705 | &res->data.fixed_memory32); |
666 | break; | 706 | break; |
667 | 707 | ||
668 | case ACPI_RESOURCE_TYPE_ADDRESS16: | 708 | case ACPI_RESOURCE_TYPE_ADDRESS16: |
669 | case ACPI_RESOURCE_TYPE_ADDRESS32: | 709 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
670 | case ACPI_RESOURCE_TYPE_ADDRESS64: | 710 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
671 | pnpacpi_parse_address_option(dev, option, res); | 711 | pnpacpi_parse_address_option(dev, option_flags, res); |
672 | break; | 712 | break; |
673 | 713 | ||
674 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 714 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
675 | break; | 715 | break; |
676 | 716 | ||
677 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 717 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
678 | pnpacpi_parse_ext_irq_option(dev, option, | 718 | pnpacpi_parse_ext_irq_option(dev, option_flags, |
679 | &res->data.extended_irq); | 719 | &res->data.extended_irq); |
680 | break; | 720 | break; |
681 | 721 | ||
@@ -699,12 +739,9 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) | |||
699 | 739 | ||
700 | dev_dbg(&dev->dev, "parse resource options\n"); | 740 | dev_dbg(&dev->dev, "parse resource options\n"); |
701 | 741 | ||
702 | parse_data.option = pnp_register_independent_option(dev); | ||
703 | if (!parse_data.option) | ||
704 | return -ENOMEM; | ||
705 | |||
706 | parse_data.option_independent = parse_data.option; | ||
707 | parse_data.dev = dev; | 742 | parse_data.dev = dev; |
743 | parse_data.option_flags = 0; | ||
744 | |||
708 | status = acpi_walk_resources(handle, METHOD_NAME__PRS, | 745 | status = acpi_walk_resources(handle, METHOD_NAME__PRS, |
709 | pnpacpi_option_resource, &parse_data); | 746 | pnpacpi_option_resource, &parse_data); |
710 | 747 | ||
@@ -806,6 +843,13 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev, | |||
806 | struct acpi_resource_irq *irq = &resource->data.irq; | 843 | struct acpi_resource_irq *irq = &resource->data.irq; |
807 | int triggering, polarity, shareable; | 844 | int triggering, polarity, shareable; |
808 | 845 | ||
846 | if (!pnp_resource_enabled(p)) { | ||
847 | irq->interrupt_count = 0; | ||
848 | dev_dbg(&dev->dev, " encode irq (%s)\n", | ||
849 | p ? "disabled" : "missing"); | ||
850 | return; | ||
851 | } | ||
852 | |||
809 | decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); | 853 | decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); |
810 | irq->triggering = triggering; | 854 | irq->triggering = triggering; |
811 | irq->polarity = polarity; | 855 | irq->polarity = polarity; |
@@ -828,6 +872,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, | |||
828 | struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; | 872 | struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; |
829 | int triggering, polarity, shareable; | 873 | int triggering, polarity, shareable; |
830 | 874 | ||
875 | if (!pnp_resource_enabled(p)) { | ||
876 | extended_irq->interrupt_count = 0; | ||
877 | dev_dbg(&dev->dev, " encode extended irq (%s)\n", | ||
878 | p ? "disabled" : "missing"); | ||
879 | return; | ||
880 | } | ||
881 | |||
831 | decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); | 882 | decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); |
832 | extended_irq->producer_consumer = ACPI_CONSUMER; | 883 | extended_irq->producer_consumer = ACPI_CONSUMER; |
833 | extended_irq->triggering = triggering; | 884 | extended_irq->triggering = triggering; |
@@ -848,6 +899,13 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev, | |||
848 | { | 899 | { |
849 | struct acpi_resource_dma *dma = &resource->data.dma; | 900 | struct acpi_resource_dma *dma = &resource->data.dma; |
850 | 901 | ||
902 | if (!pnp_resource_enabled(p)) { | ||
903 | dma->channel_count = 0; | ||
904 | dev_dbg(&dev->dev, " encode dma (%s)\n", | ||
905 | p ? "disabled" : "missing"); | ||
906 | return; | ||
907 | } | ||
908 | |||
851 | /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ | 909 | /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ |
852 | switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { | 910 | switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { |
853 | case IORESOURCE_DMA_TYPEA: | 911 | case IORESOURCE_DMA_TYPEA: |
@@ -889,17 +947,21 @@ static void pnpacpi_encode_io(struct pnp_dev *dev, | |||
889 | { | 947 | { |
890 | struct acpi_resource_io *io = &resource->data.io; | 948 | struct acpi_resource_io *io = &resource->data.io; |
891 | 949 | ||
892 | /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ | 950 | if (pnp_resource_enabled(p)) { |
893 | io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? | 951 | /* Note: pnp_assign_port copies pnp_port->flags into p->flags */ |
894 | ACPI_DECODE_16 : ACPI_DECODE_10; | 952 | io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ? |
895 | io->minimum = p->start; | 953 | ACPI_DECODE_16 : ACPI_DECODE_10; |
896 | io->maximum = p->end; | 954 | io->minimum = p->start; |
897 | io->alignment = 0; /* Correct? */ | 955 | io->maximum = p->end; |
898 | io->address_length = p->end - p->start + 1; | 956 | io->alignment = 0; /* Correct? */ |
899 | 957 | io->address_length = p->end - p->start + 1; | |
900 | dev_dbg(&dev->dev, " encode io %#llx-%#llx decode %#x\n", | 958 | } else { |
901 | (unsigned long long) p->start, (unsigned long long) p->end, | 959 | io->minimum = 0; |
902 | io->io_decode); | 960 | io->address_length = 0; |
961 | } | ||
962 | |||
963 | dev_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum, | ||
964 | io->minimum + io->address_length - 1, io->io_decode); | ||
903 | } | 965 | } |
904 | 966 | ||
905 | static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, | 967 | static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, |
@@ -908,11 +970,16 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, | |||
908 | { | 970 | { |
909 | struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io; | 971 | struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io; |
910 | 972 | ||
911 | fixed_io->address = p->start; | 973 | if (pnp_resource_enabled(p)) { |
912 | fixed_io->address_length = p->end - p->start + 1; | 974 | fixed_io->address = p->start; |
975 | fixed_io->address_length = p->end - p->start + 1; | ||
976 | } else { | ||
977 | fixed_io->address = 0; | ||
978 | fixed_io->address_length = 0; | ||
979 | } | ||
913 | 980 | ||
914 | dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", | 981 | dev_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address, |
915 | (unsigned long long) p->start, (unsigned long long) p->end); | 982 | fixed_io->address + fixed_io->address_length - 1); |
916 | } | 983 | } |
917 | 984 | ||
918 | static void pnpacpi_encode_mem24(struct pnp_dev *dev, | 985 | static void pnpacpi_encode_mem24(struct pnp_dev *dev, |
@@ -921,17 +988,22 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev, | |||
921 | { | 988 | { |
922 | struct acpi_resource_memory24 *memory24 = &resource->data.memory24; | 989 | struct acpi_resource_memory24 *memory24 = &resource->data.memory24; |
923 | 990 | ||
924 | /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ | 991 | if (pnp_resource_enabled(p)) { |
925 | memory24->write_protect = | 992 | /* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */ |
926 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? | 993 | memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ? |
927 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; | 994 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; |
928 | memory24->minimum = p->start; | 995 | memory24->minimum = p->start; |
929 | memory24->maximum = p->end; | 996 | memory24->maximum = p->end; |
930 | memory24->alignment = 0; | 997 | memory24->alignment = 0; |
931 | memory24->address_length = p->end - p->start + 1; | 998 | memory24->address_length = p->end - p->start + 1; |
932 | 999 | } else { | |
933 | dev_dbg(&dev->dev, " encode mem24 %#llx-%#llx write_protect %#x\n", | 1000 | memory24->minimum = 0; |
934 | (unsigned long long) p->start, (unsigned long long) p->end, | 1001 | memory24->address_length = 0; |
1002 | } | ||
1003 | |||
1004 | dev_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n", | ||
1005 | memory24->minimum, | ||
1006 | memory24->minimum + memory24->address_length - 1, | ||
935 | memory24->write_protect); | 1007 | memory24->write_protect); |
936 | } | 1008 | } |
937 | 1009 | ||
@@ -941,16 +1013,21 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev, | |||
941 | { | 1013 | { |
942 | struct acpi_resource_memory32 *memory32 = &resource->data.memory32; | 1014 | struct acpi_resource_memory32 *memory32 = &resource->data.memory32; |
943 | 1015 | ||
944 | memory32->write_protect = | 1016 | if (pnp_resource_enabled(p)) { |
945 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? | 1017 | memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ? |
946 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; | 1018 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; |
947 | memory32->minimum = p->start; | 1019 | memory32->minimum = p->start; |
948 | memory32->maximum = p->end; | 1020 | memory32->maximum = p->end; |
949 | memory32->alignment = 0; | 1021 | memory32->alignment = 0; |
950 | memory32->address_length = p->end - p->start + 1; | 1022 | memory32->address_length = p->end - p->start + 1; |
1023 | } else { | ||
1024 | memory32->minimum = 0; | ||
1025 | memory32->alignment = 0; | ||
1026 | } | ||
951 | 1027 | ||
952 | dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n", | 1028 | dev_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n", |
953 | (unsigned long long) p->start, (unsigned long long) p->end, | 1029 | memory32->minimum, |
1030 | memory32->minimum + memory32->address_length - 1, | ||
954 | memory32->write_protect); | 1031 | memory32->write_protect); |
955 | } | 1032 | } |
956 | 1033 | ||
@@ -960,15 +1037,20 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev, | |||
960 | { | 1037 | { |
961 | struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; | 1038 | struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; |
962 | 1039 | ||
963 | fixed_memory32->write_protect = | 1040 | if (pnp_resource_enabled(p)) { |
964 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? | 1041 | fixed_memory32->write_protect = |
965 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; | 1042 | p->flags & IORESOURCE_MEM_WRITEABLE ? |
966 | fixed_memory32->address = p->start; | 1043 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; |
967 | fixed_memory32->address_length = p->end - p->start + 1; | 1044 | fixed_memory32->address = p->start; |
1045 | fixed_memory32->address_length = p->end - p->start + 1; | ||
1046 | } else { | ||
1047 | fixed_memory32->address = 0; | ||
1048 | fixed_memory32->address_length = 0; | ||
1049 | } | ||
968 | 1050 | ||
969 | dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx " | 1051 | dev_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n", |
970 | "write_protect %#x\n", | 1052 | fixed_memory32->address, |
971 | (unsigned long long) p->start, (unsigned long long) p->end, | 1053 | fixed_memory32->address + fixed_memory32->address_length - 1, |
972 | fixed_memory32->write_protect); | 1054 | fixed_memory32->write_protect); |
973 | } | 1055 | } |
974 | 1056 | ||
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 5ff9a4c0447e..ca567671379e 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c | |||
@@ -216,137 +216,116 @@ len_err: | |||
216 | 216 | ||
217 | static __init void pnpbios_parse_mem_option(struct pnp_dev *dev, | 217 | static __init void pnpbios_parse_mem_option(struct pnp_dev *dev, |
218 | unsigned char *p, int size, | 218 | unsigned char *p, int size, |
219 | struct pnp_option *option) | 219 | unsigned int option_flags) |
220 | { | 220 | { |
221 | struct pnp_mem *mem; | 221 | resource_size_t min, max, align, len; |
222 | 222 | unsigned char flags; | |
223 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 223 | |
224 | if (!mem) | 224 | min = ((p[5] << 8) | p[4]) << 8; |
225 | return; | 225 | max = ((p[7] << 8) | p[6]) << 8; |
226 | mem->min = ((p[5] << 8) | p[4]) << 8; | 226 | align = (p[9] << 8) | p[8]; |
227 | mem->max = ((p[7] << 8) | p[6]) << 8; | 227 | len = ((p[11] << 8) | p[10]) << 8; |
228 | mem->align = (p[9] << 8) | p[8]; | 228 | flags = p[3]; |
229 | mem->size = ((p[11] << 8) | p[10]) << 8; | 229 | pnp_register_mem_resource(dev, option_flags, min, max, align, len, |
230 | mem->flags = p[3]; | 230 | flags); |
231 | pnp_register_mem_resource(dev, option, mem); | ||
232 | } | 231 | } |
233 | 232 | ||
234 | static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev, | 233 | static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev, |
235 | unsigned char *p, int size, | 234 | unsigned char *p, int size, |
236 | struct pnp_option *option) | 235 | unsigned int option_flags) |
237 | { | 236 | { |
238 | struct pnp_mem *mem; | 237 | resource_size_t min, max, align, len; |
239 | 238 | unsigned char flags; | |
240 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 239 | |
241 | if (!mem) | 240 | min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; |
242 | return; | 241 | max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; |
243 | mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; | 242 | align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; |
244 | mem->max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; | 243 | len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; |
245 | mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; | 244 | flags = p[3]; |
246 | mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; | 245 | pnp_register_mem_resource(dev, option_flags, min, max, align, len, |
247 | mem->flags = p[3]; | 246 | flags); |
248 | pnp_register_mem_resource(dev, option, mem); | ||
249 | } | 247 | } |
250 | 248 | ||
251 | static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev, | 249 | static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev, |
252 | unsigned char *p, int size, | 250 | unsigned char *p, int size, |
253 | struct pnp_option *option) | 251 | unsigned int option_flags) |
254 | { | 252 | { |
255 | struct pnp_mem *mem; | 253 | resource_size_t base, len; |
256 | 254 | unsigned char flags; | |
257 | mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 255 | |
258 | if (!mem) | 256 | base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; |
259 | return; | 257 | len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; |
260 | mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; | 258 | flags = p[3]; |
261 | mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; | 259 | pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags); |
262 | mem->align = 0; | ||
263 | mem->flags = p[3]; | ||
264 | pnp_register_mem_resource(dev, option, mem); | ||
265 | } | 260 | } |
266 | 261 | ||
267 | static __init void pnpbios_parse_irq_option(struct pnp_dev *dev, | 262 | static __init void pnpbios_parse_irq_option(struct pnp_dev *dev, |
268 | unsigned char *p, int size, | 263 | unsigned char *p, int size, |
269 | struct pnp_option *option) | 264 | unsigned int option_flags) |
270 | { | 265 | { |
271 | struct pnp_irq *irq; | ||
272 | unsigned long bits; | 266 | unsigned long bits; |
267 | pnp_irq_mask_t map; | ||
268 | unsigned char flags = IORESOURCE_IRQ_HIGHEDGE; | ||
273 | 269 | ||
274 | irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); | ||
275 | if (!irq) | ||
276 | return; | ||
277 | bits = (p[2] << 8) | p[1]; | 270 | bits = (p[2] << 8) | p[1]; |
278 | bitmap_copy(irq->map, &bits, 16); | 271 | |
272 | bitmap_zero(map.bits, PNP_IRQ_NR); | ||
273 | bitmap_copy(map.bits, &bits, 16); | ||
274 | |||
279 | if (size > 2) | 275 | if (size > 2) |
280 | irq->flags = p[3]; | 276 | flags = p[3]; |
281 | else | 277 | |
282 | irq->flags = IORESOURCE_IRQ_HIGHEDGE; | 278 | pnp_register_irq_resource(dev, option_flags, &map, flags); |
283 | pnp_register_irq_resource(dev, option, irq); | ||
284 | } | 279 | } |
285 | 280 | ||
286 | static __init void pnpbios_parse_dma_option(struct pnp_dev *dev, | 281 | static __init void pnpbios_parse_dma_option(struct pnp_dev *dev, |
287 | unsigned char *p, int size, | 282 | unsigned char *p, int size, |
288 | struct pnp_option *option) | 283 | unsigned int option_flags) |
289 | { | 284 | { |
290 | struct pnp_dma *dma; | 285 | pnp_register_dma_resource(dev, option_flags, p[1], p[2]); |
291 | |||
292 | dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); | ||
293 | if (!dma) | ||
294 | return; | ||
295 | dma->map = p[1]; | ||
296 | dma->flags = p[2]; | ||
297 | pnp_register_dma_resource(dev, option, dma); | ||
298 | } | 286 | } |
299 | 287 | ||
300 | static __init void pnpbios_parse_port_option(struct pnp_dev *dev, | 288 | static __init void pnpbios_parse_port_option(struct pnp_dev *dev, |
301 | unsigned char *p, int size, | 289 | unsigned char *p, int size, |
302 | struct pnp_option *option) | 290 | unsigned int option_flags) |
303 | { | 291 | { |
304 | struct pnp_port *port; | 292 | resource_size_t min, max, align, len; |
305 | 293 | unsigned char flags; | |
306 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); | 294 | |
307 | if (!port) | 295 | min = (p[3] << 8) | p[2]; |
308 | return; | 296 | max = (p[5] << 8) | p[4]; |
309 | port->min = (p[3] << 8) | p[2]; | 297 | align = p[6]; |
310 | port->max = (p[5] << 8) | p[4]; | 298 | len = p[7]; |
311 | port->align = p[6]; | 299 | flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0; |
312 | port->size = p[7]; | 300 | pnp_register_port_resource(dev, option_flags, min, max, align, len, |
313 | port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0; | 301 | flags); |
314 | pnp_register_port_resource(dev, option, port); | ||
315 | } | 302 | } |
316 | 303 | ||
317 | static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev, | 304 | static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev, |
318 | unsigned char *p, int size, | 305 | unsigned char *p, int size, |
319 | struct pnp_option *option) | 306 | unsigned int option_flags) |
320 | { | 307 | { |
321 | struct pnp_port *port; | 308 | resource_size_t base, len; |
322 | 309 | ||
323 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); | 310 | base = (p[2] << 8) | p[1]; |
324 | if (!port) | 311 | len = p[3]; |
325 | return; | 312 | pnp_register_port_resource(dev, option_flags, base, base, 0, len, |
326 | port->min = port->max = (p[2] << 8) | p[1]; | 313 | IORESOURCE_IO_FIXED); |
327 | port->size = p[3]; | ||
328 | port->align = 0; | ||
329 | port->flags = PNP_PORT_FLAG_FIXED; | ||
330 | pnp_register_port_resource(dev, option, port); | ||
331 | } | 314 | } |
332 | 315 | ||
333 | static __init unsigned char * | 316 | static __init unsigned char * |
334 | pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, | 317 | pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, |
335 | struct pnp_dev *dev) | 318 | struct pnp_dev *dev) |
336 | { | 319 | { |
337 | unsigned int len, tag; | 320 | unsigned int len, tag; |
338 | int priority = 0; | 321 | int priority; |
339 | struct pnp_option *option, *option_independent; | 322 | unsigned int option_flags; |
340 | 323 | ||
341 | if (!p) | 324 | if (!p) |
342 | return NULL; | 325 | return NULL; |
343 | 326 | ||
344 | dev_dbg(&dev->dev, "parse resource options\n"); | 327 | dev_dbg(&dev->dev, "parse resource options\n"); |
345 | 328 | option_flags = 0; | |
346 | option_independent = option = pnp_register_independent_option(dev); | ||
347 | if (!option) | ||
348 | return NULL; | ||
349 | |||
350 | while ((char *)p < (char *)end) { | 329 | while ((char *)p < (char *)end) { |
351 | 330 | ||
352 | /* determine the type of tag */ | 331 | /* determine the type of tag */ |
@@ -363,37 +342,38 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, | |||
363 | case LARGE_TAG_MEM: | 342 | case LARGE_TAG_MEM: |
364 | if (len != 9) | 343 | if (len != 9) |
365 | goto len_err; | 344 | goto len_err; |
366 | pnpbios_parse_mem_option(dev, p, len, option); | 345 | pnpbios_parse_mem_option(dev, p, len, option_flags); |
367 | break; | 346 | break; |
368 | 347 | ||
369 | case LARGE_TAG_MEM32: | 348 | case LARGE_TAG_MEM32: |
370 | if (len != 17) | 349 | if (len != 17) |
371 | goto len_err; | 350 | goto len_err; |
372 | pnpbios_parse_mem32_option(dev, p, len, option); | 351 | pnpbios_parse_mem32_option(dev, p, len, option_flags); |
373 | break; | 352 | break; |
374 | 353 | ||
375 | case LARGE_TAG_FIXEDMEM32: | 354 | case LARGE_TAG_FIXEDMEM32: |
376 | if (len != 9) | 355 | if (len != 9) |
377 | goto len_err; | 356 | goto len_err; |
378 | pnpbios_parse_fixed_mem32_option(dev, p, len, option); | 357 | pnpbios_parse_fixed_mem32_option(dev, p, len, |
358 | option_flags); | ||
379 | break; | 359 | break; |
380 | 360 | ||
381 | case SMALL_TAG_IRQ: | 361 | case SMALL_TAG_IRQ: |
382 | if (len < 2 || len > 3) | 362 | if (len < 2 || len > 3) |
383 | goto len_err; | 363 | goto len_err; |
384 | pnpbios_parse_irq_option(dev, p, len, option); | 364 | pnpbios_parse_irq_option(dev, p, len, option_flags); |
385 | break; | 365 | break; |
386 | 366 | ||
387 | case SMALL_TAG_DMA: | 367 | case SMALL_TAG_DMA: |
388 | if (len != 2) | 368 | if (len != 2) |
389 | goto len_err; | 369 | goto len_err; |
390 | pnpbios_parse_dma_option(dev, p, len, option); | 370 | pnpbios_parse_dma_option(dev, p, len, option_flags); |
391 | break; | 371 | break; |
392 | 372 | ||
393 | case SMALL_TAG_PORT: | 373 | case SMALL_TAG_PORT: |
394 | if (len != 7) | 374 | if (len != 7) |
395 | goto len_err; | 375 | goto len_err; |
396 | pnpbios_parse_port_option(dev, p, len, option); | 376 | pnpbios_parse_port_option(dev, p, len, option_flags); |
397 | break; | 377 | break; |
398 | 378 | ||
399 | case SMALL_TAG_VENDOR: | 379 | case SMALL_TAG_VENDOR: |
@@ -403,28 +383,23 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, | |||
403 | case SMALL_TAG_FIXEDPORT: | 383 | case SMALL_TAG_FIXEDPORT: |
404 | if (len != 3) | 384 | if (len != 3) |
405 | goto len_err; | 385 | goto len_err; |
406 | pnpbios_parse_fixed_port_option(dev, p, len, option); | 386 | pnpbios_parse_fixed_port_option(dev, p, len, |
387 | option_flags); | ||
407 | break; | 388 | break; |
408 | 389 | ||
409 | case SMALL_TAG_STARTDEP: | 390 | case SMALL_TAG_STARTDEP: |
410 | if (len > 1) | 391 | if (len > 1) |
411 | goto len_err; | 392 | goto len_err; |
412 | priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; | 393 | priority = PNP_RES_PRIORITY_ACCEPTABLE; |
413 | if (len > 0) | 394 | if (len > 0) |
414 | priority = 0x100 | p[1]; | 395 | priority = p[1]; |
415 | option = pnp_register_dependent_option(dev, priority); | 396 | option_flags = pnp_new_dependent_set(dev, priority); |
416 | if (!option) | ||
417 | return NULL; | ||
418 | break; | 397 | break; |
419 | 398 | ||
420 | case SMALL_TAG_ENDDEP: | 399 | case SMALL_TAG_ENDDEP: |
421 | if (len != 0) | 400 | if (len != 0) |
422 | goto len_err; | 401 | goto len_err; |
423 | if (option_independent == option) | 402 | option_flags = 0; |
424 | dev_warn(&dev->dev, "missing " | ||
425 | "SMALL_TAG_STARTDEP tag\n"); | ||
426 | option = option_independent; | ||
427 | dev_dbg(&dev->dev, "end dependent options\n"); | ||
428 | break; | 403 | break; |
429 | 404 | ||
430 | case SMALL_TAG_END: | 405 | case SMALL_TAG_END: |
@@ -526,8 +501,16 @@ len_err: | |||
526 | static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, | 501 | static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, |
527 | struct resource *res) | 502 | struct resource *res) |
528 | { | 503 | { |
529 | unsigned long base = res->start; | 504 | unsigned long base; |
530 | unsigned long len = res->end - res->start + 1; | 505 | unsigned long len; |
506 | |||
507 | if (pnp_resource_enabled(res)) { | ||
508 | base = res->start; | ||
509 | len = res->end - res->start + 1; | ||
510 | } else { | ||
511 | base = 0; | ||
512 | len = 0; | ||
513 | } | ||
531 | 514 | ||
532 | p[4] = (base >> 8) & 0xff; | 515 | p[4] = (base >> 8) & 0xff; |
533 | p[5] = ((base >> 8) >> 8) & 0xff; | 516 | p[5] = ((base >> 8) >> 8) & 0xff; |
@@ -536,15 +519,22 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, | |||
536 | p[10] = (len >> 8) & 0xff; | 519 | p[10] = (len >> 8) & 0xff; |
537 | p[11] = ((len >> 8) >> 8) & 0xff; | 520 | p[11] = ((len >> 8) >> 8) & 0xff; |
538 | 521 | ||
539 | dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n", | 522 | dev_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1); |
540 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
541 | } | 523 | } |
542 | 524 | ||
543 | static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, | 525 | static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, |
544 | struct resource *res) | 526 | struct resource *res) |
545 | { | 527 | { |
546 | unsigned long base = res->start; | 528 | unsigned long base; |
547 | unsigned long len = res->end - res->start + 1; | 529 | unsigned long len; |
530 | |||
531 | if (pnp_resource_enabled(res)) { | ||
532 | base = res->start; | ||
533 | len = res->end - res->start + 1; | ||
534 | } else { | ||
535 | base = 0; | ||
536 | len = 0; | ||
537 | } | ||
548 | 538 | ||
549 | p[4] = base & 0xff; | 539 | p[4] = base & 0xff; |
550 | p[5] = (base >> 8) & 0xff; | 540 | p[5] = (base >> 8) & 0xff; |
@@ -559,15 +549,22 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, | |||
559 | p[18] = (len >> 16) & 0xff; | 549 | p[18] = (len >> 16) & 0xff; |
560 | p[19] = (len >> 24) & 0xff; | 550 | p[19] = (len >> 24) & 0xff; |
561 | 551 | ||
562 | dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n", | 552 | dev_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1); |
563 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
564 | } | 553 | } |
565 | 554 | ||
566 | static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, | 555 | static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, |
567 | struct resource *res) | 556 | struct resource *res) |
568 | { | 557 | { |
569 | unsigned long base = res->start; | 558 | unsigned long base; |
570 | unsigned long len = res->end - res->start + 1; | 559 | unsigned long len; |
560 | |||
561 | if (pnp_resource_enabled(res)) { | ||
562 | base = res->start; | ||
563 | len = res->end - res->start + 1; | ||
564 | } else { | ||
565 | base = 0; | ||
566 | len = 0; | ||
567 | } | ||
571 | 568 | ||
572 | p[4] = base & 0xff; | 569 | p[4] = base & 0xff; |
573 | p[5] = (base >> 8) & 0xff; | 570 | p[5] = (base >> 8) & 0xff; |
@@ -578,40 +575,54 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, | |||
578 | p[10] = (len >> 16) & 0xff; | 575 | p[10] = (len >> 16) & 0xff; |
579 | p[11] = (len >> 24) & 0xff; | 576 | p[11] = (len >> 24) & 0xff; |
580 | 577 | ||
581 | dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n", | 578 | dev_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base, |
582 | (unsigned long long) res->start, (unsigned long long) res->end); | 579 | base + len - 1); |
583 | } | 580 | } |
584 | 581 | ||
585 | static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p, | 582 | static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p, |
586 | struct resource *res) | 583 | struct resource *res) |
587 | { | 584 | { |
588 | unsigned long map = 0; | 585 | unsigned long map; |
586 | |||
587 | if (pnp_resource_enabled(res)) | ||
588 | map = 1 << res->start; | ||
589 | else | ||
590 | map = 0; | ||
589 | 591 | ||
590 | map = 1 << res->start; | ||
591 | p[1] = map & 0xff; | 592 | p[1] = map & 0xff; |
592 | p[2] = (map >> 8) & 0xff; | 593 | p[2] = (map >> 8) & 0xff; |
593 | 594 | ||
594 | dev_dbg(&dev->dev, " encode irq %llu\n", | 595 | dev_dbg(&dev->dev, " encode irq mask %#lx\n", map); |
595 | (unsigned long long)res->start); | ||
596 | } | 596 | } |
597 | 597 | ||
598 | static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, | 598 | static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, |
599 | struct resource *res) | 599 | struct resource *res) |
600 | { | 600 | { |
601 | unsigned long map = 0; | 601 | unsigned long map; |
602 | |||
603 | if (pnp_resource_enabled(res)) | ||
604 | map = 1 << res->start; | ||
605 | else | ||
606 | map = 0; | ||
602 | 607 | ||
603 | map = 1 << res->start; | ||
604 | p[1] = map & 0xff; | 608 | p[1] = map & 0xff; |
605 | 609 | ||
606 | dev_dbg(&dev->dev, " encode dma %llu\n", | 610 | dev_dbg(&dev->dev, " encode dma mask %#lx\n", map); |
607 | (unsigned long long)res->start); | ||
608 | } | 611 | } |
609 | 612 | ||
610 | static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, | 613 | static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, |
611 | struct resource *res) | 614 | struct resource *res) |
612 | { | 615 | { |
613 | unsigned long base = res->start; | 616 | unsigned long base; |
614 | unsigned long len = res->end - res->start + 1; | 617 | unsigned long len; |
618 | |||
619 | if (pnp_resource_enabled(res)) { | ||
620 | base = res->start; | ||
621 | len = res->end - res->start + 1; | ||
622 | } else { | ||
623 | base = 0; | ||
624 | len = 0; | ||
625 | } | ||
615 | 626 | ||
616 | p[2] = base & 0xff; | 627 | p[2] = base & 0xff; |
617 | p[3] = (base >> 8) & 0xff; | 628 | p[3] = (base >> 8) & 0xff; |
@@ -619,8 +630,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, | |||
619 | p[5] = (base >> 8) & 0xff; | 630 | p[5] = (base >> 8) & 0xff; |
620 | p[7] = len & 0xff; | 631 | p[7] = len & 0xff; |
621 | 632 | ||
622 | dev_dbg(&dev->dev, " encode io %#llx-%#llx\n", | 633 | dev_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1); |
623 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
624 | } | 634 | } |
625 | 635 | ||
626 | static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, | 636 | static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, |
@@ -629,12 +639,20 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, | |||
629 | unsigned long base = res->start; | 639 | unsigned long base = res->start; |
630 | unsigned long len = res->end - res->start + 1; | 640 | unsigned long len = res->end - res->start + 1; |
631 | 641 | ||
642 | if (pnp_resource_enabled(res)) { | ||
643 | base = res->start; | ||
644 | len = res->end - res->start + 1; | ||
645 | } else { | ||
646 | base = 0; | ||
647 | len = 0; | ||
648 | } | ||
649 | |||
632 | p[1] = base & 0xff; | 650 | p[1] = base & 0xff; |
633 | p[2] = (base >> 8) & 0xff; | 651 | p[2] = (base >> 8) & 0xff; |
634 | p[3] = len & 0xff; | 652 | p[3] = len & 0xff; |
635 | 653 | ||
636 | dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", | 654 | dev_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base, |
637 | (unsigned long long) res->start, (unsigned long long) res->end); | 655 | base + len - 1); |
638 | } | 656 | } |
639 | 657 | ||
640 | static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev | 658 | static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev |
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 1ff3bb585ab2..55f55ed72dc7 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * when building up the resource structure for the first time. | 5 | * when building up the resource structure for the first time. |
6 | * | 6 | * |
7 | * Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk> | 7 | * Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk> |
8 | * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. | ||
9 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | ||
8 | * | 10 | * |
9 | * Heavily based on PCI quirks handling which is | 11 | * Heavily based on PCI quirks handling which is |
10 | * | 12 | * |
@@ -20,203 +22,207 @@ | |||
20 | #include <linux/kallsyms.h> | 22 | #include <linux/kallsyms.h> |
21 | #include "base.h" | 23 | #include "base.h" |
22 | 24 | ||
25 | static void quirk_awe32_add_ports(struct pnp_dev *dev, | ||
26 | struct pnp_option *option, | ||
27 | unsigned int offset) | ||
28 | { | ||
29 | struct pnp_option *new_option; | ||
30 | |||
31 | new_option = kmalloc(sizeof(struct pnp_option), GFP_KERNEL); | ||
32 | if (!new_option) { | ||
33 | dev_err(&dev->dev, "couldn't add ioport region to option set " | ||
34 | "%d\n", pnp_option_set(option)); | ||
35 | return; | ||
36 | } | ||
37 | |||
38 | *new_option = *option; | ||
39 | new_option->u.port.min += offset; | ||
40 | new_option->u.port.max += offset; | ||
41 | list_add(&new_option->list, &option->list); | ||
42 | |||
43 | dev_info(&dev->dev, "added ioport region %#llx-%#llx to set %d\n", | ||
44 | (unsigned long long) new_option->u.port.min, | ||
45 | (unsigned long long) new_option->u.port.max, | ||
46 | pnp_option_set(option)); | ||
47 | } | ||
48 | |||
23 | static void quirk_awe32_resources(struct pnp_dev *dev) | 49 | static void quirk_awe32_resources(struct pnp_dev *dev) |
24 | { | 50 | { |
25 | struct pnp_port *port, *port2, *port3; | 51 | struct pnp_option *option; |
26 | struct pnp_option *res = dev->dependent; | 52 | unsigned int set = ~0; |
27 | 53 | ||
28 | /* | 54 | /* |
29 | * Unfortunately the isapnp_add_port_resource is too tightly bound | 55 | * Add two extra ioport regions (at offset 0x400 and 0x800 from the |
30 | * into the PnP discovery sequence, and cannot be used. Link in the | 56 | * one given) to every dependent option set. |
31 | * two extra ports (at offset 0x400 and 0x800 from the one given) by | ||
32 | * hand. | ||
33 | */ | 57 | */ |
34 | for (; res; res = res->next) { | 58 | list_for_each_entry(option, &dev->options, list) { |
35 | port2 = pnp_alloc(sizeof(struct pnp_port)); | 59 | if (pnp_option_is_dependent(option) && |
36 | if (!port2) | 60 | pnp_option_set(option) != set) { |
37 | return; | 61 | set = pnp_option_set(option); |
38 | port3 = pnp_alloc(sizeof(struct pnp_port)); | 62 | quirk_awe32_add_ports(dev, option, 0x800); |
39 | if (!port3) { | 63 | quirk_awe32_add_ports(dev, option, 0x400); |
40 | kfree(port2); | ||
41 | return; | ||
42 | } | 64 | } |
43 | port = res->port; | ||
44 | memcpy(port2, port, sizeof(struct pnp_port)); | ||
45 | memcpy(port3, port, sizeof(struct pnp_port)); | ||
46 | port->next = port2; | ||
47 | port2->next = port3; | ||
48 | port2->min += 0x400; | ||
49 | port2->max += 0x400; | ||
50 | port3->min += 0x800; | ||
51 | port3->max += 0x800; | ||
52 | dev_info(&dev->dev, | ||
53 | "AWE32 quirk - added ioports 0x%lx and 0x%lx\n", | ||
54 | (unsigned long)port2->min, | ||
55 | (unsigned long)port3->min); | ||
56 | } | 65 | } |
57 | } | 66 | } |
58 | 67 | ||
59 | static void quirk_cmi8330_resources(struct pnp_dev *dev) | 68 | static void quirk_cmi8330_resources(struct pnp_dev *dev) |
60 | { | 69 | { |
61 | struct pnp_option *res = dev->dependent; | 70 | struct pnp_option *option; |
62 | unsigned long tmp; | 71 | struct pnp_irq *irq; |
63 | 72 | struct pnp_dma *dma; | |
64 | for (; res; res = res->next) { | ||
65 | |||
66 | struct pnp_irq *irq; | ||
67 | struct pnp_dma *dma; | ||
68 | 73 | ||
69 | for (irq = res->irq; irq; irq = irq->next) { // Valid irqs are 5, 7, 10 | 74 | list_for_each_entry(option, &dev->options, list) { |
70 | tmp = 0x04A0; | 75 | if (!pnp_option_is_dependent(option)) |
71 | bitmap_copy(irq->map, &tmp, 16); // 0000 0100 1010 0000 | 76 | continue; |
72 | } | ||
73 | 77 | ||
74 | for (dma = res->dma; dma; dma = dma->next) // Valid 8bit dma channels are 1,3 | 78 | if (option->type == IORESOURCE_IRQ) { |
79 | irq = &option->u.irq; | ||
80 | bitmap_zero(irq->map.bits, PNP_IRQ_NR); | ||
81 | __set_bit(5, irq->map.bits); | ||
82 | __set_bit(7, irq->map.bits); | ||
83 | __set_bit(10, irq->map.bits); | ||
84 | dev_info(&dev->dev, "set possible IRQs in " | ||
85 | "option set %d to 5, 7, 10\n", | ||
86 | pnp_option_set(option)); | ||
87 | } else if (option->type == IORESOURCE_DMA) { | ||
88 | dma = &option->u.dma; | ||
75 | if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) == | 89 | if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) == |
76 | IORESOURCE_DMA_8BIT) | 90 | IORESOURCE_DMA_8BIT && |
77 | dma->map = 0x000A; | 91 | dma->map != 0x0A) { |
92 | dev_info(&dev->dev, "changing possible " | ||
93 | "DMA channel mask in option set %d " | ||
94 | "from %#02x to 0x0A (1, 3)\n", | ||
95 | pnp_option_set(option), dma->map); | ||
96 | dma->map = 0x0A; | ||
97 | } | ||
98 | } | ||
78 | } | 99 | } |
79 | dev_info(&dev->dev, "CMI8330 quirk - forced possible IRQs to 5, 7, 10 " | ||
80 | "and DMA channels to 1, 3\n"); | ||
81 | } | 100 | } |
82 | 101 | ||
83 | static void quirk_sb16audio_resources(struct pnp_dev *dev) | 102 | static void quirk_sb16audio_resources(struct pnp_dev *dev) |
84 | { | 103 | { |
104 | struct pnp_option *option; | ||
105 | unsigned int prev_option_flags = ~0, n = 0; | ||
85 | struct pnp_port *port; | 106 | struct pnp_port *port; |
86 | struct pnp_option *res = dev->dependent; | ||
87 | int changed = 0; | ||
88 | 107 | ||
89 | /* | 108 | /* |
90 | * The default range on the mpu port for these devices is 0x388-0x388. | 109 | * The default range on the OPL port for these devices is 0x388-0x388. |
91 | * Here we increase that range so that two such cards can be | 110 | * Here we increase that range so that two such cards can be |
92 | * auto-configured. | 111 | * auto-configured. |
93 | */ | 112 | */ |
113 | list_for_each_entry(option, &dev->options, list) { | ||
114 | if (prev_option_flags != option->flags) { | ||
115 | prev_option_flags = option->flags; | ||
116 | n = 0; | ||
117 | } | ||
94 | 118 | ||
95 | for (; res; res = res->next) { | 119 | if (pnp_option_is_dependent(option) && |
96 | port = res->port; | 120 | option->type == IORESOURCE_IO) { |
97 | if (!port) | 121 | n++; |
98 | continue; | 122 | port = &option->u.port; |
99 | port = port->next; | 123 | if (n == 3 && port->min == port->max) { |
100 | if (!port) | 124 | port->max += 0x70; |
101 | continue; | 125 | dev_info(&dev->dev, "increased option port " |
102 | port = port->next; | 126 | "range from %#llx-%#llx to " |
103 | if (!port) | 127 | "%#llx-%#llx\n", |
104 | continue; | 128 | (unsigned long long) port->min, |
105 | if (port->min != port->max) | 129 | (unsigned long long) port->min, |
106 | continue; | 130 | (unsigned long long) port->min, |
107 | port->max += 0x70; | 131 | (unsigned long long) port->max); |
108 | changed = 1; | 132 | } |
133 | } | ||
109 | } | 134 | } |
110 | if (changed) | ||
111 | dev_info(&dev->dev, "SB audio device quirk - increased port range\n"); | ||
112 | } | 135 | } |
113 | 136 | ||
114 | static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev) | 137 | static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev, |
138 | unsigned int set) | ||
115 | { | 139 | { |
116 | struct pnp_option *head = NULL; | 140 | struct pnp_option *tail = NULL, *first_new_option = NULL; |
117 | struct pnp_option *prev = NULL; | 141 | struct pnp_option *option, *new_option; |
118 | struct pnp_option *res; | 142 | unsigned int flags; |
119 | |||
120 | /* | ||
121 | * Build a functional IRQ-less variant of each MPU option. | ||
122 | */ | ||
123 | |||
124 | for (res = dev->dependent; res; res = res->next) { | ||
125 | struct pnp_option *curr; | ||
126 | struct pnp_port *port; | ||
127 | struct pnp_port *copy; | ||
128 | 143 | ||
129 | port = res->port; | 144 | list_for_each_entry(option, &dev->options, list) { |
130 | if (!port || !res->irq) | 145 | if (pnp_option_is_dependent(option)) |
131 | continue; | 146 | tail = option; |
147 | } | ||
148 | if (!tail) { | ||
149 | dev_err(&dev->dev, "no dependent option sets\n"); | ||
150 | return NULL; | ||
151 | } | ||
132 | 152 | ||
133 | copy = pnp_alloc(sizeof *copy); | 153 | flags = pnp_new_dependent_set(dev, PNP_RES_PRIORITY_FUNCTIONAL); |
134 | if (!copy) | 154 | list_for_each_entry(option, &dev->options, list) { |
135 | break; | 155 | if (pnp_option_is_dependent(option) && |
156 | pnp_option_set(option) == set) { | ||
157 | new_option = kmalloc(sizeof(struct pnp_option), | ||
158 | GFP_KERNEL); | ||
159 | if (!new_option) { | ||
160 | dev_err(&dev->dev, "couldn't clone dependent " | ||
161 | "set %d\n", set); | ||
162 | return NULL; | ||
163 | } | ||
136 | 164 | ||
137 | copy->min = port->min; | 165 | *new_option = *option; |
138 | copy->max = port->max; | 166 | new_option->flags = flags; |
139 | copy->align = port->align; | 167 | if (!first_new_option) |
140 | copy->size = port->size; | 168 | first_new_option = new_option; |
141 | copy->flags = port->flags; | ||
142 | 169 | ||
143 | curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL); | 170 | list_add(&new_option->list, &tail->list); |
144 | if (!curr) { | 171 | tail = new_option; |
145 | kfree(copy); | ||
146 | break; | ||
147 | } | 172 | } |
148 | curr->port = copy; | ||
149 | |||
150 | if (prev) | ||
151 | prev->next = curr; | ||
152 | else | ||
153 | head = curr; | ||
154 | prev = curr; | ||
155 | } | 173 | } |
156 | if (head) | ||
157 | dev_info(&dev->dev, "adding IRQ-less MPU options\n"); | ||
158 | 174 | ||
159 | return head; | 175 | return first_new_option; |
160 | } | 176 | } |
161 | 177 | ||
162 | static void quirk_ad1815_mpu_resources(struct pnp_dev *dev) | 178 | |
179 | static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev) | ||
163 | { | 180 | { |
164 | struct pnp_option *res; | 181 | struct pnp_option *new_option; |
182 | unsigned int num_sets, i, set; | ||
165 | struct pnp_irq *irq; | 183 | struct pnp_irq *irq; |
166 | 184 | ||
167 | /* | 185 | num_sets = dev->num_dependent_sets; |
168 | * Distribute the independent IRQ over the dependent options | 186 | for (i = 0; i < num_sets; i++) { |
169 | */ | 187 | new_option = pnp_clone_dependent_set(dev, i); |
170 | 188 | if (!new_option) | |
171 | res = dev->independent; | 189 | return; |
172 | if (!res) | ||
173 | return; | ||
174 | |||
175 | irq = res->irq; | ||
176 | if (!irq || irq->next) | ||
177 | return; | ||
178 | |||
179 | res = dev->dependent; | ||
180 | if (!res) | ||
181 | return; | ||
182 | |||
183 | while (1) { | ||
184 | struct pnp_irq *copy; | ||
185 | |||
186 | copy = pnp_alloc(sizeof *copy); | ||
187 | if (!copy) | ||
188 | break; | ||
189 | |||
190 | memcpy(copy->map, irq->map, sizeof copy->map); | ||
191 | copy->flags = irq->flags; | ||
192 | 190 | ||
193 | copy->next = res->irq; /* Yes, this is NULL */ | 191 | set = pnp_option_set(new_option); |
194 | res->irq = copy; | 192 | while (new_option && pnp_option_set(new_option) == set) { |
193 | if (new_option->type == IORESOURCE_IRQ) { | ||
194 | irq = &new_option->u.irq; | ||
195 | irq->flags |= IORESOURCE_IRQ_OPTIONAL; | ||
196 | } | ||
197 | dbg_pnp_show_option(dev, new_option); | ||
198 | new_option = list_entry(new_option->list.next, | ||
199 | struct pnp_option, list); | ||
200 | } | ||
195 | 201 | ||
196 | if (!res->next) | 202 | dev_info(&dev->dev, "added dependent option set %d (same as " |
197 | break; | 203 | "set %d except IRQ optional)\n", set, i); |
198 | res = res->next; | ||
199 | } | 204 | } |
200 | kfree(irq); | ||
201 | |||
202 | res->next = quirk_isapnp_mpu_options(dev); | ||
203 | |||
204 | res = dev->independent; | ||
205 | res->irq = NULL; | ||
206 | } | 205 | } |
207 | 206 | ||
208 | static void quirk_isapnp_mpu_resources(struct pnp_dev *dev) | 207 | static void quirk_ad1815_mpu_resources(struct pnp_dev *dev) |
209 | { | 208 | { |
210 | struct pnp_option *res; | 209 | struct pnp_option *option; |
210 | struct pnp_irq *irq = NULL; | ||
211 | unsigned int independent_irqs = 0; | ||
212 | |||
213 | list_for_each_entry(option, &dev->options, list) { | ||
214 | if (option->type == IORESOURCE_IRQ && | ||
215 | !pnp_option_is_dependent(option)) { | ||
216 | independent_irqs++; | ||
217 | irq = &option->u.irq; | ||
218 | } | ||
219 | } | ||
211 | 220 | ||
212 | res = dev->dependent; | 221 | if (independent_irqs != 1) |
213 | if (!res) | ||
214 | return; | 222 | return; |
215 | 223 | ||
216 | while (res->next) | 224 | irq->flags |= IORESOURCE_IRQ_OPTIONAL; |
217 | res = res->next; | 225 | dev_info(&dev->dev, "made independent IRQ optional\n"); |
218 | |||
219 | res->next = quirk_isapnp_mpu_options(dev); | ||
220 | } | 226 | } |
221 | 227 | ||
222 | #include <linux/pci.h> | 228 | #include <linux/pci.h> |
@@ -248,8 +254,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) | |||
248 | for (j = 0; | 254 | for (j = 0; |
249 | (res = pnp_get_resource(dev, IORESOURCE_MEM, j)); | 255 | (res = pnp_get_resource(dev, IORESOURCE_MEM, j)); |
250 | j++) { | 256 | j++) { |
251 | if (res->flags & IORESOURCE_UNSET || | 257 | if (res->start == 0 && res->end == 0) |
252 | (res->start == 0 && res->end == 0)) | ||
253 | continue; | 258 | continue; |
254 | 259 | ||
255 | pnp_start = res->start; | 260 | pnp_start = res->start; |
@@ -312,10 +317,10 @@ static struct pnp_fixup pnp_fixups[] = { | |||
312 | {"CTL0043", quirk_sb16audio_resources}, | 317 | {"CTL0043", quirk_sb16audio_resources}, |
313 | {"CTL0044", quirk_sb16audio_resources}, | 318 | {"CTL0044", quirk_sb16audio_resources}, |
314 | {"CTL0045", quirk_sb16audio_resources}, | 319 | {"CTL0045", quirk_sb16audio_resources}, |
315 | /* Add IRQ-less MPU options */ | 320 | /* Add IRQ-optional MPU options */ |
316 | {"ADS7151", quirk_ad1815_mpu_resources}, | 321 | {"ADS7151", quirk_ad1815_mpu_resources}, |
317 | {"ADS7181", quirk_isapnp_mpu_resources}, | 322 | {"ADS7181", quirk_add_irq_optional_dependent_sets}, |
318 | {"AZT0002", quirk_isapnp_mpu_resources}, | 323 | {"AZT0002", quirk_add_irq_optional_dependent_sets}, |
319 | /* PnP resources that might overlap PCI BARs */ | 324 | /* PnP resources that might overlap PCI BARs */ |
320 | {"PNP0c01", quirk_system_pci_resources}, | 325 | {"PNP0c01", quirk_system_pci_resources}, |
321 | {"PNP0c02", quirk_system_pci_resources}, | 326 | {"PNP0c02", quirk_system_pci_resources}, |
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 390b50096e30..4cfe3a1efdfb 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz> | 4 | * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz> |
5 | * Copyright 2003 Adam Belay <ambx1@neo.rr.com> | 5 | * Copyright 2003 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/module.h> | 10 | #include <linux/module.h> |
@@ -28,201 +30,121 @@ static int pnp_reserve_mem[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some | |||
28 | * option registration | 30 | * option registration |
29 | */ | 31 | */ |
30 | 32 | ||
31 | struct pnp_option *pnp_build_option(int priority) | 33 | struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type, |
34 | unsigned int option_flags) | ||
32 | { | 35 | { |
33 | struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option)); | 36 | struct pnp_option *option; |
34 | 37 | ||
38 | option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL); | ||
35 | if (!option) | 39 | if (!option) |
36 | return NULL; | 40 | return NULL; |
37 | 41 | ||
38 | option->priority = priority & 0xff; | 42 | option->flags = option_flags; |
39 | /* make sure the priority is valid */ | 43 | option->type = type; |
40 | if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL) | ||
41 | option->priority = PNP_RES_PRIORITY_INVALID; | ||
42 | |||
43 | return option; | ||
44 | } | ||
45 | |||
46 | struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) | ||
47 | { | ||
48 | struct pnp_option *option; | ||
49 | |||
50 | option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED); | ||
51 | |||
52 | /* this should never happen but if it does we'll try to continue */ | ||
53 | if (dev->independent) | ||
54 | dev_err(&dev->dev, "independent resource already registered\n"); | ||
55 | dev->independent = option; | ||
56 | 44 | ||
57 | dev_dbg(&dev->dev, "new independent option\n"); | 45 | list_add_tail(&option->list, &dev->options); |
58 | return option; | 46 | return option; |
59 | } | 47 | } |
60 | 48 | ||
61 | struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, | 49 | int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags, |
62 | int priority) | 50 | pnp_irq_mask_t *map, unsigned char flags) |
63 | { | 51 | { |
64 | struct pnp_option *option; | 52 | struct pnp_option *option; |
53 | struct pnp_irq *irq; | ||
65 | 54 | ||
66 | option = pnp_build_option(priority); | 55 | option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags); |
67 | 56 | if (!option) | |
68 | if (dev->dependent) { | 57 | return -ENOMEM; |
69 | struct pnp_option *parent = dev->dependent; | ||
70 | while (parent->next) | ||
71 | parent = parent->next; | ||
72 | parent->next = option; | ||
73 | } else | ||
74 | dev->dependent = option; | ||
75 | |||
76 | dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority); | ||
77 | return option; | ||
78 | } | ||
79 | |||
80 | int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, | ||
81 | struct pnp_irq *data) | ||
82 | { | ||
83 | struct pnp_irq *ptr; | ||
84 | #ifdef DEBUG | ||
85 | char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */ | ||
86 | #endif | ||
87 | 58 | ||
88 | ptr = option->irq; | 59 | irq = &option->u.irq; |
89 | while (ptr && ptr->next) | 60 | irq->map = *map; |
90 | ptr = ptr->next; | 61 | irq->flags = flags; |
91 | if (ptr) | ||
92 | ptr->next = data; | ||
93 | else | ||
94 | option->irq = data; | ||
95 | 62 | ||
96 | #ifdef CONFIG_PCI | 63 | #ifdef CONFIG_PCI |
97 | { | 64 | { |
98 | int i; | 65 | int i; |
99 | 66 | ||
100 | for (i = 0; i < 16; i++) | 67 | for (i = 0; i < 16; i++) |
101 | if (test_bit(i, data->map)) | 68 | if (test_bit(i, irq->map.bits)) |
102 | pcibios_penalize_isa_irq(i, 0); | 69 | pcibios_penalize_isa_irq(i, 0); |
103 | } | 70 | } |
104 | #endif | 71 | #endif |
105 | 72 | ||
106 | #ifdef DEBUG | 73 | dbg_pnp_show_option(dev, option); |
107 | bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR); | ||
108 | dev_dbg(&dev->dev, " irq bitmask %s flags %#x\n", buf, | ||
109 | data->flags); | ||
110 | #endif | ||
111 | return 0; | 74 | return 0; |
112 | } | 75 | } |
113 | 76 | ||
114 | int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, | 77 | int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags, |
115 | struct pnp_dma *data) | 78 | unsigned char map, unsigned char flags) |
116 | { | 79 | { |
117 | struct pnp_dma *ptr; | 80 | struct pnp_option *option; |
118 | 81 | struct pnp_dma *dma; | |
119 | ptr = option->dma; | ||
120 | while (ptr && ptr->next) | ||
121 | ptr = ptr->next; | ||
122 | if (ptr) | ||
123 | ptr->next = data; | ||
124 | else | ||
125 | option->dma = data; | ||
126 | |||
127 | dev_dbg(&dev->dev, " dma bitmask %#x flags %#x\n", data->map, | ||
128 | data->flags); | ||
129 | return 0; | ||
130 | } | ||
131 | 82 | ||
132 | int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, | 83 | option = pnp_build_option(dev, IORESOURCE_DMA, option_flags); |
133 | struct pnp_port *data) | 84 | if (!option) |
134 | { | 85 | return -ENOMEM; |
135 | struct pnp_port *ptr; | ||
136 | |||
137 | ptr = option->port; | ||
138 | while (ptr && ptr->next) | ||
139 | ptr = ptr->next; | ||
140 | if (ptr) | ||
141 | ptr->next = data; | ||
142 | else | ||
143 | option->port = data; | ||
144 | |||
145 | dev_dbg(&dev->dev, " io " | ||
146 | "min %#x max %#x align %d size %d flags %#x\n", | ||
147 | data->min, data->max, data->align, data->size, data->flags); | ||
148 | return 0; | ||
149 | } | ||
150 | 86 | ||
151 | int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, | 87 | dma = &option->u.dma; |
152 | struct pnp_mem *data) | 88 | dma->map = map; |
153 | { | 89 | dma->flags = flags; |
154 | struct pnp_mem *ptr; | 90 | |
155 | 91 | dbg_pnp_show_option(dev, option); | |
156 | ptr = option->mem; | ||
157 | while (ptr && ptr->next) | ||
158 | ptr = ptr->next; | ||
159 | if (ptr) | ||
160 | ptr->next = data; | ||
161 | else | ||
162 | option->mem = data; | ||
163 | |||
164 | dev_dbg(&dev->dev, " mem " | ||
165 | "min %#x max %#x align %d size %d flags %#x\n", | ||
166 | data->min, data->max, data->align, data->size, data->flags); | ||
167 | return 0; | 92 | return 0; |
168 | } | 93 | } |
169 | 94 | ||
170 | static void pnp_free_port(struct pnp_port *port) | 95 | int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags, |
96 | resource_size_t min, resource_size_t max, | ||
97 | resource_size_t align, resource_size_t size, | ||
98 | unsigned char flags) | ||
171 | { | 99 | { |
172 | struct pnp_port *next; | 100 | struct pnp_option *option; |
101 | struct pnp_port *port; | ||
173 | 102 | ||
174 | while (port) { | 103 | option = pnp_build_option(dev, IORESOURCE_IO, option_flags); |
175 | next = port->next; | 104 | if (!option) |
176 | kfree(port); | 105 | return -ENOMEM; |
177 | port = next; | ||
178 | } | ||
179 | } | ||
180 | 106 | ||
181 | static void pnp_free_irq(struct pnp_irq *irq) | 107 | port = &option->u.port; |
182 | { | 108 | port->min = min; |
183 | struct pnp_irq *next; | 109 | port->max = max; |
110 | port->align = align; | ||
111 | port->size = size; | ||
112 | port->flags = flags; | ||
184 | 113 | ||
185 | while (irq) { | 114 | dbg_pnp_show_option(dev, option); |
186 | next = irq->next; | 115 | return 0; |
187 | kfree(irq); | ||
188 | irq = next; | ||
189 | } | ||
190 | } | 116 | } |
191 | 117 | ||
192 | static void pnp_free_dma(struct pnp_dma *dma) | 118 | int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags, |
119 | resource_size_t min, resource_size_t max, | ||
120 | resource_size_t align, resource_size_t size, | ||
121 | unsigned char flags) | ||
193 | { | 122 | { |
194 | struct pnp_dma *next; | 123 | struct pnp_option *option; |
124 | struct pnp_mem *mem; | ||
195 | 125 | ||
196 | while (dma) { | 126 | option = pnp_build_option(dev, IORESOURCE_MEM, option_flags); |
197 | next = dma->next; | 127 | if (!option) |
198 | kfree(dma); | 128 | return -ENOMEM; |
199 | dma = next; | ||
200 | } | ||
201 | } | ||
202 | 129 | ||
203 | static void pnp_free_mem(struct pnp_mem *mem) | 130 | mem = &option->u.mem; |
204 | { | 131 | mem->min = min; |
205 | struct pnp_mem *next; | 132 | mem->max = max; |
133 | mem->align = align; | ||
134 | mem->size = size; | ||
135 | mem->flags = flags; | ||
206 | 136 | ||
207 | while (mem) { | 137 | dbg_pnp_show_option(dev, option); |
208 | next = mem->next; | 138 | return 0; |
209 | kfree(mem); | ||
210 | mem = next; | ||
211 | } | ||
212 | } | 139 | } |
213 | 140 | ||
214 | void pnp_free_option(struct pnp_option *option) | 141 | void pnp_free_options(struct pnp_dev *dev) |
215 | { | 142 | { |
216 | struct pnp_option *next; | 143 | struct pnp_option *option, *tmp; |
217 | 144 | ||
218 | while (option) { | 145 | list_for_each_entry_safe(option, tmp, &dev->options, list) { |
219 | next = option->next; | 146 | list_del(&option->list); |
220 | pnp_free_port(option->port); | ||
221 | pnp_free_irq(option->irq); | ||
222 | pnp_free_dma(option->dma); | ||
223 | pnp_free_mem(option->mem); | ||
224 | kfree(option); | 147 | kfree(option); |
225 | option = next; | ||
226 | } | 148 | } |
227 | } | 149 | } |
228 | 150 | ||
@@ -237,7 +159,7 @@ void pnp_free_option(struct pnp_option *option) | |||
237 | !((*(enda) < *(startb)) || (*(endb) < *(starta))) | 159 | !((*(enda) < *(startb)) || (*(endb) < *(starta))) |
238 | 160 | ||
239 | #define cannot_compare(flags) \ | 161 | #define cannot_compare(flags) \ |
240 | ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) | 162 | ((flags) & IORESOURCE_DISABLED) |
241 | 163 | ||
242 | int pnp_check_port(struct pnp_dev *dev, struct resource *res) | 164 | int pnp_check_port(struct pnp_dev *dev, struct resource *res) |
243 | { | 165 | { |
@@ -364,6 +286,61 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id) | |||
364 | return IRQ_HANDLED; | 286 | return IRQ_HANDLED; |
365 | } | 287 | } |
366 | 288 | ||
289 | #ifdef CONFIG_PCI | ||
290 | static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci, | ||
291 | unsigned int irq) | ||
292 | { | ||
293 | u32 class; | ||
294 | u8 progif; | ||
295 | |||
296 | if (pci->irq == irq) { | ||
297 | dev_dbg(&pnp->dev, "device %s using irq %d\n", | ||
298 | pci_name(pci), irq); | ||
299 | return 1; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * See pci_setup_device() and ata_pci_sff_activate_host() for | ||
304 | * similar IDE legacy detection. | ||
305 | */ | ||
306 | pci_read_config_dword(pci, PCI_CLASS_REVISION, &class); | ||
307 | class >>= 8; /* discard revision ID */ | ||
308 | progif = class & 0xff; | ||
309 | class >>= 8; | ||
310 | |||
311 | if (class == PCI_CLASS_STORAGE_IDE) { | ||
312 | /* | ||
313 | * Unless both channels are native-PCI mode only, | ||
314 | * treat the compatibility IRQs as busy. | ||
315 | */ | ||
316 | if ((progif & 0x5) != 0x5) | ||
317 | if (pci_get_legacy_ide_irq(pci, 0) == irq || | ||
318 | pci_get_legacy_ide_irq(pci, 1) == irq) { | ||
319 | dev_dbg(&pnp->dev, "legacy IDE device %s " | ||
320 | "using irq %d\n", pci_name(pci), irq); | ||
321 | return 1; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | #endif | ||
328 | |||
329 | static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq) | ||
330 | { | ||
331 | #ifdef CONFIG_PCI | ||
332 | struct pci_dev *pci = NULL; | ||
333 | |||
334 | for_each_pci_dev(pci) { | ||
335 | if (pci_dev_uses_irq(pnp, pci, irq)) { | ||
336 | pci_dev_put(pci); | ||
337 | return 1; | ||
338 | } | ||
339 | } | ||
340 | #endif | ||
341 | return 0; | ||
342 | } | ||
343 | |||
367 | int pnp_check_irq(struct pnp_dev *dev, struct resource *res) | 344 | int pnp_check_irq(struct pnp_dev *dev, struct resource *res) |
368 | { | 345 | { |
369 | int i; | 346 | int i; |
@@ -395,18 +372,9 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) | |||
395 | } | 372 | } |
396 | } | 373 | } |
397 | 374 | ||
398 | #ifdef CONFIG_PCI | ||
399 | /* check if the resource is being used by a pci device */ | 375 | /* check if the resource is being used by a pci device */ |
400 | { | 376 | if (pci_uses_irq(dev, *irq)) |
401 | struct pci_dev *pci = NULL; | 377 | return 0; |
402 | for_each_pci_dev(pci) { | ||
403 | if (pci->irq == *irq) { | ||
404 | pci_dev_put(pci); | ||
405 | return 0; | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | #endif | ||
410 | 378 | ||
411 | /* check if the resource is already in use, skip if the | 379 | /* check if the resource is already in use, skip if the |
412 | * device is active because it itself may be in use */ | 380 | * device is active because it itself may be in use */ |
@@ -499,81 +467,37 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) | |||
499 | #endif | 467 | #endif |
500 | } | 468 | } |
501 | 469 | ||
502 | struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, | 470 | int pnp_resource_type(struct resource *res) |
503 | unsigned int type, unsigned int num) | ||
504 | { | 471 | { |
505 | struct pnp_resource_table *res = dev->res; | 472 | return res->flags & (IORESOURCE_IO | IORESOURCE_MEM | |
506 | 473 | IORESOURCE_IRQ | IORESOURCE_DMA); | |
507 | switch (type) { | ||
508 | case IORESOURCE_IO: | ||
509 | if (num >= PNP_MAX_PORT) | ||
510 | return NULL; | ||
511 | return &res->port[num]; | ||
512 | case IORESOURCE_MEM: | ||
513 | if (num >= PNP_MAX_MEM) | ||
514 | return NULL; | ||
515 | return &res->mem[num]; | ||
516 | case IORESOURCE_IRQ: | ||
517 | if (num >= PNP_MAX_IRQ) | ||
518 | return NULL; | ||
519 | return &res->irq[num]; | ||
520 | case IORESOURCE_DMA: | ||
521 | if (num >= PNP_MAX_DMA) | ||
522 | return NULL; | ||
523 | return &res->dma[num]; | ||
524 | } | ||
525 | return NULL; | ||
526 | } | 474 | } |
527 | 475 | ||
528 | struct resource *pnp_get_resource(struct pnp_dev *dev, | 476 | struct resource *pnp_get_resource(struct pnp_dev *dev, |
529 | unsigned int type, unsigned int num) | 477 | unsigned int type, unsigned int num) |
530 | { | 478 | { |
531 | struct pnp_resource *pnp_res; | 479 | struct pnp_resource *pnp_res; |
480 | struct resource *res; | ||
532 | 481 | ||
533 | pnp_res = pnp_get_pnp_resource(dev, type, num); | 482 | list_for_each_entry(pnp_res, &dev->resources, list) { |
534 | if (pnp_res) | 483 | res = &pnp_res->res; |
535 | return &pnp_res->res; | 484 | if (pnp_resource_type(res) == type && num-- == 0) |
536 | 485 | return res; | |
486 | } | ||
537 | return NULL; | 487 | return NULL; |
538 | } | 488 | } |
539 | EXPORT_SYMBOL(pnp_get_resource); | 489 | EXPORT_SYMBOL(pnp_get_resource); |
540 | 490 | ||
541 | static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type) | 491 | static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev) |
542 | { | 492 | { |
543 | struct pnp_resource *pnp_res; | 493 | struct pnp_resource *pnp_res; |
544 | int i; | ||
545 | 494 | ||
546 | switch (type) { | 495 | pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL); |
547 | case IORESOURCE_IO: | 496 | if (!pnp_res) |
548 | for (i = 0; i < PNP_MAX_PORT; i++) { | 497 | return NULL; |
549 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i); | 498 | |
550 | if (pnp_res && !pnp_resource_valid(&pnp_res->res)) | 499 | list_add_tail(&pnp_res->list, &dev->resources); |
551 | return pnp_res; | 500 | return pnp_res; |
552 | } | ||
553 | break; | ||
554 | case IORESOURCE_MEM: | ||
555 | for (i = 0; i < PNP_MAX_MEM; i++) { | ||
556 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i); | ||
557 | if (pnp_res && !pnp_resource_valid(&pnp_res->res)) | ||
558 | return pnp_res; | ||
559 | } | ||
560 | break; | ||
561 | case IORESOURCE_IRQ: | ||
562 | for (i = 0; i < PNP_MAX_IRQ; i++) { | ||
563 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i); | ||
564 | if (pnp_res && !pnp_resource_valid(&pnp_res->res)) | ||
565 | return pnp_res; | ||
566 | } | ||
567 | break; | ||
568 | case IORESOURCE_DMA: | ||
569 | for (i = 0; i < PNP_MAX_DMA; i++) { | ||
570 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i); | ||
571 | if (pnp_res && !pnp_resource_valid(&pnp_res->res)) | ||
572 | return pnp_res; | ||
573 | } | ||
574 | break; | ||
575 | } | ||
576 | return NULL; | ||
577 | } | 501 | } |
578 | 502 | ||
579 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, | 503 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, |
@@ -581,15 +505,10 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, | |||
581 | { | 505 | { |
582 | struct pnp_resource *pnp_res; | 506 | struct pnp_resource *pnp_res; |
583 | struct resource *res; | 507 | struct resource *res; |
584 | static unsigned char warned; | ||
585 | 508 | ||
586 | pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ); | 509 | pnp_res = pnp_new_resource(dev); |
587 | if (!pnp_res) { | 510 | if (!pnp_res) { |
588 | if (!warned) { | 511 | dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq); |
589 | dev_err(&dev->dev, "can't add resource for IRQ %d\n", | ||
590 | irq); | ||
591 | warned = 1; | ||
592 | } | ||
593 | return NULL; | 512 | return NULL; |
594 | } | 513 | } |
595 | 514 | ||
@@ -607,15 +526,10 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, | |||
607 | { | 526 | { |
608 | struct pnp_resource *pnp_res; | 527 | struct pnp_resource *pnp_res; |
609 | struct resource *res; | 528 | struct resource *res; |
610 | static unsigned char warned; | ||
611 | 529 | ||
612 | pnp_res = pnp_new_resource(dev, IORESOURCE_DMA); | 530 | pnp_res = pnp_new_resource(dev); |
613 | if (!pnp_res) { | 531 | if (!pnp_res) { |
614 | if (!warned) { | 532 | dev_err(&dev->dev, "can't add resource for DMA %d\n", dma); |
615 | dev_err(&dev->dev, "can't add resource for DMA %d\n", | ||
616 | dma); | ||
617 | warned = 1; | ||
618 | } | ||
619 | return NULL; | 533 | return NULL; |
620 | } | 534 | } |
621 | 535 | ||
@@ -634,16 +548,12 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, | |||
634 | { | 548 | { |
635 | struct pnp_resource *pnp_res; | 549 | struct pnp_resource *pnp_res; |
636 | struct resource *res; | 550 | struct resource *res; |
637 | static unsigned char warned; | ||
638 | 551 | ||
639 | pnp_res = pnp_new_resource(dev, IORESOURCE_IO); | 552 | pnp_res = pnp_new_resource(dev); |
640 | if (!pnp_res) { | 553 | if (!pnp_res) { |
641 | if (!warned) { | 554 | dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n", |
642 | dev_err(&dev->dev, "can't add resource for IO " | 555 | (unsigned long long) start, |
643 | "%#llx-%#llx\n",(unsigned long long) start, | 556 | (unsigned long long) end); |
644 | (unsigned long long) end); | ||
645 | warned = 1; | ||
646 | } | ||
647 | return NULL; | 557 | return NULL; |
648 | } | 558 | } |
649 | 559 | ||
@@ -663,16 +573,12 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, | |||
663 | { | 573 | { |
664 | struct pnp_resource *pnp_res; | 574 | struct pnp_resource *pnp_res; |
665 | struct resource *res; | 575 | struct resource *res; |
666 | static unsigned char warned; | ||
667 | 576 | ||
668 | pnp_res = pnp_new_resource(dev, IORESOURCE_MEM); | 577 | pnp_res = pnp_new_resource(dev); |
669 | if (!pnp_res) { | 578 | if (!pnp_res) { |
670 | if (!warned) { | 579 | dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n", |
671 | dev_err(&dev->dev, "can't add resource for MEM " | 580 | (unsigned long long) start, |
672 | "%#llx-%#llx\n",(unsigned long long) start, | 581 | (unsigned long long) end); |
673 | (unsigned long long) end); | ||
674 | warned = 1; | ||
675 | } | ||
676 | return NULL; | 582 | return NULL; |
677 | } | 583 | } |
678 | 584 | ||
@@ -686,6 +592,52 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, | |||
686 | return pnp_res; | 592 | return pnp_res; |
687 | } | 593 | } |
688 | 594 | ||
595 | /* | ||
596 | * Determine whether the specified resource is a possible configuration | ||
597 | * for this device. | ||
598 | */ | ||
599 | int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start, | ||
600 | resource_size_t size) | ||
601 | { | ||
602 | struct pnp_option *option; | ||
603 | struct pnp_port *port; | ||
604 | struct pnp_mem *mem; | ||
605 | struct pnp_irq *irq; | ||
606 | struct pnp_dma *dma; | ||
607 | |||
608 | list_for_each_entry(option, &dev->options, list) { | ||
609 | if (option->type != type) | ||
610 | continue; | ||
611 | |||
612 | switch (option->type) { | ||
613 | case IORESOURCE_IO: | ||
614 | port = &option->u.port; | ||
615 | if (port->min == start && port->size == size) | ||
616 | return 1; | ||
617 | break; | ||
618 | case IORESOURCE_MEM: | ||
619 | mem = &option->u.mem; | ||
620 | if (mem->min == start && mem->size == size) | ||
621 | return 1; | ||
622 | break; | ||
623 | case IORESOURCE_IRQ: | ||
624 | irq = &option->u.irq; | ||
625 | if (start < PNP_IRQ_NR && | ||
626 | test_bit(start, irq->map.bits)) | ||
627 | return 1; | ||
628 | break; | ||
629 | case IORESOURCE_DMA: | ||
630 | dma = &option->u.dma; | ||
631 | if (dma->map & (1 << start)) | ||
632 | return 1; | ||
633 | break; | ||
634 | } | ||
635 | } | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | EXPORT_SYMBOL(pnp_possible_config); | ||
640 | |||
689 | /* format is: pnp_reserve_irq=irq1[,irq2] .... */ | 641 | /* format is: pnp_reserve_irq=irq1[,irq2] .... */ |
690 | static int __init pnp_setup_reserve_irq(char *str) | 642 | static int __init pnp_setup_reserve_irq(char *str) |
691 | { | 643 | { |
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index 95b076c18c07..bbf78ef4ba02 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c | |||
@@ -2,6 +2,8 @@ | |||
2 | * support.c - standard functions for the use of pnp protocol drivers | 2 | * support.c - standard functions for the use of pnp protocol drivers |
3 | * | 3 | * |
4 | * Copyright 2003 Adam Belay <ambx1@neo.rr.com> | 4 | * Copyright 2003 Adam Belay <ambx1@neo.rr.com> |
5 | * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. | ||
6 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | ||
5 | */ | 7 | */ |
6 | 8 | ||
7 | #include <linux/module.h> | 9 | #include <linux/module.h> |
@@ -16,6 +18,10 @@ | |||
16 | */ | 18 | */ |
17 | int pnp_is_active(struct pnp_dev *dev) | 19 | int pnp_is_active(struct pnp_dev *dev) |
18 | { | 20 | { |
21 | /* | ||
22 | * I don't think this is very reliable because pnp_disable_dev() | ||
23 | * only clears out auto-assigned resources. | ||
24 | */ | ||
19 | if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 && | 25 | if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 && |
20 | !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 && | 26 | !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 && |
21 | pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1) | 27 | pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1) |
@@ -52,39 +58,154 @@ void pnp_eisa_id_to_string(u32 id, char *str) | |||
52 | str[7] = '\0'; | 58 | str[7] = '\0'; |
53 | } | 59 | } |
54 | 60 | ||
61 | char *pnp_resource_type_name(struct resource *res) | ||
62 | { | ||
63 | switch (pnp_resource_type(res)) { | ||
64 | case IORESOURCE_IO: | ||
65 | return "io"; | ||
66 | case IORESOURCE_MEM: | ||
67 | return "mem"; | ||
68 | case IORESOURCE_IRQ: | ||
69 | return "irq"; | ||
70 | case IORESOURCE_DMA: | ||
71 | return "dma"; | ||
72 | } | ||
73 | return NULL; | ||
74 | } | ||
75 | |||
55 | void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) | 76 | void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) |
56 | { | 77 | { |
57 | #ifdef DEBUG | 78 | #ifdef DEBUG |
79 | char buf[128]; | ||
80 | int len = 0; | ||
81 | struct pnp_resource *pnp_res; | ||
58 | struct resource *res; | 82 | struct resource *res; |
59 | int i; | ||
60 | 83 | ||
61 | dev_dbg(&dev->dev, "current resources: %s\n", desc); | 84 | if (list_empty(&dev->resources)) { |
62 | 85 | dev_dbg(&dev->dev, "%s: no current resources\n", desc); | |
63 | for (i = 0; i < PNP_MAX_IRQ; i++) { | 86 | return; |
64 | res = pnp_get_resource(dev, IORESOURCE_IRQ, i); | ||
65 | if (res && !(res->flags & IORESOURCE_UNSET)) | ||
66 | dev_dbg(&dev->dev, " irq %lld flags %#lx\n", | ||
67 | (unsigned long long) res->start, res->flags); | ||
68 | } | 87 | } |
69 | for (i = 0; i < PNP_MAX_DMA; i++) { | 88 | |
70 | res = pnp_get_resource(dev, IORESOURCE_DMA, i); | 89 | dev_dbg(&dev->dev, "%s: current resources:\n", desc); |
71 | if (res && !(res->flags & IORESOURCE_UNSET)) | 90 | list_for_each_entry(pnp_res, &dev->resources, list) { |
72 | dev_dbg(&dev->dev, " dma %lld flags %#lx\n", | 91 | res = &pnp_res->res; |
73 | (unsigned long long) res->start, res->flags); | 92 | |
93 | len += snprintf(buf + len, sizeof(buf) - len, " %-3s ", | ||
94 | pnp_resource_type_name(res)); | ||
95 | |||
96 | if (res->flags & IORESOURCE_DISABLED) { | ||
97 | dev_dbg(&dev->dev, "%sdisabled\n", buf); | ||
98 | continue; | ||
99 | } | ||
100 | |||
101 | switch (pnp_resource_type(res)) { | ||
102 | case IORESOURCE_IO: | ||
103 | case IORESOURCE_MEM: | ||
104 | len += snprintf(buf + len, sizeof(buf) - len, | ||
105 | "%#llx-%#llx flags %#lx", | ||
106 | (unsigned long long) res->start, | ||
107 | (unsigned long long) res->end, | ||
108 | res->flags); | ||
109 | break; | ||
110 | case IORESOURCE_IRQ: | ||
111 | case IORESOURCE_DMA: | ||
112 | len += snprintf(buf + len, sizeof(buf) - len, | ||
113 | "%lld flags %#lx", | ||
114 | (unsigned long long) res->start, | ||
115 | res->flags); | ||
116 | break; | ||
117 | } | ||
118 | dev_dbg(&dev->dev, "%s\n", buf); | ||
74 | } | 119 | } |
75 | for (i = 0; i < PNP_MAX_PORT; i++) { | 120 | #endif |
76 | res = pnp_get_resource(dev, IORESOURCE_IO, i); | 121 | } |
77 | if (res && !(res->flags & IORESOURCE_UNSET)) | 122 | |
78 | dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx\n", | 123 | char *pnp_option_priority_name(struct pnp_option *option) |
79 | (unsigned long long) res->start, | 124 | { |
80 | (unsigned long long) res->end, res->flags); | 125 | switch (pnp_option_priority(option)) { |
126 | case PNP_RES_PRIORITY_PREFERRED: | ||
127 | return "preferred"; | ||
128 | case PNP_RES_PRIORITY_ACCEPTABLE: | ||
129 | return "acceptable"; | ||
130 | case PNP_RES_PRIORITY_FUNCTIONAL: | ||
131 | return "functional"; | ||
81 | } | 132 | } |
82 | for (i = 0; i < PNP_MAX_MEM; i++) { | 133 | return "invalid"; |
83 | res = pnp_get_resource(dev, IORESOURCE_MEM, i); | 134 | } |
84 | if (res && !(res->flags & IORESOURCE_UNSET)) | 135 | |
85 | dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx\n", | 136 | void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option) |
86 | (unsigned long long) res->start, | 137 | { |
87 | (unsigned long long) res->end, res->flags); | 138 | #ifdef DEBUG |
139 | char buf[128]; | ||
140 | int len = 0, i; | ||
141 | struct pnp_port *port; | ||
142 | struct pnp_mem *mem; | ||
143 | struct pnp_irq *irq; | ||
144 | struct pnp_dma *dma; | ||
145 | |||
146 | if (pnp_option_is_dependent(option)) | ||
147 | len += snprintf(buf + len, sizeof(buf) - len, | ||
148 | " dependent set %d (%s) ", | ||
149 | pnp_option_set(option), | ||
150 | pnp_option_priority_name(option)); | ||
151 | else | ||
152 | len += snprintf(buf + len, sizeof(buf) - len, " independent "); | ||
153 | |||
154 | switch (option->type) { | ||
155 | case IORESOURCE_IO: | ||
156 | port = &option->u.port; | ||
157 | len += snprintf(buf + len, sizeof(buf) - len, "io min %#llx " | ||
158 | "max %#llx align %lld size %lld flags %#x", | ||
159 | (unsigned long long) port->min, | ||
160 | (unsigned long long) port->max, | ||
161 | (unsigned long long) port->align, | ||
162 | (unsigned long long) port->size, port->flags); | ||
163 | break; | ||
164 | case IORESOURCE_MEM: | ||
165 | mem = &option->u.mem; | ||
166 | len += snprintf(buf + len, sizeof(buf) - len, "mem min %#llx " | ||
167 | "max %#llx align %lld size %lld flags %#x", | ||
168 | (unsigned long long) mem->min, | ||
169 | (unsigned long long) mem->max, | ||
170 | (unsigned long long) mem->align, | ||
171 | (unsigned long long) mem->size, mem->flags); | ||
172 | break; | ||
173 | case IORESOURCE_IRQ: | ||
174 | irq = &option->u.irq; | ||
175 | len += snprintf(buf + len, sizeof(buf) - len, "irq"); | ||
176 | if (bitmap_empty(irq->map.bits, PNP_IRQ_NR)) | ||
177 | len += snprintf(buf + len, sizeof(buf) - len, | ||
178 | " <none>"); | ||
179 | else { | ||
180 | for (i = 0; i < PNP_IRQ_NR; i++) | ||
181 | if (test_bit(i, irq->map.bits)) | ||
182 | len += snprintf(buf + len, | ||
183 | sizeof(buf) - len, | ||
184 | " %d", i); | ||
185 | } | ||
186 | len += snprintf(buf + len, sizeof(buf) - len, " flags %#x", | ||
187 | irq->flags); | ||
188 | if (irq->flags & IORESOURCE_IRQ_OPTIONAL) | ||
189 | len += snprintf(buf + len, sizeof(buf) - len, | ||
190 | " (optional)"); | ||
191 | break; | ||
192 | case IORESOURCE_DMA: | ||
193 | dma = &option->u.dma; | ||
194 | len += snprintf(buf + len, sizeof(buf) - len, "dma"); | ||
195 | if (!dma->map) | ||
196 | len += snprintf(buf + len, sizeof(buf) - len, | ||
197 | " <none>"); | ||
198 | else { | ||
199 | for (i = 0; i < 8; i++) | ||
200 | if (dma->map & (1 << i)) | ||
201 | len += snprintf(buf + len, | ||
202 | sizeof(buf) - len, | ||
203 | " %d", i); | ||
204 | } | ||
205 | len += snprintf(buf + len, sizeof(buf) - len, " (bitmask %#x) " | ||
206 | "flags %#x", dma->map, dma->flags); | ||
207 | break; | ||
88 | } | 208 | } |
209 | dev_dbg(&dev->dev, "%s\n", buf); | ||
89 | #endif | 210 | #endif |
90 | } | 211 | } |
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index cf4e07b01d48..764f3a310685 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c | |||
@@ -60,7 +60,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) | |||
60 | int i; | 60 | int i; |
61 | 61 | ||
62 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { | 62 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { |
63 | if (res->flags & IORESOURCE_UNSET) | 63 | if (res->flags & IORESOURCE_DISABLED) |
64 | continue; | 64 | continue; |
65 | if (res->start == 0) | 65 | if (res->start == 0) |
66 | continue; /* disabled */ | 66 | continue; /* disabled */ |
@@ -81,7 +81,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) | |||
81 | } | 81 | } |
82 | 82 | ||
83 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { | 83 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { |
84 | if (res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) | 84 | if (res->flags & IORESOURCE_DISABLED) |
85 | continue; | 85 | continue; |
86 | 86 | ||
87 | reserve_range(dev, res->start, res->end, 0); | 87 | reserve_range(dev, res->start, res->end, 0); |