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: Mohammed Javid <mjavid@codeaurora.org>
This commit is contained in:
Mohammed Javid
2019-07-01 03:43:21 +05:30
committed by Akshay Pandit
parent 9c638b3e3a
commit cd6fd44586
7 changed files with 208 additions and 47 deletions

View File

@@ -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;
/* 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)
/*
* One PM resource for teth1,
* One PM resource for teth2 (CV2X),
* One for DPL,
*/
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.usb_notify_cb;
ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].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_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[IPA_TETH_BRIDGE_2].usb_notify_cb;
chan_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);
teth_bridge_params.client_type = IPA_CLIENT_USB_PROD;
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;
result = teth_bridge_disconnect(IPA_CLIENT_USB_PROD);
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;

View File

@@ -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();

View File

@@ -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

View File

@@ -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 ||

View File

@@ -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)
{
TETH_DBG_FUNC_ENTRY();
u32 pm_hdl;
if (ipa3_teth_ctx->modem_pm_hdl == ~0) {
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 (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,21 +154,32 @@ 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 {
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);
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();
@@ -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()) {
reg_params.name = "MODEM (USB RMNET)";
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;

View File

@@ -747,6 +747,7 @@ struct ipa_rm_perf_profile {
enum teth_tethering_mode {
TETH_TETHERING_MODE_RMNET,
TETH_TETHERING_MODE_MBIM,
TETH_TETHERING_MODE_RMNET_2,
TETH_TETHERING_MODE_MAX,
};

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,9 +19,16 @@ enum ipa_usb_teth_prot {
IPA_USB_RMNET = 2,
IPA_USB_MBIM = 3,
IPA_USB_DIAG = 4,
IPA_USB_RMNET_CV2X = 5,
IPA_USB_MAX_TETH_PROT_SIZE
};
enum teth_bridge_params {
IPA_TETH_BRIDGE_1 = 0,
IPA_TETH_BRIDGE_2 = 1,
IPA_TETH_BRIDGE_MAX
};
/**
* ipa_usb_teth_params - parameters for RDNIS/ECM initialization API
*