From: Wen Yang <wen.yan...@zte.com.cn> Currently there are some issues with the ucc_of_parse_tdm function: 1, a possible null pointer dereference in ucc_of_parse_tdm, detected by the semantic patch deref_null.cocci, with the following warning: drivers/soc/fsl/qe/qe_tdm.c:177:21-24: ERROR: pdev is NULL but dereferenced. 2, dev gets modified, so in any case that devm_iounmap() will fail even when the new pdev is valid, because the iomap was done with a different pdev. 3, there is no driver bind with the "fsl,t1040-qe-si" or "fsl,t1040-qe-siram" device. So allocating resources using devm_*() with these devices won't provide a cleanup path for these resources when the caller fails.
This patch fixes them. Suggested-by: Li Yang <leoyang...@nxp.com> Suggested-by: Christophe LEROY <christophe.le...@c-s.fr> Signed-off-by: Wen Yang <wen.yan...@zte.com.cn> Reviewed-by: Peng Hao <peng.h...@zte.com.cn> CC: Julia Lawall <julia.law...@lip6.fr> CC: Zhao Qiang <qiang.z...@nxp.com> CC: David S. Miller <da...@davemloft.net> CC: netdev@vger.kernel.org CC: linuxppc-...@lists.ozlabs.org CC: linux-ker...@vger.kernel.org --- drivers/net/wan/fsl_ucc_hdlc.c | 52 ++++++++++++++++++++++++++++++++++++++- drivers/soc/fsl/qe/qe_tdm.c | 55 ------------------------------------------ 2 files changed, 51 insertions(+), 56 deletions(-) diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 839fa77..07a496c 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -1057,6 +1057,26 @@ static const struct net_device_ops uhdlc_ops = { .ndo_tx_timeout = uhdlc_tx_timeout, }; +static struct resource *ucc_get_resource_by_nodename(char *name) +{ + struct device_node *np; + struct platform_device *pdev; + + np = of_find_compatible_node(NULL, NULL, name); + if (!np) + return ERR_PTR(-EINVAL); + + pdev = of_find_device_by_node(np); + if (!pdev) { + pr_err("%pOFn: failed to lookup pdev\n", np); + of_node_put(np); + return ERR_PTR(-EINVAL); + } + + of_node_put(np); + return platform_get_resource(pdev, IORESOURCE_MEM, 0); +} + static int ucc_hdlc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1070,6 +1090,8 @@ static int ucc_hdlc_probe(struct platform_device *pdev) const char *sprop; int ret; u32 val; + struct resource *r_mem; + static int siram_init_flag; ret = of_property_read_u32_index(np, "cell-index", 0, &val); if (ret) { @@ -1151,6 +1173,31 @@ static int ucc_hdlc_probe(struct platform_device *pdev) ret = ucc_of_parse_tdm(np, utdm, ut_info); if (ret) goto free_utdm; + + r_mem = ucc_get_resource_by_nodename("fsl,t1040-qe-si"); + if (IS_ERR_OR_NULL(r_mem)) { + ret = -EINVAL; + goto free_utdm; + } + utdm->si_regs = ioremap(r_mem->start, resource_size(r_mem)); + if (!utdm->si_regs) { + ret = -ENOMEM; + goto free_utdm; + } + r_mem = ucc_get_resource_by_nodename("fsl,t1040-qe-siram"); + if (IS_ERR_OR_NULL(r_mem)) { + ret = -EINVAL; + goto unmap_si_regs; + } + utdm->siram = ioremap(r_mem->start, resource_size(r_mem)); + if (!utdm->siram) { + ret = -ENOMEM; + goto unmap_si_regs; + } + if (siram_init_flag == 0) { + memset_io(utdm->siram, 0, resource_size(r_mem)); + siram_init_flag = 1; + } } if (of_property_read_u16(np, "fsl,hmask", &uhdlc_priv->hmask)) @@ -1159,7 +1206,7 @@ static int ucc_hdlc_probe(struct platform_device *pdev) ret = uhdlc_init(uhdlc_priv); if (ret) { dev_err(&pdev->dev, "Failed to init uhdlc\n"); - goto free_utdm; + goto undo_uhdlc_init; } dev = alloc_hdlcdev(uhdlc_priv); @@ -1188,6 +1235,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev) free_dev: free_netdev(dev); undo_uhdlc_init: + iounmap(utdm->siram); +unmap_si_regs: + iounmap(utdm->si_regs); free_utdm: if (uhdlc_priv->tsa) kfree(utdm); diff --git a/drivers/soc/fsl/qe/qe_tdm.c b/drivers/soc/fsl/qe/qe_tdm.c index f78c346..76480df 100644 --- a/drivers/soc/fsl/qe/qe_tdm.c +++ b/drivers/soc/fsl/qe/qe_tdm.c @@ -44,10 +44,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, const char *sprop; int ret = 0; u32 val; - struct resource *res; - struct device_node *np2; - static int siram_init_flag; - struct platform_device *pdev; sprop = of_get_property(np, "fsl,rx-sync-clock", NULL); if (sprop) { @@ -124,57 +120,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, utdm->siram_entry_id = val; set_si_param(utdm, ut_info); - - np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si"); - if (!np2) - return -EINVAL; - - pdev = of_find_device_by_node(np2); - if (!pdev) { - pr_err("%pOFn: failed to lookup pdev\n", np2); - of_node_put(np2); - return -EINVAL; - } - - of_node_put(np2); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - utdm->si_regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(utdm->si_regs)) { - ret = PTR_ERR(utdm->si_regs); - goto err_miss_siram_property; - } - - np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram"); - if (!np2) { - ret = -EINVAL; - goto err_miss_siram_property; - } - - pdev = of_find_device_by_node(np2); - if (!pdev) { - ret = -EINVAL; - pr_err("%pOFn: failed to lookup pdev\n", np2); - of_node_put(np2); - goto err_miss_siram_property; - } - - of_node_put(np2); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - utdm->siram = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(utdm->siram)) { - ret = PTR_ERR(utdm->siram); - goto err_miss_siram_property; - } - - if (siram_init_flag == 0) { - memset_io(utdm->siram, 0, resource_size(res)); - siram_init_flag = 1; - } - - return ret; - -err_miss_siram_property: - devm_iounmap(&pdev->dev, utdm->si_regs); return ret; } EXPORT_SYMBOL(ucc_of_parse_tdm); -- 2.9.5