Merge "soc: qcom: glink_probe: use lock while sending ssr notification"

This commit is contained in:
qctecmdr 2020-12-04 05:45:43 -08:00 • committed by Gerrit - the friendly Code Review server
commit 75e68a7d23

View file

@ -16,6 +16,7 @@
#define MSM_SSR_LOG_PAGE_CNT 4
static void *ssr_ilc;
static DEFINE_MUTEX(ssr_lock);
#define MSM_SSR_INFO(x, ...) ipc_log_string(ssr_ilc, x, ##__VA_ARGS__)
@ -64,8 +65,21 @@ struct glink_ssr {
u32 seq_num;
struct completion completion;
struct work_struct unreg_work;
struct kref refcount;
};
static void glink_ssr_release(struct kref *ref)
{
struct glink_ssr *ssr = container_of(ref, struct glink_ssr,
refcount);
struct glink_ssr_nb *nb, *tmp;
list_for_each_entry_safe(nb, tmp, &ssr->notify_list, list)
kfree(nb);
kfree(ssr);
}
static void glink_ssr_ssr_unreg_work(struct work_struct *work)
{
struct glink_ssr *ssr = container_of(work, struct glink_ssr,
@ -75,9 +89,8 @@ static void glink_ssr_ssr_unreg_work(struct work_struct *work)
list_for_each_entry_safe(nb, tmp, &ssr->notify_list, list) {
subsys_notif_unregister_notifier(nb->ssr_register_handle,
&nb->nb);
kfree(nb);
}
kfree(ssr);
kref_put(&ssr->refcount, glink_ssr_release);
}
static int glink_ssr_ssr_cb(struct notifier_block *this,
@ -85,12 +98,15 @@ static int glink_ssr_ssr_cb(struct notifier_block *this,
{
struct glink_ssr_nb *nb = container_of(this, struct glink_ssr_nb, nb);
struct glink_ssr *ssr = nb->ssr;
struct device *dev = ssr->dev;
struct device *dev;
struct do_cleanup_msg msg;
int ret;
kref_get(&ssr->refcount);
mutex_lock(&ssr_lock);
dev = ssr->dev;
if (!dev || !ssr->ept)
return NOTIFY_DONE;
goto out;
if (code == SUBSYS_AFTER_SHUTDOWN || code == SUBSYS_POWERUP_FAILURE) {
ssr->seq_num++;
@ -110,13 +126,16 @@ static int glink_ssr_ssr_cb(struct notifier_block *this,
if (ret) {
MSM_SSR_ERR(dev, "fail to send do cleanup to %s %d\n",
nb->ssr_label, ret);
return NOTIFY_DONE;
goto out;
}
ret = wait_for_completion_timeout(&ssr->completion, HZ);
if (!ret)
MSM_SSR_ERR(dev, "timeout waiting for cleanup resp\n");
}
out:
mutex_unlock(&ssr_lock);
kref_put(&ssr->refcount, glink_ssr_release);
return NOTIFY_DONE;
}
@ -217,6 +236,7 @@ static int glink_ssr_probe(struct rpmsg_device *rpdev)
INIT_LIST_HEAD(&ssr->notify_list);
init_completion(&ssr->completion);
INIT_WORK(&ssr->unreg_work, glink_ssr_ssr_unreg_work);
kref_init(&ssr->refcount);
ssr->dev = &rpdev->dev;
ssr->ept = rpdev->ept;
@ -235,11 +255,12 @@ static void glink_ssr_remove(struct rpmsg_device *rpdev)
{
struct glink_ssr *ssr = dev_get_drvdata(&rpdev->dev);
mutex_lock(&ssr_lock);
ssr->dev = NULL;
ssr->ept = NULL;
mutex_unlock(&ssr_lock);
dev_set_drvdata(&rpdev->dev, NULL);
schedule_work(&ssr->unreg_work);
}