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

Commit cd6fd445 authored by Mohammed Javid's avatar Mohammed Javid Committed by Akshay Pandit
Browse files

ipa: Add support in ipa-usb driver for rmnet_cv2x



Only one RmNET instance is supported till now, so
there was a check to not to support additional
protocol in ipa usb driver.
With respect to auto use case requirement we need to
support two rmnet instance, newly added rmnet_cv2x
along with legacy rmnet.
Modify code to support additional rmnet_cv2x teth
interface with respect to protocol, pm states.

Change-Id: I83984de859919a395f1115c8e2a37004d01f0688
Signed-off-by: default avatarMohammed Javid <mjavid@codeaurora.org>
parent 9c638b3e
Loading
Loading
Loading
Loading
+132 −27
Original line number Diff line number Diff line
@@ -144,13 +144,15 @@ enum ipa3_usb_state {
enum ipa3_usb_transport_type {
	IPA_USB_TRANSPORT_TETH,
	IPA_USB_TRANSPORT_DPL,
	IPA_USB_TRANSPORT_TETH_2,
	IPA_USB_TRANSPORT_MAX
};

/* Get transport type from tethering protocol */
#define IPA3_USB_GET_TTYPE(__teth_prot) \
	(((__teth_prot) == IPA_USB_DIAG) ? \
	IPA_USB_TRANSPORT_DPL : IPA_USB_TRANSPORT_TETH)
	IPA_USB_TRANSPORT_DPL : (((__teth_prot) == IPA_USB_RMNET_CV2X) ? \
	IPA_USB_TRANSPORT_TETH_2 : IPA_USB_TRANSPORT_TETH))

/* Does the given transport type is DPL? */
#define IPA3_USB_IS_TTYPE_DPL(__ttype) \
@@ -204,7 +206,7 @@ struct ipa3_usb_context {
	struct ipa3_usb_teth_prot_context
		teth_prot_ctx[IPA_USB_MAX_TETH_PROT_SIZE];
	int num_init_prot; /* without dpl */
	struct teth_bridge_init_params teth_bridge_params;
	struct teth_bridge_init_params teth_bridge_params[IPA_TETH_BRIDGE_MAX];
	struct completion dev_ready_comp;
	u32 qmi_req_id;
	spinlock_t state_lock;
@@ -770,6 +772,8 @@ static char *ipa3_usb_teth_prot_to_string(enum ipa_usb_teth_prot teth_prot)
	case IPA_USB_RMNET:
	case IPA_USB_MBIM:
		return "teth_bridge";
	case IPA_USB_RMNET_CV2X:
		return "teth_bridge_cv2x";
	case IPA_USB_DIAG:
		return "dpl";
	default:
@@ -785,6 +789,8 @@ static char *ipa3_usb_teth_bridge_prot_to_string(
	switch (teth_prot) {
	case IPA_USB_RMNET:
		return "rmnet";
	case IPA_USB_RMNET_CV2X:
		return "rmnet_cv2x";
	case IPA_USB_MBIM:
		return "mbim";
	default:
@@ -794,11 +800,18 @@ static char *ipa3_usb_teth_bridge_prot_to_string(
	return "unsupported";
}

static int ipa3_usb_init_teth_bridge(void)
static int ipa3_usb_init_teth_bridge(enum ipa_usb_teth_prot teth_prot)
{
	int result;

	result = teth_bridge_init(&ipa3_usb_ctx->teth_bridge_params);
	if (teth_prot == IPA_USB_RMNET_CV2X)
		result =
		teth_bridge_init(
		&ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2]);
	else
		result =
		teth_bridge_init(
		&ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1]);
	if (result) {
		IPA_USB_ERR("Failed to initialize teth_bridge\n");
		return result;
@@ -812,15 +825,26 @@ static int ipa3_usb_register_pm(enum ipa3_usb_transport_type ttype)
	struct ipa3_usb_transport_type_ctx *ttype_ctx =
		&ipa3_usb_ctx->ttype_ctx[ttype];
	int result;
	enum ipa_client_type consumer;

	/*
	 * One PM resource for teth1,
	 * One PM resource for teth2 (CV2X),
	 * One for DPL,
	 */

	/* there is one PM resource for teth and one for DPL */
	if (!IPA3_USB_IS_TTYPE_DPL(ttype) && ipa3_usb_ctx->num_init_prot > 0)
	if (!IPA3_USB_IS_TTYPE_DPL(ttype) && (ipa3_usb_ctx->num_init_prot > 0)
		&& (ttype != IPA_USB_TRANSPORT_TETH_2))
		return 0;

	memset(&ttype_ctx->pm_ctx.reg_params, 0,
		sizeof(ttype_ctx->pm_ctx.reg_params));
	ttype_ctx->pm_ctx.reg_params.name = (ttype == IPA_USB_TRANSPORT_DPL) ?
				"USB DPL" : "USB";
	ttype_ctx->pm_ctx.reg_params.name =
				(ttype == IPA_USB_TRANSPORT_DPL) ?
				"USB DPL" :
				(ttype == IPA_USB_TRANSPORT_TETH_2) ?
				"USB2" : "USB";

	ttype_ctx->pm_ctx.reg_params.callback = ipa3_usb_pm_cb;
	ttype_ctx->pm_ctx.reg_params.user_data = ttype_ctx;
	ttype_ctx->pm_ctx.reg_params.group = IPA_PM_GROUP_DEFAULT;
@@ -832,9 +856,12 @@ static int ipa3_usb_register_pm(enum ipa3_usb_transport_type ttype)
		goto fail_pm_reg;
	}

	consumer = (ttype == IPA_USB_TRANSPORT_DPL) ?
		IPA_CLIENT_USB_DPL_CONS :
		(ttype == IPA_USB_TRANSPORT_TETH_2) ?
		IPA_CLIENT_USB2_CONS : IPA_CLIENT_USB_CONS;
	result = ipa_pm_associate_ipa_cons_to_client(ttype_ctx->pm_ctx.hdl,
		(ttype == IPA_USB_TRANSPORT_DPL) ?
		IPA_CLIENT_USB_DPL_CONS : IPA_CLIENT_USB_CONS);
		consumer);
	if (result) {
		IPA_USB_ERR("fail to associate cons with PM %d\n", result);
		goto fail_pm_cons;
@@ -1121,9 +1148,11 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot,
			goto bad_params;
		}
		ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = user_data;
		result = ipa3_usb_init_teth_bridge();

		result = ipa3_usb_init_teth_bridge(teth_prot);
		if (result)
			goto teth_prot_init_fail;

		ipa3_usb_ctx->teth_prot_ctx[teth_prot].state =
			IPA_USB_TETH_PROT_INITIALIZED;
		ipa3_usb_ctx->num_init_prot++;
@@ -1139,6 +1168,26 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot,
		ipa3_register_client_callback(&ipa_usb_set_lock_unlock,
			&ipa3_usb_get_teth_port_state, IPA_CLIENT_USB_PROD);
		break;
	case IPA_USB_RMNET_CV2X:
		if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state !=
			IPA_USB_TETH_PROT_INVALID) {
			IPA_USB_DBG("%s already initialized\n",
				ipa3_usb_teth_prot_to_string(teth_prot));
			result = -EPERM;
			goto bad_params;
		}
		ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = user_data;

		result = ipa3_usb_init_teth_bridge(teth_prot);
		if (result)
			goto teth_prot_init_fail;

		ipa3_usb_ctx->teth_prot_ctx[teth_prot].state =
			IPA_USB_TETH_PROT_INITIALIZED;
		IPA_USB_DBG("initialized %s %s\n",
			ipa3_usb_teth_prot_to_string(teth_prot),
			ipa3_usb_teth_bridge_prot_to_string(teth_prot));
		break;
	case IPA_USB_DIAG:
		if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state !=
			IPA_USB_TETH_PROT_INVALID) {
@@ -1166,7 +1215,8 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot,

teth_prot_init_fail:
	if ((IPA3_USB_IS_TTYPE_DPL(ttype))
		|| (ipa3_usb_ctx->num_init_prot == 0)) {
		|| (ipa3_usb_ctx->num_init_prot == 0)
		|| (teth_prot == IPA_USB_RMNET_CV2X)) {
		if (ipa_pm_is_used()) {
			ipa3_usb_deregister_pm(ttype);
		} else {
@@ -1249,6 +1299,7 @@ static bool ipa3_usb_check_chan_params(struct ipa_usb_xdci_chan_params *params)
		}
		break;
	case IPA_USB_RMNET:
	case IPA_USB_RMNET_CV2X:
	case IPA_USB_MBIM:
		if (ipa3_usb_ctx->teth_prot_ctx[params->teth_prot].state ==
			IPA_USB_TETH_PROT_INVALID) {
@@ -1319,7 +1370,6 @@ static int ipa3_usb_smmu_map_xdci_channel(
		ipa3_usb_ctx->smmu_reg_map.cnt--;
	}


	result = ipa3_smmu_map_peer_buff(params->xfer_ring_base_addr_iova,
		params->xfer_ring_len, map, params->sgt_xfer_rings,
		IPA_SMMU_CB_AP);
@@ -1396,11 +1446,19 @@ static int ipa3_usb_request_xdci_channel(
	case IPA_USB_RMNET:
	case IPA_USB_MBIM:
		chan_params.priv =
			ipa3_usb_ctx->teth_bridge_params.private_data;
	ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].private_data;
		chan_params.notify =
	ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].usb_notify_cb;
		chan_params.skip_ep_cfg =
	ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].skip_ep_cfg;
		break;
	case IPA_USB_RMNET_CV2X:
		chan_params.priv =
	ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].private_data;
		chan_params.notify =
			ipa3_usb_ctx->teth_bridge_params.usb_notify_cb;
	ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].usb_notify_cb;
		chan_params.skip_ep_cfg =
			ipa3_usb_ctx->teth_bridge_params.skip_ep_cfg;
	ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].skip_ep_cfg;
		break;
	case IPA_USB_DIAG:
		chan_params.priv = NULL;
@@ -1703,6 +1761,16 @@ static int ipa3_usb_connect_dpl(void)
	return 0;
}

static int ipa3_get_tethering_mode(enum ipa_usb_teth_prot teth_prot)
{
	if (teth_prot == IPA_USB_RMNET)
		return TETH_TETHERING_MODE_RMNET;
	else if (teth_prot == IPA_USB_RMNET_CV2X)
		return TETH_TETHERING_MODE_RMNET_2;
	else
		return TETH_TETHERING_MODE_MBIM;
}

static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot)
{
	int result;
@@ -1771,6 +1839,7 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot)
			ipa3_usb_teth_prot_to_string(teth_prot));
		break;
	case IPA_USB_RMNET:
	case IPA_USB_RMNET_CV2X:
	case IPA_USB_MBIM:
		if (teth_prot_ptr->state ==
			IPA_USB_TETH_PROT_CONNECTED) {
@@ -1778,7 +1847,8 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot)
				ipa3_usb_teth_prot_to_string(teth_prot));
			break;
		}
		result = ipa3_usb_init_teth_bridge();

		result = ipa3_usb_init_teth_bridge(teth_prot);
		if (result)
			return result;

@@ -1789,14 +1859,19 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot)
		teth_bridge_params.usb_ipa_pipe_hdl =
			teth_conn_params->usb_to_ipa_clnt_hdl;
		teth_bridge_params.tethering_mode =
			(teth_prot == IPA_USB_RMNET) ?
			(TETH_TETHERING_MODE_RMNET):(TETH_TETHERING_MODE_MBIM);
			ipa3_get_tethering_mode(teth_prot);

		if (teth_prot == IPA_USB_RMNET_CV2X)
			teth_bridge_params.client_type = IPA_CLIENT_USB2_PROD;
		else
			teth_bridge_params.client_type = IPA_CLIENT_USB_PROD;

		result = ipa3_usb_connect_teth_bridge(&teth_bridge_params);
		if (result) {
			ipa3_usb_ctx->ttype_ctx[ttype].user_data = NULL;
			return result;
		}

		ipa3_usb_ctx->teth_prot_ctx[teth_prot].state =
			IPA_USB_TETH_PROT_CONNECTED;
		ipa3_usb_notify_do(ttype, IPA_USB_DEVICE_READY);
@@ -1835,11 +1910,15 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot)
	return 0;
}

static int ipa3_usb_disconnect_teth_bridge(void)
static int ipa3_usb_disconnect_teth_bridge(enum ipa_usb_teth_prot teth_prot)
{
	int result;

	if (teth_prot == IPA_USB_RMNET_CV2X)
		result = teth_bridge_disconnect(IPA_CLIENT_USB2_PROD);
	else
		result = teth_bridge_disconnect(IPA_CLIENT_USB_PROD);

	if (result) {
		IPA_USB_ERR("failed to disconnect teth_bridge\n");
		return result;
@@ -1904,6 +1983,7 @@ static int ipa3_usb_disconnect_teth_prot(enum ipa_usb_teth_prot teth_prot)
			ipa3_usb_teth_prot_to_string(teth_prot));
		break;
	case IPA_USB_RMNET:
	case IPA_USB_RMNET_CV2X:
	case IPA_USB_MBIM:
		if (teth_prot_ptr->state != IPA_USB_TETH_PROT_CONNECTED) {
			IPA_USB_DBG("%s (%s) is not connected\n",
@@ -1911,7 +1991,8 @@ static int ipa3_usb_disconnect_teth_prot(enum ipa_usb_teth_prot teth_prot)
				ipa3_usb_teth_bridge_prot_to_string(teth_prot));
			return -EPERM;
		}
		result = ipa3_usb_disconnect_teth_bridge();

		result = ipa3_usb_disconnect_teth_bridge(teth_prot);
		if (result)
			break;

@@ -1957,8 +2038,7 @@ static int ipa3_usb_xdci_connect_internal(
		return -EINVAL;
	}

	ttype = (params->teth_prot == IPA_USB_DIAG) ? IPA_USB_TRANSPORT_DPL :
		IPA_USB_TRANSPORT_TETH;
	ttype = IPA3_USB_GET_TTYPE(params->teth_prot);

	if (!ipa3_usb_check_legal_op(IPA_USB_OP_CONNECT, ttype)) {
		IPA_USB_ERR("Illegal operation\n");
@@ -2159,7 +2239,9 @@ static int ipa3_usb_get_status_dbg_info(struct ipa3_usb_status_dbg_info *status)
	for (i = 0 ; i < IPA_USB_MAX_TETH_PROT_SIZE ; i++) {
		if (ipa3_usb_ctx->teth_prot_ctx[i].state ==
			IPA_USB_TETH_PROT_INITIALIZED) {
			if ((i == IPA_USB_RMNET) || (i == IPA_USB_MBIM))
			if ((i == IPA_USB_RMNET) ||
				(i == IPA_USB_MBIM) ||
				(i == IPA_USB_RMNET_CV2X))
				status->inited_prots[status->num_init_prot++] =
					ipa3_usb_teth_bridge_prot_to_string(i);
			else
@@ -2169,6 +2251,7 @@ static int ipa3_usb_get_status_dbg_info(struct ipa3_usb_status_dbg_info *status)
			IPA_USB_TETH_PROT_CONNECTED) {
			switch (i) {
			case IPA_USB_RMNET:
			case IPA_USB_RMNET_CV2X:
			case IPA_USB_MBIM:
				status->teth_connected_prot =
					ipa3_usb_teth_bridge_prot_to_string(i);
@@ -2652,6 +2735,24 @@ int ipa_usb_deinit_teth_prot(enum ipa_usb_teth_prot teth_prot)
			ipa3_usb_teth_prot_to_string(teth_prot),
			ipa3_usb_teth_bridge_prot_to_string(teth_prot));
		break;
	case IPA_USB_RMNET_CV2X:
		if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state !=
			IPA_USB_TETH_PROT_INITIALIZED) {
			IPA_USB_ERR("%s (%s) is not initialized\n",
				ipa3_usb_teth_prot_to_string(teth_prot),
				ipa3_usb_teth_bridge_prot_to_string(teth_prot));
			result = -EINVAL;
			goto bad_params;
		}

		ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data =
			NULL;
		ipa3_usb_ctx->teth_prot_ctx[teth_prot].state =
			IPA_USB_TETH_PROT_INVALID;
		IPA_USB_DBG("deinitialized %s (%s)\n",
			ipa3_usb_teth_prot_to_string(teth_prot),
			ipa3_usb_teth_bridge_prot_to_string(teth_prot));
		break;
	case IPA_USB_DIAG:
		if (teth_prot_ptr->state !=
			IPA_USB_TETH_PROT_INITIALIZED) {
@@ -2672,7 +2773,8 @@ int ipa_usb_deinit_teth_prot(enum ipa_usb_teth_prot teth_prot)
	}

	if (IPA3_USB_IS_TTYPE_DPL(ttype) ||
		(ipa3_usb_ctx->num_init_prot == 0)) {
		(ipa3_usb_ctx->num_init_prot == 0) ||
		(teth_prot == IPA_USB_RMNET_CV2X)) {
		if (!ipa3_usb_set_state(IPA_USB_INVALID, false, ttype))
			IPA_USB_ERR(
				"failed to change state to invalid\n");
@@ -3121,6 +3223,9 @@ static int __init ipa3_usb_init(void)
	pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
	pm_ctx->hdl = ~0;
	pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work;
	pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH_2].pm_ctx;
	pm_ctx->hdl = ~0;
	pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work;
	pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
	pm_ctx->hdl = ~0;
	pm_ctx->remote_wakeup_work = &ipa3_usb_dpl_notify_remote_wakeup_work;
+7 −0
Original line number Diff line number Diff line
@@ -3584,13 +3584,20 @@ void ipa3_q6_pre_shutdown_cleanup(void)
	/* Remove delay from Q6 PRODs to avoid pending descriptors
	 * on pipe reset procedure
	 */

	if (!ipa3_ctx->ipa_endp_delay_wa) {
		ipa3_q6_pipe_delay(false);
		ipa3_set_reset_client_prod_pipe_delay(true,
			IPA_CLIENT_USB_PROD);
		if (ipa3_ctx->ipa_config_is_auto)
			ipa3_set_reset_client_prod_pipe_delay(true,
				IPA_CLIENT_USB2_PROD);
	} else {
		ipa3_start_stop_client_prod_gsi_chnl(IPA_CLIENT_USB_PROD,
						false);
		if (ipa3_ctx->ipa_config_is_auto)
			ipa3_start_stop_client_prod_gsi_chnl(
				IPA_CLIENT_USB2_PROD, false);
	}

	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+1 −1
Original line number Diff line number Diff line
@@ -2586,7 +2586,7 @@ int ipa3_teth_bridge_disconnect(enum ipa_client_type client);

int ipa3_teth_bridge_connect(struct teth_bridge_connect_params *connect_params);

int ipa3_teth_bridge_get_pm_hdl(void);
int ipa3_teth_bridge_get_pm_hdl(enum ipa_client_type client);

/*
 * Tethering client info
+2 −0
Original line number Diff line number Diff line
@@ -3002,6 +3002,7 @@ bool ipa3_should_pipe_be_suspended(enum ipa_client_type client)
		return false;

	if (client == IPA_CLIENT_USB_CONS     ||
		client == IPA_CLIENT_USB2_CONS    ||
	    client == IPA_CLIENT_USB_DPL_CONS ||
	    client == IPA_CLIENT_MHI_CONS     ||
	    client == IPA_CLIENT_MHI_DPL_CONS ||
@@ -5081,6 +5082,7 @@ int ipa3_write_qmap_id(struct ipa_ioc_write_qmapid *param_in)

	meta.qmap_id = param_in->qmap_id;
	if (param_in->client == IPA_CLIENT_USB_PROD ||
		param_in->client == IPA_CLIENT_USB2_PROD ||
	    param_in->client == IPA_CLIENT_HSIC1_PROD ||
	    param_in->client == IPA_CLIENT_ODU_PROD ||
	    param_in->client == IPA_CLIENT_ETHERNET_PROD ||
+56 −17
Original line number Diff line number Diff line
@@ -38,6 +38,12 @@
#define TETH_ERR(fmt, args...) \
	pr_err(TETH_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)

enum ipa_num_teth_iface {
	IPA_TETH_IFACE_1 = 0,
	IPA_TETH_IFACE_2 = 1,
	IPA_TETH_IFACE_MAX
};

/**
 * struct ipa3_teth_bridge_ctx - Tethering bridge driver context information
 * @class: kernel class pointer
@@ -50,7 +56,7 @@ struct ipa3_teth_bridge_ctx {
	dev_t dev_num;
	struct device *dev;
	struct cdev cdev;
	u32 modem_pm_hdl;
	u32 modem_pm_hdl[IPA_TETH_IFACE_MAX];
};
static struct ipa3_teth_bridge_ctx *ipa3_teth_ctx;

@@ -121,19 +127,25 @@ int ipa3_teth_bridge_init(struct teth_bridge_init_params *params)
 * Return codes: handle
 *		-EINVAL - Bad parameter
 */
int ipa3_teth_bridge_get_pm_hdl(void)
int ipa3_teth_bridge_get_pm_hdl(enum ipa_client_type client)
{
	u32 pm_hdl;

	TETH_DBG_FUNC_ENTRY();
	if (client == IPA_CLIENT_USB2_PROD)
		pm_hdl = ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2];
	else
		pm_hdl = ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1];

	if (ipa3_teth_ctx->modem_pm_hdl == ~0) {
	if (pm_hdl == ~0) {
		TETH_ERR("Bad parameter\n");
		TETH_DBG_FUNC_EXIT();
		return -EINVAL;
	}

	TETH_DBG("Return rm-handle %d\n", ipa3_teth_ctx->modem_pm_hdl);
	TETH_DBG("Return pm-handle %d\n", pm_hdl);
	TETH_DBG_FUNC_EXIT();
	return ipa3_teth_ctx->modem_pm_hdl;
	return pm_hdl;
}

/**
@@ -142,22 +154,33 @@ int ipa3_teth_bridge_get_pm_hdl(void)
int ipa3_teth_bridge_disconnect(enum ipa_client_type client)
{
	int res = 0;
	int *pm_hdl = NULL;

	TETH_DBG_FUNC_ENTRY();
	if (ipa_pm_is_used()) {
		res = ipa_pm_deactivate_sync(ipa3_teth_ctx->modem_pm_hdl);

		if (client == IPA_CLIENT_USB2_PROD)
			pm_hdl = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2];
		else
			pm_hdl = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1];

		res = ipa_pm_deactivate_sync(*pm_hdl);
		if (res) {
			TETH_ERR("fail to deactivate modem %d\n", res);
			return res;
		}
		res = ipa_pm_deregister(ipa3_teth_ctx->modem_pm_hdl);
		ipa3_teth_ctx->modem_pm_hdl = ~0;
		res = ipa_pm_deregister(*pm_hdl);
		*pm_hdl = ~0;
	} else {
		if (client == IPA_CLIENT_USB2_PROD) {
			TETH_ERR("No support for rm added/validated.\n");
		} else {
			ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
				IPA_RM_RESOURCE_Q6_CONS);
			ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
				IPA_RM_RESOURCE_USB_CONS);
		}
	}
	TETH_DBG_FUNC_EXIT();

	return res;
@@ -176,22 +199,36 @@ int ipa3_teth_bridge_connect(struct teth_bridge_connect_params *connect_params)
{
	int res = 0;
	struct ipa_pm_register_params reg_params;
	u32 *pm = NULL;

	memset(&reg_params, 0, sizeof(reg_params));

	TETH_DBG_FUNC_ENTRY();

	if (ipa_pm_is_used()) {
		if (connect_params->tethering_mode ==
			TETH_TETHERING_MODE_RMNET_2) {
			reg_params.name = "MODEM (USB RMNET_CV2X)";
			pm = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2];
		} else {
			reg_params.name = "MODEM (USB RMNET)";
			pm = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1];
		}
		reg_params.group = IPA_PM_GROUP_MODEM;
		reg_params.skip_clk_vote = true;
		res = ipa_pm_register(&reg_params,
			&ipa3_teth_ctx->modem_pm_hdl);
			pm);
		if (res) {
			TETH_ERR("fail to register with PM %d\n", res);
			return res;
		}
		res = ipa_pm_activate_sync(ipa3_teth_ctx->modem_pm_hdl);
		res = ipa_pm_activate_sync(*pm);
		goto bail;
	}

	if (connect_params->tethering_mode == TETH_TETHERING_MODE_RMNET_2) {
		res = -EINVAL;
		TETH_ERR("No support for rm added/validated.\n");
		goto bail;
	}

@@ -246,7 +283,7 @@ static const struct file_operations ipa3_teth_bridge_drv_fops = {
 */
int ipa3_teth_bridge_driver_init(void)
{
	int res;
	int res, i;

	TETH_DBG("Tethering bridge driver init\n");
	ipa3_teth_ctx = kzalloc(sizeof(*ipa3_teth_ctx), GFP_KERNEL);
@@ -285,7 +322,9 @@ int ipa3_teth_bridge_driver_init(void)
		goto fail_cdev_add;
	}

	ipa3_teth_ctx->modem_pm_hdl = ~0;
	for (i = 0; i < IPA_TETH_IFACE_MAX; i++)
		ipa3_teth_ctx->modem_pm_hdl[i] = ~0;

	TETH_DBG("Tethering bridge driver init OK\n");

	return 0;
Loading