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

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

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

parents cf37238a d076f020
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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__ */

msm/sde/sde_vm_msgq.c

0 → 100644
+125 −0
Original line number Diff line number Diff line
// 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);
}
Loading