|
@@ -86,14 +86,14 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
|
|
|
if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_9) {
|
|
|
gsi_evt_ring_props.intr = GSI_INTR_MSI;
|
|
|
/* 32 (for Tx) and 8 (for Rx) */
|
|
|
- if (dir == IPA_WDI3_TX_DIR)
|
|
|
+ if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR))
|
|
|
gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_32B;
|
|
|
else
|
|
|
gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_8B;
|
|
|
} else {
|
|
|
gsi_evt_ring_props.intr = GSI_INTR_IRQ;
|
|
|
/* 16 (for Tx) and 8 (for Rx) */
|
|
|
- if (dir == IPA_WDI3_TX_DIR)
|
|
|
+ if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR))
|
|
|
gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_16B;
|
|
|
else
|
|
|
gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_8B;
|
|
@@ -104,8 +104,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
|
|
|
(u64)info->event_ring_base_pa;
|
|
|
} else {
|
|
|
len = info_smmu->event_ring_size;
|
|
|
- if (dir == IPA_WDI3_TX_DIR) {
|
|
|
- if (ipa_create_gsi_smmu_mapping(IPA_WDI_CE_RING_RES,
|
|
|
+ if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
|
|
|
+ if (ipa_create_gsi_smmu_mapping((
|
|
|
+ dir == IPA_WDI3_TX_DIR) ?
|
|
|
+ IPA_WDI_CE_RING_RES : IPA_WDI_CE1_RING_RES,
|
|
|
true, info->event_ring_base_pa,
|
|
|
&info_smmu->event_ring_base, len,
|
|
|
false, &va)) {
|
|
@@ -146,7 +148,7 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
|
|
|
/* setup channel ring */
|
|
|
memset(&gsi_channel_props, 0, sizeof(gsi_channel_props));
|
|
|
gsi_channel_props.prot = GSI_CHAN_PROT_WDI3;
|
|
|
- if (dir == IPA_WDI3_TX_DIR)
|
|
|
+ if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR))
|
|
|
gsi_channel_props.dir = GSI_CHAN_DIR_FROM_GSI;
|
|
|
else
|
|
|
gsi_channel_props.dir = GSI_CHAN_DIR_TO_GSI;
|
|
@@ -164,7 +166,7 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
|
|
|
gsi_channel_props.evt_ring_hdl = ep->gsi_evt_ring_hdl;
|
|
|
if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_9) {
|
|
|
/* 32 (for Tx) and 64 (for Rx) */
|
|
|
- if (dir == IPA_WDI3_TX_DIR)
|
|
|
+ if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR))
|
|
|
gsi_channel_props.re_size = GSI_CHAN_RE_SIZE_32B;
|
|
|
else
|
|
|
gsi_channel_props.re_size = GSI_CHAN_RE_SIZE_64B;
|
|
@@ -186,8 +188,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
|
|
|
(u64)info->transfer_ring_base_pa;
|
|
|
} else {
|
|
|
len = info_smmu->transfer_ring_size;
|
|
|
- if (dir == IPA_WDI3_TX_DIR) {
|
|
|
- if (ipa_create_gsi_smmu_mapping(IPA_WDI_TX_RING_RES,
|
|
|
+ if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
|
|
|
+ if (ipa_create_gsi_smmu_mapping((
|
|
|
+ dir == IPA_WDI3_TX_DIR) ?
|
|
|
+ IPA_WDI_TX_RING_RES : IPA_WDI_TX1_RING_RES,
|
|
|
true, info->transfer_ring_base_pa,
|
|
|
&info_smmu->transfer_ring_base, len,
|
|
|
false, &va)) {
|
|
@@ -255,8 +259,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
|
|
|
addr_low = (u32)info->event_ring_doorbell_pa;
|
|
|
addr_high = (u32)((u64)info->event_ring_doorbell_pa >> 32);
|
|
|
} else {
|
|
|
- if (dir == IPA_WDI3_TX_DIR) {
|
|
|
- if (ipa_create_gsi_smmu_mapping(IPA_WDI_CE_DB_RES,
|
|
|
+ if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
|
|
|
+ if (ipa_create_gsi_smmu_mapping((
|
|
|
+ dir == IPA_WDI3_TX_DIR) ?
|
|
|
+ IPA_WDI_CE_DB_RES : IPA_WDI_CE1_DB_RES,
|
|
|
true, info_smmu->event_ring_doorbell_pa,
|
|
|
NULL, 4, true, &va)) {
|
|
|
IPAERR("failed to get smmu mapping\n");
|
|
@@ -361,8 +367,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
|
|
|
ch_scratch.wdi3.wifi_rp_address_high =
|
|
|
(u32)((u64)info->transfer_ring_doorbell_pa >> 32);
|
|
|
} else {
|
|
|
- if (dir == IPA_WDI3_TX_DIR) {
|
|
|
- if (ipa_create_gsi_smmu_mapping(IPA_WDI_TX_DB_RES,
|
|
|
+ if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
|
|
|
+ if (ipa_create_gsi_smmu_mapping((
|
|
|
+ dir == IPA_WDI3_TX_DIR) ?
|
|
|
+ IPA_WDI_TX_DB_RES : IPA_WDI_TX1_DB_RES,
|
|
|
true, info_smmu->transfer_ring_doorbell_pa,
|
|
|
NULL, 4, true, &va)) {
|
|
|
IPAERR("failed to get smmu mapping\n");
|
|
@@ -452,10 +460,13 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
|
|
|
{
|
|
|
enum ipa_client_type rx_client;
|
|
|
enum ipa_client_type tx_client;
|
|
|
+ enum ipa_client_type tx1_client;
|
|
|
struct ipa3_ep_context *ep_rx;
|
|
|
struct ipa3_ep_context *ep_tx;
|
|
|
+ struct ipa3_ep_context *ep_tx1;
|
|
|
int ipa_ep_idx_rx;
|
|
|
int ipa_ep_idx_tx;
|
|
|
+ int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
|
|
|
int result = 0;
|
|
|
u32 gsi_db_addr_low, gsi_db_addr_high;
|
|
|
void __iomem *db_addr;
|
|
@@ -505,6 +516,27 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
|
|
|
memset(ep_rx, 0, offsetof(struct ipa3_ep_context, sys));
|
|
|
memset(ep_tx, 0, offsetof(struct ipa3_ep_context, sys));
|
|
|
|
|
|
+ if (in->is_tx1_used &&
|
|
|
+ ipa3_ctx->is_wdi3_tx1_needed) {
|
|
|
+ tx1_client = (in->is_smmu_enabled) ?
|
|
|
+ in->u_tx1.tx_smmu.client : in->u_tx1.tx.client;
|
|
|
+ ipa_ep_idx_tx1 = ipa_get_ep_mapping(tx1_client);
|
|
|
+
|
|
|
+ if (ipa_ep_idx_tx1 == IPA_EP_NOT_ALLOCATED ||
|
|
|
+ ipa_ep_idx_tx1 >= IPA3_MAX_NUM_PIPES) {
|
|
|
+ IPAERR("fail to alloc ep2 tx clnt %d not supprtd %d",
|
|
|
+ tx1_client, ipa_ep_idx_tx1);
|
|
|
+ return -EINVAL;
|
|
|
+ } else {
|
|
|
+ ep_tx1 = &ipa3_ctx->ep[ipa_ep_idx_tx1];
|
|
|
+ if (ep_tx1->valid) {
|
|
|
+ IPAERR("EP already allocated.\n");
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ memset(ep_tx1, 0, offsetof(struct ipa3_ep_context, sys));
|
|
|
+ }
|
|
|
+
|
|
|
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
|
|
|
|
|
#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
|
|
@@ -635,11 +667,12 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
|
|
|
in->u_rx.rx.event_ring_size);
|
|
|
db_val += GSI_EVT_RING_RE_SIZE_8B;
|
|
|
iowrite32(db_val, db_addr);
|
|
|
- gsi_query_evt_ring_db_addr(ep_tx->gsi_evt_ring_hdl,
|
|
|
- &evt_ring_db_addr_low, &evt_ring_db_addr_high);
|
|
|
IPADBG("RX base_addr 0x%x evt wp val: 0x%x\n",
|
|
|
ep_rx->gsi_mem_info.evt_ring_base_addr, db_val);
|
|
|
|
|
|
+ gsi_query_evt_ring_db_addr(ep_tx->gsi_evt_ring_hdl,
|
|
|
+ &evt_ring_db_addr_low, &evt_ring_db_addr_high);
|
|
|
+
|
|
|
/* only 32 bit lsb is used */
|
|
|
db_addr = ioremap((phys_addr_t)(evt_ring_db_addr_low), 4);
|
|
|
/*
|
|
@@ -659,15 +692,96 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
|
|
|
IPADBG("db_addr %u TX base_addr 0x%x evt wp val: 0x%x\n",
|
|
|
evt_ring_db_addr_low,
|
|
|
ep_tx->gsi_mem_info.evt_ring_base_addr, db_val);
|
|
|
+
|
|
|
+ /* setup tx1 ep cfg */
|
|
|
+ if (in->is_tx1_used &&
|
|
|
+ ipa3_ctx->is_wdi3_tx1_needed && (ipa_ep_idx_tx1 !=
|
|
|
+ IPA_EP_NOT_ALLOCATED) && (ipa_ep_idx_tx1 <
|
|
|
+ IPA3_MAX_NUM_PIPES)) {
|
|
|
+ ep_tx1->valid = 1;
|
|
|
+ ep_tx1->client = tx1_client;
|
|
|
+ result = ipa3_disable_data_path(ipa_ep_idx_tx1);
|
|
|
+ if (result) {
|
|
|
+ IPAERR("disable data path failed res=%d ep=%d.\n",
|
|
|
+ result, ipa_ep_idx_tx1);
|
|
|
+ result = -EFAULT;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (in->is_smmu_enabled == false)
|
|
|
+ memcpy(&ep_tx1->cfg, &in->u_tx1.tx.ipa_ep_cfg,
|
|
|
+ sizeof(ep_tx1->cfg));
|
|
|
+ else
|
|
|
+ memcpy(&ep_tx1->cfg, &in->u_tx1.tx_smmu.ipa_ep_cfg,
|
|
|
+ sizeof(ep_tx1->cfg));
|
|
|
+
|
|
|
+ ep_tx1->cfg.aggr.aggr_en = IPA_ENABLE_AGGR;
|
|
|
+ ep_tx1->cfg.aggr.aggr = IPA_GENERIC;
|
|
|
+ ep_tx1->cfg.aggr.aggr_byte_limit = IPA_WLAN_AGGR_BYTE_LIMIT;
|
|
|
+ ep_tx1->cfg.aggr.aggr_pkt_limit = IPA_WLAN_AGGR_PKT_LIMIT;
|
|
|
+ ep_tx1->cfg.aggr.aggr_hard_byte_limit_en = IPA_ENABLE_AGGR;
|
|
|
+ if (ipa3_cfg_ep(ipa_ep_idx_tx1, &ep_tx1->cfg)) {
|
|
|
+ IPAERR("fail to setup tx pipe cfg\n");
|
|
|
+ result = -EFAULT;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* setup TX1 gsi channel */
|
|
|
+ if (ipa3_setup_wdi3_gsi_channel(in->is_smmu_enabled,
|
|
|
+ &in->u_tx1.tx, &in->u_tx1.tx_smmu, IPA_WDI3_TX1_DIR,
|
|
|
+ ep_tx1)) {
|
|
|
+ IPAERR("fail to setup wdi3 gsi tx1 channel\n");
|
|
|
+ result = -EFAULT;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (gsi_query_channel_db_addr(ep_tx1->gsi_chan_hdl,
|
|
|
+ &gsi_db_addr_low, &gsi_db_addr_high)) {
|
|
|
+ IPAERR("failed to query gsi tx1 db addr\n");
|
|
|
+ result = -EFAULT;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* only 32 bit lsb is used */
|
|
|
+ out->tx1_uc_db_pa = (phys_addr_t)(gsi_db_addr_low);
|
|
|
+ IPADBG("out->tx1_uc_db_pa %llu\n", out->tx1_uc_db_pa);
|
|
|
+ IPADBG("client %d (ep: %d) connected\n", tx1_client,
|
|
|
+ ipa_ep_idx_tx1);
|
|
|
+
|
|
|
+ /* ring initial event ring dbs */
|
|
|
+ gsi_query_evt_ring_db_addr(ep_tx1->gsi_evt_ring_hdl,
|
|
|
+ &evt_ring_db_addr_low, &evt_ring_db_addr_high);
|
|
|
+ /* only 32 bit lsb is used */
|
|
|
+ db_addr = ioremap((phys_addr_t)(evt_ring_db_addr_low), 4);
|
|
|
+ /*
|
|
|
+ * IPA/GSI driver should ring the event DB once after
|
|
|
+ * initialization of the event, with a value that is
|
|
|
+ * outside of the ring range. Eg: ring base = 0x1000,
|
|
|
+ * ring size = 0x100 => AP can write value > 0x1100
|
|
|
+ * into the doorbell address. Eg: 0x 1110
|
|
|
+ * Use event ring base addr + event ring size + 1 element size.
|
|
|
+ */
|
|
|
+ db_val = (u32)ep_tx1->gsi_mem_info.evt_ring_base_addr;
|
|
|
+ db_val += ((in->is_smmu_enabled) ?
|
|
|
+ in->u_tx1.tx_smmu.event_ring_size :
|
|
|
+ in->u_tx1.tx.event_ring_size);
|
|
|
+ db_val += GSI_EVT_RING_RE_SIZE_16B;
|
|
|
+ iowrite32(db_val, db_addr);
|
|
|
+ IPADBG("db_addr %u TX1 base_addr 0x%x evt wp val: 0x%x\n",
|
|
|
+ evt_ring_db_addr_low,
|
|
|
+ ep_tx1->gsi_mem_info.evt_ring_base_addr, db_val);
|
|
|
+ }
|
|
|
+
|
|
|
fail:
|
|
|
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
|
|
return result;
|
|
|
}
|
|
|
EXPORT_SYMBOL(ipa3_conn_wdi3_pipes);
|
|
|
|
|
|
-int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
+int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
|
|
|
+ int ipa_ep_idx_tx1)
|
|
|
{
|
|
|
- struct ipa3_ep_context *ep_tx, *ep_rx;
|
|
|
+ struct ipa3_ep_context *ep_tx, *ep_rx, *ep_tx1;
|
|
|
int result = 0;
|
|
|
|
|
|
/* wdi3 only support over gsi */
|
|
@@ -679,6 +793,7 @@ int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
|
|
|
IPADBG("ep_tx = %d\n", ipa_ep_idx_tx);
|
|
|
IPADBG("ep_rx = %d\n", ipa_ep_idx_rx);
|
|
|
+ IPADBG("ep_tx1 = %d\n", ipa_ep_idx_tx1);
|
|
|
|
|
|
if (ipa_ep_idx_tx < 0 || ipa_ep_idx_tx >= ipa3_get_max_num_pipes() ||
|
|
|
ipa_ep_idx_rx < 0 ||
|
|
@@ -691,6 +806,30 @@ int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
ep_rx = &ipa3_ctx->ep[ipa_ep_idx_rx];
|
|
|
|
|
|
IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(ipa_ep_idx_tx));
|
|
|
+ /* tear down tx1 pipe */
|
|
|
+ if (ipa_ep_idx_tx1 >= 0) {
|
|
|
+ ep_tx1 = &ipa3_ctx->ep[ipa_ep_idx_tx1];
|
|
|
+ result = ipa3_reset_gsi_channel(ipa_ep_idx_tx1);
|
|
|
+ if (result != GSI_STATUS_SUCCESS) {
|
|
|
+ IPAERR("failed to reset gsi channel: %d.\n", result);
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+ result = gsi_reset_evt_ring(ep_tx1->gsi_evt_ring_hdl);
|
|
|
+ if (result != GSI_STATUS_SUCCESS) {
|
|
|
+ IPAERR("failed to reset evt ring: %d.\n", result);
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+ result = ipa3_release_gsi_channel(ipa_ep_idx_tx1);
|
|
|
+ if (result) {
|
|
|
+ IPAERR("failed to release gsi channel: %d\n", result);
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+ ipa3_release_wdi3_gsi_smmu_mappings(IPA_WDI3_TX1_DIR);
|
|
|
+
|
|
|
+ memset(ep_tx1, 0, sizeof(struct ipa3_ep_context));
|
|
|
+ IPADBG("tx client (ep: %d) disconnected\n", ipa_ep_idx_tx1);
|
|
|
+ }
|
|
|
+
|
|
|
/* tear down tx pipe */
|
|
|
result = ipa3_reset_gsi_channel(ipa_ep_idx_tx);
|
|
|
if (result != GSI_STATUS_SUCCESS) {
|
|
@@ -742,10 +881,13 @@ exit:
|
|
|
}
|
|
|
EXPORT_SYMBOL(ipa3_disconn_wdi3_pipes);
|
|
|
|
|
|
-int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
+int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
|
|
|
+ int ipa_ep_idx_tx1)
|
|
|
{
|
|
|
struct ipa3_ep_context *ep_tx, *ep_rx;
|
|
|
+ struct ipa3_ep_context *ep_tx1 = NULL;
|
|
|
int result = 0;
|
|
|
+ struct ipa_ep_cfg_holb holb_cfg;
|
|
|
u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_wlan;
|
|
|
|
|
|
/* wdi3 only support over gsi */
|
|
@@ -757,9 +899,12 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
|
|
|
IPADBG("ep_tx = %d\n", ipa_ep_idx_tx);
|
|
|
IPADBG("ep_rx = %d\n", ipa_ep_idx_rx);
|
|
|
+ IPADBG("ep_tx1 = %d\n", ipa_ep_idx_tx1);
|
|
|
|
|
|
ep_tx = &ipa3_ctx->ep[ipa_ep_idx_tx];
|
|
|
ep_rx = &ipa3_ctx->ep[ipa_ep_idx_rx];
|
|
|
+ if (ipa_ep_idx_tx1 >= 0)
|
|
|
+ ep_tx1 = &ipa3_ctx->ep[ipa_ep_idx_tx1];
|
|
|
|
|
|
IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(ipa_ep_idx_tx));
|
|
|
|
|
@@ -792,11 +937,38 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
goto fail_enable_path1;
|
|
|
}
|
|
|
|
|
|
+ /* Enable and config HOLB TO for both tx pipes */
|
|
|
+ if (ipa_ep_idx_tx1 >= 0) {
|
|
|
+ result = ipa3_enable_data_path(ipa_ep_idx_tx1);
|
|
|
+ if (result) {
|
|
|
+ IPAERR("enable data path failed res=%d clnt=%d\n",
|
|
|
+ result, ipa_ep_idx_tx1);
|
|
|
+ goto fail_enable_path2;
|
|
|
+ }
|
|
|
+ memset(&holb_cfg, 0, sizeof(holb_cfg));
|
|
|
+ holb_cfg.en = IPA_HOLB_TMR_EN;
|
|
|
+ holb_cfg.tmr_val = ipa3_ctx->ipa_wdi3_5g_holb_timeout;
|
|
|
+ IPADBG("Configuring HOLB TO on tx return = %d\n",
|
|
|
+ ipa3_cfg_ep_holb(ipa_ep_idx_tx, &holb_cfg));
|
|
|
+ holb_cfg.tmr_val = ipa3_ctx->ipa_wdi3_2g_holb_timeout;
|
|
|
+ IPADBG("Configuring HOLB TO on tx1 return = %d\n",
|
|
|
+ ipa3_cfg_ep_holb(ipa_ep_idx_tx1, &holb_cfg));
|
|
|
+ }
|
|
|
+
|
|
|
/* start gsi tx channel */
|
|
|
result = gsi_start_channel(ep_tx->gsi_chan_hdl);
|
|
|
if (result) {
|
|
|
IPAERR("failed to start gsi tx channel\n");
|
|
|
- goto fail_enable_path2;
|
|
|
+ goto fail_start_channel1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* start gsi tx1 channel */
|
|
|
+ if (ipa_ep_idx_tx1 >= 0) {
|
|
|
+ result = gsi_start_channel(ep_tx1->gsi_chan_hdl);
|
|
|
+ if (result) {
|
|
|
+ IPAERR("failed to start gsi tx1 channel\n");
|
|
|
+ goto fail_start_channel2;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
result = ipa3_uc_client_add_holb_monitor(ep_tx->gsi_chan_hdl,
|
|
@@ -810,7 +982,7 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
result = gsi_start_channel(ep_rx->gsi_chan_hdl);
|
|
|
if (result) {
|
|
|
IPAERR("failed to start gsi rx channel\n");
|
|
|
- goto fail_start_channel1;
|
|
|
+ goto fail_start_channel3;
|
|
|
}
|
|
|
/* start uC gsi dbg stats monitor */
|
|
|
if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) {
|
|
@@ -822,13 +994,27 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
= ep_tx->gsi_chan_hdl;
|
|
|
ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3].ch_id_info[1].dir
|
|
|
= DIR_CONSUMER;
|
|
|
+ if (ipa_ep_idx_tx1 >= 0) {
|
|
|
+ ipa3_ctx->gsi_info[
|
|
|
+ IPA_HW_PROTOCOL_WDI3].ch_id_info[2].ch_id
|
|
|
+ = ep_tx1->gsi_chan_hdl;
|
|
|
+ ipa3_ctx->gsi_info[
|
|
|
+ IPA_HW_PROTOCOL_WDI3].ch_id_info[2].dir
|
|
|
+ = DIR_CONSUMER;
|
|
|
+ }
|
|
|
ipa3_uc_debug_stats_alloc(
|
|
|
ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3]);
|
|
|
}
|
|
|
goto exit;
|
|
|
|
|
|
-fail_start_channel1:
|
|
|
+fail_start_channel3:
|
|
|
+ if (ipa_ep_idx_tx1 >= 0)
|
|
|
+ gsi_stop_channel(ep_tx1->gsi_chan_hdl);
|
|
|
+fail_start_channel2:
|
|
|
gsi_stop_channel(ep_tx->gsi_chan_hdl);
|
|
|
+fail_start_channel1:
|
|
|
+ if (ipa_ep_idx_tx1 >= 0)
|
|
|
+ ipa3_disable_data_path(ipa_ep_idx_tx1);
|
|
|
fail_enable_path2:
|
|
|
ipa3_disable_data_path(ipa_ep_idx_tx);
|
|
|
fail_enable_path1:
|
|
@@ -839,7 +1025,8 @@ exit:
|
|
|
}
|
|
|
EXPORT_SYMBOL(ipa3_enable_wdi3_pipes);
|
|
|
|
|
|
-int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
+int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
|
|
|
+ int ipa_ep_idx_tx1)
|
|
|
{
|
|
|
int result = 0;
|
|
|
struct ipa3_ep_context *ep;
|
|
@@ -860,12 +1047,23 @@ int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
/* disable tx data path */
|
|
|
result = ipa3_disable_data_path(ipa_ep_idx_tx);
|
|
|
if (result) {
|
|
|
- IPAERR("enable data path failed res=%d clnt=%d.\n", result,
|
|
|
+ IPAERR("disable data path failed res=%d clnt=%d.\n", result,
|
|
|
ipa_ep_idx_tx);
|
|
|
result = -EFAULT;
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
+ /* disable tx1 data path */
|
|
|
+ if (ipa_ep_idx_tx1 >= 0) {
|
|
|
+ result = ipa3_disable_data_path(ipa_ep_idx_tx1);
|
|
|
+ if (result) {
|
|
|
+ IPAERR("disable data path failed res=%d clnt=%d.\n", result,
|
|
|
+ ipa_ep_idx_tx1);
|
|
|
+ result = -EFAULT;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/* disable rx data path */
|
|
|
result = ipa3_disable_data_path(ipa_ep_idx_rx);
|
|
|
if (result) {
|
|
@@ -916,6 +1114,15 @@ int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
result = -EFAULT;
|
|
|
goto fail;
|
|
|
}
|
|
|
+ /* stop gsi tx1 channel */
|
|
|
+ if (ipa_ep_idx_tx1 >= 0) {
|
|
|
+ result = ipa3_stop_gsi_channel(ipa_ep_idx_tx1);
|
|
|
+ if (result) {
|
|
|
+ IPAERR("failed to stop gsi tx1 channel\n");
|
|
|
+ result = -EFAULT;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ }
|
|
|
/* stop uC gsi dbg stats monitor */
|
|
|
if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) {
|
|
|
ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3].ch_id_info[0].ch_id
|
|
@@ -926,6 +1133,14 @@ int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|
|
= 0xff;
|
|
|
ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3].ch_id_info[1].dir
|
|
|
= DIR_CONSUMER;
|
|
|
+ if (ipa_ep_idx_tx1 >= 0) {
|
|
|
+ ipa3_ctx->gsi_info[
|
|
|
+ IPA_HW_PROTOCOL_WDI3].ch_id_info[2].ch_id
|
|
|
+ = 0xff;
|
|
|
+ ipa3_ctx->gsi_info[
|
|
|
+ IPA_HW_PROTOCOL_WDI3].ch_id_info[2].dir
|
|
|
+ = DIR_CONSUMER;
|
|
|
+ }
|
|
|
ipa3_uc_debug_stats_alloc(
|
|
|
ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3]);
|
|
|
}
|