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

Commit 3737b6bc authored by Skylar Chang's avatar Skylar Chang
Browse files

msm: ipa3: Register group 10 access issue mitigation



Due to IPA H/W limitation, RG10 registers group write access
is blocked from AP. Write to these registers using uC proxy.

Signed-off-by: default avatarGhanim Fodi <gfodi@codeaurora.org>
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
Change-Id: I2136b730255c960cbf1a920f2139e29a4b6008b6
parent ee630a97
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -59,6 +59,9 @@ memory allocation over a PCIe bridge
				workaround IPA HW limitations
- qcom,use-gsi:                 Boolean context flag to indicate if the
                                transport protocol is GSI
- qcom,use-rg10-limitation-mitigation:	Boolean context flag to activate
					the mitigation to register group 10
					AP access limitation

IPA pipe sub nodes (A2 static pipes configurations):

+58 −21
Original line number Diff line number Diff line
@@ -2977,6 +2977,40 @@ int ipa3_create_apps_resource(void)
	return result;
}

/**
 * ipa3_init_interrupts() - Register to IPA IRQs
 *
 * Return codes: 0 in success, negative in failure
 *
 */
int ipa3_init_interrupts(void)
{
	int result;

	/*register IPA IRQ handler*/
	result = ipa3_interrupts_init(ipa3_res.ipa_irq, 0,
			master_dev);
	if (result) {
		IPAERR("ipa interrupts initialization failed\n");
		return -ENODEV;
	}

	/*add handler for suspend interrupt*/
	result = ipa3_add_interrupt_handler(IPA_TX_SUSPEND_IRQ,
			ipa3_suspend_handler, true, NULL);
	if (result) {
		IPAERR("register handler for suspend interrupt failed\n");
		result = -ENODEV;
		goto fail_add_interrupt_handler;
	}

	return 0;

fail_add_interrupt_handler:
	free_irq(ipa3_res.ipa_irq, master_dev);
	return result;
}

/**
 * ipa3_destroy_flt_tbl_idrs() - destroy the idr structure for flt tables
 *  The idr strcuture per filtering table is intended for rule id generation
@@ -3069,6 +3103,7 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p,
	ipa3_ctx->skip_uc_pipe_reset = resource_p->skip_uc_pipe_reset;
	ipa3_ctx->transport_prototype = resource_p->transport_prototype;
	ipa3_ctx->ee = resource_p->ee;
	ipa3_ctx->apply_rg10_wa = resource_p->apply_rg10_wa;

	/* default aggregation parameters */
	ipa3_ctx->aggregation_type = IPA_MBIM_16;
@@ -3486,22 +3521,15 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p,
		goto fail_create_apps_resource;
	}

	/*register IPA IRQ handler*/
	result = ipa3_interrupts_init(resource_p->ipa_irq, 0,
			master_dev);
	if (!ipa3_ctx->apply_rg10_wa) {
		result = ipa3_init_interrupts();
		if (result) {
		IPAERR("ipa interrupts initialization failed\n");
			IPAERR("ipa initialization of interrupts failed\n");
			result = -ENODEV;
		goto fail_ipa_interrupts_init;
			goto fail_ipa_init_interrupts;
		}

	/*add handler for suspend interrupt*/
	result = ipa3_add_interrupt_handler(IPA_TX_SUSPEND_IRQ,
			ipa3_suspend_handler, true, NULL);
	if (result) {
		IPAERR("register handler for suspend interrupt failed\n");
		result = -ENODEV;
		goto fail_add_interrupt_handler;
	} else {
		IPADBG("Initialization of ipa interrupts skipped\n");
	}

	if (ipa3_ctx->use_ipa_teth_bridge) {
@@ -3510,7 +3538,7 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p,
		if (result) {
			IPAERR(":teth_bridge init failed (%d)\n", -result);
			result = -ENODEV;
			goto fail_add_interrupt_handler;
			goto fail_teth_bridge_driver_init;
		}
		IPADBG("teth_bridge initialized");
	}
@@ -3543,9 +3571,10 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p,

	return 0;

fail_add_interrupt_handler:
fail_teth_bridge_driver_init:
	if (!ipa3_ctx->apply_rg10_wa)
		free_irq(resource_p->ipa_irq, master_dev);
fail_ipa_interrupts_init:
fail_ipa_init_interrupts:
	ipa3_rm_delete_resource(IPA_RM_RESOURCE_APPS_CONS);
fail_create_apps_resource:
	ipa3_rm_exit();
@@ -3629,6 +3658,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
	ipa_drv_res->ipa_bam_remote_mode = false;
	ipa_drv_res->modem_cfg_emb_pipe_flt = false;
	ipa_drv_res->wan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ;
	ipa_drv_res->apply_rg10_wa = false;

	smmu_disable_htw = of_property_read_bool(pdev->dev.of_node,
			"qcom,smmu-disable-htw");
@@ -3656,7 +3686,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
		IPADBG(": found ipa_drv_res->ipa3_hw_mode = %d",
				ipa_drv_res->ipa3_hw_mode);

	/* Get IPA WAN RX pool sizee */
	/* Get IPA WAN RX pool size */
	result = of_property_read_u32(pdev->dev.of_node,
			"qcom,wan-rx-ring-size",
			&ipa_drv_res->wan_rx_ring_size);
@@ -3793,6 +3823,13 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
	if (result)
		ipa_drv_res->ee = 0;

	ipa_drv_res->apply_rg10_wa =
		of_property_read_bool(pdev->dev.of_node,
		"qcom,use-rg10-limitation-mitigation");
	IPADBG(": Use Register Group 10 limitation mitigation = %s\n",
		ipa_drv_res->apply_rg10_wa
		? "True" : "False");

	return 0;
}

+8 −0
Original line number Diff line number Diff line
@@ -1104,6 +1104,7 @@ union IpaHwMhiDlUlSyncCmdData_t {
 * @uc_loaded: Indicates if uC has loaded
 * @uc_failed: Indicates if uC has failed / returned an error
 * @uc_lock: uC interface lock to allow only one uC interaction at a time
 * @uc_spinlock: same as uc_lock but for irq contexts
 * @uc_completation: Completion mechanism to wait for uC commands
 * @uc_sram_mmio: Pointer to uC mapped memory
 * @pending_cmd: The last command sent waiting to be ACKed
@@ -1116,6 +1117,7 @@ struct ipa3_uc_ctx {
	bool uc_loaded;
	bool uc_failed;
	struct mutex uc_lock;
	spinlock_t uc_spinlock;
	struct completion uc_completion;
	struct IpaHwSharedMemCommonMapping_t *uc_sram_mmio;
	struct IpaHwEventLogInfoData_t *uc_event_top_mmio;
@@ -1253,6 +1255,7 @@ struct ipa3_hash_tuple {
 * @uc_wdi_ctx: WDI specific fields for uC interface
 * @ipa_num_pipes: The number of pipes used by IPA HW
 * @skip_uc_pipe_reset: Indicates whether pipe reset via uC needs to be avoided
 * @apply_rg10_wa: Indicates whether to use register group 10 workaround

 * IPA context - holds all relevant info about IPA driver and its state
 */
@@ -1354,6 +1357,7 @@ struct ipa3_context {
	enum ipa_transport_type transport_prototype;
	unsigned long gsi_dev_hdl;
	u32 ee;
	bool apply_rg10_wa;
	bool smmu_present;
	unsigned long peer_bam_iova;
	phys_addr_t peer_bam_pa;
@@ -1416,6 +1420,7 @@ struct ipa3_plat_drv_res {
	u32 wan_rx_ring_size;
	bool skip_uc_pipe_reset;
	enum ipa_transport_type transport_prototype;
	bool apply_rg10_wa;
};

struct ipa3_mem_partition {
@@ -2101,6 +2106,7 @@ int ipa3_mhi_handle_ipa_config_req(struct ipa_config_req_msg_v01 *config_req);
int ipa3_uc_interface_init(void);
int ipa3_uc_reset_pipe(enum ipa_client_type ipa_client);
int ipa3_uc_state_check(void);
void ipa3_uc_load_notify(void);
int ipa3_uc_send_cmd(u32 cmd, u32 opcode, u32 expected_status,
		    bool polling_mode, unsigned long timeout_jiffies);
void ipa3_register_panic_hdlr(void);
@@ -2128,6 +2134,7 @@ int ipa3_uc_mhi_print_stats(char *dbg_buff, int size);
int ipa3_uc_memcpy(phys_addr_t dest, phys_addr_t src, int len);
void ipa3_tag_free_buf(void *user1, int user2);
struct ipa_gsi_ep_config *ipa3_get_gsi_ep_info(int ipa_ep_idx);
void ipa3_uc_rg10_write_reg(void *base, u32 offset, u32 val);

u32 ipa3_get_num_pipes(void);
struct ipa_smmu_cb_ctx *ipa3_get_wlan_smmu_ctx(void);
@@ -2135,6 +2142,7 @@ struct ipa_smmu_cb_ctx *ipa3_get_uc_smmu_ctx(void);
struct iommu_domain *ipa_get_uc_smmu_domain(void);
int ipa3_ap_suspend(struct device *dev);
int ipa3_ap_resume(struct device *dev);
int ipa3_init_interrupts(void);
struct iommu_domain *ipa3_get_smmu_domain(void);
int ipa3_rm_add_dependency_sync(enum ipa_rm_resource_name resource_name,
		enum ipa_rm_resource_name depends_on_name);
+11 −6
Original line number Diff line number Diff line
@@ -181,7 +181,8 @@ static void ipa3_enable_tx_suspend_wa(struct work_struct *work)
	en |= suspend_bmask;
	IPADBG("enable TX_SUSPEND_IRQ, IPA_IRQ_EN_EE reg, write val = %u\n"
		, en);
	ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee), en);
	ipa3_uc_rg10_write_reg(ipa3_ctx->mmio,
		IPA_IRQ_EN_EE_n_ADDR(ipa_ee), en);
	ipa3_process_interrupts();
	ipa3_dec_client_disable_clks();

@@ -204,7 +205,8 @@ static void ipa3_tx_suspend_interrupt_wa(void)
	val &= ~suspend_bmask;
	IPADBG("Disabling TX_SUSPEND_IRQ, write val: %u to IPA_IRQ_EN_EE reg\n",
		val);
	ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee), val);
	ipa3_uc_rg10_write_reg(ipa3_ctx->mmio,
		IPA_IRQ_EN_EE_n_ADDR(ipa_ee), val);

	IPADBG(" processing suspend interrupt work-around, delayed work\n");
	queue_delayed_work(ipa_interrupt_wq, &dwork_en_suspend_int,
@@ -233,7 +235,7 @@ static void ipa3_process_interrupts(void)
				ipa3_handle_interrupt(i);
			bmsk = bmsk << 1;
		}
		ipa_write_reg(ipa3_ctx->mmio,
		ipa3_uc_rg10_write_reg(ipa3_ctx->mmio,
				IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), reg);
		reg = ipa_read_reg(ipa3_ctx->mmio,
				IPA_IRQ_STTS_EE_n_ADDR(ipa_ee));
@@ -324,7 +326,8 @@ int ipa3_add_interrupt_handler(enum ipa_irq_type interrupt,
	IPADBG("read IPA_IRQ_EN_EE_n_ADDR register. reg = %d\n", val);
	bmsk = 1 << irq_num;
	val |= bmsk;
	ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee), val);
	ipa3_uc_rg10_write_reg(ipa3_ctx->mmio,
		IPA_IRQ_EN_EE_n_ADDR(ipa_ee), val);
	IPADBG("wrote IPA_IRQ_EN_EE_n_ADDR register. reg = %d\n", val);
	return 0;
}
@@ -362,7 +365,8 @@ int ipa3_remove_interrupt_handler(enum ipa_irq_type interrupt)
	val = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee));
	bmsk = 1 << irq_num;
	val &= ~bmsk;
	ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee), val);
	ipa3_uc_rg10_write_reg(ipa3_ctx->mmio,
		IPA_IRQ_EN_EE_n_ADDR(ipa_ee), val);

	return 0;
}
@@ -400,7 +404,8 @@ int ipa3_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev)
	}

	/*Clearing interrupts status*/
	ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), reg);
	ipa3_uc_rg10_write_reg(ipa3_ctx->mmio,
		IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), reg);

	res = request_irq(ipa_irq, (irq_handler_t) ipa3_isr,
				IRQF_TRIGGER_RISING, "ipa", ipa_dev);
+1 −1
Original line number Diff line number Diff line
@@ -239,7 +239,7 @@

#define IPA_IRQ_EE_UC_n_OFFS(n) (0x0000301c + 0x1000 * (n))

#define IPA_UC_MAILBOX_m_n_OFFS_v3_0(m, n) (0x00022000 + 0x80 * (m) + 0x4 * (n))
#define IPA_UC_MAILBOX_m_n_OFFS_v3_0(m, n) (0x00032000 + 0x80 * (m) + 0x4 * (n))

#define IPA_SYS_PKT_PROC_CNTXT_BASE_OFST (0x000001e0)
#define IPA_LOCAL_PKT_PROC_CNTXT_BASE_OFST (0x000001e8)
Loading