diff options
author | Subhransu S. Prusty <subhransu.s.prusty@intel.com> | 2017-11-07 05:46:26 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-11-08 13:58:29 -0500 |
commit | 1c0a7de226660b0306b54aaf2cb52312e74723eb (patch) | |
tree | 2e5bd193f4e2b9005b56a7445875504dc71b6993 | |
parent | eb50fa1739a63cc4b202b40a62d71055a2d7b80c (diff) |
ASoC: hdac_hdmi: Fix possible memory leak on parse and map nid failure
During failure, widgets in cvt_list and pin_list are not freed. So fix
the possible memory leak by freeing them when failure occurs.
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Guneshwor Singh <guneshwor.o.singh@intel.com>
Acked-By: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/codecs/hdac_hdmi.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 0c0aa6182502..f3b4f4dfae6a 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c | |||
@@ -1453,6 +1453,8 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, | |||
1453 | int i, num_nodes; | 1453 | int i, num_nodes; |
1454 | struct hdac_device *hdac = &edev->hdac; | 1454 | struct hdac_device *hdac = &edev->hdac; |
1455 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1455 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1456 | struct hdac_hdmi_cvt *temp_cvt, *cvt_next; | ||
1457 | struct hdac_hdmi_pin *temp_pin, *pin_next; | ||
1456 | int ret; | 1458 | int ret; |
1457 | 1459 | ||
1458 | hdac_hdmi_skl_enable_all_pins(hdac); | 1460 | hdac_hdmi_skl_enable_all_pins(hdac); |
@@ -1482,32 +1484,54 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, | |||
1482 | case AC_WID_AUD_OUT: | 1484 | case AC_WID_AUD_OUT: |
1483 | ret = hdac_hdmi_add_cvt(edev, nid); | 1485 | ret = hdac_hdmi_add_cvt(edev, nid); |
1484 | if (ret < 0) | 1486 | if (ret < 0) |
1485 | return ret; | 1487 | goto free_widgets; |
1486 | break; | 1488 | break; |
1487 | 1489 | ||
1488 | case AC_WID_PIN: | 1490 | case AC_WID_PIN: |
1489 | ret = hdac_hdmi_add_pin(edev, nid); | 1491 | ret = hdac_hdmi_add_pin(edev, nid); |
1490 | if (ret < 0) | 1492 | if (ret < 0) |
1491 | return ret; | 1493 | goto free_widgets; |
1492 | break; | 1494 | break; |
1493 | } | 1495 | } |
1494 | } | 1496 | } |
1495 | 1497 | ||
1496 | hdac->end_nid = nid; | 1498 | hdac->end_nid = nid; |
1497 | 1499 | ||
1498 | if (!hdmi->num_pin || !hdmi->num_cvt) | 1500 | if (!hdmi->num_pin || !hdmi->num_cvt) { |
1499 | return -EIO; | 1501 | ret = -EIO; |
1502 | goto free_widgets; | ||
1503 | } | ||
1500 | 1504 | ||
1501 | ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt); | 1505 | ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt); |
1502 | if (ret) { | 1506 | if (ret) { |
1503 | dev_err(&hdac->dev, "Failed to create dais with err: %d\n", | 1507 | dev_err(&hdac->dev, "Failed to create dais with err: %d\n", |
1504 | ret); | 1508 | ret); |
1505 | return ret; | 1509 | goto free_widgets; |
1506 | } | 1510 | } |
1507 | 1511 | ||
1508 | *num_dais = hdmi->num_cvt; | 1512 | *num_dais = hdmi->num_cvt; |
1513 | ret = hdac_hdmi_init_dai_map(edev); | ||
1514 | if (ret < 0) | ||
1515 | goto free_widgets; | ||
1509 | 1516 | ||
1510 | return hdac_hdmi_init_dai_map(edev); | 1517 | return ret; |
1518 | |||
1519 | free_widgets: | ||
1520 | list_for_each_entry_safe(temp_cvt, cvt_next, &hdmi->cvt_list, head) { | ||
1521 | list_del(&temp_cvt->head); | ||
1522 | kfree(temp_cvt->name); | ||
1523 | kfree(temp_cvt); | ||
1524 | } | ||
1525 | |||
1526 | list_for_each_entry_safe(temp_pin, pin_next, &hdmi->pin_list, head) { | ||
1527 | for (i = 0; i < temp_pin->num_ports; i++) | ||
1528 | temp_pin->ports[i].pin = NULL; | ||
1529 | kfree(temp_pin->ports); | ||
1530 | list_del(&temp_pin->head); | ||
1531 | kfree(temp_pin); | ||
1532 | } | ||
1533 | |||
1534 | return ret; | ||
1511 | } | 1535 | } |
1512 | 1536 | ||
1513 | static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) | 1537 | static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) |