From 86c45e0761e895ae622c22d5a0e619ae23c22f36 Mon Sep 17 00:00:00 2001 From: Ramprasad Katkam Date: Tue, 16 Oct 2018 19:31:51 +0530 Subject: [PATCH] soc: swr-mstr: Avoid race condition during device up During device up call from platform driver, if master is already up pm get_sync is currently skipped. However pm suspend can get called after this check. Hence do a pm get_sync even if master is already up to avoid race condition. Change-Id: I1779db3d65f58bda220d1ec07706e91745814c1f Signed-off-by: Ramprasad Katkam --- soc/swr-mstr-ctrl.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 3d1b080b66..af5adac499 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -1191,6 +1191,7 @@ static int swrm_disconnect_port(struct swr_master *master, if (!port_req) { dev_err(&master->dev, "%s:port not enabled : port %d\n", __func__, portinfo->port_id[i]); + mutex_unlock(&swrm->mlock); return -EINVAL; } port_req->req_ch &= ~portinfo->ch_en[i]; @@ -2108,29 +2109,20 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) case SWR_DEVICE_UP: dev_dbg(swrm->dev, "%s: swr master up called\n", __func__); mutex_lock(&swrm->mlock); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); mutex_lock(&swrm->reslock); - if (swrm->state == SWR_MSTR_UP) { - dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n", - __func__, swrm->state); - list_for_each_entry(swr_dev, &mstr->devices, dev_list) - swr_reset_device(swr_dev); - } else { - pm_runtime_mark_last_busy(&pdev->dev); - mutex_unlock(&swrm->reslock); - pm_runtime_get_sync(&pdev->dev); - mutex_lock(&swrm->reslock); - list_for_each_entry(swr_dev, &mstr->devices, dev_list) { - ret = swr_reset_device(swr_dev); - if (ret) { - dev_err(swrm->dev, - "%s: failed to reset swr device %d\n", - __func__, swr_dev->dev_num); - swrm_clk_request(swrm, false); - } + list_for_each_entry(swr_dev, &mstr->devices, dev_list) { + ret = swr_reset_device(swr_dev); + if (ret) { + dev_err(swrm->dev, + "%s: failed to reset swr device %d\n", + __func__, swr_dev->dev_num); + swrm_clk_request(swrm, false); } - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); } + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); mutex_unlock(&swrm->reslock); mutex_unlock(&swrm->mlock); break;