Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "ccu_channel_mgr_v1.h"
12 :
13 : #include <vector>
14 : #include "orion_adapter_hccp.h"
15 : #include "hccp_tlv_hdc_manager.h"
16 :
17 : namespace Hccl {
18 :
19 : constexpr uint32_t CCU_V1_CHANNEL_DEFAULT_JETTY_NUM = 1;
20 :
21 24 : CcuChannelMgrV1::CcuChannelMgrV1(const int32_t devLogicId, const uint8_t dieId, const uint32_t devPhyId)
22 24 : : CcuChannelMgr(devLogicId, dieId, devPhyId), jettyCtxMgr(devLogicId, dieId, devPhyId)
23 : {
24 24 : }
25 :
26 28 : static HcclResult FindFreeChannelId(std::vector<ChannelResInfo> &channelResInfos,
27 : uint32_t &channelId)
28 : {
29 : // ccu v1每次都分配新的channel与jettyCtx
30 : // 故直接选择首个可用channel即可
31 28 : const uint32_t channelNum = channelResInfos.size();
32 35 : for (uint32_t i = 0; i < channelNum; i++) {
33 35 : if (!channelResInfos[i].allocated) {
34 28 : channelId = i;
35 28 : return HcclResult::HCCL_SUCCESS;
36 : }
37 : }
38 0 : return HcclResult::HCCL_E_UNAVAIL;
39 : }
40 :
41 28 : HcclResult CcuChannelMgrV1::Alloc(const ChannelPara &channelPara,
42 : std::vector<ChannelInfo> &channelInfos)
43 : {
44 28 : const uint32_t feId = channelPara.feId;
45 28 : uint32_t jettyNum = channelPara.jettyNum;
46 28 : if (jettyNum == 0) {
47 24 : jettyNum = CCU_V1_CHANNEL_DEFAULT_JETTY_NUM;
48 72 : HCCL_INFO("[CcuJettyCtxMgrV1][%s] jettyNum is 0, reset to default[%u], "
49 : "feId[%u], devLogicId[%d], dieId[%u].", __func__, jettyNum, feId, devLogicId, dieId);
50 : }
51 :
52 28 : std::lock_guard<std::mutex> lock(innerMutex);
53 28 : uint32_t channelId = 0;
54 28 : auto ret = FindFreeChannelId(channelResInfos, channelId);
55 28 : CHK_PRT_RET(ret != HcclResult::HCCL_SUCCESS,
56 : HCCL_WARNING("[CcuChannelMgrV1][%s] failed to find free channel, channel strategy[%zu], "
57 : "feId[%u], devLogicId[%d], dieId[%u].", __func__, channelResInfos.size(),
58 : feId, devLogicId, dieId),
59 : ret);
60 :
61 28 : ChannelInfo channelInfo = {};
62 28 : ret = jettyCtxMgr.Alloc(feId, jettyNum, channelPara.sqSize,
63 : channelInfo.jettyInfos);
64 28 : CHK_PRT_RET(ret != HcclResult::HCCL_SUCCESS,
65 : HCCL_WARNING("[CcuChannelMgrV1][%s] failed to allocate jetty contexts to channelId[%u], "
66 : "feId[%u], devLogicId[%d], dieId[%u].", __func__, channelId, feId, devLogicId, dieId),
67 : ret);
68 :
69 28 : channelInfo.channelId = channelId;
70 28 : channelInfo.dieId = dieId;
71 28 : channelResInfos[channelId].feId = feId;
72 28 : channelResInfos[channelId].channelInfo = channelInfo;
73 28 : channelResInfos[channelId].allocated = true;
74 28 : DumpChannelResInfo(feId, channelInfo);
75 :
76 28 : channelInfos.clear(); // ccu v1每次仅分配1个channel,不同channel不复用jettyCtx
77 28 : channelInfos.emplace_back(std::move(channelInfo));
78 28 : return ret;
79 28 : }
80 :
81 26 : static ChannelDataV1 BuildChannelDataV1(const ChannelCfg &cfg, const uint32_t feId, const uint8_t dieId,
82 : const uint16_t startTaJettyId)
83 : {
84 26 : ChannelDataV1 data = {};
85 26 : (void)memcpy_s(&data.eidRaw[0], URMA_EID_LEN, &cfg.remoteEid, URMA_EID_LEN);
86 :
87 26 : data.vtpLow = cfg.tpn & MASK_VTP_LOW;
88 26 : data.vtpHigh = ((cfg.tpn & MASK_VTP) >> SHIFT_16BITS) & MASK_VTP_HIGH;
89 :
90 26 : data.srcPfeId = static_cast<uint16_t>(feId);
91 :
92 26 : data.startJettyIdLow = startTaJettyId & MASK_START_JETTY_ID_LOW;
93 26 : data.startJettyIdHigh = (startTaJettyId >> SHIFT_4BITS) & MASK_START_JETTY_ID_HIGH;
94 :
95 : // 写入硬件减 1,cfgs的数量一定小于jetty规格数,不会超过uint8_t范围
96 26 : uint8_t jettyNum = static_cast<uint8_t>(cfg.jettyCfgs.size()) - 1;
97 26 : data.jettyNumLow = jettyNum & MASK_JETTY_NUM_LOW;
98 26 : data.jettyNumHigh = (jettyNum >> SHIFT_4BITS) & MASK_JETTY_NUM_HIGH;
99 :
100 26 : data.ioDieId = static_cast<uint16_t>(dieId);
101 :
102 26 : data.dstTokenIdLow = cfg.memTokenId & MASK_TOKEN_ID_LOW;
103 26 : data.dstTokenIdHigh = (cfg.memTokenId >> SHIFT_12BITS) & MASK_TOKEN_ID_HIGH;
104 :
105 26 : data.dstTokenValueLow = cfg.memTokenValue & MASK_TOKEN_VALUE_LOW;
106 26 : data.dstTokenValueMiddle = (cfg.memTokenValue >> SHIFT_8BITS) & MASK_TOKEN_VALUE_MID;
107 26 : data.dstTokenValueHigh = (cfg.memTokenValue >> SHIFT_24BITS) & MASK_TOKEN_VALUE_HIGH;
108 :
109 26 : uint64_t dstVa = (cfg.remoteCcuVa >> REMOTE_CCU_VA_RIGHT_SHIFT_NUM);
110 26 : data.dstVaLow = dstVa & MASK_VA_LOW;
111 26 : data.dstVaMiddle = (dstVa >> SHIFT_8BITS) & MASK_VA_MID;
112 26 : data.dstVaHigh = (dstVa >> SHIFT_24BITS) & MASK_VA_HIGH;
113 26 : data.dstVaHigher = (dstVa >> SHIFT_40BITS) & MASK_VA_HIGHER;
114 26 : data.dstTokenValueValid = TOKEN_VALUE_VALID;
115 26 : return data;
116 : }
117 :
118 28 : static void DumpChannelDataV1(const struct ChannelDataV1 &data)
119 : {
120 28 : if (IsEidEmpty(data.eidRaw)) {
121 26 : return;
122 : }
123 2 : std::string dstEidInfo = "eidRaw: ";
124 32 : for (uint32_t i = 0; i < URMA_EID_LEN - 1; i++) {
125 30 : dstEidInfo += StringFormat("0x%02x, ", data.eidRaw[i]);
126 : }
127 2 : dstEidInfo += StringFormat("0x%02x", data.eidRaw[URMA_EID_LEN - 1]);
128 6 : HCCL_INFO(dstEidInfo.c_str());
129 :
130 6 : HCCL_INFO("vtpLow: 0x%04x, vtpHigh: 0x%04x, srcPfeId: 0x%04x, "
131 : "startJettyIdLow: 0x%04x, startJettyIdHigh: 0x%04x, "
132 : "JettyNumLow: 0x%04x, JettyNumHigh: 0x%04x, ioDieId: 0x%04x, ",
133 : data.vtpLow, data.vtpHigh, data.srcPfeId, data.startJettyIdLow,
134 : data.startJettyIdHigh, data.jettyNumLow, data.jettyNumHigh,
135 : data.ioDieId);
136 :
137 6 : HCCL_INFO("dstVaLow: 0x%04x, dstVaMiddle: 0x%04x, "
138 : "dstVaHigh: 0x%04x, dstVaHigher: 0x%04x, dstTokenValueValid: 0x%04x",
139 : data.dstVaLow, data.dstVaMiddle, data.dstVaHigh, data.dstVaHigher,
140 : data.dstTokenValueValid);
141 2 : }
142 :
143 28 : static void ConfigChannelDataV1(const int32_t devLogicId, const uint32_t devPhyId, const uint8_t dieId,
144 : const uint32_t channelId, const ChannelDataV1 &channelData)
145 : {
146 28 : auto tlvHandle = HccpTlvHdcManager::GetInstance().GetTlvHandle(devLogicId);
147 28 : CHECK_NULLPTR(tlvHandle, StringFormat("[CcuChannelMgrV1][%s] tlvHandle is nullptr, devLogicId[%d]", __func__, devLogicId));
148 :
149 28 : struct CustomChannelInfoIn inBuff;
150 28 : struct CustomChannelInfoOut outBuff;
151 :
152 28 : constexpr uint32_t dataArraySize = 1; // 每次配置1个Channel
153 28 : inBuff.op = CcuOpcodeType::CCU_U_OP_SET_CHANNEL;
154 28 : inBuff.data.dataInfo.udieIdx = dieId;
155 28 : inBuff.data.dataInfo.dataArraySize = dataArraySize;
156 28 : inBuff.data.dataInfo.dataLen = sizeof(struct ChannelDataV1) * dataArraySize;
157 28 : inBuff.offsetStartIdx = channelId;
158 :
159 84 : HCCL_INFO("[CcuChannelMgrV1][%s] set data to ccu driver, devPhyId[%u], "
160 : "ioDie[%u], idx[%u], size[%u].", __func__, devPhyId, dieId, channelId,
161 : sizeof(struct ChannelDataV1));
162 28 : DumpChannelDataV1(channelData);
163 :
164 28 : (void)memcpy_s(inBuff.data.dataInfo.dataArray, sizeof(struct ChannelDataV1), &channelData,
165 : sizeof(struct ChannelDataV1));
166 28 : HrtRaTlvRequestForCustomChannel(tlvHandle, MSG_TYPE_CCU_DISPATCH_CMD, static_cast<void *>(&inBuff), static_cast<void *>(&outBuff));
167 28 : }
168 :
169 29 : HcclResult CcuChannelMgrV1::Config(const ChannelCfg &channelCfg)
170 : {
171 29 : std::lock_guard<std::mutex> lock(innerMutex);
172 29 : const uint32_t channelId = channelCfg.channelId;
173 29 : if (!CheckIfChannelAllocated(channelId)) {
174 1 : return HcclResult::HCCL_E_PARA; // 日志已在判断处处理
175 : };
176 :
177 28 : const auto &channelResInfo = channelResInfos[channelId];
178 28 : const uint32_t feId = channelResInfo.feId;
179 28 : const vector<JettyInfo> &jettyInfos = channelResInfo.channelInfo.jettyInfos;
180 28 : auto ret = jettyCtxMgr.Config(feId, jettyInfos, channelCfg.jettyCfgs);
181 28 : if (ret != HcclResult::HCCL_SUCCESS) {
182 6 : HCCL_ERROR("[CcuChannelMgrV1][%s] failed to config jetty contexts of channelId[%u], "
183 : "feId[%u], devLogicId[%d], dieId[%u].", __func__, channelId, feId,
184 : devLogicId, dieId);
185 2 : return ret;
186 : }
187 : // 因jettyCtx连续,从起始jettyCtx配置
188 26 : const uint16_t startTaJettyId = jettyInfos[0].taJettyId;
189 26 : const ChannelDataV1 &data = BuildChannelDataV1(channelCfg, feId, dieId, startTaJettyId);
190 26 : TRY_CATCH_RETURN(ConfigChannelDataV1(devLogicId, devPhyId, dieId, channelId, data));
191 26 : return HcclResult::HCCL_SUCCESS;
192 29 : }
193 :
194 3 : HcclResult CcuChannelMgrV1::Release(const uint32_t channelId)
195 : {
196 3 : std::lock_guard<std::mutex> lock(innerMutex);
197 3 : if (!CheckIfChannelAllocated(channelId)) {
198 1 : return HcclResult::HCCL_E_PARA; // 日志已在判断处处理
199 : };
200 :
201 2 : const auto &channelResInfo = channelResInfos[channelId];
202 4 : auto ret = jettyCtxMgr.Release(channelResInfo.feId,
203 2 : channelResInfo.channelInfo.jettyInfos);
204 2 : CHK_PRT_RET(ret != HcclResult::HCCL_SUCCESS,
205 : HCCL_WARNING("[CcuChannelMgrV1][%s] failed to release jetty contexts "
206 : "of channelId[%u], feId[%u], devLogicId[%d], dieId[%u].", __func__,
207 : channelId, channelResInfos[channelId].feId, devLogicId, dieId),
208 : ret);
209 : // 重置并配置Channel表,避免错误复用
210 2 : channelResInfos[channelId] = ChannelResInfo{};
211 2 : ChannelDataV1 data = {};
212 2 : TRY_CATCH_RETURN(ConfigChannelDataV1(devLogicId, devPhyId, dieId, channelId, data));
213 2 : return HcclResult::HCCL_SUCCESS;
214 3 : }
215 :
216 : }; // namespace Hccl
|