mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
DCE-KMD: dce-ipc.c: Abstract out iosys
- Abstract out iosys_* dependencies for writing/reading to/from
message header and memcpy to os specific implementation.
- Add new dce-os-ipc.c
- Cannot add these functions to existing 'dce-os-ivc.h' as
static inline functions because these functions access
dce_ipc_channel defined in dce_ipc.h.
- Cannot include dce_ipc.h to this file as it creates
a circular dependency.
- Also fix exsisting issue of not defining 'tegra_dce' inside
dce-ipc.h
- This is exposed now because we're including dce-ipc.h to
dce-os-ipc.c which doesn't include any prior headers which
define tegra_dce.
- Fix by doing forward define to avoid circular dependency
with dce.h
- Additionally fix below iosys issues:
1) Change Iabebef33719c38a8aa4db8573a0dd7dd7e5f83f6 introduced
an issue because NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP demands
different prototypes for below functions:
- dce_os_ivc_get_next_write_frame()
- dce_os_ivc_get_next_read_frame()
2) Now since dce_ipc_is_data_available() uses
dce_os_ivc_get_next_read_frame(), it needs to define
frame with iosys_map for IOSYS Linux 6.2 usecase. So need
to creata a OS abstraction for this too.
JIRA TDS-16126
Change-Id: I55594d8e34c3b572129119d1f7240cde76cf37bd
Signed-off-by: anupamg <anupamg@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3233117
Reviewed-by: Mahesh Kumar <mahkumar@nvidia.com>
Reviewed-by: Arun Swain <arswain@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
@@ -36,6 +36,7 @@ tegra-dce-$(CONFIG_TEGRA_DCE) += dce-pm.o
|
||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-os-utils.o
|
||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-hsp-smb-t264.o
|
||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-hsp-ss-t264.o
|
||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-os-ivc.o
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_FS),y)
|
||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-debug.o
|
||||
|
||||
@@ -436,48 +436,6 @@ static int _dce_ipc_get_next_write_buff(struct dce_ipc_channel *ch)
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* dce_ipc_write_channel - Writes to an ivc channel.
|
||||
*
|
||||
* @ch : Pointer to the pertinent channel.
|
||||
* @data : Pointer to the data to be written.
|
||||
* @size : Size of the data to be written.
|
||||
*
|
||||
* Return : 0 if successful.
|
||||
*/
|
||||
static int _dce_ipc_write_channel(struct dce_ipc_channel *ch,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
struct dce_ipc_header *hdr;
|
||||
|
||||
/**
|
||||
* Add actual length information to the top
|
||||
* of the IVC frame
|
||||
*/
|
||||
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
if ((ch->flags & DCE_IPC_CHANNEL_MSG_HEADER) != 0U) {
|
||||
iosys_map_wr_field(&ch->obuff, 0, struct dce_ipc_header, length,
|
||||
size);
|
||||
iosys_map_incr(&ch->obuff, sizeof(*hdr));
|
||||
}
|
||||
|
||||
if (data && size > 0)
|
||||
iosys_map_memcpy_to(&ch->obuff, 0, data, size);
|
||||
#else
|
||||
if ((ch->flags & DCE_IPC_CHANNEL_MSG_HEADER) != 0U) {
|
||||
hdr = (struct dce_ipc_header *)ch->obuff;
|
||||
hdr->length = (uint32_t)size;
|
||||
ch->obuff = (void *)(hdr + 1U);
|
||||
}
|
||||
|
||||
if (data && size > 0)
|
||||
memcpy(ch->obuff, data, size);
|
||||
#endif
|
||||
|
||||
return dce_os_ivc_write_advance(&ch->d_ivc);
|
||||
}
|
||||
|
||||
/**
|
||||
* dce_ipc_send_message - Sends messages over ipc.
|
||||
*
|
||||
@@ -505,7 +463,7 @@ int dce_ipc_send_message(struct tegra_dce *d, u32 ch_type,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _dce_ipc_write_channel(ch, data, size);
|
||||
ret = dce_os_ivc_write_channel(ch, data, size);
|
||||
if (ret) {
|
||||
dce_os_err(ch->d, "Error writing to channel");
|
||||
goto out;
|
||||
@@ -540,47 +498,6 @@ static int _dce_ipc_get_next_read_buff(struct dce_ipc_channel *ch)
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* dce_ipc_read_channel - Writes to an ivc channel.
|
||||
*
|
||||
* @ch : Pointer to the pertinent channel.
|
||||
* @data : Pointer to the data to be read.
|
||||
* @size : Size of the data to be read.
|
||||
*
|
||||
* Return : 0 if successful.
|
||||
*/
|
||||
static int _dce_ipc_read_channel(struct dce_ipc_channel *ch,
|
||||
void *data, size_t size)
|
||||
{
|
||||
struct dce_ipc_header *hdr;
|
||||
|
||||
/**
|
||||
* Get actual length information from the top
|
||||
* of the IVC frame
|
||||
*/
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
if ((ch->flags & DCE_IPC_CHANNEL_MSG_HEADER) != 0U) {
|
||||
iosys_map_wr_field(&ch->ibuff, 0, struct dce_ipc_header, length,
|
||||
size);
|
||||
iosys_map_incr(&ch->ibuff, sizeof(*hdr));
|
||||
}
|
||||
|
||||
if (data && size > 0)
|
||||
iosys_map_memcpy_from(data, &ch->ibuff, 0, size);
|
||||
#else
|
||||
if ((ch->flags & DCE_IPC_CHANNEL_MSG_HEADER) != 0U) {
|
||||
hdr = (struct dce_ipc_header *)ch->ibuff;
|
||||
size = (size_t)(hdr->length);
|
||||
ch->ibuff = (void *)(hdr + 1U);
|
||||
}
|
||||
|
||||
if (data && size > 0)
|
||||
memcpy(data, ch->ibuff, size);
|
||||
#endif
|
||||
|
||||
return dce_os_ivc_read_advance(&ch->d_ivc);
|
||||
}
|
||||
|
||||
/**
|
||||
* dce_ipc_read_message - Reads messages over ipc.
|
||||
*
|
||||
@@ -607,7 +524,7 @@ int dce_ipc_read_message(struct tegra_dce *d, u32 ch_type,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _dce_ipc_read_channel(ch, data, size);
|
||||
ret = dce_os_ivc_read_channel(ch, data, size);
|
||||
if (ret) {
|
||||
dce_os_err(ch->d, "Error reading from channel");
|
||||
goto out;
|
||||
@@ -711,25 +628,22 @@ int dce_ipc_get_region_iova_info(struct tegra_dce *d, u64 *iova, u32 *size)
|
||||
}
|
||||
|
||||
/*
|
||||
* dce_ipc_handle_notification - Handles the notification from remote
|
||||
* dce_ipc_is_data_available - Check if IVC channel has new data
|
||||
* avaialble for reading.
|
||||
*
|
||||
* @d : Pointer to tegra_dce struct
|
||||
* @id : Channel Index
|
||||
*
|
||||
* Return : True if the worker thread needs to wake up
|
||||
* Return : true if the worker thread needs to wake up
|
||||
*/
|
||||
bool dce_ipc_is_data_available(struct tegra_dce *d, u32 ch_type)
|
||||
{
|
||||
bool ret = false;
|
||||
void *frame;
|
||||
int err = 0;
|
||||
struct dce_ipc_channel *ch = d->d_ipc.ch[ch_type];
|
||||
|
||||
dce_os_mutex_lock(&ch->lock);
|
||||
|
||||
err = dce_os_ivc_get_next_read_frame(&ch->d_ivc, &frame);
|
||||
if (err == 0)
|
||||
ret = true;
|
||||
ret = dce_os_ivc_is_data_available(ch);
|
||||
|
||||
dce_os_mutex_unlock(&ch->lock);
|
||||
|
||||
|
||||
191
drivers/platform/tegra/dce/dce-os-ivc.c
Normal file
191
drivers/platform/tegra/dce/dce-os-ivc.c
Normal file
@@ -0,0 +1,191 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <dce-ipc.h>
|
||||
#include <dce-os-ivc.h>
|
||||
#include <interface/dce-ipc-header.h>
|
||||
|
||||
/**
|
||||
* dce_os_ivc_write_channel - Writes to an ivc channel.
|
||||
*
|
||||
* @ch : Pointer to the pertinent channel.
|
||||
* @data : Pointer to the data to be written.
|
||||
* @size : Size of the data to be written.
|
||||
*
|
||||
* Return : 0 if successful.
|
||||
*/
|
||||
int dce_os_ivc_write_channel(struct dce_ipc_channel *ch,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
struct dce_ipc_header *hdr;
|
||||
|
||||
/**
|
||||
* Add actual length information to the top
|
||||
* of the IVC frame
|
||||
*/
|
||||
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
if ((ch->flags & DCE_IPC_CHANNEL_MSG_HEADER) != 0U) {
|
||||
iosys_map_wr_field(&ch->obuff, 0, struct dce_ipc_header, length,
|
||||
size);
|
||||
iosys_map_incr(&ch->obuff, sizeof(*hdr));
|
||||
}
|
||||
|
||||
if (data && size > 0)
|
||||
iosys_map_memcpy_to(&ch->obuff, 0, data, size);
|
||||
#else
|
||||
if ((ch->flags & DCE_IPC_CHANNEL_MSG_HEADER) != 0U) {
|
||||
hdr = (struct dce_ipc_header *)ch->obuff;
|
||||
hdr->length = (uint32_t)size;
|
||||
ch->obuff = (void *)(hdr + 1U);
|
||||
}
|
||||
|
||||
if (data && size > 0)
|
||||
memcpy(ch->obuff, data, size);
|
||||
#endif
|
||||
|
||||
return dce_os_ivc_write_advance(&ch->d_ivc);
|
||||
}
|
||||
|
||||
/**
|
||||
* dce_os_ivc_read_channel - Writes to an ivc channel.
|
||||
*
|
||||
* @ch : Pointer to the pertinent channel.
|
||||
* @data : Pointer to the data to be read.
|
||||
* @size : Size of the data to be read.
|
||||
*
|
||||
* Return : 0 if successful.
|
||||
*/
|
||||
int dce_os_ivc_read_channel(struct dce_ipc_channel *ch,
|
||||
void *data, size_t size)
|
||||
{
|
||||
struct dce_ipc_header *hdr;
|
||||
|
||||
/**
|
||||
* Get actual length information from the top
|
||||
* of the IVC frame
|
||||
*/
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
if ((ch->flags & DCE_IPC_CHANNEL_MSG_HEADER) != 0U) {
|
||||
iosys_map_wr_field(&ch->ibuff, 0, struct dce_ipc_header, length,
|
||||
size);
|
||||
iosys_map_incr(&ch->ibuff, sizeof(*hdr));
|
||||
}
|
||||
|
||||
if (data && size > 0)
|
||||
iosys_map_memcpy_from(data, &ch->ibuff, 0, size);
|
||||
#else
|
||||
if ((ch->flags & DCE_IPC_CHANNEL_MSG_HEADER) != 0U) {
|
||||
hdr = (struct dce_ipc_header *)ch->ibuff;
|
||||
size = (size_t)(hdr->length);
|
||||
ch->ibuff = (void *)(hdr + 1U);
|
||||
}
|
||||
|
||||
if (data && size > 0)
|
||||
memcpy(data, ch->ibuff, size);
|
||||
#endif
|
||||
|
||||
return dce_os_ivc_read_advance(&ch->d_ivc);
|
||||
}
|
||||
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
|
||||
int dce_os_ivc_get_next_write_frame(dce_os_ivc_t *ivc, struct iosys_map *ppframe)
|
||||
{
|
||||
int err = 0;
|
||||
struct iosys_map pframe;
|
||||
|
||||
err = tegra_ivc_write_get_next_frame(ivc, &pframe);
|
||||
if (err) {
|
||||
iosys_map_clear(&pframe);
|
||||
goto done;
|
||||
}
|
||||
|
||||
*ppframe = pframe;
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* dce_os_ivc_get_next_read_frame - Get next read frame.
|
||||
*
|
||||
* @ivc : Pointer to IVC struct
|
||||
* @ppFrame : Pointer to frame reference.
|
||||
*
|
||||
* Return : 0 if successful.
|
||||
*/
|
||||
int dce_os_ivc_get_next_read_frame(dce_os_ivc_t *ivc, struct iosys_map *ppframe)
|
||||
{
|
||||
int err = 0;
|
||||
struct iosys_map pframe;
|
||||
|
||||
err = tegra_ivc_read_get_next_frame(ivc, &pframe);
|
||||
if (err) {
|
||||
iosys_map_clear(&pframe);
|
||||
goto done;
|
||||
}
|
||||
|
||||
*ppframe = pframe;
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
#else /* NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP */
|
||||
|
||||
int dce_os_ivc_get_next_write_frame(dce_os_ivc_t *ivc, void **ppframe)
|
||||
{
|
||||
int err = 0;
|
||||
void *pframe = NULL;
|
||||
|
||||
pframe = tegra_ivc_write_get_next_frame(ivc);
|
||||
if (IS_ERR(pframe)) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*ppframe = pframe;
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int dce_os_ivc_get_next_read_frame(dce_os_ivc_t *ivc, void **ppframe)
|
||||
{
|
||||
int err = 0;
|
||||
void *pframe = NULL;
|
||||
|
||||
pframe = tegra_ivc_read_get_next_frame(ivc);
|
||||
if (IS_ERR(pframe)) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*ppframe = pframe;
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP */
|
||||
|
||||
bool dce_os_ivc_is_data_available(struct dce_ipc_channel *ch)
|
||||
{
|
||||
bool ret = false;
|
||||
int err = 0;
|
||||
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
struct iosys_map frame;
|
||||
#else
|
||||
void *frame;
|
||||
#endif
|
||||
|
||||
err = dce_os_ivc_get_next_read_frame(&ch->d_ivc, &frame);
|
||||
if (err == 0)
|
||||
ret = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <interface/dce-ipc-state.h>
|
||||
#include <linux/platform/tegra/dce/dce-client-ipc.h>
|
||||
|
||||
struct tegra_dce;
|
||||
|
||||
#define DCE_IPC_CHANNEL_TYPE_ADMIN 0U
|
||||
#define DCE_IPC_CHANNEL_TYPE_CPU_CLIENTS 1U
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <soc/tegra/ivc.h>
|
||||
#include <nvidia/conftest.h>
|
||||
|
||||
struct dce_ipc_channel;
|
||||
|
||||
typedef struct tegra_ivc dce_os_ivc_t;
|
||||
|
||||
/*
|
||||
@@ -56,78 +58,12 @@ static inline int dce_os_ivc_notified(dce_os_ivc_t *ivc)
|
||||
return tegra_ivc_notified(ivc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return negative err code on Failure, or 0 on Success.
|
||||
* This function will populate address of next write frame
|
||||
* info functions ppframe input argument.
|
||||
*/
|
||||
static inline int dce_os_ivc_get_next_write_frame(dce_os_ivc_t *ivc, void **ppframe)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
struct iosys_map pframe;
|
||||
|
||||
err = tegra_ivc_write_get_next_frame(ivc, &pframe);
|
||||
if (err) {
|
||||
iosys_map_clear(&pframe);
|
||||
goto done;
|
||||
}
|
||||
#else
|
||||
void *pframe = NULL;
|
||||
|
||||
pframe = tegra_ivc_write_get_next_frame(ivc);
|
||||
if (IS_ERR(pframe)) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
*ppframe = pframe;
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Returns 0, or a negative error value if failed. */
|
||||
static inline int dce_os_ivc_write_advance(dce_os_ivc_t *ivc)
|
||||
{
|
||||
return tegra_ivc_write_advance(ivc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return negative err code on Failure, or 0 on Success.
|
||||
* This function will populate address of next read frame
|
||||
* info functions ppframe input argument.
|
||||
*/
|
||||
static inline int dce_os_ivc_get_next_read_frame(dce_os_ivc_t *ivc, void **ppframe)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
struct iosys_map pframe;
|
||||
|
||||
err = tegra_ivc_read_get_next_frame(ivc, &pframe);
|
||||
if (err) {
|
||||
iosys_map_clear(&pframe);
|
||||
goto done;
|
||||
}
|
||||
#else
|
||||
void *pframe = NULL;
|
||||
|
||||
pframe = tegra_ivc_read_get_next_frame(ivc);
|
||||
if (IS_ERR(pframe)) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
*ppframe = pframe;
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Returns 0, or a negative error value if failed. */
|
||||
static inline int dce_os_ivc_read_advance(dce_os_ivc_t *ivc)
|
||||
{
|
||||
@@ -145,4 +81,47 @@ static inline uint32_t dce_os_ivc_total_queue_size(uint32_t size)
|
||||
return tegra_ivc_total_queue_size(size);
|
||||
}
|
||||
|
||||
int dce_os_ivc_write_channel(struct dce_ipc_channel *ch,
|
||||
const void *data, size_t size);
|
||||
|
||||
int dce_os_ivc_read_channel(struct dce_ipc_channel *ch,
|
||||
void *data, size_t size);
|
||||
|
||||
/**
|
||||
* dce_os_ivc_is_data_available - Check if data is avaialble for reading.
|
||||
*
|
||||
* @ch : Pointer to DCE IPC channel struct
|
||||
*
|
||||
* Return : true if success and data is available, false otherwise
|
||||
*/
|
||||
bool dce_os_ivc_is_data_available(struct dce_ipc_channel *ch);
|
||||
|
||||
/**
|
||||
* dce_os_ivc_get_next_write_frame - Get next write frame.
|
||||
*
|
||||
* @ivc : Pointer to IVC struct
|
||||
* @ppFrame : Pointer to frame reference.
|
||||
*
|
||||
* Return : 0 if successful.
|
||||
*/
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
int dce_os_ivc_get_next_write_frame(dce_os_ivc_t *ivc, struct iosys_map *ppframe);
|
||||
#else /* NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP */
|
||||
int dce_os_ivc_get_next_write_frame(dce_os_ivc_t *ivc, void **ppframe);
|
||||
#endif /* NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP */
|
||||
|
||||
/**
|
||||
* dce_os_ivc_get_next_read_frame - Get next read frame.
|
||||
*
|
||||
* @ivc : Pointer to IVC struct
|
||||
* @ppFrame : Pointer to frame reference.
|
||||
*
|
||||
* Return : 0 if successful.
|
||||
*/
|
||||
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP) /* Linux v6.2 */
|
||||
int dce_os_ivc_get_next_read_frame(dce_os_ivc_t *ivc, struct iosys_map *ppframe);
|
||||
#else /* NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP */
|
||||
int dce_os_ivc_get_next_read_frame(dce_os_ivc_t *ivc, void **ppframe);
|
||||
#endif /* NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP */
|
||||
|
||||
#endif /* DCE_OS_IVC_H */
|
||||
|
||||
Reference in New Issue
Block a user