From: Marc Zyngier <maz@kernel.org>
To: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: linux-kernel@vger.kernel.org, Robin Murphy <robin.murphy@arm.com>,
Mark Rutland <mark.rutland@arm.com>,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
Rob Herring <robh+dt@kernel.org>,
Fang Xiang <fangxiang3@xiaomi.com>
Subject: Re: [PATCH 2/2] irqchip/gic-v3: Enable non-coherent redistributors/ITSes probing
Date: Tue, 03 Oct 2023 17:44:27 +0100 [thread overview]
Message-ID: <86r0mboduc.wl-maz@kernel.org> (raw)
In-Reply-To: <ZRwonK+01HKJkKXa@lpieralisi>
On Tue, 03 Oct 2023 15:43:40 +0100,
Lorenzo Pieralisi <lpieralisi@kernel.org> wrote:
>
> On Tue, Sep 05, 2023 at 12:34:58PM +0100, Marc Zyngier wrote:
>
> [...]
>
> > > * Make sure *all* the ITS are reset before we probe any, as
> > > * they may be sharing memory. If any of the ITS fails to
> > > @@ -5396,7 +5405,8 @@ static int __init its_of_probe(struct device_node *node)
> > > continue;
> > > }
> > >
> > > - its_probe_one(&res, &np->fwnode, of_node_to_nid(np));
> > > + its_probe_one(&res, &np->fwnode, of_node_to_nid(np),
> > > + of_property_read_bool(np, "dma-noncoherent"));
> > > }
> > > return 0;
> > > }
> > > @@ -5533,7 +5543,8 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
> > > }
> > >
> > > err = its_probe_one(&res, dom_handle,
> > > - acpi_get_its_numa_node(its_entry->translation_id));
> > > + acpi_get_its_numa_node(its_entry->translation_id),
> > > + false);
> >
> > I came up with the following alternative approach, which is as usual
> > completely untested. It is entirely based on the quirk infrastructure,
> > and doesn't touch the ACPI path at all.
>
> Writing the ACPI bits. We can't use the quirks framework for ACPI (we
> don't have "properties" and I don't think we want to attach any to the
> fwnode_handle) that's why I generalized its_probe_one() above with an
> extra param, that would have simplified ACPI parsing:
>
> - we alloc struct its_node in its_probe_one() but at that stage
> ACPI parsing was already done. If we have to parse the MADT(ITS) again
> just to scan for non-coherent we then have to match the MADT entries
> to the *current* struct its_node* we are handling (MADT parsing
> callbacks don't even take a param - we have to resort to global
> variables - definitely doable but it is a bit ugly).
Well, a more acceptable approach would be for its_probe_one() to take
an allocated and possibly pre-populated its_node structure (crucially,
with the quirk flags set), which itself results in a bunch of low
hanging cleanups, see the patch below.
I have boot tested it in a DT guest, so it is obviously perfect.
M.
From 978f654d4459adf0b8f3f8e896ca37035b3b114c Mon Sep 17 00:00:00 2001
From: Marc Zyngier <maz@kernel.org>
Date: Tue, 3 Oct 2023 17:35:27 +0100
Subject: [PATCH] irqchip/gic-v3-its: Split allocation from initialisation of
its_node
In order to pave the way for more fancy quirk handling without making
more of a mess of this terrible driver, split the allocation of the
ITS descriptor (its_node) from the actual probing.
This will allow firmware-specific hooks to be added between these
two points.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/irqchip/irq-gic-v3-its.c | 151 +++++++++++++++++++------------
1 file changed, 91 insertions(+), 60 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index e0c2b10d154d..bf21383b714e 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -4952,7 +4952,7 @@ static void __init __iomem *its_map_one(struct resource *res, int *err)
return NULL;
}
-static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
+static int its_init_domain(struct its_node *its)
{
struct irq_domain *inner_domain;
struct msi_domain_info *info;
@@ -4966,7 +4966,7 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
inner_domain = irq_domain_create_hierarchy(its_parent,
its->msi_domain_flags, 0,
- handle, &its_domain_ops,
+ its->fwnode_handle, &its_domain_ops,
info);
if (!inner_domain) {
kfree(info);
@@ -5017,8 +5017,7 @@ static int its_init_vpe_domain(void)
return 0;
}
-static int __init its_compute_its_list_map(struct resource *res,
- void __iomem *its_base)
+static int __init its_compute_its_list_map(struct its_node *its)
{
int its_number;
u32 ctlr;
@@ -5032,15 +5031,15 @@ static int __init its_compute_its_list_map(struct resource *res,
its_number = find_first_zero_bit(&its_list_map, GICv4_ITS_LIST_MAX);
if (its_number >= GICv4_ITS_LIST_MAX) {
pr_err("ITS@%pa: No ITSList entry available!\n",
- &res->start);
+ &its->phys_base);
return -EINVAL;
}
- ctlr = readl_relaxed(its_base + GITS_CTLR);
+ ctlr = readl_relaxed(its->base + GITS_CTLR);
ctlr &= ~GITS_CTLR_ITS_NUMBER;
ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT;
- writel_relaxed(ctlr, its_base + GITS_CTLR);
- ctlr = readl_relaxed(its_base + GITS_CTLR);
+ writel_relaxed(ctlr, its->base + GITS_CTLR);
+ ctlr = readl_relaxed(its->base + GITS_CTLR);
if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) {
its_number = ctlr & GITS_CTLR_ITS_NUMBER;
its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT;
@@ -5048,75 +5047,50 @@ static int __init its_compute_its_list_map(struct resource *res,
if (test_and_set_bit(its_number, &its_list_map)) {
pr_err("ITS@%pa: Duplicate ITSList entry %d\n",
- &res->start, its_number);
+ &its->phys_base, its_number);
return -EINVAL;
}
return its_number;
}
-static int __init its_probe_one(struct resource *res,
- struct fwnode_handle *handle, int numa_node)
+static int __init its_probe_one(struct its_node *its)
{
- struct its_node *its;
- void __iomem *its_base;
- u64 baser, tmp, typer;
+ u64 baser, tmp;
struct page *page;
u32 ctlr;
int err;
- its_base = its_map_one(res, &err);
- if (!its_base)
- return err;
-
- pr_info("ITS %pR\n", res);
-
- its = kzalloc(sizeof(*its), GFP_KERNEL);
- if (!its) {
- err = -ENOMEM;
- goto out_unmap;
- }
-
- raw_spin_lock_init(&its->lock);
- mutex_init(&its->dev_alloc_lock);
- INIT_LIST_HEAD(&its->entry);
- INIT_LIST_HEAD(&its->its_device_list);
- typer = gic_read_typer(its_base + GITS_TYPER);
- its->typer = typer;
- its->base = its_base;
- its->phys_base = res->start;
if (is_v4(its)) {
- if (!(typer & GITS_TYPER_VMOVP)) {
- err = its_compute_its_list_map(res, its_base);
+ if (!(its->typer & GITS_TYPER_VMOVP)) {
+ err = its_compute_its_list_map(its);
if (err < 0)
- goto out_free_its;
+ goto out;
its->list_nr = err;
pr_info("ITS@%pa: Using ITS number %d\n",
- &res->start, err);
+ &its->phys_base, err);
} else {
- pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
+ pr_info("ITS@%pa: Single VMOVP capable\n", &its->phys_base);
}
if (is_v4_1(its)) {
- u32 svpet = FIELD_GET(GITS_TYPER_SVPET, typer);
+ u32 svpet = FIELD_GET(GITS_TYPER_SVPET, its->typer);
- its->sgir_base = ioremap(res->start + SZ_128K, SZ_64K);
+ its->sgir_base = ioremap(its->phys_base + SZ_128K, SZ_64K);
if (!its->sgir_base) {
err = -ENOMEM;
- goto out_free_its;
+ goto out;
}
- its->mpidr = readl_relaxed(its_base + GITS_MPIDR);
+ its->mpidr = readl_relaxed(its->base + GITS_MPIDR);
pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n",
- &res->start, its->mpidr, svpet);
+ &its->phys_base, its->mpidr, svpet);
}
}
- its->numa_node = numa_node;
-
page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
get_order(ITS_CMD_QUEUE_SZ));
if (!page) {
@@ -5125,12 +5099,9 @@ static int __init its_probe_one(struct resource *res,
}
its->cmd_base = (void *)page_address(page);
its->cmd_write = its->cmd_base;
- its->fwnode_handle = handle;
its->get_msi_base = its_irq_get_msi_base;
its->msi_domain_flags = IRQ_DOMAIN_FLAG_ISOLATED_MSI;
- its_enable_quirks(its);
-
err = its_alloc_tables(its);
if (err)
goto out_free_cmd;
@@ -5174,7 +5145,7 @@ static int __init its_probe_one(struct resource *res,
ctlr |= GITS_CTLR_ImDe;
writel_relaxed(ctlr, its->base + GITS_CTLR);
- err = its_init_domain(handle, its);
+ err = its_init_domain(its);
if (err)
goto out_free_tables;
@@ -5191,11 +5162,8 @@ static int __init its_probe_one(struct resource *res,
out_unmap_sgir:
if (its->sgir_base)
iounmap(its->sgir_base);
-out_free_its:
- kfree(its);
-out_unmap:
- iounmap(its_base);
- pr_err("ITS@%pa: failed probing (%d)\n", &res->start, err);
+out:
+ pr_err("ITS@%pa: failed probing (%d)\n", &its->phys_base, err);
return err;
}
@@ -5356,10 +5324,53 @@ static const struct of_device_id its_device_id[] = {
{},
};
+static struct its_node __init *its_node_init(struct resource *res,
+ struct fwnode_handle *handle, int numa_node)
+{
+ void __iomem *its_base;
+ struct its_node *its;
+ int err;
+
+ its_base = its_map_one(res, &err);
+ if (!its_base)
+ return NULL;
+
+ pr_info("ITS %pR\n", res);
+
+ its = kzalloc(sizeof(*its), GFP_KERNEL);
+ if (!its)
+ goto out_unmap;
+
+ raw_spin_lock_init(&its->lock);
+ mutex_init(&its->dev_alloc_lock);
+ INIT_LIST_HEAD(&its->entry);
+ INIT_LIST_HEAD(&its->its_device_list);
+
+ its->typer = gic_read_typer(its_base + GITS_TYPER);
+ its->base = its_base;
+ its->phys_base = res->start;
+
+ its->numa_node = numa_node;
+ its->fwnode_handle = handle;
+
+ return its;
+
+out_unmap:
+ iounmap(its_base);
+ return NULL;
+}
+
+static void its_node_destroy(struct its_node *its)
+{
+ iounmap(its->base);
+ kfree(its);
+}
+
static int __init its_of_probe(struct device_node *node)
{
struct device_node *np;
struct resource res;
+ int err;
/*
* Make sure *all* the ITS are reset before we probe any, as
@@ -5369,8 +5380,6 @@ static int __init its_of_probe(struct device_node *node)
*/
for (np = of_find_matching_node(node, its_device_id); np;
np = of_find_matching_node(np, its_device_id)) {
- int err;
-
if (!of_device_is_available(np) ||
!of_property_read_bool(np, "msi-controller") ||
of_address_to_resource(np, 0, &res))
@@ -5383,6 +5392,8 @@ static int __init its_of_probe(struct device_node *node)
for (np = of_find_matching_node(node, its_device_id); np;
np = of_find_matching_node(np, its_device_id)) {
+ struct its_node *its;
+
if (!of_device_is_available(np))
continue;
if (!of_property_read_bool(np, "msi-controller")) {
@@ -5396,7 +5407,17 @@ static int __init its_of_probe(struct device_node *node)
continue;
}
- its_probe_one(&res, &np->fwnode, of_node_to_nid(np));
+
+ its = its_node_init(&res, &np->fwnode, of_node_to_nid(np));
+ if (!its)
+ return -ENOMEM;
+
+ its_enable_quirks(its);
+ err = its_probe_one(its);
+ if (err) {
+ its_node_destroy(its);
+ return err;
+ }
}
return 0;
}
@@ -5508,6 +5529,7 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
{
struct acpi_madt_generic_translator *its_entry;
struct fwnode_handle *dom_handle;
+ struct its_node *its;
struct resource res;
int err;
@@ -5532,11 +5554,20 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
goto dom_err;
}
- err = its_probe_one(&res, dom_handle,
- acpi_get_its_numa_node(its_entry->translation_id));
+ its = its_node_init(&res, dom_handle,
+ acpi_get_its_numa_node(its_entry->translation_id));
+ if (!its) {
+ err = -ENOMEM;
+ goto node_err;
+ }
+
+ /* Stick ACPI quirk handling here */
+
+ err = its_probe_one(its);
if (!err)
return 0;
+node_err:
iort_deregister_domain_token(its_entry->translation_id);
dom_err:
irq_domain_free_fwnode(dom_handle);
--
2.34.1
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <maz@kernel.org>
To: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: linux-kernel@vger.kernel.org, Robin Murphy <robin.murphy@arm.com>,
Mark Rutland <mark.rutland@arm.com>,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
Rob Herring <robh+dt@kernel.org>,
Fang Xiang <fangxiang3@xiaomi.com>
Subject: Re: [PATCH 2/2] irqchip/gic-v3: Enable non-coherent redistributors/ITSes probing
Date: Tue, 03 Oct 2023 17:44:27 +0100 [thread overview]
Message-ID: <86r0mboduc.wl-maz@kernel.org> (raw)
In-Reply-To: <ZRwonK+01HKJkKXa@lpieralisi>
On Tue, 03 Oct 2023 15:43:40 +0100,
Lorenzo Pieralisi <lpieralisi@kernel.org> wrote:
>
> On Tue, Sep 05, 2023 at 12:34:58PM +0100, Marc Zyngier wrote:
>
> [...]
>
> > > * Make sure *all* the ITS are reset before we probe any, as
> > > * they may be sharing memory. If any of the ITS fails to
> > > @@ -5396,7 +5405,8 @@ static int __init its_of_probe(struct device_node *node)
> > > continue;
> > > }
> > >
> > > - its_probe_one(&res, &np->fwnode, of_node_to_nid(np));
> > > + its_probe_one(&res, &np->fwnode, of_node_to_nid(np),
> > > + of_property_read_bool(np, "dma-noncoherent"));
> > > }
> > > return 0;
> > > }
> > > @@ -5533,7 +5543,8 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
> > > }
> > >
> > > err = its_probe_one(&res, dom_handle,
> > > - acpi_get_its_numa_node(its_entry->translation_id));
> > > + acpi_get_its_numa_node(its_entry->translation_id),
> > > + false);
> >
> > I came up with the following alternative approach, which is as usual
> > completely untested. It is entirely based on the quirk infrastructure,
> > and doesn't touch the ACPI path at all.
>
> Writing the ACPI bits. We can't use the quirks framework for ACPI (we
> don't have "properties" and I don't think we want to attach any to the
> fwnode_handle) that's why I generalized its_probe_one() above with an
> extra param, that would have simplified ACPI parsing:
>
> - we alloc struct its_node in its_probe_one() but at that stage
> ACPI parsing was already done. If we have to parse the MADT(ITS) again
> just to scan for non-coherent we then have to match the MADT entries
> to the *current* struct its_node* we are handling (MADT parsing
> callbacks don't even take a param - we have to resort to global
> variables - definitely doable but it is a bit ugly).
Well, a more acceptable approach would be for its_probe_one() to take
an allocated and possibly pre-populated its_node structure (crucially,
with the quirk flags set), which itself results in a bunch of low
hanging cleanups, see the patch below.
I have boot tested it in a DT guest, so it is obviously perfect.
M.
From 978f654d4459adf0b8f3f8e896ca37035b3b114c Mon Sep 17 00:00:00 2001
From: Marc Zyngier <maz@kernel.org>
Date: Tue, 3 Oct 2023 17:35:27 +0100
Subject: [PATCH] irqchip/gic-v3-its: Split allocation from initialisation of
its_node
In order to pave the way for more fancy quirk handling without making
more of a mess of this terrible driver, split the allocation of the
ITS descriptor (its_node) from the actual probing.
This will allow firmware-specific hooks to be added between these
two points.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/irqchip/irq-gic-v3-its.c | 151 +++++++++++++++++++------------
1 file changed, 91 insertions(+), 60 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index e0c2b10d154d..bf21383b714e 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -4952,7 +4952,7 @@ static void __init __iomem *its_map_one(struct resource *res, int *err)
return NULL;
}
-static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
+static int its_init_domain(struct its_node *its)
{
struct irq_domain *inner_domain;
struct msi_domain_info *info;
@@ -4966,7 +4966,7 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
inner_domain = irq_domain_create_hierarchy(its_parent,
its->msi_domain_flags, 0,
- handle, &its_domain_ops,
+ its->fwnode_handle, &its_domain_ops,
info);
if (!inner_domain) {
kfree(info);
@@ -5017,8 +5017,7 @@ static int its_init_vpe_domain(void)
return 0;
}
-static int __init its_compute_its_list_map(struct resource *res,
- void __iomem *its_base)
+static int __init its_compute_its_list_map(struct its_node *its)
{
int its_number;
u32 ctlr;
@@ -5032,15 +5031,15 @@ static int __init its_compute_its_list_map(struct resource *res,
its_number = find_first_zero_bit(&its_list_map, GICv4_ITS_LIST_MAX);
if (its_number >= GICv4_ITS_LIST_MAX) {
pr_err("ITS@%pa: No ITSList entry available!\n",
- &res->start);
+ &its->phys_base);
return -EINVAL;
}
- ctlr = readl_relaxed(its_base + GITS_CTLR);
+ ctlr = readl_relaxed(its->base + GITS_CTLR);
ctlr &= ~GITS_CTLR_ITS_NUMBER;
ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT;
- writel_relaxed(ctlr, its_base + GITS_CTLR);
- ctlr = readl_relaxed(its_base + GITS_CTLR);
+ writel_relaxed(ctlr, its->base + GITS_CTLR);
+ ctlr = readl_relaxed(its->base + GITS_CTLR);
if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) {
its_number = ctlr & GITS_CTLR_ITS_NUMBER;
its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT;
@@ -5048,75 +5047,50 @@ static int __init its_compute_its_list_map(struct resource *res,
if (test_and_set_bit(its_number, &its_list_map)) {
pr_err("ITS@%pa: Duplicate ITSList entry %d\n",
- &res->start, its_number);
+ &its->phys_base, its_number);
return -EINVAL;
}
return its_number;
}
-static int __init its_probe_one(struct resource *res,
- struct fwnode_handle *handle, int numa_node)
+static int __init its_probe_one(struct its_node *its)
{
- struct its_node *its;
- void __iomem *its_base;
- u64 baser, tmp, typer;
+ u64 baser, tmp;
struct page *page;
u32 ctlr;
int err;
- its_base = its_map_one(res, &err);
- if (!its_base)
- return err;
-
- pr_info("ITS %pR\n", res);
-
- its = kzalloc(sizeof(*its), GFP_KERNEL);
- if (!its) {
- err = -ENOMEM;
- goto out_unmap;
- }
-
- raw_spin_lock_init(&its->lock);
- mutex_init(&its->dev_alloc_lock);
- INIT_LIST_HEAD(&its->entry);
- INIT_LIST_HEAD(&its->its_device_list);
- typer = gic_read_typer(its_base + GITS_TYPER);
- its->typer = typer;
- its->base = its_base;
- its->phys_base = res->start;
if (is_v4(its)) {
- if (!(typer & GITS_TYPER_VMOVP)) {
- err = its_compute_its_list_map(res, its_base);
+ if (!(its->typer & GITS_TYPER_VMOVP)) {
+ err = its_compute_its_list_map(its);
if (err < 0)
- goto out_free_its;
+ goto out;
its->list_nr = err;
pr_info("ITS@%pa: Using ITS number %d\n",
- &res->start, err);
+ &its->phys_base, err);
} else {
- pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
+ pr_info("ITS@%pa: Single VMOVP capable\n", &its->phys_base);
}
if (is_v4_1(its)) {
- u32 svpet = FIELD_GET(GITS_TYPER_SVPET, typer);
+ u32 svpet = FIELD_GET(GITS_TYPER_SVPET, its->typer);
- its->sgir_base = ioremap(res->start + SZ_128K, SZ_64K);
+ its->sgir_base = ioremap(its->phys_base + SZ_128K, SZ_64K);
if (!its->sgir_base) {
err = -ENOMEM;
- goto out_free_its;
+ goto out;
}
- its->mpidr = readl_relaxed(its_base + GITS_MPIDR);
+ its->mpidr = readl_relaxed(its->base + GITS_MPIDR);
pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n",
- &res->start, its->mpidr, svpet);
+ &its->phys_base, its->mpidr, svpet);
}
}
- its->numa_node = numa_node;
-
page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
get_order(ITS_CMD_QUEUE_SZ));
if (!page) {
@@ -5125,12 +5099,9 @@ static int __init its_probe_one(struct resource *res,
}
its->cmd_base = (void *)page_address(page);
its->cmd_write = its->cmd_base;
- its->fwnode_handle = handle;
its->get_msi_base = its_irq_get_msi_base;
its->msi_domain_flags = IRQ_DOMAIN_FLAG_ISOLATED_MSI;
- its_enable_quirks(its);
-
err = its_alloc_tables(its);
if (err)
goto out_free_cmd;
@@ -5174,7 +5145,7 @@ static int __init its_probe_one(struct resource *res,
ctlr |= GITS_CTLR_ImDe;
writel_relaxed(ctlr, its->base + GITS_CTLR);
- err = its_init_domain(handle, its);
+ err = its_init_domain(its);
if (err)
goto out_free_tables;
@@ -5191,11 +5162,8 @@ static int __init its_probe_one(struct resource *res,
out_unmap_sgir:
if (its->sgir_base)
iounmap(its->sgir_base);
-out_free_its:
- kfree(its);
-out_unmap:
- iounmap(its_base);
- pr_err("ITS@%pa: failed probing (%d)\n", &res->start, err);
+out:
+ pr_err("ITS@%pa: failed probing (%d)\n", &its->phys_base, err);
return err;
}
@@ -5356,10 +5324,53 @@ static const struct of_device_id its_device_id[] = {
{},
};
+static struct its_node __init *its_node_init(struct resource *res,
+ struct fwnode_handle *handle, int numa_node)
+{
+ void __iomem *its_base;
+ struct its_node *its;
+ int err;
+
+ its_base = its_map_one(res, &err);
+ if (!its_base)
+ return NULL;
+
+ pr_info("ITS %pR\n", res);
+
+ its = kzalloc(sizeof(*its), GFP_KERNEL);
+ if (!its)
+ goto out_unmap;
+
+ raw_spin_lock_init(&its->lock);
+ mutex_init(&its->dev_alloc_lock);
+ INIT_LIST_HEAD(&its->entry);
+ INIT_LIST_HEAD(&its->its_device_list);
+
+ its->typer = gic_read_typer(its_base + GITS_TYPER);
+ its->base = its_base;
+ its->phys_base = res->start;
+
+ its->numa_node = numa_node;
+ its->fwnode_handle = handle;
+
+ return its;
+
+out_unmap:
+ iounmap(its_base);
+ return NULL;
+}
+
+static void its_node_destroy(struct its_node *its)
+{
+ iounmap(its->base);
+ kfree(its);
+}
+
static int __init its_of_probe(struct device_node *node)
{
struct device_node *np;
struct resource res;
+ int err;
/*
* Make sure *all* the ITS are reset before we probe any, as
@@ -5369,8 +5380,6 @@ static int __init its_of_probe(struct device_node *node)
*/
for (np = of_find_matching_node(node, its_device_id); np;
np = of_find_matching_node(np, its_device_id)) {
- int err;
-
if (!of_device_is_available(np) ||
!of_property_read_bool(np, "msi-controller") ||
of_address_to_resource(np, 0, &res))
@@ -5383,6 +5392,8 @@ static int __init its_of_probe(struct device_node *node)
for (np = of_find_matching_node(node, its_device_id); np;
np = of_find_matching_node(np, its_device_id)) {
+ struct its_node *its;
+
if (!of_device_is_available(np))
continue;
if (!of_property_read_bool(np, "msi-controller")) {
@@ -5396,7 +5407,17 @@ static int __init its_of_probe(struct device_node *node)
continue;
}
- its_probe_one(&res, &np->fwnode, of_node_to_nid(np));
+
+ its = its_node_init(&res, &np->fwnode, of_node_to_nid(np));
+ if (!its)
+ return -ENOMEM;
+
+ its_enable_quirks(its);
+ err = its_probe_one(its);
+ if (err) {
+ its_node_destroy(its);
+ return err;
+ }
}
return 0;
}
@@ -5508,6 +5529,7 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
{
struct acpi_madt_generic_translator *its_entry;
struct fwnode_handle *dom_handle;
+ struct its_node *its;
struct resource res;
int err;
@@ -5532,11 +5554,20 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
goto dom_err;
}
- err = its_probe_one(&res, dom_handle,
- acpi_get_its_numa_node(its_entry->translation_id));
+ its = its_node_init(&res, dom_handle,
+ acpi_get_its_numa_node(its_entry->translation_id));
+ if (!its) {
+ err = -ENOMEM;
+ goto node_err;
+ }
+
+ /* Stick ACPI quirk handling here */
+
+ err = its_probe_one(its);
if (!err)
return 0;
+node_err:
iort_deregister_domain_token(its_entry->translation_id);
dom_err:
irq_domain_free_fwnode(dom_handle);
--
2.34.1
--
Without deviation from the norm, progress is not possible.
next prev parent reply other threads:[~2023-10-03 16:45 UTC|newest]
Thread overview: 117+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-05 10:47 [PATCH 0/2] irqchip/gic-v3: Enable non-coherent GIC designs probing Lorenzo Pieralisi
2023-09-05 10:47 ` Lorenzo Pieralisi
2023-09-05 10:47 ` [PATCH 1/2] dt-bindings: interrupt-controller: arm,gic-v3: Add dma-noncoherent property Lorenzo Pieralisi
2023-09-05 10:47 ` Lorenzo Pieralisi
2023-09-05 11:17 ` Robin Murphy
2023-09-05 11:17 ` Robin Murphy
2023-09-05 12:22 ` Lorenzo Pieralisi
2023-09-05 12:22 ` Lorenzo Pieralisi
2023-09-05 12:57 ` Robin Murphy
2023-09-05 12:57 ` Robin Murphy
2023-09-05 18:23 ` Rob Herring
2023-09-05 18:23 ` Rob Herring
2023-09-05 10:47 ` [PATCH 2/2] irqchip/gic-v3: Enable non-coherent redistributors/ITSes probing Lorenzo Pieralisi
2023-09-05 10:47 ` Lorenzo Pieralisi
2023-09-05 11:34 ` Marc Zyngier
2023-09-05 11:34 ` Marc Zyngier
2023-09-05 12:14 ` Robin Murphy
2023-09-05 12:14 ` Robin Murphy
2023-09-05 12:30 ` Lorenzo Pieralisi
2023-09-05 12:30 ` Lorenzo Pieralisi
2023-09-05 12:41 ` Marc Zyngier
2023-09-05 12:41 ` Marc Zyngier
2023-09-05 14:24 ` Lorenzo Pieralisi
2023-09-05 14:24 ` Lorenzo Pieralisi
2023-09-05 14:34 ` Marc Zyngier
2023-09-05 14:34 ` Marc Zyngier
2023-09-06 11:01 ` Fang Xiang
2023-09-06 11:01 ` Fang Xiang
2023-09-06 11:10 ` Marc Zyngier
2023-10-03 14:43 ` Lorenzo Pieralisi
2023-10-03 14:43 ` Lorenzo Pieralisi
2023-10-03 16:18 ` Robin Murphy
2023-10-03 16:18 ` Robin Murphy
2023-10-03 16:44 ` Marc Zyngier [this message]
2023-10-03 16:44 ` Marc Zyngier
2023-10-04 7:13 ` Lorenzo Pieralisi
2023-10-04 7:13 ` Lorenzo Pieralisi
2023-10-05 13:59 ` Lorenzo Pieralisi
2023-10-05 13:59 ` Lorenzo Pieralisi
2023-09-06 9:41 ` [PATCH v2 0/2] irqchip/gic-v3: Enable non-coherent GIC designs probing Lorenzo Pieralisi
2023-09-06 9:41 ` Lorenzo Pieralisi
2023-09-06 9:41 ` [PATCH v2 1/2] dt-bindings: interrupt-controller: arm,gic-v3: Add dma-noncoherent property Lorenzo Pieralisi
2023-09-06 9:41 ` Lorenzo Pieralisi
2023-09-06 11:23 ` Rob Herring
2023-09-06 11:23 ` Rob Herring
2023-09-06 11:27 ` Lorenzo Pieralisi
2023-09-06 11:27 ` Lorenzo Pieralisi
2023-09-06 9:41 ` [PATCH v2 2/2] irqchip/gic-v3: Enable non-coherent redistributors/ITSes probing Lorenzo Pieralisi
2023-09-06 9:41 ` Lorenzo Pieralisi
2023-09-06 9:52 ` [PATCH v2 0/2] irqchip/gic-v3: Enable non-coherent GIC designs probing Marc Zyngier
2023-09-06 9:52 ` Marc Zyngier
2023-09-06 11:23 ` Lorenzo Pieralisi
2023-09-06 11:23 ` Lorenzo Pieralisi
2023-09-21 10:11 ` Lorenzo Pieralisi
2023-09-21 10:11 ` Lorenzo Pieralisi
2023-10-06 12:59 ` [PATCH v3 0/5] " Lorenzo Pieralisi
2023-10-06 12:59 ` Lorenzo Pieralisi
2023-10-06 12:59 ` [PATCH v3 1/5] dt-bindings: interrupt-controller: arm,gic-v3: Add dma-noncoherent property Lorenzo Pieralisi
2023-10-06 12:59 ` Lorenzo Pieralisi
2023-10-07 12:00 ` [irqchip: irq/irqchip-fixes] " irqchip-bot for Lorenzo Pieralisi
2023-10-06 12:59 ` [PATCH v3 2/5] irqchip/gic-v3: Enable non-coherent redistributors/ITSes DT probing Lorenzo Pieralisi
2023-10-06 12:59 ` Lorenzo Pieralisi
2023-10-07 12:00 ` [irqchip: irq/irqchip-fixes] " irqchip-bot for Lorenzo Pieralisi
2023-10-06 12:59 ` [PATCH v3 3/5] irqchip/gic-v3-its: Split allocation from initialisation of its_node Lorenzo Pieralisi
2023-10-06 12:59 ` Lorenzo Pieralisi
2023-10-07 12:00 ` [irqchip: irq/irqchip-fixes] " irqchip-bot for Marc Zyngier
2023-10-24 8:48 ` [PATCH v3 3/5] " Dominic Rath
2023-10-24 8:48 ` Dominic Rath
2023-10-24 10:18 ` Marc Zyngier
2023-10-24 10:18 ` Marc Zyngier
2023-10-24 13:13 ` Dominic Rath
2023-10-24 13:13 ` Dominic Rath
2023-10-25 19:51 ` [tip: irq/urgent] irqchip/gic-v3-its: Don't override quirk settings with default values tip-bot2 for Marc Zyngier
2023-10-06 12:59 ` [PATCH v3 4/5] ACPICA: Add new MADT GICC/GICR/ITS flags handling [code first] Lorenzo Pieralisi
2023-10-06 12:59 ` Lorenzo Pieralisi
2023-10-06 12:59 ` [PATCH v3 5/5] irqchip/gic-v3: Enable non-coherent redistributors/ITSes ACPI probing Lorenzo Pieralisi
2023-10-06 12:59 ` Lorenzo Pieralisi
2023-10-17 14:19 ` Lorenzo Pieralisi
2023-10-17 14:19 ` Lorenzo Pieralisi
2023-10-17 16:44 ` Marc Zyngier
2023-10-17 16:44 ` Marc Zyngier
2023-10-18 8:42 ` Lorenzo Pieralisi
2023-10-18 8:42 ` Lorenzo Pieralisi
2023-10-19 11:12 ` Marc Zyngier
2023-10-19 11:12 ` Marc Zyngier
2023-12-27 11:00 ` [PATCH v4 0/3] irqchip/gic-v3: Enable non-coherent GIC designs probing Lorenzo Pieralisi
2023-12-27 11:00 ` Lorenzo Pieralisi
2023-12-27 11:00 ` [PATCH v4 1/3] ACPICA: MADT: Add GICC online capable bit handling Lorenzo Pieralisi
2023-12-27 11:00 ` Lorenzo Pieralisi
2024-01-09 14:27 ` Rafael J. Wysocki
2024-01-09 14:27 ` Rafael J. Wysocki
2023-12-27 11:00 ` [PATCH v4 2/3] ACPICA: MADT: Add new MADT GICC/GICR/ITS non-coherent flags handling Lorenzo Pieralisi
2023-12-27 11:00 ` Lorenzo Pieralisi
2023-12-27 11:00 ` [PATCH v4 3/3] irqchip/gic-v3: Enable non-coherent redistributors/ITSes ACPI probing Lorenzo Pieralisi
2023-12-27 11:00 ` Lorenzo Pieralisi
2024-01-04 11:12 ` Marc Zyngier
2024-01-04 11:12 ` Marc Zyngier
2024-01-08 9:43 ` Lorenzo Pieralisi
2024-01-08 9:43 ` Lorenzo Pieralisi
2024-01-08 9:52 ` Marc Zyngier
2024-01-08 9:52 ` Marc Zyngier
2024-01-22 16:18 ` Lorenzo Pieralisi
2024-01-22 16:18 ` Lorenzo Pieralisi
2024-01-22 18:27 ` Marc Zyngier
2024-01-22 18:27 ` Marc Zyngier
2024-01-03 13:43 ` [PATCH v4 0/3] irqchip/gic-v3: Enable non-coherent GIC designs probing Rafael J. Wysocki
2024-01-03 13:43 ` Rafael J. Wysocki
2024-01-04 11:34 ` Marc Zyngier
2024-01-04 11:34 ` Marc Zyngier
2024-01-04 12:04 ` Russell King (Oracle)
2024-01-04 12:04 ` Russell King (Oracle)
2024-01-04 13:21 ` Rafael J. Wysocki
2024-01-04 13:21 ` Rafael J. Wysocki
2024-01-04 13:47 ` Russell King (Oracle)
2024-01-04 13:47 ` Russell King (Oracle)
2024-01-08 9:45 ` Lorenzo Pieralisi
2024-01-08 9:45 ` Lorenzo Pieralisi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=86r0mboduc.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=fangxiang3@xiaomi.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lpieralisi@kernel.org \
--cc=mark.rutland@arm.com \
--cc=robh+dt@kernel.org \
--cc=robin.murphy@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.