xref: /openbmc/linux/drivers/pnp/resource.c (revision 96de0e252cedffad61b3cb5e05662c591898e69a)
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 				return 0;
372 		}
373 	}
374 #endif
375 
376 	/* check if the resource is already in use, skip if the
377 	 * device is active because it itself may be in use */
378 	if (!dev->active) {
379 		if (request_irq(*irq, pnp_test_handler,
380 				IRQF_DISABLED | IRQF_PROBE_SHARED, "pnp", NULL))
381 			return 0;
382 		free_irq(*irq, NULL);
383 	}
384 
385 	/* check for conflicts with other pnp devices */
386 	pnp_for_each_dev(tdev) {
387 		if (tdev == dev)
388 			continue;
389 		for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
390 			if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
391 				if (cannot_compare
392 				    (tdev->res.irq_resource[tmp].flags))
393 					continue;
394 				if ((tdev->res.irq_resource[tmp].start == *irq))
395 					return 0;
396 			}
397 		}
398 	}
399 
400 	return 1;
401 }
402 
403 int pnp_check_dma(struct pnp_dev *dev, int idx)
404 {
405 #ifndef CONFIG_IA64
406 	int tmp;
407 	struct pnp_dev *tdev;
408 	resource_size_t *dma = &dev->res.dma_resource[idx].start;
409 
410 	/* if the resource doesn't exist, don't complain about it */
411 	if (cannot_compare(dev->res.dma_resource[idx].flags))
412 		return 1;
413 
414 	/* check if the resource is valid */
415 	if (*dma < 0 || *dma == 4 || *dma > 7)
416 		return 0;
417 
418 	/* check if the resource is reserved */
419 	for (tmp = 0; tmp < 8; tmp++) {
420 		if (pnp_reserve_dma[tmp] == *dma)
421 			return 0;
422 	}
423 
424 	/* check for internal conflicts */
425 	for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) {
426 		if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
427 			if (dev->res.dma_resource[tmp].start == *dma)
428 				return 0;
429 		}
430 	}
431 
432 	/* check if the resource is already in use, skip if the
433 	 * device is active because it itself may be in use */
434 	if (!dev->active) {
435 		if (request_dma(*dma, "pnp"))
436 			return 0;
437 		free_dma(*dma);
438 	}
439 
440 	/* check for conflicts with other pnp devices */
441 	pnp_for_each_dev(tdev) {
442 		if (tdev == dev)
443 			continue;
444 		for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
445 			if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
446 				if (cannot_compare
447 				    (tdev->res.dma_resource[tmp].flags))
448 					continue;
449 				if ((tdev->res.dma_resource[tmp].start == *dma))
450 					return 0;
451 			}
452 		}
453 	}
454 
455 	return 1;
456 #else
457 	/* IA64 does not have legacy DMA */
458 	return 0;
459 #endif
460 }
461 
462 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
463 static int __init pnp_setup_reserve_irq(char *str)
464 {
465 	int i;
466 
467 	for (i = 0; i < 16; i++)
468 		if (get_option(&str, &pnp_reserve_irq[i]) != 2)
469 			break;
470 	return 1;
471 }
472 
473 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq);
474 
475 /* format is: pnp_reserve_dma=dma1[,dma2] .... */
476 static int __init pnp_setup_reserve_dma(char *str)
477 {
478 	int i;
479 
480 	for (i = 0; i < 8; i++)
481 		if (get_option(&str, &pnp_reserve_dma[i]) != 2)
482 			break;
483 	return 1;
484 }
485 
486 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma);
487 
488 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
489 static int __init pnp_setup_reserve_io(char *str)
490 {
491 	int i;
492 
493 	for (i = 0; i < 16; i++)
494 		if (get_option(&str, &pnp_reserve_io[i]) != 2)
495 			break;
496 	return 1;
497 }
498 
499 __setup("pnp_reserve_io=", pnp_setup_reserve_io);
500 
501 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
502 static int __init pnp_setup_reserve_mem(char *str)
503 {
504 	int i;
505 
506 	for (i = 0; i < 16; i++)
507 		if (get_option(&str, &pnp_reserve_mem[i]) != 2)
508 			break;
509 	return 1;
510 }
511 
512 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem);
513