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