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

Reply via email to