* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "securec.h"
#include "pbl/pbl_uda.h"
#include "pbl/pbl_feature_loader.h"
#include "dms/dms_cmd_def.h"
#include "dms_define.h"
#include "ascend_platform.h"
#include "ascend_dev_num.h"
#include "devdrv_user_common.h"
#include "ka_task_pub.h"
#include "ka_base_pub.h"
#include "dms_sdk_ex_version.h"
#ifndef STATIC_SKIP
#define STATIC static
#else
#define STATIC
#endif
#define DMS_SDK_EX_VER_NOTIFIER "sdk_ex_ver"
#define DMS_OP_GET_SDK_EX_VERSION 0
#define DMS_OP_SET_SDK_EX_VERSION 1
#define DMS_OP_CLEAR_SDK_EX_VERSION 2
static ka_rwlock_t g_sdk_ex_ver_lock;
char sdk_pf_ex_version[ASCEND_PDEV_MAX_NUM][DMS_SDK_EX_VERSION_LEN_MAX + 1];
char sdk_vf_ex_version[ASCEND_VDEV_MAX_NUM][DMS_SDK_EX_VERSION_LEN_MAX + 1];
STATIC int dms_get_sdk_ex_ver_pointer(unsigned int udevid, char **p_ver)
{
int offset = 0;
if (uda_is_phy_dev(udevid)) {
offset = udevid;
if ((offset >= ASCEND_PDEV_MAX_NUM) || (offset < 0)) {
dms_err("Invalid parameter. (udevid=%u; offset=%d)", udevid, offset);
return -EINVAL;
}
*p_ver = sdk_pf_ex_version[offset];
} else {
offset = udevid - ASCEND_VDEV_ID_START;
if ((offset >= ASCEND_VDEV_MAX_NUM) || (offset < 0)) {
dms_err("Invalid parameter. (udevid=%u; offset=%d)", udevid, offset);
return -EINVAL;
}
*p_ver = sdk_vf_ex_version[offset];
}
return 0;
}
STATIC int dms_operate_sdk_ex_version(int opcode, unsigned int udevid, char *buff, unsigned int *len)
{
int ret;
char *p_ver = NULL;
ret = dms_get_sdk_ex_ver_pointer(udevid, &p_ver);
if ((ret != 0) || (p_ver == NULL)) {
dms_err("Invalid parameter. (udevid=%u)", udevid);
return -EINVAL;
}
if (opcode == DMS_OP_GET_SDK_EX_VERSION) {
ka_task_read_lock(&g_sdk_ex_ver_lock);
*len = (u32)ka_base_strnlen(p_ver, DMS_SDK_EX_VERSION_LEN_MAX);
if (*len != 0) {
ret = memcpy_s(buff, DMS_SDK_EX_VERSION_LEN_MAX, p_ver, *len);
if (ret != 0) {
dms_err("Failed to invoke memcpy_s. (ret=%d)\n", ret);
ret = -ENOMEM;
}
} else {
ret = 0;
}
ka_task_read_unlock(&g_sdk_ex_ver_lock);
} else if (opcode == DMS_OP_SET_SDK_EX_VERSION) {
ka_task_write_lock(&g_sdk_ex_ver_lock);
ret = memcpy_s(p_ver, DMS_SDK_EX_VERSION_LEN_MAX, buff, *len);
if (ret != 0) {
dms_err("Failed to invoke memcpy_s. (ret=%d)", ret);
ret = -ENOMEM;
} else {
p_ver[*len] = '\0';
dms_event("Set SDK Ex success. (udevid=%u; ver=%s)\n", udevid, p_ver);
}
ka_task_write_unlock(&g_sdk_ex_ver_lock);
} else if (opcode == DMS_OP_CLEAR_SDK_EX_VERSION) {
ka_task_write_lock(&g_sdk_ex_ver_lock);
ret = memset_s(p_ver, DMS_SDK_EX_VERSION_LEN_MAX + 1, 0, DMS_SDK_EX_VERSION_LEN_MAX + 1);
if (ret != 0) {
dms_warn("Can not clear sdk ex version. (udevid=%u)", udevid);
}
ka_task_write_unlock(&g_sdk_ex_ver_lock);
ret = 0;
} else {
ret = -EINVAL;
}
return ret;
}
int dms_get_sdk_ex_version(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
int ret;
unsigned int udevid, vf_id, soc_type;
struct dms_hal_device_info_stru *cfg_in = NULL;
struct dms_hal_device_info_stru *cfg_out = NULL;
if ((feature == NULL) ||
(in == NULL) || (in_len != (DMS_HAL_DEV_INFO_HEAD_LEN + DMS_SDK_EX_VERSION_LEN_MAX)) ||
(out == NULL) || (out_len != (DMS_HAL_DEV_INFO_HEAD_LEN + DMS_SDK_EX_VERSION_LEN_MAX))) {
dms_err("Invalid parameter. (feature=%s; in=%s; in_len=%u; out=%s; out_len=%u)\n",
(feature == NULL) ? "NULL" : "OK",
(in == NULL) ? "NULL" : "OK", in_len, (out == NULL) ? "NULL" : "OK", out_len);
return -EINVAL;
}
cfg_in = (struct dms_hal_device_info_stru *)in;
if (cfg_in->buff_size != DMS_SDK_EX_VERSION_LEN_MAX) {
dms_err("Invalid parameter. (buff_size=%u; buff_max_len=%u)\n", cfg_in->buff_size, DMS_SDK_EX_VERSION_LEN_MAX);
return -EINVAL;
}
cfg_out = (struct dms_hal_device_info_stru *)out;
ret = uda_devid_to_phy_devid(cfg_in->dev_id, &udevid, &vf_id);
if (ret != 0) {
dms_err("Failed to convert the logical_id to the physical_id. (logical_id=%u; ret=%d)\n", cfg_in->dev_id, ret);
return -EINVAL;
}
soc_type = uda_get_chip_type(udevid);
if ((soc_type == HISI_CLOUD_V1) || (soc_type == HISI_MINI_V2) || (soc_type == HISI_MINI_V3)) {
if ((vf_id != 0) || !uda_is_phy_dev(udevid)) {
return -EOPNOTSUPP;
}
}
ret = dms_operate_sdk_ex_version(DMS_OP_GET_SDK_EX_VERSION, udevid, cfg_out->payload, &cfg_out->buff_size);
if (ret != 0) {
dms_err("Failed to get SDK Ex version. (udevid=%u; ret=%d)\n", udevid, ret);
}
return ret;
}
int dms_set_sdk_ex_version(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
int ret;
unsigned int udevid, vf_id, soc_type;
struct dms_hal_device_info_stru *cfg_in = NULL;
if ((feature == NULL) ||
(in == NULL) || (in_len < DMS_HAL_DEV_INFO_HEAD_LEN) ||
(out == NULL) || (out_len < DMS_HAL_DEV_INFO_HEAD_LEN)) {
dms_err("Invalid parameter. (feature=%s; in=%s; in_len=%u; out=%s; out_len=%u)\n",
(feature == NULL) ? "NULL" : "OK",
(in == NULL) ? "NULL" : "OK", in_len, (out == NULL) ? "NULL" : "OK", out_len);
return -EINVAL;
}
cfg_in = (struct dms_hal_device_info_stru *)in;
if ((cfg_in->buff_size == 0) || (cfg_in->buff_size > DMS_SDK_EX_VERSION_LEN_MAX) ||
(in_len < (DMS_HAL_DEV_INFO_HEAD_LEN + cfg_in->buff_size))) {
dms_err("Invalid parameter. (in_len=%u; buff_size=%u)\n", in_len, cfg_in->buff_size);
return -EINVAL;
}
ret = uda_devid_to_phy_devid(cfg_in->dev_id, &udevid, &vf_id);
if (ret != 0) {
dms_err("Failed to convert the logical_id to the physical_id. (logical_id=%u; ret=%d)\n", cfg_in->dev_id, ret);
return -EINVAL;
}
soc_type = uda_get_chip_type(udevid);
if ((soc_type == HISI_CLOUD_V1) || (soc_type == HISI_MINI_V2) || (soc_type == HISI_MINI_V3)) {
if ((vf_id != 0) || !uda_is_phy_dev(udevid)) {
return -EOPNOTSUPP;
}
}
ret = dms_operate_sdk_ex_version(DMS_OP_SET_SDK_EX_VERSION, udevid, cfg_in->payload, &cfg_in->buff_size);
if (ret != 0) {
dms_err("Failed to set SDK Ex version. (udevid=%u; ret=%d)\n", udevid, ret);
}
return ret;
}
STATIC int dms_sdk_ex_ver_uda_notifier_func(u32 udevid, enum uda_notified_action action)
{
if ((action == UDA_INIT) || (action == UDA_UNINIT)) {
dms_operate_sdk_ex_version(DMS_OP_CLEAR_SDK_EX_VERSION, udevid, NULL, NULL);
}
dms_info("notifier action. (udevid=%u; action=%d)\n", udevid, action);
return 0;
}
int dms_sdK_ex_ver_init(void)
{
int ret;
struct uda_dev_type type = { 0 };
ka_task_rwlock_init(&g_sdk_ex_ver_lock);
uda_davinci_local_real_entity_type_pack(&type);
ret = uda_real_virtual_notifier_register(DMS_SDK_EX_VER_NOTIFIER, &type, UDA_PRI2,
dms_sdk_ex_ver_uda_notifier_func);
if (ret != 0) {
dms_err("Device register local real virtual type failed. (ret=%d)\n", ret);
return ret;
}
dms_info("dms sdk ex ver init.\n");
return ret;
}
DECLAER_FEATURE_AUTO_INIT(dms_sdK_ex_ver_init, FEATURE_LOADER_STAGE_5);
void dms_sdK_ex_ver_exit(void)
{
struct uda_dev_type type = { 0 };
uda_davinci_local_real_entity_type_pack(&type);
(void)uda_real_virtual_notifier_unregister(DMS_SDK_EX_VER_NOTIFIER, &type);
dms_info("dms sdk ex ver exit.\n");
}
DECLAER_FEATURE_AUTO_UNINIT(dms_sdK_ex_ver_exit, FEATURE_LOADER_STAGE_5);