xref: /openbmc/linux/drivers/pnp/resource.c (revision f42b3800)
1 /*
2  * resource.c - Contains functions for registering and analyzing resource information
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/module.h>
9 #include <linux/errno.h>
10 #include <linux/interrupt.h>
11 #include <linux/kernel.h>
12 #include <asm/io.h>
13 #include <asm/dma.h>
14 #include <asm/irq.h>
15 #include <linux/pci.h>
16 #include <linux/ioport.h>
17 #include <linux/init.h>
18 
19 #include <linux/pnp.h>
20 #include "base.h"
21 
22 static int pnp_reserve_irq[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some IRQ */
23 static int pnp_reserve_dma[8] = {[0 ... 7] = -1 };	/* reserve (don't use) some DMA */
24 static int pnp_reserve_io[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some I/O region */
25 static int pnp_reserve_mem[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some memory region */
26 
27 /*
28  * option registration
29  */
30 
31 static struct pnp_option *pnp_build_option(int priority)
32 {
33 	struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option));
34 
35 	if (!option)
36 		return NULL;
37 
38 	option->priority = priority & 0xff;
39 	/* make sure the priority is valid */
40 	if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL)
41 		option->priority = PNP_RES_PRIORITY_INVALID;
42 
43 	return option;
44 }
45 
46 struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
47 {
48 	struct pnp_option *option;
49 
50 	option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED);
51 
52 	/* this should never happen but if it does we'll try to continue */
53 	if (dev->independent)
54 		dev_err(&dev->dev, "independent resource already registered\n");
55 	dev->independent = option;
56 	return option;
57 }
58 
59 struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
60 						 int priority)
61 {
62 	struct pnp_option *option;
63 
64 	option = pnp_build_option(priority);
65 
66 	if (dev->dependent) {
67 		struct pnp_option *parent = dev->dependent;
68 		while (parent->next)
69 			parent = parent->next;
70 		parent->next = option;
71 	} else
72 		dev->dependent = option;
73 	return option;
74 }
75 
76 int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data)
77 {
78 	struct pnp_irq *ptr;
79 
80 	ptr = option->irq;
81 	while (ptr && ptr->next)
82 		ptr = ptr->next;
83 	if (ptr)
84 		ptr->next = data;
85 	else
86 		option->irq = data;
87 
88 #ifdef CONFIG_PCI
89 	{
90 		int i;
91 
92 		for (i = 0; i < 16; i++)
93 			if (test_bit(i, data->map))
94 				pcibios_penalize_isa_irq(i, 0);
95 	}
96 #endif
97 	return 0;
98 }
99 
100 int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data)
101 {
102 	struct pnp_dma *ptr;
103 
104 	ptr = option->dma;
105 	while (ptr && ptr->next)
106 		ptr = ptr->next;
107 	if (ptr)
108 		ptr->next = data;
109 	else
110 		option->dma = data;
111 
112 	return 0;
113 }
114 
115 int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data)
116 {
117 	struct pnp_port *ptr;
118 
119 	ptr = option->port;
120 	while (ptr && ptr->next)
121 		ptr = ptr->next;
122 	if (ptr)
123 		ptr->next = data;
124 	else
125 		option->port = data;
126 
127 	return 0;
128 }
129 
130 int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data)
131 {
132 	struct pnp_mem *ptr;
133 
134 	ptr = option->mem;
135 	while (ptr && ptr->next)
136 		ptr = ptr->next;
137 	if (ptr)
138 		ptr->next = data;
139 	else
140 		option->mem = data;
141 	return 0;
142 }
143 
144 static void pnp_free_port(struct pnp_port *port)
145 {
146 	struct pnp_port *next;
147 
148 	while (port) {
149 		next = port->next;
150 		kfree(port);
151 		port = next;
152 	}
153 }
154 
155 static void pnp_free_irq(struct pnp_irq *irq)
156 {
157 	struct pnp_irq *next;
158 
159 	while (irq) {
160 		next = irq->next;
161 		kfree(irq);
162 		irq = next;
163 	}
164 }
165 
166 static void pnp_free_dma(struct pnp_dma *dma)
167 {
168 	struct pnp_dma *next;
169 
170 	while (dma) {
171 		next = dma->next;
172 		kfree(dma);
173 		dma = next;
174 	}
175 }
176 
177 static void pnp_free_mem(struct pnp_mem *mem)
178 {
179 	struct pnp_mem *next;
180 
181 	while (mem) {
182 		next = mem->next;
183 		kfree(mem);
184 		mem = next;
185 	}
186 }
187 
188 void pnp_free_option(struct pnp_option *option)
189 {
190 	struct pnp_option *next;
191 
192 	while (option) {
193 		next = option->next;
194 		pnp_free_port(option->port);
195 		pnp_free_irq(option->irq);
196 		pnp_free_dma(option->dma);
197 		pnp_free_mem(option->mem);
198 		kfree(option);
199 		option = next;
200 	}
201 }
202 
203 /*
204  * resource validity checking
205  */
206 
207 #define length(start, end) (*(end) - *(start) + 1)
208 
209 /* Two ranges conflict if one doesn't end before the other starts */
210 #define ranged_conflict(starta, enda, startb, endb) \
211 	!((*(enda) < *(startb)) || (*(endb) < *(starta)))
212 
213 #define cannot_compare(flags) \
214 ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
215 
216 int pnp_check_port(struct pnp_dev *dev, int idx)
217 {
218 	int tmp;
219 	struct pnp_dev *tdev;
220 	resource_size_t *port, *end, *tport, *tend;
221 
222 	port = &dev->res.port_resource[idx].start;
223 	end = &dev->res.port_resource[idx].end;
224 
225 	/* if the resource doesn't exist, don't complain about it */
226 	if (cannot_compare(dev->res.port_resource[idx].flags))
227 		return 1;
228 
229 	/* check if the resource is already in use, skip if the
230 	 * device is active because it itself may be in use */
231 	if (!dev->active) {
232 		if (__check_region(&ioport_resource, *port, length(port, end)))
233 			return 0;
234 	}
235 
236 	/* check if the resource is reserved */
237 	for (tmp = 0; tmp < 8; tmp++) {
238 		int rport = pnp_reserve_io[tmp << 1];
239 		int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1;
240 		if (ranged_conflict(port, end, &rport, &rend))
241 			return 0;
242 	}
243 
244 	/* check for internal conflicts */
245 	for (tmp = 0; tmp < PNP_MAX_PORT && tmp != idx; tmp++) {
246 		if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) {
247 			tport = &dev->res.port_resource[tmp].start;
248 			tend = &dev->res.port_resource[tmp].end;
249 			if (ranged_conflict(port, end, tport, tend))
250 				return 0;
251 		}
252 	}
253 
254 	/* check for conflicts with other pnp devices */
255 	pnp_for_each_dev(tdev) {
256 		if (tdev == dev)
257 			continue;
258 		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
259 			if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
260 				if (cannot_compare
261 				    (tdev->res.port_resource[tmp].flags))
262 					continue;
263 				tport = &tdev->res.port_resource[tmp].start;
264 				tend = &tdev->res.port_resource[tmp].end;
265 				if (ranged_conflict(port, end, tport, tend))
266 					return 0;
267 			}
268 		}
269 	}
270 
271 	return 1;
272 }
273 
274 int pnp_check_mem(struct pnp_dev *dev, int idx)
275 {
276 	int tmp;
277 	struct pnp_dev *tdev;
278 	resource_size_t *addr, *end, *taddr, *tend;
279 
280 	addr = &dev->res.mem_resource[idx].start;
281 	end = &dev->res.mem_resource[idx].end;
282 
283 	/* if the resource doesn't exist, don't complain about it */
284 	if (cannot_compare(dev->res.mem_resource[idx].flags))
285 		return 1;
286 
287 	/* check if the resource is already in use, skip if the
288 	 * device is active because it itself may be in use */
289 	if (!dev->active) {
290 		if (check_mem_region(*addr, length(addr, end)))
291 			return 0;
292 	}
293 
294 	/* check if the resource is reserved */
295 	for (tmp = 0; tmp < 8; tmp++) {
296 		int raddr = pnp_reserve_mem[tmp << 1];
297 		int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1;
298 		if (ranged_conflict(addr, end, &raddr, &rend))
299 			return 0;
300 	}
301 
302 	/* check for internal conflicts */
303 	for (tmp = 0; tmp < PNP_MAX_MEM && tmp != idx; tmp++) {
304 		if (dev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
305 			taddr = &dev->res.mem_resource[tmp].start;
306 			tend = &dev->res.mem_resource[tmp].end;
307 			if (ranged_conflict(addr, end, taddr, tend))
308 				return 0;
309 		}
310 	}
311 
312 	/* check for conflicts with other pnp devices */
313 	pnp_for_each_dev(tdev) {
314 		if (tdev == dev)
315 			continue;
316 		for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
317 			if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
318 				if (cannot_compare
319 				    (tdev->res.mem_resource[tmp].flags))
320 					continue;
321 				taddr = &tdev->res.mem_resource[tmp].start;
322 				tend = &tdev->res.mem_resource[tmp].end;
323 				if (ranged_conflict(addr, end, taddr, tend))
324 					return 0;
325 			}
326 		}
327 	}
328 
329 	return 1;
330 }
331 
332 static irqreturn_t pnp_test_handler(int irq, void *dev_id)
333 {
334 	return IRQ_HANDLED;
335 }
336 
337 int pnp_check_irq(struct pnp_dev *dev, int idx)
338 {
339 	int tmp;
340 	struct pnp_dev *tdev;
341 	resource_size_t *irq = &dev->res.irq_resource[idx].start;
342 
343 	/* if the resource doesn't exist, don't complain about it */
344 	if (cannot_compare(dev->res.irq_resource[idx].flags))
345 		return 1;
346 
347 	/* check if the resource is valid */
348 	if (*irq < 0 || *irq > 15)
349 		return 0;
350 
351 	/* check if the resource is reserved */
352 	for (tmp = 0; tmp < 16; tmp++) {
353 		if (pnp_reserve_irq[tmp] == *irq)
354 			return 0;
355 	}
356 
357 	/* check for internal conflicts */
358 	for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) {
359 		if (dev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
360 			if (dev->res.irq_resource[tmp].start == *irq)
361 				return 0;
362 		}
363 	}
364 
365 #ifdef CONFIG_PCI
366 	/* check if the resource is being used by a pci device */
367 	{
368 		struct pci_dev *pci = NULL;
369 		for_each_pci_dev(pci) {
370 			if (pci->irq == *irq) {
371 				pci_dev_put(pci);
372 				return 0;
373 			}
374 		}
375 	}
376 #endif
377 
378 	/* check if the resource is already in use, skip if the
379 	 * device is active because it itself may be in use */
380 	if (!dev->active) {
381 		if (request_irq(*irq, pnp_test_handler,
382 				IRQF_DISABLED | IRQF_PROBE_SHARED, "pnp", NULL))
383 			return 0;
384 		free_irq(*irq, NULL);
385 	}
386 
387 	/* check for conflicts with other pnp devices */
388 	pnp_for_each_dev(tdev) {
389 		if (tdev == dev)
390 			continue;
391 		for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
392 			if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
393 				if (cannot_compare
394 				    (tdev->res.irq_resource[tmp].flags))
395 					continue;
396 				if ((tdev->res.irq_resource[tmp].start == *irq))
397 					return 0;
398 			}
399 		}
400 	}
401 
402 	return 1;
403 }
404 
405 int pnp_check_dma(struct pnp_dev *dev, int idx)
406 {
407 #ifndef CONFIG_IA64
408 	int tmp;
409 	struct pnp_dev *tdev;
410 	resource_size_t *dma = &dev->res.dma_resource[idx].start;
411 
412 	/* if the resource doesn't exist, don't complain about it */
413 	if (cannot_compare(dev->res.dma_resource[idx].flags))
414 		return 1;
415 
416 	/* check if the resource is valid */
417 	if (*dma < 0 || *dma == 4 || *dma > 7)
418 		return 0;
419 
420 	/* check if the resource is reserved */
421 	for (tmp = 0; tmp < 8; tmp++) {
422 		if (pnp_reserve_dma[tmp] == *dma)
423 			return 0;
424 	}
425 
426 	/* check for internal conflicts */
427 	for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) {
428 		if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
429 			if (dev->res.dma_resource[tmp].start == *dma)
430 				return 0;
431 		}
432 	}
433 
434 	/* check if the resource is already in use, skip if the
435 	 * device is active because it itself may be in use */
436 	if (!dev->active) {
437 		if (request_dma(*dma, "pnp"))
438 			return 0;
439 		free_dma(*dma);
440 	}
441 
442 	/* check for conflicts with other pnp devices */
443 	pnp_for_each_dev(tdev) {
444 		if (tdev == dev)
445 			continue;
446 		for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
447 			if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
448 				if (cannot_compare
449 				    (tdev->res.dma_resource[tmp].flags))
450 					continue;
451 				if ((tdev->res.dma_resource[tmp].start == *dma))
452 					return 0;
453 			}
454 		}
455 	}
456 
457 	return 1;
458 #else
459 	/* IA64 does not have legacy DMA */
460 	return 0;
461 #endif
462 }
463 
464 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
465 static int __init pnp_setup_reserve_irq(char *str)
466 {
467 	int i;
468 
469 	for (i = 0; i < 16; i++)
470 		if (get_option(&str, &pnp_reserve_irq[i]) != 2)
471 			break;
472 	return 1;
473 }
474 
475 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq);
476 
477 /* format is: pnp_reserve_dma=dma1[,dma2] .... */
478 static int __init pnp_setup_reserve_dma(char *str)
479 {
480 	int i;
481 
482 	for (i = 0; i < 8; i++)
483 		if (get_option(&str, &pnp_reserve_dma[i]) != 2)
484 			break;
485 	return 1;
486 }
487 
488 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma);
489 
490 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
491 static int __init pnp_setup_reserve_io(char *str)
492 {
493 	int i;
494 
495 	for (i = 0; i < 16; i++)
496 		if (get_option(&str, &pnp_reserve_io[i]) != 2)
497 			break;
498 	return 1;
499 }
500 
501 __setup("pnp_reserve_io=", pnp_setup_reserve_io);
502 
503 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
504 static int __init pnp_setup_reserve_mem(char *str)
505 {
506 	int i;
507 
508 	for (i = 0; i < 16; i++)
509 		if (get_option(&str, &pnp_reserve_mem[i]) != 2)
510 			break;
511 	return 1;
512 }
513 
514 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem);
515