Skip to content

Commit 9585a49

Browse files
author
Marc Zyngier
committed
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 <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 5e5c636 commit 9585a49

File tree

1 file changed

+89
-60
lines changed

1 file changed

+89
-60
lines changed

drivers/irqchip/irq-gic-v3-its.c

Lines changed: 89 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4952,7 +4952,7 @@ static void __init __iomem *its_map_one(struct resource *res, int *err)
49524952
return NULL;
49534953
}
49544954

4955-
static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
4955+
static int its_init_domain(struct its_node *its)
49564956
{
49574957
struct irq_domain *inner_domain;
49584958
struct msi_domain_info *info;
@@ -4966,7 +4966,7 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
49664966

49674967
inner_domain = irq_domain_create_hierarchy(its_parent,
49684968
its->msi_domain_flags, 0,
4969-
handle, &its_domain_ops,
4969+
its->fwnode_handle, &its_domain_ops,
49704970
info);
49714971
if (!inner_domain) {
49724972
kfree(info);
@@ -5017,8 +5017,7 @@ static int its_init_vpe_domain(void)
50175017
return 0;
50185018
}
50195019

5020-
static int __init its_compute_its_list_map(struct resource *res,
5021-
void __iomem *its_base)
5020+
static int __init its_compute_its_list_map(struct its_node *its)
50225021
{
50235022
int its_number;
50245023
u32 ctlr;
@@ -5032,91 +5031,66 @@ static int __init its_compute_its_list_map(struct resource *res,
50325031
its_number = find_first_zero_bit(&its_list_map, GICv4_ITS_LIST_MAX);
50335032
if (its_number >= GICv4_ITS_LIST_MAX) {
50345033
pr_err("ITS@%pa: No ITSList entry available!\n",
5035-
&res->start);
5034+
&its->phys_base);
50365035
return -EINVAL;
50375036
}
50385037

5039-
ctlr = readl_relaxed(its_base + GITS_CTLR);
5038+
ctlr = readl_relaxed(its->base + GITS_CTLR);
50405039
ctlr &= ~GITS_CTLR_ITS_NUMBER;
50415040
ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT;
5042-
writel_relaxed(ctlr, its_base + GITS_CTLR);
5043-
ctlr = readl_relaxed(its_base + GITS_CTLR);
5041+
writel_relaxed(ctlr, its->base + GITS_CTLR);
5042+
ctlr = readl_relaxed(its->base + GITS_CTLR);
50445043
if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) {
50455044
its_number = ctlr & GITS_CTLR_ITS_NUMBER;
50465045
its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT;
50475046
}
50485047

50495048
if (test_and_set_bit(its_number, &its_list_map)) {
50505049
pr_err("ITS@%pa: Duplicate ITSList entry %d\n",
5051-
&res->start, its_number);
5050+
&its->phys_base, its_number);
50525051
return -EINVAL;
50535052
}
50545053

50555054
return its_number;
50565055
}
50575056

5058-
static int __init its_probe_one(struct resource *res,
5059-
struct fwnode_handle *handle, int numa_node)
5057+
static int __init its_probe_one(struct its_node *its)
50605058
{
5061-
struct its_node *its;
5062-
void __iomem *its_base;
5063-
u64 baser, tmp, typer;
5059+
u64 baser, tmp;
50645060
struct page *page;
50655061
u32 ctlr;
50665062
int err;
50675063

5068-
its_base = its_map_one(res, &err);
5069-
if (!its_base)
5070-
return err;
5071-
5072-
pr_info("ITS %pR\n", res);
5073-
5074-
its = kzalloc(sizeof(*its), GFP_KERNEL);
5075-
if (!its) {
5076-
err = -ENOMEM;
5077-
goto out_unmap;
5078-
}
5079-
5080-
raw_spin_lock_init(&its->lock);
5081-
mutex_init(&its->dev_alloc_lock);
5082-
INIT_LIST_HEAD(&its->entry);
5083-
INIT_LIST_HEAD(&its->its_device_list);
5084-
typer = gic_read_typer(its_base + GITS_TYPER);
5085-
its->typer = typer;
5086-
its->base = its_base;
5087-
its->phys_base = res->start;
50885064
if (is_v4(its)) {
5089-
if (!(typer & GITS_TYPER_VMOVP)) {
5090-
err = its_compute_its_list_map(res, its_base);
5065+
if (!(its->typer & GITS_TYPER_VMOVP)) {
5066+
err = its_compute_its_list_map(its);
50915067
if (err < 0)
5092-
goto out_free_its;
5068+
goto out;
50935069

50945070
its->list_nr = err;
50955071

50965072
pr_info("ITS@%pa: Using ITS number %d\n",
5097-
&res->start, err);
5073+
&its->phys_base, err);
50985074
} else {
5099-
pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
5075+
pr_info("ITS@%pa: Single VMOVP capable\n", &its->phys_base);
51005076
}
51015077

51025078
if (is_v4_1(its)) {
5103-
u32 svpet = FIELD_GET(GITS_TYPER_SVPET, typer);
5079+
u32 svpet = FIELD_GET(GITS_TYPER_SVPET, its->typer);
51045080

5105-
its->sgir_base = ioremap(res->start + SZ_128K, SZ_64K);
5081+
its->sgir_base = ioremap(its->phys_base + SZ_128K, SZ_64K);
51065082
if (!its->sgir_base) {
51075083
err = -ENOMEM;
5108-
goto out_free_its;
5084+
goto out;
51095085
}
51105086

5111-
its->mpidr = readl_relaxed(its_base + GITS_MPIDR);
5087+
its->mpidr = readl_relaxed(its->base + GITS_MPIDR);
51125088

51135089
pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n",
5114-
&res->start, its->mpidr, svpet);
5090+
&its->phys_base, its->mpidr, svpet);
51155091
}
51165092
}
51175093

5118-
its->numa_node = numa_node;
5119-
51205094
page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
51215095
get_order(ITS_CMD_QUEUE_SZ));
51225096
if (!page) {
@@ -5125,12 +5099,9 @@ static int __init its_probe_one(struct resource *res,
51255099
}
51265100
its->cmd_base = (void *)page_address(page);
51275101
its->cmd_write = its->cmd_base;
5128-
its->fwnode_handle = handle;
51295102
its->get_msi_base = its_irq_get_msi_base;
51305103
its->msi_domain_flags = IRQ_DOMAIN_FLAG_ISOLATED_MSI;
51315104

5132-
its_enable_quirks(its);
5133-
51345105
err = its_alloc_tables(its);
51355106
if (err)
51365107
goto out_free_cmd;
@@ -5174,7 +5145,7 @@ static int __init its_probe_one(struct resource *res,
51745145
ctlr |= GITS_CTLR_ImDe;
51755146
writel_relaxed(ctlr, its->base + GITS_CTLR);
51765147

5177-
err = its_init_domain(handle, its);
5148+
err = its_init_domain(its);
51785149
if (err)
51795150
goto out_free_tables;
51805151

@@ -5191,11 +5162,8 @@ static int __init its_probe_one(struct resource *res,
51915162
out_unmap_sgir:
51925163
if (its->sgir_base)
51935164
iounmap(its->sgir_base);
5194-
out_free_its:
5195-
kfree(its);
5196-
out_unmap:
5197-
iounmap(its_base);
5198-
pr_err("ITS@%pa: failed probing (%d)\n", &res->start, err);
5165+
out:
5166+
pr_err("ITS@%pa: failed probing (%d)\n", &its->phys_base, err);
51995167
return err;
52005168
}
52015169

@@ -5356,10 +5324,53 @@ static const struct of_device_id its_device_id[] = {
53565324
{},
53575325
};
53585326

5327+
static struct its_node __init *its_node_init(struct resource *res,
5328+
struct fwnode_handle *handle, int numa_node)
5329+
{
5330+
void __iomem *its_base;
5331+
struct its_node *its;
5332+
int err;
5333+
5334+
its_base = its_map_one(res, &err);
5335+
if (!its_base)
5336+
return NULL;
5337+
5338+
pr_info("ITS %pR\n", res);
5339+
5340+
its = kzalloc(sizeof(*its), GFP_KERNEL);
5341+
if (!its)
5342+
goto out_unmap;
5343+
5344+
raw_spin_lock_init(&its->lock);
5345+
mutex_init(&its->dev_alloc_lock);
5346+
INIT_LIST_HEAD(&its->entry);
5347+
INIT_LIST_HEAD(&its->its_device_list);
5348+
5349+
its->typer = gic_read_typer(its_base + GITS_TYPER);
5350+
its->base = its_base;
5351+
its->phys_base = res->start;
5352+
5353+
its->numa_node = numa_node;
5354+
its->fwnode_handle = handle;
5355+
5356+
return its;
5357+
5358+
out_unmap:
5359+
iounmap(its_base);
5360+
return NULL;
5361+
}
5362+
5363+
static void its_node_destroy(struct its_node *its)
5364+
{
5365+
iounmap(its->base);
5366+
kfree(its);
5367+
}
5368+
53595369
static int __init its_of_probe(struct device_node *node)
53605370
{
53615371
struct device_node *np;
53625372
struct resource res;
5373+
int err;
53635374

53645375
/*
53655376
* 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)
53695380
*/
53705381
for (np = of_find_matching_node(node, its_device_id); np;
53715382
np = of_find_matching_node(np, its_device_id)) {
5372-
int err;
5373-
53745383
if (!of_device_is_available(np) ||
53755384
!of_property_read_bool(np, "msi-controller") ||
53765385
of_address_to_resource(np, 0, &res))
@@ -5383,6 +5392,8 @@ static int __init its_of_probe(struct device_node *node)
53835392

53845393
for (np = of_find_matching_node(node, its_device_id); np;
53855394
np = of_find_matching_node(np, its_device_id)) {
5395+
struct its_node *its;
5396+
53865397
if (!of_device_is_available(np))
53875398
continue;
53885399
if (!of_property_read_bool(np, "msi-controller")) {
@@ -5396,7 +5407,17 @@ static int __init its_of_probe(struct device_node *node)
53965407
continue;
53975408
}
53985409

5399-
its_probe_one(&res, &np->fwnode, of_node_to_nid(np));
5410+
5411+
its = its_node_init(&res, &np->fwnode, of_node_to_nid(np));
5412+
if (!its)
5413+
return -ENOMEM;
5414+
5415+
its_enable_quirks(its);
5416+
err = its_probe_one(its);
5417+
if (err) {
5418+
its_node_destroy(its);
5419+
return err;
5420+
}
54005421
}
54015422
return 0;
54025423
}
@@ -5508,6 +5529,7 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
55085529
{
55095530
struct acpi_madt_generic_translator *its_entry;
55105531
struct fwnode_handle *dom_handle;
5532+
struct its_node *its;
55115533
struct resource res;
55125534
int err;
55135535

@@ -5532,11 +5554,18 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
55325554
goto dom_err;
55335555
}
55345556

5535-
err = its_probe_one(&res, dom_handle,
5536-
acpi_get_its_numa_node(its_entry->translation_id));
5557+
its = its_node_init(&res, dom_handle,
5558+
acpi_get_its_numa_node(its_entry->translation_id));
5559+
if (!its) {
5560+
err = -ENOMEM;
5561+
goto node_err;
5562+
}
5563+
5564+
err = its_probe_one(its);
55375565
if (!err)
55385566
return 0;
55395567

5568+
node_err:
55405569
iort_deregister_domain_token(its_entry->translation_id);
55415570
dom_err:
55425571
irq_domain_free_fwnode(dom_handle);

0 commit comments

Comments
 (0)