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 15 : CcuChannelCtxMgrV2::CcuChannelCtxMgrV2(const int32_t devLogicId, const uint8_t dieId, const uint32_t devPhyId)
23 15 : : CcuChannelCtxMgr(devLogicId, dieId, devPhyId), jettyCtxMgr_(devLogicId, dieId, devPhyId)
24 : {
25 15 : (void)CcuResSpecifications::GetInstance(devLogicId).GetChannelJettyMap(dieId, channelJettyMap_);
26 15 : }
27 :
28 15 : HcclResult CcuChannelCtxMgrV2::Init()
29 : {
30 15 : uint32_t strategy = 0; // 获取失败或为0场景,分配将按资源不足操作
31 15 : (void)CcuResSpecifications::GetInstance(devLogicId_).GetChannelNum(dieId_, strategy);
32 15 : channelResInfos_.resize(strategy);
33 15 : CHK_RET(jettyCtxMgr_.Init());
34 15 : return HcclResult::HCCL_SUCCESS;
35 : }
36 :
37 10 : static uint32_t CheckAndAdjustJettyNum(const ChannelPara &channelPara,
38 : const CcuChannelJettyMap &channelJettyMap)
39 : {
40 10 : uint32_t jettyNum = channelPara.jettyNum;
41 10 : const uint32_t jettyGroupSize = channelJettyMap.jettyNum;
42 10 : if (jettyNum != jettyGroupSize) {
43 5 : HCCL_INFO("[CcuChannelCtxMgrV2][%s] jetty num[%u] reset to channelJettyMap."
44 : "jettyNum[%u], feId[%u].", __func__, jettyNum,
45 : jettyGroupSize, channelPara.feId);
46 5 : jettyNum = jettyGroupSize;
47 : }
48 10 : return jettyNum;
49 : }
50 :
51 9 : static HcclResult GetStartChannelId(const uint32_t jettyCtxStartId,
52 : const CcuChannelJettyMap &channelJettyMap,
53 : uint32_t &channelId)
54 : {
55 : // channelJettyMap来自静态定义,认为其不会为0
56 9 : const uint32_t channelGroupSize = channelJettyMap.channelNum;
57 9 : const uint32_t jettyGroupSize = channelJettyMap.jettyNum;
58 9 : const uint32_t jettyGroupId = jettyCtxStartId / jettyGroupSize;
59 9 : 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 9 : channelId = channelGroupSize * jettyGroupId;
66 9 : return HcclResult::HCCL_SUCCESS;
67 : }
68 :
69 9 : static HcclResult CheckChannelRangeAllocatable(
70 : const uint32_t startChannelId, const uint32_t channelNum, std::vector<ChannelResInfo> &channelResInfos)
71 : {
72 9 : const uint32_t endChannelId = startChannelId + channelNum;
73 9 : 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[%u].", __func__, startChannelId,
76 : endChannelId, channelResInfos.size()),
77 : HcclResult::HCCL_E_INTERNAL);
78 :
79 81 : for (uint32_t i = startChannelId; i < endChannelId; i++) {
80 72 : 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 9 : return HcclResult::HCCL_SUCCESS;
88 : }
89 :
90 10 : HcclResult CcuChannelCtxMgrV2::Alloc(const ChannelPara &channelPara,
91 : std::vector<ChannelInfo> &channelInfos)
92 : {
93 10 : const uint32_t feId = channelPara.feId;
94 10 : uint32_t jettyNum = CheckAndAdjustJettyNum(channelPara, channelJettyMap_);
95 :
96 10 : std::lock_guard<std::mutex> lock(innerMutex_);
97 :
98 10 : std::vector<JettyInfo> jettyInfos;
99 : // sqsize 每个jetty预留32分配
100 10 : auto ret = jettyCtxMgr_.Alloc(feId, jettyNum, channelPara.sqSize, jettyInfos);
101 10 : 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 9 : const uint32_t channelGroupSize = channelJettyMap_.channelNum;
107 : // 分配成功保证数量不为0
108 9 : const uint32_t jettyCtxStartId = static_cast<uint32_t>(jettyInfos[0].jettyCtxId);
109 9 : uint32_t startChannelId = 0;
110 9 : CHK_RET(GetStartChannelId(jettyCtxStartId, channelJettyMap_, startChannelId));
111 9 : ret = CheckChannelRangeAllocatable(startChannelId, channelGroupSize, channelResInfos_);
112 9 : 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 9 : AllocateChannelResources(channelPara, jettyInfos, startChannelId, channelInfos);
124 9 : return HcclResult::HCCL_SUCCESS;
125 10 : }
126 :
127 9 : 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 9 : channelInfos.clear();
134 9 : const uint32_t feId = channelPara.feId;
135 9 : const uint32_t channelGroupSize = channelJettyMap_.channelNum;
136 81 : for (uint32_t i = 0; i < channelGroupSize; i++) {
137 72 : uint32_t channelId = i + startChannelId;
138 72 : ChannelInfo channelInfo{};
139 72 : channelInfo.channelId = channelId;
140 72 : channelInfo.dieId = dieId_;
141 72 : channelInfo.jettyInfos = jettyInfos; // 拷贝相同的jetty信息
142 :
143 72 : auto &channelResInfo = channelResInfos_[channelId];
144 72 : channelResInfo.feId = feId;
145 72 : channelResInfo.channelInfo = channelInfo;
146 72 : channelResInfo.allocated = true;
147 72 : channelInfos.emplace_back(std::move(channelInfo));
148 72 : }
149 :
150 9 : 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 9 : HCCL_INFO("[CcuChannelCtxMgrV2][%s] the start channel: ", __func__);
155 9 : DumpChannelResInfo(feId, channelInfos[0]);
156 9 : }
157 :
158 5 : static ChannelDataV2 BuildChannelDataV2(const ChannelCfg &cfg, const uint8_t dieId)
159 : {
160 5 : ChannelDataV2 data{};
161 5 : (void)memcpy_s(&data.eidRaw[0], URMA_EID_LEN, &cfg.remoteEid, URMA_EID_LEN);
162 :
163 5 : data.vtpLow = cfg.tpn & MASK_VTP_LOW;
164 5 : data.vtpHigh = ((cfg.tpn & MASK_VTP) >> Hccl::SHIFT_16BITS) & MASK_VTP_HIGH;
165 5 : data.ioDieId = static_cast<uint16_t>(dieId);
166 :
167 5 : return data;
168 : }
169 :
170 6 : static void DumpChannelDataV2(struct ChannelDataV2 &tmp)
171 : {
172 6 : if (IsEidEmpty(tmp.eidRaw)) {
173 2 : return;
174 : }
175 :
176 4 : std::string dstEidInfo = "eidRaw: ";
177 64 : for (uint32_t i = 0; i < URMA_EID_LEN - 1; i++) {
178 60 : dstEidInfo += Hccl::StringFormat("0x%02x, ", tmp.eidRaw[i]);
179 : }
180 4 : dstEidInfo += Hccl::StringFormat("0x%02x", tmp.eidRaw[URMA_EID_LEN - 1]);
181 4 : HCCL_INFO("[ChannelDataV2][%s] dstEidInfo is %s ",__func__, dstEidInfo.c_str());
182 4 : HCCL_INFO("vtpLow: 0x%04x, vtpHigh: 0x%04x, ioDieId: 0x%04x.",
183 : tmp.vtpLow, tmp.vtpHigh, tmp.ioDieId);
184 4 : }
185 :
186 6 : static HcclResult ConfigChannelCtxDataV2(int32_t devLogicId, const uint32_t devPhyId,
187 : const uint8_t dieId, const uint32_t channelId, ChannelDataV2 &channelData)
188 : {
189 6 : CustomChannelInfoIn inBuff{};
190 6 : CustomChannelInfoOut outBuff{};
191 :
192 6 : constexpr uint32_t dataArraySize = 1; // 每次配置1个Channel
193 6 : inBuff.op = CcuOpcodeType::CCU_U_OP_SET_CHANNEL;
194 6 : inBuff.data.dataInfo.udieIdx = dieId;
195 6 : inBuff.data.dataInfo.dataArraySize = dataArraySize;
196 6 : inBuff.data.dataInfo.dataLen = sizeof(struct ChannelDataV2) * dataArraySize;
197 6 : inBuff.offsetStartIdx = channelId;
198 :
199 6 : 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 6 : DumpChannelDataV2(channelData);
203 :
204 6 : (void)memcpy_s(inBuff.data.dataInfo.dataArray, sizeof(struct ChannelDataV2), &channelData,
205 : sizeof(struct ChannelDataV2));
206 :
207 6 : auto ret = HccpRaTlvCcuCustomChannel(devLogicId,
208 : static_cast<void *>(&inBuff), static_cast<void *>(&outBuff));
209 6 : 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 6 : return HcclResult::HCCL_SUCCESS;
216 : }
217 :
218 8 : HcclResult CcuChannelCtxMgrV2::Config(const ChannelCfg &channelCfg)
219 : {
220 8 : std::lock_guard<std::mutex> lock(innerMutex_);
221 8 : uint32_t channelId = channelCfg.channelId;
222 8 : if (!CheckIfChannelAllocated(channelId)) {
223 2 : return HcclResult::HCCL_E_PARA; // 日志已在判断处处理
224 : };
225 :
226 6 : const auto &channelResInfo = channelResInfos_[channelId];
227 6 : const uint32_t feId = channelResInfo.feId;
228 6 : const std::vector<JettyInfo> &jettyInfos = channelResInfo.channelInfo.jettyInfos;
229 6 : auto ret = jettyCtxMgr_.Config(feId, jettyInfos, channelCfg.jettyCfgs);
230 6 : 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 5 : ChannelDataV2 data = BuildChannelDataV2(channelCfg, dieId_);
237 5 : CHK_RET(ConfigChannelCtxDataV2(devLogicId_, devPhyId_, dieId_, channelId, data));
238 5 : return HcclResult::HCCL_SUCCESS;
239 8 : }
240 :
241 3 : HcclResult CcuChannelCtxMgrV2::Release(const uint32_t channelId)
242 : {
243 3 : std::lock_guard<std::mutex> lock(innerMutex_);
244 3 : if (!CheckIfChannelAllocated(channelId)) {
245 2 : return HcclResult::HCCL_E_PARA; // 日志已在判断处处理
246 : };
247 :
248 1 : const auto &channelResInfo = channelResInfos_[channelId];
249 2 : auto ret = jettyCtxMgr_.Release(channelResInfo.feId,
250 1 : channelResInfo.channelInfo.jettyInfos);
251 1 : 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 1 : channelResInfos_[channelId] = ChannelResInfo{};
258 : // V2 验证阶段未启用动态channel,保持重置Channel配置表,避免错误复用
259 1 : ChannelDataV2 data = {};
260 1 : CHK_RET(ConfigChannelCtxDataV2(devLogicId_, devPhyId_, dieId_, channelId, data));
261 1 : return HcclResult::HCCL_SUCCESS;
262 3 : }
263 :
264 : }; // namespace hcomm
|