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

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

Merge "msm: ipa3: Fix to race condition in IPA client lock"

parents d00abe62 72dbdc73
Loading
Loading
Loading
Loading
+37 −23
Original line number Diff line number Diff line
@@ -644,66 +644,80 @@ int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt,
	return 0;
}

static enum ipa_client_cb_type ipa_get_client_cb_type(u32 ipa_ep_idx)
{
	enum ipa_client_type client_type;
	enum ipa_client_cb_type client_cb;

	client_type = ipa3_get_client_by_pipe(ipa_ep_idx);

	if (client_type == IPA_CLIENT_USB_PROD ||
			client_type == IPA_CLIENT_USB_CONS) {
		IPADBG("USB Client registered\n");
		client_cb = IPA_USB_CLNT;
	} else if (client_type == IPA_CLIENT_MHI_PROD ||
			client_type == IPA_CLIENT_MHI_CONS) {
		IPADBG("MHI Client registered\n");
		client_cb = IPA_MHI_CLNT;
	} else {
		IPAERR("Invalid IPA client\n");
		client_cb = IPA_MAX_CLNT;
	}

	return client_cb;
}
void ipa3_register_lock_unlock_callback(int (*client_cb)(bool is_lock),
						u32 ipa_ep_idx)
{
	struct ipa3_ep_context *ep;
	enum ipa_client_cb_type client;

	IPADBG("entry\n");

	ep = &ipa3_ctx->ep[ipa_ep_idx];

	if (!ep->valid) {
		IPAERR("Invalid EP\n");
	client = ipa_get_client_cb_type(ipa_ep_idx);
	if (client == IPA_MAX_CLNT)
		return;
	}

	if (client_cb == NULL) {
		IPAERR("Bad Param");
		return;
	}

	ep->client_lock_unlock = client_cb;
	if (!ipa3_ctx->client_lock_unlock[client])
		ipa3_ctx->client_lock_unlock[client] = client_cb;
	IPADBG("exit\n");
}

void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx)
{
	struct ipa3_ep_context *ep;
	enum ipa_client_cb_type client_cb;

	IPADBG("entry\n");

	ep = &ipa3_ctx->ep[ipa_ep_idx];

	if (!ep->valid) {
		IPAERR("Invalid EP\n");
	client_cb = ipa_get_client_cb_type(ipa_ep_idx);
	if (client_cb == IPA_MAX_CLNT)
		return;
	}

	if (ep->client_lock_unlock == NULL) {
	if (ipa3_ctx->client_lock_unlock[client_cb] == NULL) {
		IPAERR("client_lock_unlock is already NULL");
		return;
	}

	ep->client_lock_unlock = NULL;
	ipa3_ctx->client_lock_unlock[client_cb] = NULL;
	IPADBG("exit\n");
}

static void client_lock_unlock_cb(u32 ipa_ep_idx, bool is_lock)
{
	struct ipa3_ep_context *ep;
	enum ipa_client_cb_type client_cb;

	IPADBG("entry\n");

	ep = &ipa3_ctx->ep[ipa_ep_idx];

	if (!ep->valid) {
		IPAERR("Invalid EP\n");
	client_cb = ipa_get_client_cb_type(ipa_ep_idx);
	if (client_cb == IPA_MAX_CLNT)
		return;
	}

	if (ep->client_lock_unlock)
		ep->client_lock_unlock(is_lock);
	if (ipa3_ctx->client_lock_unlock[client_cb])
		ipa3_ctx->client_lock_unlock[client_cb](is_lock);

	IPADBG("exit\n");
}
+8 −2
Original line number Diff line number Diff line
@@ -782,8 +782,6 @@ struct ipa3_ep_context {
	u32 eot_in_poll_err;
	bool ep_delay_set;

	int (*client_lock_unlock)(bool is_lock);

	/* sys MUST be the last element of this struct */
	struct ipa3_sys_context *sys;
};
@@ -1377,6 +1375,12 @@ enum ipa_smmu_cb_type {
	IPA_SMMU_CB_MAX
};

enum ipa_client_cb_type {
	IPA_USB_CLNT,
	IPA_MHI_CLNT,
	IPA_MAX_CLNT
};

/**
 * struct ipa3_char_device_context - IPA character device
 * @class: pointer to the struct class
@@ -1620,6 +1624,7 @@ struct ipa3_context {
	bool vlan_mode_iface[IPA_VLAN_IF_MAX];
	bool wdi_over_pcie;
	bool fw_loaded;
	int (*client_lock_unlock[IPA_MAX_CLNT])(bool is_lock);
};

struct ipa3_plat_drv_res {
@@ -2290,6 +2295,7 @@ void ipa3_proxy_clk_unvote(void);
bool ipa3_is_client_handle_valid(u32 clnt_hdl);

enum ipa_client_type ipa3_get_client_mapping(int pipe_idx);
enum ipa_client_type ipa3_get_client_by_pipe(int pipe_idx);

void ipa_init_ep_flt_bitmap(void);

+1 −1
Original line number Diff line number Diff line
@@ -2888,7 +2888,7 @@ enum ipa_client_type ipa3_get_client_mapping(int pipe_idx)
 *
 * Return value: client type
 */
static enum ipa_client_type ipa3_get_client_by_pipe(int pipe_idx)
enum ipa_client_type ipa3_get_client_by_pipe(int pipe_idx)
{
	int j = 0;