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_ctx_mgr_v1.h"
12 :
13 : #include <vector>
14 : #include <string>
15 :
16 : #include "ccu_res_specs.h"
17 : #include "hcomm_adapter_hccp.h"
18 :
19 : namespace hcomm {
20 :
21 : constexpr uint32_t CCU_V1_CHANNEL_DEFAULT_JETTY_NUM = 1;
22 :
23 170 : HcclResult CcuChannelCtxMgrV1::Init()
24 : {
25 170 : uint32_t strategy = 0; // 获取失败或为0场景,分配将按资源不足操作
26 170 : (void)CcuResSpecifications::GetInstance(devLogicId_).GetChannelNum(dieId_, strategy);
27 170 : channelResInfos_.resize(strategy);
28 170 : CHK_RET(jettyCtxMgr_.Init());
29 170 : return HcclResult::HCCL_SUCCESS;
30 : }
31 :
32 183 : static HcclResult FindFreeChannelId(std::vector<ChannelResInfo>& channelResInfos, uint32_t& channelId)
33 : {
34 : // ccu v1每次都分配新的channel与jettyCtx
35 : // 故直接选择首个可用channel即可
36 183 : const uint32_t channelNum = channelResInfos.size();
37 196 : for (uint32_t i = 0; i < channelNum; i++) {
38 196 : if (!channelResInfos[i].allocated) {
39 183 : channelId = i;
40 183 : return HcclResult::HCCL_SUCCESS;
41 : }
42 : }
43 0 : return HcclResult::HCCL_E_UNAVAIL;
44 : }
45 :
46 183 : HcclResult CcuChannelCtxMgrV1::Alloc(const ChannelPara& channelPara, std::vector<ChannelInfo>& channelInfos)
47 : {
48 183 : const uint32_t feId = channelPara.feId;
49 183 : uint32_t jettyNum = channelPara.jettyNum;
50 183 : if (jettyNum == 0) {
51 183 : jettyNum = CCU_V1_CHANNEL_DEFAULT_JETTY_NUM;
52 183 : HCCL_INFO(
53 : "[CcuJettyCtxMgrV1][%s] jettyNum is 0, reset to default[%u], "
54 : "feId[%u], devLogicId[%d], dieId[%u].",
55 : __func__, jettyNum, feId, devLogicId_, dieId_);
56 : }
57 :
58 183 : std::lock_guard<std::mutex> lock(innerMutex_);
59 183 : uint32_t channelId = 0;
60 183 : auto ret = FindFreeChannelId(channelResInfos_, channelId);
61 183 : CHK_PRT_RET(
62 : ret == HcclResult::HCCL_E_UNAVAIL,
63 : HCCL_WARNING(
64 : "[CcuChannelCtxMgrV1][%s] failed to find free channel, channel strategy[%zu], "
65 : "left resources are not enough, feId[%u], devLogicId[%d], dieId[%u].",
66 : __func__, channelResInfos_.size(), feId, devLogicId_, dieId_),
67 : ret);
68 183 : CHK_RET(ret);
69 :
70 183 : ChannelInfo channelInfo = {};
71 183 : ret = jettyCtxMgr_.Alloc(feId, jettyNum, channelPara.sqSize, channelInfo.jettyInfos);
72 183 : CHK_PRT_RET(
73 : ret == HcclResult::HCCL_E_UNAVAIL,
74 : HCCL_WARNING(
75 : "[CcuChannelCtxMgrV1][%s] failed to allocate jetty contexts to channelId[%u], "
76 : "left resources are not enough, feId[%u], devLogicId[%d], dieId[%u].",
77 : __func__, channelId, feId, devLogicId_, dieId_),
78 : ret);
79 183 : CHK_RET(ret);
80 :
81 183 : channelInfo.channelId = channelId;
82 183 : channelInfo.dieId = dieId_;
83 183 : channelResInfos_[channelId].feId = feId;
84 183 : channelResInfos_[channelId].channelInfo = channelInfo;
85 183 : channelResInfos_[channelId].allocated = true;
86 183 : DumpChannelResInfo(feId, channelInfo);
87 :
88 183 : channelInfos.clear(); // ccu v1每次仅分配1个channel,不同channel不复用jettyCtx
89 183 : channelInfos.emplace_back(std::move(channelInfo));
90 183 : return ret;
91 183 : }
92 :
93 : static ChannelCtxDataV1
94 170 : BuildChannelCtxDataV1(const ChannelCfg& cfg, const uint32_t feId, const uint8_t dieId, const uint16_t startTaJettyId)
95 : {
96 170 : ChannelCtxDataV1 data = {};
97 170 : (void)memcpy_s(&data.eidRaw[0], URMA_EID_LEN, &cfg.remoteEid, URMA_EID_LEN);
98 :
99 170 : data.vtpLow = cfg.tpn & MASK_VTP_LOW;
100 170 : data.vtpHigh = ((cfg.tpn & MASK_VTP) >> Hccl::SHIFT_16BITS) & MASK_VTP_HIGH;
101 :
102 170 : data.srcPfeId = static_cast<uint16_t>(feId);
103 :
104 170 : data.startJettyIdLow = startTaJettyId & MASK_START_JETTY_ID_LOW;
105 170 : data.startJettyIdHigh = (startTaJettyId >> Hccl::SHIFT_4BITS) & MASK_START_JETTY_ID_HIGH;
106 :
107 : // 写入硬件减 1,cfgs的数量一定小于jetty规格数,不会超过uint8_t范围
108 170 : uint8_t jettyNum = static_cast<uint8_t>(cfg.jettyCfgs.size()) - 1;
109 170 : data.jettyNumLow = jettyNum & MASK_JETTY_NUM_LOW;
110 170 : data.jettyNumHigh = (jettyNum >> Hccl::SHIFT_4BITS) & MASK_JETTY_NUM_HIGH;
111 :
112 170 : data.ioDieId = static_cast<uint16_t>(dieId);
113 :
114 170 : data.dstTokenIdLow = cfg.memTokenId & MASK_TOKEN_ID_LOW;
115 170 : data.dstTokenIdHigh = (cfg.memTokenId >> Hccl::SHIFT_12BITS) & MASK_TOKEN_ID_HIGH;
116 :
117 170 : data.dstTokenValueLow = cfg.memTokenValue & MASK_TOKEN_VALUE_LOW;
118 170 : data.dstTokenValueMiddle = (cfg.memTokenValue >> Hccl::SHIFT_8BITS) & MASK_TOKEN_VALUE_MID;
119 170 : data.dstTokenValueHigh = (cfg.memTokenValue >> Hccl::SHIFT_24BITS) & MASK_TOKEN_VALUE_HIGH;
120 :
121 170 : uint64_t dstVa = (cfg.remoteCcuVa >> REMOTE_CCU_VA_RIGHT_SHIFT_NUM);
122 170 : data.dstVaLow = dstVa & MASK_VA_LOW;
123 170 : data.dstVaMiddle = (dstVa >> Hccl::SHIFT_8BITS) & MASK_VA_MID;
124 170 : data.dstVaHigh = (dstVa >> Hccl::SHIFT_24BITS) & MASK_VA_HIGH;
125 170 : data.dstVaHigher = (dstVa >> Hccl::SHIFT_40BITS) & MASK_VA_HIGHER;
126 170 : data.dstTokenValueValid = TOKEN_VALUE_VALID;
127 170 : return data;
128 : }
129 :
130 183 : static void DumpChannelCtxDataV1(const struct ChannelCtxDataV1& data)
131 : {
132 183 : if (IsEidEmpty(data.eidRaw)) {
133 13 : return;
134 : }
135 170 : std::string dstEidInfo = "eidRaw: ";
136 2720 : for (uint32_t i = 0; i < URMA_EID_LEN - 1; i++) {
137 2550 : dstEidInfo += Hccl::StringFormat("0x%02x, ", data.eidRaw[i]);
138 : }
139 170 : dstEidInfo += Hccl::StringFormat("0x%02x", data.eidRaw[URMA_EID_LEN - 1]);
140 170 : HCCL_INFO("%s.", dstEidInfo.c_str());
141 :
142 170 : HCCL_INFO(
143 : "vtpLow: 0x%04x, vtpHigh: 0x%04x, srcPfeId: 0x%04x, "
144 : "startJettyIdLow: 0x%04x, startJettyIdHigh: 0x%04x, "
145 : "JettyNumLow: 0x%04x, JettyNumHigh: 0x%04x, ioDieId: 0x%04x, ",
146 : data.vtpLow, data.vtpHigh, data.srcPfeId, data.startJettyIdLow, data.startJettyIdHigh, data.jettyNumLow,
147 : data.jettyNumHigh, data.ioDieId);
148 :
149 170 : HCCL_INFO(
150 : "dstVaLow: 0x%04x, dstVaMiddle: 0x%04x, "
151 : "dstVaHigh: 0x%04x, dstVaHigher: 0x%04x, dstTokenValueValid: 0x%04x",
152 : data.dstVaLow, data.dstVaMiddle, data.dstVaHigh, data.dstVaHigher, data.dstTokenValueValid);
153 170 : }
154 :
155 183 : static HcclResult ConfigChannelCtxDataV1(
156 : const int32_t devLogicId, const uint32_t devPhyId, const uint8_t dieId, const uint32_t channelId,
157 : const ChannelCtxDataV1& channelCtxData)
158 : {
159 183 : CustomChannelInfoIn inBuff{};
160 183 : CustomChannelInfoOut outBuff{};
161 :
162 183 : constexpr uint32_t dataArraySize = 1; // 每次配置1个Channel
163 183 : inBuff.op = CcuOpcodeType::CCU_U_OP_SET_CHANNEL;
164 183 : inBuff.data.dataInfo.udieIdx = dieId;
165 183 : inBuff.data.dataInfo.dataArraySize = dataArraySize;
166 183 : inBuff.data.dataInfo.dataLen = sizeof(struct ChannelCtxDataV1) * dataArraySize;
167 183 : inBuff.offsetStartIdx = channelId;
168 :
169 183 : HCCL_INFO(
170 : "[CcuChannelCtxMgrV1][%s] set data to ccu driver, devLogicId[%d] devPhyId[%u], "
171 : "ioDie[%u], idx[%u], size[%u].",
172 : __func__, devLogicId, devPhyId, dieId, channelId, sizeof(struct ChannelCtxDataV1));
173 183 : DumpChannelCtxDataV1(channelCtxData);
174 :
175 183 : (void)memcpy_s(
176 : inBuff.data.dataInfo.dataArray, sizeof(struct ChannelCtxDataV1), &channelCtxData,
177 : sizeof(struct ChannelCtxDataV1));
178 :
179 183 : auto ret = HccpRaTlvCcuCustomChannel(devLogicId, static_cast<void*>(&inBuff), static_cast<void*>(&outBuff));
180 183 : if (ret != HCCL_SUCCESS) {
181 0 : HCCL_ERROR(
182 : "[CcuChannelCtxMgrV1][%s] failed to call ccu driver, "
183 : "devLogicId[%d] devPhyId[%u] dieId[%d] op[%s] ret[%d].",
184 : __func__, devLogicId, devPhyId, dieId, "SET_CHANNEL", ret);
185 0 : return ret;
186 : }
187 :
188 183 : return HcclResult::HCCL_SUCCESS;
189 : }
190 :
191 170 : HcclResult CcuChannelCtxMgrV1::Config(const ChannelCfg& channelCfg)
192 : {
193 170 : std::lock_guard<std::mutex> lock(innerMutex_);
194 170 : const uint32_t channelId = channelCfg.channelId;
195 170 : if (!CheckIfChannelAllocated(channelId)) {
196 0 : return HcclResult::HCCL_E_PARA; // 日志已在判断处处理
197 : };
198 :
199 170 : const auto& channelResInfo = channelResInfos_[channelId];
200 170 : const uint32_t feId = channelResInfo.feId;
201 170 : const std::vector<JettyInfo>& jettyInfos = channelResInfo.channelInfo.jettyInfos;
202 170 : auto ret = jettyCtxMgr_.Config(feId, jettyInfos, channelCfg.jettyCfgs);
203 170 : if (ret != HcclResult::HCCL_SUCCESS) {
204 0 : HCCL_ERROR(
205 : "[CcuChannelCtxMgrV1][%s] failed to config jetty contexts of channelId[%u], "
206 : "feId[%u], devLogicId[%d], dieId[%u].",
207 : __func__, channelId, feId, devLogicId_, dieId_);
208 0 : return ret;
209 : }
210 : // 因jettyCtx连续,从起始jettyCtx配置
211 170 : const uint16_t startTaJettyId = jettyInfos[0].taJettyId;
212 170 : const ChannelCtxDataV1& data = BuildChannelCtxDataV1(channelCfg, feId, dieId_, startTaJettyId);
213 170 : CHK_RET(ConfigChannelCtxDataV1(devLogicId_, devPhyId_, dieId_, channelId, data));
214 170 : return HcclResult::HCCL_SUCCESS;
215 170 : }
216 :
217 13 : HcclResult CcuChannelCtxMgrV1::Release(const uint32_t channelId)
218 : {
219 13 : std::lock_guard<std::mutex> lock(innerMutex_);
220 13 : if (!CheckIfChannelAllocated(channelId)) {
221 0 : return HcclResult::HCCL_E_PARA; // 日志已在判断处处理
222 : };
223 :
224 13 : const auto& channelResInfo = channelResInfos_[channelId];
225 13 : auto ret = jettyCtxMgr_.Release(channelResInfo.feId, channelResInfo.channelInfo.jettyInfos);
226 13 : CHK_PRT_RET(
227 : ret != HcclResult::HCCL_SUCCESS,
228 : HCCL_WARNING(
229 : "[CcuChannelCtxMgrV1][%s] failed to release jetty contexts "
230 : "of channelId[%u], feId[%u], devLogicId[%d], dieId[%u].",
231 : __func__, channelId, channelResInfos_[channelId].feId, devLogicId_, dieId_),
232 : ret);
233 : // 重置并配置Channel表,避免错误复用
234 13 : channelResInfos_[channelId] = ChannelResInfo{};
235 13 : ChannelCtxDataV1 data = {};
236 13 : CHK_RET(ConfigChannelCtxDataV1(devLogicId_, devPhyId_, dieId_, channelId, data));
237 13 : return HcclResult::HCCL_SUCCESS;
238 13 : }
239 :
240 : }; // namespace hcomm
|