Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4286797a authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: glink_probe: Use ref count for holding ssr context"

parents 179baba0 9c27cf71
Loading
Loading
Loading
Loading
+44 −8
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@ struct glink_ssr {

	u32 seq_num;
	struct completion completion;
	struct work_struct unreg_work;
	struct kref refcount;
};

struct edge_info {
@@ -85,6 +87,31 @@ struct edge_info {
};
LIST_HEAD(edge_infos);

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,
					     unreg_work);
	struct glink_ssr_nb *nb, *tmp;

	list_for_each_entry_safe(nb, tmp, &ssr->notify_list, list) {
		subsys_notif_unregister_notifier(nb->ssr_register_handle,
						 &nb->nb);
	}
	kref_put(&ssr->refcount, glink_ssr_release);
}

static int glink_ssr_ssr_cb(struct notifier_block *this,
			    unsigned long code, void *data)
{
@@ -94,6 +121,11 @@ static int glink_ssr_ssr_cb(struct notifier_block *this,
	struct do_cleanup_msg msg;
	int ret;

	if (!dev || !ssr->ept)
		return NOTIFY_DONE;

	kref_get(&ssr->refcount);

	if (code == SUBSYS_AFTER_SHUTDOWN) {
		ssr->seq_num++;
		reinit_completion(&ssr->completion);
@@ -112,6 +144,7 @@ static int glink_ssr_ssr_cb(struct notifier_block *this,
		if (ret) {
			GLINK_ERR(dev, "fail to send do cleanup to %s %d\n",
				  nb->ssr_label, ret);
			kref_put(&ssr->refcount, glink_ssr_release);
			return NOTIFY_DONE;
		}

@@ -119,6 +152,7 @@ static int glink_ssr_ssr_cb(struct notifier_block *this,
		if (!ret)
			GLINK_ERR(dev, "timeout waiting for cleanup resp\n");
	}
	kref_put(&ssr->refcount, glink_ssr_release);
	return NOTIFY_DONE;
}

@@ -169,7 +203,7 @@ static void glink_ssr_init_notify(struct glink_ssr *ssr)
		if (!node)
			break;

		nb = devm_kzalloc(dev, sizeof(*nb), GFP_KERNEL);
		nb = kzalloc(sizeof(*nb), GFP_KERNEL);
		if (!nb)
			return;

@@ -182,6 +216,7 @@ static void glink_ssr_init_notify(struct glink_ssr *ssr)
		if (ret < 0) {
			GLINK_ERR(dev, "no qcom,glink-label for %s\n",
				  nb->ssr_label);
			kfree(nb);
			continue;
		}

@@ -193,6 +228,7 @@ static void glink_ssr_init_notify(struct glink_ssr *ssr)
		if (IS_ERR_OR_NULL(handle)) {
			GLINK_ERR(dev, "register fail for %s SSR notifier\n",
				  nb->ssr_label);
			kfree(nb);
			continue;
		}

@@ -205,12 +241,14 @@ static int glink_ssr_probe(struct rpmsg_device *rpdev)
{
	struct glink_ssr *ssr;

	ssr = devm_kzalloc(&rpdev->dev, sizeof(*ssr), GFP_KERNEL);
	ssr = kzalloc(sizeof(*ssr), GFP_KERNEL);
	if (!ssr)
		return -ENOMEM;

	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;
@@ -225,14 +263,12 @@ static int glink_ssr_probe(struct rpmsg_device *rpdev)
static void glink_ssr_remove(struct rpmsg_device *rpdev)
{
	struct glink_ssr *ssr = dev_get_drvdata(&rpdev->dev);
	struct glink_ssr_nb *nb;

	list_for_each_entry(nb, &ssr->notify_list, list) {
		subsys_notif_unregister_notifier(nb->ssr_register_handle,
						 &nb->nb);
	}

	ssr->dev = NULL;
	ssr->ept = NULL;
	dev_set_drvdata(&rpdev->dev, NULL);

	schedule_work(&ssr->unreg_work);
}

static const struct rpmsg_device_id glink_ssr_match[] = {