Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f9c9fc1 authored by Mohammed Javid's avatar Mohammed Javid
Browse files

msm: ipa: Fix clock enable/disable in wdi3 API's



 - Enable/disable clock while disconnect WDI,
   which leads to un-clocked NOC access.
 - Fix decrement clock in update QMAP_ID API,
   without which ipa clocks will be ON throughout
   and it will not allow system enter low power mode.
 - Handle error condition for smmu-s1 enabled case.

Change-Id: Id4913cf1eddc7aa4f407a5d242fcd3467ff73447
Signed-off-by: default avatarMohammed Javid <mjavid@codeaurora.org>
parent d131eb25
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2484,6 +2484,8 @@ int ipa_create_gsi_smmu_mapping(int res_idx, bool wlan_smmu_en,
		phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
		unsigned long *iova);

void ipa3_release_wdi3_gsi_smmu_mappings(u8 dir);

/*
 * Tethering bridge (Rmnet / MBIM)
 */
+30 −0
Original line number Diff line number Diff line
@@ -869,6 +869,36 @@ int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
	return 0;
}

void ipa3_release_wdi3_gsi_smmu_mappings(u8 dir)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
	int i, j, start, end;

	if (dir == IPA_WDI3_TX_DIR) {
		start = IPA_WDI_TX_RING_RES;
		end = IPA_WDI_TX_DB_RES;
	} else {
		start = IPA_WDI_RX_RING_RES;
		end = IPA_WDI_RX_COMP_RING_WP_RES;
	}

	for (i = start; i <= end; i++) {
		if (wdi_res[i].valid) {
			for (j = 0; j < wdi_res[i].nents; j++) {
				iommu_unmap(cb->mapping->domain,
					wdi_res[i].res[j].iova,
					wdi_res[i].res[j].size);
				ipa3_ctx->wdi_map_cnt--;
			}
			kfree(wdi_res[i].res);
			wdi_res[i].valid = false;
		}
	}

	if (ipa3_ctx->wdi_map_cnt == 0)
		cb->next_addr = cb->va_end;
}

int ipa_create_gsi_smmu_mapping(int res_idx, bool wlan_smmu_en,
		phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
		unsigned long *iova)
+30 −28
Original line number Diff line number Diff line
@@ -12,9 +12,6 @@
#include "ipa_i.h"
#include <linux/ipa_wdi3.h>

#define IPA_WDI3_TX_DIR 1
#define IPA_WDI3_RX_DIR 2

#define UPDATE_RP_MODERATION_CONFIG 1
#define UPDATE_RP_MODERATION_THRESHOLD 8

@@ -135,8 +132,8 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
		&ep->gsi_evt_ring_hdl);
	if (result != GSI_STATUS_SUCCESS) {
		IPAERR("fail to alloc RX event ring\n");
		/* TODO: release the gsi_smmu_mapping here if smmu enabled */
		return -EFAULT;
		result = -EFAULT;
		goto fail_smmu_mapping;
	}

	ep->gsi_mem_info.evt_ring_len = gsi_evt_ring_props.ring_len;
@@ -204,7 +201,6 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
	result = gsi_alloc_channel(&gsi_channel_props, ipa3_ctx->gsi_dev_hdl,
		&ep->gsi_chan_hdl);
	if (result != GSI_STATUS_SUCCESS) {
		/* TODO: release the gsi_smmu_mapping here if smmu enabled */
		goto fail_get_gsi_ep_info;
	}

@@ -371,10 +367,6 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
				result = -EFAULT;
				goto fail_write_scratch;
			}
			/*
			 * TODO: for all access over PCIe for MDM,
			 * there is no SMMU
			 */
			ch_scratch.wdi3.wifi_rp_address_low = (u32)va;
			ch_scratch.wdi3.wifi_rp_address_high =
				(u32)((u64)va >> 32);
@@ -436,6 +428,8 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
fail_get_gsi_ep_info:
	gsi_dealloc_evt_ring(ep->gsi_evt_ring_hdl);
	ep->gsi_evt_ring_hdl = ~0;
fail_smmu_mapping:
	ipa3_release_wdi3_gsi_smmu_mappings(dir);
	return result;
}

@@ -666,21 +660,22 @@ int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
	ep_tx = &ipa3_ctx->ep[ipa_ep_idx_tx];
	ep_rx = &ipa3_ctx->ep[ipa_ep_idx_rx];

	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(ipa_ep_idx_tx));
	/* tear down tx pipe */
	result = ipa3_reset_gsi_channel(ipa_ep_idx_tx);
	if (result != GSI_STATUS_SUCCESS) {
		IPAERR("failed to reset gsi channel: %d.\n", result);
		return result;
		goto exit;
	}
	result = gsi_reset_evt_ring(ep_tx->gsi_evt_ring_hdl);
	if (result != GSI_STATUS_SUCCESS) {
		IPAERR("failed to reset evt ring: %d.\n", result);
		return result;
		goto exit;
	}
	result = ipa3_release_gsi_channel(ipa_ep_idx_tx);
	if (result) {
		IPAERR("failed to release gsi channel: %d\n", result);
		return result;
		goto exit;
	}

	memset(ep_tx, 0, sizeof(struct ipa3_ep_context));
@@ -690,23 +685,25 @@ int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
	result = ipa3_reset_gsi_channel(ipa_ep_idx_rx);
	if (result != GSI_STATUS_SUCCESS) {
		IPAERR("failed to reset gsi channel: %d.\n", result);
		return result;
		goto exit;
	}
	result = gsi_reset_evt_ring(ep_rx->gsi_evt_ring_hdl);
	if (result != GSI_STATUS_SUCCESS) {
		IPAERR("failed to reset evt ring: %d.\n", result);
		return result;
		goto exit;
	}
	result = ipa3_release_gsi_channel(ipa_ep_idx_rx);
	if (result) {
		IPAERR("failed to release gsi channel: %d\n", result);
		return result;
		goto exit;
	}

	ipa3_delete_dflt_flt_rules(ipa_ep_idx_rx);
	memset(ep_rx, 0, sizeof(struct ipa3_ep_context));
	IPADBG("rx client (ep: %d) disconnected\n", ipa_ep_idx_rx);

exit:
	IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_by_pipe(ipa_ep_idx_tx));
	return result;
}

@@ -728,20 +725,23 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
	ep_tx = &ipa3_ctx->ep[ipa_ep_idx_tx];
	ep_rx = &ipa3_ctx->ep[ipa_ep_idx_rx];

	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(ipa_ep_idx_tx));

	/* start gsi tx channel */
	result = gsi_start_channel(ep_tx->gsi_chan_hdl);
	if (result) {
		IPAERR("failed to start gsi tx channel\n");
		return -EFAULT;
		result = -EFAULT;
		goto exit;
	}

	/* start gsi rx channel */
	result = gsi_start_channel(ep_rx->gsi_chan_hdl);
	if (result) {
		IPAERR("failed to start gsi rx channel\n");
		return -EFAULT;
		result = -EFAULT;
		goto exit;
	}
	IPA_ACTIVE_CLIENTS_INC_SIMPLE();

	/* enable data path */
	result = ipa3_enable_data_path(ipa_ep_idx_rx);
@@ -749,7 +749,7 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
		IPAERR("enable data path failed res=%d clnt=%d.\n", result,
			ipa_ep_idx_rx);
		result = -EFAULT;
		goto fail;
		goto exit;
	}

	result = ipa3_enable_data_path(ipa_ep_idx_tx);
@@ -757,11 +757,11 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
		IPAERR("enable data path failed res=%d clnt=%d.\n", result,
			ipa_ep_idx_tx);
		result = -EFAULT;
		goto fail;
		goto exit;
	}

fail:
	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
exit:
	IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(ipa_ep_idx_tx));
	return result;
}

@@ -865,13 +865,13 @@ int ipa3_write_qmapid_wdi3_gsi_pipe(u32 clnt_hdl, u8 qmap_id)

	if (result != GSI_STATUS_SUCCESS) {
		IPAERR("failed to read channel scratch %d\n", result);
		return result;
		goto exit;
	}
	result = gsi_stop_channel(ep->gsi_chan_hdl);
	if (result != GSI_STATUS_SUCCESS && result != -GSI_STATUS_AGAIN &&
		result != -GSI_STATUS_TIMED_OUT) {
		IPAERR("failed to stop gsi channel %d\n", result);
		return result;
		goto exit;
	}

	ch_scratch.wdi3.qmap_id = qmap_id;
@@ -879,14 +879,16 @@ int ipa3_write_qmapid_wdi3_gsi_pipe(u32 clnt_hdl, u8 qmap_id)
			ch_scratch);
	if (result != GSI_STATUS_SUCCESS) {
		IPAERR("failed to write channel scratch %d\n", result);
		return result;
		goto exit;
	}

	result =  gsi_start_channel(ep->gsi_chan_hdl);
	if (result != GSI_STATUS_SUCCESS) {
		IPAERR("failed to start gsi channel %d\n", result);
		return result;
		goto exit;
	}

	return 0;
exit:
	IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
	return result;
}
+3 −0
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@ enum ipa_wdi_version {
	IPA_WDI_3
};

#define IPA_WDI3_TX_DIR 1
#define IPA_WDI3_RX_DIR 2

/**
 * struct ipa_wdi_init_in_params - wdi init input parameters
 *