]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/ofed/include/linux/interrupt.h
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / ofed / include / linux / interrupt.h
1 /*-
2  * Copyright (c) 2010 Isilon Systems, Inc.
3  * Copyright (c) 2010 iX Systems, Inc.
4  * Copyright (c) 2010 Panasas, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #ifndef _LINUX_INTERRUPT_H_
30 #define _LINUX_INTERRUPT_H_
31
32 #include <linux/device.h>
33 #include <linux/pci.h>
34
35 #include <sys/bus.h>
36 #include <sys/rman.h>
37
38 typedef irqreturn_t     (*irq_handler_t)(int, void *);
39
40 #define IRQ_RETVAL(x)   ((x) != IRQ_NONE)
41
42 #define IRQF_SHARED     RF_SHAREABLE
43
44 struct irq_ent {
45         struct list_head        links;
46         struct device   *dev;
47         struct resource *res;
48         void            *arg;
49         irqreturn_t     (*handler)(int, void *);
50         void            *tag;
51         int              irq;
52 };
53
54 static inline int
55 _irq_rid(struct device *dev, int irq)
56 {
57         if (irq == dev->irq)
58                 return (0);
59         return irq - dev->msix + 1;
60 }
61
62 static void
63 _irq_handler(void *ent)
64 {
65         struct irq_ent *irqe;
66
67         irqe = ent;
68         irqe->handler(irqe->irq, irqe->arg);
69 }
70
71 static inline struct irq_ent *
72 _irq_ent(struct device *dev, int irq)
73 {
74         struct irq_ent *irqe;
75
76         list_for_each_entry(irqe, &dev->irqents, links)
77                 if (irqe->irq == irq)
78                         return (irqe);
79
80         return (NULL);
81 }
82
83 static inline int
84 request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
85     const char *name, void *arg)
86 {
87         struct resource *res;
88         struct irq_ent *irqe;
89         struct device *dev;
90         int error;
91         int rid;
92
93         dev = _pci_find_irq_dev(irq);
94         if (dev == NULL)
95                 return -ENXIO;
96         rid = _irq_rid(dev, irq);
97         res = bus_alloc_resource_any(dev->bsddev, SYS_RES_IRQ, &rid,
98             flags | RF_ACTIVE);
99         if (res == NULL)
100                 return (-ENXIO);
101         irqe = kmalloc(sizeof(*irqe), GFP_KERNEL);
102         irqe->dev = dev;
103         irqe->res = res;
104         irqe->arg = arg;
105         irqe->handler = handler;
106         irqe->irq = irq;
107         error = bus_setup_intr(dev->bsddev, res, INTR_TYPE_NET | INTR_MPSAFE,
108             NULL, _irq_handler, irqe, &irqe->tag);
109         if (error) {
110                 bus_release_resource(dev->bsddev, SYS_RES_IRQ, rid, irqe->res);
111                 kfree(irqe);
112                 return (-error);
113         }
114         list_add(&irqe->links, &dev->irqents);
115
116         return 0;
117 }
118
119 static inline void
120 free_irq(unsigned int irq, void *device)
121 {
122         struct irq_ent *irqe;
123         struct device *dev;
124         int rid;
125
126         dev = _pci_find_irq_dev(irq);
127         if (dev == NULL)
128                 return;
129         rid = _irq_rid(dev, irq);
130         irqe = _irq_ent(dev, irq);
131         if (irqe == NULL)
132                 return;
133         bus_teardown_intr(dev->bsddev, irqe->res, irqe->tag);
134         bus_release_resource(dev->bsddev, SYS_RES_IRQ, rid, irqe->res);
135         list_del(&irqe->links);
136         kfree(irqe);
137 }
138
139 #endif  /* _LINUX_INTERRUPT_H_ */