123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
- */
- #include "ipa_i.h"
- #define IPA_UC_NTN_DB_PA_TX 0x79620DC
- #define IPA_UC_NTN_DB_PA_RX 0x79620D8
- static void ipa3_uc_ntn_event_log_info_handler(
- struct IpaHwEventLogInfoData_t *uc_event_top_mmio)
- {
- struct Ipa3HwEventInfoData_t *statsPtr = &uc_event_top_mmio->statsInfo;
- if ((uc_event_top_mmio->protocolMask &
- (1 << IPA_HW_PROTOCOL_ETH)) == 0) {
- IPAERR("NTN protocol missing 0x%x\n",
- uc_event_top_mmio->protocolMask);
- return;
- }
- if (statsPtr->featureInfo[IPA_HW_PROTOCOL_ETH].params.size !=
- sizeof(struct Ipa3HwStatsNTNInfoData_t)) {
- IPAERR("NTN stats sz invalid exp=%zu is=%u\n",
- sizeof(struct Ipa3HwStatsNTNInfoData_t),
- statsPtr->featureInfo[IPA_HW_PROTOCOL_ETH].params.size);
- return;
- }
- ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_ofst =
- uc_event_top_mmio->statsInfo.baseAddrOffset +
- statsPtr->featureInfo[IPA_HW_PROTOCOL_ETH].params.offset;
- IPAERR("NTN stats ofst=0x%x\n", ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_ofst);
- if (ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_ofst +
- sizeof(struct Ipa3HwStatsNTNInfoData_t) >=
- ipa3_ctx->ctrl->ipa_reg_base_ofst +
- ipahal_get_reg_n_ofst(IPA_SW_AREA_RAM_DIRECT_ACCESS_n, 0) +
- ipa3_ctx->smem_sz) {
- IPAERR("uc_ntn_stats 0x%x outside SRAM\n",
- ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_ofst);
- return;
- }
- ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio =
- ioremap(ipa3_ctx->ipa_wrapper_base +
- ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_ofst,
- sizeof(struct Ipa3HwStatsNTNInfoData_t));
- if (!ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio) {
- IPAERR("fail to ioremap uc ntn stats\n");
- return;
- }
- }
- /**
- * ipa2_get_wdi_stats() - Query WDI statistics from uc
- * @stats: [inout] stats blob from client populated by driver
- *
- * Returns: 0 on success, negative on failure
- *
- * @note Cannot be called from atomic context
- *
- */
- int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats)
- {
- #define TX_STATS(y) stats->tx_ch_stats[0].y = \
- ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio->tx_ch_stats[0].y
- #define RX_STATS(y) stats->rx_ch_stats[0].y = \
- ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio->rx_ch_stats[0].y
- if (unlikely(!ipa3_ctx)) {
- IPAERR("IPA driver was not initialized\n");
- return -EINVAL;
- }
- if (!stats || !ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio) {
- IPAERR("bad parms stats=%pK ntn_stats=%pK\n",
- stats,
- ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio);
- return -EINVAL;
- }
- IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- TX_STATS(num_pkts_processed);
- TX_STATS(ring_stats.ringFull);
- TX_STATS(ring_stats.ringEmpty);
- TX_STATS(ring_stats.ringUsageHigh);
- TX_STATS(ring_stats.ringUsageLow);
- TX_STATS(ring_stats.RingUtilCount);
- TX_STATS(gsi_stats.bamFifoFull);
- TX_STATS(gsi_stats.bamFifoEmpty);
- TX_STATS(gsi_stats.bamFifoUsageHigh);
- TX_STATS(gsi_stats.bamFifoUsageLow);
- TX_STATS(gsi_stats.bamUtilCount);
- TX_STATS(num_db);
- TX_STATS(num_qmb_int_handled);
- TX_STATS(ipa_pipe_number);
- RX_STATS(num_pkts_processed);
- RX_STATS(ring_stats.ringFull);
- RX_STATS(ring_stats.ringEmpty);
- RX_STATS(ring_stats.ringUsageHigh);
- RX_STATS(ring_stats.ringUsageLow);
- RX_STATS(ring_stats.RingUtilCount);
- RX_STATS(gsi_stats.bamFifoFull);
- RX_STATS(gsi_stats.bamFifoEmpty);
- RX_STATS(gsi_stats.bamFifoUsageHigh);
- RX_STATS(gsi_stats.bamFifoUsageLow);
- RX_STATS(gsi_stats.bamUtilCount);
- RX_STATS(num_db);
- RX_STATS(num_qmb_int_handled);
- RX_STATS(ipa_pipe_number);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return 0;
- }
- int ipa3_ntn_uc_reg_rdyCB(void (*ipa_ready_cb)(void *), void *user_data)
- {
- int ret;
- if (!ipa3_ctx) {
- IPAERR("IPA ctx is null\n");
- return -ENXIO;
- }
- ret = ipa3_uc_state_check();
- if (ret) {
- ipa3_ctx->uc_ntn_ctx.uc_ready_cb = ipa_ready_cb;
- ipa3_ctx->uc_ntn_ctx.priv = user_data;
- return 0;
- }
- return -EEXIST;
- }
- void ipa3_ntn_uc_dereg_rdyCB(void)
- {
- ipa3_ctx->uc_ntn_ctx.uc_ready_cb = NULL;
- ipa3_ctx->uc_ntn_ctx.priv = NULL;
- }
- static void ipa3_uc_ntn_loaded_handler(void)
- {
- if (!ipa3_ctx) {
- IPAERR("IPA ctx is null\n");
- return;
- }
- if (ipa3_ctx->uc_ntn_ctx.uc_ready_cb) {
- ipa3_ctx->uc_ntn_ctx.uc_ready_cb(
- ipa3_ctx->uc_ntn_ctx.priv);
- ipa3_ctx->uc_ntn_ctx.uc_ready_cb =
- NULL;
- ipa3_ctx->uc_ntn_ctx.priv = NULL;
- }
- }
- int ipa3_ntn_init(void)
- {
- struct ipa3_uc_hdlrs uc_ntn_cbs = { 0 };
- uc_ntn_cbs.ipa_uc_event_log_info_hdlr =
- ipa3_uc_ntn_event_log_info_handler;
- uc_ntn_cbs.ipa_uc_loaded_hdlr =
- ipa3_uc_ntn_loaded_handler;
- ipa3_uc_register_handlers(IPA_HW_FEATURE_NTN, &uc_ntn_cbs);
- return 0;
- }
- static int ipa3_uc_send_ntn_setup_pipe_cmd(
- struct ipa_ntn_setup_info *ntn_info, u8 dir)
- {
- int ipa_ep_idx;
- int result = 0;
- struct ipa_mem_buffer cmd;
- struct Ipa3HwNtnSetUpCmdData_t *Ntn_params;
- struct IpaHwOffloadSetUpCmdData_t *cmd_data;
- struct IpaHwOffloadSetUpCmdData_t_v4_0 *cmd_data_v4_0;
- if (ntn_info == NULL) {
- IPAERR("invalid input\n");
- return -EINVAL;
- }
- ipa_ep_idx = ipa_get_ep_mapping(ntn_info->client);
- if (ipa_ep_idx == -1) {
- IPAERR("fail to get ep idx.\n");
- return -EFAULT;
- }
- IPADBG("client=%d ep=%d\n", ntn_info->client, ipa_ep_idx);
- IPADBG("ring_base_pa = 0x%pa\n",
- &ntn_info->ring_base_pa);
- IPADBG("ring_base_iova = 0x%pa\n",
- &ntn_info->ring_base_iova);
- IPADBG("ntn_ring_size = %d\n", ntn_info->ntn_ring_size);
- IPADBG("buff_pool_base_pa = 0x%pa\n", &ntn_info->buff_pool_base_pa);
- IPADBG("buff_pool_base_iova = 0x%pa\n", &ntn_info->buff_pool_base_iova);
- IPADBG("num_buffers = %d\n", ntn_info->num_buffers);
- IPADBG("data_buff_size = %d\n", ntn_info->data_buff_size);
- IPADBG("tail_ptr_base_pa = 0x%pa\n", &ntn_info->ntn_reg_base_ptr_pa);
- if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
- cmd.size = sizeof(*cmd_data_v4_0);
- else
- cmd.size = sizeof(*cmd_data);
- cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
- &cmd.phys_base, GFP_KERNEL);
- if (cmd.base == NULL) {
- IPAERR("fail to get DMA memory.\n");
- return -ENOMEM;
- }
- if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
- cmd_data_v4_0 = (struct IpaHwOffloadSetUpCmdData_t_v4_0 *)
- cmd.base;
- cmd_data_v4_0->protocol = IPA_HW_PROTOCOL_ETH;
- Ntn_params = &cmd_data_v4_0->SetupCh_params.NtnSetupCh_params;
- } else {
- cmd_data = (struct IpaHwOffloadSetUpCmdData_t *)cmd.base;
- cmd_data->protocol = IPA_HW_PROTOCOL_ETH;
- Ntn_params = &cmd_data->SetupCh_params.NtnSetupCh_params;
- }
- if (ntn_info->smmu_enabled) {
- Ntn_params->ring_base_pa = (u32)ntn_info->ring_base_iova;
- Ntn_params->buff_pool_base_pa =
- (u32)ntn_info->buff_pool_base_iova;
- } else {
- Ntn_params->ring_base_pa = ntn_info->ring_base_pa;
- Ntn_params->buff_pool_base_pa = ntn_info->buff_pool_base_pa;
- }
- Ntn_params->ntn_ring_size = ntn_info->ntn_ring_size;
- Ntn_params->num_buffers = ntn_info->num_buffers;
- Ntn_params->ntn_reg_base_ptr_pa = ntn_info->ntn_reg_base_ptr_pa;
- Ntn_params->data_buff_size = ntn_info->data_buff_size;
- Ntn_params->ipa_pipe_number = ipa_ep_idx;
- Ntn_params->dir = dir;
- result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
- IPA_CPU_2_HW_CMD_OFFLOAD_CHANNEL_SET_UP,
- IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
- false, 10*HZ);
- if (result)
- result = -EFAULT;
- dma_free_coherent(ipa3_ctx->uc_pdev, cmd.size, cmd.base, cmd.phys_base);
- return result;
- }
- static int ipa3_smmu_map_uc_ntn_pipes(struct ipa_ntn_setup_info *params,
- bool map)
- {
- struct iommu_domain *smmu_domain;
- int result;
- int i;
- u64 iova;
- phys_addr_t pa;
- u64 iova_p;
- phys_addr_t pa_p;
- u32 size_p;
- if (params->data_buff_size > PAGE_SIZE) {
- IPAERR("invalid data buff size\n");
- return -EINVAL;
- }
- result = ipa3_smmu_map_peer_reg(rounddown(params->ntn_reg_base_ptr_pa,
- PAGE_SIZE), map, IPA_SMMU_CB_UC);
- if (result) {
- IPAERR("failed to %s uC regs %d\n",
- map ? "map" : "unmap", result);
- goto fail;
- }
- if (params->smmu_enabled) {
- IPADBG("smmu is enabled on EMAC\n");
- result = ipa3_smmu_map_peer_buff((u64)params->ring_base_iova,
- params->ntn_ring_size, map, params->ring_base_sgt,
- IPA_SMMU_CB_UC);
- if (result) {
- IPAERR("failed to %s ntn ring %d\n",
- map ? "map" : "unmap", result);
- goto fail_map_ring;
- }
- result = ipa3_smmu_map_peer_buff(
- (u64)params->buff_pool_base_iova,
- params->num_buffers * 4, map,
- params->buff_pool_base_sgt, IPA_SMMU_CB_UC);
- if (result) {
- IPAERR("failed to %s pool buffs %d\n",
- map ? "map" : "unmap", result);
- goto fail_map_buffer_smmu_enabled;
- }
- } else {
- IPADBG("smmu is disabled on EMAC\n");
- result = ipa3_smmu_map_peer_buff((u64)params->ring_base_pa,
- params->ntn_ring_size, map, NULL, IPA_SMMU_CB_UC);
- if (result) {
- IPAERR("failed to %s ntn ring %d\n",
- map ? "map" : "unmap", result);
- goto fail_map_ring;
- }
- result = ipa3_smmu_map_peer_buff(params->buff_pool_base_pa,
- params->num_buffers * 4, map, NULL, IPA_SMMU_CB_UC);
- if (result) {
- IPAERR("failed to %s pool buffs %d\n",
- map ? "map" : "unmap", result);
- goto fail_map_buffer_smmu_disabled;
- }
- }
- if (ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP]) {
- IPADBG("AP SMMU is set to s1 bypass\n");
- return 0;
- }
- smmu_domain = ipa3_get_smmu_domain();
- if (!smmu_domain) {
- IPAERR("invalid smmu domain\n");
- return -EINVAL;
- }
- for (i = 0; i < params->num_buffers; i++) {
- iova = (u64)params->data_buff_list[i].iova;
- pa = (phys_addr_t)params->data_buff_list[i].pa;
- IPA_SMMU_ROUND_TO_PAGE(iova, pa, params->data_buff_size, iova_p,
- pa_p, size_p);
- IPADBG("%s 0x%llx to 0x%pa size %d\n", map ? "mapping" :
- "unmapping", iova_p, &pa_p, size_p);
- if (map) {
- result = ipa3_iommu_map(smmu_domain, iova_p, pa_p,
- size_p, IOMMU_READ | IOMMU_WRITE);
- if (result)
- IPAERR("Fail to map 0x%llx\n", iova);
- } else {
- result = iommu_unmap(smmu_domain, iova_p, size_p);
- if (result != params->data_buff_size)
- IPAERR("Fail to unmap 0x%llx\n", iova);
- }
- if (result) {
- if (params->smmu_enabled)
- goto fail_map_data_buff_smmu_enabled;
- else
- goto fail_map_data_buff_smmu_disabled;
- }
- }
- return 0;
- fail_map_data_buff_smmu_enabled:
- ipa3_smmu_map_peer_buff((u64)params->buff_pool_base_iova,
- params->num_buffers * 4, !map, NULL, IPA_SMMU_CB_UC);
- goto fail_map_buffer_smmu_enabled;
- fail_map_data_buff_smmu_disabled:
- ipa3_smmu_map_peer_buff(params->buff_pool_base_pa,
- params->num_buffers * 4, !map, NULL, IPA_SMMU_CB_UC);
- goto fail_map_buffer_smmu_disabled;
- fail_map_buffer_smmu_enabled:
- ipa3_smmu_map_peer_buff((u64)params->ring_base_iova,
- params->ntn_ring_size, !map, params->ring_base_sgt,
- IPA_SMMU_CB_UC);
- goto fail_map_ring;
- fail_map_buffer_smmu_disabled:
- ipa3_smmu_map_peer_buff((u64)params->ring_base_pa,
- params->ntn_ring_size, !map, NULL, IPA_SMMU_CB_UC);
- fail_map_ring:
- ipa3_smmu_map_peer_reg(rounddown(params->ntn_reg_base_ptr_pa,
- PAGE_SIZE), !map, IPA_SMMU_CB_UC);
- fail:
- return result;
- }
- /**
- * ipa3_setup_uc_ntn_pipes() - setup uc offload pipes
- */
- int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
- ipa_notify_cb notify, void *priv, u8 hdr_len,
- struct ipa_ntn_conn_out_params *outp)
- {
- struct ipa3_ep_context *ep_ul;
- struct ipa3_ep_context *ep_dl;
- int ipa_ep_idx_ul;
- int ipa_ep_idx_dl;
- int result = 0;
- if (in == NULL) {
- IPAERR("invalid input\n");
- return -EINVAL;
- }
- ipa_ep_idx_ul = ipa_get_ep_mapping(in->ul.client);
- if (ipa_ep_idx_ul == IPA_EP_NOT_ALLOCATED ||
- ipa_ep_idx_ul >= IPA3_MAX_NUM_PIPES) {
- IPAERR("fail to alloc UL EP ipa_ep_idx_ul=%d\n",
- ipa_ep_idx_ul);
- return -EFAULT;
- }
- ipa_ep_idx_dl = ipa_get_ep_mapping(in->dl.client);
- if (ipa_ep_idx_dl == IPA_EP_NOT_ALLOCATED ||
- ipa_ep_idx_dl >= IPA3_MAX_NUM_PIPES) {
- IPAERR("fail to alloc DL EP ipa_ep_idx_dl=%d\n",
- ipa_ep_idx_dl);
- return -EFAULT;
- }
- ep_ul = &ipa3_ctx->ep[ipa_ep_idx_ul];
- ep_dl = &ipa3_ctx->ep[ipa_ep_idx_dl];
- if (ep_ul->valid || ep_dl->valid) {
- IPAERR("EP already allocated ul:%d dl:%d\n",
- ep_ul->valid, ep_dl->valid);
- return -EFAULT;
- }
- memset(ep_ul, 0, offsetof(struct ipa3_ep_context, sys));
- memset(ep_dl, 0, offsetof(struct ipa3_ep_context, sys));
- IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- /* setup ul ep cfg */
- ep_ul->valid = 1;
- ep_ul->client = in->ul.client;
- ep_ul->client_notify = notify;
- ep_ul->priv = priv;
- memset(&ep_ul->cfg, 0, sizeof(ep_ul->cfg));
- ep_ul->cfg.nat.nat_en = IPA_SRC_NAT;
- ep_ul->cfg.hdr.hdr_len = hdr_len;
- ep_ul->cfg.mode.mode = IPA_BASIC;
- if (ipa3_cfg_ep(ipa_ep_idx_ul, &ep_ul->cfg)) {
- IPAERR("fail to setup ul pipe cfg\n");
- result = -EFAULT;
- goto fail;
- }
- result = ipa3_smmu_map_uc_ntn_pipes(&in->ul, true);
- if (result) {
- IPAERR("failed to map SMMU for UL %d\n", result);
- goto fail;
- }
- result = ipa3_enable_data_path(ipa_ep_idx_ul);
- if (result) {
- IPAERR("Enable data path failed res=%d pipe=%d.\n", result,
- ipa_ep_idx_ul);
- result = -EFAULT;
- goto fail_smmu_unmap_ul;
- }
- if (ipa3_uc_send_ntn_setup_pipe_cmd(&in->ul, IPA_NTN_RX_DIR)) {
- IPAERR("fail to send cmd to uc for ul pipe\n");
- result = -EFAULT;
- goto fail_disable_dp_ul;
- }
- ipa3_install_dflt_flt_rules(ipa_ep_idx_ul);
- outp->ul_uc_db_pa = IPA_UC_NTN_DB_PA_RX;
- ep_ul->uc_offload_state |= IPA_UC_OFFLOAD_CONNECTED;
- IPADBG("client %d (ep: %d) connected\n", in->ul.client,
- ipa_ep_idx_ul);
- /* setup dl ep cfg */
- ep_dl->valid = 1;
- ep_dl->client = in->dl.client;
- 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;
- ep_dl->cfg.mode.mode = IPA_BASIC;
- if (ipa3_cfg_ep(ipa_ep_idx_dl, &ep_dl->cfg)) {
- IPAERR("fail to setup dl pipe cfg\n");
- result = -EFAULT;
- goto fail_disable_dp_ul;
- }
- result = ipa3_smmu_map_uc_ntn_pipes(&in->dl, true);
- if (result) {
- IPAERR("failed to map SMMU for DL %d\n", result);
- goto fail_disable_dp_ul;
- }
- result = ipa3_enable_data_path(ipa_ep_idx_dl);
- if (result) {
- IPAERR("Enable data path failed res=%d pipe=%d.\n", result,
- ipa_ep_idx_dl);
- result = -EFAULT;
- goto fail_smmu_unmap_dl;
- }
- if (ipa3_uc_send_ntn_setup_pipe_cmd(&in->dl, IPA_NTN_TX_DIR)) {
- IPAERR("fail to send cmd to uc for dl pipe\n");
- result = -EFAULT;
- goto fail_disable_dp_dl;
- }
- outp->dl_uc_db_pa = IPA_UC_NTN_DB_PA_TX;
- ep_dl->uc_offload_state |= IPA_UC_OFFLOAD_CONNECTED;
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- IPADBG("client %d (ep: %d) connected\n", in->dl.client,
- ipa_ep_idx_dl);
- return 0;
- fail_disable_dp_dl:
- ipa3_disable_data_path(ipa_ep_idx_dl);
- fail_smmu_unmap_dl:
- ipa3_smmu_map_uc_ntn_pipes(&in->dl, false);
- fail_disable_dp_ul:
- ipa3_disable_data_path(ipa_ep_idx_ul);
- fail_smmu_unmap_ul:
- ipa3_smmu_map_uc_ntn_pipes(&in->ul, false);
- fail:
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return result;
- }
- /**
- * ipa3_tear_down_uc_offload_pipes() - tear down uc offload pipes
- */
- int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul,
- int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params)
- {
- struct ipa_mem_buffer cmd;
- struct ipa3_ep_context *ep_ul, *ep_dl;
- struct IpaHwOffloadCommonChCmdData_t *cmd_data;
- struct IpaHwOffloadCommonChCmdData_t_v4_0 *cmd_data_v4_0;
- union Ipa3HwNtnCommonChCmdData_t *tear;
- int result = 0;
- IPADBG("ep_ul = %d\n", ipa_ep_idx_ul);
- IPADBG("ep_dl = %d\n", ipa_ep_idx_dl);
- ep_ul = &ipa3_ctx->ep[ipa_ep_idx_ul];
- ep_dl = &ipa3_ctx->ep[ipa_ep_idx_dl];
- if (ep_ul->uc_offload_state != IPA_UC_OFFLOAD_CONNECTED ||
- ep_dl->uc_offload_state != IPA_UC_OFFLOAD_CONNECTED) {
- IPAERR("channel bad state: ul %d dl %d\n",
- ep_ul->uc_offload_state, ep_dl->uc_offload_state);
- return -EFAULT;
- }
- atomic_set(&ep_ul->disconnect_in_progress, 1);
- atomic_set(&ep_dl->disconnect_in_progress, 1);
- if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
- cmd.size = sizeof(*cmd_data_v4_0);
- else
- cmd.size = sizeof(*cmd_data);
- cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
- &cmd.phys_base, GFP_KERNEL);
- if (cmd.base == NULL) {
- IPAERR("fail to get DMA memory.\n");
- return -ENOMEM;
- }
- IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
- cmd_data_v4_0 = (struct IpaHwOffloadCommonChCmdData_t_v4_0 *)
- cmd.base;
- cmd_data_v4_0->protocol = IPA_HW_PROTOCOL_ETH;
- tear = &cmd_data_v4_0->CommonCh_params.NtnCommonCh_params;
- } else {
- cmd_data = (struct IpaHwOffloadCommonChCmdData_t *)cmd.base;
- cmd_data->protocol = IPA_HW_PROTOCOL_ETH;
- tear = &cmd_data->CommonCh_params.NtnCommonCh_params;
- }
- /* 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 dl pipe\n");
- result = -EFAULT;
- goto fail;
- }
- /* unmap the DL pipe */
- result = ipa3_smmu_map_uc_ntn_pipes(¶ms->dl, false);
- if (result) {
- IPAERR("failed to unmap SMMU for DL %d\n", result);
- goto fail;
- }
- /* teardown the UL pipe */
- ipa3_disable_data_path(ipa_ep_idx_ul);
- 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,
- false, 10*HZ);
- if (result) {
- IPAERR("fail to tear down ul pipe\n");
- result = -EFAULT;
- goto fail;
- }
- /* unmap the UL pipe */
- result = ipa3_smmu_map_uc_ntn_pipes(¶ms->ul, false);
- if (result) {
- IPAERR("failed to unmap SMMU for UL %d\n", result);
- goto fail;
- }
- 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);
- fail:
- dma_free_coherent(ipa3_ctx->uc_pdev, cmd.size, cmd.base, cmd.phys_base);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return result;
- }
|