diff options
Diffstat (limited to 'drivers/pnp/manager.c')
-rw-r--r-- | drivers/pnp/manager.c | 145 |
1 files changed, 46 insertions, 99 deletions
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index a20accb5ef8f..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> |
@@ -228,102 +230,51 @@ static void pnp_clean_resource_table(struct pnp_dev *dev) | |||
228 | /** | 230 | /** |
229 | * 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 |
230 | * @dev: pointer to the desired device | 232 | * @dev: pointer to the desired device |
231 | * @depnum: the dependent function number | 233 | * @set: the dependent function number |
232 | * | ||
233 | * Only set depnum to 0 if the device does not have dependent options. | ||
234 | */ | 234 | */ |
235 | static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | 235 | static int pnp_assign_resources(struct pnp_dev *dev, int set) |
236 | { | 236 | { |
237 | struct pnp_port *port; | 237 | struct pnp_option *option; |
238 | struct pnp_mem *mem; | ||
239 | struct pnp_irq *irq; | ||
240 | struct pnp_dma *dma; | ||
241 | int nport = 0, nmem = 0, nirq = 0, ndma = 0; | 238 | int nport = 0, nmem = 0, nirq = 0, ndma = 0; |
239 | int ret = 0; | ||
242 | 240 | ||
243 | dbg_pnp_show_resources(dev, "before pnp_assign_resources"); | 241 | dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set); |
244 | mutex_lock(&pnp_res_mutex); | 242 | mutex_lock(&pnp_res_mutex); |
245 | pnp_clean_resource_table(dev); | 243 | pnp_clean_resource_table(dev); |
246 | if (dev->independent) { | ||
247 | dev_dbg(&dev->dev, "assigning independent options\n"); | ||
248 | port = dev->independent->port; | ||
249 | mem = dev->independent->mem; | ||
250 | irq = dev->independent->irq; | ||
251 | dma = dev->independent->dma; | ||
252 | while (port) { | ||
253 | if (pnp_assign_port(dev, port, nport) < 0) | ||
254 | goto fail; | ||
255 | nport++; | ||
256 | port = port->next; | ||
257 | } | ||
258 | while (mem) { | ||
259 | if (pnp_assign_mem(dev, mem, nmem) < 0) | ||
260 | goto fail; | ||
261 | nmem++; | ||
262 | mem = mem->next; | ||
263 | } | ||
264 | while (irq) { | ||
265 | if (pnp_assign_irq(dev, irq, nirq) < 0) | ||
266 | goto fail; | ||
267 | nirq++; | ||
268 | irq = irq->next; | ||
269 | } | ||
270 | while (dma) { | ||
271 | if (pnp_assign_dma(dev, dma, ndma) < 0) | ||
272 | goto fail; | ||
273 | ndma++; | ||
274 | dma = dma->next; | ||
275 | } | ||
276 | } | ||
277 | 244 | ||
278 | if (depnum) { | 245 | list_for_each_entry(option, &dev->options, list) { |
279 | struct pnp_option *dep; | 246 | if (pnp_option_is_dependent(option) && |
280 | int i; | 247 | pnp_option_set(option) != set) |
281 | 248 | continue; | |
282 | dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); | 249 | |
283 | for (i = 1, dep = dev->dependent; i < depnum; | 250 | switch (option->type) { |
284 | i++, dep = dep->next) | 251 | case IORESOURCE_IO: |
285 | if (!dep) | 252 | ret = pnp_assign_port(dev, &option->u.port, nport++); |
286 | goto fail; | 253 | break; |
287 | port = dep->port; | 254 | case IORESOURCE_MEM: |
288 | mem = dep->mem; | 255 | ret = pnp_assign_mem(dev, &option->u.mem, nmem++); |
289 | irq = dep->irq; | 256 | break; |
290 | dma = dep->dma; | 257 | case IORESOURCE_IRQ: |
291 | while (port) { | 258 | ret = pnp_assign_irq(dev, &option->u.irq, nirq++); |
292 | if (pnp_assign_port(dev, port, nport) < 0) | 259 | break; |
293 | goto fail; | 260 | case IORESOURCE_DMA: |
294 | nport++; | 261 | ret = pnp_assign_dma(dev, &option->u.dma, ndma++); |
295 | port = port->next; | 262 | break; |
296 | } | 263 | default: |
297 | while (mem) { | 264 | ret = -EINVAL; |
298 | if (pnp_assign_mem(dev, mem, nmem) < 0) | 265 | break; |
299 | goto fail; | ||
300 | nmem++; | ||
301 | mem = mem->next; | ||
302 | } | ||
303 | while (irq) { | ||
304 | if (pnp_assign_irq(dev, irq, nirq) < 0) | ||
305 | goto fail; | ||
306 | nirq++; | ||
307 | irq = irq->next; | ||
308 | } | ||
309 | while (dma) { | ||
310 | if (pnp_assign_dma(dev, dma, ndma) < 0) | ||
311 | goto fail; | ||
312 | ndma++; | ||
313 | dma = dma->next; | ||
314 | } | 266 | } |
315 | } else if (dev->dependent) | 267 | if (ret < 0) |
316 | goto fail; | 268 | break; |
317 | 269 | } | |
318 | mutex_unlock(&pnp_res_mutex); | ||
319 | dbg_pnp_show_resources(dev, "after pnp_assign_resources"); | ||
320 | return 1; | ||
321 | 270 | ||
322 | fail: | ||
323 | pnp_clean_resource_table(dev); | ||
324 | mutex_unlock(&pnp_res_mutex); | 271 | mutex_unlock(&pnp_res_mutex); |
325 | dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); | 272 | if (ret < 0) { |
326 | 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; | ||
327 | } | 278 | } |
328 | 279 | ||
329 | /** | 280 | /** |
@@ -332,29 +283,25 @@ fail: | |||
332 | */ | 283 | */ |
333 | int pnp_auto_config_dev(struct pnp_dev *dev) | 284 | int pnp_auto_config_dev(struct pnp_dev *dev) |
334 | { | 285 | { |
335 | struct pnp_option *dep; | 286 | int i, ret; |
336 | int i = 1; | ||
337 | 287 | ||
338 | if (!pnp_can_configure(dev)) { | 288 | if (!pnp_can_configure(dev)) { |
339 | dev_dbg(&dev->dev, "configuration not supported\n"); | 289 | dev_dbg(&dev->dev, "configuration not supported\n"); |
340 | return -ENODEV; | 290 | return -ENODEV; |
341 | } | 291 | } |
342 | 292 | ||
343 | if (!dev->dependent) { | 293 | ret = pnp_assign_resources(dev, 0); |
344 | 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) | ||
345 | return 0; | 300 | return 0; |
346 | } else { | ||
347 | dep = dev->dependent; | ||
348 | do { | ||
349 | if (pnp_assign_resources(dev, i)) | ||
350 | return 0; | ||
351 | dep = dep->next; | ||
352 | i++; | ||
353 | } while (dep); | ||
354 | } | 301 | } |
355 | 302 | ||
356 | dev_err(&dev->dev, "unable to assign resources\n"); | 303 | dev_err(&dev->dev, "unable to assign resources\n"); |
357 | return -EBUSY; | 304 | return ret; |
358 | } | 305 | } |
359 | 306 | ||
360 | /** | 307 | /** |