interrupt.h revision 310250
1216115Slstewart/*- 2216115Slstewart * Copyright (c) 2010 Isilon Systems, Inc. 3216115Slstewart * Copyright (c) 2010 iX Systems, Inc. 4216115Slstewart * Copyright (c) 2010 Panasas, Inc. 5216115Slstewart * Copyright (c) 2013-2015 Mellanox Technologies, Ltd. 6216115Slstewart * All rights reserved. 7216115Slstewart * 8216115Slstewart * Redistribution and use in source and binary forms, with or without 9220560Slstewart * modification, are permitted provided that the following conditions 10220560Slstewart * are met: 11220560Slstewart * 1. Redistributions of source code must retain the above copyright 12216115Slstewart * notice unmodified, this list of conditions, and the following 13216115Slstewart * disclaimer. 14216115Slstewart * 2. Redistributions in binary form must reproduce the above copyright 15216115Slstewart * notice, this list of conditions and the following disclaimer in the 16216115Slstewart * documentation and/or other materials provided with the distribution. 17216115Slstewart * 18216115Slstewart * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19216115Slstewart * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20216115Slstewart * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21216115Slstewart * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22216115Slstewart * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23216115Slstewart * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24216115Slstewart * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25216115Slstewart * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26216115Slstewart * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27216115Slstewart * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28216115Slstewart * 29216115Slstewart * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/linux/interrupt.h 310250 2016-12-19 09:47:34Z hselasky $ 30216115Slstewart */ 31216115Slstewart#ifndef _LINUX_INTERRUPT_H_ 32216115Slstewart#define _LINUX_INTERRUPT_H_ 33216115Slstewart 34216115Slstewart#include <linux/device.h> 35216115Slstewart#include <linux/pci.h> 36216115Slstewart 37216115Slstewart#include <sys/bus.h> 38216115Slstewart#include <sys/rman.h> 39216115Slstewart 40216115Slstewarttypedef irqreturn_t (*irq_handler_t)(int, void *); 41216115Slstewart 42216115Slstewart#define IRQ_RETVAL(x) ((x) != IRQ_NONE) 43220560Slstewart 44220560Slstewart#define IRQF_SHARED RF_SHAREABLE 45220560Slstewart 46220560Slstewartstruct irq_ent { 47216115Slstewart struct list_head links; 48216115Slstewart struct device *dev; 49216115Slstewart struct resource *res; 50216115Slstewart void *arg; 51216115Slstewart irqreturn_t (*handler)(int, void *); 52216115Slstewart void *tag; 53216115Slstewart unsigned int irq; 54216115Slstewart}; 55216115Slstewart 56216115Slstewartstatic inline int 57216115Slstewartlinux_irq_rid(struct device *dev, unsigned int irq) 58216115Slstewart{ 59216115Slstewart if (irq == dev->irq) 60216115Slstewart return (0); 61216115Slstewart return irq - dev->msix + 1; 62216115Slstewart} 63216115Slstewart 64216115Slstewartextern void linux_irq_handler(void *); 65216115Slstewart 66216115Slstewartstatic inline struct irq_ent * 67216115Slstewartlinux_irq_ent(struct device *dev, unsigned int irq) 68216115Slstewart{ 69216115Slstewart struct irq_ent *irqe; 70216115Slstewart 71216115Slstewart list_for_each_entry(irqe, &dev->irqents, links) 72216115Slstewart if (irqe->irq == irq) 73216115Slstewart return (irqe); 74216115Slstewart 75216115Slstewart return (NULL); 76216115Slstewart} 77216115Slstewart 78216115Slstewartstatic inline int 79216115Slstewartrequest_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, 80216115Slstewart const char *name, void *arg) 81216115Slstewart{ 82216115Slstewart struct resource *res; 83216115Slstewart struct irq_ent *irqe; 84216115Slstewart struct device *dev; 85216115Slstewart int error; 86216115Slstewart int rid; 87216115Slstewart 88216115Slstewart dev = linux_pci_find_irq_dev(irq); 89216115Slstewart if (dev == NULL) 90216115Slstewart return -ENXIO; 91216115Slstewart rid = linux_irq_rid(dev, irq); 92216115Slstewart res = bus_alloc_resource_any(dev->bsddev, SYS_RES_IRQ, &rid, 93216115Slstewart flags | RF_ACTIVE); 94216115Slstewart if (res == NULL) 95216115Slstewart return (-ENXIO); 96216115Slstewart irqe = kmalloc(sizeof(*irqe), GFP_KERNEL); 97216115Slstewart irqe->dev = dev; 98216115Slstewart irqe->res = res; 99216115Slstewart irqe->arg = arg; 100216115Slstewart irqe->handler = handler; 101216115Slstewart irqe->irq = irq; 102216115Slstewart error = bus_setup_intr(dev->bsddev, res, INTR_TYPE_NET | INTR_MPSAFE, 103216115Slstewart NULL, linux_irq_handler, irqe, &irqe->tag); 104216115Slstewart if (error) { 105216115Slstewart bus_release_resource(dev->bsddev, SYS_RES_IRQ, rid, irqe->res); 106216115Slstewart kfree(irqe); 107216115Slstewart return (-error); 108216115Slstewart } 109216115Slstewart list_add(&irqe->links, &dev->irqents); 110216115Slstewart 111216115Slstewart return 0; 112216115Slstewart} 113216115Slstewart 114216115Slstewartstatic inline int 115216115Slstewartbind_irq_to_cpu(unsigned int irq, int cpu_id) 116216115Slstewart{ 117216115Slstewart struct irq_ent *irqe; 118216115Slstewart struct device *dev; 119216115Slstewart 120216115Slstewart dev = linux_pci_find_irq_dev(irq); 121216115Slstewart if (dev == NULL) 122216115Slstewart return (-ENOENT); 123216115Slstewart 124216115Slstewart irqe = linux_irq_ent(dev, irq); 125216115Slstewart if (irqe == NULL) 126216115Slstewart return (-ENOENT); 127216115Slstewart 128216115Slstewart return (-bus_bind_intr(dev->bsddev, irqe->res, cpu_id)); 129216115Slstewart} 130216115Slstewart 131216115Slstewartstatic inline void 132216115Slstewartfree_irq(unsigned int irq, void *device) 133216115Slstewart{ 134216115Slstewart struct irq_ent *irqe; 135216115Slstewart struct device *dev; 136216115Slstewart int rid; 137216115Slstewart 138216115Slstewart dev = linux_pci_find_irq_dev(irq); 139216115Slstewart if (dev == NULL) 140216115Slstewart return; 141216115Slstewart rid = linux_irq_rid(dev, irq); 142216115Slstewart irqe = linux_irq_ent(dev, irq); 143216115Slstewart if (irqe == NULL) 144216115Slstewart return; 145216115Slstewart bus_teardown_intr(dev->bsddev, irqe->res, irqe->tag); 146216115Slstewart bus_release_resource(dev->bsddev, SYS_RES_IRQ, rid, irqe->res); 147216115Slstewart list_del(&irqe->links); 148216115Slstewart kfree(irqe); 149216115Slstewart} 150216115Slstewart 151216115Slstewart#endif /* _LINUX_INTERRUPT_H_ */ 152216115Slstewart