Commit bb160e79 authored by Harini T's avatar Harini T Committed by Jassi Brar
Browse files

mailbox: zynqmp-ipi: Fix SGI cleanup on unbind



The driver incorrectly determines SGI vs SPI interrupts by checking IRQ
number < 16, which fails with dynamic IRQ allocation. During unbind,
this causes improper SGI cleanup leading to kernel crash.

Add explicit irq_type field to pdata for reliable identification of SGI
interrupts (type-2) and only clean up SGI resources when appropriate.

Fixes: 6ffb1635 ("mailbox: zynqmp: handle SGI for shared IPI")
Signed-off-by: default avatarHarini T <harini.t@amd.com>
Reviewed-by: default avatarPeng Fan <peng.fan@nxp.com>
Signed-off-by: default avatarJassi Brar <jassisinghbrar@gmail.com>
parent 0aead819
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -62,7 +62,8 @@
#define DST_BIT_POS	9U
#define SRC_BITMASK	GENMASK(11, 8)

#define MAX_SGI 16
/* Macro to represent SGI type for IPI IRQs */
#define IPI_IRQ_TYPE_SGI	2

/*
 * Module parameters
@@ -121,6 +122,7 @@ struct zynqmp_ipi_mbox {
 * @dev:                  device pointer corresponding to the Xilinx ZynqMP
 *                        IPI agent
 * @irq:                  IPI agent interrupt ID
 * @irq_type:             IPI SGI or SPI IRQ type
 * @method:               IPI SMC or HVC is going to be used
 * @local_id:             local IPI agent ID
 * @virq_sgi:             IRQ number mapped to SGI
@@ -130,6 +132,7 @@ struct zynqmp_ipi_mbox {
struct zynqmp_ipi_pdata {
	struct device *dev;
	int irq;
	unsigned int irq_type;
	unsigned int method;
	u32 local_id;
	int virq_sgi;
@@ -887,7 +890,7 @@ static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata)
	struct zynqmp_ipi_mbox *ipi_mbox;
	int i;

	if (pdata->irq < MAX_SGI)
	if (pdata->irq_type == IPI_IRQ_TYPE_SGI)
		xlnx_mbox_cleanup_sgi(pdata);

	i = pdata->num_mboxes - 1;
@@ -956,14 +959,16 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
		dev_err(dev, "failed to parse interrupts\n");
		goto free_mbox_dev;
	}
	ret = out_irq.args[1];

	/* Use interrupt type to distinguish SGI and SPI interrupts */
	pdata->irq_type = out_irq.args[0];

	/*
	 * If Interrupt number is in SGI range, then request SGI else request
	 * IPI system IRQ.
	 */
	if (ret < MAX_SGI) {
		pdata->irq = ret;
	if (pdata->irq_type == IPI_IRQ_TYPE_SGI) {
		pdata->irq = out_irq.args[1];
		ret = xlnx_mbox_init_sgi(pdev, pdata->irq, pdata);
		if (ret)
			goto free_mbox_dev;