Skip to content

Commit 645d56e

Browse files
joehattorigregkh
authored andcommitted
usb: typec: anx7411: fix fwnode_handle reference leak
An fwnode_handle and usb_role_switch are obtained with an incremented refcount in anx7411_typec_port_probe(), however the refcounts are not decremented in the error path. The fwnode_handle is also not decremented in the .remove() function. Therefore, call fwnode_handle_put() and usb_role_switch_put() accordingly. Fixes: fe6d8a9 ("usb: typec: anx7411: Add Analogix PD ANX7411 support") Cc: [email protected] Signed-off-by: Joe Hattori <[email protected]> Reviewed-by: Heikki Krogerus <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 0d2ada0 commit 645d56e

File tree

1 file changed

+29
-18
lines changed

1 file changed

+29
-18
lines changed

drivers/usb/typec/anx7411.c

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,16 @@ static void anx7411_port_unregister_altmodes(struct typec_altmode **adev)
10211021
}
10221022
}
10231023

1024+
static void anx7411_port_unregister(struct typec_params *typecp)
1025+
{
1026+
fwnode_handle_put(typecp->caps.fwnode);
1027+
anx7411_port_unregister_altmodes(typecp->port_amode);
1028+
if (typecp->port)
1029+
typec_unregister_port(typecp->port);
1030+
if (typecp->role_sw)
1031+
usb_role_switch_put(typecp->role_sw);
1032+
}
1033+
10241034
static int anx7411_usb_mux_set(struct typec_mux_dev *mux,
10251035
struct typec_mux_state *state)
10261036
{
@@ -1154,34 +1164,34 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
11541164
ret = fwnode_property_read_string(fwnode, "power-role", &buf);
11551165
if (ret) {
11561166
dev_err(dev, "power-role not found: %d\n", ret);
1157-
return ret;
1167+
goto put_fwnode;
11581168
}
11591169

11601170
ret = typec_find_port_power_role(buf);
11611171
if (ret < 0)
1162-
return ret;
1172+
goto put_fwnode;
11631173
cap->type = ret;
11641174

11651175
ret = fwnode_property_read_string(fwnode, "data-role", &buf);
11661176
if (ret) {
11671177
dev_err(dev, "data-role not found: %d\n", ret);
1168-
return ret;
1178+
goto put_fwnode;
11691179
}
11701180

11711181
ret = typec_find_port_data_role(buf);
11721182
if (ret < 0)
1173-
return ret;
1183+
goto put_fwnode;
11741184
cap->data = ret;
11751185

11761186
ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
11771187
if (ret) {
11781188
dev_err(dev, "try-power-role not found: %d\n", ret);
1179-
return ret;
1189+
goto put_fwnode;
11801190
}
11811191

11821192
ret = typec_find_power_role(buf);
11831193
if (ret < 0)
1184-
return ret;
1194+
goto put_fwnode;
11851195
cap->prefer_role = ret;
11861196

11871197
/* Get source pdos */
@@ -1193,7 +1203,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
11931203
typecp->src_pdo_nr);
11941204
if (ret < 0) {
11951205
dev_err(dev, "source cap validate failed: %d\n", ret);
1196-
return -EINVAL;
1206+
goto put_fwnode;
11971207
}
11981208

11991209
typecp->caps_flags |= HAS_SOURCE_CAP;
@@ -1207,7 +1217,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
12071217
typecp->sink_pdo_nr);
12081218
if (ret < 0) {
12091219
dev_err(dev, "sink cap validate failed: %d\n", ret);
1210-
return -EINVAL;
1220+
goto put_fwnode;
12111221
}
12121222

12131223
for (i = 0; i < typecp->sink_pdo_nr; i++) {
@@ -1251,13 +1261,21 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
12511261
ret = PTR_ERR(ctx->typec.port);
12521262
ctx->typec.port = NULL;
12531263
dev_err(dev, "Failed to register type c port %d\n", ret);
1254-
return ret;
1264+
goto put_usb_role_switch;
12551265
}
12561266

12571267
typec_port_register_altmodes(ctx->typec.port, NULL, ctx,
12581268
ctx->typec.port_amode,
12591269
MAX_ALTMODE);
12601270
return 0;
1271+
1272+
put_usb_role_switch:
1273+
if (ctx->typec.role_sw)
1274+
usb_role_switch_put(ctx->typec.role_sw);
1275+
put_fwnode:
1276+
fwnode_handle_put(fwnode);
1277+
1278+
return ret;
12611279
}
12621280

12631281
static int anx7411_typec_check_connection(struct anx7411_data *ctx)
@@ -1523,8 +1541,7 @@ static int anx7411_i2c_probe(struct i2c_client *client)
15231541
destroy_workqueue(plat->workqueue);
15241542

15251543
free_typec_port:
1526-
typec_unregister_port(plat->typec.port);
1527-
anx7411_port_unregister_altmodes(plat->typec.port_amode);
1544+
anx7411_port_unregister(&plat->typec);
15281545

15291546
free_typec_switch:
15301547
anx7411_unregister_switch(plat);
@@ -1548,17 +1565,11 @@ static void anx7411_i2c_remove(struct i2c_client *client)
15481565

15491566
i2c_unregister_device(plat->spi_client);
15501567

1551-
if (plat->typec.role_sw)
1552-
usb_role_switch_put(plat->typec.role_sw);
1553-
15541568
anx7411_unregister_mux(plat);
15551569

15561570
anx7411_unregister_switch(plat);
15571571

1558-
if (plat->typec.port)
1559-
typec_unregister_port(plat->typec.port);
1560-
1561-
anx7411_port_unregister_altmodes(plat->typec.port_amode);
1572+
anx7411_port_unregister(&plat->typec);
15621573
}
15631574

15641575
static const struct i2c_device_id anx7411_id[] = {

0 commit comments

Comments
 (0)