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

Commit 5d5f0e3f authored by Utkarsh Saxena's avatar Utkarsh Saxena
Browse files

msm: ipa: disconnect sequence change for USB 2.0



For USB 2.0 there is a requirement to not to flush the
USB endpoints after the pipes are disconnected. Otherwise
this can result into NOC errors. Make a change to modify the
disconnect sequence as below.

1) USB driver first disable the pipes
2) New API is provided from IPA to disable the endpoint.
3) As part of disable, make sure pipes are empty and reset
the pipes.
4) USB resets its BAM and flushes the ep.
5) USB then disconnects both IPA and USB pipes.

Change-Id: I917f025678e6abb03058d5be4ec42d9e6d76835f
Acked-by: default avatarChaitanya Pratapa <cpratapa@qti.qualcomm.com>
Signed-off-by: default avatarUtkarsh Saxena <usaxena@codeaurora.org>
parent e99d73e0
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -251,6 +251,24 @@ int ipa_reset_endpoint(u32 clnt_hdl)
}
EXPORT_SYMBOL(ipa_reset_endpoint);

/**
* ipa_disable_endpoint() - Disable an endpoint from IPA perspective
* @clnt_hdl:	[in] IPA client handle
*
* Returns:	0 on success, negative on failure
*
* Note:		Should not be called from atomic context
*/
int ipa_disable_endpoint(u32 clnt_hdl)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_disable_endpoint, clnt_hdl);

	return ret;
}
EXPORT_SYMBOL(ipa_disable_endpoint);


/**
 * ipa_cfg_ep - IPA end-point configuration
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ struct ipa_api_controller {

	int (*ipa_clear_endpoint_delay)(u32 clnt_hdl);

	int (*ipa_disable_endpoint)(u32 clnt_hdl);

	int (*ipa_cfg_ep)(u32 clnt_hdl, const struct ipa_ep_cfg *ipa_ep_cfg);

	int (*ipa_cfg_ep_nat)(u32 clnt_hdl,
+96 −15
Original line number Diff line number Diff line
@@ -560,23 +560,31 @@ int ipa2_disconnect(u32 clnt_hdl)
	if (!ep->keep_ipa_awake)
		IPA_ACTIVE_CLIENTS_INC_EP(client_type);

	/* For USB 2.0 controller, first the ep will be disabled.
	 * so this sequence is not needed again when disconnecting the pipe.
	 */
	if (!ep->ep_disabled) {
		/* Set Disconnect in Progress flag. */
		spin_lock(&ipa_ctx->disconnect_lock);
		ep->disconnect_in_progress = true;
		spin_unlock(&ipa_ctx->disconnect_lock);

	/* Notify uc to stop monitoring holb on USB BAM Producer pipe. */
		/* Notify uc to stop monitoring holb on USB BAM
		 * Producer pipe.
		 */
		if (IPA_CLIENT_IS_USB_CONS(ep->client)) {
			ipa_uc_monitor_holb(ep->client, false);
		IPADBG("Disabling holb monitor for client: %d\n", ep->client);
			IPADBG("Disabling holb monitor for client: %d\n",
				ep->client);
		}

		result = ipa_disable_data_path(clnt_hdl);
		if (result) {
		IPAERR("disable data path failed res=%d clnt=%d.\n", result,
				clnt_hdl);
			IPAERR("disable data path failed res=%d clnt=%d.\n",
				result, clnt_hdl);
			return -EPERM;
		}
	}

	result = sps_disconnect(ep->ep_hdl);
	if (result) {
@@ -783,6 +791,79 @@ int ipa2_clear_endpoint_delay(u32 clnt_hdl)
	return 0;
}

/**
 * ipa2_disable_endpoint() - low-level IPA client disable endpoint
 * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
 *
 * Should be called by the driver of the peripheral that wants to
 * disable the pipe from IPA in BAM-BAM mode.
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa2_disable_endpoint(u32 clnt_hdl)
{
	int result;
	struct ipa_ep_context *ep;
	enum ipa_client_type client_type;
	unsigned long bam;

	if (unlikely(!ipa_ctx)) {
		IPAERR("IPA driver was not initialized\n");
		return -EINVAL;
	}

	if (clnt_hdl >= ipa_ctx->ipa_num_pipes ||
		ipa_ctx->ep[clnt_hdl].valid == 0) {
		IPAERR("bad parm.\n");
		return -EINVAL;
	}

	ep = &ipa_ctx->ep[clnt_hdl];
	client_type = ipa2_get_client_mapping(clnt_hdl);
	if (!ep->keep_ipa_awake)
		IPA_ACTIVE_CLIENTS_INC_EP(client_type);

	/* Set Disconnect in Progress flag. */
	spin_lock(&ipa_ctx->disconnect_lock);
	ep->disconnect_in_progress = true;
	spin_unlock(&ipa_ctx->disconnect_lock);

	/* Notify uc to stop monitoring holb on USB BAM Producer pipe. */
	if (IPA_CLIENT_IS_USB_CONS(ep->client)) {
		ipa_uc_monitor_holb(ep->client, false);
		IPADBG("Disabling holb monitor for client: %d\n", ep->client);
	}

	result = ipa_disable_data_path(clnt_hdl);
	if (result) {
		IPAERR("disable data path failed res=%d clnt=%d.\n", result,
				clnt_hdl);
		return -EPERM;
	}

	if (IPA_CLIENT_IS_CONS(ep->client))
		bam = ep->connect.source;
	else
		bam = ep->connect.destination;

	result = sps_pipe_reset(bam, clnt_hdl);
	if (result) {
		IPAERR("SPS pipe reset failed.\n");
		return -EPERM;
	}

	ep->ep_disabled = true;

	IPA_ACTIVE_CLIENTS_DEC_EP(client_type);

	IPADBG("client (ep: %d) disabled\n", clnt_hdl);

	return 0;
}


/**
 * ipa_sps_connect_safe() - connect endpoint from BAM prespective
 * @h: [in] sps pipe handle
+6 −0
Original line number Diff line number Diff line
@@ -546,6 +546,7 @@ struct ipa_ep_context {
	bool disconnect_in_progress;
	u32 qmi_request_sent;
	enum ipa_wakelock_ref_client wakelock_client;
	bool ep_disabled;

	/* sys MUST be the last element of this struct */
	struct ipa_sys_context *sys;
@@ -1417,6 +1418,11 @@ int ipa2_reset_endpoint(u32 clnt_hdl);
 */
int ipa2_clear_endpoint_delay(u32 clnt_hdl);

/*
 * Disable ep
 */
int ipa2_disable_endpoint(u32 clnt_hdl);

/*
 * Configuration
 */
+1 −0
Original line number Diff line number Diff line
@@ -4984,6 +4984,7 @@ int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type,
	api_ctrl->ipa_disconnect = ipa2_disconnect;
	api_ctrl->ipa_reset_endpoint = ipa2_reset_endpoint;
	api_ctrl->ipa_clear_endpoint_delay = ipa2_clear_endpoint_delay;
	api_ctrl->ipa_disable_endpoint = ipa2_disable_endpoint;
	api_ctrl->ipa_cfg_ep = ipa2_cfg_ep;
	api_ctrl->ipa_cfg_ep_nat = ipa2_cfg_ep_nat;
	api_ctrl->ipa_cfg_ep_hdr = ipa2_cfg_ep_hdr;
Loading