Commit 147cc583 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'irq-core-2022-01-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq updates from Thomas Gleixner:
 "Updates for the interrupt subsystem:

  Core:

   - Provide a new interface for affinity hints to provide a separation
     between hint and actual affinity change which has become a hidden
     property of the current interface

   - Fix up the in tree usage of the affinity hint interfaces

  Drivers:

   - No new irqchip drivers!

   - Fix GICv3 redistributor table reservation with RT across kexec

   - Fix GICv4.1 redistributor view of the VPE table across kexec

   - Add support for extra interrupts on spear-shirq

   - Make obtaining some interrupts optional for the Renesas drivers

   - Various cleanups and bug fixes"

* tag 'irq-core-2022-01-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (25 commits)
  irqchip/renesas-intc-irqpin: Use platform_get_irq_optional() to get the interrupt
  irqchip/renesas-irqc: Use platform_get_irq_optional() to get the interrupt
  irqchip/gic-v4: Disable redistributors' view of the VPE table at boot time
  irqchip/ingenic-tcu: Use correctly sized arguments for bit field
  irqchip/gic-v2m: Add const to of_device_id
  irqchip/imx-gpcv2: Mark imx_gpcv2_instance with __ro_after_init
  irqchip/spear-shirq: Add support for IRQ 0..6
  irqchip/gic-v3-its: Limit memreserve cpuhp state lifetime
  irqchip/gic-v3-its: Postpone LPI pending table freeing and memreserve
  irqchip/gic-v3-its: Give the percpu rdist struct its own flags field
  net/mlx4: Use irq_update_affinity_hint()
  net/mlx5: Use irq_set_affinity_and_hint()
  hinic: Use irq_set_affinity_and_hint()
  scsi: lpfc: Use irq_set_affinity()
  mailbox: Use irq_update_affinity_hint()
  ixgbe: Use irq_update_affinity_hint()
  be2net: Use irq_update_affinity_hint()
  enic: Use irq_update_affinity_hint()
  RDMA/irdma: Use irq_update_affinity_hint()
  scsi: mpt3sas: Use irq_set_affinity_and_hint()
  ...
parents 455e73a0 67d50b5f
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -550,7 +550,7 @@ static void irdma_destroy_irq(struct irdma_pci_f *rf,
	struct irdma_sc_dev *dev = &rf->sc_dev;
	struct irdma_sc_dev *dev = &rf->sc_dev;


	dev->irq_ops->irdma_dis_irq(dev, msix_vec->idx);
	dev->irq_ops->irdma_dis_irq(dev, msix_vec->idx);
	irq_set_affinity_hint(msix_vec->irq, NULL);
	irq_update_affinity_hint(msix_vec->irq, NULL);
	free_irq(msix_vec->irq, dev_id);
	free_irq(msix_vec->irq, dev_id);
}
}


@@ -1100,7 +1100,7 @@ irdma_cfg_ceq_vector(struct irdma_pci_f *rf, struct irdma_ceq *iwceq,
	}
	}
	cpumask_clear(&msix_vec->mask);
	cpumask_clear(&msix_vec->mask);
	cpumask_set_cpu(msix_vec->cpu_affinity, &msix_vec->mask);
	cpumask_set_cpu(msix_vec->cpu_affinity, &msix_vec->mask);
	irq_set_affinity_hint(msix_vec->irq, &msix_vec->mask);
	irq_update_affinity_hint(msix_vec->irq, &msix_vec->mask);
	if (status) {
	if (status) {
		ibdev_dbg(&rf->iwdev->ibdev, "ERR: ceq irq config fail\n");
		ibdev_dbg(&rf->iwdev->ibdev, "ERR: ceq irq config fail\n");
		return IRDMA_ERR_CFG;
		return IRDMA_ERR_CFG;
+1 −1
Original line number Original line Diff line number Diff line
@@ -405,7 +405,7 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
	return ret;
	return ret;
}
}


static struct of_device_id gicv2m_device_id[] = {
static const struct of_device_id gicv2m_device_id[] = {
	{	.compatible	= "arm,gic-v2m-frame",	},
	{	.compatible	= "arm,gic-v2m-frame",	},
	{},
	{},
};
};
+75 −7
Original line number Original line Diff line number Diff line
@@ -46,6 +46,10 @@
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING	(1 << 0)
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING	(1 << 0)
#define RDIST_FLAGS_RD_TABLES_PREALLOCATED	(1 << 1)
#define RDIST_FLAGS_RD_TABLES_PREALLOCATED	(1 << 1)


#define RD_LOCAL_LPI_ENABLED                    BIT(0)
#define RD_LOCAL_PENDTABLE_PREALLOCATED         BIT(1)
#define RD_LOCAL_MEMRESERVE_DONE                BIT(2)

static u32 lpi_id_bits;
static u32 lpi_id_bits;


/*
/*
@@ -3044,7 +3048,7 @@ static void its_cpu_init_lpis(void)
	phys_addr_t paddr;
	phys_addr_t paddr;
	u64 val, tmp;
	u64 val, tmp;


	if (gic_data_rdist()->lpi_enabled)
	if (gic_data_rdist()->flags & RD_LOCAL_LPI_ENABLED)
		return;
		return;


	val = readl_relaxed(rbase + GICR_CTLR);
	val = readl_relaxed(rbase + GICR_CTLR);
@@ -3063,15 +3067,13 @@ static void its_cpu_init_lpis(void)
		paddr &= GENMASK_ULL(51, 16);
		paddr &= GENMASK_ULL(51, 16);


		WARN_ON(!gic_check_reserved_range(paddr, LPI_PENDBASE_SZ));
		WARN_ON(!gic_check_reserved_range(paddr, LPI_PENDBASE_SZ));
		its_free_pending_table(gic_data_rdist()->pend_page);
		gic_data_rdist()->flags |= RD_LOCAL_PENDTABLE_PREALLOCATED;
		gic_data_rdist()->pend_page = NULL;


		goto out;
		goto out;
	}
	}


	pend_page = gic_data_rdist()->pend_page;
	pend_page = gic_data_rdist()->pend_page;
	paddr = page_to_phys(pend_page);
	paddr = page_to_phys(pend_page);
	WARN_ON(gic_reserve_range(paddr, LPI_PENDBASE_SZ));


	/* set PROPBASE */
	/* set PROPBASE */
	val = (gic_rdists->prop_table_pa |
	val = (gic_rdists->prop_table_pa |
@@ -3158,10 +3160,11 @@ static void its_cpu_init_lpis(void)
	/* Make sure the GIC has seen the above */
	/* Make sure the GIC has seen the above */
	dsb(sy);
	dsb(sy);
out:
out:
	gic_data_rdist()->lpi_enabled = true;
	gic_data_rdist()->flags |= RD_LOCAL_LPI_ENABLED;
	pr_info("GICv3: CPU%d: using %s LPI pending table @%pa\n",
	pr_info("GICv3: CPU%d: using %s LPI pending table @%pa\n",
		smp_processor_id(),
		smp_processor_id(),
		gic_data_rdist()->pend_page ? "allocated" : "reserved",
		gic_data_rdist()->flags & RD_LOCAL_PENDTABLE_PREALLOCATED ?
		"reserved" : "allocated",
		&paddr);
		&paddr);
}
}


@@ -5138,7 +5141,7 @@ static int redist_disable_lpis(void)
	 *
	 *
	 * If running with preallocated tables, there is nothing to do.
	 * If running with preallocated tables, there is nothing to do.
	 */
	 */
	if (gic_data_rdist()->lpi_enabled ||
	if ((gic_data_rdist()->flags & RD_LOCAL_LPI_ENABLED) ||
	    (gic_rdists->flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED))
	    (gic_rdists->flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED))
		return 0;
		return 0;


@@ -5200,6 +5203,51 @@ int its_cpu_init(void)
	return 0;
	return 0;
}
}


static void rdist_memreserve_cpuhp_cleanup_workfn(struct work_struct *work)
{
	cpuhp_remove_state_nocalls(gic_rdists->cpuhp_memreserve_state);
	gic_rdists->cpuhp_memreserve_state = CPUHP_INVALID;
}

static DECLARE_WORK(rdist_memreserve_cpuhp_cleanup_work,
		    rdist_memreserve_cpuhp_cleanup_workfn);

static int its_cpu_memreserve_lpi(unsigned int cpu)
{
	struct page *pend_page;
	int ret = 0;

	/* This gets to run exactly once per CPU */
	if (gic_data_rdist()->flags & RD_LOCAL_MEMRESERVE_DONE)
		return 0;

	pend_page = gic_data_rdist()->pend_page;
	if (WARN_ON(!pend_page)) {
		ret = -ENOMEM;
		goto out;
	}
	/*
	 * If the pending table was pre-programmed, free the memory we
	 * preemptively allocated. Otherwise, reserve that memory for
	 * later kexecs.
	 */
	if (gic_data_rdist()->flags & RD_LOCAL_PENDTABLE_PREALLOCATED) {
		its_free_pending_table(pend_page);
		gic_data_rdist()->pend_page = NULL;
	} else {
		phys_addr_t paddr = page_to_phys(pend_page);
		WARN_ON(gic_reserve_range(paddr, LPI_PENDBASE_SZ));
	}

out:
	/* Last CPU being brought up gets to issue the cleanup */
	if (cpumask_equal(&cpus_booted_once_mask, cpu_possible_mask))
		schedule_work(&rdist_memreserve_cpuhp_cleanup_work);

	gic_data_rdist()->flags |= RD_LOCAL_MEMRESERVE_DONE;
	return ret;
}

static const struct of_device_id its_device_id[] = {
static const struct of_device_id its_device_id[] = {
	{	.compatible	= "arm,gic-v3-its",	},
	{	.compatible	= "arm,gic-v3-its",	},
	{},
	{},
@@ -5383,6 +5431,26 @@ static void __init its_acpi_probe(void)
static void __init its_acpi_probe(void) { }
static void __init its_acpi_probe(void) { }
#endif
#endif


int __init its_lpi_memreserve_init(void)
{
	int state;

	if (!efi_enabled(EFI_CONFIG_TABLES))
		return 0;

	gic_rdists->cpuhp_memreserve_state = CPUHP_INVALID;
	state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
				  "irqchip/arm/gicv3/memreserve:online",
				  its_cpu_memreserve_lpi,
				  NULL);
	if (state < 0)
		return state;

	gic_rdists->cpuhp_memreserve_state = state;

	return 0;
}

int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
		    struct irq_domain *parent_domain)
		    struct irq_domain *parent_domain)
{
{
+17 −0
Original line number Original line Diff line number Diff line
@@ -920,6 +920,22 @@ static int __gic_update_rdist_properties(struct redist_region *region,
{
{
	u64 typer = gic_read_typer(ptr + GICR_TYPER);
	u64 typer = gic_read_typer(ptr + GICR_TYPER);


	/* Boot-time cleanip */
	if ((typer & GICR_TYPER_VLPIS) && (typer & GICR_TYPER_RVPEID)) {
		u64 val;

		/* Deactivate any present vPE */
		val = gicr_read_vpendbaser(ptr + SZ_128K + GICR_VPENDBASER);
		if (val & GICR_VPENDBASER_Valid)
			gicr_write_vpendbaser(GICR_VPENDBASER_PendingLast,
					      ptr + SZ_128K + GICR_VPENDBASER);

		/* Mark the VPE table as invalid */
		val = gicr_read_vpropbaser(ptr + SZ_128K + GICR_VPROPBASER);
		val &= ~GICR_VPROPBASER_4_1_VALID;
		gicr_write_vpropbaser(val, ptr + SZ_128K + GICR_VPROPBASER);
	}

	gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
	gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);


	/* RVPEID implies some form of DirectLPI, no matter what the doc says... :-/ */
	/* RVPEID implies some form of DirectLPI, no matter what the doc says... :-/ */
@@ -1802,6 +1818,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
	if (gic_dist_supports_lpis()) {
	if (gic_dist_supports_lpis()) {
		its_init(handle, &gic_data.rdists, gic_data.domain);
		its_init(handle, &gic_data.rdists, gic_data.domain);
		its_cpu_init();
		its_cpu_init();
		its_lpi_memreserve_init();
	} else {
	} else {
		if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
		if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
			gicv2m_init(handle, gic_data.domain);
			gicv2m_init(handle, gic_data.domain);
+1 −1
Original line number Original line Diff line number Diff line
@@ -26,7 +26,7 @@ struct gpcv2_irqchip_data {
	u32			cpu2wakeup;
	u32			cpu2wakeup;
};
};


static struct gpcv2_irqchip_data *imx_gpcv2_instance;
static struct gpcv2_irqchip_data *imx_gpcv2_instance __ro_after_init;


static void __iomem *gpcv2_idx_to_reg(struct gpcv2_irqchip_data *cd, int i)
static void __iomem *gpcv2_idx_to_reg(struct gpcv2_irqchip_data *cd, int i)
{
{
Loading