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

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

Merge "net: qrtr: haven: Read peer name from device tree"

parents 4f34190e 026bc864
Loading
Loading
Loading
Loading
+9 −1
Original line number Original line Diff line number Diff line
@@ -3,6 +3,7 @@
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 */
 */


#include <linux/completion.h>
#include <linux/list.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/module.h>
@@ -31,6 +32,7 @@ static struct kobj_type guestvm_kobj_type = {


struct guestvm_loader_private {
struct guestvm_loader_private {
	struct notifier_block guestvm_nb;
	struct notifier_block guestvm_nb;
	struct completion vm_start;
	struct kobject vm_loader_kobj;
	struct kobject vm_loader_kobj;
	struct device *dev;
	struct device *dev;
	char vm_name[MAX_LEN];
	char vm_name[MAX_LEN];
@@ -82,6 +84,7 @@ static int guestvm_loader_nb_handler(struct notifier_block *this,
				vm_status_payload->vmid, ret);
				vm_status_payload->vmid, ret);
			return NOTIFY_DONE;
			return NOTIFY_DONE;
		}
		}
		complete_all(&priv->vm_start);
		break;
		break;
	case HH_RM_VM_STATUS_RUNNING:
	case HH_RM_VM_STATUS_RUNNING:
		break;
		break;
@@ -129,6 +132,8 @@ static ssize_t guestvm_loader_start(struct kobject *kobj,
			priv->vm_loaded = NULL;
			priv->vm_loaded = NULL;
			return ret;
			return ret;
		}
		}
		if (wait_for_completion_interruptible(&priv->vm_start))
			dev_err(priv->dev, "VM start completion interrupted\n");


		priv->vm_status = HH_RM_VM_STATUS_RUNNING;
		priv->vm_status = HH_RM_VM_STATUS_RUNNING;
		ret = hh_rm_vm_start(priv->vmid);
		ret = hh_rm_vm_start(priv->vmid);
@@ -184,6 +189,7 @@ static int guestvm_loader_probe(struct platform_device *pdev)
		goto error_return;
		goto error_return;
	}
	}


	init_completion(&priv->vm_start);
	priv->guestvm_nb.notifier_call = guestvm_loader_nb_handler;
	priv->guestvm_nb.notifier_call = guestvm_loader_nb_handler;
	ret = hh_rm_register_notifier(&priv->guestvm_nb);
	ret = hh_rm_register_notifier(&priv->guestvm_nb);
	if (ret)
	if (ret)
@@ -207,8 +213,10 @@ static int guestvm_loader_remove(struct platform_device *pdev)
{
{
	struct guestvm_loader_private *priv = platform_get_drvdata(pdev);
	struct guestvm_loader_private *priv = platform_get_drvdata(pdev);


	if (priv->vm_loaded)
	if (priv->vm_loaded) {
		subsystem_put(priv->vm_loaded);
		subsystem_put(priv->vm_loaded);
		init_completion(&priv->vm_start);
	}


	if (kobject_name(&priv->vm_loader_kobj) != NULL) {
	if (kobject_name(&priv->vm_loader_kobj) != NULL) {
		kobject_del(&priv->vm_loader_kobj);
		kobject_del(&priv->vm_loader_kobj);
+132 −9
Original line number Original line Diff line number Diff line
@@ -19,7 +19,9 @@
#include <linux/kthread.h>
#include <linux/kthread.h>
#include <linux/neuron.h>
#include <linux/neuron.h>
#include <asm-generic/barrier.h>
#include <asm-generic/barrier.h>
#include <linux/haven/hh_rm_drv.h>
#include <linux/haven/hh_dbl.h>
#include <linux/haven/hh_dbl.h>
#include <soc/qcom/secure_buffer.h>
#include "ch_mq_shmem_common.h"
#include "ch_mq_shmem_common.h"


#define CHANNEL_VERSION NEURON_SHMEM_CHANNEL_V1
#define CHANNEL_VERSION NEURON_SHMEM_CHANNEL_V1
@@ -294,6 +296,113 @@ static int channel_sync_thread(void *data)
	return 0;
	return 0;
}
}


static int channel_hh_share_mem(struct neuron_mq_data_priv *priv,
				hh_vmid_t self, hh_vmid_t peer)
{
	u32 src_vmlist[1] = {self};
	int dst_vmlist[2] = {self, peer};
	int dst_perms[2] = {PERM_READ | PERM_WRITE, PERM_READ | PERM_WRITE};
	struct hh_acl_desc *acl;
	struct hh_sgl_desc *sgl;
	int ret;

	ret = hyp_assign_phys(priv->buffer.start, resource_size(&priv->buffer),
			      src_vmlist, 1,
			      dst_vmlist, dst_perms, 2);
	if (ret) {
		pr_err("hyp_assign_phys failed addr=%x size=%u err=%d\n",
		       priv->buffer.start, resource_size(&priv->buffer), ret);
		return ret;
	}

	acl = kzalloc(offsetof(struct hh_acl_desc, acl_entries[2]), GFP_KERNEL);
	if (!acl)
		return -ENOMEM;
	sgl = kzalloc(offsetof(struct hh_sgl_desc, sgl_entries[1]), GFP_KERNEL);
	if (!sgl) {
		kfree(acl);
		return -ENOMEM;
	}

	acl->n_acl_entries = 2;
	acl->acl_entries[0].vmid = (u16)self;
	acl->acl_entries[0].perms = HH_RM_ACL_R | HH_RM_ACL_W;
	acl->acl_entries[1].vmid = (u16)peer;
	acl->acl_entries[1].perms = HH_RM_ACL_R | HH_RM_ACL_W;

	sgl->n_sgl_entries = 1;
	sgl->sgl_entries[0].ipa_base = priv->buffer.start;
	sgl->sgl_entries[0].size = resource_size(&priv->buffer);
	ret = hh_rm_mem_qcom_lookup_sgl(HH_RM_MEM_TYPE_NORMAL,
					priv->haven_label,
					acl, sgl, NULL,
					&priv->shm_memparcel);
	kfree(acl);
	kfree(sgl);

	return ret;
}

static int channel_hh_rm_cb(struct notifier_block *nb, unsigned long cmd,
			    void *data)
{
	struct hh_rm_notif_vm_status_payload *vm_status_payload;
	struct neuron_mq_data_priv *priv;
	hh_vmid_t peer_vmid;
	hh_vmid_t self_vmid;

	priv = container_of(nb, struct neuron_mq_data_priv, rm_nb);

	if (cmd != HH_RM_NOTIF_VM_STATUS)
		return NOTIFY_DONE;

	vm_status_payload = data;
	if (vm_status_payload->vm_status != HH_RM_VM_STATUS_READY)
		return NOTIFY_DONE;
	if (hh_rm_get_vmid(priv->peer_name, &peer_vmid))
		return NOTIFY_DONE;
	if (hh_rm_get_vmid(HH_PRIMARY_VM, &self_vmid))
		return NOTIFY_DONE;
	if (peer_vmid != vm_status_payload->vmid)
		return NOTIFY_DONE;

	if (channel_hh_share_mem(priv, self_vmid, peer_vmid))
		pr_err("%s: failed to share memory\n", __func__);

	return NOTIFY_DONE;
}

static struct device_node *
channel_hh_svm_of_parse(struct neuron_mq_data_priv *priv, struct device *dev)
{
	const char *compat = "qcom,neuron-channel-haven-shmem-gen";
	struct device_node *np = NULL;
	struct device_node *shm_np;
	u32 label;
	int ret;

	while ((np = of_find_compatible_node(np, NULL, compat))) {
		ret = of_property_read_u32(np, "qcom,label", &label);
		if (ret) {
			of_node_put(np);
			continue;
		}
		if (label == priv->haven_label)
			break;

		of_node_put(np);
	}
	if (!np)
		return NULL;

	shm_np = of_parse_phandle(np, "memory-region", 0);
	if (!shm_np)
		dev_err(dev, "cant parse svm shared mem node!\n");

	of_node_put(np);
	return shm_np;
}

static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
				 struct device *dev)
				 struct device *dev)
{
{
@@ -304,9 +413,12 @@ static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,


	np = of_parse_phandle(dev->of_node, "shared-buffer", 0);
	np = of_parse_phandle(dev->of_node, "shared-buffer", 0);
	if (!np) {
	if (!np) {
		dev_err(dev, "shared-buffer node missing!\n");
		np = channel_hh_svm_of_parse(priv, dev);
		if (!np) {
			dev_err(dev, "cant parse shared mem node!\n");
			return -EINVAL;
			return -EINVAL;
		}
		}
	}


	ret = of_address_to_resource(np, 0, &priv->buffer);
	ret = of_address_to_resource(np, 0, &priv->buffer);
	of_node_put(np);
	of_node_put(np);
@@ -335,10 +447,20 @@ static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
		return -ENXIO;
		return -ENXIO;
	}
	}


	if (of_property_read_bool(dev->of_node, "qcom,primary"))
	if (of_property_read_bool(dev->of_node, "qcom,primary")) {
		memset(priv->base, 0,
		memset(priv->base, 0,
		       sizeof(struct neuron_shmem_channel_header));
		       sizeof(struct neuron_shmem_channel_header));


		ret = of_property_read_u32(dev->of_node, "peer-name",
					   &priv->peer_name);
		if (ret)
			priv->peer_name = HH_SELF_VM;

		priv->rm_nb.notifier_call = channel_hh_rm_cb;
		priv->rm_nb.priority = INT_MAX;
		hh_rm_register_notifier(&priv->rm_nb);
	}

	return 0;
	return 0;
}
}


@@ -358,19 +480,20 @@ static int channel_hh_probe(struct neuron_channel *cdev)
		return -ENOMEM;
		return -ENOMEM;
	priv->dev = cdev;
	priv->dev = cdev;


	ret = channel_hh_map_memory(priv, dev);
	ret = of_property_read_u32(node, "haven-label", &priv->haven_label);
	if (ret) {
	if (ret) {
		dev_err(dev, "failed to map memory %d\n", ret);
		dev_err(dev, "failed to read label info %d\n", ret);
		return ret;
		return ret;
	}
	}


	/* Get outgoing haven doorbell information */
	ret = channel_hh_map_memory(priv, dev);
	ret = of_property_read_u32(node, "haven-label", &dbl_label);
	if (ret) {
	if (ret) {
		dev_err(dev, "failed to read label info %d\n", ret);
		dev_err(dev, "failed to map memory %d\n", ret);
		goto fail_tx_dbl;
		return ret;
	}
	}


	/* Get outgoing haven doorbell information */
	dbl_label = priv->haven_label;
	priv->tx_dbl = hh_dbl_tx_register(dbl_label);
	priv->tx_dbl = hh_dbl_tx_register(dbl_label);
	if (IS_ERR_OR_NULL(priv->tx_dbl)) {
	if (IS_ERR_OR_NULL(priv->tx_dbl)) {
		ret = PTR_ERR(priv->tx_dbl);
		ret = PTR_ERR(priv->tx_dbl);
+130 −9
Original line number Original line Diff line number Diff line
@@ -19,7 +19,9 @@
#include <linux/kthread.h>
#include <linux/kthread.h>
#include <linux/neuron.h>
#include <linux/neuron.h>
#include <asm-generic/barrier.h>
#include <asm-generic/barrier.h>
#include <linux/haven/hh_rm_drv.h>
#include <linux/haven/hh_dbl.h>
#include <linux/haven/hh_dbl.h>
#include <soc/qcom/secure_buffer.h>
#include "ch_mq_shmem_common.h"
#include "ch_mq_shmem_common.h"


#define CHANNEL_VERSION NEURON_SHMEM_CHANNEL_V1
#define CHANNEL_VERSION NEURON_SHMEM_CHANNEL_V1
@@ -279,6 +281,111 @@ static int channel_sync_thread(void *data)
	return 0;
	return 0;
}
}


static int channel_hh_share_mem(struct neuron_mq_data_priv *priv,
				hh_vmid_t self, hh_vmid_t peer)
{
	u32 src_vmlist[1] = {self};
	int dst_vmlist[2] = {self, peer};
	int dst_perms[2] = {PERM_READ | PERM_WRITE, PERM_READ | PERM_WRITE};
	struct hh_acl_desc *acl;
	struct hh_sgl_desc *sgl;
	int ret;

	ret = hyp_assign_phys(priv->buffer.start, resource_size(&priv->buffer),
			      src_vmlist, 1,
			      dst_vmlist, dst_perms, 2);
	if (ret) {
		pr_err("hyp_assign_phys failed addr=%x size=%u err=%d\n",
		       priv->buffer.start, resource_size(&priv->buffer), ret);
		return ret;
	}

	acl = kzalloc(offsetof(struct hh_acl_desc, acl_entries[2]), GFP_KERNEL);
	if (!acl)
		return -ENOMEM;
	sgl = kzalloc(offsetof(struct hh_sgl_desc, sgl_entries[1]), GFP_KERNEL);
	if (!sgl) {
		kfree(acl);
		return -ENOMEM;
	}

	acl->n_acl_entries = 2;
	acl->acl_entries[0].vmid = (u16)self;
	acl->acl_entries[0].perms = HH_RM_ACL_R | HH_RM_ACL_W;
	acl->acl_entries[1].vmid = (u16)peer;
	acl->acl_entries[1].perms = HH_RM_ACL_R | HH_RM_ACL_W;

	sgl->n_sgl_entries = 1;
	sgl->sgl_entries[0].ipa_base = priv->buffer.start;
	sgl->sgl_entries[0].size = resource_size(&priv->buffer);
	ret = hh_rm_mem_qcom_lookup_sgl(HH_RM_MEM_TYPE_NORMAL,
					priv->haven_label,
					acl, sgl, NULL,
					&priv->shm_memparcel);
	kfree(acl);
	kfree(sgl);

	return ret;
}

static int channel_hh_rm_cb(struct notifier_block *nb, unsigned long cmd,
			    void *data)
{
	struct hh_rm_notif_vm_status_payload *vm_status_payload = data;
	struct neuron_mq_data_priv *priv;
	hh_vmid_t peer_vmid;
	hh_vmid_t self_vmid;

	priv = container_of(nb, struct neuron_mq_data_priv, rm_nb);
	if (cmd != HH_RM_NOTIF_VM_STATUS)
		return NOTIFY_DONE;

	if (vm_status_payload->vm_status != HH_RM_VM_STATUS_READY)
		return NOTIFY_DONE;
	if (hh_rm_get_vmid(priv->peer_name, &peer_vmid))
		return NOTIFY_DONE;
	if (hh_rm_get_vmid(HH_PRIMARY_VM, &self_vmid))
		return NOTIFY_DONE;
	if (peer_vmid != vm_status_payload->vmid)
		return NOTIFY_DONE;

	if (channel_hh_share_mem(priv, self_vmid, peer_vmid))
		pr_err("%s: failed to share memory\n", __func__);

	return NOTIFY_DONE;
}

static struct device_node *
channel_hh_svm_of_parse(struct neuron_mq_data_priv *priv, struct device *dev)
{
	const char *compat = "qcom,neuron-channel-haven-shmem-gen";
	struct device_node *np = NULL;
	struct device_node *shm_np;
	u32 label;
	int ret;

	while ((np = of_find_compatible_node(np, NULL, compat))) {
		ret = of_property_read_u32(np, "qcom,label", &label);
		if (ret) {
			of_node_put(np);
			continue;
		}
		if (label == priv->haven_label)
			break;

		of_node_put(np);
	}
	if (!np)
		return NULL;

	shm_np = of_parse_phandle(np, "memory-region", 0);
	if (!shm_np)
		dev_err(dev, "cant parse svm shared mem node!\n");

	of_node_put(np);
	return shm_np;
}

static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
				 struct device *dev)
				 struct device *dev)
{
{
@@ -289,9 +396,12 @@ static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,


	np = of_parse_phandle(dev->of_node, "shared-buffer", 0);
	np = of_parse_phandle(dev->of_node, "shared-buffer", 0);
	if (!np) {
	if (!np) {
		dev_err(dev, "shared-buffer node missing!\n");
		np = channel_hh_svm_of_parse(priv, dev);
		if (!np) {
			dev_err(dev, "cant parse shared mem node!\n");
			return -EINVAL;
			return -EINVAL;
		}
		}
	}


	ret = of_address_to_resource(np, 0, &priv->buffer);
	ret = of_address_to_resource(np, 0, &priv->buffer);
	of_node_put(np);
	of_node_put(np);
@@ -320,10 +430,20 @@ static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
		return -ENXIO;
		return -ENXIO;
	}
	}


	if (of_property_read_bool(dev->of_node, "qcom,primary"))
	if (of_property_read_bool(dev->of_node, "qcom,primary")) {
		memset(priv->base, 0,
		memset(priv->base, 0,
		       sizeof(struct neuron_shmem_channel_header));
		       sizeof(struct neuron_shmem_channel_header));


		ret = of_property_read_u32(dev->of_node, "peer-name",
					   &priv->peer_name);
		if (ret)
			priv->peer_name = HH_SELF_VM;

		priv->rm_nb.notifier_call = channel_hh_rm_cb;
		priv->rm_nb.priority = INT_MAX;
		hh_rm_register_notifier(&priv->rm_nb);
	}

	return 0;
	return 0;
}
}


@@ -343,17 +463,18 @@ static int channel_hh_probe(struct neuron_channel *cdev)
		return -ENOMEM;
		return -ENOMEM;
	priv->dev = cdev;
	priv->dev = cdev;


	ret = of_property_read_u32(node, "haven-label", &priv->haven_label);
	if (ret) {
		dev_err(dev, "failed to read label info %d\n", ret);
		return ret;
	}

	ret = channel_hh_map_memory(priv, dev);
	ret = channel_hh_map_memory(priv, dev);
	if (ret)
	if (ret)
		return ret;
		return ret;


	/* Get outgoing haven doorbell information */
	/* Get outgoing haven doorbell information */
	ret = of_property_read_u32(node, "haven-label", &dbl_label);
	dbl_label = priv->haven_label;
	if (ret) {
		dev_err(dev, "failed to read label info %d\n", ret);
		goto fail_tx_dbl;
	}

	priv->tx_dbl = hh_dbl_tx_register(dbl_label);
	priv->tx_dbl = hh_dbl_tx_register(dbl_label);
	if (IS_ERR_OR_NULL(priv->tx_dbl)) {
	if (IS_ERR_OR_NULL(priv->tx_dbl)) {
		ret = PTR_ERR(priv->tx_dbl);
		ret = PTR_ERR(priv->tx_dbl);
+8 −0
Original line number Original line Diff line number Diff line
@@ -76,10 +76,18 @@ struct neuron_mq_data_priv {
	atomic64_t virq_payload;
	atomic64_t virq_payload;
	/* A counter to calculate the interrupt received. */
	/* A counter to calculate the interrupt received. */
	u32 interrupt_counter;
	u32 interrupt_counter;
	/* name of peer vm */
	u32 peer_name;
	/* label to get haven resources like doorbell and shm */
	u32 haven_label;
	/* haven tx doorbell descriptor */
	/* haven tx doorbell descriptor */
	void *tx_dbl;
	void *tx_dbl;
	/* haven rx doorbell descriptor */
	/* haven rx doorbell descriptor */
	void *rx_dbl;
	void *rx_dbl;
	/* memparcel handle after assigning label to shared memory */
	u32 shm_memparcel;
	/* haven rm status notifier block */
	struct notifier_block rm_nb;
	/* pointer to the device structure */
	/* pointer to the device structure */
	struct neuron_channel *dev;
	struct neuron_channel *dev;
	/* shared memory mapped address */
	/* shared memory mapped address */
+17 −5
Original line number Original line Diff line number Diff line
@@ -40,6 +40,8 @@ struct haven_pipe {
 * @base: Base of the shared fifo.
 * @base: Base of the shared fifo.
 * @size: fifo size.
 * @size: fifo size.
 * @master: primary vm indicator.
 * @master: primary vm indicator.
 * @peer_name: name of vm peer.
 * @label: label for haven resources
 * @tx_dbl: doorbell for tx notifications.
 * @tx_dbl: doorbell for tx notifications.
 * @rx_dbl: doorbell for rx notifications.
 * @rx_dbl: doorbell for rx notifications.
 * @tx_pipe: TX haven specific info.
 * @tx_pipe: TX haven specific info.
@@ -53,7 +55,9 @@ struct qrtr_haven_dev {
	void *base;
	void *base;
	size_t size;
	size_t size;
	bool master;
	bool master;
	u32 peer_name;


	u32 label;
	void *tx_dbl;
	void *tx_dbl;
	void *rx_dbl;
	void *rx_dbl;


@@ -328,18 +332,26 @@ static int qrtr_haven_probe(struct platform_device *pdev)
	if (!qdev->buf)
	if (!qdev->buf)
		return -ENOMEM;
		return -ENOMEM;


	ret = of_property_read_u32(node, "haven-label", &qdev->label);
	if (ret) {
		dev_err(qdev->dev, "failed to read label info %d\n", ret);
		return ret;
	}
	qdev->master = of_property_read_bool(node, "qcom,master");
	qdev->master = of_property_read_bool(node, "qcom,master");

	ret = qrtr_haven_map_memory(qdev);
	ret = qrtr_haven_map_memory(qdev);
	if (ret)
	if (ret)
		return ret;
		return ret;


	ret = of_property_read_u32(node, "haven-label", &dbl_label);
	if (ret) {
		dev_err(qdev->dev, "failed to read label info %d\n", ret);
		return ret;
	}
	qrtr_haven_fifo_init(qdev);
	qrtr_haven_fifo_init(qdev);


	if (qdev->master) {
		ret = of_property_read_u32(node, "peer-name", &qdev->peer_name);
		if (ret)
			qdev->peer_name = HH_SELF_VM;
	}

	dbl_label = qdev->label;
	qdev->tx_dbl = hh_dbl_tx_register(dbl_label);
	qdev->tx_dbl = hh_dbl_tx_register(dbl_label);
	if (IS_ERR_OR_NULL(qdev->tx_dbl)) {
	if (IS_ERR_OR_NULL(qdev->tx_dbl)) {
		ret = PTR_ERR(qdev->tx_dbl);
		ret = PTR_ERR(qdev->tx_dbl);