Commit 1c0a7de2 authored by Subhransu S. Prusty's avatar Subhransu S. Prusty Committed by Mark Brown

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: default avatarSubhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: default avatarGuneshwor Singh <guneshwor.o.singh@intel.com>
Acked-By: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent eb50fa17
...@@ -1453,6 +1453,8 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, ...@@ -1453,6 +1453,8 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
int i, num_nodes; int i, num_nodes;
struct hdac_device *hdac = &edev->hdac; struct hdac_device *hdac = &edev->hdac;
struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_priv *hdmi = edev->private_data;
struct hdac_hdmi_cvt *temp_cvt, *cvt_next;
struct hdac_hdmi_pin *temp_pin, *pin_next;
int ret; int ret;
hdac_hdmi_skl_enable_all_pins(hdac); 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,32 +1484,54 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
case AC_WID_AUD_OUT: case AC_WID_AUD_OUT:
ret = hdac_hdmi_add_cvt(edev, nid); ret = hdac_hdmi_add_cvt(edev, nid);
if (ret < 0) if (ret < 0)
return ret; goto free_widgets;
break; break;
case AC_WID_PIN: case AC_WID_PIN:
ret = hdac_hdmi_add_pin(edev, nid); ret = hdac_hdmi_add_pin(edev, nid);
if (ret < 0) if (ret < 0)
return ret; goto free_widgets;
break; break;
} }
} }
hdac->end_nid = nid; hdac->end_nid = nid;
if (!hdmi->num_pin || !hdmi->num_cvt) if (!hdmi->num_pin || !hdmi->num_cvt) {
return -EIO; ret = -EIO;
goto free_widgets;
}
ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt); ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt);
if (ret) { if (ret) {
dev_err(&hdac->dev, "Failed to create dais with err: %d\n", dev_err(&hdac->dev, "Failed to create dais with err: %d\n",
ret); ret);
return ret; goto free_widgets;
} }
*num_dais = hdmi->num_cvt; *num_dais = hdmi->num_cvt;
ret = hdac_hdmi_init_dai_map(edev);
if (ret < 0)
goto free_widgets;
return hdac_hdmi_init_dai_map(edev); return ret;
free_widgets:
list_for_each_entry_safe(temp_cvt, cvt_next, &hdmi->cvt_list, head) {
list_del(&temp_cvt->head);
kfree(temp_cvt->name);
kfree(temp_cvt);
}
list_for_each_entry_safe(temp_pin, pin_next, &hdmi->pin_list, head) {
for (i = 0; i < temp_pin->num_ports; i++)
temp_pin->ports[i].pin = NULL;
kfree(temp_pin->ports);
list_del(&temp_pin->head);
kfree(temp_pin);
}
return ret;
} }
static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment