mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
Miscellaneous irqchip driver fixes:
- Fix frozen interrupt bug in the sifive-plic driver
- Limit per-device MSI interrupts on uncommon gic-v3-its
hardware variants
- Address Sparse warning by constifying a variable in
the MMP driver
- Revert broken commit and also fix an error check
in the ls-extirq driver
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmmj/MMRHG1pbmdvQGtl
cm5lbC5vcmcACgkQEnMQ0APhK1iRdg//eKX6ScDG6IT/hzKHBVP9tGqFcvfR+LWf
3Q5I/5YipYNf2aqZS7UFcfhsOvMkwALF55CrNUCFatW2W4VAUR5pgt5JWNfMS4VO
+9sGkkAhUenhLlGgGnIpuIHgIrkJFCqhQIy2pwMpVF5Sp/7jzJfIwonYziv3UUyD
cWhv6zQULWFMzkLOjBC8Ba44gIfSSq6wERE0JZiE2aZMJ3Azjh+prKwkH5Q48adb
Ni7b19wFFLDSvv8KGzpoFrA3S5Wwzppy4YJpTEKGXUq9AQr08BUtv2KNeLz660ma
pWD9ZzPnclxUiWhmAdi3x+vmn8209Id3pYRGD2auZlT0+7cE1yvyFNl30IWwac5K
IoGQ54F3nWYynT6ScYNJilKlN/kDDX6Azt1AELl+fHhOvp5VpjxlDpiUahvqJGpX
bhNo1GC8fQSZFKehA987IZol1vp9z2utqxEQhm0hZX4FhIRaS8LfUa1e7A66FZ1Q
cp+Hz/8oYczZAEb3vXNdEVkhtIFTzS90uRhrjaRLlO67Yo/0xWxwP34DuBv8MiL7
XWK+rj3TSxYR3U6cAIAkU0bft+XFIVI8fKc92duE2Cx5Nx2s0gHRYsM/F2lFrhIw
jETLC60lWj1Sf1HP03VKi7EjFht6qSVs4PgPVYopZtn94eXV+HK+sZ5CmkxqgfFT
OYpG1VbMxEU=
=hIKS
-----END PGP SIGNATURE-----
Merge tag 'irq-urgent-2026-03-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irqchip driver fixes from Ingo Molnar:
- Fix frozen interrupt bug in the sifive-plic driver
- Limit per-device MSI interrupts on uncommon gic-v3-its hardware
variants
- Address Sparse warning by constifying a variable in the MMP driver
- Revert broken commit and also fix an error check in the ls-extirq
driver
* tag 'irq-urgent-2026-03-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
irqchip/ls-extirq: Fix devm_of_iomap() error check
Revert "irqchip/ls-extirq: Use for_each_of_imap_item iterator"
irqchip/mmp: Make icu_irq_chip variable static const
irqchip/gic-v3-its: Limit number of per-device MSIs to the range the ITS supports
irqchip/sifive-plic: Fix frozen interrupt due to affinity setting
This commit is contained in:
commit
afa844360b
5 changed files with 46 additions and 21 deletions
|
|
@ -3474,6 +3474,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
|
|||
int lpi_base;
|
||||
int nr_lpis;
|
||||
int nr_ites;
|
||||
int id_bits;
|
||||
int sz;
|
||||
|
||||
if (!its_alloc_device_table(its, dev_id))
|
||||
|
|
@ -3485,7 +3486,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
|
|||
/*
|
||||
* Even if the device wants a single LPI, the ITT must be
|
||||
* sized as a power of two (and you need at least one bit...).
|
||||
* Also honor the ITS's own EID limit.
|
||||
*/
|
||||
id_bits = FIELD_GET(GITS_TYPER_IDBITS, its->typer) + 1;
|
||||
nvecs = min_t(unsigned int, nvecs, BIT(id_bits));
|
||||
nr_ites = max(2, nvecs);
|
||||
sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
|
||||
sz = max(sz, ITS_ITT_ALIGN);
|
||||
|
|
|
|||
|
|
@ -125,32 +125,45 @@ static const struct irq_domain_ops extirq_domain_ops = {
|
|||
static int
|
||||
ls_extirq_parse_map(struct ls_extirq_data *priv, struct device_node *node)
|
||||
{
|
||||
struct of_imap_parser imap_parser;
|
||||
struct of_imap_item imap_item;
|
||||
const __be32 *map;
|
||||
u32 mapsize;
|
||||
int ret;
|
||||
|
||||
ret = of_imap_parser_init(&imap_parser, node, &imap_item);
|
||||
if (ret)
|
||||
return ret;
|
||||
map = of_get_property(node, "interrupt-map", &mapsize);
|
||||
if (!map)
|
||||
return -ENOENT;
|
||||
if (mapsize % sizeof(*map))
|
||||
return -EINVAL;
|
||||
mapsize /= sizeof(*map);
|
||||
|
||||
for_each_of_imap_item(&imap_parser, &imap_item) {
|
||||
while (mapsize) {
|
||||
struct device_node *ipar;
|
||||
u32 hwirq;
|
||||
int i;
|
||||
u32 hwirq, intsize, j;
|
||||
|
||||
hwirq = imap_item.child_imap[0];
|
||||
if (hwirq >= MAXIRQ) {
|
||||
of_node_put(imap_item.parent_args.np);
|
||||
if (mapsize < 3)
|
||||
return -EINVAL;
|
||||
hwirq = be32_to_cpup(map);
|
||||
if (hwirq >= MAXIRQ)
|
||||
return -EINVAL;
|
||||
}
|
||||
priv->nirq = max(priv->nirq, hwirq + 1);
|
||||
|
||||
ipar = of_node_get(imap_item.parent_args.np);
|
||||
priv->map[hwirq].fwnode = of_fwnode_handle(ipar);
|
||||
ipar = of_find_node_by_phandle(be32_to_cpup(map + 2));
|
||||
map += 3;
|
||||
mapsize -= 3;
|
||||
if (!ipar)
|
||||
return -EINVAL;
|
||||
priv->map[hwirq].fwnode = &ipar->fwnode;
|
||||
ret = of_property_read_u32(ipar, "#interrupt-cells", &intsize);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->map[hwirq].param_count = imap_item.parent_args.args_count;
|
||||
for (i = 0; i < priv->map[hwirq].param_count; i++)
|
||||
priv->map[hwirq].param[i] = imap_item.parent_args.args[i];
|
||||
if (intsize > mapsize)
|
||||
return -EINVAL;
|
||||
|
||||
priv->map[hwirq].param_count = intsize;
|
||||
for (j = 0; j < intsize; ++j)
|
||||
priv->map[hwirq].param[j] = be32_to_cpup(map++);
|
||||
mapsize -= intsize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -177,8 +190,10 @@ static int ls_extirq_probe(struct platform_device *pdev)
|
|||
return dev_err_probe(dev, -ENOMEM, "Failed to allocate memory\n");
|
||||
|
||||
priv->intpcr = devm_of_iomap(dev, node, 0, NULL);
|
||||
if (!priv->intpcr)
|
||||
return dev_err_probe(dev, -ENOMEM, "Cannot ioremap OF node %pOF\n", node);
|
||||
if (IS_ERR(priv->intpcr)) {
|
||||
return dev_err_probe(dev, PTR_ERR(priv->intpcr),
|
||||
"Cannot ioremap OF node %pOF\n", node);
|
||||
}
|
||||
|
||||
ret = ls_extirq_parse_map(priv, node);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ static void icu_unmask_irq(struct irq_data *d)
|
|||
}
|
||||
}
|
||||
|
||||
struct irq_chip icu_irq_chip = {
|
||||
static const struct irq_chip icu_irq_chip = {
|
||||
.name = "icu_irq",
|
||||
.irq_mask = icu_mask_irq,
|
||||
.irq_mask_ack = icu_mask_ack_irq,
|
||||
|
|
|
|||
|
|
@ -172,8 +172,13 @@ static void plic_irq_disable(struct irq_data *d)
|
|||
static void plic_irq_eoi(struct irq_data *d)
|
||||
{
|
||||
struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
|
||||
u32 __iomem *reg;
|
||||
bool enabled;
|
||||
|
||||
if (unlikely(irqd_irq_disabled(d))) {
|
||||
reg = handler->enable_base + (d->hwirq / 32) * sizeof(u32);
|
||||
enabled = readl(reg) & BIT(d->hwirq % 32);
|
||||
|
||||
if (unlikely(!enabled)) {
|
||||
plic_toggle(handler, d->hwirq, 1);
|
||||
writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
|
||||
plic_toggle(handler, d->hwirq, 0);
|
||||
|
|
|
|||
|
|
@ -394,6 +394,7 @@
|
|||
#define GITS_TYPER_VLPIS (1UL << 1)
|
||||
#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT 4
|
||||
#define GITS_TYPER_ITT_ENTRY_SIZE GENMASK_ULL(7, 4)
|
||||
#define GITS_TYPER_IDBITS GENMASK_ULL(12, 8)
|
||||
#define GITS_TYPER_IDBITS_SHIFT 8
|
||||
#define GITS_TYPER_DEVBITS_SHIFT 13
|
||||
#define GITS_TYPER_DEVBITS GENMASK_ULL(17, 13)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue