xref: /openbmc/linux/drivers/pnp/manager.c (revision 87c2ce3b)
1 /*
2  * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices
3  *
4  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
5  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
6  *
7  */
8 
9 #include <linux/config.h>
10 #include <linux/errno.h>
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/pnp.h>
15 #include <linux/slab.h>
16 #include <linux/bitmap.h>
17 #include "base.h"
18 
19 DECLARE_MUTEX(pnp_res_mutex);
20 
21 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
22 {
23 	unsigned long *start, *end, *flags;
24 
25 	if (!dev || !rule)
26 		return -EINVAL;
27 
28 	if (idx >= PNP_MAX_PORT) {
29 		pnp_err("More than 4 ports is incompatible with pnp specifications.");
30 		/* pretend we were successful so at least the manager won't try again */
31 		return 1;
32 	}
33 
34 	/* check if this resource has been manually set, if so skip */
35 	if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
36 		return 1;
37 
38 	start = &dev->res.port_resource[idx].start;
39 	end = &dev->res.port_resource[idx].end;
40 	flags = &dev->res.port_resource[idx].flags;
41 
42 	/* set the initial values */
43 	*flags |= rule->flags | IORESOURCE_IO;
44 	*flags &=  ~IORESOURCE_UNSET;
45 
46 	if (!rule->size) {
47 		*flags |= IORESOURCE_DISABLED;
48 		return 1; /* skip disabled resource requests */
49 	}
50 
51 	*start = rule->min;
52 	*end = *start + rule->size - 1;
53 
54 	/* run through until pnp_check_port is happy */
55 	while (!pnp_check_port(dev, idx)) {
56 		*start += rule->align;
57 		*end = *start + rule->size - 1;
58 		if (*start > rule->max || !rule->align)
59 			return 0;
60 	}
61 	return 1;
62 }
63 
64 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
65 {
66 	unsigned long *start, *end, *flags;
67 
68 	if (!dev || !rule)
69 		return -EINVAL;
70 
71 	if (idx >= PNP_MAX_MEM) {
72 		pnp_err("More than 8 mems is incompatible with pnp specifications.");
73 		/* pretend we were successful so at least the manager won't try again */
74 		return 1;
75 	}
76 
77 	/* check if this resource has been manually set, if so skip */
78 	if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO))
79 		return 1;
80 
81 	start = &dev->res.mem_resource[idx].start;
82 	end = &dev->res.mem_resource[idx].end;
83 	flags = &dev->res.mem_resource[idx].flags;
84 
85 	/* set the initial values */
86 	*flags |= rule->flags | IORESOURCE_MEM;
87 	*flags &=  ~IORESOURCE_UNSET;
88 
89 	/* convert pnp flags to standard Linux flags */
90 	if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
91 		*flags |= IORESOURCE_READONLY;
92 	if (rule->flags & IORESOURCE_MEM_CACHEABLE)
93 		*flags |= IORESOURCE_CACHEABLE;
94 	if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
95 		*flags |= IORESOURCE_RANGELENGTH;
96 	if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
97 		*flags |= IORESOURCE_SHADOWABLE;
98 
99 	if (!rule->size) {
100 		*flags |= IORESOURCE_DISABLED;
101 		return 1; /* skip disabled resource requests */
102 	}
103 
104 	*start = rule->min;
105 	*end = *start + rule->size -1;
106 
107 	/* run through until pnp_check_mem is happy */
108 	while (!pnp_check_mem(dev, idx)) {
109 		*start += rule->align;
110 		*end = *start + rule->size - 1;
111 		if (*start > rule->max || !rule->align)
112 			return 0;
113 	}
114 	return 1;
115 }
116 
117 static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx)
118 {
119 	unsigned long *start, *end, *flags;
120 	int i;
121 
122 	/* IRQ priority: this table is good for i386 */
123 	static unsigned short xtab[16] = {
124 		5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
125 	};
126 
127 	if (!dev || !rule)
128 		return -EINVAL;
129 
130 	if (idx >= PNP_MAX_IRQ) {
131 		pnp_err("More than 2 irqs is incompatible with pnp specifications.");
132 		/* pretend we were successful so at least the manager won't try again */
133 		return 1;
134 	}
135 
136 	/* check if this resource has been manually set, if so skip */
137 	if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO))
138 		return 1;
139 
140 	start = &dev->res.irq_resource[idx].start;
141 	end = &dev->res.irq_resource[idx].end;
142 	flags = &dev->res.irq_resource[idx].flags;
143 
144 	/* set the initial values */
145 	*flags |= rule->flags | IORESOURCE_IRQ;
146 	*flags &=  ~IORESOURCE_UNSET;
147 
148 	if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
149 		*flags |= IORESOURCE_DISABLED;
150 		return 1; /* skip disabled resource requests */
151 	}
152 
153 	/* TBD: need check for >16 IRQ */
154 	*start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
155 	if (*start < PNP_IRQ_NR) {
156 		*end = *start;
157 		return 1;
158 	}
159 	for (i = 0; i < 16; i++) {
160 		if(test_bit(xtab[i], rule->map)) {
161 			*start = *end = xtab[i];
162 			if(pnp_check_irq(dev, idx))
163 				return 1;
164 		}
165 	}
166 	return 0;
167 }
168 
169 static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
170 {
171 	unsigned long *start, *end, *flags;
172 	int i;
173 
174 	/* DMA priority: this table is good for i386 */
175 	static unsigned short xtab[8] = {
176 		1, 3, 5, 6, 7, 0, 2, 4
177 	};
178 
179 	if (!dev || !rule)
180 		return -EINVAL;
181 
182 	if (idx >= PNP_MAX_DMA) {
183 		pnp_err("More than 2 dmas is incompatible with pnp specifications.");
184 		/* pretend we were successful so at least the manager won't try again */
185 		return 1;
186 	}
187 
188 	/* check if this resource has been manually set, if so skip */
189 	if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO))
190 		return 1;
191 
192 	start = &dev->res.dma_resource[idx].start;
193 	end = &dev->res.dma_resource[idx].end;
194 	flags = &dev->res.dma_resource[idx].flags;
195 
196 	/* set the initial values */
197 	*flags |= rule->flags | IORESOURCE_DMA;
198 	*flags &=  ~IORESOURCE_UNSET;
199 
200 	if (!rule->map) {
201 		*flags |= IORESOURCE_DISABLED;
202 		return 1; /* skip disabled resource requests */
203 	}
204 
205 	for (i = 0; i < 8; i++) {
206 		if(rule->map & (1<<xtab[i])) {
207 			*start = *end = xtab[i];
208 			if(pnp_check_dma(dev, idx))
209 				return 1;
210 		}
211 	}
212 	return 0;
213 }
214 
215 /**
216  * pnp_init_resources - Resets a resource table to default values.
217  * @table: pointer to the desired resource table
218  *
219  */
220 void pnp_init_resource_table(struct pnp_resource_table *table)
221 {
222 	int idx;
223 	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
224 		table->irq_resource[idx].name = NULL;
225 		table->irq_resource[idx].start = -1;
226 		table->irq_resource[idx].end = -1;
227 		table->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
228 	}
229 	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
230 		table->dma_resource[idx].name = NULL;
231 		table->dma_resource[idx].start = -1;
232 		table->dma_resource[idx].end = -1;
233 		table->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
234 	}
235 	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
236 		table->port_resource[idx].name = NULL;
237 		table->port_resource[idx].start = 0;
238 		table->port_resource[idx].end = 0;
239 		table->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
240 	}
241 	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
242 		table->mem_resource[idx].name = NULL;
243 		table->mem_resource[idx].start = 0;
244 		table->mem_resource[idx].end = 0;
245 		table->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
246 	}
247 }
248 
249 /**
250  * pnp_clean_resources - clears resources that were not manually set
251  * @res: the resources to clean
252  *
253  */
254 static void pnp_clean_resource_table(struct pnp_resource_table * res)
255 {
256 	int idx;
257 	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
258 		if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO))
259 			continue;
260 		res->irq_resource[idx].start = -1;
261 		res->irq_resource[idx].end = -1;
262 		res->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
263 	}
264 	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
265 		if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO))
266 			continue;
267 		res->dma_resource[idx].start = -1;
268 		res->dma_resource[idx].end = -1;
269 		res->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
270 	}
271 	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
272 		if (!(res->port_resource[idx].flags & IORESOURCE_AUTO))
273 			continue;
274 		res->port_resource[idx].start = 0;
275 		res->port_resource[idx].end = 0;
276 		res->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
277 	}
278 	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
279 		if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO))
280 			continue;
281 		res->mem_resource[idx].start = 0;
282 		res->mem_resource[idx].end = 0;
283 		res->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
284 	}
285 }
286 
287 /**
288  * pnp_assign_resources - assigns resources to the device based on the specified dependent number
289  * @dev: pointer to the desired device
290  * @depnum: the dependent function number
291  *
292  * Only set depnum to 0 if the device does not have dependent options.
293  */
294 static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
295 {
296 	struct pnp_port *port;
297 	struct pnp_mem *mem;
298 	struct pnp_irq *irq;
299 	struct pnp_dma *dma;
300 	int nport = 0, nmem = 0, nirq = 0, ndma = 0;
301 
302 	if (!pnp_can_configure(dev))
303 		return -ENODEV;
304 
305 	down(&pnp_res_mutex);
306 	pnp_clean_resource_table(&dev->res); /* start with a fresh slate */
307 	if (dev->independent) {
308 		port = dev->independent->port;
309 		mem = dev->independent->mem;
310 		irq = dev->independent->irq;
311 		dma = dev->independent->dma;
312 		while (port) {
313 			if (!pnp_assign_port(dev, port, nport))
314 				goto fail;
315 			nport++;
316 			port = port->next;
317 		}
318 		while (mem) {
319 			if (!pnp_assign_mem(dev, mem, nmem))
320 				goto fail;
321 			nmem++;
322 			mem = mem->next;
323 		}
324 		while (irq) {
325 			if (!pnp_assign_irq(dev, irq, nirq))
326 				goto fail;
327 			nirq++;
328 			irq = irq->next;
329 		}
330 		while (dma) {
331 			if (!pnp_assign_dma(dev, dma, ndma))
332 				goto fail;
333 			ndma++;
334 			dma = dma->next;
335 		}
336 	}
337 
338 	if (depnum) {
339 		struct pnp_option *dep;
340 		int i;
341 		for (i=1,dep=dev->dependent; i<depnum; i++, dep=dep->next)
342 			if(!dep)
343 				goto fail;
344 		port =dep->port;
345 		mem = dep->mem;
346 		irq = dep->irq;
347 		dma = dep->dma;
348 		while (port) {
349 			if (!pnp_assign_port(dev, port, nport))
350 				goto fail;
351 			nport++;
352 			port = port->next;
353 		}
354 		while (mem) {
355 			if (!pnp_assign_mem(dev, mem, nmem))
356 				goto fail;
357 			nmem++;
358 			mem = mem->next;
359 		}
360 		while (irq) {
361 			if (!pnp_assign_irq(dev, irq, nirq))
362 				goto fail;
363 			nirq++;
364 			irq = irq->next;
365 		}
366 		while (dma) {
367 			if (!pnp_assign_dma(dev, dma, ndma))
368 				goto fail;
369 			ndma++;
370 			dma = dma->next;
371 		}
372 	} else if (dev->dependent)
373 		goto fail;
374 
375 	up(&pnp_res_mutex);
376 	return 1;
377 
378 fail:
379 	pnp_clean_resource_table(&dev->res);
380 	up(&pnp_res_mutex);
381 	return 0;
382 }
383 
384 /**
385  * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
386  * @dev: pointer to the desired device
387  * @res: pointer to the new resource config
388  * @mode: 0 or PNP_CONFIG_FORCE
389  *
390  * This function can be used by drivers that want to manually set thier resources.
391  */
392 int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, int mode)
393 {
394 	int i;
395 	struct pnp_resource_table * bak;
396 	if (!dev || !res)
397 		return -EINVAL;
398 	if (!pnp_can_configure(dev))
399 		return -ENODEV;
400 	bak = pnp_alloc(sizeof(struct pnp_resource_table));
401 	if (!bak)
402 		return -ENOMEM;
403 	*bak = dev->res;
404 
405 	down(&pnp_res_mutex);
406 	dev->res = *res;
407 	if (!(mode & PNP_CONFIG_FORCE)) {
408 		for (i = 0; i < PNP_MAX_PORT; i++) {
409 			if(!pnp_check_port(dev,i))
410 				goto fail;
411 		}
412 		for (i = 0; i < PNP_MAX_MEM; i++) {
413 			if(!pnp_check_mem(dev,i))
414 				goto fail;
415 		}
416 		for (i = 0; i < PNP_MAX_IRQ; i++) {
417 			if(!pnp_check_irq(dev,i))
418 				goto fail;
419 		}
420 		for (i = 0; i < PNP_MAX_DMA; i++) {
421 			if(!pnp_check_dma(dev,i))
422 				goto fail;
423 		}
424 	}
425 	up(&pnp_res_mutex);
426 
427 	kfree(bak);
428 	return 0;
429 
430 fail:
431 	dev->res = *bak;
432 	up(&pnp_res_mutex);
433 	kfree(bak);
434 	return -EINVAL;
435 }
436 
437 /**
438  * pnp_auto_config_dev - automatically assigns resources to a device
439  * @dev: pointer to the desired device
440  *
441  */
442 int pnp_auto_config_dev(struct pnp_dev *dev)
443 {
444 	struct pnp_option *dep;
445 	int i = 1;
446 
447 	if(!dev)
448 		return -EINVAL;
449 
450 	if(!pnp_can_configure(dev)) {
451 		pnp_info("Device %s does not support resource configuration.", dev->dev.bus_id);
452 		return -ENODEV;
453 	}
454 
455 	if (!dev->dependent) {
456 		if (pnp_assign_resources(dev, 0))
457 			return 0;
458 	} else {
459 		dep = dev->dependent;
460 		do {
461 			if (pnp_assign_resources(dev, i))
462 				return 0;
463 			dep = dep->next;
464 			i++;
465 		} while (dep);
466 	}
467 
468 	pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id);
469 	return -EBUSY;
470 }
471 
472 /**
473  * pnp_start_dev - low-level start of the PnP device
474  * @dev: pointer to the desired device
475  *
476  * assumes that resources have alread been allocated
477  */
478 
479 int pnp_start_dev(struct pnp_dev *dev)
480 {
481 	if (!pnp_can_write(dev)) {
482 		pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
483 		return -EINVAL;
484 	}
485 
486 	if (dev->protocol->set(dev, &dev->res)<0) {
487 		pnp_err("Failed to activate device %s.", dev->dev.bus_id);
488 		return -EIO;
489 	}
490 
491 	pnp_info("Device %s activated.", dev->dev.bus_id);
492 
493 	return 0;
494 }
495 
496 /**
497  * pnp_stop_dev - low-level disable of the PnP device
498  * @dev: pointer to the desired device
499  *
500  * does not free resources
501  */
502 
503 int pnp_stop_dev(struct pnp_dev *dev)
504 {
505 	if (!pnp_can_disable(dev)) {
506 		pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
507 		return -EINVAL;
508 	}
509 	if (dev->protocol->disable(dev)<0) {
510 		pnp_err("Failed to disable device %s.", dev->dev.bus_id);
511 		return -EIO;
512 	}
513 
514 	pnp_info("Device %s disabled.", dev->dev.bus_id);
515 
516 	return 0;
517 }
518 
519 /**
520  * pnp_activate_dev - activates a PnP device for use
521  * @dev: pointer to the desired device
522  *
523  * does not validate or set resources so be careful.
524  */
525 int pnp_activate_dev(struct pnp_dev *dev)
526 {
527 	int error;
528 
529 	if (!dev)
530 		return -EINVAL;
531 	if (dev->active) {
532 		return 0; /* the device is already active */
533 	}
534 
535 	/* ensure resources are allocated */
536 	if (pnp_auto_config_dev(dev))
537 		return -EBUSY;
538 
539 	error = pnp_start_dev(dev);
540 	if (error)
541 		return error;
542 
543 	dev->active = 1;
544 
545 	return 1;
546 }
547 
548 /**
549  * pnp_disable_dev - disables device
550  * @dev: pointer to the desired device
551  *
552  * inform the correct pnp protocol so that resources can be used by other devices
553  */
554 int pnp_disable_dev(struct pnp_dev *dev)
555 {
556 	int error;
557 
558         if (!dev)
559                 return -EINVAL;
560 	if (!dev->active) {
561 		return 0; /* the device is already disabled */
562 	}
563 
564 	error = pnp_stop_dev(dev);
565 	if (error)
566 		return error;
567 
568 	dev->active = 0;
569 
570 	/* release the resources so that other devices can use them */
571 	down(&pnp_res_mutex);
572 	pnp_clean_resource_table(&dev->res);
573 	up(&pnp_res_mutex);
574 
575 	return 1;
576 }
577 
578 /**
579  * pnp_resource_change - change one resource
580  * @resource: pointer to resource to be changed
581  * @start: start of region
582  * @size: size of region
583  *
584  */
585 void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size)
586 {
587 	if (resource == NULL)
588 		return;
589 	resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET);
590 	resource->start = start;
591 	resource->end = start + size - 1;
592 }
593 
594 
595 EXPORT_SYMBOL(pnp_manual_config_dev);
596 #if 0
597 EXPORT_SYMBOL(pnp_auto_config_dev);
598 #endif
599 EXPORT_SYMBOL(pnp_start_dev);
600 EXPORT_SYMBOL(pnp_stop_dev);
601 EXPORT_SYMBOL(pnp_activate_dev);
602 EXPORT_SYMBOL(pnp_disable_dev);
603 EXPORT_SYMBOL(pnp_resource_change);
604 EXPORT_SYMBOL(pnp_init_resource_table);
605