فهرست منبع

Merge "disp: msm: sde: add msgq support for sde vm layer"

qctecmdr 4 سال پیش
والد
کامیت
987888e623
8فایلهای تغییر یافته به همراه251 افزوده شده و 2 حذف شده
  1. 2 1
      msm/Makefile
  2. 50 0
      msm/sde/sde_vm.h
  3. 9 0
      msm/sde/sde_vm_common.c
  4. 16 1
      msm/sde/sde_vm_common.h
  5. 125 0
      msm/sde/sde_vm_msgq.c
  6. 28 0
      msm/sde/sde_vm_msgq.h
  7. 10 0
      msm/sde/sde_vm_primary.c
  8. 11 0
      msm/sde/sde_vm_trusted.c

+ 2 - 1
msm/Makefile

@@ -87,7 +87,8 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
 
 msm_drm-$(CONFIG_DRM_SDE_VM) += sde/sde_vm_common.o \
 	sde/sde_vm_primary.o \
-	sde/sde_vm_trusted.o
+	sde/sde_vm_trusted.o \
+	sde/sde_vm_msgq.o
 
 msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
 	sde/sde_encoder_phys_wb.o

+ 50 - 0
msm/sde/sde_vm.h

@@ -12,6 +12,35 @@
 
 struct sde_kms;
 
+/* sde_vm_msg_type - msg_type for dispaly custom messages */
+enum sde_vm_msg_type {
+	SDE_VM_MSG_MAX,
+};
+
+/**
+ * sde_vm_msg_work - sde msgq work definition
+ * @work - base kthread work object
+ * @msg_buf - payload buffer
+ * @msg_size - payload buffer size
+ * @sde_vm - handle to vm structure
+ */
+struct sde_vm_msg_work {
+	struct kthread_work work;
+	void *msg_buf;
+	size_t msg_size;
+	struct sde_vm *sde_vm;
+};
+
+/**
+ * sde_vm_msg_header - header definition for custom messages. Must
+ *                     be placed at the beginning of each custom
+ *                     message definition.
+ * @msg_type - type of the message
+ */
+struct sde_vm_msg_header {
+	enum sde_vm_msg_type msg_type;
+};
+
 /**
  * sde_vm_irq_entry - VM irq specification
  * @label - VM_IRQ_LABEL assigned by Hyp RM
@@ -122,6 +151,21 @@ struct sde_vm_ops {
 	 * @sde_kms - handle to sde_kms
 	 */
 	int (*vm_acquire_fail_handler)(struct sde_kms *sde_kms);
+
+	/** vm_msg_recv_cb - sde kms callback hook for msgq data
+	 * @sde_vm - handle to sde_vm struct
+	 * @data - paylod data
+	 * @size - size of payload data
+	 */
+	void (*vm_msg_recv_cb)(struct sde_vm *sde_vm, void *data, size_t size);
+
+	/** vm_msg_send - hook to send custom data to VM
+	 * @sde_vm - handle to sde_vm struct
+	 * @msg - payload data
+	 * @msg_size - payload data size
+	 * @return - 0 on success, errorcode otherwise
+	 */
+	int (*vm_msg_send)(struct sde_vm *sde_vm, void *msg, size_t msg_size);
 };
 
 /**
@@ -132,6 +176,9 @@ struct sde_vm_ops {
  * @io_mem_handle - RM identifier for the IO range
  * @sde_kms - handle to sde_kms
  * @vm_ops - VM operation hooks for respective VM type
+ * @msgq_listener_thread - handle to msgq receiver thread
+ * @vm_work - kthread work obj for msgq
+ * @msgq_handle - handle to display msgq
  */
 struct sde_vm {
 	struct mutex vm_res_lock;
@@ -140,6 +187,9 @@ struct sde_vm {
 	int io_mem_handle;
 	struct sde_kms *sde_kms;
 	struct sde_vm_ops vm_ops;
+	struct task_struct *msgq_listener_thread;
+	struct sde_vm_msg_work vm_work;
+	void *msgq_handle;
 };
 
 /**

+ 9 - 0
msm/sde/sde_vm_common.c

@@ -10,6 +10,7 @@
 #include "sde_kms.h"
 #include "sde_vm_common.h"
 #include "sde_crtc.h"
+#include "sde_vm_msgq.h"
 
 struct hh_notify_vmid_desc *sde_vm_populate_vmid(hh_vmid_t vmid)
 {
@@ -321,3 +322,11 @@ int sde_vm_request_valid(struct sde_kms *sde_kms,
 
 	return rc;
 }
+
+int sde_vm_msg_send(struct sde_vm *sde_vm, void *msg, size_t msg_size)
+{
+	if (!sde_vm)
+		return -EINVAL;
+
+	return sde_vm_msgq_send(sde_vm, msg, msg_size);
+}

+ 16 - 1
msm/sde/sde_vm_common.h

@@ -75,9 +75,24 @@ int sde_vm_post_acquire(struct sde_kms *kms);
  */
 int sde_vm_pre_release(struct sde_kms *kms);
 
-
+/**
+ * sde_vm_request_valid - check the validity of state transition request
+ * @sde_kms: handle to sde_kms
+ * @old_state: old crtc vm req state
+ * @new_state: new crtc vm req state
+ * @return: 0 on success
+ */
 int sde_vm_request_valid(struct sde_kms *sde_kms,
 			  enum sde_crtc_vm_req old_state,
 			  enum sde_crtc_vm_req new_state);
 
+/**
+ * sde_vm_msg_send - send display custom message through message queue
+ * @sde_vm: handle to sde_vm struct
+ * @msg: payload data
+ * @msg_size: payload data size
+ * @return: 0 on success
+ */
+int sde_vm_msg_send(struct sde_vm *sde_vm, void *msg, size_t msg_size);
+
 #endif /* __SDE_VM_COMMON_H__ */

+ 125 - 0
msm/sde/sde_vm_msgq.c

@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/haven/hh_msgq.h>
+#include <linux/kthread.h>
+#include "sde_kms.h"
+#include "sde_vm.h"
+
+static void _sde_vm_msgq_process_msg(struct kthread_work *work)
+{
+	struct sde_vm_msg_work *vm_work =
+		container_of(work, struct sde_vm_msg_work, work);
+	struct sde_vm_ops *vm_ops = &vm_work->sde_vm->vm_ops;
+
+	if (vm_ops->vm_msg_recv_cb)
+		vm_ops->vm_msg_recv_cb(vm_work->sde_vm, vm_work->msg_buf,
+				vm_work->msg_size);
+
+	kfree(vm_work->msg_buf);
+}
+
+static int _sde_vm_msgq_listener(void *data)
+{
+	struct sde_vm *sde_vm = (struct sde_vm *)data;
+	struct sde_kms *sde_kms = sde_vm->sde_kms;
+	struct sde_vm_msg_work *vm_work;
+	struct msm_drm_private *priv;
+	struct msm_drm_thread *event_thread;
+	void *buf;
+	size_t size;
+	int ret = 0;
+
+	priv = sde_kms->dev->dev_private;
+	event_thread = &priv->event_thread[0];
+	vm_work = &sde_vm->vm_work;
+
+	while (true) {
+		buf = kzalloc(HH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+
+		ret = hh_msgq_recv(sde_vm->msgq_handle, buf,
+				HH_MSGQ_MAX_MSG_SIZE_BYTES, &size, 0);
+		if (ret < 0) {
+			kfree(buf);
+			SDE_ERROR("hh_msgq_recv failed, rc=%d\n", ret);
+			return -EINVAL;
+		}
+
+		vm_work->msg_buf = buf;
+		vm_work->msg_size = size;
+		vm_work->sde_vm = sde_vm;
+
+		kthread_queue_work(&event_thread->worker, &vm_work->work);
+	}
+
+	return 0;
+}
+
+int sde_vm_msgq_send(struct sde_vm *sde_vm, void *msg, size_t msg_size)
+{
+	if (!sde_vm->msgq_handle) {
+		SDE_ERROR("Failed to send msg, invalid msgq handle\n");
+		return -EINVAL;
+	}
+
+	if (msg_size > HH_MSGQ_MAX_MSG_SIZE_BYTES) {
+		SDE_ERROR("msg size unsupported for msgq: %d > %d\n", msg_size,
+				HH_MSGQ_MAX_MSG_SIZE_BYTES);
+		return -E2BIG;
+	}
+
+	return hh_msgq_send(sde_vm->msgq_handle, msg, msg_size, HH_MSGQ_TX_PUSH);
+}
+
+int sde_vm_msgq_init(struct sde_vm *sde_vm)
+{
+	struct sde_vm_ops *vm_ops = &sde_vm->vm_ops;
+	void *msgq_handle = NULL;
+	struct task_struct *msgq_listener_thread = NULL;
+	int rc = 0;
+
+	msgq_handle = hh_msgq_register(HH_MSGQ_LABEL_DISPLAY);
+	if (IS_ERR(msgq_handle)) {
+		SDE_ERROR("hh_msgq_register failed, hdl=%p\n", msgq_handle);
+		return -EINVAL;
+	}
+
+	sde_vm->msgq_handle = msgq_handle;
+
+	if (!vm_ops->vm_msg_recv_cb)
+		goto done;
+
+	msgq_listener_thread = kthread_run(_sde_vm_msgq_listener,
+			(void *)sde_vm, "disp_msgq_listener");
+	if (IS_ERR(msgq_listener_thread)) {
+		SDE_ERROR("kthread creation failed for msgq, hdl: %p\n",
+				msgq_listener_thread);
+		rc = -EINVAL;
+		goto kthread_create_fail;
+	}
+
+	kthread_init_work(&sde_vm->vm_work.work, _sde_vm_msgq_process_msg);
+
+	sde_vm->msgq_listener_thread = msgq_listener_thread;
+
+	return 0;
+
+kthread_create_fail:
+	hh_msgq_unregister(msgq_handle);
+	sde_vm->msgq_handle = NULL;
+done:
+	return rc;
+}
+
+void sde_vm_msgq_deinit(struct sde_vm *sde_vm)
+{
+	if (sde_vm->msgq_listener_thread)
+		kthread_stop(sde_vm->msgq_listener_thread);
+
+	if (sde_vm->msgq_handle)
+		hh_msgq_unregister(sde_vm->msgq_handle);
+}

+ 28 - 0
msm/sde/sde_vm_msgq.h

@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+#ifndef __SDE_VM_MSGQ_H__
+#define __SDE_VM_MSGQ_H__
+
+/**
+ * sde_vm_msgq_init - initialize display message queue: both TX and RX
+ * @sde_kms - handle to sde_kms
+ */
+int sde_vm_msgq_init(struct sde_vm *sde_vm);
+
+/**
+ * sde_vm_msgq_deinit - deinitialize display message queue: both TX and RX
+ * @sde_kms - handle to sde_kms
+ */
+void sde_vm_msgq_deinit(struct sde_vm *sde_vm);
+
+/**
+ * sde_vm_msgq_send - send custom messages across VM's
+ * @sde_vm - handle to vm base struct
+ * @msg - payload data
+ * @msg_size - size of the payload_data
+ */
+int sde_vm_msgq_send(struct sde_vm *sde_vm, void *msg, size_t msg_size);
+
+#endif // __SDE_VM_MSGQ_H__

+ 10 - 0
msm/sde/sde_vm_primary.c

@@ -9,6 +9,7 @@
 #include "sde_kms.h"
 #include "sde_vm.h"
 #include "sde_vm_common.h"
+#include "sde_vm_msgq.h"
 
 #define to_vm_primary(vm) ((struct sde_vm_primary *)vm)
 
@@ -266,6 +267,8 @@ static void _sde_vm_deinit(struct sde_kms *sde_kms, struct sde_vm_ops *ops)
 
 	sde_vm = to_vm_primary(sde_kms->vm);
 
+	sde_vm_msgq_deinit(sde_kms->vm);
+
 	if (sde_vm->base.mem_notification_cookie)
 		hh_mem_notifier_unregister(
 				sde_vm->base.mem_notification_cookie);
@@ -289,6 +292,7 @@ static void _sde_vm_set_ops(struct sde_vm_ops *ops)
 	ops->vm_prepare_commit = sde_kms_vm_primary_prepare_commit;
 	ops->vm_post_commit = sde_kms_vm_primary_post_commit;
 	ops->vm_request_valid = sde_vm_request_valid;
+	ops->vm_msg_send = sde_vm_msg_send;
 }
 
 int sde_vm_primary_init(struct sde_kms *kms)
@@ -318,6 +322,12 @@ int sde_vm_primary_init(struct sde_kms *kms)
 
 	mutex_init(&sde_vm->base.vm_res_lock);
 
+	rc = sde_vm_msgq_init(kms->vm);
+	if (rc) {
+		SDE_ERROR("failed to initialize the msgq, rc=%d\n", rc);
+		goto init_fail;
+	}
+
 	return 0;
 init_fail:
 	_sde_vm_deinit(kms, &sde_vm->base.vm_ops);

+ 11 - 0
msm/sde/sde_vm_trusted.c

@@ -13,6 +13,8 @@
 #include "sde_kms.h"
 #include "sde_vm_common.h"
 #include "sde_vm.h"
+#include "sde_vm_msgq.h"
+
 
 #define to_vm_trusted(vm) ((struct sde_vm_trusted *)vm)
 
@@ -247,6 +249,8 @@ static void  _sde_vm_deinit(struct sde_kms *kms, struct sde_vm_ops *ops)
 
 	memset(ops, 0, sizeof(*ops));
 
+	sde_vm_msgq_deinit(kms->vm);
+
 	if (sde_vm->base.mem_notification_cookie)
 		hh_mem_notifier_unregister(
 				sde_vm->base.mem_notification_cookie);
@@ -409,6 +413,7 @@ static void _sde_vm_set_ops(struct sde_vm_ops *ops)
 	ops->vm_post_commit = sde_kms_vm_trusted_post_commit;
 	ops->vm_request_valid = sde_vm_request_valid;
 	ops->vm_acquire_fail_handler = _sde_vm_release;
+	ops->vm_msg_send = sde_vm_msg_send;
 }
 
 int sde_vm_trusted_init(struct sde_kms *kms)
@@ -460,6 +465,12 @@ int sde_vm_trusted_init(struct sde_kms *kms)
 
 	atomic_set(&sde_vm->base.n_irq_lent, 0);
 
+	rc = sde_vm_msgq_init(kms->vm);
+	if (rc) {
+		SDE_ERROR("failed to initialize the msgq, rc=%d\n", rc);
+		goto init_fail;
+	}
+
 	return 0;
 init_fail:
 	_sde_vm_deinit(kms, &sde_vm->base.vm_ops);