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

Commit af57eb70 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa4: bypass smmu for MHI"

parents 6ba01f5c efc0a0f8
Loading
Loading
Loading
Loading
+255 −188
Original line number Diff line number Diff line
@@ -269,6 +269,9 @@ static DECLARE_DELAYED_WORK(ipa3_transport_release_resource_work,
	ipa3_transport_release_resource);
static void ipa_gsi_notify_cb(struct gsi_per_notify *notify);

static int ipa3_attach_to_smmu(void);
static int ipa3_alloc_pkt_init(void);

static void ipa3_load_ipa_fw(struct work_struct *work);
static DECLARE_WORK(ipa3_fw_loading_work, ipa3_load_ipa_fw);

@@ -277,15 +280,12 @@ static DECLARE_WORK(ipa_dec_clients_disable_clks_on_wq_work,
	ipa_dec_clients_disable_clks_on_wq);

static struct ipa3_plat_drv_res ipa3_res = {0, };
struct msm_bus_scale_pdata *ipa3_bus_scale_table;

static struct clk *ipa3_clk;

struct ipa3_context *ipa3_ctx;
static struct device *master_dev;
struct platform_device *ipa3_pdev;
static struct {
	bool present;
	bool present[IPA_SMMU_CB_MAX];
	bool arm_smmu;
	bool fast_map;
	bool s1_bypass_arr[IPA_SMMU_CB_MAX];
@@ -508,42 +508,19 @@ struct device *ipa3_get_dma_dev(void)
}

/**
 * ipa3_get_smmu_ctx()- Return the wlan smmu context
 *
 * Return value: pointer to smmu context address
 */
struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(void)
{
	return &smmu_cb[IPA_SMMU_CB_AP];
}

/**
 * ipa3_get_wlan_smmu_ctx()- Return the wlan smmu context
 * ipa3_get_smmu_ctx()- Return smmu context for the given cb_type
 *
 * Return value: pointer to smmu context address
 */
struct ipa_smmu_cb_ctx *ipa3_get_wlan_smmu_ctx(void)
struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(enum ipa_smmu_cb_type cb_type)
{
	return &smmu_cb[IPA_SMMU_CB_WLAN];
}

/**
 * ipa3_get_uc_smmu_ctx()- Return the uc smmu context
 *
 * Return value: pointer to smmu context address
 */
struct ipa_smmu_cb_ctx *ipa3_get_uc_smmu_ctx(void)
{
	return &smmu_cb[IPA_SMMU_CB_UC];
	return &smmu_cb[cb_type];
}

static int ipa3_open(struct inode *inode, struct file *filp)
{
	struct ipa3_context *ctx = NULL;

	IPADBG_LOW("ENTER\n");
	ctx = container_of(inode->i_cdev, struct ipa3_context, cdev);
	filp->private_data = ctx;
	filp->private_data = ipa3_ctx;

	return 0;
}
@@ -3509,6 +3486,11 @@ static unsigned int ipa3_get_bus_vote(void)
*/
void ipa3_enable_clks(void)
{
	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
		IPAERR("not supported in this mode\n");
		return;
	}

	IPADBG("enabling IPA clocks and bus voting\n");

	if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl,
@@ -3540,6 +3522,11 @@ void _ipa_disable_clks_v3_0(void)
*/
void ipa3_disable_clks(void)
{
	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
		IPAERR("not supported in this mode\n");
		return;
	}

	IPADBG("disabling IPA clocks and bus voting\n");

	ipa3_ctx->ctrl->ipa3_disable_clks();
@@ -3870,6 +3857,11 @@ int ipa3_set_clock_plan_from_pm(int idx)
	if (!ipa3_ctx->enable_clock_scaling)
		return 0;

	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
		IPAERR("not supported in this mode\n");
		return 0;
	}

	IPADBG_LOW("idx = %d\n", idx);

	if (idx <= 0 || idx >= ipa3_ctx->ctrl->msm_bus_data_ptr->num_usecases) {
@@ -3921,6 +3913,11 @@ int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
	enum ipa_voltage_level needed_voltage;
	u32 clk_rate;

	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
		IPAERR("not supported in this mode\n");
		return 0;
	}

	IPADBG_LOW("floor_voltage=%d, bandwidth_mbps=%u",
					floor_voltage, bandwidth_mbps);

@@ -4177,7 +4174,7 @@ int ipa3_init_interrupts(void)

	/*register IPA IRQ handler*/
	result = ipa3_interrupts_init(ipa3_res.ipa_irq, 0,
			master_dev);
			&ipa3_ctx->master_pdev->dev);
	if (result) {
		IPAERR("ipa interrupts initialization failed\n");
		return -ENODEV;
@@ -4195,7 +4192,7 @@ int ipa3_init_interrupts(void)
	return 0;

fail_add_interrupt_handler:
	free_irq(ipa3_res.ipa_irq, master_dev);
	free_irq(ipa3_res.ipa_irq, &ipa3_ctx->master_pdev->dev);
	return result;
}

@@ -4411,6 +4408,78 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
	if (ipa3_ctx->ipa_hw_type != IPA_HW_v4_0)
		ipa3_proxy_clk_vote();

	/* SMMU was already attached if used, safe to do allocations */
	if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio,
		ipa3_ctx->pdev)) {
		IPAERR("fail to init ipahal\n");
		result = -EFAULT;
		goto fail_ipahal;
	}

	result = ipa3_init_hw();
	if (result) {
		IPAERR(":error initializing HW\n");
		result = -ENODEV;
		goto fail_init_hw;
	}
	IPADBG("IPA HW initialization sequence completed");

	ipa3_ctx->ipa_num_pipes = ipa3_get_num_pipes();
	if (ipa3_ctx->ipa_num_pipes > IPA3_MAX_NUM_PIPES) {
		IPAERR("IPA has more pipes then supported has %d, max %d\n",
			ipa3_ctx->ipa_num_pipes, IPA3_MAX_NUM_PIPES);
		result = -ENODEV;
		goto fail_init_hw;
	}

	ipa3_ctx->ctrl->ipa_sram_read_settings();
	IPADBG("SRAM, size: 0x%x, restricted bytes: 0x%x\n",
		ipa3_ctx->smem_sz, ipa3_ctx->smem_restricted_bytes);

	IPADBG("hdr_lcl=%u ip4_rt_hash=%u ip4_rt_nonhash=%u\n",
		ipa3_ctx->hdr_tbl_lcl, ipa3_ctx->ip4_rt_tbl_hash_lcl,
		ipa3_ctx->ip4_rt_tbl_nhash_lcl);

	IPADBG("ip6_rt_hash=%u ip6_rt_nonhash=%u\n",
		ipa3_ctx->ip6_rt_tbl_hash_lcl, ipa3_ctx->ip6_rt_tbl_nhash_lcl);

	IPADBG("ip4_flt_hash=%u ip4_flt_nonhash=%u\n",
		ipa3_ctx->ip4_flt_tbl_hash_lcl,
		ipa3_ctx->ip4_flt_tbl_nhash_lcl);

	IPADBG("ip6_flt_hash=%u ip6_flt_nonhash=%u\n",
		ipa3_ctx->ip6_flt_tbl_hash_lcl,
		ipa3_ctx->ip6_flt_tbl_nhash_lcl);

	if (ipa3_ctx->smem_reqd_sz > ipa3_ctx->smem_sz) {
		IPAERR("SW expect more core memory, needed %d, avail %d\n",
			ipa3_ctx->smem_reqd_sz, ipa3_ctx->smem_sz);
		result = -ENOMEM;
		goto fail_init_hw;
	}

	result = ipa3_allocate_dma_task_for_gsi();
	if (result) {
		IPAERR("failed to allocate dma task\n");
		goto fail_dma_task;
	}

	if (ipa3_nat_ipv6ct_init_devices()) {
		IPAERR("unable to init NAT and IPv6CT devices\n");
		result = -ENODEV;
		goto fail_nat_ipv6ct_init_dev;
	}

	result = ipa3_alloc_pkt_init();
	if (result) {
		IPAERR("Failed to alloc pkt_init payload\n");
		result = -ENODEV;
		goto fail_allok_pkt_init;
	}

	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5)
		ipa3_enable_dcd();

	/*
	 * indication whether working in MHI config or non MHI config is given
	 * in ipa3_write which is launched before ipa3_post_init. i.e. from
@@ -4563,6 +4632,15 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
fail_register_device:
	ipa3_destroy_flt_tbl_idrs();
	ipa3_proxy_clk_unvote();
fail_allok_pkt_init:
	ipa3_nat_ipv6ct_destroy_devices();
fail_nat_ipv6ct_init_dev:
	ipa3_free_dma_task_for_gsi();
fail_dma_task:
fail_init_hw:
	ipahal_destroy();
fail_ipahal:

	return result;
}

@@ -4573,7 +4651,7 @@ static int ipa3_manual_load_ipa_fws(void)

	IPADBG("Manual FW loading process initiated\n");

	result = request_firmware(&fw, IPA_FWS_PATH, ipa3_ctx->dev);
	result = request_firmware(&fw, IPA_FWS_PATH, ipa3_ctx->cdev.dev);
	if (result < 0) {
		IPAERR("request_firmware failed, error %d\n", result);
		return result;
@@ -4629,6 +4707,12 @@ static void ipa3_load_ipa_fw(struct work_struct *work)

	IPADBG("Entry\n");

	result = ipa3_attach_to_smmu();
	if (result) {
		IPAERR("IPA attach to smmu failed %d\n", result);
		return;
	}

	IPA_ACTIVE_CLIENTS_INC_SIMPLE();

	if (ipa3_is_msm_device() || (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5))
@@ -4644,7 +4728,7 @@ static void ipa3_load_ipa_fw(struct work_struct *work)
	}
	pr_info("IPA FW loaded successfully\n");

	result = ipa3_post_init(&ipa3_res, ipa3_ctx->dev);
	result = ipa3_post_init(&ipa3_res, ipa3_ctx->cdev.dev);
	if (result)
		IPAERR("IPA post init failed %d\n", result);
}
@@ -4867,12 +4951,13 @@ static int ipa3_alloc_pkt_init(void)
* Configure GSI registers (in GSI case)
*/
static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		struct device *ipa_dev)
		struct platform_device *ipa_pdev)
{
	int result = 0;
	int i;
	struct ipa3_rt_tbl_set *rset;
	struct ipa_active_client_logging_info log_info;
	struct cdev *cdev;

	IPADBG("IPA Driver initialization started\n");

@@ -4887,8 +4972,8 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	if (ipa3_ctx->logbuf == NULL)
		IPAERR("failed to create IPC log, continue...\n");

	ipa3_ctx->pdev = ipa_dev;
	ipa3_ctx->uc_pdev = ipa_dev;
	/* ipa3_ctx->pdev and ipa3_ctx->uc_pdev will be set in the smmu probes*/
	ipa3_ctx->master_pdev = ipa_pdev;
	ipa3_ctx->smmu_present = smmu_info.present;
	if (!ipa3_ctx->smmu_present) {
		for (i = 0; i < IPA_SMMU_CB_MAX; i++)
@@ -4917,6 +5002,10 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	ipa3_ctx->ipa3_active_clients_logging.log_rdy = false;
	ipa3_ctx->mhi_evid_limits[0] = resource_p->mhi_evid_limits[0];
	ipa3_ctx->mhi_evid_limits[1] = resource_p->mhi_evid_limits[1];

	WARN(ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL,
		"Non NORMAL IPA HW mode, is this emulation platform ?");

	if (resource_p->ipa_tz_unlock_reg) {
		ipa3_ctx->ipa_tz_unlock_reg_num =
			resource_p->ipa_tz_unlock_reg_num;
@@ -4961,18 +5050,22 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		goto fail_bind;
	}

	result = ipa3_init_mem_partition(master_dev->of_node);
	result = ipa3_init_mem_partition(ipa3_ctx->master_pdev->dev.of_node);
	if (result) {
		IPAERR(":ipa3_init_mem_partition failed!\n");
		result = -ENODEV;
		goto fail_init_mem_partition;
	}

	if (ipa3_bus_scale_table) {
		IPADBG("Use bus scaling info from device tree #usecases=%d\n",
			ipa3_bus_scale_table->num_usecases);
		ipa3_ctx->ctrl->msm_bus_data_ptr = ipa3_bus_scale_table;
	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL) {
		ipa3_ctx->ctrl->msm_bus_data_ptr =
			msm_bus_cl_get_pdata(ipa3_ctx->master_pdev);
		if (ipa3_ctx->ctrl->msm_bus_data_ptr == NULL) {
			IPAERR("failed to get bus scaling\n");
			goto fail_bus_reg;
		}
		IPADBG("Use bus scaling info from device tree #usecases=%d\n",
			ipa3_ctx->ctrl->msm_bus_data_ptr->num_usecases);

		/* get BUS handle */
		ipa3_ctx->ipa_bus_hdl =
@@ -4983,9 +5076,10 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
			result = -ENODEV;
			goto fail_bus_reg;
		}
	}

	/* get IPA clocks */
	result = ipa3_get_clks(master_dev);
	result = ipa3_get_clks(&ipa3_ctx->master_pdev->dev);
	if (result)
		goto fail_clk;

@@ -5013,55 +5107,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		goto fail_remap;
	}

	if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio,
		ipa3_ctx->pdev)) {
		IPAERR("fail to init ipahal\n");
		result = -EFAULT;
		goto fail_ipahal;
	}

	result = ipa3_init_hw();
	if (result) {
		IPAERR(":error initializing HW.\n");
		result = -ENODEV;
		goto fail_init_hw;
	}
	IPADBG("IPA HW initialization sequence completed");

	ipa3_ctx->ipa_num_pipes = ipa3_get_num_pipes();
	if (ipa3_ctx->ipa_num_pipes > IPA3_MAX_NUM_PIPES) {
		IPAERR("IPA has more pipes then supported! has %d, max %d\n",
			ipa3_ctx->ipa_num_pipes, IPA3_MAX_NUM_PIPES);
		result = -ENODEV;
		goto fail_init_hw;
	}

	ipa3_ctx->ctrl->ipa_sram_read_settings();
	IPADBG("SRAM, size: 0x%x, restricted bytes: 0x%x\n",
		ipa3_ctx->smem_sz, ipa3_ctx->smem_restricted_bytes);

	IPADBG("hdr_lcl=%u ip4_rt_hash=%u ip4_rt_nonhash=%u\n",
		ipa3_ctx->hdr_tbl_lcl, ipa3_ctx->ip4_rt_tbl_hash_lcl,
		ipa3_ctx->ip4_rt_tbl_nhash_lcl);

	IPADBG("ip6_rt_hash=%u ip6_rt_nonhash=%u\n",
		ipa3_ctx->ip6_rt_tbl_hash_lcl, ipa3_ctx->ip6_rt_tbl_nhash_lcl);

	IPADBG("ip4_flt_hash=%u ip4_flt_nonhash=%u\n",
		ipa3_ctx->ip4_flt_tbl_hash_lcl,
		ipa3_ctx->ip4_flt_tbl_nhash_lcl);

	IPADBG("ip6_flt_hash=%u ip6_flt_nonhash=%u\n",
		ipa3_ctx->ip6_flt_tbl_hash_lcl,
		ipa3_ctx->ip6_flt_tbl_nhash_lcl);

	if (ipa3_ctx->smem_reqd_sz > ipa3_ctx->smem_sz) {
		IPAERR("SW expect more core memory, needed %d, avail %d\n",
			ipa3_ctx->smem_reqd_sz, ipa3_ctx->smem_sz);
		result = -ENOMEM;
		goto fail_init_hw;
	}

	mutex_init(&ipa3_ctx->ipa3_active_clients.mutex);

	IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "PROXY_CLK_VOTE");
@@ -5160,13 +5205,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		goto fail_rx_pkt_wrapper_cache;
	}

	/* allocate memory for DMA_TASK workaround */
	result = ipa3_allocate_dma_task_for_gsi();
	if (result) {
		IPAERR("failed to allocate dma task\n");
		goto fail_dma_task;
	}

	/* init the various list heads */
	INIT_LIST_HEAD(&ipa3_ctx->hdr_tbl.head_hdr_entry_list);
	for (i = 0; i < IPA_HDR_BIN_MAX; i++) {
@@ -5210,29 +5248,23 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	spin_lock_init(&ipa3_ctx->wc_memb.ipa_tx_mul_spinlock);
	INIT_LIST_HEAD(&ipa3_ctx->wc_memb.wlan_comm_desc_list);

	ipa3_ctx->class = class_create(THIS_MODULE, DRV_NAME);
	ipa3_ctx->cdev.class = class_create(THIS_MODULE, DRV_NAME);

	result = alloc_chrdev_region(&ipa3_ctx->dev_num, 0, 1, DRV_NAME);
	result = alloc_chrdev_region(&ipa3_ctx->cdev.dev_num, 0, 1, DRV_NAME);
	if (result) {
		IPAERR("alloc_chrdev_region err.\n");
		result = -ENODEV;
		goto fail_alloc_chrdev_region;
	}

	ipa3_ctx->dev = device_create(ipa3_ctx->class, NULL, ipa3_ctx->dev_num,
			ipa3_ctx, DRV_NAME);
	if (IS_ERR(ipa3_ctx->dev)) {
	ipa3_ctx->cdev.dev = device_create(ipa3_ctx->cdev.class, NULL,
		 ipa3_ctx->cdev.dev_num, ipa3_ctx, DRV_NAME);
	if (IS_ERR(ipa3_ctx->cdev.dev)) {
		IPAERR(":device_create err.\n");
		result = -ENODEV;
		goto fail_device_create;
	}

	if (ipa3_nat_ipv6ct_init_devices()) {
		IPAERR("unable to init NAT and IPv6CT devices\n");
		result = -ENODEV;
		goto fail_nat_ipv6ct_init_dev;
	}

	/* Create a wakeup source. */
	wakeup_source_init(&ipa3_ctx->w_lock, "IPA_WS");
	spin_lock_init(&ipa3_ctx->wakelock_ref_cnt.spinlock);
@@ -5263,16 +5295,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		}
	}

	result = ipa3_alloc_pkt_init();
	if (result) {
		IPAERR("Failed to alloc pkt_init payload\n");
		result = -ENODEV;
		goto fail_allok_pkt_init;
	}

	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5)
		ipa3_enable_dcd();

	INIT_LIST_HEAD(&ipa3_ctx->ipa_ready_cb_list);

	init_completion(&ipa3_ctx->init_completion_obj);
@@ -5301,19 +5323,20 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		}
	}

	cdev_init(&ipa3_ctx->cdev, &ipa3_drv_fops);
	ipa3_ctx->cdev.owner = THIS_MODULE;
	ipa3_ctx->cdev.ops = &ipa3_drv_fops;  /* from LDD3 */
	cdev = &ipa3_ctx->cdev.cdev;
	cdev_init(cdev, &ipa3_drv_fops);
	cdev->owner = THIS_MODULE;
	cdev->ops = &ipa3_drv_fops;  /* from LDD3 */

	result = cdev_add(&ipa3_ctx->cdev, ipa3_ctx->dev_num, 1);
	result = cdev_add(cdev, ipa3_ctx->cdev.dev_num, 1);
	if (result) {
		IPAERR(":cdev_add err=%d\n", -result);
		result = -ENODEV;
		goto fail_cdev_add;
	}
	IPADBG("ipa cdev added successful. major:%d minor:%d\n",
			MAJOR(ipa3_ctx->dev_num),
			MINOR(ipa3_ctx->dev_num));
			MAJOR(ipa3_ctx->cdev.dev_num),
			MINOR(ipa3_ctx->cdev.dev_num));
	/*
	 * for IPA 4.0 offline charge is not needed and we need to prevent
	 * power collapse until IPA uC is loaded.
@@ -5328,7 +5351,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
fail_gsi_pre_fw_load_init:
	ipa3_dma_shutdown();
fail_ipa_dma_setup:
fail_allok_pkt_init:
	if (ipa3_ctx->use_ipa_pm)
		ipa_pm_destroy();
	else
@@ -5337,11 +5359,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	if (!ipa3_ctx->use_ipa_pm)
		ipa_rm_exit();
fail_ipa_rm_init:
	ipa3_nat_ipv6ct_destroy_devices();
fail_nat_ipv6ct_init_dev:
	device_destroy(ipa3_ctx->class, ipa3_ctx->dev_num);
	device_destroy(ipa3_ctx->cdev.class, ipa3_ctx->cdev.dev_num);
fail_device_create:
	unregister_chrdev_region(ipa3_ctx->dev_num, 1);
	unregister_chrdev_region(ipa3_ctx->cdev.dev_num, 1);
fail_alloc_chrdev_region:
	idr_destroy(&ipa3_ctx->ipa_idr);
	rset = &ipa3_ctx->reap_rt_tbl_set[IPA_IP_v6];
@@ -5350,8 +5370,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	idr_destroy(&rset->rule_ids);
	idr_destroy(&ipa3_ctx->rt_tbl_set[IPA_IP_v6].rule_ids);
	idr_destroy(&ipa3_ctx->rt_tbl_set[IPA_IP_v4].rule_ids);
	ipa3_free_dma_task_for_gsi();
fail_dma_task:
	kmem_cache_destroy(ipa3_ctx->rx_pkt_wrapper_cache);
fail_rx_pkt_wrapper_cache:
	kmem_cache_destroy(ipa3_ctx->tx_pkt_wrapper_cache);
@@ -5374,8 +5392,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
fail_create_transport_wq:
	destroy_workqueue(ipa3_ctx->power_mgmt_wq);
fail_init_hw:
	ipahal_destroy();
fail_ipahal:
	iounmap(ipa3_ctx->mmio);
fail_remap:
	ipa3_disable_clks();
@@ -5385,12 +5401,11 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		clk_put(ipa3_clk);
	ipa3_clk = NULL;
fail_clk:
	if (ipa3_ctx->ipa_bus_hdl)
		msm_bus_scale_unregister_client(ipa3_ctx->ipa_bus_hdl);
fail_bus_reg:
	if (ipa3_bus_scale_table) {
		msm_bus_cl_clear_pdata(ipa3_bus_scale_table);
		ipa3_bus_scale_table = NULL;
	}
	if (ipa3_ctx->ctrl->msm_bus_data_ptr)
		msm_bus_cl_clear_pdata(ipa3_ctx->ctrl->msm_bus_data_ptr);
fail_init_mem_partition:
fail_bind:
	kfree(ipa3_ctx->ctrl);
@@ -5777,7 +5792,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,

static int ipa_smmu_wlan_cb_probe(struct device *dev)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_wlan_smmu_ctx();
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
	int atomic_ctx = 1;
	int fast = 1;
	int bypass = 1;
@@ -5788,6 +5803,11 @@ static int ipa_smmu_wlan_cb_probe(struct device *dev)

	IPADBG("sub pdev=%p\n", dev);

	if (!smmu_info.present[IPA_SMMU_CB_WLAN]) {
		IPAERR("WLAN SMMU is disabled\n");
		return 0;
	}

	cb->dev = dev;
	cb->iommu = iommu_domain_alloc(dev->bus);
	if (!cb->iommu) {
@@ -5797,7 +5817,8 @@ static int ipa_smmu_wlan_cb_probe(struct device *dev)
	}
	cb->valid = true;

	if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass")) {
	if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass") ||
		ipa3_ctx->ipa_config_is_mhi) {
		smmu_info.s1_bypass_arr[IPA_SMMU_CB_WLAN] = true;
		ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_WLAN] = true;

@@ -5877,7 +5898,7 @@ static int ipa_smmu_wlan_cb_probe(struct device *dev)

static int ipa_smmu_uc_cb_probe(struct device *dev)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_uc_smmu_ctx();
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
	int atomic_ctx = 1;
	int bypass = 1;
	int fast = 1;
@@ -5886,6 +5907,11 @@ static int ipa_smmu_uc_cb_probe(struct device *dev)

	IPADBG("UC CB PROBE sub pdev=%p\n", dev);

	if (!smmu_info.present[IPA_SMMU_CB_UC]) {
		IPAERR("UC SMMU is disabled\n");
		return 0;
	}

	ret = of_property_read_u32_array(dev->of_node, "qcom,iova-mapping",
			iova_ap_mapping, 2);
	if (ret) {
@@ -5925,7 +5951,8 @@ static int ipa_smmu_uc_cb_probe(struct device *dev)

	IPADBG("UC CB PROBE sub pdev=%p set attribute\n", dev);

	if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass")) {
	if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass") ||
		ipa3_ctx->ipa_config_is_mhi) {
		smmu_info.s1_bypass_arr[IPA_SMMU_CB_UC] = true;
		ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_UC] = true;

@@ -5985,7 +6012,7 @@ static int ipa_smmu_uc_cb_probe(struct device *dev)

static int ipa_smmu_ap_cb_probe(struct device *dev)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx();
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
	int result;
	int atomic_ctx = 1;
	int fast = 1;
@@ -5999,6 +6026,11 @@ static int ipa_smmu_ap_cb_probe(struct device *dev)

	IPADBG("AP CB probe: sub pdev=%p\n", dev);

	if (!smmu_info.present[IPA_SMMU_CB_AP]) {
		IPAERR("AP SMMU is disabled");
		return 0;
	}

	result = of_property_read_u32_array(dev->of_node, "qcom,iova-mapping",
		iova_ap_mapping, 2);
	if (result) {
@@ -6036,7 +6068,7 @@ static int ipa_smmu_ap_cb_probe(struct device *dev)
	cb->valid = true;

	if (of_property_read_bool(dev->of_node,
		"qcom,smmu-s1-bypass")) {
		"qcom,smmu-s1-bypass") || ipa3_ctx->ipa_config_is_mhi) {
		smmu_info.s1_bypass_arr[IPA_SMMU_CB_AP] = true;
		if (iommu_domain_set_attr(cb->mapping->domain,
				DOMAIN_ATTR_S1_BYPASS,
@@ -6138,22 +6170,47 @@ static int ipa_smmu_ap_cb_probe(struct device *dev)
	}


	smmu_info.present = true;

	if (!ipa3_bus_scale_table)
		ipa3_bus_scale_table = msm_bus_cl_get_pdata(ipa3_pdev);
	smmu_info.present[IPA_SMMU_CB_AP] = true;
	ipa3_ctx->pdev = dev;

	/* Proceed to real initialization */
	result = ipa3_pre_init(&ipa3_res, dev);
	if (result) {
		IPAERR("ipa_init failed\n");
		arm_iommu_detach_device(cb->dev);
		arm_iommu_release_mapping(cb->mapping);
		cb->valid = false;
	return result;
}

	return result;
static int ipa_smmu_cb_probe(struct device *dev, enum ipa_smmu_cb_type cb_type)
{
	switch (cb_type) {
	case IPA_SMMU_CB_AP:
		return ipa_smmu_ap_cb_probe(dev);
	case IPA_SMMU_CB_WLAN:
		return ipa_smmu_wlan_cb_probe(dev);
	case IPA_SMMU_CB_UC:
		return ipa_smmu_uc_cb_probe(dev);
	case IPA_SMMU_CB_MAX:
		IPAERR("Invalid cb_type\n");
	}
	return 0;
}

static int ipa3_attach_to_smmu(void)
{
	struct ipa_smmu_cb_ctx *cb;
	int i, result;

	ipa3_ctx->pdev = &ipa3_ctx->master_pdev->dev;
	ipa3_ctx->uc_pdev = &ipa3_ctx->master_pdev->dev;

	if (smmu_info.arm_smmu) {
		IPADBG("smmu is enabled\n");
		for (i = 0; i < IPA_SMMU_CB_MAX; i++) {
			cb = ipa3_get_smmu_ctx(i);
			result = ipa_smmu_cb_probe(cb->dev, i);
			if (result)
				IPAERR("probe failed for cb %d\n", i);
		}
	} else {
		IPADBG("smmu is disabled\n");
	}
	return 0;
}

static irqreturn_t ipa3_smp2p_modem_clk_query_isr(int irq, void *ctxt)
@@ -6226,18 +6283,34 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p,
{
	int result;
	struct device *dev = &pdev_p->dev;
	struct ipa_smmu_cb_ctx *cb;

	IPADBG("IPA driver probing started\n");
	IPADBG("dev->of_node->name = %s\n", dev->of_node->name);

	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-ap-cb"))
		return ipa_smmu_ap_cb_probe(dev);
	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-ap-cb")) {
		cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
		cb->dev = dev;
		smmu_info.present[IPA_SMMU_CB_AP] = true;

	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-wlan-cb"))
		return ipa_smmu_wlan_cb_probe(dev);
		return 0;
	}

	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-uc-cb"))
		return ipa_smmu_uc_cb_probe(dev);
	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-wlan-cb")) {
		cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
		cb->dev = dev;
		smmu_info.present[IPA_SMMU_CB_WLAN] = true;

		return 0;
	}

	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-uc-cb")) {
		cb =  ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
		cb->dev = dev;
		smmu_info.present[IPA_SMMU_CB_UC] = true;

		return 0;
	}

	if (of_device_is_compatible(dev->of_node,
	    "qcom,smp2pgpio-map-ipa-1-in"))
@@ -6247,10 +6320,6 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p,
	    "qcom,smp2pgpio-map-ipa-1-out"))
		return ipa3_smp2p_probe(dev);

	master_dev = dev;
	if (!ipa3_pdev)
		ipa3_pdev = pdev_p;

	result = get_ipa_dts_configuration(pdev_p, &ipa3_res);
	if (result) {
		IPAERR("IPA dts parsing failed\n");
@@ -6292,16 +6361,14 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p,
				return -EOPNOTSUPP;
			}
		}
	}

		if (!ipa3_bus_scale_table)
			ipa3_bus_scale_table = msm_bus_cl_get_pdata(pdev_p);
	/* Proceed to real initialization */
		result = ipa3_pre_init(&ipa3_res, dev);
	result = ipa3_pre_init(&ipa3_res, pdev_p);
	if (result) {
		IPAERR("ipa3_init failed\n");
		return result;
	}
	}

	result = of_platform_populate(pdev_p->dev.of_node,
		pdrv_match, NULL, &pdev_p->dev);
@@ -6448,8 +6515,8 @@ int ipa3_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data)
int ipa3_iommu_map(struct iommu_domain *domain,
	unsigned long iova, phys_addr_t paddr, size_t size, int prot)
{
	struct ipa_smmu_cb_ctx *ap_cb = ipa3_get_smmu_ctx();
	struct ipa_smmu_cb_ctx *uc_cb = ipa3_get_uc_smmu_ctx();
	struct ipa_smmu_cb_ctx *ap_cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
	struct ipa_smmu_cb_ctx *uc_cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);

	IPADBG("domain =0x%p iova 0x%lx\n", domain, iova);
	IPADBG("paddr =0x%pa size 0x%x\n", &paddr, (u32)size);
+15 −8
Original line number Diff line number Diff line
@@ -1161,11 +1161,22 @@ enum ipa_smmu_cb_type {
};

/**
 * struct ipa3_context - IPA context
 * struct ipa3_char_device_context - IPA character device
 * @class: pointer to the struct class
 * @dev_num: device number
 * @dev: the dev_t of the device
 * @cdev: cdev of the device
 */
struct ipa3_char_device_context {
	struct class *class;
	dev_t dev_num;
	struct device *dev;
	struct cdev cdev;
};

/**
 * struct ipa3_context - IPA context
 * @cdev: cdev context
 * @ep: list of all end points
 * @skip_ep_cfg_shadow: state to update filter table correctly across
  power-save
@@ -1251,10 +1262,7 @@ enum ipa_smmu_cb_type {
 * IPA context - holds all relevant info about IPA driver and its state
 */
struct ipa3_context {
	struct class *class;
	dev_t dev_num;
	struct device *dev;
	struct cdev cdev;
	struct ipa3_char_device_context cdev;
	struct ipa3_ep_context ep[IPA3_MAX_NUM_PIPES];
	bool skip_ep_cfg_shadow[IPA3_MAX_NUM_PIPES];
	u32 ep_flt_bitmap;
@@ -1336,6 +1344,7 @@ struct ipa3_context {
	u32 ipa_bus_hdl;
	struct ipa3_controller *ctrl;
	struct idr ipa_idr;
	struct platform_device *master_pdev;
	struct device *pdev;
	struct device *uc_pdev;
	spinlock_t idr_lock;
@@ -2278,9 +2287,7 @@ int ipa_reset_flt_rt_stats(enum ipa_ip_type ip, bool filtering, u16 rule_id);
int ipa_reset_all_flt_rt_stats(enum ipa_ip_type ip, bool filtering);

u32 ipa3_get_num_pipes(void);
struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(void);
struct ipa_smmu_cb_ctx *ipa3_get_wlan_smmu_ctx(void);
struct ipa_smmu_cb_ctx *ipa3_get_uc_smmu_ctx(void);
struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(enum ipa_smmu_cb_type);
struct iommu_domain *ipa3_get_smmu_domain(void);
struct iommu_domain *ipa3_get_uc_smmu_domain(void);
struct iommu_domain *ipa3_get_wlan_smmu_domain(void);
+5 −5
Original line number Diff line number Diff line
@@ -495,7 +495,7 @@ int ipa3_wdi_init(void)
static int ipa_create_uc_smmu_mapping_pa(phys_addr_t pa, size_t len,
		bool device, unsigned long *iova)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_uc_smmu_ctx();
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
	unsigned long va = roundup(cb->next_addr, PAGE_SIZE);
	int prot = IOMMU_READ | IOMMU_WRITE;
	size_t true_len = roundup(len + pa - rounddown(pa, PAGE_SIZE),
@@ -524,7 +524,7 @@ static int ipa_create_uc_smmu_mapping_pa(phys_addr_t pa, size_t len,
static int ipa_create_uc_smmu_mapping_sgt(struct sg_table *sgt,
		unsigned long *iova)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_uc_smmu_ctx();
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
	unsigned long va = roundup(cb->next_addr, PAGE_SIZE);
	int prot = IOMMU_READ | IOMMU_WRITE;
	int ret;
@@ -573,7 +573,7 @@ static int ipa_create_uc_smmu_mapping_sgt(struct sg_table *sgt,

static void ipa_release_uc_smmu_mappings(enum ipa_client_type client)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_uc_smmu_ctx();
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
	int i;
	int j;
	int start;
@@ -1810,7 +1810,7 @@ static void ipa3_uc_wdi_loaded_handler(void)

int ipa3_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_wlan_smmu_ctx();
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
	int i;
	int ret = 0;
	int prot = IOMMU_READ | IOMMU_WRITE;
@@ -1846,7 +1846,7 @@ int ipa3_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info)

int ipa3_release_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info)
{
	struct ipa_smmu_cb_ctx *cb = ipa3_get_wlan_smmu_ctx();
	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
	int i;
	int ret = 0;

+0 −48
Original line number Diff line number Diff line
@@ -1477,53 +1477,6 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
			{ 31, 31, 8, 8, IPA_EE_AP } },
};

static struct msm_bus_vectors ipa_init_vectors_v3_0[]  = {
	{
		.src = MSM_BUS_MASTER_IPA,
		.dst = MSM_BUS_SLAVE_EBI_CH0,
		.ab = 0,
		.ib = 0,
	},
	{
		.src = MSM_BUS_MASTER_IPA,
		.dst = MSM_BUS_SLAVE_OCIMEM,
		.ab = 0,
		.ib = 0,
	},
};

static struct msm_bus_vectors ipa_nominal_perf_vectors_v3_0[]  = {
	{
		.src = MSM_BUS_MASTER_IPA,
		.dst = MSM_BUS_SLAVE_EBI_CH0,
		.ab = 100000000,
		.ib = 1300000000,
	},
	{
		.src = MSM_BUS_MASTER_IPA,
		.dst = MSM_BUS_SLAVE_OCIMEM,
		.ab = 100000000,
		.ib = 1300000000,
	},
};

static struct msm_bus_paths ipa_usecases_v3_0[]  = {
	{
		.num_paths = ARRAY_SIZE(ipa_init_vectors_v3_0),
		.vectors = ipa_init_vectors_v3_0,
	},
	{
		.num_paths = ARRAY_SIZE(ipa_nominal_perf_vectors_v3_0),
		.vectors = ipa_nominal_perf_vectors_v3_0,
	},
};

static struct msm_bus_scale_pdata ipa_bus_client_pdata_v3_0 = {
	.usecase = ipa_usecases_v3_0,
	.num_usecases = ARRAY_SIZE(ipa_usecases_v3_0),
	.name = "ipa",
};

/**
 * ipa3_get_clients_from_rm_resource() - get IPA clients which are related to an
 * IPA_RM resource
@@ -3786,7 +3739,6 @@ int ipa3_controller_static_bind(struct ipa3_controller *ctrl,
	ctrl->ipa3_commit_hdr = __ipa_commit_hdr_v3_0;
	ctrl->ipa3_enable_clks = _ipa_enable_clks_v3_0;
	ctrl->ipa3_disable_clks = _ipa_disable_clks_v3_0;
	ctrl->msm_bus_data_ptr = &ipa_bus_client_pdata_v3_0;
	ctrl->clock_scaling_bw_threshold_svs =
		IPA_V3_0_BW_THRESHOLD_SVS_MBPS;
	ctrl->clock_scaling_bw_threshold_nominal =