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

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

Merge "icnss: Add hypervisor call for legacy platform"

parents 80947559 7340814d
Loading
Loading
Loading
Loading
+158 −4
Original line number Original line Diff line number Diff line
@@ -79,6 +79,40 @@ void *icnss_ipc_log_long_context;
#define ICNSS_EVENT_UNINTERRUPTIBLE		BIT(1)
#define ICNSS_EVENT_UNINTERRUPTIBLE		BIT(1)
#define ICNSS_EVENT_SYNC_UNINTERRUPTIBLE	(ICNSS_EVENT_UNINTERRUPTIBLE | \
#define ICNSS_EVENT_SYNC_UNINTERRUPTIBLE	(ICNSS_EVENT_UNINTERRUPTIBLE | \
						 ICNSS_EVENT_SYNC)
						 ICNSS_EVENT_SYNC)

struct icnss_msa_perm_list_t msa_perm_secure_list[ICNSS_MSA_PERM_MAX] = {
	[ICNSS_MSA_PERM_HLOS_ALL] = {
		.vmids = {VMID_HLOS},
		.perms = {PERM_READ | PERM_WRITE | PERM_EXEC},
		.nelems = 1,
	},

	[ICNSS_MSA_PERM_WLAN_HW_RW] = {
		.vmids = {VMID_MSS_MSA, VMID_WLAN},
		.perms = {PERM_READ | PERM_WRITE,
			PERM_READ | PERM_WRITE},
		.nelems = 2,
	},

};

struct icnss_msa_perm_list_t msa_perm_list[ICNSS_MSA_PERM_MAX] = {
	[ICNSS_MSA_PERM_HLOS_ALL] = {
		.vmids = {VMID_HLOS},
		.perms = {PERM_READ | PERM_WRITE | PERM_EXEC},
		.nelems = 1,
	},

	[ICNSS_MSA_PERM_WLAN_HW_RW] = {
		.vmids = {VMID_MSS_MSA, VMID_WLAN, VMID_WLAN_CE},
		.perms = {PERM_READ | PERM_WRITE,
			PERM_READ | PERM_WRITE,
			PERM_READ | PERM_WRITE},
		.nelems = 3,
	},

};

static struct icnss_vreg_info icnss_vreg_info[] = {
static struct icnss_vreg_info icnss_vreg_info[] = {
	{NULL, "vdd-cx-mx", 752000, 752000, 0, 0, false},
	{NULL, "vdd-cx-mx", 752000, 752000, 0, 0, false},
	{NULL, "vdd-1.8-xo", 1800000, 1800000, 0, 0, false},
	{NULL, "vdd-1.8-xo", 1800000, 1800000, 0, 0, false},
@@ -121,6 +155,94 @@ static ssize_t icnss_sysfs_store(struct kobject *kobj,
static struct kobj_attribute icnss_sysfs_attribute =
static struct kobj_attribute icnss_sysfs_attribute =
__ATTR(shutdown, 0660, NULL, icnss_sysfs_store);
__ATTR(shutdown, 0660, NULL, icnss_sysfs_store);


static int icnss_assign_msa_perm(struct icnss_mem_region_info
				 *mem_region, enum icnss_msa_perm new_perm)
{
	int ret = 0;
	phys_addr_t addr;
	u32 size;
	u32 i = 0;
	u32 source_vmids[ICNSS_MAX_VMIDS] = {0};
	u32 source_nelems;
	u32 dest_vmids[ICNSS_MAX_VMIDS] = {0};
	u32 dest_perms[ICNSS_MAX_VMIDS] = {0};
	u32 dest_nelems;
	enum icnss_msa_perm cur_perm = mem_region->perm;
	struct icnss_msa_perm_list_t *new_perm_list, *old_perm_list;

	if (penv && !penv->is_hyp_enabled) {
		icnss_pr_err("hyperviser disabled");
		return 0;
	}

	addr = mem_region->reg_addr;
	size = mem_region->size;

	if (mem_region->secure_flag) {
		new_perm_list = &msa_perm_secure_list[new_perm];
		old_perm_list = &msa_perm_secure_list[cur_perm];
	} else {
		new_perm_list = &msa_perm_list[new_perm];
		old_perm_list = &msa_perm_list[cur_perm];
	}

	source_nelems = old_perm_list->nelems;
	dest_nelems = new_perm_list->nelems;

	for (i = 0; i < source_nelems; ++i)
		source_vmids[i] = old_perm_list->vmids[i];

	for (i = 0; i < dest_nelems; ++i) {
		dest_vmids[i] = new_perm_list->vmids[i];
		dest_perms[i] = new_perm_list->perms[i];
	}

	ret = hyp_assign_phys(addr, size, source_vmids, source_nelems,
			      dest_vmids, dest_perms, dest_nelems);
	if (ret) {
		icnss_pr_err("Hyperviser map failed for PA=%pa size=%u err=%d\n",
			     &addr, size, ret);
		goto out;
	}

	icnss_pr_dbg("Hypervisor map for source_nelems=%d, source[0]=%x, source[1]=%x, source[2]=%x, source[3]=%x, dest_nelems=%d, dest[0]=%x, dest[1]=%x, dest[2]=%x, dest[3]=%x\n",
		     source_nelems, source_vmids[0], source_vmids[1],
		     source_vmids[2], source_vmids[3], dest_nelems,
		     dest_vmids[0], dest_vmids[1], dest_vmids[2],
		     dest_vmids[3]);
out:
	return ret;
}

static int icnss_assign_msa_perm_all(struct icnss_priv *priv,
				     enum icnss_msa_perm new_perm)
{
	int ret;
	int i;
	enum icnss_msa_perm old_perm;

	if (priv->nr_mem_region > WLFW_MAX_NUM_MEMORY_REGIONS) {
		icnss_pr_err("Invalid memory region len %d\n",
			     priv->nr_mem_region);
		return -EINVAL;
	}

	for (i = 0; i < priv->nr_mem_region; i++) {
		old_perm = priv->mem_region[i].perm;
		ret = icnss_assign_msa_perm(&priv->mem_region[i], new_perm);
		if (ret)
			goto err_unmap;
		priv->mem_region[i].perm = new_perm;
	}
	return 0;

err_unmap:
	for (i--; i >= 0; i--)
		icnss_assign_msa_perm(&priv->mem_region[i], old_perm);

	return ret;
}

static void icnss_pm_stay_awake(struct icnss_priv *priv)
static void icnss_pm_stay_awake(struct icnss_priv *priv)
{
{
	if (atomic_inc_return(&priv->pm_count) != 1)
	if (atomic_inc_return(&priv->pm_count) != 1)
@@ -885,16 +1007,24 @@ static int icnss_driver_event_server_arrive(void *data)
		goto err_power_on;
		goto err_power_on;
	}
	}


	if (!test_bit(ICNSS_MSA0_ASSIGNED, &penv->state)) {
		ret = icnss_assign_msa_perm_all(penv,
						ICNSS_MSA_PERM_WLAN_HW_RW);
		if (ret < 0)
			goto err_power_on;
		set_bit(ICNSS_MSA0_ASSIGNED, &penv->state);
	}

	ret = wlfw_msa_ready_send_sync_msg(penv);
	ret = wlfw_msa_ready_send_sync_msg(penv);
	if (ret < 0) {
	if (ret < 0) {
		ignore_assert = true;
		ignore_assert = true;
		goto err_power_on;
		goto err_setup_msa;
	}
	}


	ret = wlfw_cap_send_sync_msg(penv);
	ret = wlfw_cap_send_sync_msg(penv);
	if (ret < 0) {
	if (ret < 0) {
		ignore_assert = true;
		ignore_assert = true;
		goto err_power_on;
		goto err_setup_msa;
	}
	}


	wlfw_dynamic_feature_mask_send_sync_msg(penv,
	wlfw_dynamic_feature_mask_send_sync_msg(penv,
@@ -911,6 +1041,9 @@ static int icnss_driver_event_server_arrive(void *data)


	return ret;
	return ret;


err_setup_msa:
	icnss_assign_msa_perm_all(penv, ICNSS_MSA_PERM_HLOS_ALL);
	clear_bit(ICNSS_MSA0_ASSIGNED, &penv->state);
err_power_on:
err_power_on:
	icnss_hw_power_off(penv);
	icnss_hw_power_off(penv);
clear_server:
clear_server:
@@ -1455,13 +1588,23 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
	struct icnss_priv *priv = container_of(nb, struct icnss_priv,
	struct icnss_priv *priv = container_of(nb, struct icnss_priv,
					       modem_ssr_nb);
					       modem_ssr_nb);
	struct icnss_uevent_fw_down_data fw_down_data = {0};
	struct icnss_uevent_fw_down_data fw_down_data = {0};
	int ret;


	icnss_pr_vdbg("Modem-Notify: event %lu\n", code);
	icnss_pr_vdbg("Modem-Notify: event %lu\n", code);


	if (code == SUBSYS_AFTER_SHUTDOWN &&
	if (code == SUBSYS_AFTER_SHUTDOWN &&
	    notif->crashed == CRASH_STATUS_ERR_FATAL) {
	    notif->crashed == CRASH_STATUS_ERR_FATAL) {
		ret = icnss_assign_msa_perm_all(priv,
						ICNSS_MSA_PERM_HLOS_ALL);
		if (!ret) {
			icnss_pr_info("Collecting msa0 segment dump\n");
			icnss_pr_info("Collecting msa0 segment dump\n");
			icnss_msa0_ramdump(priv);
			icnss_msa0_ramdump(priv);
			icnss_assign_msa_perm_all(priv,
						  ICNSS_MSA_PERM_WLAN_HW_RW);
		} else {
			icnss_pr_err("Not able to Collect msa0 segment dump, Apps permissions not assigned %d\n",
				     ret);
		}
		goto out;
		goto out;
	}
	}


@@ -2777,6 +2920,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
		case ICNSS_PD_RESTART:
		case ICNSS_PD_RESTART:
			seq_puts(s, "PD RESTART");
			seq_puts(s, "PD RESTART");
			continue;
			continue;
		case ICNSS_MSA0_ASSIGNED:
			seq_puts(s, "MSA0 ASSIGNED");
			continue;
		case ICNSS_WLFW_EXISTS:
		case ICNSS_WLFW_EXISTS:
			seq_puts(s, "WLAN FW EXISTS");
			seq_puts(s, "WLAN FW EXISTS");
			continue;
			continue;
@@ -3344,6 +3490,11 @@ static int icnss_resource_parse(struct icnss_priv *priv)
			goto out;
			goto out;
	}
	}


	if (of_property_read_bool(pdev->dev.of_node, "qcom,hyp_enabled"))
		priv->is_hyp_enabled = true;

	icnss_pr_dbg("Hypervisor enabled = %d\n", priv->is_hyp_enabled);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "membase");
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "membase");
	if (!res) {
	if (!res) {
		icnss_pr_err("Memory base not found in DT\n");
		icnss_pr_err("Memory base not found in DT\n");
@@ -3593,6 +3744,9 @@ static int icnss_remove(struct platform_device *pdev)


	icnss_hw_power_off(penv);
	icnss_hw_power_off(penv);


	icnss_assign_msa_perm_all(penv, ICNSS_MSA_PERM_HLOS_ALL);
	clear_bit(ICNSS_MSA0_ASSIGNED, &penv->state);

	dev_set_drvdata(&pdev->dev, NULL);
	dev_set_drvdata(&pdev->dev, NULL);


	return 0;
	return 0;
+17 −0
Original line number Original line Diff line number Diff line
@@ -148,6 +148,7 @@ enum icnss_driver_state {
	ICNSS_SSR_REGISTERED,
	ICNSS_SSR_REGISTERED,
	ICNSS_PDR_REGISTERED,
	ICNSS_PDR_REGISTERED,
	ICNSS_PD_RESTART,
	ICNSS_PD_RESTART,
	ICNSS_MSA0_ASSIGNED,
	ICNSS_WLFW_EXISTS,
	ICNSS_WLFW_EXISTS,
	ICNSS_SHUTDOWN_DONE,
	ICNSS_SHUTDOWN_DONE,
	ICNSS_HOST_TRIGGERED_PDR,
	ICNSS_HOST_TRIGGERED_PDR,
@@ -276,10 +277,25 @@ struct wlfw_fw_version_info {
	char fw_build_timestamp[WLFW_MAX_TIMESTAMP_LEN + 1];
	char fw_build_timestamp[WLFW_MAX_TIMESTAMP_LEN + 1];
};
};


enum icnss_msa_perm {
	ICNSS_MSA_PERM_HLOS_ALL = 0,
	ICNSS_MSA_PERM_WLAN_HW_RW = 1,
	ICNSS_MSA_PERM_MAX,
};

#define ICNSS_MAX_VMIDS     4

struct icnss_mem_region_info {
struct icnss_mem_region_info {
	uint64_t reg_addr;
	uint64_t reg_addr;
	uint32_t size;
	uint32_t size;
	uint8_t secure_flag;
	uint8_t secure_flag;
	enum icnss_msa_perm perm;
};

struct icnss_msa_perm_list_t {
	int vmids[ICNSS_MAX_VMIDS];
	int perms[ICNSS_MAX_VMIDS];
	int nelems;
};
};


struct icnss_priv {
struct icnss_priv {
@@ -356,6 +372,7 @@ struct icnss_priv {
	void __iomem *hang_event_data_va;
	void __iomem *hang_event_data_va;
	uint16_t hang_event_data_len;
	uint16_t hang_event_data_len;
	void *hang_event_data;
	void *hang_event_data;
	bool is_hyp_enabled;
};
};


struct icnss_reg_info {
struct icnss_reg_info {