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

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

Merge "soc: qcom: glink: Fix parallel migration issue"

parents fe2e14fd 3adf2d69
Loading
Loading
Loading
Loading
+104 −1
Original line number Diff line number Diff line
@@ -142,11 +142,28 @@ struct glink_core_xprt_ctx {
	bool qos_req_active;
	bool tx_path_activity;
	struct delayed_work pm_qos_work;
	struct glink_core_edge_ctx *edge_ctx;

	struct mutex xprt_dbgfs_lock_lhb4;
	void *log_ctx;
};

/**
 * Edge Context
 * @list_node		edge list node used by edge list
 * @name:		name of the edge
 * @edge_migration_lock:mutex lock for migration over edge
 * @edge_ref_lock:	lock for reference count
 */
struct glink_core_edge_ctx {
	struct list_head list_node;
	char name[GLINK_NAME_SIZE];
	struct mutex edge_migration_lock_lhd2;
	struct rwref_lock edge_ref_lock_lhd1;
};

static LIST_HEAD(edge_list);
static DEFINE_MUTEX(edge_list_lock_lhd0);
/**
 * Channel Context
 * @xprt_state_lhb0:	controls read/write access to channel state
@@ -953,6 +970,83 @@ err:
	return NULL;
}

/**
 * glink_core_migration_edge_lock() - gains a reference count for edge and
 *					take muted lock
 * @xprt_ctx:	transport of the edge
 */
static void glink_core_migration_edge_lock(struct glink_core_xprt_ctx *xprt_ctx)
{
	struct glink_core_edge_ctx *edge_ctx = xprt_ctx->edge_ctx;

	rwref_get(&edge_ctx->edge_ref_lock_lhd1);
	mutex_lock(&edge_ctx->edge_migration_lock_lhd2);
}

/**
 * glink_core_migration_edge_unlock() - release a reference count for edge
 *					and release muted lock.
 * @xprt_ctx:	transport of the edge
 */
static void glink_core_migration_edge_unlock(
					struct glink_core_xprt_ctx *xprt_ctx)
{
	struct glink_core_edge_ctx *edge_ctx = xprt_ctx->edge_ctx;

	mutex_unlock(&edge_ctx->edge_migration_lock_lhd2);
	rwref_put(&edge_ctx->edge_ref_lock_lhd1);
}

/**
 * glink_edge_ctx_release - Free the edge context
 * @ch_st_lock:	handle to the rwref_lock associated with the edge
 *
 * This should only be called when the reference count associated with the
 * edge goes to zero.
 */
static void glink_edge_ctx_release(struct rwref_lock *ch_st_lock)
{
	struct glink_core_edge_ctx *ctx = container_of(ch_st_lock,
					struct glink_core_edge_ctx,
						edge_ref_lock_lhd1);

	mutex_lock(&edge_list_lock_lhd0);
	list_del(&ctx->list_node);
	mutex_unlock(&edge_list_lock_lhd0);
	kfree(ctx);
}


/**
 * edge_name_to_ctx_create() - lookup a edge by name, create the edge ctx if
 *                              it is not found.
 * @xprt_ctx:	Transport to search for a matching edge.
 *
 * Return: The edge ctx corresponding to edge of @xprt_ctx.
 */
static struct glink_core_edge_ctx *edge_name_to_ctx_create(
				struct glink_core_xprt_ctx *xprt_ctx)
{
	struct glink_core_edge_ctx *edge_ctx;

	mutex_lock(&edge_list_lock_lhd0);
	list_for_each_entry(edge_ctx, &edge_list, list_node) {
		if (!strcmp(edge_ctx->name, xprt_ctx->edge)) {
			rwref_get(&edge_ctx->edge_ref_lock_lhd1);
			mutex_unlock(&edge_list_lock_lhd0);
			return edge_ctx;
		}
	}
	edge_ctx = kzalloc(sizeof(struct glink_core_edge_ctx), GFP_KERNEL);
	strlcpy(edge_ctx->name, xprt_ctx->edge, GLINK_NAME_SIZE);
	rwref_lock_init(&edge_ctx->edge_ref_lock_lhd1, glink_edge_ctx_release);
	mutex_init(&edge_ctx->edge_migration_lock_lhd2);
	INIT_LIST_HEAD(&edge_ctx->list_node);
	list_add_tail(&edge_ctx->list_node, &edge_list);
	mutex_unlock(&edge_list_lock_lhd0);
	return edge_ctx;
}

/**
 * xprt_lcid_to_ch_ctx_get() - lookup a channel by local id
 * @xprt_ctx:	Transport to search for a matching channel.
@@ -3440,6 +3534,7 @@ void glink_xprt_ctx_release(struct rwref_lock *xprt_st_lock)
	xprt_rm_dbgfs.par_name = "xprt";
	glink_debugfs_remove_recur(&xprt_rm_dbgfs);
	GLINK_INFO("%s: xprt debugfs removec\n", __func__);
	rwref_put(&xprt_ctx->edge_ctx->edge_ref_lock_lhd1);
	kthread_stop(xprt_ctx->tx_task);
	xprt_ctx->tx_task = NULL;
	glink_core_deinit_xprt_qos_cfg(xprt_ctx);
@@ -3709,6 +3804,7 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr,
	xprt_ptr->versions_entries = cfg->versions_entries;
	xprt_ptr->local_version_idx = cfg->versions_entries - 1;
	xprt_ptr->remote_version_idx = cfg->versions_entries - 1;
	xprt_ptr->edge_ctx = edge_name_to_ctx_create(xprt_ptr);
	xprt_ptr->l_features =
			cfg->versions[cfg->versions_entries - 1].features;
	if (!if_ptr->poll)
@@ -4557,11 +4653,13 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr,
	uint16_t xprt_resp;
	bool do_migrate;

	glink_core_migration_edge_lock(if_ptr->glink_core_priv);
	ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name);
	if (ctx == NULL) {
		GLINK_ERR_XPRT(if_ptr->glink_core_priv,
		       "%s: invalid rcid %u received, name '%s'\n",
		       __func__, rcid, name);
		glink_core_migration_edge_unlock(if_ptr->glink_core_priv);
		return;
	}

@@ -4570,6 +4668,7 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr,
		GLINK_ERR_CH(ctx,
		       "%s: Duplicate remote open for rcid %u, name '%s'\n",
		       __func__, rcid, name);
		glink_core_migration_edge_unlock(if_ptr->glink_core_priv);
		return;
	}

@@ -4591,6 +4690,7 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr,

	if (do_migrate)
		ch_migrate(NULL, ctx);
	glink_core_migration_edge_unlock(if_ptr->glink_core_priv);
}

/**
@@ -4604,13 +4704,14 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr,
	uint32_t lcid, uint16_t xprt_resp)
{
	struct channel_ctx *ctx;

	glink_core_migration_edge_lock(if_ptr->glink_core_priv);
	ctx = xprt_lcid_to_ch_ctx_get(if_ptr->glink_core_priv, lcid);
	if (!ctx) {
		/* unknown LCID received - this shouldn't happen */
		GLINK_ERR_XPRT(if_ptr->glink_core_priv,
				"%s: invalid lcid %u received\n", __func__,
				(unsigned)lcid);
		glink_core_migration_edge_unlock(if_ptr->glink_core_priv);
		return;
	}

@@ -4619,6 +4720,7 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr,
			"%s: unexpected open ack receive for lcid. Current state: %u. Thread: %u\n",
				__func__, ctx->local_open_state, current->pid);
		rwref_put(&ctx->ch_state_lhb2);
		glink_core_migration_edge_unlock(if_ptr->glink_core_priv);
		return;
	}

@@ -4637,6 +4739,7 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr,
		}
	}
	rwref_put(&ctx->ch_state_lhb2);
	glink_core_migration_edge_unlock(if_ptr->glink_core_priv);
}

/**