static struct ipa_uc_offload_ctx *ipa_uc_offload_ctx[IPA_UC_MAX_PROT_SIZE];
+static int ipa_uc_ntn_cons_release(void);
+static int ipa_uc_ntn_cons_request(void);
+static void ipa_uc_offload_rm_notify(void *, enum ipa_rm_event, unsigned long);
+
static int ipa_commit_partial_hdr(
struct ipa_ioc_add_hdr *hdr,
const char *netdev_name,
struct ipa_uc_offload_out_params *outp,
struct ipa_uc_offload_ctx *ntn_ctx)
{
- struct ipa_ioc_add_hdr *hdr;
+ struct ipa_ioc_add_hdr *hdr = NULL;
struct ipa_tx_intf tx;
struct ipa_rx_intf rx;
struct ipa_ioc_tx_intf_prop tx_prop[2];
struct ipa_ioc_rx_intf_prop rx_prop[2];
+ struct ipa_rm_create_params param;
u32 len;
int ret = 0;
IPA_UC_OFFLOAD_DBG("register interface for netdev %s\n",
inp->netdev_name);
+ memset(¶m, 0, sizeof(param));
+ param.name = IPA_RM_RESOURCE_ODU_ADAPT_PROD;
+ param.reg_params.user_data = ntn_ctx;
+ param.reg_params.notify_cb = ipa_uc_offload_rm_notify;
+ param.floor_voltage = IPA_VOLTAGE_SVS;
+ ret = ipa_rm_create_resource(¶m);
+ if (ret) {
+ IPA_UC_OFFLOAD_ERR("fail to create ODU_ADAPT_PROD resource\n");
+ return -EFAULT;
+ }
+
+ memset(¶m, 0, sizeof(param));
+ param.name = IPA_RM_RESOURCE_ODU_ADAPT_CONS;
+ param.request_resource = ipa_uc_ntn_cons_request;
+ param.release_resource = ipa_uc_ntn_cons_release;
+ ret = ipa_rm_create_resource(¶m);
+ if (ret) {
+ IPA_UC_OFFLOAD_ERR("fail to create ODU_ADAPT_CONS resource\n");
+ goto fail_create_rm_cons;
+ }
memcpy(ntn_ctx->netdev_name, inp->netdev_name, IPA_RESOURCE_NAME_MAX);
ntn_ctx->hdr_len = inp->hdr_info[0].hdr_len;
hdr = kzalloc(len, GFP_KERNEL);
if (hdr == NULL) {
IPA_UC_OFFLOAD_ERR("fail to alloc %d bytes\n", len);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail_alloc;
}
if (ipa_commit_partial_hdr(hdr, ntn_ctx->netdev_name, inp->hdr_info)) {
init_completion(&ntn_ctx->ntn_completion);
ntn_ctx->state = IPA_UC_OFFLOAD_STATE_INITIALIZED;
+ kfree(hdr);
+ return ret;
+
fail:
kfree(hdr);
+fail_alloc:
+ ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS);
+fail_create_rm_cons:
+ ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
return ret;
}
struct ipa_ntn_conn_out_params *outp,
struct ipa_uc_offload_ctx *ntn_ctx)
{
- struct ipa_rm_create_params param;
int result = 0;
+ enum ipa_uc_offload_state prev_state;
+ prev_state = ntn_ctx->state;
if (inp->dl.ring_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT ||
inp->dl.buff_pool_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT) {
IPA_UC_OFFLOAD_ERR("alignment failure on TX\n");
return -EINVAL;
}
- memset(¶m, 0, sizeof(param));
- param.name = IPA_RM_RESOURCE_ODU_ADAPT_PROD;
- param.reg_params.user_data = ntn_ctx;
- param.reg_params.notify_cb = ipa_uc_offload_rm_notify;
- param.floor_voltage = IPA_VOLTAGE_SVS;
- result = ipa_rm_create_resource(¶m);
- if (result) {
- IPA_UC_OFFLOAD_ERR("fail to create ODU_ADAPT_PROD resource\n");
- return -EFAULT;
- }
-
- memset(¶m, 0, sizeof(param));
- param.name = IPA_RM_RESOURCE_ODU_ADAPT_CONS;
- param.request_resource = ipa_uc_ntn_cons_request;
- param.release_resource = ipa_uc_ntn_cons_release;
- result = ipa_rm_create_resource(¶m);
+ result = ipa_rm_add_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+ IPA_RM_RESOURCE_APPS_CONS);
if (result) {
- IPA_UC_OFFLOAD_ERR("fail to create ODU_ADAPT_CONS resource\n");
- goto fail_create_rm_cons;
- }
-
- if (ipa_rm_add_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
- IPA_RM_RESOURCE_APPS_CONS)) {
- IPA_UC_OFFLOAD_ERR("fail to add rm dependency\n");
- result = -EFAULT;
- goto fail;
- }
-
- if (ipa_setup_uc_ntn_pipes(inp, ntn_ctx->notify,
- ntn_ctx->priv, ntn_ctx->hdr_len, outp)) {
- IPA_UC_OFFLOAD_ERR("fail to setup uc offload pipes\n");
- result = -EFAULT;
- goto fail;
+ IPA_UC_OFFLOAD_ERR("fail to add rm dependency: %d\n", result);
+ return result;
}
- ntn_ctx->state = IPA_UC_OFFLOAD_STATE_UP;
result = ipa_rm_request_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
if (result == -EINPROGRESS) {
if (wait_for_completion_timeout(&ntn_ctx->ntn_completion,
goto fail;
}
+ ntn_ctx->state = IPA_UC_OFFLOAD_STATE_UP;
+ result = ipa_setup_uc_ntn_pipes(inp, ntn_ctx->notify,
+ ntn_ctx->priv, ntn_ctx->hdr_len, outp);
+ if (result) {
+ IPA_UC_OFFLOAD_ERR("fail to setup uc offload pipes: %d\n",
+ result);
+ ntn_ctx->state = prev_state;
+ result = -EFAULT;
+ goto fail;
+ }
+
return 0;
fail:
- ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS);
-fail_create_rm_cons:
- ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
-
+ ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+ IPA_RM_RESOURCE_APPS_CONS);
return result;
}
return -EINVAL;
}
- if (offload_ctx->state != IPA_UC_OFFLOAD_STATE_INITIALIZED) {
+ if (offload_ctx->state != IPA_UC_OFFLOAD_STATE_INITIALIZED &&
+ offload_ctx->state != IPA_UC_OFFLOAD_STATE_DOWN) {
IPA_UC_OFFLOAD_ERR("Invalid state %d\n", offload_ctx->state);
return -EPERM;
}
static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx)
{
int ipa_ep_idx_ul, ipa_ep_idx_dl;
+ int ret = 0;
ntn_ctx->state = IPA_UC_OFFLOAD_STATE_DOWN;
- if (ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
- IPA_RM_RESOURCE_APPS_CONS)) {
- IPA_UC_OFFLOAD_ERR("fail to delete rm dependency\n");
- return -EFAULT;
- }
- if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD)) {
- IPA_UC_OFFLOAD_ERR("fail to delete ODU_ADAPT_PROD resource\n");
+ ret = ipa_rm_release_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
+ if (ret) {
+ IPA_UC_OFFLOAD_ERR("fail to release ODU_ADAPT_PROD res: %d\n",
+ ret);
return -EFAULT;
}
- if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS)) {
- IPA_UC_OFFLOAD_ERR("fail to delete ODU_ADAPT_CONS resource\n");
+ ret = ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+ IPA_RM_RESOURCE_APPS_CONS);
+ if (ret) {
+ IPA_UC_OFFLOAD_ERR("fail to del dep ODU->APPS, %d\n", ret);
return -EFAULT;
}
ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ODU_PROD);
ipa_ep_idx_dl = ipa_get_ep_mapping(IPA_CLIENT_ODU_TETH_CONS);
- if (ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl)) {
- IPA_UC_OFFLOAD_ERR("fail to tear down uc offload pipes\n");
+ ret = ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl);
+ if (ret) {
+ IPA_UC_OFFLOAD_ERR("fail to tear down ntn offload pipes, %d\n",
+ ret);
return -EFAULT;
}
- return 0;
+ return ret;
}
int ipa_uc_offload_disconn_pipes(u32 clnt_hdl)
int len, result = 0;
struct ipa_ioc_del_hdr *hdr;
+ if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD)) {
+ IPA_UC_OFFLOAD_ERR("fail to delete ODU_ADAPT_PROD resource\n");
+ return -EFAULT;
+ }
+
+ if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS)) {
+ IPA_UC_OFFLOAD_ERR("fail to delete ODU_ADAPT_CONS resource\n");
+ return -EFAULT;
+ }
+
len = sizeof(struct ipa_ioc_del_hdr) + 2 * sizeof(struct ipa_hdr_del);
hdr = kzalloc(len, GFP_KERNEL);
if (hdr == NULL) {
if (ipa_rm_dep_graph_get_resource(graph,
resource_name,
&dependent)) {
- IPA_RM_ERR("%s does not exist\n",
+ IPA_RM_DBG("%s does not exist\n",
ipa_rm_resource_str(resource_name));
result = -EINVAL;
goto bail;
if (ipa_rm_dep_graph_get_resource(graph,
depends_on_name,
&dependency)) {
- IPA_RM_ERR("%s does not exist\n",
+ IPA_RM_DBG("%s does not exist\n",
ipa_rm_resource_str(depends_on_name));
result = -EINVAL;
goto bail;
mutex_lock(&ipa_ctx->lock);
tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v4];
- tbl->sticky_rear = true;
rule.action = IPA_PASS_TO_EXCEPTION;
- __ipa_add_flt_rule(tbl, IPA_IP_v4, &rule, false,
+ __ipa_add_flt_rule(tbl, IPA_IP_v4, &rule, true,
&ep->dflt_flt4_rule_hdl);
ipa_ctx->ctrl->ipa_commit_flt(IPA_IP_v4);
+ tbl->sticky_rear = true;
tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v6];
- tbl->sticky_rear = true;
rule.action = IPA_PASS_TO_EXCEPTION;
- __ipa_add_flt_rule(tbl, IPA_IP_v6, &rule, false,
+ __ipa_add_flt_rule(tbl, IPA_IP_v6, &rule, true,
&ep->dflt_flt6_rule_hdl);
ipa_ctx->ctrl->ipa_commit_flt(IPA_IP_v6);
+ tbl->sticky_rear = true;
mutex_unlock(&ipa_ctx->lock);
}
/* setup ul ep cfg */
ep_ul->valid = 1;
ep_ul->client = in->ul.client;
- result = ipa_enable_data_path(ipa_ep_idx_ul);
- if (result) {
- IPAERR("disable data path failed res=%d clnt=%d.\n", result,
- ipa_ep_idx_ul);
- return -EFAULT;
- }
ep_ul->client_notify = notify;
ep_ul->priv = priv;
/* setup dl ep cfg */
ep_dl->valid = 1;
ep_dl->client = in->dl.client;
- result = ipa_enable_data_path(ipa_ep_idx_dl);
- if (result) {
- IPAERR("disable data path failed res=%d clnt=%d.\n", result,
- ipa_ep_idx_dl);
- result = -EFAULT;
- goto fail;
- }
-
memset(&ep_dl->cfg, 0, sizeof(ep_ul->cfg));
ep_dl->cfg.nat.nat_en = IPA_BYPASS_NAT;
ep_dl->cfg.hdr.hdr_len = hdr_len;
}
outp->dl_uc_db_pa = IPA_UC_NTN_DB_PA_TX;
ep_dl->uc_offload_state |= IPA_UC_OFFLOAD_CONNECTED;
+
+ result = ipa_enable_data_path(ipa_ep_idx_dl);
+ if (result) {
+ IPAERR("Enable data path failed res=%d clnt=%d.\n", result,
+ ipa_ep_idx_dl);
+ result = -EFAULT;
+ goto fail;
+ }
IPAERR("client %d (ep: %d) connected\n", in->dl.client,
ipa_ep_idx_dl);
- ipa_inc_acquire_wakelock(IPA_WAKELOCK_REF_CLIENT_ODU_RX);
fail:
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
}
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- /* teardown the UL pipe */
cmd_data = (struct IpaHwOffloadCommonChCmdData_t *)cmd.base;
cmd_data->protocol = IPA_HW_FEATURE_NTN;
-
tear = &cmd_data->CommonCh_params.NtnCommonCh_params;
- tear->params.ipa_pipe_number = ipa_ep_idx_ul;
+
+ /* teardown the DL pipe */
+ ipa_disable_data_path(ipa_ep_idx_dl);
+ /*
+ * Reset ep before sending cmd otherwise disconnect
+ * during data transfer will result into
+ * enormous suspend interrupts
+ */
+ memset(&ipa_ctx->ep[ipa_ep_idx_dl], 0, sizeof(struct ipa_ep_context));
+ IPADBG("dl client (ep: %d) disconnected\n", ipa_ep_idx_dl);
+ tear->params.ipa_pipe_number = ipa_ep_idx_dl;
result = ipa_uc_send_cmd((u32)(cmd.phys_base),
IPA_CPU_2_HW_CMD_OFFLOAD_TEAR_DOWN,
IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
false, 10*HZ);
if (result) {
- IPAERR("fail to tear down ul pipe\n");
+ IPAERR("fail to tear down dl pipe\n");
result = -EFAULT;
goto fail;
}
- ipa_disable_data_path(ipa_ep_idx_ul);
- ipa_delete_dflt_flt_rules(ipa_ep_idx_ul);
- memset(&ipa_ctx->ep[ipa_ep_idx_ul], 0, sizeof(struct ipa_ep_context));
- IPADBG("ul client (ep: %d) disconnected\n", ipa_ep_idx_ul);
- /* teardown the DL pipe */
- tear->params.ipa_pipe_number = ipa_ep_idx_dl;
+ /* teardown the UL pipe */
+ tear->params.ipa_pipe_number = ipa_ep_idx_ul;
result = ipa_uc_send_cmd((u32)(cmd.phys_base),
IPA_CPU_2_HW_CMD_OFFLOAD_TEAR_DOWN,
IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
result = -EFAULT;
goto fail;
}
- ipa_disable_data_path(ipa_ep_idx_dl);
- memset(&ipa_ctx->ep[ipa_ep_idx_dl], 0, sizeof(struct ipa_ep_context));
- IPADBG("dl client (ep: %d) disconnected\n", ipa_ep_idx_dl);
- ipa_dec_release_wakelock(IPA_WAKELOCK_REF_CLIENT_ODU_RX);
+
+ ipa_delete_dflt_flt_rules(ipa_ep_idx_ul);
+ memset(&ipa_ctx->ep[ipa_ep_idx_ul], 0, sizeof(struct ipa_ep_context));
+ IPADBG("ul client (ep: %d) disconnected\n", ipa_ep_idx_ul);
fail:
dma_free_coherent(ipa_ctx->uc_pdev, cmd.size, cmd.base, cmd.phys_base);
/* setup ul ep cfg */
ep_ul->valid = 1;
ep_ul->client = in->ul.client;
- result = ipa3_enable_data_path(ipa_ep_idx_ul);
- if (result) {
- IPAERR("disable data path failed res=%d clnt=%d.\n", result,
- ipa_ep_idx_ul);
- return -EFAULT;
- }
ep_ul->client_notify = notify;
ep_ul->priv = priv;
/* setup dl ep cfg */
ep_dl->valid = 1;
ep_dl->client = in->dl.client;
- result = ipa3_enable_data_path(ipa_ep_idx_dl);
- if (result) {
- IPAERR("disable data path failed res=%d clnt=%d.\n", result,
- ipa_ep_idx_dl);
- result = -EFAULT;
- goto fail;
- }
-
memset(&ep_dl->cfg, 0, sizeof(ep_ul->cfg));
ep_dl->cfg.nat.nat_en = IPA_BYPASS_NAT;
ep_dl->cfg.hdr.hdr_len = hdr_len;
}
outp->dl_uc_db_pa = IPA_UC_NTN_DB_PA_TX;
ep_dl->uc_offload_state |= IPA_UC_OFFLOAD_CONNECTED;
+
+ result = ipa3_enable_data_path(ipa_ep_idx_dl);
+ if (result) {
+ IPAERR("Enable data path failed res=%d clnt=%d.\n", result,
+ ipa_ep_idx_dl);
+ result = -EFAULT;
+ goto fail;
+ }
IPADBG("client %d (ep: %d) connected\n", in->dl.client,
ipa_ep_idx_dl);
}
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- /* teardown the UL pipe */
cmd_data = (struct IpaHwOffloadCommonChCmdData_t *)cmd.base;
cmd_data->protocol = IPA_HW_FEATURE_NTN;
-
tear = &cmd_data->CommonCh_params.NtnCommonCh_params;
- tear->params.ipa_pipe_number = ipa_ep_idx_ul;
+
+ /* teardown the DL pipe */
+ ipa3_disable_data_path(ipa_ep_idx_dl);
+ /*
+ * Reset ep before sending cmd otherwise disconnect
+ * during data transfer will result into
+ * enormous suspend interrupts
+ */
+ memset(&ipa3_ctx->ep[ipa_ep_idx_dl], 0, sizeof(struct ipa3_ep_context));
+ IPADBG("dl client (ep: %d) disconnected\n", ipa_ep_idx_dl);
+ tear->params.ipa_pipe_number = ipa_ep_idx_dl;
result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
IPA_CPU_2_HW_CMD_OFFLOAD_TEAR_DOWN,
IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
false, 10*HZ);
if (result) {
- IPAERR("fail to tear down ul pipe\n");
+ IPAERR("fail to tear down dl pipe\n");
result = -EFAULT;
goto fail;
}
- ipa3_disable_data_path(ipa_ep_idx_ul);
- ipa3_delete_dflt_flt_rules(ipa_ep_idx_ul);
- memset(&ipa3_ctx->ep[ipa_ep_idx_ul], 0, sizeof(struct ipa3_ep_context));
- IPADBG("ul client (ep: %d) disconnected\n", ipa_ep_idx_ul);
- /* teardown the DL pipe */
- tear->params.ipa_pipe_number = ipa_ep_idx_dl;
+ /* teardown the UL pipe */
+ tear->params.ipa_pipe_number = ipa_ep_idx_ul;
result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
IPA_CPU_2_HW_CMD_OFFLOAD_TEAR_DOWN,
IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
result = -EFAULT;
goto fail;
}
- ipa3_disable_data_path(ipa_ep_idx_dl);
+ ipa3_delete_dflt_flt_rules(ipa_ep_idx_ul);
memset(&ipa3_ctx->ep[ipa_ep_idx_dl], 0, sizeof(struct ipa3_ep_context));
- IPADBG("dl client (ep: %d) disconnected\n", ipa_ep_idx_dl);
+ IPADBG("ul client (ep: %d) disconnected\n", ipa_ep_idx_ul);
fail:
dma_free_coherent(ipa3_ctx->uc_pdev, cmd.size, cmd.base, cmd.phys_base);