Loading msm/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading msm/sde/sde_vm.h +50 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); }; /** Loading @@ -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; Loading @@ -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; }; /** Loading msm/sde/sde_vm_common.c +9 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } msm/sde/sde_vm_common.h +16 −1 Original line number Diff line number Diff line Loading @@ -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
msm/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
msm/sde/sde_vm.h +50 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); }; /** Loading @@ -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; Loading @@ -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; }; /** Loading
msm/sde/sde_vm_common.c +9 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); }
msm/sde/sde_vm_common.h +16 −1 Original line number Diff line number Diff line Loading @@ -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); }