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

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

Merge "icnss: Setup hypervisor permissions for MSA0"

parents e0addbd9 037f52de
Loading
Loading
Loading
Loading
+110 −2
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/icnss.h>
#include <soc/qcom/msm_qmi_interface.h>
#include <soc/qcom/secure_buffer.h>

#include "wlan_firmware_service_v01.h"

@@ -533,6 +534,105 @@ int icnss_power_off(struct device *dev)
}
EXPORT_SYMBOL(icnss_power_off);

int icnss_map_msa_permissions(struct icnss_data *priv, u32 index)
{
	int ret = 0;
	phys_addr_t addr;
	u32 size;
	u32 source_vmlist[1] = {VMID_HLOS};
	int dest_vmids[3] = {VMID_MSS_MSA, VMID_WLAN, 0};
	int dest_perms[3] = {PERM_READ|PERM_WRITE,
			     PERM_READ|PERM_WRITE,
			     PERM_READ|PERM_WRITE};
	int source_nelems = sizeof(source_vmlist)/sizeof(u32);
	int dest_nelems = 0;

	addr = priv->icnss_mem_region[index].reg_addr;
	size = priv->icnss_mem_region[index].size;

	if (!priv->icnss_mem_region[index].secure_flag) {
		dest_vmids[2] = VMID_WLAN_CE;
		dest_nelems = 3;
	} else {
		dest_vmids[2] = 0;
		dest_nelems = 2;
	}
	ret = hyp_assign_phys(addr, size, source_vmlist, source_nelems,
			      dest_vmids, dest_perms, dest_nelems);
	if (ret) {
		icnss_pr_err("region %u hyp_assign_phys failed IPA=%pa size=%u err=%d\n",
			     index, &addr, size, ret);
		goto out;
	}
	icnss_pr_dbg("hypervisor map for region %u: source=%x, dest_nelems=%d, dest[0]=%x, dest[1]=%x, dest[2]=%x\n",
		     index, source_vmlist[0], dest_nelems,
		     dest_vmids[0], dest_vmids[1], dest_vmids[2]);
out:
	return ret;

}

int icnss_unmap_msa_permissions(struct icnss_data *priv, u32 index)
{
	int ret = 0;
	phys_addr_t addr;
	u32 size;
	u32 dest_vmids[1] = {VMID_HLOS};
	int source_vmlist[3] = {VMID_MSS_MSA, VMID_WLAN, 0};
	int dest_perms[1] = {PERM_READ|PERM_WRITE};
	int source_nelems = 0;
	int dest_nelems = sizeof(dest_vmids)/sizeof(u32);

	addr = priv->icnss_mem_region[index].reg_addr;
	size = priv->icnss_mem_region[index].size;
	if (!priv->icnss_mem_region[index].secure_flag) {
		source_vmlist[2] = VMID_WLAN_CE;
		source_nelems = 3;
	} else {
		source_vmlist[2] = 0;
		source_nelems = 2;
	}

	ret = hyp_assign_phys(addr, size, source_vmlist, source_nelems,
			      dest_vmids, dest_perms, dest_nelems);
	if (ret) {
		icnss_pr_err("region %u hyp_assign_phys failed IPA=%pa size=%u err=%d\n",
			     index, &addr, size, ret);
		goto out;
	}
	icnss_pr_dbg("hypervisor unmap for region %u, source_nelems=%d, source[0]=%x, source[1]=%x, source[2]=%x, dest=%x\n",
		     index, source_nelems,
		     source_vmlist[0], source_vmlist[1], source_vmlist[2],
		     dest_vmids[0]);
out:
	return ret;
}

static int icnss_setup_msa_permissions(struct icnss_data *priv)
{
	int ret = 0;

	ret = icnss_map_msa_permissions(priv, 0);
	if (ret)
		return ret;

	ret = icnss_map_msa_permissions(priv, 1);
	if (ret)
		goto err_map_msa;

	return ret;

err_map_msa:
	icnss_unmap_msa_permissions(priv, 0);
	return ret;
}

static void icnss_remove_msa_permissions(struct icnss_data *priv)
{
	icnss_unmap_msa_permissions(priv, 0);
	icnss_unmap_msa_permissions(priv, 1);
}

static int wlfw_msa_mem_info_send_sync_msg(void)
{
	int ret = 0;
@@ -1049,19 +1149,27 @@ static int icnss_driver_event_server_arrive(void *data)
		icnss_pr_err("Failed to send MSA info: %d\n", ret);
		goto err_power_on;
	}
	ret = icnss_setup_msa_permissions(penv);
	if (ret < 0) {
		icnss_pr_err("Failed to setup msa permissions: %d\n",
			     ret);
		goto err_power_on;
	}
	ret = wlfw_msa_ready_send_sync_msg();
	if (ret < 0) {
		icnss_pr_err("Failed to send MSA ready : %d\n", ret);
		goto err_power_on;
		goto err_setup_msa;
	}

	ret = wlfw_cap_send_sync_msg();
	if (ret < 0) {
		icnss_pr_err("Failed to get capability: %d\n", ret);
		goto err_power_on;
		goto err_setup_msa;
	}
	return ret;

err_setup_msa:
	icnss_remove_msa_permissions(penv);
err_power_on:
	icnss_hw_power_off(penv);
fail: