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