lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 20 Jul 2022 11:21:44 +0800
From:   Huacai Chen <chenhuacai@...nel.org>
To:     Jianmin Lv <lvjianmin@...ngson.cn>
Cc:     Thomas Gleixner <tglx@...utronix.de>,
        Marc Zyngier <maz@...nel.org>,
        LKML <linux-kernel@...r.kernel.org>, loongarch@...ts.linux.dev,
        Hanjun Guo <guohanjun@...wei.com>,
        Lorenzo Pieralisi <lorenzo.pieralisi@....com>,
        Jiaxun Yang <jiaxun.yang@...goat.com>,
        Huacai Chen <chenhuacai@...ngson.cn>
Subject: Re: [PATCH V17 10/13] irqchip/loongson-liointc: Add ACPI init support

Hi, Jianmin,

On Wed, Jul 20, 2022 at 10:01 AM Jianmin Lv <lvjianmin@...ngson.cn> wrote:
>
> From: Huacai Chen <chenhuacai@...ngson.cn>
>
> LIOINTC stands for "Legacy I/O Interrupts" that described in Section
> 11.1 of "Loongson 3A5000 Processor Reference Manual". For more
> information please refer Documentation/loongarch/irq-chip-model.rst.
>
> Co-developed-by: Jianmin Lv <lvjianmin@...ngson.cn>
> Signed-off-by: Jianmin Lv <lvjianmin@...ngson.cn>
> Signed-off-by: Huacai Chen <chenhuacai@...ngson.cn>
> ---
>  arch/loongarch/include/asm/irq.h       |   4 +-
>  arch/loongarch/kernel/irq.c            |   1 -
>  drivers/irqchip/irq-loongson-liointc.c | 204 +++++++++++++++++++++------------
>  3 files changed, 131 insertions(+), 78 deletions(-)
>
> diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h
> index e9039f2..c847300 100644
> --- a/arch/loongarch/include/asm/irq.h
> +++ b/arch/loongarch/include/asm/irq.h
> @@ -105,7 +105,7 @@ static inline void eiointc_enable(void)
>
>  struct irq_domain *loongarch_cpu_irq_init(void);
>
> -struct irq_domain *liointc_acpi_init(struct irq_domain *parent,
> +int liointc_acpi_init(struct irq_domain *parent,
>                                         struct acpi_madt_lio_pic *acpi_liointc);
>  struct irq_domain *eiointc_acpi_init(struct irq_domain *parent,
>                                         struct acpi_madt_eio_pic *acpi_eiointc);
> @@ -138,7 +138,7 @@ int pch_pic_acpi_init(struct irq_domain *parent,
>  extern struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS];
>
>  extern struct irq_domain *cpu_domain;
> -extern struct irq_domain *liointc_domain;
> +extern struct fwnode_handle *liointc_handle;
>  extern struct fwnode_handle *pch_lpc_handle;
>  extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];
>
> diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c
> index 066f892..da131f5 100644
> --- a/arch/loongarch/kernel/irq.c
> +++ b/arch/loongarch/kernel/irq.c
> @@ -26,7 +26,6 @@
>  EXPORT_PER_CPU_SYMBOL(irq_stat);
>
>  struct irq_domain *cpu_domain;
> -struct irq_domain *liointc_domain;
>
>  struct acpi_vector_group pch_group[MAX_IO_PICS];
>  struct acpi_vector_group msi_group[MAX_IO_PICS];
> diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
> index 8d05d8b..fb78fff 100644
> --- a/drivers/irqchip/irq-loongson-liointc.c
> +++ b/drivers/irqchip/irq-loongson-liointc.c
> @@ -23,7 +23,7 @@
>  #endif
>
>  #define LIOINTC_CHIP_IRQ       32
> -#define LIOINTC_NUM_PARENT 4
> +#define LIOINTC_NUM_PARENT     4
>  #define LIOINTC_NUM_CORES      4
>
>  #define LIOINTC_INTC_CHIP_START        0x20
> @@ -41,6 +41,7 @@
>
>  #if defined(CONFIG_MIPS)
>  #define liointc_core_id get_ebase_cpunum()
> +#define GSI_MIN_CPU_IRQ                0
It seems this should be defined in arch/mips.


Huacai
>  #else
>  #define liointc_core_id get_csr_cpuid()
>  #endif
> @@ -58,6 +59,8 @@ struct liointc_priv {
>         bool                            has_lpc_irq_errata;
>  };
>
> +struct fwnode_handle *liointc_handle;
> +
>  static void liointc_chained_handle_irq(struct irq_desc *desc)
>  {
>         struct liointc_handler_data *handler = irq_desc_get_handler_data(desc);
> @@ -153,97 +156,79 @@ static void liointc_resume(struct irq_chip_generic *gc)
>         irq_gc_unlock_irqrestore(gc, flags);
>  }
>
> -static const char * const parent_names[] = {"int0", "int1", "int2", "int3"};
> -static const char * const core_reg_names[] = {"isr0", "isr1", "isr2", "isr3"};
> +static int parent_irq[LIOINTC_NUM_PARENT];
> +static u32 parent_int_map[LIOINTC_NUM_PARENT];
> +static const char *const parent_names[] = {"int0", "int1", "int2", "int3"};
> +static const char *const core_reg_names[] = {"isr0", "isr1", "isr2", "isr3"};
>
> -static void __iomem *liointc_get_reg_byname(struct device_node *node,
> -                                               const char *name)
> +static int liointc_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
> +                            const u32 *intspec, unsigned int intsize,
> +                            unsigned long *out_hwirq, unsigned int *out_type)
>  {
> -       int index = of_property_match_string(node, "reg-names", name);
> -
> -       if (index < 0)
> -               return NULL;
> -
> -       return of_iomap(node, index);
> +       if (WARN_ON(intsize < 1))
> +               return -EINVAL;
> +       *out_hwirq = intspec[0] - GSI_MIN_CPU_IRQ;
> +       *out_type = IRQ_TYPE_NONE;
> +       return 0;
>  }
>
> -static int __init liointc_of_init(struct device_node *node,
> -                                 struct device_node *parent)
> +static const struct irq_domain_ops acpi_irq_gc_ops = {
> +       .map    = irq_map_generic_chip,
> +       .unmap  = irq_unmap_generic_chip,
> +       .xlate  = liointc_domain_xlate,
> +};
> +
> +static int liointc_init(phys_addr_t addr, unsigned long size, int revision,
> +               struct fwnode_handle *domain_handle, struct device_node *node)
>  {
> +       int i, err;
> +       void __iomem *base;
> +       struct irq_chip_type *ct;
>         struct irq_chip_generic *gc;
>         struct irq_domain *domain;
> -       struct irq_chip_type *ct;
>         struct liointc_priv *priv;
> -       void __iomem *base;
> -       u32 of_parent_int_map[LIOINTC_NUM_PARENT];
> -       int parent_irq[LIOINTC_NUM_PARENT];
> -       bool have_parent = FALSE;
> -       int sz, i, err = 0;
>
>         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
>         if (!priv)
>                 return -ENOMEM;
>
> -       if (of_device_is_compatible(node, "loongson,liointc-2.0")) {
> -               base = liointc_get_reg_byname(node, "main");
> -               if (!base) {
> -                       err = -ENODEV;
> -                       goto out_free_priv;
> -               }
> +       base = ioremap(addr, size);
> +       if (!base)
> +               goto out_free_priv;
>
> -               for (i = 0; i < LIOINTC_NUM_CORES; i++)
> -                       priv->core_isr[i] = liointc_get_reg_byname(node, core_reg_names[i]);
> -               if (!priv->core_isr[0]) {
> -                       err = -ENODEV;
> -                       goto out_iounmap_base;
> -               }
> -       } else {
> -               base = of_iomap(node, 0);
> -               if (!base) {
> -                       err = -ENODEV;
> -                       goto out_free_priv;
> -               }
> +       for (i = 0; i < LIOINTC_NUM_CORES; i++)
> +               priv->core_isr[i] = base + LIOINTC_REG_INTC_STATUS;
>
> -               for (i = 0; i < LIOINTC_NUM_CORES; i++)
> -                       priv->core_isr[i] = base + LIOINTC_REG_INTC_STATUS;
> -       }
> +       for (i = 0; i < LIOINTC_NUM_PARENT; i++)
> +               priv->handler[i].parent_int_map = parent_int_map[i];
>
> -       for (i = 0; i < LIOINTC_NUM_PARENT; i++) {
> -               parent_irq[i] = of_irq_get_byname(node, parent_names[i]);
> -               if (parent_irq[i] > 0)
> -                       have_parent = TRUE;
> -       }
> -       if (!have_parent) {
> -               err = -ENODEV;
> -               goto out_iounmap_isr;
> -       }
> +       if (revision > 1) {
> +               for (i = 0; i < LIOINTC_NUM_CORES; i++) {
> +                       int index = of_property_match_string(node,
> +                                       "reg-names", core_reg_names[i]);
>
> -       sz = of_property_read_variable_u32_array(node,
> -                                               "loongson,parent_int_map",
> -                                               &of_parent_int_map[0],
> -                                               LIOINTC_NUM_PARENT,
> -                                               LIOINTC_NUM_PARENT);
> -       if (sz < 4) {
> -               pr_err("loongson-liointc: No parent_int_map\n");
> -               err = -ENODEV;
> -               goto out_iounmap_isr;
> -       }
> +                       if (index < 0)
> +                               return -EINVAL;
>
> -       for (i = 0; i < LIOINTC_NUM_PARENT; i++)
> -               priv->handler[i].parent_int_map = of_parent_int_map[i];
> +                       priv->core_isr[i] = of_iomap(node, index);
> +               }
> +       }
>
>         /* Setup IRQ domain */
> -       domain = irq_domain_add_linear(node, 32,
> +       if (!acpi_disabled)
> +               domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ,
> +                                       &acpi_irq_gc_ops, priv);
> +       else
> +               domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ,
>                                         &irq_generic_chip_ops, priv);
>         if (!domain) {
>                 pr_err("loongson-liointc: cannot add IRQ domain\n");
> -               err = -EINVAL;
> -               goto out_iounmap_isr;
> +               goto out_iounmap;
>         }
>
> -       err = irq_alloc_domain_generic_chips(domain, 32, 1,
> -                                       node->full_name, handle_level_irq,
> -                                       IRQ_NOPROBE, 0, 0);
> +       err = irq_alloc_domain_generic_chips(domain, LIOINTC_CHIP_IRQ, 1,
> +                                       (node ? node->full_name : "LIOINTC"),
> +                                       handle_level_irq, 0, IRQ_NOPROBE, 0);
>         if (err) {
>                 pr_err("loongson-liointc: unable to register IRQ domain\n");
>                 goto out_free_domain;
> @@ -299,24 +284,93 @@ static int __init liointc_of_init(struct device_node *node,
>                                 liointc_chained_handle_irq, &priv->handler[i]);
>         }
>
> +       liointc_handle = domain_handle;
>         return 0;
>
>  out_free_domain:
>         irq_domain_remove(domain);
> -out_iounmap_isr:
> -       for (i = 0; i < LIOINTC_NUM_CORES; i++) {
> -               if (!priv->core_isr[i])
> -                       continue;
> -               iounmap(priv->core_isr[i]);
> -       }
> -out_iounmap_base:
> +out_iounmap:
>         iounmap(base);
>  out_free_priv:
>         kfree(priv);
>
> -       return err;
> +       return -EINVAL;
> +}
> +
> +#ifdef CONFIG_OF
> +
> +static int __init liointc_of_init(struct device_node *node,
> +                                 struct device_node *parent)
> +{
> +       bool have_parent = FALSE;
> +       int sz, i, index, revision, err = 0;
> +       struct resource res;
> +
> +       if (!of_device_is_compatible(node, "loongson,liointc-2.0")) {
> +               index = 0;
> +               revision = 1;
> +       } else {
> +               index = of_property_match_string(node, "reg-names", "main");
> +               revision = 2;
> +       }
> +
> +       if (of_address_to_resource(node, index, &res))
> +               return -EINVAL;
> +
> +       for (i = 0; i < LIOINTC_NUM_PARENT; i++) {
> +               parent_irq[i] = of_irq_get_byname(node, parent_names[i]);
> +               if (parent_irq[i] > 0)
> +                       have_parent = TRUE;
> +       }
> +       if (!have_parent)
> +               return -ENODEV;
> +
> +       sz = of_property_read_variable_u32_array(node,
> +                                               "loongson,parent_int_map",
> +                                               &parent_int_map[0],
> +                                               LIOINTC_NUM_PARENT,
> +                                               LIOINTC_NUM_PARENT);
> +       if (sz < 4) {
> +               pr_err("loongson-liointc: No parent_int_map\n");
> +               return -ENODEV;
> +       }
> +
> +       err = liointc_init(res.start, resource_size(&res),
> +                       revision, of_node_to_fwnode(node), node);
> +       if (err < 0)
> +               return err;
> +
> +       return 0;
>  }
>
>  IRQCHIP_DECLARE(loongson_liointc_1_0, "loongson,liointc-1.0", liointc_of_init);
>  IRQCHIP_DECLARE(loongson_liointc_1_0a, "loongson,liointc-1.0a", liointc_of_init);
>  IRQCHIP_DECLARE(loongson_liointc_2_0, "loongson,liointc-2.0", liointc_of_init);
> +
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +int __init liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic *acpi_liointc)
> +{
> +       int ret;
> +       struct fwnode_handle *domain_handle;
> +
> +       parent_int_map[0] = acpi_liointc->cascade_map[0];
> +       parent_int_map[1] = acpi_liointc->cascade_map[1];
> +
> +       parent_irq[0] = irq_create_mapping(parent, acpi_liointc->cascade[0]);
> +       parent_irq[1] = irq_create_mapping(parent, acpi_liointc->cascade[1]);
> +
> +       domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_liointc);
> +       if (!domain_handle) {
> +               pr_err("Unable to allocate domain handle\n");
> +               return -ENOMEM;
> +       }
> +       ret = liointc_init(acpi_liointc->address, acpi_liointc->size,
> +                          1, domain_handle, NULL);
> +       if (ret)
> +               irq_domain_free_fwnode(domain_handle);
> +
> +       return ret;
> +}
> +#endif
> --
> 1.8.3.1
>
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ