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