Line data Source code
1 : /**
2 : * Copyright (c) 2026 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_ctx_mgr_v2.h"
12 :
13 : #include "orion_adapter_hccp.h"
14 :
15 : #include "ccu_res_specs.h"
16 :
17 : #include "env_config.h"
18 : #include "string_util.h"
19 :
20 : namespace hcomm {
21 :
22 41 : CcuChannelCtxMgrV2::CcuChannelCtxMgrV2(const int32_t devLogicId, const uint8_t dieId, const uint32_t devPhyId)
23 : : CcuChannelCtxMgr(devLogicId, dieId, devPhyId),
24 41 : jettyCtxMgr_(devLogicId, dieId, devPhyId)
25 : {
26 41 : (void)CcuResSpecifications::GetInstance(devLogicId).GetChannelJettyMap(dieId, channelJettyMap_);
27 41 : }
28 :
29 41 : HcclResult CcuChannelCtxMgrV2::Init()
30 : {
31 41 : uint32_t strategy = 0; // 获取失败或为0场景,分配将按资源不足操作
32 41 : (void)CcuResSpecifications::GetInstance(devLogicId_).GetChannelNum(dieId_, strategy);
33 41 : channelResInfos_.resize(strategy);
34 41 : CHK_RET(jettyCtxMgr_.Init());
35 41 : return HcclResult::HCCL_SUCCESS;
36 : }
37 :
38 38 : static uint32_t CheckAndAdjustJettyNum(const ChannelPara& channelPara, const CcuChannelJettyMap& channelJettyMap)
39 : {
40 38 : uint32_t jettyNum = channelPara.jettyNum;
41 38 : const uint32_t jettyGroupSize = channelJettyMap.jettyNum;
42 38 : if (jettyNum != jettyGroupSize) {
43 33 : HCCL_INFO(
44 : "[CcuChannelCtxMgrV2][%s] jetty num[%u] reset to channelJettyMap."
45 : "jettyNum[%u], feId[%u].",
46 : __func__, jettyNum, jettyGroupSize, channelPara.feId);
47 33 : jettyNum = jettyGroupSize;
48 : }
49 38 : return jettyNum;
50 : }
51 :
52 : static HcclResult
53 37 : GetStartChannelId(const uint32_t jettyCtxStartId, const CcuChannelJettyMap& channelJettyMap, uint32_t& channelId)
54 : {
55 : // channelJettyMap来自静态定义,认为其不会为0
56 37 : const uint32_t channelGroupSize = channelJettyMap.channelNum;
57 37 : const uint32_t jettyGroupSize = channelJettyMap.jettyNum;
58 37 : const uint32_t jettyGroupId = jettyCtxStartId / jettyGroupSize;
59 37 : if (UINT32_MAX / channelGroupSize < jettyGroupId) {
60 0 : HCCL_ERROR(
61 : "[CcuChannelCtxMgrV2][%s] failed, channelId result overflow "
62 : "UINT32_MAX, jettyStartId[%u].",
63 : __func__, jettyCtxStartId);
64 0 : return HcclResult::HCCL_E_INTERNAL;
65 : }
66 :
67 37 : channelId = channelGroupSize * jettyGroupId;
68 37 : return HcclResult::HCCL_SUCCESS;
69 : }
70 :
71 37 : static HcclResult CheckChannelRangeAllocatable(
72 : const uint32_t startChannelId, const uint32_t channelNum, std::vector<ChannelResInfo>& channelResInfos)
73 : {
74 37 : const uint32_t endChannelId = startChannelId + channelNum;
75 37 : CHK_PRT_RET(
76 : channelResInfos.size() < endChannelId || startChannelId >= endChannelId,
77 : HCCL_ERROR(
78 : "[CcuChannelCtxMgrV2][%s] failed, channel id range[%u, %u) is not expected, "
79 : "should be less than channelResInfos size[%zu].",
80 : __func__, startChannelId, endChannelId, channelResInfos.size()),
81 : HcclResult::HCCL_E_INTERNAL);
82 :
83 333 : for (uint32_t i = startChannelId; i < endChannelId; i++) {
84 296 : if (channelResInfos[i].allocated) {
85 0 : HCCL_WARNING(
86 : "[CcuChannelCtxMgrV2][%s] failed, channel id[%u] is already allocated, "
87 : "channel group range[%u, %u).",
88 : __func__, i, startChannelId, endChannelId);
89 0 : return HcclResult::HCCL_E_UNAVAIL;
90 : }
91 : }
92 :
93 37 : return HcclResult::HCCL_SUCCESS;
94 : }
95 :
96 38 : HcclResult CcuChannelCtxMgrV2::Alloc(const ChannelPara& channelPara, std::vector<ChannelInfo>& channelInfos)
97 : {
98 38 : const uint32_t feId = channelPara.feId;
99 38 : uint32_t jettyNum = CheckAndAdjustJettyNum(channelPara, channelJettyMap_);
100 :
101 38 : std::lock_guard<std::mutex> lock(innerMutex_);
102 :
103 38 : std::vector<JettyInfo> jettyInfos;
104 : // sqsize 每个jetty预留32分配
105 38 : auto ret = jettyCtxMgr_.Alloc(feId, jettyNum, channelPara.sqSize, jettyInfos);
106 38 : CHK_PRT_RET(
107 : ret != HcclResult::HCCL_SUCCESS,
108 : HCCL_WARNING(
109 : "[CcuChannelCtxMgrV2][%s] failed to allocate jetty contexts of feId[%u], "
110 : "devLogicId[%d], dieId[%u].",
111 : __func__, feId, devLogicId_, dieId_),
112 : ret);
113 :
114 37 : const uint32_t channelGroupSize = channelJettyMap_.channelNum;
115 : // 分配成功保证数量不为0
116 37 : const uint32_t jettyCtxStartId = static_cast<uint32_t>(jettyInfos[0].jettyCtxId);
117 37 : uint32_t startChannelId = 0;
118 37 : CHK_RET(GetStartChannelId(jettyCtxStartId, channelJettyMap_, startChannelId));
119 37 : ret = CheckChannelRangeAllocatable(startChannelId, channelGroupSize, channelResInfos_);
120 37 : if (ret != HcclResult::HCCL_SUCCESS) {
121 0 : HCCL_WARNING(
122 : "[CcuChannelCtxMgrV2][%s] failed to find free channels, "
123 : "jettyCtxStartId[%u], jettyNum[%u], need to release temp jetty contexts.",
124 : __func__, jettyCtxStartId, jettyNum);
125 :
126 0 : for (uint32_t i = 0; i < channelGroupSize; i++) { // 存在借用计数故需多次释放
127 0 : CHK_RET(jettyCtxMgr_.Release(feId, jettyInfos));
128 : }
129 0 : return ret;
130 : }
131 :
132 37 : AllocateChannelResources(channelPara, jettyInfos, startChannelId, channelInfos);
133 37 : return HcclResult::HCCL_SUCCESS;
134 38 : }
135 :
136 37 : void CcuChannelCtxMgrV2::AllocateChannelResources(
137 : const ChannelPara& channelPara, const std::vector<CcuJettyInfo>& jettyInfos, uint32_t startChannelId,
138 : std::vector<ChannelInfo>& channelInfos)
139 : {
140 : // ccu v2按配比关系以组的粒度分配channel,同channel组复用jettyCtx
141 : // 调用者不处理channel组的概念,认为各channel独立
142 37 : channelInfos.clear();
143 37 : const uint32_t feId = channelPara.feId;
144 37 : const uint32_t channelGroupSize = channelJettyMap_.channelNum;
145 333 : for (uint32_t i = 0; i < channelGroupSize; i++) {
146 296 : uint32_t channelId = i + startChannelId;
147 296 : ChannelInfo channelInfo{};
148 296 : channelInfo.channelId = channelId;
149 296 : channelInfo.dieId = dieId_;
150 296 : channelInfo.jettyInfos = jettyInfos; // 拷贝相同的jetty信息
151 :
152 296 : auto& channelResInfo = channelResInfos_[channelId];
153 296 : channelResInfo.feId = feId;
154 296 : channelResInfo.channelInfo = channelInfo;
155 296 : channelResInfo.allocated = true;
156 296 : channelInfos.emplace_back(std::move(channelInfo));
157 296 : }
158 :
159 37 : HCCL_INFO(
160 : "[CcuChannelCtxMgrV2][%s] allocated channels[%u, %u) successfully, "
161 : "devLogicId[%d], ioDie[%u], channelNum[%u].",
162 : __func__, startChannelId, startChannelId + channelGroupSize, devLogicId_, dieId_, channelGroupSize);
163 : // 只打印首channel,避免刷屏,分配成功保证数量不为0
164 37 : HCCL_INFO("[CcuChannelCtxMgrV2][%s] the start channel: ", __func__);
165 37 : DumpChannelResInfo(feId, channelInfos[0]);
166 37 : }
167 :
168 31 : static ChannelDataV2 BuildChannelDataV2(const ChannelCfg& cfg, const uint8_t dieId)
169 : {
170 31 : ChannelDataV2 data{};
171 31 : (void)memcpy_s(&data.eidRaw[0], URMA_EID_LEN, &cfg.remoteEid, URMA_EID_LEN);
172 :
173 31 : data.vtpLow = cfg.tpn & MASK_VTP_LOW;
174 31 : data.vtpHigh = ((cfg.tpn & MASK_VTP) >> Hccl::SHIFT_16BITS) & MASK_VTP_HIGH;
175 31 : data.ioDieId = static_cast<uint16_t>(dieId);
176 :
177 31 : return data;
178 : }
179 :
180 48 : static void DumpChannelDataV2(struct ChannelDataV2& tmp)
181 : {
182 48 : if (IsEidEmpty(tmp.eidRaw)) {
183 18 : return;
184 : }
185 :
186 30 : std::string dstEidInfo = "eidRaw: ";
187 480 : for (uint32_t i = 0; i < URMA_EID_LEN - 1; i++) {
188 450 : dstEidInfo += Hccl::StringFormat("0x%02x, ", tmp.eidRaw[i]);
189 : }
190 30 : dstEidInfo += Hccl::StringFormat("0x%02x", tmp.eidRaw[URMA_EID_LEN - 1]);
191 30 : HCCL_INFO("[ChannelDataV2][%s] dstEidInfo is %s ", __func__, dstEidInfo.c_str());
192 30 : HCCL_INFO("vtpLow: 0x%04x, vtpHigh: 0x%04x, ioDieId: 0x%04x.", tmp.vtpLow, tmp.vtpHigh, tmp.ioDieId);
193 30 : }
194 :
195 48 : static HcclResult ConfigChannelCtxDataV2(
196 : int32_t devLogicId, const uint32_t devPhyId, const uint8_t dieId, const uint32_t channelId,
197 : ChannelDataV2& channelData)
198 : {
199 48 : CustomChannelInfoIn inBuff{};
200 48 : CustomChannelInfoOut outBuff{};
201 :
202 48 : constexpr uint32_t dataArraySize = 1; // 每次配置1个Channel
203 48 : inBuff.op = CcuOpcodeType::CCU_U_OP_SET_CHANNEL;
204 48 : inBuff.data.dataInfo.udieIdx = dieId;
205 48 : inBuff.data.dataInfo.dataArraySize = dataArraySize;
206 48 : inBuff.data.dataInfo.dataLen = sizeof(struct ChannelDataV2) * dataArraySize;
207 48 : inBuff.offsetStartIdx = channelId;
208 :
209 48 : HCCL_INFO(
210 : "[CcuChannelCtxMgrV2][%s] config data to ccu driver, devPhyId[%u], "
211 : "ioDie[%u], idx[%u], size[%u].",
212 : __func__, devPhyId, dieId, channelId, sizeof(struct ChannelDataV2));
213 48 : DumpChannelDataV2(channelData);
214 :
215 48 : (void)memcpy_s(
216 : inBuff.data.dataInfo.dataArray, sizeof(struct ChannelDataV2), &channelData, sizeof(struct ChannelDataV2));
217 :
218 48 : auto ret = HccpRaTlvCcuCustomChannel(devLogicId, static_cast<void*>(&inBuff), static_cast<void*>(&outBuff));
219 48 : if (ret != 0) {
220 0 : HCCL_ERROR(
221 : "[CcuChannelCtxMgrV2][%s] failed to call ccu driver, "
222 : "devLogicId[%d] devPhyId[%u] dieId[%d] op[%s] ret[%d].",
223 : __func__, devLogicId, devPhyId, dieId, "SET_CHANNEL", ret);
224 0 : return ret;
225 : }
226 48 : return HcclResult::HCCL_SUCCESS;
227 : }
228 :
229 34 : HcclResult CcuChannelCtxMgrV2::Config(const ChannelCfg& channelCfg)
230 : {
231 34 : std::lock_guard<std::mutex> lock(innerMutex_);
232 34 : uint32_t channelId = channelCfg.channelId;
233 34 : if (!CheckIfChannelAllocated(channelId)) {
234 2 : return HcclResult::HCCL_E_PARA; // 日志已在判断处处理
235 : }
236 :
237 32 : const auto& channelResInfo = channelResInfos_[channelId];
238 32 : const uint32_t feId = channelResInfo.feId;
239 32 : const std::vector<JettyInfo>& jettyInfos = channelResInfo.channelInfo.jettyInfos;
240 32 : auto ret = jettyCtxMgr_.Config(feId, jettyInfos, channelCfg.jettyCfgs);
241 32 : CHK_PRT_RET(
242 : ret != HcclResult::HCCL_SUCCESS,
243 : HCCL_ERROR(
244 : "[CcuChannelCtxMgrV2][%s] failed to config jetty contexts of channelId[%u], "
245 : "feId[%u], devLogicId[%d], dieId[%u].",
246 : __func__, channelId, feId, devLogicId_, static_cast<uint32_t>(dieId_)),
247 : ret);
248 :
249 31 : ChannelDataV2 data = BuildChannelDataV2(channelCfg, dieId_);
250 31 : CHK_RET(ConfigChannelCtxDataV2(devLogicId_, devPhyId_, dieId_, channelId, data));
251 31 : return HcclResult::HCCL_SUCCESS;
252 34 : }
253 :
254 19 : HcclResult CcuChannelCtxMgrV2::Release(const uint32_t channelId)
255 : {
256 19 : std::lock_guard<std::mutex> lock(innerMutex_);
257 19 : if (!CheckIfChannelAllocated(channelId)) {
258 2 : return HcclResult::HCCL_E_PARA; // 日志已在判断处处理
259 : };
260 :
261 17 : const auto& channelResInfo = channelResInfos_[channelId];
262 17 : auto ret = jettyCtxMgr_.Release(channelResInfo.feId, channelResInfo.channelInfo.jettyInfos);
263 17 : CHK_PRT_RET(
264 : ret != HcclResult::HCCL_SUCCESS,
265 : HCCL_WARNING(
266 : "[CcuChannelCtxMgrV2][%s] failed to release jetty contexts "
267 : "of channelId[%u], feId[%u], devLogicId[%d], dieId[%u].",
268 : __func__, channelId, channelResInfos_[channelId].feId, devLogicId_, dieId_),
269 : ret);
270 :
271 17 : channelResInfos_[channelId] = ChannelResInfo{};
272 : // V2 验证阶段未启用动态channel,保持重置Channel配置表,避免错误复用
273 17 : ChannelDataV2 data = {};
274 17 : CHK_RET(ConfigChannelCtxDataV2(devLogicId_, devPhyId_, dieId_, channelId, data));
275 17 : return HcclResult::HCCL_SUCCESS;
276 19 : }
277 :
278 : }; // namespace hcomm
|