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