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