Skip to content

Commit 3dfa576

Browse files
author
Marc Zyngier
committed
irqchip/gic-v3-its: Add probing for VLPI properties
Add the probing code for the ITS VLPI support. This includes configuring the ITS number if not supporting the single VMOVP command feature. Reviewed-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
1 parent a13b040 commit 3dfa576

File tree

2 files changed

+72
-4
lines changed

2 files changed

+72
-4
lines changed

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

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ struct its_node {
101101
u32 ite_size;
102102
u32 device_ids;
103103
int numa_node;
104+
bool is_v4;
104105
};
105106

106107
#define ITS_ITT_ALIGN SZ_256
@@ -133,6 +134,14 @@ static DEFINE_SPINLOCK(its_lock);
133134
static struct rdists *gic_rdists;
134135
static struct irq_domain *its_parent;
135136

137+
/*
138+
* We have a maximum number of 16 ITSs in the whole system if we're
139+
* using the ITSList mechanism
140+
*/
141+
#define ITS_LIST_MAX 16
142+
143+
static unsigned long its_list_map;
144+
136145
#define gic_data_rdist() (raw_cpu_ptr(gic_rdists->rdist))
137146
#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
138147

@@ -1679,13 +1688,51 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
16791688
return 0;
16801689
}
16811690

1691+
static int __init its_compute_its_list_map(struct resource *res,
1692+
void __iomem *its_base)
1693+
{
1694+
int its_number;
1695+
u32 ctlr;
1696+
1697+
/*
1698+
* This is assumed to be done early enough that we're
1699+
* guaranteed to be single-threaded, hence no
1700+
* locking. Should this change, we should address
1701+
* this.
1702+
*/
1703+
its_number = find_first_zero_bit(&its_list_map, ITS_LIST_MAX);
1704+
if (its_number >= ITS_LIST_MAX) {
1705+
pr_err("ITS@%pa: No ITSList entry available!\n",
1706+
&res->start);
1707+
return -EINVAL;
1708+
}
1709+
1710+
ctlr = readl_relaxed(its_base + GITS_CTLR);
1711+
ctlr &= ~GITS_CTLR_ITS_NUMBER;
1712+
ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT;
1713+
writel_relaxed(ctlr, its_base + GITS_CTLR);
1714+
ctlr = readl_relaxed(its_base + GITS_CTLR);
1715+
if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) {
1716+
its_number = ctlr & GITS_CTLR_ITS_NUMBER;
1717+
its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT;
1718+
}
1719+
1720+
if (test_and_set_bit(its_number, &its_list_map)) {
1721+
pr_err("ITS@%pa: Duplicate ITSList entry %d\n",
1722+
&res->start, its_number);
1723+
return -EINVAL;
1724+
}
1725+
1726+
return its_number;
1727+
}
1728+
16821729
static int __init its_probe_one(struct resource *res,
16831730
struct fwnode_handle *handle, int numa_node)
16841731
{
16851732
struct its_node *its;
16861733
void __iomem *its_base;
1687-
u32 val;
1688-
u64 baser, tmp;
1734+
u32 val, ctlr;
1735+
u64 baser, tmp, typer;
16891736
int err;
16901737

16911738
its_base = ioremap(res->start, resource_size(res));
@@ -1718,9 +1765,24 @@ static int __init its_probe_one(struct resource *res,
17181765
raw_spin_lock_init(&its->lock);
17191766
INIT_LIST_HEAD(&its->entry);
17201767
INIT_LIST_HEAD(&its->its_device_list);
1768+
typer = gic_read_typer(its_base + GITS_TYPER);
17211769
its->base = its_base;
17221770
its->phys_base = res->start;
1723-
its->ite_size = ((gic_read_typer(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
1771+
its->ite_size = GITS_TYPER_ITT_ENTRY_SIZE(typer);
1772+
its->is_v4 = !!(typer & GITS_TYPER_VLPIS);
1773+
if (its->is_v4) {
1774+
if (!(typer & GITS_TYPER_VMOVP)) {
1775+
err = its_compute_its_list_map(res, its_base);
1776+
if (err < 0)
1777+
goto out_free_its;
1778+
1779+
pr_info("ITS@%pa: Using ITS number %d\n",
1780+
&res->start, err);
1781+
} else {
1782+
pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
1783+
}
1784+
}
1785+
17241786
its->numa_node = numa_node;
17251787

17261788
its->cmd_base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
@@ -1767,7 +1829,8 @@ static int __init its_probe_one(struct resource *res,
17671829
}
17681830

17691831
gits_write_cwriter(0, its->base + GITS_CWRITER);
1770-
writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
1832+
ctlr = readl_relaxed(its->base + GITS_CTLR);
1833+
writel_relaxed(ctlr | GITS_CTLR_ENABLE, its->base + GITS_CTLR);
17711834

17721835
err = its_init_domain(handle, its);
17731836
if (err)

include/linux/irqchip/arm-gic-v3.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,20 @@
235235
#define GITS_TRANSLATER 0x10040
236236

237237
#define GITS_CTLR_ENABLE (1U << 0)
238+
#define GITS_CTLR_ITS_NUMBER_SHIFT 4
239+
#define GITS_CTLR_ITS_NUMBER (0xFU << GITS_CTLR_ITS_NUMBER_SHIFT)
238240
#define GITS_CTLR_QUIESCENT (1U << 31)
239241

240242
#define GITS_TYPER_PLPIS (1UL << 0)
243+
#define GITS_TYPER_VLPIS (1UL << 1)
241244
#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT 4
245+
#define GITS_TYPER_ITT_ENTRY_SIZE(r) ((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
242246
#define GITS_TYPER_IDBITS_SHIFT 8
243247
#define GITS_TYPER_DEVBITS_SHIFT 13
244248
#define GITS_TYPER_DEVBITS(r) ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
245249
#define GITS_TYPER_PTA (1UL << 19)
246250
#define GITS_TYPER_HWCOLLCNT_SHIFT 24
251+
#define GITS_TYPER_VMOVP (1ULL << 37)
247252

248253
#define GITS_IIDR_REV_SHIFT 12
249254
#define GITS_IIDR_REV_MASK (0xf << GITS_IIDR_REV_SHIFT)

0 commit comments

Comments
 (0)