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

Commit d24203ad authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: ADPL over ODL support on MHI Prime channels"

parents 39764218 47e6e4fd
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -2992,6 +2992,7 @@ int ipa_mpm_reset_dma_mode(enum ipa_client_type src_pipe,
	enum ipa_client_type dst_pipe);
int ipa_mpm_panic_handler(char *buf, int size);
int ipa3_get_mhip_gsi_stats(struct ipa3_uc_dbg_ring_stats *stats);
int ipa3_mpm_enable_adpl_over_odl(bool enable);
#else
static inline int ipa_mpm_mhip_xdci_pipe_enable(
	enum ipa_usb_teth_prot prot)
@@ -3026,6 +3027,12 @@ static inline int ipa3_get_mhip_gsi_stats(struct ipa3_uc_dbg_ring_stats *stats)
{
	return 0;
}

static inline int ipa3_mpm_enable_adpl_over_odl(bool enable)
{
	return 0;
}

#endif /* CONFIG_IPA3_MHI_PRIME_MANAGER */

static inline void *alloc_and_init(u32 size, u32 init_val)
@@ -3040,4 +3047,6 @@ static inline void *alloc_and_init(u32 size, u32 init_val)

/* query ipa APQ mode*/
bool ipa3_is_apq(void);
/* check if odl is connected */
bool ipa3_is_odl_connected(void);
#endif /* _IPA3_I_H_ */
+122 −48
Original line number Diff line number Diff line
@@ -271,7 +271,7 @@ static struct ipa_ep_cfg mhip_ul_rmnet_ep_cfg = {
	},
};

/* For configuring IPA_CLIENT_MHIP_DPL_PROD */
/* For configuring IPA_CLIENT_MHIP_DPL_PROD using USB*/
static struct ipa_ep_cfg mhip_dl_dpl_ep_cfg = {
	.mode = {
		.mode = IPA_DMA,
@@ -391,6 +391,7 @@ struct ipa_mpm_context {
	atomic_t probe_cnt;
	atomic_t pcie_clk_total_cnt;
	atomic_t ipa_clk_total_cnt;
	atomic_t adpl_over_usb_available;
	struct device *parent_pdev;
	struct ipa_smmu_cb_ctx carved_smmu_cb;
	struct device *mhi_parent_dev;
@@ -469,6 +470,29 @@ static void ipa_mpm_gsi_chan_err_cb(struct gsi_chan_err_notify *err_data)
	ipa_assert();
}

static int ipa_mpm_set_dma_mode(enum ipa_client_type src_pipe,
	enum ipa_client_type dst_pipe, bool reset)
{
	int result = 0;
	struct ipa_ep_cfg ep_cfg = { { 0 } };

	IPA_MPM_FUNC_ENTRY();
	IPA_MPM_DBG("DMA from %d to %d reset=%d\n", src_pipe, dst_pipe, reset);

	/* Reset to basic if reset = 1, otherwise set to DMA */
	if (reset)
		ep_cfg.mode.mode = IPA_BASIC;
	else
		ep_cfg.mode.mode = IPA_DMA;
	ep_cfg.mode.dst = dst_pipe;
	ep_cfg.seq.set_dynamic = true;

	result = ipa_cfg_ep(ipa_get_ep_mapping(src_pipe), &ep_cfg);
	IPA_MPM_FUNC_EXIT();

	return result;
}

/**
 * ipa_mpm_smmu_map() - SMMU maps ring and the buffer pointer.
 * @va_addr: virtual address that needs to be mapped
@@ -2198,6 +2222,15 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev,

	atomic_inc(&ipa_mpm_ctx->probe_cnt);
	ipa_mpm_ctx->md[probe_id].init_complete = true;

	/* Check if ODL pipe is connected to MHIP DPL pipe before probe */
	if (probe_id == IPA_MPM_MHIP_CH_ID_2 &&
		ipa3_is_odl_connected()) {
		IPA_MPM_ERR("setting DPL DMA to ODL\n");
		ret = ipa_mpm_set_dma_mode(IPA_CLIENT_MHI_PRIME_DPL_PROD,
			IPA_CLIENT_USB_DPL_CONS, false);
	}

	IPA_MPM_FUNC_EXIT();
	return 0;

@@ -2344,46 +2377,6 @@ static void ipa_mpm_mhi_status_cb(struct mhi_device *mhi_dev,
	mutex_unlock(&ipa_mpm_ctx->md[mhip_idx].lpm_mutex);
}

static int ipa_mpm_set_dma_mode(enum ipa_client_type src_pipe,
	enum ipa_client_type dst_pipe)
{
	int result = 0;
	struct ipa_ep_cfg ep_cfg = { { 0 } };

	IPA_MPM_FUNC_ENTRY();
	IPA_MPM_DBG("DMA from %d to %d\n", src_pipe, dst_pipe);

	/* Set USB PROD PIPE DMA to MHIP PROD PIPE */
	ep_cfg.mode.mode = IPA_DMA;
	ep_cfg.mode.dst = dst_pipe;
	ep_cfg.seq.set_dynamic = true;

	result = ipa_cfg_ep(ipa_get_ep_mapping(src_pipe), &ep_cfg);
	IPA_MPM_FUNC_EXIT();

	return result;
}

int ipa_mpm_reset_dma_mode(enum ipa_client_type src_pipe,
	enum ipa_client_type dst_pipe)
{
	int result = 0;
	struct ipa_ep_cfg ep_cfg = { { 0 } };

	IPA_MPM_FUNC_ENTRY();
	IPA_MPM_DBG("DMA from %d to %d\n", src_pipe, dst_pipe);

	/* Set USB PROD PIPE DMA to MHIP PROD PIPE */
	ep_cfg.mode.mode = IPA_BASIC;
	ep_cfg.mode.dst = IPA_CLIENT_APPS_LAN_CONS;
	ep_cfg.seq.set_dynamic = true;

	result = ipa_cfg_ep(ipa_get_ep_mapping(src_pipe), &ep_cfg);
	IPA_MPM_FUNC_EXIT();

	return result;
}

static void ipa_mpm_mhip_map_prot(enum ipa_usb_teth_prot prot,
	enum ipa_mpm_mhip_client_type *mhip_client)
{
@@ -2447,11 +2440,12 @@ int ipa_mpm_mhip_xdci_pipe_enable(enum ipa_usb_teth_prot xdci_teth_prot)
	switch (mhip_client) {
	case IPA_MPM_MHIP_USB_RMNET:
		ipa_mpm_set_dma_mode(IPA_CLIENT_USB_PROD,
			IPA_CLIENT_MHI_PRIME_RMNET_CONS);
			IPA_CLIENT_MHI_PRIME_RMNET_CONS, false);
		break;
	case IPA_MPM_MHIP_USB_DPL:
		IPA_MPM_DBG("connecting DPL prot %d\n", mhip_client);
		ipa_mpm_change_teth_state(probe_id, IPA_MPM_TETH_CONNECTED);
		atomic_set(&ipa_mpm_ctx->adpl_over_usb_available, 1);
		return 0;
	default:
		IPA_MPM_DBG("mhip_client = %d not processed\n", mhip_client);
@@ -2538,8 +2532,8 @@ int ipa_mpm_mhip_xdci_pipe_disable(enum ipa_usb_teth_prot xdci_teth_prot)

	switch (mhip_client) {
	case IPA_MPM_MHIP_USB_RMNET:
		ret = ipa_mpm_reset_dma_mode(IPA_CLIENT_USB_PROD,
			IPA_CLIENT_MHI_PRIME_RMNET_CONS);
		ret = ipa_mpm_set_dma_mode(IPA_CLIENT_USB_PROD,
			IPA_CLIENT_APPS_LAN_CONS, true);
		if (ret) {
			IPA_MPM_ERR("failed to reset dma mode\n");
			return ret;
@@ -2550,12 +2544,17 @@ int ipa_mpm_mhip_xdci_pipe_disable(enum ipa_usb_teth_prot xdci_teth_prot)
		return 0;
	case IPA_MPM_MHIP_USB_DPL:
		IPA_MPM_DBG("Teth Disconnecting for DPL\n");

		/* change teth state only if ODL is disconnected */
		if (!ipa3_is_odl_connected()) {
			ipa_mpm_change_teth_state(probe_id, IPA_MPM_TETH_INIT);
			ipa_mpm_ctx->md[probe_id].mhip_client =
				IPA_MPM_MHIP_NONE;
		}
		ret = ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id);
		if (ret)
			IPA_MPM_ERR("Error cloking off PCIe clk, err = %d\n",
				ret);
		ipa_mpm_ctx->md[probe_id].mhip_client = IPA_MPM_MHIP_NONE;
			IPA_MPM_ERR("Error clking off PCIe clk err%d\n", ret);
		atomic_set(&ipa_mpm_ctx->adpl_over_usb_available, 0);
		return ret;
	default:
		IPA_MPM_ERR("mhip_client = %d not supported\n", mhip_client);
@@ -2867,6 +2866,81 @@ int ipa3_get_mhip_gsi_stats(struct ipa3_uc_dbg_ring_stats *stats)
	return 0;
}

/**
 * ipa3_mpm_enable_adpl_over_odl() - Enable or disable ADPL over ODL
 * @enable:	true for enable, false for disable
 *
 * Returns:	0 on success, negative on failure
 *
 */
int ipa3_mpm_enable_adpl_over_odl(bool enable)
{
	int ret;

	IPA_MPM_FUNC_ENTRY();

	if (!ipa3_is_mhip_offload_enabled()) {
		IPA_MPM_ERR("mpm ctx is NULL\n");
		return -EPERM;
	}

	if (enable) {
		/* inc clk count and set DMA to ODL */
		IPA_MPM_DBG("mpm enabling ADPL over ODL\n");

		ret = ipa_mpm_vote_unvote_pcie_clk(CLK_ON,
			IPA_MPM_MHIP_CH_ID_2);
		if (ret) {
			IPA_MPM_ERR("Error cloking on PCIe clk, err = %d\n",
				ret);
			return ret;
		}

		ret = ipa_mpm_set_dma_mode(IPA_CLIENT_MHI_PRIME_DPL_PROD,
			IPA_CLIENT_ODL_DPL_CONS, false);
		if (ret) {
			IPA_MPM_ERR("MPM failed to set dma mode to ODL\n");
			ipa_mpm_vote_unvote_pcie_clk(CLK_OFF,
				IPA_MPM_MHIP_CH_ID_2);
			return ret;
		}

		ipa_mpm_change_teth_state(IPA_MPM_MHIP_CH_ID_2,
			IPA_MPM_TETH_CONNECTED);
	} else {
		/* dec clk count and set DMA to USB */
		IPA_MPM_DBG("mpm disabling ADPL over ODL\n");

		ret = ipa_mpm_vote_unvote_pcie_clk(CLK_OFF,
			IPA_MPM_MHIP_CH_ID_2);
		if (ret) {
			IPA_MPM_ERR("Error cloking off PCIe clk, err = %d\n",
				ret);
				return ret;
		}

		ret = ipa_mpm_set_dma_mode(IPA_CLIENT_MHI_PRIME_DPL_PROD,
			IPA_CLIENT_USB_DPL_CONS, false);
		if (ret) {
			IPA_MPM_ERR("MPM failed to set dma mode to USB\n");
			ipa_mpm_vote_unvote_pcie_clk(CLK_ON,
				IPA_MPM_MHIP_CH_ID_2);
			return ret;
		}

		/* If USB is not available then reset teth state */
		if (atomic_read(&ipa_mpm_ctx->adpl_over_usb_available)) {
			IPA_MPM_DBG("mpm enabling ADPL over USB\n");
		} else {
			ipa_mpm_change_teth_state(IPA_MPM_MHIP_CH_ID_2,
				IPA_MPM_TETH_INIT);
			IPA_MPM_DBG("USB disconnected. ADPL on standby\n");
		}
	}

	IPA_MPM_FUNC_EXIT();
	return ret;
}

late_initcall(ipa_mpm_init);
MODULE_LICENSE("GPL v2");
+38 −4
Original line number Diff line number Diff line
@@ -287,6 +287,10 @@ int ipa_setup_odl_pipe(void)

	ipa_odl_ep_cfg->ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR;
	ipa_odl_ep_cfg->ipa_ep_cfg.aggr.aggr_hard_byte_limit_en = 1;
	if (ipa3_is_mhip_offload_enabled()) {
		IPADBG("MHIP is enabled, disable aggregation for ODL pipe");
		ipa_odl_ep_cfg->ipa_ep_cfg.aggr.aggr_en = IPA_BYPASS_AGGR;
	}
	ipa_odl_ep_cfg->ipa_ep_cfg.aggr.aggr = IPA_GENERIC;
	ipa_odl_ep_cfg->ipa_ep_cfg.aggr.aggr_byte_limit =
						IPA_ODL_AGGR_BYTE_LIMIT;
@@ -375,11 +379,27 @@ int ipa3_odl_pipe_open(void)
	 * Send signal to ipa_odl_ctl_fops_read,
	 * to send ODL ep open notification
	 */
	if (ipa3_is_mhip_offload_enabled()) {
		IPADBG("MHIP is enabled, continue\n");
		ipa3_odl_ctx->odl_state.odl_open = true;
		ipa3_odl_ctx->odl_state.odl_setup_done_sent = true;
		ipa3_odl_ctx->odl_state.odl_ep_info_sent = true;
		ipa3_odl_ctx->odl_state.odl_connected = true;
		ipa3_odl_ctx->odl_state.odl_disconnected = false;

		/* Enable ADPL over ODL for MPM */
		ret = ipa3_mpm_enable_adpl_over_odl(true);
		if (ret) {
			IPAERR("mpm failed to enable ADPL over ODL %d\n", ret);
			return ret;
		}
	} else {
		ipa3_odl_ctx->odl_ctl_msg_wq_flag = true;
	IPADBG("Wake up odl ctl\n");
		IPAERR("Wake up odl ctl\n");
		wake_up_interruptible(&odl_ctl_msg_wq);
		if (ipa3_odl_ctx->odl_state.odl_disconnected)
			ipa3_odl_ctx->odl_state.odl_disconnected = false;
	}
fail:
	return ret;

@@ -414,6 +434,15 @@ static int ipa_adpl_release(struct inode *inode, struct file *filp)
	if (ret)
		IPAERR("failed to activate pm\n");
	ipa3_odl_pipe_cleanup(false);

	/* Disable ADPL over ODL for MPM */
	if (ipa3_is_mhip_offload_enabled()) {
		ret = ipa3_mpm_enable_adpl_over_odl(false);
		if (ret)
			IPAERR("mpm failed to disable ADPL over ODL\n");

	}

	return ret;
}

@@ -727,3 +756,8 @@ int ipa_odl_init(void)
fail_mem_ctx:
	return result;
}

bool ipa3_is_odl_connected(void)
{
	return ipa3_odl_ctx->odl_state.odl_connected;
}