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