Commit 1e3e330c authored by Johan Hovold's avatar Johan Hovold Committed by Thomas Gleixner
Browse files

irqchip: Pass platform device to platform drivers



The IRQCHIP_PLATFORM_DRIVER macros can be used to convert OF irqchip
drivers to platform drivers but currently reuse the OF init callback
prototype that only takes OF nodes as arguments. This forces drivers to
do reverse lookups of their struct devices during probe if they need
them for things like dev_printk() and device managed resources.

Half of the drivers doing reverse lookups also currently fail to release
the additional reference taken during the lookup, while other drivers
have had the reference leak plugged in various ways (e.g. using
non-intuitive cleanup constructs which still confuse static checkers).

Switch to using a probe callback that takes a platform device as its
first argument to simplify drivers and plug the remaining (mostly
benign) reference leaks.

Fixes: 32c6c054 ("irqchip: Add Broadcom BCM2712 MSI-X interrupt controller")
Fixes: 70afdab9 ("irqchip: Add IMX MU MSI controller driver")
Fixes: a6199bb5 ("irqchip: Add Qualcomm MPM controller driver")
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarFlorian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: default avatarChanghuang Liang <changhuang.liang@starfivetech.com>
parent 3540d99c
Loading
Loading
Loading
Loading
+3 −7
Original line number Diff line number Diff line
@@ -232,16 +232,12 @@ static int mip_parse_dt(struct mip_priv *mip, struct device_node *np)
	return ret;
}

static int mip_of_msi_init(struct device_node *node, struct device_node *parent)
static int mip_msi_probe(struct platform_device *pdev, struct device_node *parent)
{
	struct platform_device *pdev;
	struct device_node *node = pdev->dev.of_node;
	struct mip_priv *mip;
	int ret;

	pdev = of_find_device_by_node(node);
	if (!pdev)
		return -EPROBE_DEFER;

	mip = kzalloc(sizeof(*mip), GFP_KERNEL);
	if (!mip)
		return -ENOMEM;
@@ -284,7 +280,7 @@ static int mip_of_msi_init(struct device_node *node, struct device_node *parent)
}

IRQCHIP_PLATFORM_DRIVER_BEGIN(mip_msi)
IRQCHIP_MATCH("brcm,bcm2712-mip", mip_of_msi_init)
IRQCHIP_MATCH("brcm,bcm2712-mip", mip_msi_probe)
IRQCHIP_PLATFORM_DRIVER_END(mip_msi)
MODULE_DESCRIPTION("Broadcom BCM2712 MSI-X interrupt controller");
MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
+3 −2
Original line number Diff line number Diff line
@@ -394,8 +394,9 @@ static const struct irq_domain_ops bcm7038_l1_domain_ops = {
	.map			= bcm7038_l1_map,
};

static int bcm7038_l1_of_init(struct device_node *dn, struct device_node *parent)
static int bcm7038_l1_probe(struct platform_device *pdev, struct device_node *parent)
{
	struct device_node *dn = pdev->dev.of_node;
	struct bcm7038_l1_chip *intc;
	int idx, ret;

@@ -453,7 +454,7 @@ static int bcm7038_l1_of_init(struct device_node *dn, struct device_node *parent
}

IRQCHIP_PLATFORM_DRIVER_BEGIN(bcm7038_l1)
IRQCHIP_MATCH("brcm,bcm7038-l1-intc", bcm7038_l1_of_init)
IRQCHIP_MATCH("brcm,bcm7038-l1-intc", bcm7038_l1_probe)
IRQCHIP_PLATFORM_DRIVER_END(bcm7038_l1)
MODULE_DESCRIPTION("Broadcom STB 7038-style L1/L2 interrupt controller");
MODULE_LICENSE("GPL v2");
+6 −14
Original line number Diff line number Diff line
@@ -206,14 +206,14 @@ static int bcm7120_l2_intc_iomap_3380(struct device_node *dn, struct bcm7120_l2_
	return 0;
}

static int bcm7120_l2_intc_probe(struct device_node *dn, struct device_node *parent,
static int bcm7120_l2_intc_probe(struct platform_device *pdev, struct device_node *parent,
				 int (*iomap_regs_fn)(struct device_node *,
						      struct bcm7120_l2_intc_data *),
				 const char *intc_name)
{
	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
	struct device_node *dn = pdev->dev.of_node;
	struct bcm7120_l2_intc_data *data;
	struct platform_device *pdev;
	struct irq_chip_generic *gc;
	struct irq_chip_type *ct;
	int ret = 0;
@@ -224,14 +224,7 @@ static int bcm7120_l2_intc_probe(struct device_node *dn, struct device_node *par
	if (!data)
		return -ENOMEM;

	pdev = of_find_device_by_node(dn);
	if (!pdev) {
		ret = -ENODEV;
		goto out_free_data;
	}

	data->num_parent_irqs = platform_irq_count(pdev);
	put_device(&pdev->dev);
	if (data->num_parent_irqs <= 0) {
		pr_err("invalid number of parent interrupts\n");
		ret = -ENOMEM;
@@ -331,20 +324,19 @@ static int bcm7120_l2_intc_probe(struct device_node *dn, struct device_node *par
		if (data->map_base[idx])
			iounmap(data->map_base[idx]);
	}
out_free_data:
	kfree(data);
	return ret;
}

static int bcm7120_l2_intc_probe_7120(struct device_node *dn, struct device_node *parent)
static int bcm7120_l2_intc_probe_7120(struct platform_device *pdev, struct device_node *parent)
{
	return bcm7120_l2_intc_probe(dn, parent, bcm7120_l2_intc_iomap_7120,
	return bcm7120_l2_intc_probe(pdev, parent, bcm7120_l2_intc_iomap_7120,
				     "BCM7120 L2");
}

static int bcm7120_l2_intc_probe_3380(struct device_node *dn, struct device_node *parent)
static int bcm7120_l2_intc_probe_3380(struct platform_device *pdev, struct device_node *parent)
{
	return bcm7120_l2_intc_probe(dn, parent, bcm7120_l2_intc_iomap_3380,
	return bcm7120_l2_intc_probe(pdev, parent, bcm7120_l2_intc_iomap_3380,
				     "BCM3380 L2");
}

+11 −10
Original line number Diff line number Diff line
@@ -138,11 +138,12 @@ static void brcmstb_l2_intc_resume(struct irq_data *d)
	irq_reg_writel(gc, ~b->saved_mask, ct->regs.enable);
}

static int brcmstb_l2_intc_of_init(struct device_node *np, struct device_node *parent,
static int brcmstb_l2_intc_probe(struct platform_device *pdev, struct device_node *parent,
				 const struct brcmstb_intc_init_params *init_params)
{
	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
	unsigned int set = 0;
	struct device_node *np = pdev->dev.of_node;
	struct brcmstb_l2_intc_data *data;
	struct irq_chip_type *ct;
	int ret;
@@ -255,21 +256,21 @@ static int brcmstb_l2_intc_of_init(struct device_node *np, struct device_node *p
	return ret;
}

static int brcmstb_l2_edge_intc_of_init(struct device_node *np, struct device_node *parent)
static int brcmstb_l2_edge_intc_probe(struct platform_device *pdev, struct device_node *parent)
{
	return brcmstb_l2_intc_of_init(np, parent, &l2_edge_intc_init);
	return brcmstb_l2_intc_probe(pdev, parent, &l2_edge_intc_init);
}

static int brcmstb_l2_lvl_intc_of_init(struct device_node *np, struct device_node *parent)
static int brcmstb_l2_lvl_intc_probe(struct platform_device *pdev, struct device_node *parent)
{
	return brcmstb_l2_intc_of_init(np, parent, &l2_lvl_intc_init);
	return brcmstb_l2_intc_probe(pdev, parent, &l2_lvl_intc_init);
}

IRQCHIP_PLATFORM_DRIVER_BEGIN(brcmstb_l2)
IRQCHIP_MATCH("brcm,l2-intc", brcmstb_l2_edge_intc_of_init)
IRQCHIP_MATCH("brcm,hif-spi-l2-intc", brcmstb_l2_edge_intc_of_init)
IRQCHIP_MATCH("brcm,upg-aux-aon-l2-intc", brcmstb_l2_edge_intc_of_init)
IRQCHIP_MATCH("brcm,bcm7271-l2-intc", brcmstb_l2_lvl_intc_of_init)
IRQCHIP_MATCH("brcm,l2-intc", brcmstb_l2_edge_intc_probe)
IRQCHIP_MATCH("brcm,hif-spi-l2-intc", brcmstb_l2_edge_intc_probe)
IRQCHIP_MATCH("brcm,upg-aux-aon-l2-intc", brcmstb_l2_edge_intc_probe)
IRQCHIP_MATCH("brcm,bcm7271-l2-intc", brcmstb_l2_lvl_intc_probe)
IRQCHIP_PLATFORM_DRIVER_END(brcmstb_l2)
MODULE_DESCRIPTION("Broadcom STB generic L2 interrupt controller");
MODULE_LICENSE("GPL v2");
+11 −13
Original line number Diff line number Diff line
@@ -296,10 +296,9 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = {
		  },
};

static int imx_mu_of_init(struct device_node *dn, struct device_node *parent,
static int imx_mu_probe(struct platform_device *pdev, struct device_node *parent,
			const struct imx_mu_dcfg *cfg)
{
	struct platform_device *pdev = of_find_device_by_node(dn);
	struct device_link *pd_link_a;
	struct device_link *pd_link_b;
	struct imx_mu_msi *msi_data;
@@ -415,28 +414,27 @@ static const struct dev_pm_ops imx_mu_pm_ops = {
			   imx_mu_runtime_resume, NULL)
};

static int imx_mu_imx7ulp_of_init(struct device_node *dn, struct device_node *parent)
static int imx_mu_imx7ulp_probe(struct platform_device *pdev, struct device_node *parent)
{
	return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx7ulp);
	return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx7ulp);
}

static int imx_mu_imx6sx_of_init(struct device_node *dn, struct device_node *parent)
static int imx_mu_imx6sx_probe(struct platform_device *pdev, struct device_node *parent)
{
	return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx6sx);
	return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx6sx);
}

static int imx_mu_imx8ulp_of_init(struct device_node *dn, struct device_node *parent)
static int imx_mu_imx8ulp_probe(struct platform_device *pdev, struct device_node *parent)
{
	return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx8ulp);
	return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx8ulp);
}

IRQCHIP_PLATFORM_DRIVER_BEGIN(imx_mu_msi)
IRQCHIP_MATCH("fsl,imx7ulp-mu-msi", imx_mu_imx7ulp_of_init)
IRQCHIP_MATCH("fsl,imx6sx-mu-msi", imx_mu_imx6sx_of_init)
IRQCHIP_MATCH("fsl,imx8ulp-mu-msi", imx_mu_imx8ulp_of_init)
IRQCHIP_MATCH("fsl,imx7ulp-mu-msi", imx_mu_imx7ulp_probe)
IRQCHIP_MATCH("fsl,imx6sx-mu-msi", imx_mu_imx6sx_probe)
IRQCHIP_MATCH("fsl,imx8ulp-mu-msi", imx_mu_imx8ulp_probe)
IRQCHIP_PLATFORM_DRIVER_END(imx_mu_msi, .pm = &imx_mu_pm_ops)


MODULE_AUTHOR("Frank Li <Frank.Li@nxp.com>");
MODULE_DESCRIPTION("Freescale MU MSI controller driver");
MODULE_LICENSE("GPL");
Loading