aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/manager.c')
-rw-r--r--drivers/pnp/manager.c145
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 */
235static int pnp_assign_resources(struct pnp_dev *dev, int depnum) 235static 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
322fail:
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 */
333int pnp_auto_config_dev(struct pnp_dev *dev) 284int 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/**