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

Commit 314a420a authored by c_mtharu's avatar c_mtharu
Browse files

msm: ADSPRPC: Close glink channel after remote disconnected



Close glink channel only after receiving notification for remote
disconnected during subsystem restart. It will avoid race condition
to reopen the channel again before remote gets disconnected.

Change-Id: Ifa9bab946a229656a7c5440c4bd00e30c45a7140
Acked-by: default avatarViswanatham Paduchuri <vpaduchu@qti.qualcomm.com>
Signed-off-by: default avatarTharun Kumar Merugu <mtharu@codeaurora.org>
parent 76913944
Loading
Loading
Loading
Loading
+51 −31
Original line number Diff line number Diff line
@@ -75,6 +75,8 @@
#define FASTRPC_LINK_CONNECTING   (0x1)
#define FASTRPC_LINK_CONNECTED    (0x3)
#define FASTRPC_LINK_DISCONNECTING (0x7)
#define FASTRPC_LINK_REMOTE_DISCONNECTING (0x8)
#define FASTRPC_GLINK_INTENT_LEN  (64)

#define PERF_KEYS "count:flush:map:copy:glink:getargs:putargs:invalidate:invoke"
#define FASTRPC_STATIC_HANDLE_LISTENER (3)
@@ -235,13 +237,13 @@ struct fastrpc_channel_ctx {
	int ramdumpenabled;
	void *remoteheap_ramdump_dev;
	struct fastrpc_glink_info link;
	struct mutex mut;
};

struct fastrpc_apps {
	struct fastrpc_channel_ctx *channel;
	struct cdev cdev;
	struct class *class;
	struct mutex smd_mutex;
	struct smq_phy_page range;
	struct hlist_head maps;
	uint32_t staticpd_flags;
@@ -1486,12 +1488,12 @@ static void fastrpc_init(struct fastrpc_apps *me)

	INIT_HLIST_HEAD(&me->drivers);
	spin_lock_init(&me->hlock);
	mutex_init(&me->smd_mutex);
	me->channel = &gcinfo[0];
	for (i = 0; i < NUM_CHANNELS; i++) {
		init_completion(&me->channel[i].work);
		init_completion(&me->channel[i].workport);
		me->channel[i].sesscount = 0;
		mutex_init(&me->channel[i].mut);
	}
}

@@ -2087,7 +2089,7 @@ static void fastrpc_channel_close(struct kref *kref)
	ctx->chan = NULL;
	glink_unregister_link_state_cb(ctx->link.link_notify_handle);
	ctx->link.link_notify_handle = NULL;
	mutex_unlock(&me->smd_mutex);
	mutex_unlock(&ctx->mut);
	pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name,
						MAJOR(me->dev_no), cid);
}
@@ -2180,10 +2182,15 @@ static void fastrpc_glink_notify_state(void *handle, const void *priv,
		link->port_state = FASTRPC_LINK_DISCONNECTED;
		break;
	case GLINK_REMOTE_DISCONNECTED:
		mutex_lock(&me->channel[cid].mut);
		if (me->channel[cid].chan) {
			link->port_state = FASTRPC_LINK_REMOTE_DISCONNECTING;
			fastrpc_glink_close(me->channel[cid].chan, cid);
			me->channel[cid].chan = NULL;
		} else {
			link->port_state = FASTRPC_LINK_DISCONNECTED;
		}
		mutex_unlock(&me->channel[cid].mut);
		break;
	default:
		break;
@@ -2194,23 +2201,20 @@ static int fastrpc_session_alloc(struct fastrpc_channel_ctx *chan, int secure,
					struct fastrpc_session_ctx **session)
{
	int err = 0;
	struct fastrpc_apps *me = &gfa;

	mutex_lock(&me->smd_mutex);
	mutex_lock(&chan->mut);
	if (!*session)
		err = fastrpc_session_alloc_locked(chan, secure, session);
	mutex_unlock(&me->smd_mutex);
	mutex_unlock(&chan->mut);
	return err;
}

static void fastrpc_session_free(struct fastrpc_channel_ctx *chan,
				struct fastrpc_session_ctx *session)
{
	struct fastrpc_apps *me = &gfa;

	mutex_lock(&me->smd_mutex);
	mutex_lock(&chan->mut);
	session->used = 0;
	mutex_unlock(&me->smd_mutex);
	mutex_unlock(&chan->mut);
}

static int fastrpc_file_free(struct fastrpc_file *fl)
@@ -2243,7 +2247,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
	}
	if (fl->ssrcount == fl->apps->channel[cid].ssrcount)
		kref_put_mutex(&fl->apps->channel[cid].kref,
				fastrpc_channel_close, &fl->apps->smd_mutex);
			fastrpc_channel_close, &fl->apps->channel[cid].mut);
	if (fl->sctx)
		fastrpc_session_free(&fl->apps->channel[cid], fl->sctx);
	if (fl->secsctx)
@@ -2320,6 +2324,20 @@ static int fastrpc_glink_register(int cid, struct fastrpc_apps *me)
	return err;
}

static void fastrpc_glink_stop(int cid)
{
	int err = 0;
	struct fastrpc_glink_info *link;

	VERIFY(err, (cid >= 0 && cid < NUM_CHANNELS));
	if (err)
		return;
	link = &gfa.channel[cid].link;

	if (link->port_state == FASTRPC_LINK_CONNECTED)
		link->port_state = FASTRPC_LINK_REMOTE_DISCONNECTING;
}

static void fastrpc_glink_close(void *chan, int cid)
{
	int err = 0;
@@ -2330,7 +2348,8 @@ static void fastrpc_glink_close(void *chan, int cid)
		return;
	link = &gfa.channel[cid].link;

	if (link->port_state == FASTRPC_LINK_CONNECTED) {
	if (link->port_state == FASTRPC_LINK_CONNECTED ||
		link->port_state == FASTRPC_LINK_REMOTE_DISCONNECTING) {
		link->port_state = FASTRPC_LINK_DISCONNECTING;
		glink_close(chan);
	}
@@ -2496,12 +2515,14 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
	struct fastrpc_apps *me = &gfa;
	int cid, err = 0;

	mutex_lock(&me->smd_mutex);

	VERIFY(err, fl && fl->sctx);
	if (err)
		goto bail;
		return err;
	cid = fl->cid;
	VERIFY(err, cid >= 0 && cid < NUM_CHANNELS);
	if (err)
		goto bail;
	mutex_lock(&me->channel[cid].mut);
	if (me->channel[cid].ssrcount !=
				 me->channel[cid].prevssrcount) {
		if (!me->channel[cid].issubsystemup) {
@@ -2510,9 +2531,6 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
				goto bail;
		}
	}
	VERIFY(err, cid >= 0 && cid < NUM_CHANNELS);
	if (err)
		goto bail;
	fl->ssrcount = me->channel[cid].ssrcount;
	if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) ||
	    (me->channel[cid].chan == NULL)) {
@@ -2523,9 +2541,11 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
		if (err)
			goto bail;

		mutex_unlock(&me->channel[cid].mut);
		VERIFY(err,
			 wait_for_completion_timeout(&me->channel[cid].workport,
						RPC_TIMEOUT));
		mutex_lock(&me->channel[cid].mut);
		if (err) {
			me->channel[cid].chan = NULL;
			goto bail;
@@ -2533,8 +2553,10 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
		kref_init(&me->channel[cid].kref);
		pr_info("'opened /dev/%s c %d %d'\n", gcinfo[cid].name,
						MAJOR(me->dev_no), cid);
		err = glink_queue_rx_intent(me->channel[cid].chan, NULL, 16);
		err |= glink_queue_rx_intent(me->channel[cid].chan, NULL, 64);
		err = glink_queue_rx_intent(me->channel[cid].chan, NULL,
			FASTRPC_GLINK_INTENT_LEN);
		err |= glink_queue_rx_intent(me->channel[cid].chan, NULL,
			FASTRPC_GLINK_INTENT_LEN);
		if (err)
			pr_warn("adsprpc: initial intent fail for %d err %d\n",
					 cid, err);
@@ -2548,7 +2570,7 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
	}

bail:
	mutex_unlock(&me->smd_mutex);
	mutex_unlock(&me->channel[cid].mut);
	return err;
}

@@ -2826,16 +2848,14 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb,
	ctx = container_of(nb, struct fastrpc_channel_ctx, nb);
	cid = ctx - &me->channel[0];
	if (code == SUBSYS_BEFORE_SHUTDOWN) {
		mutex_lock(&me->smd_mutex);
		mutex_lock(&ctx->mut);
		ctx->ssrcount++;
		ctx->issubsystemup = 0;
		if (ctx->chan) {
			fastrpc_glink_close(ctx->chan, cid);
			ctx->chan = NULL;
			pr_info("'restart notifier: closed /dev/%s c %d %d'\n",
		pr_info("'restart notifier: /dev/%s c %d %d'\n",
			 gcinfo[cid].name, MAJOR(me->dev_no), cid);
		}
		mutex_unlock(&me->smd_mutex);
		if (ctx->chan)
			fastrpc_glink_stop(cid);
		mutex_unlock(&ctx->mut);
		if (cid == 0)
			me->staticpd_flags = 0;
		fastrpc_notify_drivers(me, cid);
@@ -3000,15 +3020,15 @@ static int fastrpc_probe(struct platform_device *pdev)

static void fastrpc_deinit(void)
{
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_channel_ctx *chan = gcinfo;
	int i, j;

	for (i = 0; i < NUM_CHANNELS; i++, chan++) {
		if (chan->chan) {
			kref_put_mutex(&chan->kref,
				fastrpc_channel_close, &me->smd_mutex);
				fastrpc_channel_close, &chan->mut);
			chan->chan = NULL;
			mutex_destroy(&chan->mut);
		}
		for (j = 0; j < NUM_SESSIONS; j++) {
			struct fastrpc_session_ctx *sess = &chan->session[j];