mm-drivers: hw_fence: add implementation of translation to synx API

Add implementation to translate the msm_hw_fence API into synx API.

Change-Id: I5d0b7afcc297a4e3c8ec4ed9867831b5d2dfc3af
Signed-off-by: Grace An <quic_gracan@quicinc.com>
Dieser Commit ist enthalten in:
Grace An
2022-12-08 15:40:49 -08:00
Ursprung 5eec9ba76c
Commit 41b11c1d09
3 geänderte Dateien mit 338 neuen und 3 gelöschten Zeilen

Datei anzeigen

@@ -3,7 +3,9 @@
KDIR := $(TOP)/kernel_platform/msm-kernel
include $(MSM_HW_FENCE_ROOT)/config/kalamammdrivers.conf
LINUXINCLUDE += -include $(MSM_HW_FENCE_ROOT)/config/kalamammdriversconf.h \
-I$(MSM_HW_FENCE_ROOT)hw_fence/include/
-I$(MSM_HW_FENCE_ROOT)hw_fence/include/ \
-I$(MSM_HW_FENCE_ROOT)/../synx-kernel/msm/synx/ \
-I$(MSM_HW_FENCE_ROOT)/../synx-kernel/include/uapi/synx/media/
ifdef CONFIG_QTI_HW_FENCE
obj-m += msm_hw_fence.o
@@ -12,7 +14,8 @@ msm_hw_fence-y := src/msm_hw_fence.o \
src/hw_fence_drv_priv.o \
src/hw_fence_drv_utils.o \
src/hw_fence_drv_debug.o \
src/hw_fence_drv_ipc.o
src/hw_fence_drv_ipc.o \
src/msm_hw_fence_synx_translation.o
msm_hw_fence-$(CONFIG_DEBUG_FS) += src/hw_fence_ioctl.o

Datei anzeigen

@@ -15,7 +15,7 @@
#include "hw_fence_drv_ipc.h"
struct hw_fence_driver_data *hw_fence_drv_data;
static bool hw_fence_driver_enable;
bool hw_fence_driver_enable;
void *msm_hw_fence_register(enum hw_fence_client_id client_id_ext,
struct msm_hw_fence_mem_addr *mem_descriptor)

Datei anzeigen

@@ -0,0 +1,332 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/soc/qcom/msm_hw_fence.h>
#include "msm_hw_fence_synx_translation.h"
#include "hw_fence_drv_priv.h"
#include "hw_fence_drv_debug.h"
/**
* MAX_SUPPORTED_DPU0:
* Maximum number of dpu clients supported
*/
#define MAX_SUPPORTED_DPU0 (HW_FENCE_CLIENT_ID_CTL5 - HW_FENCE_CLIENT_ID_CTL0)
static int to_synx_status(int hw_fence_status_code)
{
int synx_status_code;
switch (hw_fence_status_code) {
case 0:
synx_status_code = SYNX_SUCCESS;
break;
case -ENOMEM:
synx_status_code = -SYNX_NOMEM;
break;
case -EPERM:
synx_status_code = -SYNX_NOPERM;
break;
case -ETIMEDOUT:
synx_status_code = -SYNX_TIMEOUT;
break;
case -EALREADY:
synx_status_code = -SYNX_ALREADY;
break;
case -ENOENT:
synx_status_code = -SYNX_NOENT;
break;
case -EINVAL:
synx_status_code = -SYNX_INVALID;
break;
case -EBUSY:
synx_status_code = -SYNX_BUSY;
break;
default:
synx_status_code = hw_fence_status_code;
break;
}
return synx_status_code;
}
static enum hw_fence_client_id _get_hw_fence_client_id(enum synx_client_id synx_client_id)
{
enum hw_fence_client_id hw_fence_client_id;
switch ((int)synx_client_id) {
case SYNX_CLIENT_HW_FENCE_GFX_CTX0:
hw_fence_client_id = HW_FENCE_CLIENT_ID_CTX0;
break;
case SYNX_CLIENT_HW_FENCE_IPE_CTX0 ... SYNX_CLIENT_HW_FENCE_IPE_CTX0 +
SYNX_MAX_SIGNAL_PER_CLIENT - 1:
hw_fence_client_id = synx_client_id - SYNX_CLIENT_HW_FENCE_IPE_CTX0 +
HW_FENCE_CLIENT_ID_IPE;
break;
case SYNX_CLIENT_HW_FENCE_VID_CTX0 ... SYNX_CLIENT_HW_FENCE_VID_CTX0 +
SYNX_MAX_SIGNAL_PER_CLIENT - 1:
hw_fence_client_id = synx_client_id - SYNX_CLIENT_HW_FENCE_VID_CTX0 +
HW_FENCE_CLIENT_ID_VPU;
break;
case SYNX_CLIENT_HW_FENCE_DPU0_CTL0 ... SYNX_CLIENT_HW_FENCE_DPU0_CTL0 + MAX_SUPPORTED_DPU0:
hw_fence_client_id = synx_client_id - SYNX_CLIENT_HW_FENCE_DPU0_CTL0 +
HW_FENCE_CLIENT_ID_CTL0;
break;
case SYNX_CLIENT_HW_FENCE_IFE0_CTX0 ... SYNX_CLIENT_HW_FENCE_IFE7_CTX0 +
SYNX_MAX_SIGNAL_PER_CLIENT - 1:
hw_fence_client_id = synx_client_id - SYNX_CLIENT_HW_FENCE_IFE0_CTX0 +
HW_FENCE_CLIENT_ID_IFE0;
break;
default:
HWFNC_ERR("Unsupported hw-fence client for synx_id:%d\n", synx_client_id);
hw_fence_client_id = HW_FENCE_CLIENT_MAX;
break;
}
return hw_fence_client_id;
}
static bool is_hw_fence_client(enum synx_client_id synx_client_id)
{
return synx_client_id >= SYNX_HW_FENCE_CLIENT_START
&& synx_client_id < SYNX_HW_FENCE_CLIENT_END;
}
struct synx_session *synx_hwfence_initialize(struct synx_initialization_params *params)
{
struct synx_session *session = NULL;
enum hw_fence_client_id client_id;
void *client_handle;
if (!hw_fence_driver_enable)
return ERR_PTR(-SYNX_INVALID);
if (IS_ERR_OR_NULL(params) || IS_ERR_OR_NULL(params->ptr)) {
HWFNC_ERR("invalid params:0x%pK params->ptr:0x%pK\n", params,
IS_ERR_OR_NULL(params) ? NULL : params->ptr);
return ERR_PTR(-SYNX_INVALID);
}
client_id = _get_hw_fence_client_id(params->id);
if (!is_hw_fence_client(params->id) || client_id == HW_FENCE_CLIENT_MAX) {
HWFNC_ERR("Initializing session for invalid synx_id:%d\n", params->id);
return ERR_PTR(-SYNX_INVALID);
}
session = kzalloc(sizeof(struct synx_session), GFP_KERNEL);
if (!session)
return ERR_PTR(-SYNX_NOMEM);
client_handle = msm_hw_fence_register(client_id,
(struct msm_hw_fence_mem_addr *)params->ptr);
if (IS_ERR_OR_NULL(client_handle)) {
kfree(session);
HWFNC_ERR("failed to initialize synx_id:%d ret:%d\n", params->id,
PTR_ERR(client_handle));
return ERR_PTR(to_synx_status(PTR_ERR(client_handle)));
}
session->client = client_handle;
session->type = params->id;
HWFNC_DBG_INIT("initialized session synx_id:%d hw_fence_id:%d\n", params->id, client_id);
return session;
}
EXPORT_SYMBOL(synx_hwfence_initialize);
int synx_hwfence_uninitialize(struct synx_session *session)
{
int ret;
if (IS_ERR_OR_NULL(session) || !is_hw_fence_client(session->type)) {
HWFNC_ERR("invalid session:0x%pK synx_id:%d\n", session,
IS_ERR_OR_NULL(session) ? -1 : session->type);
return -SYNX_INVALID;
}
ret = msm_hw_fence_deregister(session->client);
if (ret)
HWFNC_ERR("Failed to deregister synx_id:%d ret:%d\n", session->type, ret);
else
kfree(session);
return to_synx_status(ret);
}
EXPORT_SYMBOL(synx_hwfence_uninitialize);
int synx_hwfence_create(struct synx_session *session, struct synx_create_params *params)
{
int ret = 0;
struct msm_hw_fence_create_params hwfence_params;
u64 handle;
if (IS_ERR_OR_NULL(session) || !is_hw_fence_client(session->type) ||
IS_ERR_OR_NULL(params)) {
HWFNC_ERR("invalid session:0x%pK synx_id:%d params:0x%pK\n", session,
IS_ERR_OR_NULL(session) ? -1 : session->type, params);
return -SYNX_INVALID;
}
if (IS_ERR_OR_NULL(params->h_synx) || (params->flags != SYNX_CREATE_DMA_FENCE) ||
IS_ERR_OR_NULL(params->fence)) {
HWFNC_ERR("synx_id:%d invalid create params h_synx:0x%pK flags:0x%x fence:0x%pK\n",
session->type, params->h_synx, params->flags, params->fence);
return -SYNX_INVALID;
}
hwfence_params.fence = params->fence;
hwfence_params.handle = &handle;
ret = msm_hw_fence_create(session->client, &hwfence_params);
if (ret) {
HWFNC_ERR("synx_id:%d failed create fence:0x%pK flags:0x%x ret:%d\n", session->type,
params->fence, params->flags, ret);
return to_synx_status(ret);
}
if (handle > U32_MAX) {
HWFNC_ERR("synx_id:%d fence handle:%llu would overflow h_synx\n", session->type,
handle);
msm_hw_fence_destroy_with_handle(session->client, handle);
return -SYNX_INVALID;
}
*params->h_synx = handle;
return SYNX_SUCCESS;
}
EXPORT_SYMBOL(synx_hwfence_create);
int synx_hwfence_release(struct synx_session *session, u32 h_synx)
{
int ret;
if (IS_ERR_OR_NULL(session) || !is_hw_fence_client(session->type)) {
HWFNC_ERR("invalid session:0x%pK synx_id:%d\n", session,
IS_ERR_OR_NULL(session) ? -1 : session->type);
return -SYNX_INVALID;
}
ret = msm_hw_fence_destroy_with_handle(session->client, h_synx);
if (ret)
HWFNC_ERR("synx_id:%d failed to destroy fence h_synx:%u ret:%d\n", session->type,
h_synx, ret);
return to_synx_status(ret);
}
EXPORT_SYMBOL(synx_hwfence_release);
int synx_hwfence_signal(struct synx_session *session, u32 h_synx, enum synx_signal_status status)
{
int ret;
if (IS_ERR_OR_NULL(session) || !is_hw_fence_client(session->type)) {
HWFNC_ERR("invalid session:0x%pK synx_id:%d\n", session,
IS_ERR_OR_NULL(session) ? -1 : session->type);
return -SYNX_INVALID;
}
ret = msm_hw_fence_update_txq(session->client, h_synx, 0, (u32)status);
if (ret)
HWFNC_ERR("synx_id:%d failed to signal fence h_synx:%u status:%d ret:%d\n",
session->type, h_synx, status, ret);
return to_synx_status(ret);
}
EXPORT_SYMBOL(synx_hwfence_signal);
int synx_hwfence_recover(enum synx_client_id id)
{
int ret;
if (!is_hw_fence_client(id)) {
HWFNC_ERR("invalid synx_id:%d\n", id);
return -SYNX_INVALID;
}
ret = msm_hw_fence_reset_client_by_id(_get_hw_fence_client_id(id),
MSM_HW_FENCE_RESET_WITHOUT_DESTROY);
if (ret)
HWFNC_ERR("synx_id:%d failed to recover ret:%d\n", id, ret);
return to_synx_status(ret);
}
EXPORT_SYMBOL(synx_hwfence_recover);
static int synx_hwfence_import_indv(void *client, struct synx_import_indv_params *params)
{
u64 handle;
int ret;
if (IS_ERR_OR_NULL(client) || IS_ERR_OR_NULL(params) ||
IS_ERR_OR_NULL(params->new_h_synx) ||
(params->flags != SYNX_IMPORT_DMA_FENCE) || IS_ERR_OR_NULL(params->fence)) {
HWFNC_ERR("invalid client:0x%pK params:0x%pK h_synx:0x%pK flags:0x%x fence:0x%pK\n",
client, params, IS_ERR_OR_NULL(params) ? NULL : params->new_h_synx,
IS_ERR_OR_NULL(params) ? 0 : params->flags,
IS_ERR_OR_NULL(params) ? NULL : params->fence);
return -SYNX_INVALID;
}
ret = msm_hw_fence_wait_update_v2(client, (struct dma_fence **)&params->fence, &handle,
NULL, 1, true);
if (ret) {
HWFNC_ERR("failed to import fence:0x%pK flags:0x%x ret:%d\n", params->fence,
params->flags, ret);
return to_synx_status(ret);
}
if (handle > U32_MAX) {
HWFNC_ERR("fence handle:%llu would overflow new_h_synx\n", handle);
msm_hw_fence_wait_update_v2(client, (struct dma_fence **)&params->fence, &handle,
NULL, 1, false);
return -SYNX_INVALID;
}
*params->new_h_synx = handle;
return SYNX_SUCCESS;
}
static int synx_hwfence_import_arr(void *client, struct synx_import_arr_params *params)
{
int i, ret;
if (IS_ERR_OR_NULL(client) || IS_ERR_OR_NULL(params) || !params->num_fences) {
HWFNC_ERR("invalid import arr client:0x%pK params:0x%pK num_fences:%u\n", client,
params, IS_ERR_OR_NULL(params) ? -1 : params->num_fences);
return -SYNX_INVALID;
}
for (i = 0; i < params->num_fences; i++) {
ret = synx_hwfence_import_indv(client, &params->list[i]);
if (ret) {
HWFNC_ERR("importing fence[%u] 0x%pK failed ret:%d\n", i,
params->list[i].fence, ret);
return ret;
}
}
return SYNX_SUCCESS;
}
int synx_hwfence_import(struct synx_session *session, struct synx_import_params *params)
{
int ret;
if (IS_ERR_OR_NULL(session) || !is_hw_fence_client(session->type)
|| IS_ERR_OR_NULL(params)) {
HWFNC_ERR("invalid session:0x%pK synx_id:%d params:0x%pK\n", session,
IS_ERR_OR_NULL(session) ? -1 : session->type, params);
return -SYNX_INVALID;
}
if (params->type == SYNX_IMPORT_ARR_PARAMS)
ret = synx_hwfence_import_arr(session->client, &params->arr);
else
ret = synx_hwfence_import_indv(session->client, &params->indv);
if (ret)
HWFNC_ERR("synx_id:%d failed to import type:%s fences ret:%d\n", session->type,
(params->type == SYNX_IMPORT_ARR_PARAMS) ? "arr" : "indv", ret);
return ret;
}
EXPORT_SYMBOL(synx_hwfence_import);