lkml.org 
[lkml]   [2009]   [May]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: [v0 PATCH 1/4] EDAC: MPIC Hypertransport IRQ support
    From
    Date
    On Fri, 2009-05-15 at 16:43 +0800, Harry Ciao wrote:
    > Support EDAC INT mode for Hypertransport devices, where southbridge
    > NMI Request messages posted through Hypertransport Channel will
    > be transferred to a MPIC interrupt instance that latches MPIC INT0
    > pin. Also, Hypertransport Hostbridge controller may latch MPIC INT2
    > pin for Hypertransport Link Errors.
    >
    > Since multiple Hypertransport southbridges such as AMD8131 & AMD8111
    > could post NMI request messages, EDAC core should be responsible
    > for maintaining the mapping from hwirq == 0 to a virq.
    >
    > The edac_mpic_irq.c is inert for EDAC drivers where related hardware
    > is not connecting to MPIC, so it should be controlled by CONFIG_MPIC.

    It would have been simpler to ajust avoid this layer completely and
    always just map the interrupts.

    IE. There is no problem with calling irq_create_mapping() for the same
    hwirq multiple times, though they aren't refcounted, so just don't call
    irq_dispose_mapping() and you're done :-)

    IRQ mappings don't need to be disposed of, especially with mpic where
    they don't actually occupy resources (the reverse map is of fixed size
    anyway).

    Ben.

    > Signed-off-by: Harry Ciao <qingtao.cao@windriver.com>
    > diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
    > index 07a31cf..62778ee 100644
    > --- a/drivers/edac/Makefile
    > +++ b/drivers/edac/Makefile
    > @@ -17,6 +17,10 @@ ifdef CONFIG_PCI
    > edac_core-objs += edac_pci.o edac_pci_sysfs.o
    > endif
    >
    > +ifdef CONFIG_MPIC
    > +edac_core-objs += edac_mpic_irq.o
    > +endif
    > +
    > obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
    > obj-$(CONFIG_EDAC_CPC925) += cpc925_edac.o
    > obj-$(CONFIG_EDAC_I5000) += i5000_edac.o
    > diff --git a/drivers/edac/edac_mpic_irq.c b/drivers/edac/edac_mpic_irq.c
    > new file mode 100644
    > index 0000000..26b43c0
    > --- /dev/null
    > +++ b/drivers/edac/edac_mpic_irq.c
    > @@ -0,0 +1,145 @@
    > +/*
    > + * edac_mpic_irq.c -
    > + * For all EDAC Hypertransport southbridge devices(such as AMD8111
    > + * or AMD8131) that could post upstream NMI Request Messages, this
    > + * driver is used to manage the mapping from the hardware IRQ that
    > + * carried in the NMI Request Message to its related virtual IRQ.
    > + *
    > + * The EDAC driver for a specific Hypertransport southbridge device
    > + * must implement its mach-specific method for edac_mach_get_irq().
    > + *
    > + * Copyright (c) 2009 Wind River Systems, Inc.
    > + *
    > + * Authors: Cao Qingtao <qingtao.cao@windriver.com>
    > + *
    > + * This program is free software; you can redistribute it and/or modify
    > + * it under the terms of the GNU General Public License version 2 as
    > + * published by the Free Software Foundation.
    > + *
    > + * This program is distributed in the hope that it will be useful,
    > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    > + * See the GNU General Public License for more details.
    > + *
    > + * You should have received a copy of the GNU General Public License
    > + * along with this program; if not, write to the Free Software
    > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    > + */
    > +
    > +#include <linux/kernel.h>
    > +#include <linux/module.h>
    > +#include <linux/interrupt.h>
    > +#include <linux/of.h>
    > +#include <linux/edac.h>
    > +
    > +struct irqmap {
    > + int virq;
    > + int count;
    > +};
    > +
    > +static struct irqmap hwirq2virqs[MPIC_HWIRQS] = {
    > + [MPIC_HWIRQ_HT_NMI] = {
    > + .virq = NO_IRQ,
    > + .count = 0,
    > + },
    > + [MPIC_HWIRQ_INTERNAL_ERROR] = {
    > + .virq = NO_IRQ,
    > + .count = 0,
    > + },
    > +};
    > +
    > +#ifdef CONFIG_PPC_MAPLE
    > +static int edac_maple_get_irq(int hwirq)
    > +{
    > + struct device_node *np, *mpic_node = NULL;
    > + int irq = NO_IRQ;
    > +
    > + /*
    > + * Locate MPIC in the device-tree. Note that there is a bug
    > + * in Maple device-tree where the type of the controller is
    > + * open-pic and not interrupt-controller
    > + */
    > + for_each_node_by_type(np, "interrupt-controller") {
    > + if (of_device_is_compatible(np, "open-pic")) {
    > + mpic_node = np;
    > + break;
    > + }
    > + }
    > +
    > + if (mpic_node == NULL) {
    > + for_each_node_by_type(np, "open-pic") {
    > + mpic_node = np;
    > + break;
    > + }
    > + }
    > +
    > + if (mpic_node) {
    > + irq = irq_create_of_mapping(mpic_node, &hwirq, 1);
    > + of_node_put(mpic_node);
    > + } else
    > + printk(KERN_ERR "Failed to locate the MPIC DTB node\n");
    > +
    > + return irq;
    > +}
    > +#endif
    > +
    > +/*
    > + * NOTE:
    > + * The EDAC driver should implement and register its machine-specific
    > + * method to get a virtual IRQ here.
    > + */
    > +static int edac_mach_get_irq(int hwirq)
    > +{
    > + int virq = NO_IRQ;
    > +
    > +#ifdef CONFIG_PPC_MAPLE
    > + virq = edac_maple_get_irq(hwirq);
    > +#endif
    > +
    > + return virq;
    > +}
    > +
    > +int edac_get_mpic_irq(int hwirq)
    > +{
    > + struct irqmap *irq;
    > +
    > + if ((hwirq != MPIC_HWIRQ_HT_NMI) &&
    > + (hwirq != MPIC_HWIRQ_INTERNAL_ERROR))
    > + return NO_IRQ;
    > +
    > + irq = &hwirq2virqs[hwirq];
    > +
    > + if (irq->virq == NO_IRQ) {
    > + if (irq->count == 0) {
    > + irq->virq = edac_mach_get_irq(hwirq);
    > + if (irq->virq != NO_IRQ)
    > + irq->count++;
    > + else
    > + irq->count = -1; /* error */
    > + }
    > + } else
    > + irq->count++;
    > +
    > + return irq->virq;
    > +}
    > +EXPORT_SYMBOL_GPL(edac_get_mpic_irq);
    > +
    > +void edac_put_mpic_irq(int hwirq)
    > +{
    > + struct irqmap *irq;
    > +
    > + if ((hwirq != MPIC_HWIRQ_HT_NMI) &&
    > + (hwirq != MPIC_HWIRQ_INTERNAL_ERROR))
    > + return;
    > +
    > + irq = &hwirq2virqs[hwirq];
    > +
    > + if (irq->count <= 0)
    > + return;
    > +
    > + if (--irq->count == 0) {
    > + irq_dispose_mapping(irq->virq);
    > + irq->virq = NO_IRQ;
    > + }
    > +}
    > +EXPORT_SYMBOL_GPL(edac_put_mpic_irq);
    > diff --git a/include/linux/edac.h b/include/linux/edac.h
    > index 7cf92e8..804dbb6 100644
    > --- a/include/linux/edac.h
    > +++ b/include/linux/edac.h
    > @@ -38,4 +38,27 @@ static inline void opstate_init(void)
    > return;
    > }
    >
    > +#ifdef CONFIG_MPIC
    > +enum {
    > + /*
    > + * Vector carried in southbridge NMI Request Messages
    > + * posted through Hypertransport Channel
    > + */
    > + MPIC_HWIRQ_HT_NMI = 0,
    > +
    > + /*
    > + * Vector for MPIC Internal Error
    > + */
    > + MPIC_HWIRQ_INTERNAL_ERROR = 2,
    > +
    > + MPIC_HWIRQS, /* must be the very last */
    > +};
    > +
    > +/* Create a hwirq2virq mapping for the specified hwirq */
    > +extern int edac_get_mpic_irq(int hwirq);
    > +
    > +/* Dispose the hwirq2virq mapping for the specified hwirq */
    > +extern void edac_put_mpic_irq(int hwirq);
    > +#endif
    > +
    > #endif
    > _______________________________________________
    > Linuxppc-dev mailing list
    > Linuxppc-dev@ozlabs.org
    > https://ozlabs.org/mailman/listinfo/linuxppc-dev



    \
     
     \ /
      Last update: 2009-05-18 00:03    [W:0.036 / U:0.364 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site