mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 07:37:31 -04:00
Merge "disp: msm: sde: add msgq support for sde vm layer"
This commit is contained in:
commit
987888e623
8 changed files with 251 additions and 2 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
msm/sde/sde_vm_msgq.c
Normal file
125
msm/sde/sde_vm_msgq.c
Normal file
|
|
@ -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
msm/sde/sde_vm_msgq.h
Normal file
28
msm/sde/sde_vm_msgq.h
Normal file
|
|
@ -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__
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue