diff options
author | Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | 2018-06-04 05:39:01 -0400 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2018-06-04 15:35:03 -0400 |
commit | 4a2e84c6ed85434ce7843e4844b4d3263f7e233b (patch) | |
tree | 44ce7a2a7f84a94d1b3888149f26b7131424a9ca /drivers/rpmsg | |
parent | 136200f4fd365a0a9c549893c9641f6eeff53f22 (diff) |
rpmsg: smd: do not use mananged resources for endpoints and channels
All the managed resources would be freed by the time release function
is invoked. Handling such memory in qcom_smd_edge_release() would do
bad things.
Found this issue while testing Audio usecase where the dsp is started up
and shutdown in a loop.
This patch fixes this issue by using simple kzalloc for allocating
channel->name and channel which is then freed in qcom_smd_edge_release().
Without this patch restarting a remoteproc would crash the system.
Fixes: 53e2822e56c7 ("rpmsg: Introduce Qualcomm SMD backend")
Cc: <stable@vger.kernel.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/rpmsg')
-rw-r--r-- | drivers/rpmsg/qcom_smd.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c index 6d01eefe2bda..6437bbeebc91 100644 --- a/drivers/rpmsg/qcom_smd.c +++ b/drivers/rpmsg/qcom_smd.c | |||
@@ -1108,12 +1108,12 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed | |||
1108 | void *info; | 1108 | void *info; |
1109 | int ret; | 1109 | int ret; |
1110 | 1110 | ||
1111 | channel = devm_kzalloc(&edge->dev, sizeof(*channel), GFP_KERNEL); | 1111 | channel = kzalloc(sizeof(*channel), GFP_KERNEL); |
1112 | if (!channel) | 1112 | if (!channel) |
1113 | return ERR_PTR(-ENOMEM); | 1113 | return ERR_PTR(-ENOMEM); |
1114 | 1114 | ||
1115 | channel->edge = edge; | 1115 | channel->edge = edge; |
1116 | channel->name = devm_kstrdup(&edge->dev, name, GFP_KERNEL); | 1116 | channel->name = kstrdup(name, GFP_KERNEL); |
1117 | if (!channel->name) | 1117 | if (!channel->name) |
1118 | return ERR_PTR(-ENOMEM); | 1118 | return ERR_PTR(-ENOMEM); |
1119 | 1119 | ||
@@ -1164,8 +1164,8 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed | |||
1164 | return channel; | 1164 | return channel; |
1165 | 1165 | ||
1166 | free_name_and_channel: | 1166 | free_name_and_channel: |
1167 | devm_kfree(&edge->dev, channel->name); | 1167 | kfree(channel->name); |
1168 | devm_kfree(&edge->dev, channel); | 1168 | kfree(channel); |
1169 | 1169 | ||
1170 | return ERR_PTR(ret); | 1170 | return ERR_PTR(ret); |
1171 | } | 1171 | } |
@@ -1396,13 +1396,13 @@ static int qcom_smd_parse_edge(struct device *dev, | |||
1396 | */ | 1396 | */ |
1397 | static void qcom_smd_edge_release(struct device *dev) | 1397 | static void qcom_smd_edge_release(struct device *dev) |
1398 | { | 1398 | { |
1399 | struct qcom_smd_channel *channel; | 1399 | struct qcom_smd_channel *channel, *tmp; |
1400 | struct qcom_smd_edge *edge = to_smd_edge(dev); | 1400 | struct qcom_smd_edge *edge = to_smd_edge(dev); |
1401 | 1401 | ||
1402 | list_for_each_entry(channel, &edge->channels, list) { | 1402 | list_for_each_entry_safe(channel, tmp, &edge->channels, list) { |
1403 | SET_RX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); | 1403 | list_del(&channel->list); |
1404 | SET_RX_CHANNEL_INFO(channel, head, 0); | 1404 | kfree(channel->name); |
1405 | SET_RX_CHANNEL_INFO(channel, tail, 0); | 1405 | kfree(channel); |
1406 | } | 1406 | } |
1407 | 1407 | ||
1408 | kfree(edge); | 1408 | kfree(edge); |