Commit afa84436 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 39c63326 fe5669e3
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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);
+34 −19
Original line number Diff line number Diff line
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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,
+6 −1
Original line number Diff line number Diff line
@@ -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;

	reg = handler->enable_base + (d->hwirq / 32) * sizeof(u32);
	enabled = readl(reg) & BIT(d->hwirq % 32);

	if (unlikely(irqd_irq_disabled(d))) {
	if (unlikely(!enabled)) {
		plic_toggle(handler, d->hwirq, 1);
		writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
		plic_toggle(handler, d->hwirq, 0);
+1 −0
Original line number Diff line number Diff line
@@ -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)