* 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 "pbl/pbl_feature_loader.h"
#include "pbl/pbl_runenv_config.h"
#include "pbl/pbl_urd_main_cmd_def.h"
#include "pbl/pbl_urd_sub_cmd_def.h"
#include "urd_acc_ctrl.h"
#include "ascend_dev_num.h"
#include "msg_chan_main.h"
int ascend_msg_chan_init_urd(void);
void ascend_msg_chan_uninit_urd(void);
STATIC int devdrv_get_device_boot_status_urd(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
u32 phys_id, boot_status;
int ret;
if ((in == NULL) || (in_len != sizeof(u32))) {
devdrv_err("Input argument is null, or in_len is wrong. (in_len=%u)\n", in_len);
return -EINVAL;
}
if ((out == NULL) || (out_len < sizeof(u32))) {
devdrv_err("Output argument is null, or out_len is wrong. (out_len=%u)\n", out_len);
return -EINVAL;
}
phys_id = *(u32 *)in;
if (phys_id >= ASCEND_DEV_MAX_NUM) {
devdrv_err("phys_id %d is invalid\n", phys_id);
return -EINVAL;
}
if (run_in_normal_docker()) {
if (!uda_task_can_access_udevid_inherit(ka_task_get_current(), phys_id)) {
devdrv_err("device phyid %u is not belong to current docker\n", phys_id);
return -EFAULT;
}
}
ret = devdrv_get_device_boot_status(phys_id, &boot_status);
if (ret != 0) {
#ifndef EMU_ST
devdrv_warn("cannot get device boot status, ret(%d), dev_id(%u).\n", ret, phys_id);
return ret;
#endif
}
ret = memcpy_s((void *)out, out_len, (void *)&boot_status, sizeof(u32));
if (ret != 0) {
#ifndef EMU_ST
devdrv_err("Call memcpy_s failed. (ret=%d)\n", ret);
return -EINVAL;
#endif
}
devdrv_debug("read boot status success.(devid=%u, status=%u)\n", phys_id, boot_status);
return 0;
}
STATIC int devdrv_get_p2p_attr_urd(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
struct urd_p2p_attr *p2p_attr = NULL;
struct devdrv_base_comm_p2p_attr base_attr;
u32 phys_id = 0;
int ret;
if ((in == NULL) || (in_len != sizeof(struct urd_p2p_attr))) {
devdrv_err("Input argument is null, or in_len is wrong. (in_len=%u)\n", in_len);
return -EINVAL;
}
if ((out == NULL) || (out_len < sizeof(struct urd_p2p_attr))) {
devdrv_err("Output argument is null, or out_len is wrong. (out_len=%u)\n", out_len);
return -EINVAL;
}
p2p_attr = (struct urd_p2p_attr *)in;
if (uda_devid_to_udevid(p2p_attr->dev_id, &phys_id) != 0) {
devdrv_err("Can't transform virt id. (devid=%u) \n", p2p_attr->dev_id);
return -EFAULT;
}
base_attr.devid = phys_id;
base_attr.peer_dev_id = p2p_attr->peer_dev_id;
base_attr.pid = ka_task_get_current_tgid();
base_attr.status = &p2p_attr->status;
base_attr.capability = &p2p_attr->capability;
base_attr.op = p2p_attr->op;
base_attr.type = p2p_attr->type;
ret = devdrv_p2p_attr_op(&base_attr);
if (ret == -EOPNOTSUPP) {
return ret;
} else if (ret != 0) {
devdrv_err("p2p_attr_op fail. (devid=%u; ret=%d)\n", phys_id, ret);
return ret;
}
ret = memcpy_s((void *)out, out_len, p2p_attr, sizeof(struct urd_p2p_attr));
if (ret) {
#ifndef EMU_ST
devdrv_err("copy_to_user_safe failed.\n");
return -EINVAL;
#endif
}
devdrv_debug("P2P attr. (op=%u; devid=%u; peerid=%u; pid=%d; status=%u; cap=%llx)\n",
p2p_attr->op, p2p_attr->dev_id, p2p_attr->peer_dev_id, ka_task_get_current_tgid(), p2p_attr->status, p2p_attr->capability);
return ret;
}
STATIC int devdrv_get_device_info_urd(void *feature, char *in, u32 in_len, char *out, u32 out_len)
{
struct urd_vender_id_info device_id_info = {0};
struct devdrv_base_device_info device_info = {0};
unsigned int dev_id, logic_devid, vfid;
int ret;
if ((in == NULL) || (in_len != sizeof(u32))) {
devdrv_err("Input argument is null, or in_len is wrong. (in_len=%u)\n", in_len);
return -EINVAL;
}
if ((out == NULL) || (out_len < sizeof(struct urd_vender_id_info))) {
devdrv_err("Output argument is null, or out_len is wrong. (out_len=%u)\n", out_len);
return -EINVAL;
}
logic_devid = *(u32 *)in;
ret = uda_devid_to_phy_devid(logic_devid, &dev_id, &vfid);
if (ret != 0) {
devdrv_err("can't transform logic_devid %u, ret=%d\n", logic_devid, ret);
return ret;
}
ret = devdrv_get_device_info(dev_id, &device_info);
if (ret == -EOPNOTSUPP) {
devdrv_warn("Not support get dev info. (dev_id=%u)\n", dev_id);
return ret;
} else if (ret != 0) {
devdrv_err("devdrv_get_pcie_id failed.\n");
return ret;
}
device_id_info.venderid = device_info.venderid;
device_id_info.subvenderid = device_info.subvenderid;
device_id_info.deviceid = device_info.deviceid;
device_id_info.subdeviceid = device_info.subdeviceid;
device_id_info.bus = device_info.bus;
device_id_info.device = device_info.device;
device_id_info.fn = device_info.fn;
ret = memcpy_s((void *)out, out_len, &device_id_info, sizeof(struct urd_vender_id_info));
if (ret) {
devdrv_err("copy_to_user_safe failed.\n");
#ifndef EMU_ST
return -EINVAL;
#endif
}
devdrv_debug("Dev info. (vender=%u; subv=%u; devid=%u; subd=%d; bus=%#x; dev=%#x; fn=%#x)\n",
device_id_info.venderid, device_id_info.subvenderid, device_id_info.deviceid, device_id_info.subdeviceid,
device_id_info.bus, device_id_info.device, device_id_info.fn);
return 0;
}
int init_module_ASCEND_MSG_CHAN_CMD_NAME(void);
int exit_module_ASCEND_MSG_CHAN_CMD_NAME(void);
#define ASCEND_MSG_CHAN_CMD_NAME "ASCEND_MSG_CHAN"
BEGIN_DMS_MODULE_DECLARATION(ASCEND_MSG_CHAN_CMD_NAME)
BEGIN_FEATURE_COMMAND()
ADD_FEATURE_COMMAND(ASCEND_MSG_CHAN_CMD_NAME,
DMS_MAIN_CMD_BASIC,
DMS_SUBCMD_GET_DEV_BOOT_STATUS,
NULL,
NULL,
DMS_SUPPORT_ALL,
devdrv_get_device_boot_status_urd)
ADD_FEATURE_COMMAND(ASCEND_MSG_CHAN_CMD_NAME,
DMS_MAIN_CMD_BASIC,
DMS_SUBCMD_GET_DEV_PROBE_LIST,
NULL,
NULL,
DMS_ACC_ALL | DMS_ENV_NOT_NORMAL_DOCKER,
devdrv_get_device_probe_list_urd)
ADD_FEATURE_COMMAND(ASCEND_MSG_CHAN_CMD_NAME,
DMS_MAIN_CMD_BASIC,
DMS_SUBCMD_DEV_P2P_ATTR,
NULL,
NULL,
DMS_ACC_ALL | DMS_ENV_ALL,
devdrv_get_p2p_attr_urd)
ADD_FEATURE_COMMAND(ASCEND_MSG_CHAN_CMD_NAME,
DMS_MAIN_CMD_BASIC,
DMS_SUBCMD_GET_PCIE_INFO,
NULL,
NULL,
DMS_SUPPORT_ALL,
devdrv_get_device_info_urd)
ADD_FEATURE_COMMAND(ASCEND_MSG_CHAN_CMD_NAME,
DMS_MAIN_CMD_BASIC,
DMS_SUBCMD_GET_DEV_PROBE_NUM,
NULL,
NULL,
DMS_SUPPORT_ALL,
devdrv_get_device_probe_num_urd)
ADD_FEATURE_COMMAND(ASCEND_MSG_CHAN_CMD_NAME,
DMS_MAIN_CMD_BASIC,
DMS_SUBCMD_GET_ALL_DEV_LIST,
NULL,
NULL,
DMS_SUPPORT_ALL,
devdrv_get_device_probe_list_urd)
ADD_FEATURE_COMMAND(ASCEND_MSG_CHAN_CMD_NAME,
DMS_MAIN_CMD_BASIC,
DMS_SUBCMD_GET_CONNECT_TYPE,
NULL,
NULL,
DMS_SUPPORT_ALL_USER,
devdrv_get_connect_type_urd)
ADD_FEATURE_COMMAND(ASCEND_MSG_CHAN_CMD_NAME,
DMS_MAIN_CMD_BASIC,
DMS_SUBCMD_GET_TOKEN_VAL,
NULL,
NULL,
DMS_SUPPORT_ALL,
devdrv_get_token_val_urd)
END_FEATURE_COMMAND()
END_MODULE_DECLARATION()
int ascend_msg_chan_init_urd(void)
{
CALL_INIT_MODULE(ASCEND_MSG_CHAN_CMD_NAME);
devdrv_info("Register urd feature finish.\n");
return 0;
}
void ascend_msg_chan_uninit_urd(void)
{
CALL_EXIT_MODULE(ASCEND_MSG_CHAN_CMD_NAME);
devdrv_info("Unregister urd feature finish.\n");
return;
}
DECLAER_FEATURE_AUTO_INIT(ascend_msg_chan_init_urd, FEATURE_LOADER_STAGE_5);
DECLAER_FEATURE_AUTO_UNINIT(ascend_msg_chan_uninit_urd, FEATURE_LOADER_STAGE_5);