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:
committed by
Akshay Pandit
parent
9c638b3e3a
commit
cd6fd44586
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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(®_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(®_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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user