aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSubhransu S. Prusty <subhransu.s.prusty@intel.com>2017-11-07 05:46:26 -0500
committerMark Brown <broonie@kernel.org>2017-11-08 13:58:29 -0500
commit1c0a7de226660b0306b54aaf2cb52312e74723eb (patch)
tree2e5bd193f4e2b9005b56a7445875504dc71b6993
parenteb50fa1739a63cc4b202b40a62d71055a2d7b80c (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.c36
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
1519free_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
1513static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) 1537static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)