From patchwork Mon May 24 20:13:40 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 53463 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 5876CB7D83 for ; Tue, 25 May 2010 06:30:37 +1000 (EST) Received: from localhost ([127.0.0.1]:53422 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OGeIC-0002cz-Pm for incoming@patchwork.ozlabs.org; Mon, 24 May 2010 16:30:32 -0400 Received: from [140.186.70.92] (port=41124 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OGe3R-0001rI-MC for qemu-devel@nongnu.org; Mon, 24 May 2010 16:15:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OGe3K-0000NF-LA for qemu-devel@nongnu.org; Mon, 24 May 2010 16:15:17 -0400 Received: from fmmailgate03.web.de ([217.72.192.234]:51059) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OGe3J-0000N2-Fc for qemu-devel@nongnu.org; Mon, 24 May 2010 16:15:10 -0400 Received: from smtp05.web.de ( [172.20.4.166]) by fmmailgate03.web.de (Postfix) with ESMTP id 9D9B5152093E3; Mon, 24 May 2010 22:13:56 +0200 (CEST) Received: from [88.65.39.229] (helo=localhost.localdomain) by smtp05.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.110 #4) id 1OGe28-0004UY-02; Mon, 24 May 2010 22:13:56 +0200 From: Jan Kiszka To: qemu-devel@nongnu.org Date: Mon, 24 May 2010 22:13:40 +0200 Message-Id: X-Mailer: git-send-email 1.6.0.2 In-Reply-To: References: In-Reply-To: References: X-Sender: jan.kiszka@web.de X-Provags-ID: V01U2FsdGVkX1+tODmyjZ7O1m3KJ14zWIcDuHhhzx33hK6aJu2V deIXZ9IQo7//n6Cbp/cx696krbkAa4uKOaYFBlqdGmG0Tf1xoc Usivtmlsg= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: blue Swirl , Jan Kiszka , Juan Quintela Subject: [Qemu-devel] [RFT][PATCH 07/15] qemu_irq: Add IRQ handlers with delivery feedback X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Jan Kiszka This allows to communicate potential IRQ coalescing during delivery from the sink back to the source. Targets that support IRQ coalescing workarounds need to register handlers that return the appropriate QEMU_IRQ_* code, and they have to propergate the code across all IRQ redirections. If the IRQ source receives a QEMU_IRQ_COALESCED, it can apply its workaround. If multiple sinks exist, the source may only consider an IRQ coalesced if all other sinks either report QEMU_IRQ_COALESCED as well or QEMU_IRQ_MASKED. Signed-off-by: Jan Kiszka --- hw/irq.c | 38 +++++++++++++++++++++++++++++--------- hw/irq.h | 22 +++++++++++++++------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/hw/irq.c b/hw/irq.c index 7703f62..db2cce6 100644 --- a/hw/irq.c +++ b/hw/irq.c @@ -26,19 +26,27 @@ struct IRQState { qemu_irq_handler handler; + qemu_irq_fb_handler feedback_handler; void *opaque; int n; }; -void qemu_set_irq(qemu_irq irq, int level) +int qemu_set_irq(qemu_irq irq, int level) { - if (!irq) - return; - - irq->handler(irq->opaque, irq->n, level); + if (!irq) { + return 0; + } + if (irq->feedback_handler) { + return irq->feedback_handler(irq->opaque, irq->n, level); + } else { + irq->handler(irq->opaque, irq->n, level); + return QEMU_IRQ_DELIVERED; + } } -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) +static qemu_irq *allocate_irqs(qemu_irq_handler handler, + qemu_irq_fb_handler feedback_handler, + void *opaque, int n) { qemu_irq *s; struct IRQState *p; @@ -48,6 +56,7 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) p = (struct IRQState *)qemu_mallocz(sizeof(struct IRQState) * n); for (i = 0; i < n; i++) { p->handler = handler; + p->feedback_handler = feedback_handler; p->opaque = opaque; p->n = i; s[i] = p; @@ -56,22 +65,33 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) return s; } +qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) +{ + return allocate_irqs(handler, NULL, opaque, n); +} + +qemu_irq *qemu_allocate_feedback_irqs(qemu_irq_fb_handler handler, + void *opaque, int n) +{ + return allocate_irqs(NULL, handler, opaque, n); +} + void qemu_free_irqs(qemu_irq *s) { qemu_free(s[0]); qemu_free(s); } -static void qemu_notirq(void *opaque, int line, int level) +static int qemu_notirq(void *opaque, int line, int level) { struct IRQState *irq = opaque; - irq->handler(irq->opaque, irq->n, !level); + return qemu_set_irq(irq, !level); } qemu_irq qemu_irq_invert(qemu_irq irq) { /* The default state for IRQs is low, so raise the output now. */ qemu_irq_raise(irq); - return qemu_allocate_irqs(qemu_notirq, irq, 1)[0]; + return allocate_irqs(NULL, qemu_notirq, irq, 1)[0]; } diff --git a/hw/irq.h b/hw/irq.h index 5daae44..eee03e6 100644 --- a/hw/irq.h +++ b/hw/irq.h @@ -3,15 +3,18 @@ /* Generic IRQ/GPIO pin infrastructure. */ -/* FIXME: Rmove one of these. */ +#define QEMU_IRQ_DELIVERED 0 +#define QEMU_IRQ_COALESCED (-1) +#define QEMU_IRQ_MASKED (-2) + typedef void (*qemu_irq_handler)(void *opaque, int n, int level); -typedef void SetIRQFunc(void *opaque, int irq_num, int level); +typedef int (*qemu_irq_fb_handler)(void *opaque, int n, int level); -void qemu_set_irq(qemu_irq irq, int level); +int qemu_set_irq(qemu_irq irq, int level); -static inline void qemu_irq_raise(qemu_irq irq) +static inline int qemu_irq_raise(qemu_irq irq) { - qemu_set_irq(irq, 1); + return qemu_set_irq(irq, 1); } static inline void qemu_irq_lower(qemu_irq irq) @@ -19,14 +22,19 @@ static inline void qemu_irq_lower(qemu_irq irq) qemu_set_irq(irq, 0); } -static inline void qemu_irq_pulse(qemu_irq irq) +static inline int qemu_irq_pulse(qemu_irq irq) { - qemu_set_irq(irq, 1); + int ret; + + ret = qemu_set_irq(irq, 1); qemu_set_irq(irq, 0); + return ret; } /* Returns an array of N IRQs. */ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n); +qemu_irq *qemu_allocate_feedback_irqs(qemu_irq_fb_handler handler, + void *opaque, int n); void qemu_free_irqs(qemu_irq *s); /* Returns a new IRQ with opposite polarity. */