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

Commit e2b42702 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ADSPRPC: Close glink channel after remote disconnected"

parents 804337ad 314a420a
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];