Skip to content

Commit 8d68100

Browse files
tasksetdavem330
authored andcommitted
soc/fsl/qe: fix err handling of ucc_of_parse_tdm
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 <[email protected]> Suggested-by: Christophe LEROY <[email protected]> Signed-off-by: Wen Yang <[email protected]> Reviewed-by: Peng Hao <[email protected]> CC: Julia Lawall <[email protected]> CC: Zhao Qiang <[email protected]> CC: David S. Miller <[email protected]> CC: [email protected] CC: [email protected] CC: [email protected] Signed-off-by: David S. Miller <[email protected]>
1 parent 3635299 commit 8d68100

File tree

2 files changed

+61
-56
lines changed

2 files changed

+61
-56
lines changed

drivers/net/wan/fsl_ucc_hdlc.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,54 @@ static const struct net_device_ops uhdlc_ops = {
10571057
.ndo_tx_timeout = uhdlc_tx_timeout,
10581058
};
10591059

1060+
static int hdlc_map_iomem(char *name, int init_flag, void __iomem **ptr)
1061+
{
1062+
struct device_node *np;
1063+
struct platform_device *pdev;
1064+
struct resource *res;
1065+
static int siram_init_flag;
1066+
int ret = 0;
1067+
1068+
np = of_find_compatible_node(NULL, NULL, name);
1069+
if (!np)
1070+
return -EINVAL;
1071+
1072+
pdev = of_find_device_by_node(np);
1073+
if (!pdev) {
1074+
pr_err("%pOFn: failed to lookup pdev\n", np);
1075+
of_node_put(np);
1076+
return -EINVAL;
1077+
}
1078+
1079+
of_node_put(np);
1080+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1081+
if (!res) {
1082+
ret = -EINVAL;
1083+
goto error_put_device;
1084+
}
1085+
*ptr = ioremap(res->start, resource_size(res));
1086+
if (!*ptr) {
1087+
ret = -ENOMEM;
1088+
goto error_put_device;
1089+
}
1090+
1091+
/* We've remapped the addresses, and we don't need the device any
1092+
* more, so we should release it.
1093+
*/
1094+
put_device(&pdev->dev);
1095+
1096+
if (init_flag && siram_init_flag == 0) {
1097+
memset_io(*ptr, 0, resource_size(res));
1098+
siram_init_flag = 1;
1099+
}
1100+
return 0;
1101+
1102+
error_put_device:
1103+
put_device(&pdev->dev);
1104+
1105+
return ret;
1106+
}
1107+
10601108
static int ucc_hdlc_probe(struct platform_device *pdev)
10611109
{
10621110
struct device_node *np = pdev->dev.of_node;
@@ -1151,6 +1199,15 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
11511199
ret = ucc_of_parse_tdm(np, utdm, ut_info);
11521200
if (ret)
11531201
goto free_utdm;
1202+
1203+
ret = hdlc_map_iomem("fsl,t1040-qe-si", 0,
1204+
(void __iomem **)&utdm->si_regs);
1205+
if (ret)
1206+
goto free_utdm;
1207+
ret = hdlc_map_iomem("fsl,t1040-qe-siram", 1,
1208+
(void __iomem **)&utdm->siram);
1209+
if (ret)
1210+
goto unmap_si_regs;
11541211
}
11551212

11561213
if (of_property_read_u16(np, "fsl,hmask", &uhdlc_priv->hmask))
@@ -1159,7 +1216,7 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
11591216
ret = uhdlc_init(uhdlc_priv);
11601217
if (ret) {
11611218
dev_err(&pdev->dev, "Failed to init uhdlc\n");
1162-
goto free_utdm;
1219+
goto undo_uhdlc_init;
11631220
}
11641221

11651222
dev = alloc_hdlcdev(uhdlc_priv);
@@ -1188,6 +1245,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
11881245
free_dev:
11891246
free_netdev(dev);
11901247
undo_uhdlc_init:
1248+
iounmap(utdm->siram);
1249+
unmap_si_regs:
1250+
iounmap(utdm->si_regs);
11911251
free_utdm:
11921252
if (uhdlc_priv->tsa)
11931253
kfree(utdm);

drivers/soc/fsl/qe/qe_tdm.c

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
4444
const char *sprop;
4545
int ret = 0;
4646
u32 val;
47-
struct resource *res;
48-
struct device_node *np2;
49-
static int siram_init_flag;
50-
struct platform_device *pdev;
5147

5248
sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
5349
if (sprop) {
@@ -124,57 +120,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
124120
utdm->siram_entry_id = val;
125121

126122
set_si_param(utdm, ut_info);
127-
128-
np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si");
129-
if (!np2)
130-
return -EINVAL;
131-
132-
pdev = of_find_device_by_node(np2);
133-
if (!pdev) {
134-
pr_err("%pOFn: failed to lookup pdev\n", np2);
135-
of_node_put(np2);
136-
return -EINVAL;
137-
}
138-
139-
of_node_put(np2);
140-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
141-
utdm->si_regs = devm_ioremap_resource(&pdev->dev, res);
142-
if (IS_ERR(utdm->si_regs)) {
143-
ret = PTR_ERR(utdm->si_regs);
144-
goto err_miss_siram_property;
145-
}
146-
147-
np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram");
148-
if (!np2) {
149-
ret = -EINVAL;
150-
goto err_miss_siram_property;
151-
}
152-
153-
pdev = of_find_device_by_node(np2);
154-
if (!pdev) {
155-
ret = -EINVAL;
156-
pr_err("%pOFn: failed to lookup pdev\n", np2);
157-
of_node_put(np2);
158-
goto err_miss_siram_property;
159-
}
160-
161-
of_node_put(np2);
162-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
163-
utdm->siram = devm_ioremap_resource(&pdev->dev, res);
164-
if (IS_ERR(utdm->siram)) {
165-
ret = PTR_ERR(utdm->siram);
166-
goto err_miss_siram_property;
167-
}
168-
169-
if (siram_init_flag == 0) {
170-
memset_io(utdm->siram, 0, resource_size(res));
171-
siram_init_flag = 1;
172-
}
173-
174-
return ret;
175-
176-
err_miss_siram_property:
177-
devm_iounmap(&pdev->dev, utdm->si_regs);
178123
return ret;
179124
}
180125
EXPORT_SYMBOL(ucc_of_parse_tdm);

0 commit comments

Comments
 (0)