diff options
-rw-r--r-- | lib/Makefile.am | 3 | ||||
-rw-r--r-- | lib/intr.c | 80 | ||||
-rw-r--r-- | lib/main.c | 75 | ||||
-rw-r--r-- | lib/priv.h | 23 |
4 files changed, 107 insertions, 74 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 67e67c6f8..352dd9f31 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -4,4 +4,5 @@ libpciaccessos_la_CPPFLAGS = -I${top_srcdir}/nvkm/include \ -I${top_srcdir}/nvkm libpciaccessos_la_CFLAGS = @PCIACCESS_CFLAGS@ libpciaccessos_la_LDFLAGS = @PCIACCESS_LIBS@ -lpthread -libpciaccessos_la_SOURCES = main.c +libpciaccessos_la_SOURCES = intr.c \ + main.c diff --git a/lib/intr.c b/lib/intr.c new file mode 100644 index 000000000..5563c372b --- /dev/null +++ b/lib/intr.c @@ -0,0 +1,80 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <core/device.h> +#include <core/client.h> +#include "priv.h" + +pthread_t os_intr_thread; +struct os_intr { + struct list_head head; + irq_handler_t handler; + int irq; + void *dev; +}; +static LIST_HEAD(os_intr_list); + +int +os_intr_init(unsigned int irq, irq_handler_t handler, unsigned long flags, + const char *name, void *dev) +{ + struct os_intr *intr = malloc(sizeof(*intr)); + if (!intr) + return -ENOMEM; + intr->handler = handler; + intr->irq = irq; + intr->dev = dev; + list_add(&intr->head, &os_intr_list); + return 0; +} + +void +os_intr_free(unsigned int irq, void *dev) +{ + struct os_intr *intr; + + list_for_each_entry(intr, &os_intr_list, head) { + if (intr->irq == irq && intr->dev == dev) { + list_del(&intr->head); + free(intr); + break; + } + } +} + +void * +os_intr(void *arg) +{ + struct os_intr *intr; + + while (1) { + list_for_each_entry(intr, &os_intr_list, head) { + intr->handler(intr->irq, intr->dev); + } + + usleep(10000); + } + + return NULL; +} diff --git a/lib/main.c b/lib/main.c index afec06d45..ed1b34d2b 100644 --- a/lib/main.c +++ b/lib/main.c @@ -23,7 +23,6 @@ */ #include <core/os.h> -#include <signal.h> #include <core/object.h> #include <core/client.h> @@ -34,81 +33,13 @@ #include <engine/device.h> #include <subdev/mc.h> -struct os_device { - struct nouveau_device base; - struct list_head head; - char *name; - char *cfg; - char *dbg; -}; - -struct os_client { - struct nouveau_client base; - struct list_head head; -}; +#include "priv.h" static LIST_HEAD(os_device_list); static LIST_HEAD(os_client_list); static int os_client_id = 0; /****************************************************************************** - * "interrupt" handling - *****************************************************************************/ -#define INTR_FREQ 10000 - -struct os_intr { - struct list_head head; - irq_handler_t handler; - int irq; - void *dev; -}; -static LIST_HEAD(os_intr_list); - -int -os_intr_init(unsigned int irq, irq_handler_t handler, unsigned long flags, - const char *name, void *dev) -{ - struct os_intr *intr = malloc(sizeof(*intr)); - if (!intr) - return -ENOMEM; - intr->handler = handler; - intr->irq = irq; - intr->dev = dev; - list_add(&intr->head, &os_intr_list); - return 0; -} - -void -os_intr_free(unsigned int irq, void *dev) -{ - struct os_intr *intr; - - list_for_each_entry(intr, &os_intr_list, head) { - if (intr->irq == irq && intr->dev == dev) { - list_del(&intr->head); - free(intr); - break; - } - } -} - -static void -os_intr(int signal) -{ - struct os_intr *intr; - - list_for_each_entry(intr, &os_intr_list, head) { - intr->handler(intr->irq, intr->dev); - } - - ualarm(INTR_FREQ, 0); -} - -static struct sigaction intr = { - .sa_handler = os_intr, -}; - -/****************************************************************************** * horrific stuff to implement linux's ioremap interface on top of pciaccess *****************************************************************************/ static struct os_ioremap_info { @@ -248,9 +179,7 @@ os_init(char *cfg, char *dbg, bool init) os_init_device(pdev, cfg, dbg); } - sigaction(SIGALRM, &intr, 0); - ualarm(INTR_FREQ, 0); - return 0; + return pthread_create(&os_intr_thread, NULL, os_intr, NULL); } static void diff --git a/lib/priv.h b/lib/priv.h new file mode 100644 index 000000000..65448b24b --- /dev/null +++ b/lib/priv.h @@ -0,0 +1,23 @@ +#ifndef __OS_PRIV_H__ +#define __OS_PRIV_H__ + +#include <pthread.h> +#include <unistd.h> + +struct os_device { + struct nouveau_device base; + struct list_head head; + char *name; + char *cfg; + char *dbg; +}; + +struct os_client { + struct nouveau_client base; + struct list_head head; +}; + +extern pthread_t os_intr_thread; +void *os_intr(void *arg); + +#endif |