aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2007-02-11 10:41:31 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 14:18:07 -0500
commit5ea8176994003483a18c8fed580901e2125f8a83 (patch)
tree0712ec9cd3384fbd897eb454ce9c0f907289ab51 /kernel/irq
parent2835fdfa4a7f1400986d76d054237809a9392406 (diff)
[PATCH] sort the devres mess out
* Split the implementation-agnostic stuff in separate files. * Make sure that targets using non-default request_irq() pull kernel/irq/devres.o * Introduce new symbols (HAS_IOPORT and HAS_IOMEM) defaulting to positive; allow architectures to turn them off (we needed these symbols anyway for dependencies of quite a few drivers). * protect the ioport-related parts of lib/devres.o with CONFIG_HAS_IOPORT. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/Makefile2
-rw-r--r--kernel/irq/devres.c88
-rw-r--r--kernel/irq/manage.c86
3 files changed, 89 insertions, 87 deletions
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 1dab0ac3f79..681c52dbfe2 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -1,5 +1,5 @@
1 1
2obj-y := handle.o manage.o spurious.o resend.o chip.o 2obj-y := handle.o manage.o spurious.o resend.o chip.o devres.o
3obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o 3obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
4obj-$(CONFIG_PROC_FS) += proc.o 4obj-$(CONFIG_PROC_FS) += proc.o
5obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o 5obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c
new file mode 100644
index 00000000000..85a430da0fb
--- /dev/null
+++ b/kernel/irq/devres.c
@@ -0,0 +1,88 @@
1#include <linux/module.h>
2#include <linux/interrupt.h>
3
4/*
5 * Device resource management aware IRQ request/free implementation.
6 */
7struct irq_devres {
8 unsigned int irq;
9 void *dev_id;
10};
11
12static void devm_irq_release(struct device *dev, void *res)
13{
14 struct irq_devres *this = res;
15
16 free_irq(this->irq, this->dev_id);
17}
18
19static int devm_irq_match(struct device *dev, void *res, void *data)
20{
21 struct irq_devres *this = res, *match = data;
22
23 return this->irq == match->irq && this->dev_id == match->dev_id;
24}
25
26/**
27 * devm_request_irq - allocate an interrupt line for a managed device
28 * @dev: device to request interrupt for
29 * @irq: Interrupt line to allocate
30 * @handler: Function to be called when the IRQ occurs
31 * @irqflags: Interrupt type flags
32 * @devname: An ascii name for the claiming device
33 * @dev_id: A cookie passed back to the handler function
34 *
35 * Except for the extra @dev argument, this function takes the
36 * same arguments and performs the same function as
37 * request_irq(). IRQs requested with this function will be
38 * automatically freed on driver detach.
39 *
40 * If an IRQ allocated with this function needs to be freed
41 * separately, dev_free_irq() must be used.
42 */
43int devm_request_irq(struct device *dev, unsigned int irq,
44 irq_handler_t handler, unsigned long irqflags,
45 const char *devname, void *dev_id)
46{
47 struct irq_devres *dr;
48 int rc;
49
50 dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
51 GFP_KERNEL);
52 if (!dr)
53 return -ENOMEM;
54
55 rc = request_irq(irq, handler, irqflags, devname, dev_id);
56 if (rc) {
57 kfree(dr);
58 return rc;
59 }
60
61 dr->irq = irq;
62 dr->dev_id = dev_id;
63 devres_add(dev, dr);
64
65 return 0;
66}
67EXPORT_SYMBOL(devm_request_irq);
68
69/**
70 * devm_free_irq - free an interrupt
71 * @dev: device to free interrupt for
72 * @irq: Interrupt line to free
73 * @dev_id: Device identity to free
74 *
75 * Except for the extra @dev argument, this function takes the
76 * same arguments and performs the same function as free_irq().
77 * This function instead of free_irq() should be used to manually
78 * free IRQs allocated with dev_request_irq().
79 */
80void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
81{
82 struct irq_devres match_data = { irq, dev_id };
83
84 free_irq(irq, dev_id);
85 WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
86 &match_data));
87}
88EXPORT_SYMBOL(devm_free_irq);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index c4b7ed1cebf..8b961adc3bd 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -482,89 +482,3 @@ int request_irq(unsigned int irq, irq_handler_t handler,
482 return retval; 482 return retval;
483} 483}
484EXPORT_SYMBOL(request_irq); 484EXPORT_SYMBOL(request_irq);
485
486/*
487 * Device resource management aware IRQ request/free implementation.
488 */
489struct irq_devres {
490 unsigned int irq;
491 void *dev_id;
492};
493
494static void devm_irq_release(struct device *dev, void *res)
495{
496 struct irq_devres *this = res;
497
498 free_irq(this->irq, this->dev_id);
499}
500
501static int devm_irq_match(struct device *dev, void *res, void *data)
502{
503 struct irq_devres *this = res, *match = data;
504
505 return this->irq == match->irq && this->dev_id == match->dev_id;
506}
507
508/**
509 * devm_request_irq - allocate an interrupt line for a managed device
510 * @dev: device to request interrupt for
511 * @irq: Interrupt line to allocate
512 * @handler: Function to be called when the IRQ occurs
513 * @irqflags: Interrupt type flags
514 * @devname: An ascii name for the claiming device
515 * @dev_id: A cookie passed back to the handler function
516 *
517 * Except for the extra @dev argument, this function takes the
518 * same arguments and performs the same function as
519 * request_irq(). IRQs requested with this function will be
520 * automatically freed on driver detach.
521 *
522 * If an IRQ allocated with this function needs to be freed
523 * separately, dev_free_irq() must be used.
524 */
525int devm_request_irq(struct device *dev, unsigned int irq,
526 irq_handler_t handler, unsigned long irqflags,
527 const char *devname, void *dev_id)
528{
529 struct irq_devres *dr;
530 int rc;
531
532 dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
533 GFP_KERNEL);
534 if (!dr)
535 return -ENOMEM;
536
537 rc = request_irq(irq, handler, irqflags, devname, dev_id);
538 if (rc) {
539 kfree(dr);
540 return rc;
541 }
542
543 dr->irq = irq;
544 dr->dev_id = dev_id;
545 devres_add(dev, dr);
546
547 return 0;
548}
549EXPORT_SYMBOL(devm_request_irq);
550
551/**
552 * devm_free_irq - free an interrupt
553 * @dev: device to free interrupt for
554 * @irq: Interrupt line to free
555 * @dev_id: Device identity to free
556 *
557 * Except for the extra @dev argument, this function takes the
558 * same arguments and performs the same function as free_irq().
559 * This function instead of free_irq() should be used to manually
560 * free IRQs allocated with dev_request_irq().
561 */
562void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
563{
564 struct irq_devres match_data = { irq, dev_id };
565
566 free_irq(irq, dev_id);
567 WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
568 &match_data));
569}
570EXPORT_SYMBOL(devm_free_irq);