From patchwork Thu Apr 22 13:09:58 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guillaume Knispel X-Patchwork-Id: 50736 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 7C224B8289 for ; Thu, 22 Apr 2010 23:10:36 +1000 (EST) Received: from mx1.corp.avencall.com (mx1.corp.avencall.com [91.194.178.12]) by ozlabs.org (Postfix) with ESMTP id 75EF2B7D18 for ; Thu, 22 Apr 2010 23:10:09 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by mx1.corp.avencall.com (Postfix) with ESMTP id 8EFC850611F; Thu, 22 Apr 2010 15:10:04 +0200 (CEST) X-Virus-Scanned: amavisd-new at mx1.corp.avencall.com Received: from mx1.corp.avencall.com ([127.0.0.1]) by localhost (mx1.corp.avencall.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id DL6KswS2Qd13; Thu, 22 Apr 2010 15:10:02 +0200 (CEST) Received: from localhost.localdomain (unknown [92.103.5.174]) by mx1.corp.avencall.com (Postfix) with ESMTPSA id 1D22B50611A; Thu, 22 Apr 2010 15:10:02 +0200 (CEST) From: Guillaume Knispel To: linux-kernel@vger.kernel.org, Linuxppc-dev@lists.ozlabs.org Subject: [PATCH 2/2] genirq: update doc Date: Thu, 22 Apr 2010 15:09:58 +0200 Message-Id: <1271941798-9659-3-git-send-email-gknispel@proformatique.com> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: <1271941798-9659-1-git-send-email-gknispel@proformatique.com> References: <1271941798-9659-1-git-send-email-gknispel@proformatique.com> Cc: Lars-Peter Clausen , Russell King , Bartlomiej Zolnierkiewicz , Haavard Skinnemoen , Peter Zijlstra , Guillaume Knispel , Michael Buesch , Ingo Molnar , Linus Torvalds , Thomas Gleixner X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Following "genirq: always build resend_irqs" and previous changes, this commit updates the genirq DocBook. Signed-off-by: Guillaume Knispel CC: linux-kernel@vger.kernel.org CC: Linuxppc-dev@lists.ozlabs.org CC: Bartlomiej Zolnierkiewicz CC: Benjamin Herrenschmidt CC: Haavard Skinnemoen CC: Ingo Molnar CC: Lars-Peter Clausen CC: Linus Torvalds CC: Michael Buesch CC: Peter Zijlstra CC: Russell King CC: Thomas Gleixner --- Documentation/DocBook/genericirq.tmpl | 73 ++++++++++++++++++-------------- 1 files changed, 41 insertions(+), 32 deletions(-) diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl index 1448b33..5ee204c 100644 --- a/Documentation/DocBook/genericirq.tmpl +++ b/Documentation/DocBook/genericirq.tmpl @@ -240,8 +240,6 @@ default_enable(irq) default_disable(irq) { - if (!delay_disable(irq)) - desc->chip->mask(irq); } default_ack(irq) @@ -264,7 +262,11 @@ noop(irq) } - + Note: default_disable is empty so that an edge-triggered + interrupt happening between a disable_irq() and an enable_irq() + is catched by the kernel for later replay. See + for details. + @@ -278,9 +280,14 @@ noop(irq) The following control flow is implemented (simplified excerpt): -desc->chip->start(); +desc->chip->mask_ack(); +if (desc->status & inprogress) + return; +desc->status |= inprogress; handle_IRQ_event(desc->action); -desc->chip->end(); +desc->status &= inprogress; +if (!(desc->status & disabled)) + desc->chip->unmask_ack(); @@ -293,21 +300,23 @@ desc->chip->end(); The following control flow is implemented (simplified excerpt): -if (desc->status & running) { - desc->chip->hold(); +if (desc->status & (inprogress | disabled)) { desc->status |= pending | masked; + desc->chip->mask_ack(); return; } -desc->chip->start(); -desc->status |= running; +desc->chip->ack(); +desc->status |= inprogress; do { - if (desc->status & masked) - desc->chip->enable(); + if ((desc->status & (pending | masked | disabled)) + == (pending | masked)) { + desc->chip->unmask(); + desc->status &= ~masked; + } desc->status &= ~pending; handle_IRQ_event(desc->action); -} while (status & pending); -desc->status &= ~running; -desc->chip->end(); +} while ((status & (pending | disabled)) == pending); +desc->status &= inprogress; @@ -342,9 +351,9 @@ handle_IRQ_event(desc->action); The following control flow is implemented (simplified excerpt): -desc->chip->start(); +desc->chip->ack(); handle_IRQ_event(desc->action); -desc->chip->end(); +desc->chip->eoi(); @@ -361,22 +370,20 @@ desc->chip->end(); Delayed interrupt disable - This per interrupt selectable feature, which was introduced by Russell - King in the ARM interrupt implementation, does not mask an interrupt - at the hardware level when disable_irq() is called. The interrupt is - kept enabled and is masked in the flow handler when an interrupt event - happens. This prevents losing edge interrupts on hardware which does - not store an edge interrupt event while the interrupt is disabled at - the hardware level. When an interrupt arrives while the IRQ_DISABLED - flag is set, then the interrupt is masked at the hardware level and - the IRQ_PENDING bit is set. When the interrupt is re-enabled by - enable_irq() the pending bit is checked and if it is set, the - interrupt is resent either via hardware or by a software resend - mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when - you want to use the delayed interrupt disable feature and your - hardware is not capable of retriggering an interrupt.) - The delayed interrupt disable can be runtime enabled, per interrupt, - by setting the IRQ_DELAYED_DISABLE flag in the irq_desc status field. + At least when using default_disable as the ->disable() callback of a + chip handler, an interrupt is not masked at the hardware level when + disable_irq() is called. The interrupt is kept enabled and is masked + in the flow handler when an interrupt event happens. This prevents + losing edge interrupts on hardware which does not store an edge + interrupt event while the interrupt is disabled at the hardware level. + This makes use of the replay mechanism that is mandatory anyway to + prevent potential race conditions between an interrupt event and a call + to disable_irq() at the same time. When an interrupt arrives in + handle_edge_irq() while the IRQ_DISABLED flag is set, then the + interrupt is masked at the hardware level and the IRQ_PENDING bit is + set. When the interrupt is re-enabled by enable_irq() the pending bit + is checked and if it is set, the interrupt is resent either via + hardware or by a software resend mechanism. @@ -387,6 +394,8 @@ desc->chip->end(); contains all the direct chip relevant functions, which can be utilized by the irq flow implementations. + disable() - Optional + enable() - Optional ack() mask_ack() - Optional, recommended for performance mask()